Скрипт для сбора портов подключения коммутаторов D-link, Zyxel и занесение их в NetK

Скрипт для сбора портов подключения коммутаторов D-link, Zyxel и занесение их в NetK
Скажу сразу, всё оборудование уже занесено в NetK - визуализатор сети, поэтому задача построения топологии сети не ставилась. Однако данные скрипты могут послужить основой для автоматической генерации топологии сети.
Итак, необходимо получить информацию по портам подключения коммутаторов:
1) порт вышестоящего коммутатора, к которому подключен текущий коммутатор;
2) порт (uplink) текущего коммутатора, к которому подключен вышестоящий коммутатор.
Пример портов подключения из NetK - коммутатор с IP-адресом 10.32.198.234 (назовем его текущий коммутатор) подключен к 26 порту вышестоящего коммутатора с IP-адресом 10.32.198.249. Порт подключения на текущем коммутаторе - 28.
Для реализации данной задачи буду перебирать MAC-адреса, полученные из таблицы коммутации оборудования. Предварительно необходимо пропинговать коммутатор (в случае, если к нему давно не было обращений), MAC-адрес которого необходимо найти, чтобы данный мак появился в arp таблице.
IP и MAC-адреса формировала sql запросом к базе данных NetK в следующем формате.
1. Для получения порта вышестоящего коммутатора, на который подключен текущий коммутатор:
10.32.198.249;00 1e 58 a0 dc 62; 10.32.198.234;1
где 10.32.198.249 - IP-адрес вышестоящего коммутатора, на котором необходимо найти MAC-адрес 00:1e:58:a0:dc:62 текущего коммутатора 10.32.198.134. Флаг 1 указывает, что производитель коммутатора 10.32.198.249 -D-link (флаг 0 - для коммутаторов Zyxel).
2. Для получения порта (uplink) текущего коммутатора, к которому подключен вышестоящий коммутатор:
10.32.198.234;00 1e 58 a8 56 2d; 10.32.198.249;1
где 10.32.198.234 - IP-адрес текущего коммутатора, на котором необходимо найти MAC-адрес 00:1e:58:a8:56:2d вышестоящего коммутатора 10.32.198.249. Флаг 1 указывает, что производитель коммутатора 10.32.198.234 -D-link (флаг 0 - для коммутаторов Zyxel).
IP-адреса коммутаторов D-link и Zyxel формировала отдельными списками ввиду большого количества оборудования - порядка 4-х тысяч.
Алгоритм сбора портов подключения коммутаторов:
1. Заходим по telnet на коммутатор, IP-адрес которого указан первым в строке.
2. Пингуем коммутатор, IP-адрес которого указан вторым в строке.
На коммутаторах D-link:
# ping $ip times 1 # logo
На коммутаторах Zyxel:
# ping $ip # exit
3. Выполняем команду snmpwalk из пакета Net-SNMP.
На коммутаторах D-link:
/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v2c $ip .1.3.6.1.2.1.17.7.1.2.2.1.2
Пример возвращаемого значения:
.1.3.6.1.2.1.17.7.1.2.2.1.2.2.0.28.240.40.57.191 = INTEGER: 21
где 0.28.240.40.57.191 - MAC-адрес в десятичной системе;
21 - номер порта.
На коммутаторах Zyxel:
/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v2c $ip .1.3.6.1.2.1.17.4.3.1.2
Пример возвращаемого значения:
.1.3.6.1.2.1.17.4.3.1.2.0.1.108.25.235.110 = INTEGER: 11
где 0.1.108.25.235.120 - MAC-адрес в десятичной системе;
11 - номер порта.
4. Сравниваем мак-адреса из таблицы коммутации с мак-адресом из строки и находим необходимый порт.
Скрипт сбора портов подключения коммутаторов - port.pl:
#!/usr/bin/perl
use strict;
use File::Copy;
use Net::Telnet;
my $storepath = './';
my $source_list = $storepath.'ip-mac.txt';
my $macaddr;
my $result;
my $oid_mac;
my $oid_port;
my $i_count=0;
my $dumplog = './dump_port.log';
sub trim($) {
$_[0]=~s/(^\s+)|(\s+$)|(\n$)//gs;
return $_[0];
};
open (RW," >>$dumplog") or die "can't open dumplog: $!";
open (RL, $source_list) or die "can't open source list: $!";
while(<RL>){
my $ip= (split(/[;]/), $_)[0];
trim($ip);
my $mac=(split(/[;]/), $_)[1];
trim($mac);
my $ip_to= (split(/[;]/), $_)[2];
trim($ip_to);
my $flag=(split(/[;]/), $_)[3];
trim($flag);
print "-----------------------------------------\n";
print "start $ip-$ip_to-$mac\n";
my $username = 'LOGIN';
my $password = 'PASS';
my $dumplog_telnet = 'dump_telnet.log';
if ($ip =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) {
#Zyxel
if($flag == 0){
print "telnet...start\n";
my $command_ping= 'ping '.$ip_to;
my $command_ex='exit';
my $telnet = new Net::Telnet ( Timeout=>20, Errmode=> 'return', Dump_Log => $dumplog_telnet);
if($telnet->open($ip)){
if($telnet->print($username)){
sleep(1);
if($telnet->print($password)){
if($telnet->print($command_ping)){
sleep(1);
if($telnet->print($command_ex)){
sleep(1);
}
}else{
print "error ping";
}
}else{
print "error pass";
}
}else{
print "error username";
}
if($telnet->close){
print "telnet...end\n";
}
}else{
print "error open";
}
sleep(3);
open DATA,"/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v 2c $ip .1.3.6.1.2.1.17.4.3.1.2|";
$oid_mac="";
$macaddr="";
$oid_port="";
while (<DATA>){
$oid_mac=(split(/[=]/), $_)[0];
trim($oid_mac);
$oid_port=(split(/[ ]/), $_)[3];
trim($oid_port);
if ($oid_mac =~ /^\.1\.3\.6\.1\.2\.1\.17\.4\.3\.1\.2\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
my $mac1=sprintf "%02lx",$1;
my $mac2=sprintf "%02lx",$2;
my $mac3=sprintf "%02lx",$3;
my $mac4=sprintf "%02lx",$4;
my $mac5=sprintf "%02lx",$5;
my $mac6=sprintf "%02lx",$6;
$macaddr=$mac1.' '.$mac2.' '.$mac3.' '.$mac4.' '.$mac5.' '.$mac6;
trim($macaddr);
}
if ($macaddr =~ /$mac/) {
$i_count=$i_count + 1;
print "$i_count: $ip - $oid_port - $mac - $ip_to - $flag\n";
print RW "$ip;$oid_port;$mac;$ip_to;$flag\n";
}
}
}elsif($flag == 1){
#D-link
print "telnet...start\n";
my $command_ping= 'ping '.$ip_to.' times 1';
my $command_ex='logo';
my $telnet = new Net::Telnet ( Timeout=>20, Errmode=> 'return', Dump_Log => $dumplog_telnet);
if($telnet->open($ip)){
if($telnet->print($username)){
sleep(1);
if($telnet->print($password)){
if($telnet->print($command_ping)){
sleep(1);
if($telnet->print($command_ex)){
sleep(1);
}
}else{
print "error ping";
}
}else{
print "error pass";
}
}else{
print "error username";
}
if($telnet->close){
print "telnet...end\n";
}
}else{
print "error open";
}
sleep(3);
open DATA,"/usr/local/bin/snmpwalk -Osfn -c COMMUNITY -v 2c $ip .1.3.6.1.2.1.17.7.1.2.2.1.2|";
$oid_mac="";
$macaddr="";
$oid_port="";
while (<DATA>){
$oid_mac=(split(/[=]/), $_)[0];
trim($oid_mac);
$oid_port=(split(/[ ]/), $_)[3];
trim($oid_port);
if ($oid_mac =~ /^\.1\.3\.6\.1\.2\.1\.17\.7\.1\.2\.2\.1\.2\.\d{1,3}\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/) {
my $mac1=sprintf "%02lx",$1;
my $mac2=sprintf "%02lx",$2;
my $mac3=sprintf "%02lx",$3;
my $mac4=sprintf "%02lx",$4;
my $mac5=sprintf "%02lx",$5;
my $mac6=sprintf "%02lx",$6;
$macaddr=$mac1.' '.$mac2.' '.$mac3.' '.$mac4.' '.$mac5.' '.$mac6;
trim($macaddr);
if ($macaddr =~ /$mac/) {
$flag=1;
$i_count=$i_count + 1;
print "$i_count: $ip - $oid_port - $mac - $ip_to - $flag\n";
print RW "$ip;$oid_port;$mac;$ip_to;$flag\n";
}
}
}
}
}
}
close(RW);
close(RL);
Результат можно наблюдать в файле dump_port.log. Формат записей:
10.32.198.249;26;00 1e 58 a0 dc 62; 10.32.198.234;1
где 26 - искомый порт.
Скрипт обновления порта подключения текущего коммутатора к вышестоящему в базе данных NetK
В примере выше для узла с IP-адресом 10.32.198.234 номер порта - 26. Пример входных данных:
10.32.198.249;26;00 1e 58 a0 dc 62; 10.32.198.234;1
update_port_to.php:
<?php
include("./config.php");
$filename ="./dump_port.log";
$fp =fopen($filename, "r");
$pub = fread($fp, filesize($filename));
fclose($fp);
$arr = array();
$arr = preg_split('/\n/', $pub,-1, PREG_SPLIT_NO_EMPTY);
$count_port=0;
foreach ($arr as $idx=> $val) {
$count_port++;
$knot_par = explode(";", $arr[$idx]);
$knot_ip=trim($knot_par[3]);
$knot_port=trim($knot_par[1]);
mysql_query("LOCK TABLES `net` WRITE;");
$query_up = "UPDATE net SET port_to='$knot_port' where INET_NTOA(ip_for)='$knot_ip'";
if(!mysql_query($query_up))
{
echo "error update";
}
mysql_query("UNLOCK TABLES");
}
echo"port $count_port";
?>
Скрипт обновления порта подключения вышестоящего коммутатора к текущему в базе данных NetK
В примере выше для узла с IP-адресом 10.32.198.234 номер порта - 28. Пример входных данных:
10.32.198.234;28;00 1e 58 a8 56 2d; 10.32.198.249;1
update_port_for.php:
<?php
include("./config.php");
$filename ="./dump_port.log";
$fp =fopen($filename, "r");
$pub = fread($fp, filesize($filename));
fclose($fp);
$arr = array();
$arr = preg_split('/\n/', $pub,-1, PREG_SPLIT_NO_EMPTY);
$count_port=0;
foreach ($arr as $idx=> $val) {
$count_port++;
$knot_par = explode(";", $arr[$idx]);
$knot_ip=trim($knot_par[0]);
$knot_port=trim($knot_par[1]);
mysql_query("LOCK TABLES `net` WRITE;");
$query_up = "UPDATE net SET port_for='$knot_port' where INET_NTOA(ip_for)='$knot_ip'";
if(!mysql_query($query_up))
{
echo "error update";
}
mysql_query("UNLOCK TABLES");
}
echo"port $count_port";
?>
Нажимая кнопку «Сохранить», я подтверждаю свою дееспособность, согласие на получение информации от NetK, согласие на обработку персональных данных в соответствии с Политикой конфиденциальности и Пользовательским соглашением.
Опубликовано: 27.10.2012 - 14:39 | 
