Search code examples
pythonpysnmp

Pysnmp 7.0.3 Bulk walk Agent MIB Returning additional Data


When following the SNMPv2c example found here https://docs.lextudio.com/pysnmp/examples/v1arch/asyncio/manager/cmdgen/walking-operations I am seeing additional returned information which I haven't requested as part of the SNMPBulkWalk.

For example when running "snmpbulkwalk -v2c -c 1.3.6.1.2.1.2.2.1.2 from linux CLI I receive a list of all interface names of the device I am querying.

:~ $ snmpbulkwalk -v2c -c SNMPubliV2c 10.180.0.8 1.3.6.1.2.1.2.2.1.2
iso.3.6.1.2.1.2.2.1.2.1 = STRING: "lo"
iso.3.6.1.2.1.2.2.1.2.2 = STRING: "eth3"
iso.3.6.1.2.1.2.2.1.2.3 = STRING: "eth0"
iso.3.6.1.2.1.2.2.1.2.4 = STRING: "eth1"
iso.3.6.1.2.1.2.2.1.2.5 = STRING: "eth2"
iso.3.6.1.2.1.2.2.1.2.6 = STRING: "npi0"
iso.3.6.1.2.1.2.2.1.2.7 = STRING: "npi1"
iso.3.6.1.2.1.2.2.1.2.8 = STRING: "npi2"
iso.3.6.1.2.1.2.2.1.2.9 = STRING: "npi3"
iso.3.6.1.2.1.2.2.1.2.10 = STRING: "loop0"
iso.3.6.1.2.1.2.2.1.2.11 = STRING: "loop1"
iso.3.6.1.2.1.2.2.1.2.12 = STRING: "loop2"
iso.3.6.1.2.1.2.2.1.2.13 = STRING: "loop3"
iso.3.6.1.2.1.2.2.1.2.14 = STRING: "imq0"
iso.3.6.1.2.1.2.2.1.2.15 = STRING: "eth1.130"
iso.3.6.1.2.1.2.2.1.2.17 = STRING: "pppoe0"

Where as when I run the example code but with my and 1.3.6.1.2.1.2.2.1.2. I seem to get a whole bunch of additional data. I have copy a section of it here but there is way more being spewed out to console.

...
1.3.6.1.4.1.2021.13.15.1.1.10.12 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.13 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.14 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.15 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.16 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.17 - 0
1.3.6.1.4.1.2021.13.15.1.1.10.18 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.1 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.2 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.3 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.4 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.5 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.6 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.7 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.8 - 0
1.3.6.1.4.1.2021.13.15.1.1.11.9 - 0
...

I have found if I put an exit(0) above the return wholeMsg from the SNMPv2c example. It prints only the requested information to the terminal. But then of cause the script stops...

I am pretty new to all of this and stepping through the code with print statements I couldn't really identify how additional mibs are being returned when I have only specified one value in headVars.

from pysnmp.carrier.asyncio.dispatch import AsyncioDispatcher
from pysnmp.carrier.asyncio.dgram import udp
from pyasn1.codec.ber import encoder, decoder
from pysnmp.proto.api import v2c

# SNMP table header
headVars = [v2c.ObjectIdentifier((1,3,6,1,2,1,2,2,1,2))]

# Build PDU
reqPDU = v2c.GetBulkRequestPDU()
v2c.apiBulkPDU.setDefaults(reqPDU)
v2c.apiBulkPDU.setNonRepeaters(reqPDU, 0)
v2c.apiBulkPDU.setMaxRepetitions(reqPDU, 25)
v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x in headVars])

# Build message
reqMsg = v2c.Message()
v2c.apiMessage.setDefaults(reqMsg)
v2c.apiMessage.setCommunity(reqMsg, "<COMMUNITY")
v2c.apiMessage.setPDU(reqMsg, reqPDU)


# noinspection PyUnusedLocal
def cbRecvFun(
    transportDispatcher,
    transportDomain,
    transportAddress,
    wholeMsg,
    reqPDU=reqPDU,
    headVars=headVars,
):
    while wholeMsg:
        rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message())

        rspPDU = v2c.apiMessage.getPDU(rspMsg)

        # Match response to request
        if v2c.apiBulkPDU.getRequestID(reqPDU) == v2c.apiBulkPDU.getRequestID(rspPDU):
            # Format var-binds table
            varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU)

            # Check for SNMP errors reported
            errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU)
            if errorStatus and errorStatus != 2:
                errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU)
                print(
                    "{} at {}".format(
                        errorStatus.prettyPrint(),
                        errorIndex and varBindTable[int(errorIndex) - 1] or "?",
                    )
                )
                transportDispatcher.jobFinished(1)
                break

            # Report SNMP table
            for tableRow in varBindTable:
                for name, val in tableRow:
                    print(f'{name} - {val}')

            # Stop on EOM
            for oid, val in varBindTable[-1]:
                if not isinstance(val, v2c.Null):
                    break

            else:
                transportDispatcher.jobFinished(1)
                continue

            # Generate request for next row
            v2c.apiBulkPDU.setVarBinds(
                reqPDU, [(x, v2c.null) for x, y in varBindTable[-1]]
            )

            v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID())

            transportDispatcher.sendMessage(
                encoder.encode(reqMsg), transportDomain, transportAddress
            )
    # <-----Placing exit(0) here prints only the MIBS I am looking for.
    return wholeMsg


transportDispatcher = AsyncioDispatcher()

transportDispatcher.registerRecvCbFun(cbRecvFun)

transportDispatcher.registerTransport(
    udp.DOMAIN_NAME, udp.UdpAsyncioTransport().openClientMode()
)

transportDispatcher.sendMessage(
    encoder.encode(reqMsg), udp.DOMAIN_NAME, ("<IPADDRESS>", 161)
)

transportDispatcher.jobStarted(1)

# Dispatcher will finish as job#1 counter reaches zero
transportDispatcher.runDispatcher(3)

transportDispatcher.closeDispatcher()

It looks like this library went though a period of not being managed and is now once again being managed but a lot has changed and other stackoverflow records either aren't relevant anymore or point of links which dont exist.

Any help would really be appreciated as I want to learn but I am very stumped.


Solution

  • This is simply because the sample script is designed to perform a complete WALK defined in IETF RFC to discover every following objects, while Net-SNMP snmpbulkwalk command performs a partial WALK and discovers only objects within the subtree of your input OID.

    Nothing is wrong here, and the behavior is consistent from 4.x to 7.x.