Search code examples
pythonpython-3.xpysnmp

How can I know if the context is being set correctly in pysnmp?


I'm trying to make an snmp server with custom handlers. Looking online, I found that the following code is supposed to do this:

from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.smi import instrum
from pysnmp.proto.api import v2c

# -- Configurable items --
srvHost = '127.0.0.1'
srvPort = 1610
snmpCommunity = 'public'
snmpArea = 'public'
baseMquestOid = (1, 3, 6, 1, 4, 1, 31971)
baseCommonOid = (1, 3, 6, 1, 2, 1)
basePath = '/usr/share/snmp/mibs'
asn1Path = "http://mibs.snmplabs.com/asn1/"

# Create an SNMP context
snmpContext = context.SnmpContext(snmpEngine)


# Very basic Management Instrumentation Controller without
# any Managed Objects attached. It supports only GET's and
# always echos request var-binds in response.
class EchoMibInstrumController(instrum.AbstractMibInstrumController):

    def readMibObjects(self, *varBinds, **context):
        cbFun = context.get('cbFun')
        if cbFun:
            cbFun([(ov[0], "Example") for ov in varBinds], **context) 


# Create a custom Management Instrumentation Controller and register at
# SNMP Context under ContextName 'my-context'
snmpContext.registerContextName(
    v2c.OctetString('mq -context'),  # Context Name
    EchoMibInstrumController()  # Management Instrumentation
)

# Register GET&SET Applications at the SNMP engine for a custom SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)

# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)

# Run I/O dispatcher which would receive queries and send responses
try:
    snmpEngine.transportDispatcher.runDispatcher()

finally:
    snmpEngine.transportDispatcher.closeDispatcher()

Which should create a context that uses that custom readMibObjects function. So if I call a specific existing OID with a get request snmpget -v2c -c public 127.0.0.1:1610 1.3.6.1.2.1.1.9.1.3.1 , let's say that OID belongs to 'SNMPv2-MIB' in the server; I should get something like the following format:

SNMPv2-MIB::sysObjectID.0 = Example

But I am getting the following:

SNMPv2-MIB::sysObjectID.0 = PYSNMP-MIB::pysnmp

So I think that the server is not using the context I'm passing it. Do I need to write something to make the server used the registered context? How can I make it use the custom function I'm passing it to handle the get requests?

I tried debugging by printing the context names with print(snmpContext.contextNames) while initializing the server. That returns the following: {b'': <pysnmp.smi.instrum.MibInstrumController object at 0x78d381975820>, b'mq-context': <__main__.CustomMibInstrumController object at 0x78d381777400>}. I can see that a b'' context exists. Maybe it's using that one. So I tried unregistering using snmpContext.unregisterContextName(OctetString('')), which managed to leave only mq-context in the contextNames variable expecting for the server to use my own context. But when I do that the server doesn't return anything in the snmp get request (or any request).


Solution

  • I was using an old version of pysnmp. It turns out that it was maintained by a new organization and my code (based on code I found online and legacy) was deprecated.