etingof / pysnmp

Python SNMP library
http://snmplabs.com/pysnmp/
BSD 2-Clause "Simplified" License
582 stars 200 forks source link

Set Request Error: Requested OID is out of MIB view #298

Closed dsecca-mss closed 5 years ago

dsecca-mss commented 5 years ago

Hello,

I am using pySNMP 4.4.9 and Python 3.7

I have implemented an SNMP Agent that keeps track of a custom MIB. When I issue a Set Request at any of the OIDs in my MIB, the callback function in my SNMP Manager returns a “notWritable” error status. The OIDs are valid because I can issue a Get Request to them with no problem. The MAX-ACCESS of my OIDs are also read-write so I should be able to write to them.

I stepped into the pySNMP code and I saw that the error originates from the call to acFun when the writeTest method of the MibScalar class tests the access to the OID (line 631 in SNMPv2-SMI.py):

def writeTest(self, name, val, idx, acInfo):
    acFun, acCtx = acInfo
    if name == self.name:
        raise error.NoAccessError(idx=idx, name=name)
    if acFun:
        if self.maxAccess not in ('readwrite', 'readcreate') or \
                acFun(name, self.syntax, idx, 'write', acCtx):
            raise error.NotWritableError(idx=idx, name=name)
    MibTree.writeTest(self, name, val, idx, acInfo)

Stepping into acFun, I see that the call below fails with the “Requested OID is out of MIB view” error:

snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
    snmpEngine, securityModel, securityName,
    securityLevel, viewType, contextName, name
)

This call is made in the _verifyAccess method of the CommandResponder (line 234 in cmdrsp.py).

What am I missing? What does the error “Requested OID is out of MIB view” mean?

I load the MIB using the following code in my Agent:

mib_builder = self._snmpContext.getMibInstrum().getMibBuilder()
        mib_sources = mib_builder.getMibSources() + (builder.DirMibSource('./../../../MIBS/'),)
        mib_builder.setMibSources(*mib_sources)

        # our variables will subclass this since we only have scalar types
        # can't load this type directly, need to import it
        mib_scalar_instance, = mib_builder.importSymbols('SNMPv2-SMI',
                                                         'MibScalarInstance')
        # export our custom mib
       # mib_object contains MIB name, the variable to interact with, a getter and setter function
       # to read and write to the MIB
        for mib_object in mib_objects:
            next_var, = mib_builder.importSymbols(mib_object.mibName,
                                                  mib_object.objectType)
            instance = create_variable(mib_scalar_instance,
                                       mib_object.value_get_func,
                                       mib_object.value_set_func,
                                       next_var.name, (0,),
                                       next_var.syntax)
            # need to export as <var name>Instance
            instance_dict = {str(next_var.name)+"Instance": instance}
            mib_builder.exportSymbols(mib_object.mibName,
                                      **instance_dict)

create_variable class overwrites methods from the MibScalarInstance object but the writeTest and writeCommit methods are never called when the set request is made.

def create_variable(super_class, get_value, set_value, *args):
    class Var(super_class):
        def readGet(self, name, *args):
            return name, self.syntax.clone(get_value())

        def writeTest(self, name, *args):
            print(" Testing var...")

        def writeCommit(self, name, val, *args):
            print(" Setting var...")
            set_value(val)
    return Var(*args)

Thanks for your help!

David

dsecca-mss commented 5 years ago

You can disregard this question! I found my error. My config.addVacmUser function only had a readSubTree argument defined. The Agent was dropping my set request because the setSubTree argument was not defined.