pythonpython-2.7snmppysnmp

pysnmp resolving oids to mibname


Currently I have setup the trap listener and it can listen to snmp notifications fine. However it only comes back with the numerical oid, I want to be able to resolve this oid to a human readable name. I have looked at the documentation however I do not really understand it all that well. I am using the example script

    from pysnmp.carrier.asyncore.dispatch import AsyncoreDispatcher
from pysnmp.carrier.asyncore.dgram import udp, udp6, unix
from pyasn1.codec.ber import decoder
from pysnmp.proto import api


# noinspection PyUnusedLocal
def cbFun(transportDispatcher, transportDomain, transportAddress, wholeMsg):
    while wholeMsg:
        msgVer = int(api.decodeMessageVersion(wholeMsg))
        if msgVer in api.protoModules:
            pMod = api.protoModules[msgVer]
        else:
            print('Unsupported SNMP version %s' % msgVer)
            return
        reqMsg, wholeMsg = decoder.decode(
            wholeMsg, asn1Spec=pMod.Message(),
        )
        print('Notification message from %s:%s: ' % (
            transportDomain, transportAddress
        )
              )
        reqPDU = pMod.apiMessage.getPDU(reqMsg)
        if reqPDU.isSameTypeWith(pMod.TrapPDU()):
            if msgVer == api.protoVersion1:
                print('Enterprise: %s' % (pMod.apiTrapPDU.getEnterprise(reqPDU).prettyPrint()))
                print('Agent Address: %s' % (pMod.apiTrapPDU.getAgentAddr(reqPDU).prettyPrint()))
                print('Generic Trap: %s' % (pMod.apiTrapPDU.getGenericTrap(reqPDU).prettyPrint()))
                print('Specific Trap: %s' % (pMod.apiTrapPDU.getSpecificTrap(reqPDU).prettyPrint()))
                print('Uptime: %s' % (pMod.apiTrapPDU.getTimeStamp(reqPDU).prettyPrint()))
                varBinds = pMod.apiTrapPDU.getVarBindList(reqPDU)
            else:
                varBinds = pMod.apiPDU.getVarBindList(reqPDU)
            print('Var-binds:')
            for oid, val in varBinds:
                print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
    return wholeMsg


transportDispatcher = AsyncoreDispatcher()

transportDispatcher.registerRecvCbFun(cbFun)

# UDP/IPv4
transportDispatcher.registerTransport(
    udp.domainName, udp.UdpSocketTransport().openServerMode(('localhost', 162))
)

# UDP/IPv6
transportDispatcher.registerTransport(
    udp6.domainName, udp6.Udp6SocketTransport().openServerMode(('::1', 162))
)

## Local domain socket
# transportDispatcher.registerTransport(
#    unix.domainName, unix.UnixSocketTransport().openServerMode('/tmp/snmp-manager')
# )

transportDispatcher.jobStarted(1)

try:
    # Dispatcher will never finish as job#1 never reaches zero
    transportDispatcher.runDispatcher()
except:
    transportDispatcher.closeDispatcher()
    raise

I was wondering how I would go about resolving the oids to mibs. I have downloaded the cisco mib .my files and have stuck them in a directory which I point the mibbuilder to like so,

snmpEngine = SnmpEngine()
mibBuilder = builder.MibBuilder()
mibPath = mibBuilder.getMibSources() + (builder.DirMibSource('/opt/mibs'),)
mibBuilder.setMibSources(*mibPath)
mibBuilder.loadModules('CISCO-CONFIG-MAN-MIB',)
mibViewController = view.MibViewController(mibBuilder)

and within the example script where I do the prettyPrint() statements I have

for oid, val in varBinds:
    objectType = ObjectType(ObjectIdentity(oid.prettyPrint()))
    objectType.resolveWithMib(mibViewController)
    print str(objectType)

    print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))

After making the changes I have now encountered two errors,

Traceback (most recent call last): File "traplistener.py", line 200, in 'CISCO-BRIDGE-EXT-MIB', File "/usr/local/lib/python2.7/site-packages/pysnmp/smi/builder.py", line 344, in loadModules raise error.MibNotFoundError('%s compilation error(s): %s' % (modName, errs)) pysnmp.smi.error.MibNotFoundError: CISCO-CONFIG-MAN-MIB compilation error(s): missing; no module "CISCO-SMI" in symbolTable at MIB CISCO-CONFIG-MAN-MIB; missing; missing; missing; missing; missing; missing


Solution

  • Since you are working with a low-level API (rather than pysnmp.hlapi), I can offer you the following snippet that effectively comprises a MIB resolver:

    from pysnmp.smi import builder, view, compiler, rfc1902
    
    # Assemble MIB viewer
    mibBuilder = builder.MibBuilder()
    compiler.addMibCompiler(mibBuilder, sources=['file:///usr/share/snmp/mibs',
                                                 'http://mibs.snmplabs.com/asn1/@mib@'])
    
    mibViewController = view.MibViewController(mibBuilder)
    
    # Pre-load MIB modules we expect to work with
    mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB')
    
    # This is what we can get in TRAP PDU
    varBinds = [
        ('1.3.6.1.2.1.1.3.0', 12345),
        ('1.3.6.1.6.3.1.1.4.1.0', '1.3.6.1.6.3.1.1.5.2'),
        ('1.3.6.1.6.3.18.1.3.0', '0.0.0.0'),
        ('1.3.6.1.6.3.18.1.4.0', ''),
        ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'),
        ('1.3.6.1.2.1.1.1.0', 'my system')
    ]
    
    # Run var-binds received in PDU (a sequence of OID-value pairs)
    # through MIB viewer to turn them into MIB objects.
    # You may want to catch and ignore MIB lookup errors here.
    varBinds = [rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds]
    
    for varBind in varBinds:
        print(varBind.prettyPrint())