История изменений
Исправление HighwayStar, (текущая версия) :
я вот так делал н а python когда нужно было спарсить со всех свичей связки ip-mac binding
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' автологин на cisco, d'link, huawei
с детектированием вендора
'''
# импортируем необходимые модули
import pexpect
import re
from sys import argv
#https://pythex.org/
class Dlink(object):
login='user'
password='pass'
command_show_ip_mac_all = 'show address_binding ip_mac all'
pattern_username = "([Uu]ser ?[Nn]ame|[Ll]ogin):"
pattern_password = "[Pp]ass[Ww]ord:"
pattern_unpriveleged_prompt = r"^\S+:(3|6|user|operator)#"
pattern_syntax_error = r"(Available commands|Next possible completions|Ambiguous token):"
pattern_prompt = r"[^|\p](?P<hostname>\S+(:\S+)*)#"
pattern_more = "CTRL\+C.+?a.+?All"
pattern_total = re.compile(r"[^|\p]Total Entries\s?:\s+(?P<total>\d+)")
command_more = "a"
#IP Address MAC Address M ACL Ports
#--------------------------------------- ----------------- -- -- ---------------
#192.168.1.1 00-13-34-CF-BF-6F S I 1
#3526 pattern
#192.168.1.1 00-13-34-CF-BF-6F 4 ARP
#192.168.1.2 00-13-34-CF-BF-6F 24 ARP
#192.168.1.3 00-13-34-CF-BF-6F 7
#CTRL+C ESC q Quit SPACE n Next Page ENTER Next Entry a All
pattern_ip_mac = re.compile(r"(?P<ip>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s+(?P<mac>\S+)\s+(?P<mode>\S+)\s+(?P<acl>\S+)\s+(?P<port>\S+)\s*(\s+\S+\s)?$",re.MULTILINE)
def get_mac_list(self, ip_addr):
# принимаем ip адрес аргументом командной строки
p=pexpect.spawn('telnet %s' % ip_addr)
mac_list=''
total=0
try:
i = p.expect(['.D-Link.','login:','Username:'])
if i == 0:
# print ('D-Link detected')
p.expect([self.pattern_username])
# print("Sending login")
p.sendline(self.login)
p.expect([self.pattern_password])
# print("Sending pass")
p.sendline(self.password)
rx_promt = re.compile(self.pattern_prompt)
i = p.expect(rx_promt)
if i == 1:
print('Login Failed')
else:
p.sendline(self.command_show_ip_mac_all)
rx_error = re.compile(self.pattern_syntax_error)
i = p.expect([self.pattern_prompt,rx_error, self.pattern_more])
if i==1:
print("Syntax error")
elif i == 2:
print("call more")
p.sendline(self.command_more)
mac_list = p.before
i = p.expect([self.pattern_prompt,rx_error, self.pattern_more])
# print('Answer:')
# print(p.before)
mac_list += p.before
total_list = self.pattern_total.findall(mac_list)
if len(total_list):
total=int(total_list[0])
r = []
for match in self.pattern_ip_mac.finditer(mac_list):
r += [{
"ip" : match.group("ip"),
"mac" : match.group("mac"),
"port" : match.group("port"),
}]
# print(r)
if total != len(r):
print("Error, entries count doesnt match: parsed ", total, "matched: ", len(r), "host", ip_addr)
else:
print(ip_addr, " : OK, total: ", total)
except pexpect.EOF:
print("Not D-Link switch or no route to host", ip_addr, "\n", p.before)
p.sendline("logout")
p.close()
def main():
switch = Dlink()
for line in open('switches.txt','r').readlines():
switch.get_mac_list(line)
if __name__ =='__main__':main()
список ip адресов задается в switches.txt просто по ip адресу на строку вроде
127.0.0.1
127.0.0.2
127.0.0.3
спарсенное записывал в sqlite базу для дальнейшей сверки с биллингом. По аналогии можно сделать парсинг VID и всего что выводится по telnet. Если сравнивать с snmp, то по telnet гораздо проще сделать парсер при наличии разных моделей коммутаторов, интерфейс telnet у длинк от модели к модели гораздо больше похож чем snmp. То же самое делал на snmp, там получалось минимум 3 разных набора oid, причем по свежим моделям и прошивкам их надо выпрашивать в техподдержке.
P.S. отталкивался от этого скрипта https://habrahabr.ru/post/127748/
Исходная версия HighwayStar, :
я вот так делал н а python когда нужно было спарсить со всех свичей связки ip-mac binding
#!/usr/bin/env python
# -*- coding: utf-8 -*-
''' автологин на cisco, d'link, huawei
с детектированием вендора
'''
# импортируем необходимые модули
import pexpect
import re
from sys import argv
#https://pythex.org/
class Dlink(object):
login='user'
password='pass'
command_show_ip_mac_all = 'show address_binding ip_mac all'
pattern_username = "([Uu]ser ?[Nn]ame|[Ll]ogin):"
pattern_password = "[Pp]ass[Ww]ord:"
pattern_unpriveleged_prompt = r"^\S+:(3|6|user|operator)#"
pattern_syntax_error = r"(Available commands|Next possible completions|Ambiguous token):"
pattern_prompt = r"[^|\p](?P<hostname>\S+(:\S+)*)#"
pattern_more = "CTRL\+C.+?a.+?All"
pattern_total = re.compile(r"[^|\p]Total Entries\s?:\s+(?P<total>\d+)")
command_more = "a"
#IP Address MAC Address M ACL Ports
#--------------------------------------- ----------------- -- -- ---------------
#192.168.1.1 00-13-34-CF-BF-6F S I 1
#3526 pattern
#192.168.1.1 00-13-34-CF-BF-6F 4 ARP
#192.168.1.2 00-13-34-CF-BF-6F 24 ARP
#192.168.1.3 00-13-34-CF-BF-6F 7
#CTRL+C ESC q Quit SPACE n Next Page ENTER Next Entry a All
pattern_ip_mac = re.compile(r"(?P<ip>[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)\s+(?P<mac>\S+)\s+(?P<mode>\S+)\s+(?P<acl>\S+)\s+(?P<port>\S+)\s*(\s+\S+\s)?$",re.MULTILINE)
def get_mac_list(self, ip_addr):
# принимаем ip адрес аргументом командной строки
p=pexpect.spawn('telnet %s' % ip_addr)
mac_list=''
total=0
try:
i = p.expect(['.D-Link.','login:','Username:'])
if i == 0:
# print ('D-Link detected')
p.expect([self.pattern_username])
# print("Sending login")
p.sendline(self.login)
p.expect([self.pattern_password])
# print("Sending pass")
p.sendline(self.password)
rx_promt = re.compile(self.pattern_prompt)
i = p.expect(rx_promt)
if i == 1:
print('Login Failed')
else:
p.sendline(self.command_show_ip_mac_all)
rx_error = re.compile(self.pattern_syntax_error)
i = p.expect([self.pattern_prompt,rx_error, self.pattern_more])
if i==1:
print("Syntax error")
elif i == 2:
print("call more")
p.sendline(self.command_more)
mac_list = p.before
i = p.expect([self.pattern_prompt,rx_error, self.pattern_more])
# print('Answer:')
# print(p.before)
mac_list += p.before
total_list = self.pattern_total.findall(mac_list)
if len(total_list):
total=int(total_list[0])
r = []
for match in self.pattern_ip_mac.finditer(mac_list):
r += [{
"ip" : match.group("ip"),
"mac" : match.group("mac"),
"port" : match.group("port"),
}]
# print(r)
if total != len(r):
print("Error, entries count doesnt match: parsed ", total, "matched: ", len(r), "host", ip_addr)
else:
print(ip_addr, " : OK, total: ", total)
except pexpect.EOF:
print("Not D-Link switch or no route to host", ip_addr, "\n", p.before)
p.sendline("logout")
p.close()
def main():
switch = Dlink()
for line in open('switches.txt','r').readlines():
switch.get_mac_list(line)
if __name__ =='__main__':main()
список ip адресов задается в switches.txt просто по ip адресу на строку вроде
127.0.0.1
127.0.0.2
127.0.0.3
спарсенное записывал в sqlite базу для дальнейшей сверки с биллингом. По аналогии можно сделать парсинг VID и всего что выводится по telnet. Если сравнивать с snmp, то по telnet гораздо проще сделать парсер при наличии разных моделей коммутаторов, интерфейс telnet у длинк от модели к модели гораздо больше похож чем snmp. То же самое делал на snmp, там получалось минимум 3 разных набора oid, причем по свежим моделям и прошивкам их надо выпрашивать в техподдержке.