Python SNMP 获取交换机ARP表和FDB表(MAC和端口对应表)

import sys

import pysnmp.hlapi as hlapi
import pysnmp.proto.rfc1902 as rfc1902


def snmp_walk(host, oid, format='str', strip_prefix=True, community='public'):
    res = []
    for (errorIndication,
         errorStatus,
         errorIndex,
         varBinds) in hlapi.nextCmd(hlapi.SnmpEngine(),
                                    hlapi.CommunityData(community),
                                    hlapi.UdpTransportTarget((host, 161), timeout=4.0, retries=3),
                                    hlapi.ContextData(),
                                    hlapi.ObjectType(hlapi.ObjectIdentity(oid)),
                                    lookupMib=False,
                                    lexicographicMode=False):
        if errorIndication:
            raise ConnectionError(f'SNMP error: "{str(errorIndication)}". Status={str(errorStatus)}')
        elif errorStatus:
            raise ConnectionError('errorStatus: %s at %s' % (errorStatus.prettyPrint(),
                                                             errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
        else:
            for x in varBinds:
                k, v = x
                if strip_prefix:
                    k = str(k)[len(str(oid)) + 1:]
                if isinstance(v, rfc1902.Integer):
                    res.append((str(k), int(v)))
                else:
                    if format == 'numbers':
                        res.append((str(k), v.asNumbers()))
                    elif format == 'hex':
                        res.append((str(k), v.asOctets().hex()))
                    elif format == 'raw':
                        res.append((str(k), v))
                    elif format == 'bin':
                        res.append((str(k), v.asOctets()))
                    elif format == 'int':
                        res.append((str(k), int(v)))
                    elif format == 'preview':
                        res.append((str(k), str(v)))
                    elif format == 'any':
                        try:
                            res.append((str(k), v.asOctets().decode('utf-8')))
                        except UnicodeDecodeError:
                            res.append((str(k), '0x' + v.asOctets().hex()))
                    elif format == 'str':
                        res.append((str(k), v.asOctets().decode(v.encoding)))
                    else:
                        assert False, "Unknown format for walk()."
    res = {a: b for a, b in res}
    return res


def split_numbers(oid):
    return [int(x) for x in oid.split('.')]


def read_ipv4_from_oid_tail(oid, with_len=True):
    parts = [int(x) for x in oid.split('.')]
    if with_len:
        assert (parts[-5] == 4)  # number of elements
    return '.'.join([str(x) for x in parts[-4:]])


def read_bid_from_oid_tail(oid, with_len=True):
    parts = [int(x) for x in oid.split('.')]
    if with_len:
        assert (parts[-5] == 1)  # number of elements
    return '.'.join([str(x) for x in parts[-1:]])


def read_mac_from_oid_tail(oid, with_len=True):
    parts = [int(x) for x in oid.split('.')]
    if with_len:
        assert (parts[-5] == 6)  # number of elements
    return '.'.join([str(x) for x in parts[-6:]])


def machex(getvar):
    macs = getvar.split('.')
    i = 0
    ma = []
    for x in range(0, 6):
        maca = macs[i]
        if len(maca) == 1:
            a = hex(int(maca)).replace("x", "")
        else:
            a = hex(int(maca))[2:]
        ma.append(a)
        i = i + 1
    return ma[0] + ":" + ma[1] + ":" + ma[2] + ":" + ma[3] + ":" + ma[4] + ":" + ma[5]


if __name__ == "__main__":

    # Read ARP table
    print(" - Reading device ARP table...", file=sys.stderr)
    atPhysAddress = snmp_walk('192.168.0.1', '1.3.6.1.2.1.3.1.1.2', 'hex', community='public')
    for oid, mac in atPhysAddress.items():
        ip = read_ipv4_from_oid_tail(oid, with_len=False)
        print(ip)
        print(mac)
    # Read dot1dBasePortIfIndex table
    print(" - Reading device dot1dBasePortIfIndex table...", file=sys.stderr)
    dot1dBasePortIfIndex = snmp_walk('192.168.0.1', '1.3.6.1.2.1.17.1.4.1.2', 'int', community='public')
    dot1dBasePort = {}
    for bid, id in dot1dBasePortIfIndex.items():
        ip = read_ipv4_from_oid_tail(bid, with_len=False)
        print('bid=', bid)
        print('id=', id)
        dot1dBasePort[bid] = str(id)
    print(dot1dBasePort)

    # Read ifDescr table
    print(" - Reading device ifDescr table...", file=sys.stderr)
    ifDescr = snmp_walk('192.168.0.1', '1.3.6.1.2.1.2.2.1.2', 'str', community='public')
    Descr = {}
    for id, desc in ifDescr.items():
        ip = read_ipv4_from_oid_tail(id, with_len=False)
        print('id=', id)
        print('desc=', desc)
        Descr[id] = desc
    print(Descr)

    dot1dBasePortDescr = {}
    for key in dot1dBasePort.keys():
        dot1dBasePortDescr[key] = Descr[dot1dBasePort[key]]

    print(dot1dBasePortDescr)

    # Read dot1qTpFdbPort table
    print(" - Reading device dot1qTpFdbPort table...", file=sys.stderr)
    dot1qTpFdbPort = snmp_walk('192.168.0.1', '1.3.6.1.2.1.17.4.3.1.2', 'int', community='public')
    dot1qTpFdb = {}
    for mac, bid in dot1qTpFdbPort.items():
        macdec = read_mac_from_oid_tail(mac, with_len=False)
        print('machex=', machex(macdec))
        print('bid=', bid)
        dot1qTpFdb[machex(macdec)] = str(bid)
    print(dot1qTpFdb)

    dot1qTpFdbDescr = {}
    for key in dot1qTpFdb.keys():
        if dot1qTpFdb[key] in dot1dBasePortDescr.keys():
            dot1qTpFdbDescr[key] = dot1dBasePortDescr[dot1qTpFdb[key]]

    print(dot1qTpFdbDescr)

测试思科、华为、H3C可以正常运行;

有些H3C设备没有提供

dot1qTpFdbPort(1.3.6.1.2.1.17.7.1.2.2.1.2)

需要使用

dot1dTpFdbPort

MAC地址对应的端口号。

1.3.6.1.2.1.17.4.3.1.2

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
SNMP(Simple Network Management Protocol)是一种网络管理协议,可以用于监控和管理网络设备。在Python中,你可以使用第三方库PySNMP来实现SNMP的功能。 要使用PySNMP,你需要先安装它。你可以使用pip命令在命令行中安装PySNMP: ``` pip install pysnmp ``` 安装完成后,你可以在Python脚本中导入PySNMP库: ```python from pysnmp.hlapi import * # 这里可以编写使用PySNMP的代码 ``` 使用PySNMP可以执行各种SNMP操作,例如获取设备的系统信息、获取设备的接口信息、设置设备的配置等。你可以根据具体的需求选择适合的操作。 以下是一个简单的示例,演示如何使用PySNMP获取设备的系统描述信息: ```python from pysnmp.hlapi import * # 定义SNMP协议参数 snmp_community = 'public' snmp_host = '192.168.1.1' snmp_port = 161 # 定义SNMP OID(Object Identifier):1.3.6.1.2.1.1.1.0 示系统描述信息 snmp_oid = ObjectIdentity('1.3.6.1.2.1.1.1.0') # 创建SNMP请求 snmp_get = getCmd(SnmpEngine(), CommunityData(snmp_community), UdpTransportTarget((snmp_host, snmp_port)), ContextData(), ObjectType(snmp_oid)) # 发送SNMP请求,并获取响应 snmp_result = next(snmp_get) # 解析SNMP响应 error_indication, error_status, error_index, var_binds = snmp_result # 打印设备的系统描述信息 if error_indication: print(f'Error: {error_indication}') else: for var_bind in var_binds: print(f'System Description: {var_bind[1]}') ``` 这只是一个简单的示例,你可以根据自己的需求进行更复杂的操作。PySNMP库有丰富的API,可以满足各种SNMP操作的需求。你可以参考PySNMP的官方文档来了解更多使用方法和示例:https://pysnmp.readthedocs.io/

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值