Unpacking OctetString data into a variable for further processing

2.9k views Asked by At

All - I am working with python and pysnmp to collect Cisco Discovery Protocol data via snmp. Since I am working with CDP, I am using the CISCO-CDP-MIB.my and the issues that I am facing are with unpacking the contents of cdpCacheCapabilities and cdpCacheAddressType. I have seen many examples and tried them in my code, but they do not help my particular scenario. Please help me understand the principles behind unpacking so that I can not only apply them to the two MIBs I am working but also with other MIBs that are also likely to return data in a packed format. The results of the cdpCacheCapabilities should be similar to "00000040", I've gotten as far as being able to print the results, but "0x" always precedes my value, I need the value only, without the notation. The results of cdpCacheAddress should be an IP address in hex notation. For cdpCacheAddress I need to first unpack the contents, thus leaving me with a hex string and then convert that to an IP address i.e. "192.168.1.10". Kindly explain the logic behind your answer so that I can adjust it in other scenarios. Thanks

from pysnmp.hlapi import *
from pysnmp import debug
import binascii
import struct

#use specific flags or 'all' for full debugging
#debug.setLogger(debug.Debug('dsp', 'msgproc'))

for (errorIndication,
     errorStatus,
     errorIndex,
     varBinds) in nextCmd(SnmpEngine(),
                          CommunityData('public'),
                          UdpTransportTarget(('10.1.1.1', 161)),
                          ContextData(),
                          ObjectType(ObjectIdentity('CISCO-CDP-MIB', 'cdpCacheCapabilities')),
                          lookupNames=True,
                          lookupValues=True,
                          lexicographicMode=False):

    if errorIndication:
        print(errorIndication)
        break
    elif errorStatus:
        print('%s at %s' % (errorStatus.prettyPrint(),
                            errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
        break
    else:
        for varBind in varBinds:
            value = varBind[-1]
            arg = value.prettyPrint()
            print(arg)
            #dec = format(value,'x')
            #dec = repr(value)
            dec = struct.unpack('c',value)
            print(dec)
1

There are 1 answers

1
Ilya Etingof On BEST ANSWER

By enabling MIB lookup you are asking pysnmp to use MIB to convert SNMP variable-binding pairs (OID and value) into something human-friendly.

If you need just bare, non-formatted values and assuming that the type of these two managed objects are OCTET STRING, you can call .asOctets() or .asNumbers() methods on the value to get a sequence of either a raw str|bytes or int:

for oid, value in varBinds:
   raw_string = value.asOctets()
   raw_ints = value.asNumbers()

EDIT:

Once you have raw values, you can turn them into whatever:

>>> ''.join(['%.2x' % x for x in b'\x00\x00\x04\x90'])
'00000490'
>>> 
>>> '.'.join(['%d' % x for x in (10,0,1,202)])
'10.0.1.202'