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).
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.