27.02.2015

Скрипт для выявления порта свитча по маку. Опрос по SNMP

Допилил предыдущий скрипт . Необходимо знать аплинки каждого из свитчей. В моем случае, все они подключены к одному корневому (RootSwitch). Скрипт вытягивает по SNMP FDB таблицу корневого свитча, ищет в ней заданный MAC, сверяет его по заранее заданной таблице аплинков до свитчей доступа, переходит на следующий свитч и с него так же забирает FDB таблицу, а в ней уже ищет необходимый MAC. Информация выводится следующим образом "MAC, vlan, port корневого свитча; MAC, vlan, port конечного свитча".


Для работы с SNMP необходимо подключить модуль SharpSNMP.
Из неожиданностей

  •  в OID  MAC адреса хранятся в десятичном формате, пришлось их переводить в шестнадцатеричный. 
  • Простым способом вернуть несколько значений из функции невозможно. Пришлось городить хэш-таблицу, в которой хранились бы три массива (MAC, vlan, port)

В OID информация хранится следующим образом:
OID                                                                                   Data
---                                                                                       ----
.1.3.6.1.2.1.17.7.1.2.1.1.2.1                                               223
.1.3.6.1.2.1.17.7.1.2.1.1.2.41                                              63
.1.3.6.1.2.1.17.7.1.2.1.1.2.4026                                         222
.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.43                3
.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.63                6
.1.3.6.1.2.1.17.7.1.2.2.1.2.1.144.2.166.50.206.126              4
.1.3.6.1.2.1.17.7.1.2.2.1.2.41.0.21.100.59.187.78                26
.1.3.6.1.2.1.17.7.1.2.2.1.2.4026.0.9.136.173.129.150          26
.1.3.6.1.2.1.17.7.1.2.2.1.3.4026.232.64.241.24.239.215      3
.1.3.6.1.2.1.17.7.1.2.2.1.3.4026.232.64.241.24.242.213      3

Первые три строки (может быть больше или меньше, в зависиомсти от количества vlan'ов): последняя цифра - номер vlan'а, data - количество MAC-адресов в этом влане в FDB-таблице.

Далее следуют строки с перечислением MAC-адресов, сгруппированные по vlan'ам: после символов .1.3.6.1.2.1.17.7.1.2.2.1.2. идет номер vlan (1, 41, 4026 в нашем случае), а за ним MAC адрес в десятичном формате. В поле Data - порт с найденным MAC-ом.

Далее следуют строки, начинающиеся на .1.3.6.1.2.1.17.7.1.2.2.1.3. Они содержат информацию, о способе получения MAC-адреса. Если параметр 3 - MAC получен методом learning (опрос порта), 4 - MAC коммутатора, с которого взяли FDB.

Мы будем обрабатывать строки из второго блока. Сначала отсекаем ненужную нам часть OID, затем разбиваем на подстроки и запоминаем данные. Полученные данные выводим по порядку в 3 массива - MAC, port, vlan.

Собственно скрипт:

function findonswitch ([string]$ip) {
$oid=".1.3.6.1.2.1.17.7.1.2.2.1.2."
$mas = Invoke-SnmpWalk $ip ".1.3.6.1.2.1.17.7.1.2" #vlans
$i=0
$vlan=@()
$mac=@()
$port=@()
foreach ($pt in $mas)
{
if ($pt.OID -like "*$oid*")
{
$pt.OID = $pt.OID.remove(0,28)
$vlan += $pt.OID.Substring(0, $pt.OID.IndexOf("."))
$temp = $pt.OID.Substring($pt.OID.IndexOf(".") + 1, $pt.OID.Length - $pt.OID.IndexOf(".")-1)
###перевод из Dec в Hex
$mas=$temp.split(".")
$nmac=@()
foreach ($sdec in $mas)
{
$dec = [int]$sdec
$nmac += '{0:X2}' -f $dec
}
$str=$nmac -join "-"
###
$mac += $str
$port += $pt.Data
}

}
$return= @{}
$return.vlan=$vlan
$return.mac=$mac
$return.port=$port
return $return
}

####################################################################
$rootIP = "192.168.0.21"
$sport = ("1", "2", "5", "12", "13", "14", "43", "44", "65", "66", "74", "107")
$swDB = ("192.168.0.42", "192.168.0.44", "192.168.0.61", "192.168.0.52", "192.168.0.51", "192.168.0.12", "192.168.0.33", "192.168.0.32", "192.168.0.41", "192.168.0.43", "192.168.0.11", "192.168.0.34")

function findinarr ($array, $value) {
    for ($i=0; $i -lt $array.count;$i++) { 
        if($array[$i] -eq $value){$i}
    }
}

$res=findonswitch $rootIP
$dataMACRoot = $res.mac
$dataPortRoot = $res.port
$dataVlanRoot = $res.vlan
$mac = Read-Host "Enter MAC"
if ($mac.indexof(":") -ne 0)
{
$mac=$mac.replace(":", "-")
}
$i=0
$flag=0
foreach ($S in $dataMACRoot)
{
if ($mac -eq $s)
{
$portRoot = $dataPortRoot[$i]
$vlanRoot = $dataVlanRoot[$i]
Write-Host $mac on $portRoot 'in vlan' $vlanRoot on RootSwitch
if ($flag -eq 0)
{
$portRoot1 = $dataPortRoot[$i]
}
$flag++
}
$i++
}

$A = findinarr $sport $portRoot1

$res=findonswitch $swDB[$A]
$dataMAC = $res.mac
$dataPort = $res.port
$dataVlan = $res.vlan
$i=0
foreach ($S in $dataMAC)
{
if ($mac -eq $s)
{
$port = $dataPort[$i]
$vlan = $dataVlan[$i]
Write-Host $mac on $port 'in vlan' $vlan on 'switch' $swDB[$A]
}
$i++
}

Работа второй части скрипта (после ###########) описана в предыдущем посте. Тут она претерпела некоторые изменения, в связи с входящей информацией из массива, а не из csv-файла, но логика не изменилась.

Комментариев нет:

Отправить комментарий