2

I am trying to implement a snmp agent with two different context name.I got some sample program .This is my agent side code look like . which I got from the snmplabs.com. I tried to implement it and I am facing some error while doing the snmpwalk.

"""
| $ snmpwalk -v3 -u usr-md5-none -l authNoPriv -A authkey1 -n context-a 127.0.0.1 .1.3.6
| $ snmpwalk -v3 -u usr-md5-none -l authNoPriv -A authkey1 -n context-b 127.0.0.1 .1.3.6

"""  #
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, builder
from pysnmp.proto.api import v2c
import datetime
from pysnmp.smi import exval
# Create SNMP engine
snmpEngine = engine.SnmpEngine()

# Transport setup

# UDP over IPv4
config.addTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)

# SNMPv3/USM setup

# user: usr-md5-none, auth: MD5, priv NONE
config.addV3User(
    snmpEngine, 'usr-md5-none',
    config.usmHMACMD5AuthProtocol, 'authkey1'
)

# Allow full MIB access for each user at VACM
config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (1, 3, 6, 1, 2, 1), (1, 3, 6, 1, 2, 1))

# Create an SNMP context with default ContextEngineId (same as SNMP engine ID)
snmpContext = context.SnmpContext(snmpEngine)


class EchoMibInstrumController(instrum.AbstractMibInstrumController):

    def readVars(self, varBinds, acInfo=(None, None)):
        retItem = []
        print ('varbinds', varBinds)
        for ov in varBinds:
            if str(ov[0]) == '1.3.6.1.2.1.1.1.0':
                currentDT = datetime.datetime.now()
                retItem.extend([(ov[0], v2c.OctetString('Hello World! It\'s currently: %s' % str(currentDT)))])
            elif str(ov[0]) == '1.3.6.1.2.1.1.1.1': 
                retItem.extend([(ov[0], v2c.OctetString('You queried  walk  OID %s' % ov[0]))])
            else:
                retItem.extend([(ov[0], v2c.OctetString('You queried readVars OID %s' % str(currentDT)))])
        return retItem

    def readNextVars(self, varBinds, acInfo=(None, None)):
        retItem = []
        print ('Next varbinds', varBinds)
        for ov in varBinds:
            if str(ov[0]) == '1.3.6.1.2.1.1.1.0':
                currentDT = datetime.datetime.now()
                retItem.extend([(ov[0], v2c.OctetString('Hello World! It\'s currently: %s' % str(currentDT)))])
            elif str(ov[0]) == '1.3.6.1.2.1.1.1.1': 
                retItem.extend([(ov[0], v2c.OctetString('You queried  walk  OID %s' % ov[0]))])
            else:
                currentDT = datetime.datetime.now()
                retItem.extend([(ov[0], v2c.OctetString('You queried readNextVars OID %s' % str(currentDT)))])
        return retItem


mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
# mibInstrum = instrum.MibInstrumController(mibBuilder)

MibScalar, MibScalarInstance = mibBuilder.importSymbols(
    'SNMPv2-SMI', 'MibScalar', 'MibScalarInstance'
)


class MyStaticMibScalarInstance(MibScalarInstance):

    def getValue(self, name, idx):
        currentDT = datetime.datetime.now()
        return self.getSyntax().clone(
            'Hello World! It\'s currently: ' + str(currentDT)
        )


mibBuilder.exportSymbols(
    '__MY_MIB', MibScalar((1, 3, 6, 1, 2, 1, 1, 1), v2c.OctetString()),
    MyStaticMibScalarInstance((1, 3, 6, 1, 2, 1, 1, 1), (0,), v2c.OctetString())
)

# Create multiple independent trees of MIB managed objects (empty so far)
mibTreeA = EchoMibInstrumController()
mibTreeB = instrum.MibInstrumController(builder.MibBuilder())

# Register MIB trees at distinct SNMP Context names
snmpContext.registerContextName(v2c.OctetString('context-a'), mibTreeA)
snmpContext.registerContextName(v2c.OctetString('context-b'), mibTreeB)

oid, val = (), None
# logging.debug('done')

# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(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()

except:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise

when I ever I do snmpwalk like

snmpwalk -v3 -u usr-md5-none -l authNoPriv -A authkey1 -n context-a 192.168.2.233 .1.3.6 

It giving reply like

SNMPv2-SMI::dod = STRING: "You queried readNextVars OID 2019-11-21 19:18:22.566000"
Error: OID not increasing: SNMPv2-SMI::dod
 >= SNMPv2-SMI::dod

So my doubt is what I am doing wrong and how to increase this OID ?

Visakh V
  • 55
  • 1
  • 11

1 Answers1

3

Your server (agent) should never return lesser or equal OIDs than arrived with GETNEXT/GETBULK commands.

With your code, make sure that readNextVars always returns increasing OIDs.

SNMP manager has a check for that condition, otherwise manager-agent pair may engage in an endless exchange.

Ilya Etingof
  • 5,440
  • 1
  • 17
  • 21
  • But it should increase automatically right? Could you please provide any snmp agent sample program in the snmpalabs.com which uses multiple context name. I am stuck at this issue. – Visakh V Dec 04 '19 at 09:19
  • 1
    Let me explain by example: the manager asks the agent for the value of OID past 1.1, the agent responds with OID 1.1.1. Then the manager asks the agent for OID past 1.1.1, the agent returns 1.1.2. That way the manager traverses the entire OID tree accessible to it. If the agent would not increase the OID it responds with, then this exchange will never stop. – Ilya Etingof Dec 04 '19 at 17:16