Example #1
0
    def sendVarBinds(self,
                     snmpEngine,
                     notificationTarget,
                     contextEngineId,
                     contextName,
                     varBinds=(),
                     cbFun=None,
                     cbCtx=None):
        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationTarget %s, contextEngineId %s, '
            'contextName "%s", varBinds %s' %
            (notificationTarget, contextEngineId
             or '<default>', contextName, varBinds))

        mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        if contextName:
            __SnmpAdminString, = mibBuilder.importSymbols(
                'SNMP-FRAMEWORK-MIB', 'SnmpAdminString')
            contextName = __SnmpAdminString(contextName)

        # 3.3
        notifyTag, notifyType = config.getNotificationInfo(
            snmpEngine, notificationTarget)

        notificationHandle = getNextHandle()

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationHandle %s, notifyTag %s, '
            'notifyType %s' % (notificationHandle, notifyTag, notifyType))

        varBinds = [(v2c.ObjectIdentifier(x), y) for x, y in varBinds]

        # 3.3.2 & 3.3.3
        snmpTrapOID, sysUpTime = mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpTrapOID', 'sysUpTime')

        snmpTrapOID = snmpTrapOID.getName()
        sysUpTime, uptime = sysUpTime.getName(), sysUpTime.getSyntax()

        # Add sysUpTime if not present already
        if not varBinds or varBinds[0][0] != sysUpTime:
            varBinds.insert(0,
                            (v2c.ObjectIdentifier(sysUpTime), uptime.clone()))

        # Search for and reposition sysUpTime if it's elsewhere
        for idx, varBind in enumerate(varBinds[1:]):
            if varBind[0] == sysUpTime:
                varBinds[0] = varBind
                del varBinds[idx + 1]
                break

        if len(varBinds) < 2:
            raise error.PySnmpError('SNMP notification PDU requires '
                                    'SNMPv2-MIB::snmpTrapOID.0 to be present')

        # Search for and reposition snmpTrapOID if it's elsewhere
        for idx, varBind in enumerate(varBinds[2:]):
            if varBind[0] == snmpTrapOID:
                del varBinds[idx + 2]
                if varBinds[1][0] == snmpTrapOID:
                    varBinds[1] = varBind

                else:
                    varBinds.insert(1, varBind)
                break

        if varBinds[1][0] != snmpTrapOID:
            raise error.PySnmpError('SNMP notification PDU requires '
                                    'SNMPv2-MIB::snmpTrapOID.0 to be present')

        sendRequestHandle = -1

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: final varBinds %s' % (varBinds, ))

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            (transportDomain, transportAddress, timeout, retryCount,
             params) = config.getTargetAddr(snmpEngine, targetAddrName)

            (messageProcessingModel, securityModel, securityName,
             securityLevel) = config.getTargetParams(snmpEngine, params)

            # 3.3.1 XXX
            # XXX filtering's yet to be implemented
            #             filterProfileName = config.getNotifyFilterProfile(params)

            #             (filterSubtree, filterMask,
            #              filterType) = config.getNotifyFilter(filterProfileName)

            debug.logger & debug.FLAG_APP and debug.logger(
                'sendVarBinds: notificationHandle %s, notifyTag %s yields: '
                'transportDomain %s, transportAddress %r, securityModel %s, '
                'securityName %s, securityLevel %s' %
                (notificationHandle, notifyTag, transportDomain,
                 transportAddress, securityModel, securityName, securityLevel))

            for varName, varVal in varBinds:
                if varName in (sysUpTime, snmpTrapOID):
                    continue

                try:
                    snmpEngine.accessControlModel[self.ACM_ID].isAccessAllowed(
                        snmpEngine, securityModel, securityName, securityLevel,
                        'notify', contextName, varName)

                    debug.logger & debug.FLAG_APP and debug.logger(
                        'sendVarBinds: ACL succeeded for OID %s securityName %s'
                        % (varName, securityName))

                except error.StatusInformation:
                    debug.logger & debug.FLAG_APP and debug.logger(
                        'sendVarBinds: ACL denied access for OID %s securityName %s,'
                        'dropping notification' % (varName, securityName))
                    return

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()

            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()

            else:
                raise error.ProtocolError('Unknown notify-type %r', notifyType)

            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # 3.3.5
            try:
                sendRequestHandle = self.sendPdu(
                    snmpEngine, targetAddrName, contextEngineId, contextName,
                    pdu, self.processResponseVarBinds,
                    (notificationHandle, cbFun, cbCtx))

            except error.StatusInformation as exc:
                statusInformation = exc

                debug.logger & debug.FLAG_APP and debug.logger(
                    'sendVarBinds: sendRequestHandle %s: sendPdu() failed '
                    'with %r' % (sendRequestHandle, statusInformation))

                if (notificationHandle not in self.__pendingNotifications or
                        not self.__pendingNotifications[notificationHandle]):

                    if notificationHandle in self.__pendingNotifications:
                        del self.__pendingNotifications[notificationHandle]

                    if cbFun:
                        cbFun(snmpEngine, notificationHandle,
                              statusInformation['errorIndication'], 0, 0, (),
                              cbCtx)

                return notificationHandle

            debug.logger & debug.FLAG_APP and debug.logger(
                'sendVarBinds: notificationHandle %s, sendRequestHandle %s, '
                'timeout %d' %
                (notificationHandle, sendRequestHandle, timeout))

            if notifyType == 2:
                if notificationHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[notificationHandle] = set()
                self.__pendingNotifications[notificationHandle].add(
                    sendRequestHandle)

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationHandle %s, sendRequestHandle %s, '
            'notification(s) sent' % (notificationHandle, sendRequestHandle))

        return notificationHandle
Example #2
0
    def sendVarBinds(self,
                     snmpEngine,
                     notificationTarget,
                     contextEngineId,
                     contextName,
                     varBinds=(),
                     cbFun=None,
                     cbCtx=None):
        debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationTarget %s, contextEngineId %s, contextName "%s", varBinds %s' % (notificationTarget, contextEngineId or '<default>', contextName, varBinds))

        if contextName:
            __SnmpAdminString, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-FRAMEWORK-MIB', 'SnmpAdminString')
            contextName = __SnmpAdminString(contextName)
 
        # 3.3
        ( notifyTag,
          notifyType ) = config.getNotificationInfo(
                snmpEngine, notificationTarget
            )

        notificationHandle = getNextHandle()

        debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, notifyTag %s, notifyType %s' % (notificationHandle, notifyTag, notifyType))

        varBinds = [  (v2c.ObjectIdentifier(x),y) for x,y in varBinds ]

        # 3.3.2 & 3.3.3
        snmpTrapOID, sysUpTime = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpTrapOID', 'sysUpTime')

        for idx in range(len(varBinds)):
            if idx and varBinds[idx][0] == sysUpTime.getName():
                if varBinds[0][0] == sysUpTime.getName():
                    varBinds[0] = varBinds[idx]
                else:
                    varBinds.insert(0, varBinds[idx])
                    del varBinds[idx]

            if varBinds[0][0] != sysUpTime.getName():
                varBinds.insert(0, (v2c.ObjectIdentifier(sysUpTime.getName()),
                                    sysUpTime.getSyntax().clone()))

        if len(varBinds) < 2 or varBinds[1][0] != snmpTrapOID.getName():
            varBinds.insert(1, (v2c.ObjectIdentifier(snmpTrapOID.getName()),
                                snmpTrapOID.getSyntax()))

        debug.logger & debug.flagApp and debug.logger('sendVarBinds: final varBinds %s' % (varBinds,))

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            ( transportDomain,
              transportAddress,
              timeout,
              retryCount,
              params ) = config.getTargetAddr(snmpEngine, targetAddrName)
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel ) = config.getTargetParams(snmpEngine, params)

            # 3.3.1 XXX
# XXX filtering's yet to be implemented
#             filterProfileName = config.getNotifyFilterProfile(params)

#             ( filterSubtree,
#               filterMask,
#               filterType ) = config.getNotifyFilter(filterProfileName)

            debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (notificationHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel))

            for varName, varVal in varBinds:
                if varName in (sysUpTime.name, snmpTrapOID.name):
                    continue
                try:
                    snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName,
                        securityLevel, 'notify', contextName, varName
                        )

                    debug.logger & debug.flagApp and debug.logger('sendVarBinds: ACL succeeded for OID %s securityName %s' % (varName, securityName))

                except error.StatusInformation:
                    debug.logger & debug.flagApp and debug.logger('sendVarBinds: ACL denied access for OID %s securityName %s, droppping notification' % (varName, securityName))
                    return

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise error.ProtocolError('Unknown notify-type %r', notifyType)
            
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # 3.3.5
            try:
                sendRequestHandle = self.sendPdu(snmpEngine,
                                                 targetAddrName,
                                                 contextEngineId,
                                                 contextName,
                                                 pdu,
                                                 self.processResponseVarBinds,
                                                 (notificationHandle, 
                                                  cbFun, cbCtx))
                
            except error.StatusInformation:
                statusInformation = sys.exc_info()[1]
                debug.logger & debug.flagApp and debug.logger('sendVarBinds: sendRequestHandle %s: sendPdu() failed with %r' % (sendRequestHandle, statusInformation))
                if notificationHandle not in self.__pendingNotifications or \
                       not self.__pendingNotifications[notificationHandle]:
                    if notificationHandle in self.__pendingNotifications:
                        del self.__pendingNotifications[notificationHandle]
                    cbFun(snmpEngine,
                          notificationHandle,
                          statusInformation['errorIndication'],
                          0, 0, (), cbCtx)
                return notificationHandle

            debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, sendRequestHandle %s, timeout %d' % (notificationHandle, sendRequestHandle, timeout))

            if notifyType == 2:
                if notificationHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[notificationHandle] = set()
                self.__pendingNotifications[notificationHandle].add(sendRequestHandle)

        debug.logger & debug.flagApp and debug.logger('sendVarBinds: notificationHandle %s, sendRequestHandle %s, notification(s) sent' % (notificationHandle, sendRequestHandle))

        return notificationHandle
Example #3
0
    def sendNotification(self,
                         snmpEngine,
                         notificationTarget,
                         notificationName,
                         additionalVarBinds=None,
                         cbFun=None,
                         cbCtx=None,
                         contextName=null):
        # 3.3
        (notifyTag,
         notifyType) = config.getNotificationInfo(snmpEngine,
                                                  notificationTarget)

        metaSendPduHandle = getNextHandle()

        debug.logger & debug.flagApp and debug.logger(
            'sendNotification: metaSendPduHandle %s, notifyTag %s, notifyType %s'
            % (metaSendPduHandle, notifyTag, notifyType))

        contextMibInstrumCtl = self.__context.getMibInstrum(contextName)

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            (transportDomain, transportAddress, timeout, retryCount,
             params) = config.getTargetAddr(snmpEngine, targetAddrName)
            (messageProcessingModel, securityModel, securityName,
             securityLevel) = config.getTargetParams(snmpEngine, params)

            debug.logger & debug.flagApp and debug.logger(
                'sendNotification: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s'
                %
                (metaSendPduHandle, notifyTag, transportDomain,
                 transportAddress, securityModel, securityName, securityLevel))

            # 3.3.1 XXX
            # XXX filtering's yet to be implemented
            #             filterProfileName = config.getNotifyFilterProfile(params)

            #             ( filterSubtree,
            #               filterMask,
            #               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []

            # 3.3.2 & 3.3.3
            sysUpTime, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'sysUpTime')

            if additionalVarBinds:
                for varName, varVal in additionalVarBinds:
                    if varName == sysUpTime.name:
                        varBinds.append((varName, varVal))
                        break
            if not varBinds:
                varBinds.append((sysUpTime.name,
                                 sysUpTime.syntax.clone()))  # for actual value

            snmpTrapOid, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpTrapOID')
            if notificationName:
                varBinds.append((snmpTrapOid.name,
                                 snmpTrapOid.syntax.clone(notificationName)))
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

# XXX it's still not clear how to instantiate OBJECTS clause
#             # Get notification objects names
#             for notificationObject in snmpTrapVal.getObjects():
#                 mibNode, = contextMibInstrumCtl.mibBuilder.importSymbols(
#                     *notificationObject
#                     )
#                 try:
#                     objectInstance = mibNode.getNode(mibNode.name + (0,))
#                 except error.SmiError:
#                     return
#                 varBinds.append((objectInstance.name, objectInstance.syntax))

            for varName, varVal in additionalVarBinds:
                if varName in (sysUpTime.name, snmpTrapOid.name):
                    continue
                try:
                    snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName, securityLevel,
                        'notify', contextName, varName)
                except error.SmiError:
                    debug.logger & debug.flagApp and debug.logger(
                        'sendNotification: OID %s not allowed for %s, droppping notification'
                        % (varName, securityName))
                    return
                else:
                    varBinds.append((varName, varVal))

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                pdu = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                pduVersion = 1

            # 3.3.5
            if notifyType == 1:
                snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine, transportDomain, transportAddress,
                    messageProcessingModel, securityModel, securityName,
                    securityLevel, self.__context.contextEngineId, contextName,
                    pduVersion, pdu, None)
            else:
                # Convert timeout in seconds into timeout in timer ticks
                timeoutInTicks = float(
                    timeout
                ) / 100 / snmpEngine.transportDispatcher.getTimerResolution()

                # 3.3.6a
                sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine,
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    1,  # expectResponse
                    timeoutInTicks,
                    self.processResponsePdu,
                    (cbFun, cbCtx))

                debug.logger & debug.flagApp and debug.logger(
                    'sendNotification: metaSendPduHandle %s, sendPduHandle %s, timeout %d'
                    % (metaSendPduHandle, sendPduHandle, timeout))

                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain, transportAddress, messageProcessingModel,
                    securityModel, securityName, securityLevel,
                    self.__context.contextEngineId, contextName, pduVersion,
                    pdu, timeout, retryCount, 1, metaSendPduHandle)

                if metaSendPduHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[metaSendPduHandle] = 0
                self.__pendingNotifications[metaSendPduHandle] += 1

                snmpEngine.transportDispatcher.jobStarted(id(self))

        debug.logger & debug.flagApp and debug.logger(
            'sendNotification: metaSendPduHandle %s, notification(s) sent' %
            metaSendPduHandle)

        return metaSendPduHandle
Example #4
0
    def sendNotification(
        self,
        snmpEngine,
        notificationTarget,
        notificationName,
        additionalVarBinds=None,
        cbFun=None,
        cbCtx=None,
        contextName=''
        ):
        # 3.3
        ( notifyTag,
          notifyType ) = config.getNotificationInfo(
            snmpEngine, notificationTarget
            )
        contextMibInstrumCtl = self.__context.getMibInstrum(
            contextName
            )
        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            ( transportDomain,
              transportAddress,
              timeout,
              retryCount,
              params ) = config.getTargetAddr(snmpEngine, targetAddrName)
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel ) = config.getTargetParams(snmpEngine, params)

            # 3.3.1 XXX
# XXX filtering's yet to be implemented
#             filterProfileName = config.getNotifyFilterProfile(params)

#             ( filterSubtree,
#               filterMask,
#               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []
            
            # 3.3.2 & 3.3.3
            sysUpTime, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'sysUpTime'
                )            
            varBinds.append(
                (sysUpTime.name, sysUpTime.syntax.clone()) # for actual value
                )

            snmpTrapOid, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpTrapOID'
                )
            if notificationName:
                varBinds.append(
                    (snmpTrapOid.name,
                     snmpTrapOid.syntax.clone(notificationName))
                    )
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

# XXX it's still not clear how to instantiate OBJECTS clause
#             # Get notification objects names
#             for notificationObject in snmpTrapVal.getObjects():
#                 mibNode, = apply(
#                     contextMibInstrumCtl.mibBuilder.importSymbols,
#                     notificationObject
#                     )
#                 try:
#                     objectInstance = mibNode.getNode(mibNode.name + (0,))
#                 except error.SmiError:
#                     return
#                 varBinds.append((objectInstance.name, objectInstance.syntax))

            if additionalVarBinds:
                if version_info < (1, 6):
                    additionalVarBinds = list(additionalVarBinds)
                varBinds.extend(additionalVarBinds)

            for varName, varVal in varBinds:
                try:
                    snmpEngine.accessControlModel[vacmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName,
                        securityLevel, 'notify', contextName, varName
                        )
                except error.SmiError:
                    return

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                pdu = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                pduVersion = 1
            
            # 3.3.5
            if notifyType == 1:
                snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine,
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    None
                    )
            else:
                # 3.3.6a
                sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine,
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    (self.processResponsePdu, float(timeout)/100 + time.time(),
                     (cbFun, cbCtx))
                    )
                
                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    timeout,
                    retryCount,
                    1,
                    getNextHandle()
                    )
                
                snmpEngine.transportDispatcher.jobStarted(id(self))
    def sendNotification(
        self,
        snmpEngine,
        notificationTarget,
        notificationName,
        additionalVarBinds=(),
        cbFun=None,
        cbCtx=None,
        contextName=null,
        instanceIndex=None
        ):
        debug.logger & debug.flagApp and debug.logger('sendNotification: notificationTarget %s, notificationName %s, additionalVarBinds %s, contextName "%s", instanceIndex %s' % (notificationTarget, notificationName, additionalVarBinds, contextName, instanceIndex))

        if contextName:
            __SnmpAdminString, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMP-FRAMEWORK-MIB', 'SnmpAdminString')
            contextName = __SnmpAdminString(contextName)
 
        # 3.3
        ( notifyTag,
          notifyType ) = config.getNotificationInfo(
            snmpEngine, notificationTarget
            )

        metaSendPduHandle = getNextHandle()

        debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s, notifyType %s' % (metaSendPduHandle, notifyTag, notifyType))

        contextMibInstrumCtl = self.snmpContext.getMibInstrum(contextName)
       
        additionalVarBinds = [  (v2c.ObjectIdentifier(x),y) for x,y in additionalVarBinds ]

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            ( transportDomain,
              transportAddress,
              timeout,
              retryCount,
              params ) = config.getTargetAddr(snmpEngine, targetAddrName)
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel ) = config.getTargetParams(snmpEngine, params)

            debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (metaSendPduHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel))

            # 3.3.1 XXX
# XXX filtering's yet to be implemented
#             filterProfileName = config.getNotifyFilterProfile(params)

#             ( filterSubtree,
#               filterMask,
#               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []
            
            # 3.3.2 & 3.3.3
            sysUpTime, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'sysUpTime')

            for varName, varVal in additionalVarBinds:
                if varName == sysUpTime.name:
                    varBinds.append((varName, varVal))
                    break
            if not varBinds:
                varBinds.append((sysUpTime.name,
                                 sysUpTime.syntax.clone())) # for actual value

            snmpTrapOid, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpTrapOID')
            if len(notificationName) == 2:  # ('MIB', 'symbol')
                notificationTypeObject, = contextMibInstrumCtl.mibBuilder.importSymbols(*notificationName)
                varBinds.append((snmpTrapOid.name, v2c.ObjectIdentifier(notificationTypeObject.name)))
                debug.logger & debug.flagApp and debug.logger('sendNotification: notification type object is %s' % notificationTypeObject)
                for notificationObject in notificationTypeObject.getObjects():
                    mibNode, = contextMibInstrumCtl.mibBuilder.importSymbols(*notificationObject)
                    if instanceIndex:
                        mibNode = mibNode.getNode(mibNode.name + instanceIndex)
                    else:
                        mibNode = mibNode.getNextNode(mibNode.name)
                    varBinds.append((mibNode.name, mibNode.syntax))
                    debug.logger & debug.flagApp and debug.logger('sendNotification: processed notification object %s, instance index %s, var-bind %s' % (notificationObject, instanceIndex is None and "<first>" or instanceIndex, mibNode))
            elif notificationName:  # numeric OID
                varBinds.append(
                    (snmpTrapOid.name,
                     snmpTrapOid.syntax.clone(notificationName))
                )
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

            for varName, varVal in additionalVarBinds:
                if varName in (sysUpTime.name, snmpTrapOid.name):
                    continue
                try:
                    snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName,
                        securityLevel, 'notify', contextName, varName
                        )
                except error.StatusInformation:
                    debug.logger & debug.flagApp and debug.logger('sendNotification: OID %s not allowed for %s, droppping notification' % (varName, securityName))
                    return
                else:
                    varBinds.append((varName, varVal))

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                reqPDU = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                reqPDU = pdu
                pduVersion = 1
            
            # 3.3.5
            if notifyType == 1:
                try:
                    snmpEngine.msgAndPduDsp.sendPdu(
                        snmpEngine,
                        transportDomain,
                        transportAddress,
                        messageProcessingModel,
                        securityModel,
                        securityName,
                        securityLevel,
                        self.snmpContext.contextEngineId,
                        contextName,
                        pduVersion,
                        reqPDU,
                        None
                    )
                except error.StatusInformation:
                    statusInformation = sys.exc_info()[1]
                    debug.logger & debug.flagApp and debug.logger('sendReq: metaSendPduHandle %s: sendPdu() failed with %r' % (metaSendPduHandle, statusInformation))
                    if not self.__pendingNotifications[metaSendPduHandle]:
                        del self.__pendingNotifications[metaSendPduHandle]
                        self._handleResponse(
                            metaSendPduHandle,
                            statusInformation['errorIndication'],
                            0, 0, (),
                            cbFun,
                            cbCtx
                        )
                    return metaSendPduHandle
            else:
                # Convert timeout in seconds into timeout in timer ticks
                timeoutInTicks = float(timeout)/100/snmpEngine.transportDispatcher.getTimerResolution()

                # 3.3.6a
                try:
                    sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                        snmpEngine,
                        transportDomain,
                        transportAddress,
                        messageProcessingModel,
                        securityModel,
                        securityName,
                        securityLevel,
                        self.snmpContext.contextEngineId,
                        contextName,
                        pduVersion,
                        reqPDU,
                        1,                      # expectResponse
                        timeoutInTicks,
                        self.processResponsePdu,
                        (cbFun, cbCtx)
                    )
                except error.StatusInformation:
                    statusInformation = sys.exc_info()[1]
                    debug.logger & debug.flagApp and debug.logger('sendReq: metaSendPduHandle %s: sendPdu() failed with %r' % (metaSendPduHandle, statusInformation))
                    if not self.__pendingNotifications[metaSendPduHandle]:
                        del self.__pendingNotifications[metaSendPduHandle]
                        self._handleResponse(
                            metaSendPduHandle,
                            statusInformation['errorIndication'],
                            0, 0, (),
                            cbFun,
                            cbCtx
                        )
                    return metaSendPduHandle

                debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, sendPduHandle %s, timeout %d' % (metaSendPduHandle, sendPduHandle, timeout))
                
                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.snmpContext.contextEngineId,
                    contextName,
                    pdu,
                    timeout,
                    retryCount,
                    1,
                    metaSendPduHandle
                )
               
                if metaSendPduHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[metaSendPduHandle] = 0
                self.__pendingNotifications[metaSendPduHandle] += 1

                snmpEngine.transportDispatcher.jobStarted(id(self))

        debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notification(s) sent' % metaSendPduHandle)

        return metaSendPduHandle
Example #6
0
    def sendVarBinds(self, snmpEngine, notificationTarget, contextEngineId,
                     contextName, varBinds=(), cbFun=None, cbCtx=None):
        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationTarget %s, contextEngineId %s, '
            'contextName "%s", varBinds %s' % (
                notificationTarget, contextEngineId or '<default>',
                contextName, varBinds))

        mibBuilder = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        if contextName:
            __SnmpAdminString, = mibBuilder.importSymbols(
                'SNMP-FRAMEWORK-MIB', 'SnmpAdminString')
            contextName = __SnmpAdminString(contextName)

        # 3.3
        notifyTag, notifyType = config.getNotificationInfo(
            snmpEngine, notificationTarget)

        notificationHandle = getNextHandle()

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationHandle %s, notifyTag %s, '
            'notifyType %s' % (notificationHandle, notifyTag, notifyType))

        varBinds = [(v2c.ObjectIdentifier(x), y) for x, y in varBinds]

        # 3.3.2 & 3.3.3
        snmpTrapOID, sysUpTime = mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpTrapOID', 'sysUpTime')

        snmpTrapOID = snmpTrapOID.getName()
        sysUpTime, uptime = sysUpTime.getName(), sysUpTime.getSyntax()

        # Add sysUpTime if not present already
        if not varBinds or varBinds[0][0] != sysUpTime:
            varBinds.insert(0, (v2c.ObjectIdentifier(sysUpTime), uptime.clone()))

        # Search for and reposition sysUpTime if it's elsewhere
        for idx, varBind in enumerate(varBinds[1:]):
            if varBind[0] == sysUpTime:
                varBinds[0] = varBind
                del varBinds[idx + 1]
                break

        if len(varBinds) < 2:
            raise error.PySnmpError('SNMP notification PDU requires '
                                    'SNMPv2-MIB::snmpTrapOID.0 to be present')

        # Search for and reposition snmpTrapOID if it's elsewhere
        for idx, varBind in enumerate(varBinds[2:]):
            if varBind[0] == snmpTrapOID:
                del varBinds[idx + 2]
                if varBinds[1][0] == snmpTrapOID:
                    varBinds[1] = varBind

                else:
                    varBinds.insert(1, varBind)
                break

        if varBinds[1][0] != snmpTrapOID:
            raise error.PySnmpError('SNMP notification PDU requires '
                                    'SNMPv2-MIB::snmpTrapOID.0 to be present')

        sendRequestHandle = -1

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: final varBinds %s' % (varBinds,))

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            (transportDomain, transportAddress, timeout,
             retryCount, params) = config.getTargetAddr(snmpEngine,
                                                        targetAddrName)

            (messageProcessingModel, securityModel, securityName,
             securityLevel) = config.getTargetParams(snmpEngine, params)

            # 3.3.1 XXX
            # XXX filtering's yet to be implemented
            #             filterProfileName = config.getNotifyFilterProfile(params)

            #             (filterSubtree, filterMask,
            #              filterType) = config.getNotifyFilter(filterProfileName)

            debug.logger & debug.FLAG_APP and debug.logger(
                'sendVarBinds: notificationHandle %s, notifyTag %s yields: '
                'transportDomain %s, transportAddress %r, securityModel %s, '
                'securityName %s, securityLevel %s' % (
                    notificationHandle, notifyTag, transportDomain, transportAddress,
                    securityModel, securityName, securityLevel))

            for varName, varVal in varBinds:
                if varName in (sysUpTime, snmpTrapOID):
                    continue

                try:
                    snmpEngine.accessControlModel[self.ACM_ID].isAccessAllowed(
                        snmpEngine, securityModel, securityName,
                        securityLevel, 'notify', contextName, varName
                    )

                    debug.logger & debug.FLAG_APP and debug.logger(
                        'sendVarBinds: ACL succeeded for OID %s securityName %s' % (
                            varName, securityName))

                except error.StatusInformation:
                    debug.logger & debug.FLAG_APP and debug.logger(
                        'sendVarBinds: ACL denied access for OID %s securityName %s,'
                        'dropping notification' % (varName, securityName))
                    return

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()

            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()

            else:
                raise error.ProtocolError('Unknown notify-type %r', notifyType)

            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # 3.3.5
            try:
                sendRequestHandle = self.sendPdu(
                    snmpEngine, targetAddrName, contextEngineId,
                    contextName, pdu, self.processResponseVarBinds,
                    (notificationHandle, cbFun, cbCtx)
                )

            except error.StatusInformation as exc:
                statusInformation = exc

                debug.logger & debug.FLAG_APP and debug.logger(
                    'sendVarBinds: sendRequestHandle %s: sendPdu() failed '
                    'with %r' % (sendRequestHandle, statusInformation))

                if (notificationHandle not in self.__pendingNotifications or
                        not self.__pendingNotifications[notificationHandle]):

                    if notificationHandle in self.__pendingNotifications:
                        del self.__pendingNotifications[notificationHandle]

                    if cbFun:
                        cbFun(snmpEngine, notificationHandle,
                              statusInformation['errorIndication'], 0, 0, (),
                              cbCtx)

                return notificationHandle

            debug.logger & debug.FLAG_APP and debug.logger(
                'sendVarBinds: notificationHandle %s, sendRequestHandle %s, '
                'timeout %d' % (notificationHandle, sendRequestHandle, timeout))

            if notifyType == 2:
                if notificationHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[notificationHandle] = set()
                self.__pendingNotifications[notificationHandle].add(sendRequestHandle)

        debug.logger & debug.FLAG_APP and debug.logger(
            'sendVarBinds: notificationHandle %s, sendRequestHandle %s, '
            'notification(s) sent' % (notificationHandle, sendRequestHandle))

        return notificationHandle
Example #7
0
    def sendNotification(self,
                         snmpEngine,
                         notificationTarget,
                         notificationName,
                         additionalVarBinds=(),
                         cbFun=None,
                         cbCtx=None,
                         contextName=null,
                         instanceIndex=None):
        debug.logger & debug.flagApp and debug.logger(
            'sendNotification: notificationTarget %s, notificationName %s, additionalVarBinds %s, contextName "%s", instanceIndex %s'
            % (notificationTarget, notificationName, additionalVarBinds,
               contextName, instanceIndex))

        if contextName:
            __SnmpAdminString, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                'SNMP-FRAMEWORK-MIB', 'SnmpAdminString')
            contextName = __SnmpAdminString(contextName)

        # 3.3
        (notifyTag,
         notifyType) = config.getNotificationInfo(snmpEngine,
                                                  notificationTarget)

        metaSendPduHandle = getNextHandle()

        debug.logger & debug.flagApp and debug.logger(
            'sendNotification: metaSendPduHandle %s, notifyTag %s, notifyType %s'
            % (metaSendPduHandle, notifyTag, notifyType))

        contextMibInstrumCtl = self.snmpContext.getMibInstrum(contextName)

        additionalVarBinds = [(v2c.ObjectIdentifier(x), y)
                              for x, y in additionalVarBinds]

        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            (transportDomain, transportAddress, timeout, retryCount,
             params) = config.getTargetAddr(snmpEngine, targetAddrName)
            (messageProcessingModel, securityModel, securityName,
             securityLevel) = config.getTargetParams(snmpEngine, params)

            debug.logger & debug.flagApp and debug.logger(
                'sendNotification: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s'
                %
                (metaSendPduHandle, notifyTag, transportDomain,
                 transportAddress, securityModel, securityName, securityLevel))

            # 3.3.1 XXX
            # XXX filtering's yet to be implemented
            #             filterProfileName = config.getNotifyFilterProfile(params)

            #             ( filterSubtree,
            #               filterMask,
            #               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []

            # 3.3.2 & 3.3.3
            sysUpTime, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'sysUpTime')

            for varName, varVal in additionalVarBinds:
                if varName == sysUpTime.name:
                    varBinds.append((varName, varVal))
                    break
            if not varBinds:
                varBinds.append((sysUpTime.name,
                                 sysUpTime.syntax.clone()))  # for actual value

            snmpTrapOid, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpTrapOID')
            if len(notificationName) == 2:  # ('MIB', 'symbol')
                notificationTypeObject, = contextMibInstrumCtl.mibBuilder.importSymbols(
                    *notificationName)
                varBinds.append(
                    (snmpTrapOid.name,
                     v2c.ObjectIdentifier(notificationTypeObject.name)))
                debug.logger & debug.flagApp and debug.logger(
                    'sendNotification: notification type object is %s' %
                    notificationTypeObject)
                for notificationObject in notificationTypeObject.getObjects():
                    mibNode, = contextMibInstrumCtl.mibBuilder.importSymbols(
                        *notificationObject)
                    if instanceIndex:
                        mibNode = mibNode.getNode(mibNode.name + instanceIndex)
                    else:
                        mibNode = mibNode.getNextNode(mibNode.name)
                    varBinds.append((mibNode.name, mibNode.syntax))
                    debug.logger & debug.flagApp and debug.logger(
                        'sendNotification: processed notification object %s, instance index %s, var-bind %s'
                        % (notificationObject, instanceIndex is None
                           and "<first>" or instanceIndex, mibNode))
            elif notificationName:  # numeric OID
                varBinds.append((snmpTrapOid.name,
                                 snmpTrapOid.syntax.clone(notificationName)))
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

            for varName, varVal in additionalVarBinds:
                if varName in (sysUpTime.name, snmpTrapOid.name):
                    continue
                try:
                    snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName, securityLevel,
                        'notify', contextName, varName)
                except error.StatusInformation:
                    debug.logger & debug.flagApp and debug.logger(
                        'sendNotification: OID %s not allowed for %s, droppping notification'
                        % (varName, securityName))
                    return
                else:
                    varBinds.append((varName, varVal))

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                reqPDU = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                reqPDU = pdu
                pduVersion = 1

            # 3.3.5
            if notifyType == 1:
                try:
                    snmpEngine.msgAndPduDsp.sendPdu(
                        snmpEngine, transportDomain, transportAddress,
                        messageProcessingModel, securityModel, securityName,
                        securityLevel, self.snmpContext.contextEngineId,
                        contextName, pduVersion, reqPDU, None)
                except error.StatusInformation:
                    statusInformation = sys.exc_info()[1]
                    debug.logger & debug.flagApp and debug.logger(
                        'sendReq: metaSendPduHandle %s: sendPdu() failed with %r'
                        % (metaSendPduHandle, statusInformation))
                    if metaSendPduHandle not in self.__pendingNotifications or \
                            not self.__pendingNotifications[metaSendPduHandle]:
                        if metaSendPduHandle in self.__pendingNotifications:
                            del self.__pendingNotifications[metaSendPduHandle]
                        self._handleResponse(
                            metaSendPduHandle,
                            statusInformation['errorIndication'], 0, 0, (),
                            cbFun, cbCtx)
                    return metaSendPduHandle
            else:
                # Convert timeout in seconds into timeout in timer ticks
                timeoutInTicks = float(
                    timeout
                ) / 100 / snmpEngine.transportDispatcher.getTimerResolution()

                # 3.3.6a
                try:
                    sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                        snmpEngine,
                        transportDomain,
                        transportAddress,
                        messageProcessingModel,
                        securityModel,
                        securityName,
                        securityLevel,
                        self.snmpContext.contextEngineId,
                        contextName,
                        pduVersion,
                        reqPDU,
                        1,  # expectResponse
                        timeoutInTicks,
                        self.processResponsePdu,
                        (cbFun, cbCtx))
                except error.StatusInformation:
                    statusInformation = sys.exc_info()[1]
                    debug.logger & debug.flagApp and debug.logger(
                        'sendReq: metaSendPduHandle %s: sendPdu() failed with %r'
                        % (metaSendPduHandle, statusInformation))
                    if metaSendPduHandle not in self.__pendingNotifications or \
                            not self.__pendingNotifications[metaSendPduHandle]:
                        if metaSendPduHandle in self.__pendingNotifications:
                            del self.__pendingNotifications[metaSendPduHandle]
                        self._handleResponse(
                            metaSendPduHandle,
                            statusInformation['errorIndication'], 0, 0, (),
                            cbFun, cbCtx)
                    return metaSendPduHandle

                debug.logger & debug.flagApp and debug.logger(
                    'sendNotification: metaSendPduHandle %s, sendPduHandle %s, timeout %d'
                    % (metaSendPduHandle, sendPduHandle, timeout))

                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain, transportAddress, messageProcessingModel,
                    securityModel, securityName, securityLevel,
                    self.snmpContext.contextEngineId, contextName, pdu,
                    timeout, retryCount, 1, metaSendPduHandle)

                if metaSendPduHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[metaSendPduHandle] = 0
                self.__pendingNotifications[metaSendPduHandle] += 1

                snmpEngine.transportDispatcher.jobStarted(id(self))

        debug.logger & debug.flagApp and debug.logger(
            'sendNotification: metaSendPduHandle %s, notification(s) sent' %
            metaSendPduHandle)

        return metaSendPduHandle
Example #8
0
    def sendNotification(self,
                         snmpEngine,
                         notificationTarget,
                         notificationName,
                         additionalVarBinds=None,
                         cbFun=None,
                         cbCtx=None,
                         contextName=''):
        # 3.3
        (notifyTag,
         notifyType) = config.getNotificationInfo(snmpEngine,
                                                  notificationTarget)
        contextMibInstrumCtl = self.__context.getMibInstrum(contextName)
        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            (transportDomain, transportAddress, timeout, retryCount,
             params) = config.getTargetAddr(snmpEngine, targetAddrName)
            (messageProcessingModel, securityModel, securityName,
             securityLevel) = config.getTargetParams(snmpEngine, params)

            # 3.3.1 XXX
            # XXX filtering's yet to be implemented
            #             filterProfileName = config.getNotifyFilterProfile(params)

            #             ( filterSubtree,
            #               filterMask,
            #               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []

            # 3.3.2 & 3.3.3
            sysUpTime, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'sysUpTime')
            varBinds.append(
                (sysUpTime.name, sysUpTime.syntax.clone())  # for actual value
            )

            snmpTrapOid, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpTrapOID')
            if notificationName:
                varBinds.append((snmpTrapOid.name,
                                 snmpTrapOid.syntax.clone(notificationName)))
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

# XXX it's still not clear how to instantiate OBJECTS clause
#             # Get notification objects names
#             for notificationObject in snmpTrapVal.getObjects():
#                 mibNode, = apply(
#                     contextMibInstrumCtl.mibBuilder.importSymbols,
#                     notificationObject
#                     )
#                 try:
#                     objectInstance = mibNode.getNode(mibNode.name + (0,))
#                 except error.SmiError:
#                     return
#                 varBinds.append((objectInstance.name, objectInstance.syntax))

            if additionalVarBinds:
                if version_info < (1, 6):
                    additionalVarBinds = list(additionalVarBinds)
                varBinds.extend(additionalVarBinds)

            for varName, varVal in varBinds:
                try:
                    snmpEngine.accessControlModel[vacmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName, securityLevel,
                        'notify', contextName, varName)
                except error.SmiError:
                    return

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                pdu = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                pduVersion = 1

            # 3.3.5
            if notifyType == 1:
                snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine, transportDomain, transportAddress,
                    messageProcessingModel, securityModel, securityName,
                    securityLevel, self.__context.contextEngineId, contextName,
                    pduVersion, pdu, None)
            else:
                # 3.3.6a
                sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine, transportDomain, transportAddress,
                    messageProcessingModel, securityModel, securityName,
                    securityLevel, self.__context.contextEngineId, contextName,
                    pduVersion, pdu,
                    (self.processResponsePdu,
                     float(timeout) / 100 + time.time(), (cbFun, cbCtx)))

                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain, transportAddress, messageProcessingModel,
                    securityModel, securityName, securityLevel,
                    self.__context.contextEngineId, contextName, pduVersion,
                    pdu, timeout, retryCount, 1, getNextHandle())

                snmpEngine.transportDispatcher.jobStarted(id(self))

                return sendPduHandle
Example #9
0
    def sendNotification(
        self,
        snmpEngine,
        notificationTarget,
        notificationName,
        additionalVarBinds=None,
        cbFun=None,
        cbCtx=None,
        contextName=null
        ):
        # 3.3
        ( notifyTag,
          notifyType ) = config.getNotificationInfo(
            snmpEngine, notificationTarget
            )

        metaSendPduHandle = getNextHandle()

        debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s, notifyType %s' % (metaSendPduHandle, notifyTag, notifyType))
                
        contextMibInstrumCtl = self.__context.getMibInstrum(
            contextName
            )
        
        for targetAddrName in config.getTargetNames(snmpEngine, notifyTag):
            ( transportDomain,
              transportAddress,
              timeout,
              retryCount,
              params ) = config.getTargetAddr(snmpEngine, targetAddrName)
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel ) = config.getTargetParams(snmpEngine, params)

            debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notifyTag %s yields: transportDomain %s, transportAddress %r, securityModel %s, securityName %s, securityLevel %s' % (metaSendPduHandle, notifyTag, transportDomain, transportAddress, securityModel, securityName, securityLevel))

            # 3.3.1 XXX
# XXX filtering's yet to be implemented
#             filterProfileName = config.getNotifyFilterProfile(params)

#             ( filterSubtree,
#               filterMask,
#               filterType ) = config.getNotifyFilter(filterProfileName)

            varBinds = []
            
            # 3.3.2 & 3.3.3
            sysUpTime, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'sysUpTime'
                )

            if additionalVarBinds:
                for varName, varVal in additionalVarBinds:
                    if varName == sysUpTime.name:
                        varBinds.append((varName, varVal))
                        break
            if not varBinds:
                varBinds.append((sysUpTime.name,
                                 sysUpTime.syntax.clone())) # for actual value

            snmpTrapOid, = contextMibInstrumCtl.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpTrapOID'
                )
            if notificationName:
                varBinds.append(
                    (snmpTrapOid.name,
                     snmpTrapOid.syntax.clone(notificationName))
                    )
            else:
                varBinds.append((snmpTrapOid.name, snmpTrapOid.syntax))

# XXX it's still not clear how to instantiate OBJECTS clause
#             # Get notification objects names
#             for notificationObject in snmpTrapVal.getObjects():
#                 mibNode, = contextMibInstrumCtl.mibBuilder.importSymbols(
#                     *notificationObject
#                     )
#                 try:
#                     objectInstance = mibNode.getNode(mibNode.name + (0,))
#                 except error.SmiError:
#                     return
#                 varBinds.append((objectInstance.name, objectInstance.syntax))

            for varName, varVal in additionalVarBinds:
                if varName in (sysUpTime.name, snmpTrapOid.name):
                    continue
                try:
                    snmpEngine.accessControlModel[self.acmID].isAccessAllowed(
                        snmpEngine, securityModel, securityName,
                        securityLevel, 'notify', contextName, varName
                        )
                except error.SmiError:
                    debug.logger & debug.flagApp and debug.logger('sendNotification: OID %s not allowed for %s, droppping notification' % (varName, securityName))
                    return
                else:
                    varBinds.append((varName, varVal))

            # 3.3.4
            if notifyType == 1:
                pdu = v2c.SNMPv2TrapPDU()
            elif notifyType == 2:
                pdu = v2c.InformRequestPDU()
            else:
                raise RuntimeError()
            v2c.apiPDU.setDefaults(pdu)
            v2c.apiPDU.setVarBinds(pdu, varBinds)

            # User-side API assumes SMIv2
            if messageProcessingModel == 0:
                pdu = rfc2576.v2ToV1(pdu)
                pduVersion = 0
            else:
                pduVersion = 1
            
            # 3.3.5
            if notifyType == 1:
                snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine,
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    None
                    )
            else:
                # Convert timeout in seconds into timeout in timer ticks
                timeoutInTicks = float(timeout)/100/snmpEngine.transportDispatcher.getTimerResolution()

                # 3.3.6a
                sendPduHandle = snmpEngine.msgAndPduDsp.sendPdu(
                    snmpEngine,
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    1,                      # expectResponse
                    timeoutInTicks,
                    self.processResponsePdu,
                    (cbFun, cbCtx)
                    )

                debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, sendPduHandle %s, timeout %d' % (metaSendPduHandle, sendPduHandle, timeout))
                
                # 3.3.6b
                self.__pendingReqs[sendPduHandle] = (
                    transportDomain,
                    transportAddress,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    self.__context.contextEngineId,
                    contextName,
                    pduVersion,
                    pdu,
                    timeout,
                    retryCount,
                    1,
                    metaSendPduHandle
                )
               
                if metaSendPduHandle not in self.__pendingNotifications:
                    self.__pendingNotifications[metaSendPduHandle] = 0
                self.__pendingNotifications[metaSendPduHandle] += 1

                snmpEngine.transportDispatcher.jobStarted(id(self))

        debug.logger & debug.flagApp and debug.logger('sendNotification: metaSendPduHandle %s, notification(s) sent' % metaSendPduHandle)

        return metaSendPduHandle