LINUX.ORG.RU

История изменений

Исправление 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, причем по свежим моделям и прошивкам их надо выпрашивать в техподдержке.