URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 52897
[ Назад ]

Исходное сообщение
"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"

Отправлено jr , 30-Янв-05 13:00 
Использую модуль perl для снятия статистики по MAC адресам свича - Net::SNMP
В дереве BRIDGE-MIB есть параметр dot1dTpFdbAddress, который хранит таблицу с динамическими MAC адресами свича, и формат которого в RFC-1512 описан как OCTET STRING (SIZE (6)).
Мой скрипт выводит эту таблицу примерно так:
0x0050fc48a885
0x0050fcf0cd20
0x006008b80047
что и есть MAC адреса,
но некоторые адреса получаются в странном виде:
0O-xU
что это может быть?
как правильно вывести в perl переменную в формате OCTET STRING (SIZE (6))?

Содержание

Сообщения в этом обсуждении
"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено jr , 31-Янв-05 11:02 
добавлю еще, что адреса, которые выводятся print-ом как:
0x0050fc48a885
имеют размер length $mac равный 14
а для адресов типа:
0O-xU
размер length $mac ревен 6

"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено Vasia , 31-Янв-05 14:47 
>добавлю еще, что адреса, которые выводятся print-ом как:
>0x0050fc48a885
>имеют размер length $mac равный 14
>а для адресов типа:
>0O-xU
>размер length $mac ревен 6
что смущает то ? в языке Си и Перл (Перл исключительно написан на Си, многим похож на него) шестнадцатиричные числа обычно имеют вид 0x...
MAC-адрес представлен же исключительно 6 байтами, 1 байт шестнадцетиричное число от 00 до FF.
т.е. 0x0050fc48a885 = 00 50 fc 48 a8 85 - это и есть МАК.. в чем проблема или я не понял вопроса ?


"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено jr , 31-Янв-05 18:29 
>что смущает то ? в языке Си и Перл (Перл исключительно написан
>на Си, многим похож на него) шестнадцатиричные числа обычно имеют вид
>0x...
>MAC-адрес представлен же исключительно 6 байтами, 1 байт шестнадцетиричное число от 00
>до FF.
>т.е. 0x0050fc48a885 = 00 50 fc 48 a8 85 - это и
>есть МАК.. в чем проблема или я не понял вопроса ?
>
смущает то, что рамер переменной $mac, в которую я помещаю MAC адрес, равна 14, и отображается эта переменная командой print как:
0x0050fc48a885
но в некоторых случаях размер равен 6, и отображается командой print, как нечто непонятное, подобно этому:
0O-xU
вот я и не пойму как все это интерпритировать

"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено Vasia , 01-Фев-05 08:49 
эмм.. тогда разберись с типом переменной $mac, см. perl доки. как известно переменные могут быть char, int, double, float, long это опять таки из Си, посмотри откуда зачитывается твоя $mac т.е. откуда и как в нее попадают твои данные. вообще трудно судить, не видя исходников.

"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено jr , 02-Фев-05 18:00 
>эмм.. тогда разберись с типом переменной $mac, см. perl доки. как известно
>переменные могут быть char, int, double, float, long это опять таки
>из Си, посмотри откуда зачитывается твоя $mac т.е. откуда и как
>в нее попадают твои данные. вообще трудно судить, не видя исходников.
>

Код приведен ниже.
Когда $length равен 6, то распечатка print-ом переменной $mac дает результат подобно 0O-xN
Когда $length НЕ равен 6 (он бывает разного размера - и 14, и 17, и 16), то распечатка print-ом переменной $mac дает результат подобный 0x00304f2ef032, т.е. тот, который и нужен

------------------------------------------
# cat test.pl
#!/usr/bin/perl

use strict;
use Net::SNMP;

my $hostname = "192.168.0.10";
my $password = "public";
my $dot1dTpFdbAddress = ".1.3.6.1.2.1.17.4.3.1.1";
my $dot1dTpFdbPort = ".1.3.6.1.2.1.17.4.3.1.2";
my $dot1dTpFdbStatus = ".1.3.6.1.2.1.17.4.3.1.3";
my @table = ();
my ( $ObjectID, $ObjectID1, $ObjectID2 );
my $port;
my $mac;
my $status;
my $result;
my $length;

my ( $session, $error ) = Net::SNMP->session (
   Hostname => $hostname,
   Community => $password
);
die "session error: $error" unless ( $session );

$ObjectID = $dot1dTpFdbPort;
for ( ; ; ) {
   $result = $session->get_next_request (
      varbindlist => [$ObjectID]
   );
   die "request error: ".$session->error unless ( defined $result );
   ( $ObjectID, $port ) = each %$result;
   unless ( $ObjectID =~ /$dot1dTpFdbPort(.*)/ ) { last; }
   $ObjectID1 = $dot1dTpFdbAddress.$1;
   $ObjectID2 = $dot1dTpFdbStatus.$1;
   $result = $session->get_request (
      varbindlist => [$ObjectID1]
   );
   die "request error: ".$session->error unless ( defined $result );
   $mac = "$result->{$ObjectID1}";
   $length = length $mac;
   $result = $session->get_request (
      varbindlist => [$ObjectID2]
   );
   die "request error: ".$session->error unless ( defined $result );
   $status = "$result->{$ObjectID2}";
   print "$port\t$mac\t$length\t$status\n";
}

$session->close;
------------------------------------------
запускаем:
------------------------------------------
# ./test.pl
1       0x0007e997013a  14      3
9       0x0007e997453b  14      3
1       0x0008a12ce4e6  14      3
10      0x000039377e8f  14      3
1       0O-_(   6       3
1       0O-xN   6       3
1       0O-xU   6       3
13      0x08004668f49f  14      3
1       0x2680000020d6  14      3
------------------------------------------
вот такая вот фигня...


"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено bass , 03-Фев-05 04:48 
>вот такая вот фигня...

$dot1dTpFdbPort не работает с 3com свитчами. c cisco иногда вот такая фигня и вылазит...

возможно вам пригодится более тривиальное решение снятия ip-mac:
(однако в циске можно снять только в пределах вилана, с которого запрос)
#!/usr/bin/perl -w
sub trim($) {$_[0]=~s/(^\s+)|(\s+$)|(\n$)//gs;return $_[0];};
use strict;
my @H1; my %H1;my %H2; my @keys;my $key;
open DATA,"/usr/bin/snmpwalk -Osf -c public -v 1 10.0.0.2 .1.3.6.1.2.1.17.4.3.1.2|";
while (<DATA>){%H1=(%H1, map {(split(/[.= ]+/))[19,17]} trim($_));}
open DATA,"/usr/bin/snmpwalk -Osf -c public -v 1 10.0.0.2 .1.3.6.1.2.1.17.4.3.1.1|";
while (<DATA>){%H2=(%H2, map {(split(/[.=]/))[18,17]} trim($_));}
foreach my $key (sort {$a <=> $b} keys %H1){
@keys = grep { $H2{$_} == $H1{$key} }sort keys %H2;
print "port $key:\n", (join "\n", @keys), "\n";}


"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено jr , 04-Фев-05 10:47 
>$dot1dTpFdbPort не работает с 3com свитчами. c cisco иногда вот такая фигня
>и вылазит...
>
>возможно вам пригодится более тривиальное решение снятия ip-mac:
>(однако в циске можно снять только в пределах вилана, с которого запрос)
>
>#!/usr/bin/perl -w
>sub trim($) {$_[0]=~s/(^\s+)|(\s+$)|(\n$)//gs;return $_[0];};
>use strict;
>my @H1; my %H1;my %H2; my @keys;my $key;
>open DATA,"/usr/bin/snmpwalk -Osf -c public -v 1 10.0.0.2 .1.3.6.1.2.1.17.4.3.1.2|";
>while (<DATA>){%H1=(%H1, map {(split(/[.= ]+/))[19,17]} trim($_));}
>open DATA,"/usr/bin/snmpwalk -Osf -c public -v 1 10.0.0.2 .1.3.6.1.2.1.17.4.3.1.1|";
>while (<DATA>){%H2=(%H2, map {(split(/[.=]/))[18,17]} trim($_));}
>foreach my $key (sort {$a <=> $b} keys %H1){
>@keys = grep { $H2{$_} == $H1{$key} }sort keys %H2;
>print "port $key:\n", (join "\n", @keys), "\n";}

да, snmpwalk нормально выдает MAC адреса, похоже какой-то косяк в модуле Net::SNMP

вот что выяснил:
если добавить вот такой код
------------------------------
$length = length $mac;
if ( $length == 6 ) {
   $mac = join('',map { sprintf "x",$_ } unpack('C*',$mac));
}
------------------------------
то MAC адреса, подобные 0O-xU преобразуются в нормальный вид, типа 0090f51bdb91


"perl - SNMP - BRIDGE_MIB - OCTET STRING (SIZE (6))"
Отправлено jr , 22-Мрт-05 13:46 
Продолжая тему.
Задача в следующем: нужно иметь возможность через SNMP забивать MAC-адреса в коммутатор с привязкой к порту и включать так называемый port security на портах, к которым привязаны MAC-адреса. Как это сделать?