Example #1
0
    def _recvCb(self, snmpEngine, transportDomain, transportAddress, wholeMsg):
        try:
            mpModel = verdec.decodeMessageVersion(wholeMsg)

        except error.ProtocolError:
            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.FLAG_DSP and debug.logger('receiveMessage: msgVersion %s, msg decoded' % mpModel)

        pMod = api.PROTOCOL_MODULES[mpModel]

        while wholeMsg:
            rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=pMod.Message())
            rspPdu = pMod.apiMessage.getPDU(rspMsg)

            requestId = pMod.apiPDU.getRequestID(rspPdu)

            try:
                stateInfo = self._pendingReqs.pop(requestId)

            except KeyError:
                continue

            self.transportDispatcher.jobFinished(id(self))

            cbFun = stateInfo['cbFun']
            cbCtx = stateInfo['cbCtx']

            if cbFun:
                cbFun(self, requestId, None, rspPdu, cbCtx)

        return wholeMsg
Example #2
0
    def receiveMessage(self, snmpEngine, transportDomain, transportAddress,
                       wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts')
        snmpInPkts.syntax = snmpInPkts.syntax + 1

        # 4.2.1.2
        try:
            restOfWholeMsg = ''  # XXX fix decoder non-recursive return
            msgVersion = verdec.decodeMessageVersion(wholeMsg)
        except PySnmpError:
            snmpInAsn1ParseErrs, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInAsn1ParseErrs')
            snmpInAsn1ParseErrs.syntax = snmpInAsn1ParseErrs.syntax + 1
            return ''  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger(
            'receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        mpHandler = snmpEngine.messageProcessingSubsystems.get(
            int(messageProcessingModel))
        if mpHandler is None:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax = snmpInBadVersions.syntax + 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel, securityModel, securityName,
             securityLevel, contextEngineId, contextName, pduVersion, PDU,
             pduType, sendPduHandle, maxSizeResponseScopedPDU,
             statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                 snmpEngine, transportDomain, transportAddress, wholeMsg)
            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: MP succeded')
        except error.StatusInformation, statusInformation:
            if statusInformation.has_key('sendPduHandle'):
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s' %
                    statusInformation)
                self.__expireRequest(
                    snmpEngine,
                    self.__cachePop(statusInformation['sendPduHandle']),
                    statusInformation)
            return restOfWholeMsg
    def log(self, msg, address, direction):
        #TODO: log snmp request/response at the same time.

        if direction == 'in':
            direction = 'request from'
            log_key = 'request'
        else:
            direction = 'reply to'
            log_key = 'response'

        #0 = v1, 1 = v2, 3 = v3
        version = verdec.decodeMessageVersion(msg)
        if version == 0 or version == 1:
            pMod = api.protoModules[version]

            rspMsg, wholeMsg = decoder.decode(msg, asn1Spec=pMod.Message())
            community_name = rspMsg.getComponentByPosition(1)
            request_pdu = pMod.apiMessage.getPDU(rspMsg)
            request_type = request_pdu.__class__.__name__

            session_id = request_pdu.getComponentByPosition(0)
            #will there ever be more than one item?
            for oid, val in pMod.apiPDU.getVarBinds(request_pdu):
                logger.debug('SNMPv{0} {1} {2}, Type: {3}, Community: {4}, '
                             'Oid: {5}, Value: {6}'.format(version + 1, direction, address, request_type,
                                                           community_name, oid, val))
        elif version == 3:
            logger.debug('SNMPv3 {0}: {1}. (Decoding not supported yet.)'.format(log_key, msg.encode('hex')))
        else:
            logger.debug('Unknown SNMP {0}: {1}'.format(log_key, msg.encode('hex')))

        #raw data (all snmp version)
        self.log_queue.put(
            {'remote': address,
             'timestamp': datetime.utcnow(),
             'data_type': 'snmp',
             'data': {
                 0: {log_key: msg.encode('hex')}
             }}
        )
    def log(self, msg, address, direction):
        # TODO: log snmp request/response at the same time.

        if direction == "in":
            direction = "request from"
            log_key = "request"
        else:
            direction = "reply to"
            log_key = "response"

        # 0 = v1, 1 = v2, 3 = v3
        version = verdec.decodeMessageVersion(msg)
        if version == 0 or version == 1:
            pMod = api.protoModules[version]

            rspMsg, wholeMsg = decoder.decode(msg, asn1Spec=pMod.Message())
            community_name = rspMsg.getComponentByPosition(1)
            request_pdu = pMod.apiMessage.getPDU(rspMsg)
            request_type = request_pdu.__class__.__name__

            session_id = request_pdu.getComponentByPosition(0)
            # will there ever be more than one item?
            for oid, val in pMod.apiPDU.getVarBinds(request_pdu):
                logger.debug(
                    "SNMPv{0} {1} {2}, Type: {3}, Community: {4}, "
                    "Oid: {5}, Value: {6}".format(
                        version + 1, direction, address, request_type, community_name, oid, val
                    )
                )

        # raw data (all snmp version)
        self.log_queue.put(
            {
                "remote": address,
                "timestamp": datetime.utcnow(),
                "data_type": "snmp",
                "data": {0: {log_key: msg.encode("hex")}},
            }
        )
Example #5
0
    def receiveMessage(
        self,
        snmpEngine,
        transportDomain,
        transportAddress,
        wholeMsg
        ):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts'
            )
        snmpInPkts.syntax = snmpInPkts.syntax + 1

        # 4.2.1.2
        try:
            restOfWholeMsg = null # XXX fix decoder non-recursive return
            msgVersion = verdec.decodeMessageVersion(wholeMsg)
        except PySnmpError:
            snmpInAsn1ParseErrs, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInAsn1ParseErrs')
            snmpInAsn1ParseErrs.syntax = snmpInAsn1ParseErrs.syntax + 1
            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger('receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        k = int(messageProcessingModel)
        if k in snmpEngine.messageProcessingSubsystems:
            mpHandler = snmpEngine.messageProcessingSubsystems[k]
        else:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax = snmpInBadVersions.syntax + 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel,
              contextEngineId,
              contextName,
              pduVersion,
              PDU,
              pduType,
              sendPduHandle,
              maxSizeResponseScopedPDU,
              statusInformation,
              stateReference ) = mpHandler.prepareDataElements(
                snmpEngine,
                transportDomain,
                transportAddress,
                wholeMsg
                )
            debug.logger & debug.flagDsp and debug.logger('receiveMessage: MP succeded')
        except error.StatusInformation:
            statusInformation = sys.exc_info()[1]
            if 'sendPduHandle' in statusInformation:
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger('receiveMessage: MP failed, statusInformation %s' % statusInformation)
                self.__expireRequest(
                    statusInformation['sendPduHandle'],
                    self.__cache.pop(statusInformation['sendPduHandle']),
                    snmpEngine,
                    statusInformation
                    )
            return restOfWholeMsg

        debug.logger & debug.flagDsp and debug.logger('receiveMessage: PDU %s' % PDU.prettyPrint())

        # 4.2.2
        if sendPduHandle is None:
            # 4.2.2.1 (request or notification)

            debug.logger & debug.flagDsp and debug.logger('receiveMessage: pduType %s' % pduType)
            # 4.2.2.1.1
            processPdu = self.getRegisteredApp(contextEngineId, pduType)
            
            # 4.2.2.1.2
            if processPdu is None:
                # 4.2.2.1.2.a
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax = snmpUnknownPDUHandlers.syntax+1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': errind.unknownPDUHandler,
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                    }                    

                debug.logger & debug.flagDsp and debug.logger('receiveMessage: unhandled PDU type')
                
                # XXX fails on unknown PDU
                
                try:
                    ( destTransportDomain,
                      destTransportAddress,
                      outgoingMessage ) = mpHandler.prepareResponseMessage(
                        snmpEngine,
                        messageProcessingModel,
                        securityModel,
                        securityName,
                        securityLevel,
                        contextEngineId,
                        contextName,
                        pduVersion,
                        PDU,
                        maxSizeResponseScopedPDU,
                        stateReference,
                        statusInformation
                        )
                except error.StatusInformation:
                    debug.logger & debug.flagDsp and debug.logger('receiveMessage: report failed, statusInformation %s' % sys.exc_info()[1])
                    return restOfWholeMsg
                
                # 4.2.2.1.2.c
                try:
                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage,
                        destTransportDomain,
                        destTransportAddress
                        )
                except PySnmpError: # XXX
                    pass

                debug.logger & debug.flagDsp and debug.logger('receiveMessage: reporting succeeded')
                
                # 4.2.2.1.2.d
                return restOfWholeMsg
            else:
                # Pass transport info to app
                if stateReference is not None:
                    self.__transportInfo[stateReference] = (
                        transportDomain, transportAddress
                        )
                # 4.2.2.1.3
                processPdu(
                    snmpEngine,
                    messageProcessingModel,
                    securityModel,
                    securityName,
                    securityLevel,
                    contextEngineId,
                    contextName,
                    pduVersion,
                    PDU,
                    maxSizeResponseScopedPDU,
                    stateReference
                    )
                if stateReference is not None:
                    del self.__transportInfo[stateReference]
                debug.logger & debug.flagDsp and debug.logger('receiveMessage: processPdu succeeded')
                return restOfWholeMsg
        else:
            # 4.2.2.2 (response)
            
            # 4.2.2.2.1
            cachedParams = self.__cache.pop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax = snmpUnknownPDUHandlers.syntax+1
                return restOfWholeMsg

            debug.logger & debug.flagDsp and debug.logger('receiveMessage: cache read by sendPduHandle %s' % sendPduHandle)
            
            # 4.2.2.2.3
            # no-op ? XXX

            # 4.2.2.2.4
            processResponsePdu = cachedParams['cbFun']
            processResponsePdu(
                snmpEngine,
                messageProcessingModel,
                securityModel,
                securityName,
                securityLevel,
                contextEngineId,
                contextName,
                pduVersion,
                PDU,
                statusInformation,
                cachedParams['sendPduHandle'],
                cachedParams['cbCtx']
                )
            debug.logger & debug.flagDsp and debug.logger('receiveMessage: processResponsePdu succeeded')
            return restOfWholeMsg
Example #6
0
    def receiveMessage(self, snmpEngine, transportDomain,
                       transportAddress, wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts'
        )
        snmpInPkts.syntax += 1

        # 4.2.1.2
        try:
            restOfWholeMsg = null  # XXX fix decoder non-recursive return
            msgVersion = verdec.decodeMessageVersion(wholeMsg)
        except error.ProtocolError:
            snmpInASNParseErrs, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB',
                                                                                     'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1
            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger('receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        k = int(messageProcessingModel)
        if k in snmpEngine.messageProcessingSubsystems:
            mpHandler = snmpEngine.messageProcessingSubsystems[k]
        else:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax += 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel, securityModel, securityName,
             securityLevel, contextEngineId, contextName,
             pduVersion, PDU, pduType, sendPduHandle,
             maxSizeResponseScopedPDU, statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                snmpEngine, transportDomain, transportAddress, wholeMsg
            )

            debug.logger & debug.flagDsp and debug.logger('receiveMessage: MP succeded')

        except error.StatusInformation:
            statusInformation = sys.exc_info()[1]
            if 'sendPduHandle' in statusInformation:
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s, forcing a retry' % statusInformation)
                self.__expireRequest(
                    statusInformation['sendPduHandle'],
                    self.__cache.pop(statusInformation['sendPduHandle']),
                    snmpEngine,
                    statusInformation
                )
            return restOfWholeMsg

        debug.logger & debug.flagDsp and debug.logger('receiveMessage: PDU %s' % PDU.prettyPrint())

        # 4.2.2
        if sendPduHandle is None:
            # 4.2.2.1 (request or notification)

            debug.logger & debug.flagDsp and debug.logger('receiveMessage: pduType %s' % pduType)
            # 4.2.2.1.1
            processPdu = self.getRegisteredApp(contextEngineId, pduType)

            # 4.2.2.1.2
            if processPdu is None:
                # 4.2.2.1.2.a
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB',
                                                                                             'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': errind.unknownPDUHandler,
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                }

                debug.logger & debug.flagDsp and debug.logger('receiveMessage: unhandled PDU type')

                # 4.2.2.1.2.c
                try:
                    (destTransportDomain,
                     destTransportAddress,
                     outgoingMessage) = mpHandler.prepareResponseMessage(
                        snmpEngine, messageProcessingModel,
                        securityModel, securityName, securityLevel,
                        contextEngineId, contextName, pduVersion,
                        PDU, maxSizeResponseScopedPDU, stateReference,
                        statusInformation
                    )

                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage, destTransportDomain,
                        destTransportAddress
                    )

                except PySnmpError:
                    debug.logger & debug.flagDsp and debug.logger(
                        'receiveMessage: report failed, statusInformation %s' % sys.exc_info()[1])

                else:
                    debug.logger & debug.flagDsp and debug.logger('receiveMessage: reporting succeeded')

                # 4.2.2.1.2.d
                return restOfWholeMsg

            else:
                snmpEngine.observer.storeExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request',
                    dict(transportDomain=transportDomain,
                         transportAddress=transportAddress,
                         wholeMsg=wholeMsg,
                         messageProcessingModel=messageProcessingModel,
                         securityModel=securityModel,
                         securityName=securityName,
                         securityLevel=securityLevel,
                         contextEngineId=contextEngineId,
                         contextName=contextName,
                         pdu=PDU)
                )

                # pass transport info to app (legacy)
                if stateReference is not None:
                    self.__transportInfo[stateReference] = (
                        transportDomain, transportAddress
                    )

                # 4.2.2.1.3
                processPdu(snmpEngine, messageProcessingModel,
                           securityModel, securityName, securityLevel,
                           contextEngineId, contextName, pduVersion,
                           PDU, maxSizeResponseScopedPDU, stateReference)

                snmpEngine.observer.clearExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request'
                )

                # legacy
                if stateReference is not None:
                    del self.__transportInfo[stateReference]

                debug.logger & debug.flagDsp and debug.logger('receiveMessage: processPdu succeeded')
                return restOfWholeMsg
        else:
            # 4.2.2.2 (response)

            # 4.2.2.2.1
            cachedParams = self.__cache.pop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols('__SNMP-MPD-MIB',
                                                                                             'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1
                return restOfWholeMsg

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: cache read by sendPduHandle %s' % sendPduHandle)

            # 4.2.2.2.3
            # no-op ? XXX

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     wholeMsg=wholeMsg,
                     messageProcessingModel=messageProcessingModel,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     pdu=PDU)
            )

            # 4.2.2.2.4
            processResponsePdu = cachedParams['cbFun']

            processResponsePdu(snmpEngine, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion,
                               PDU, statusInformation,
                               cachedParams['sendPduHandle'],
                               cachedParams['cbCtx'])

            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response'
            )

            debug.logger & debug.flagDsp and debug.logger('receiveMessage: processResponsePdu succeeded')

            return restOfWholeMsg
Example #7
0
    def receiveMessage(
        self,
        snmpEngine,
        transportDomain,
        transportAddress,
        wholeMsg
        ):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts'
            )
        snmpInPkts.syntax = snmpInPkts.syntax + 1

        # 4.2.1.2
        try:
            restOfWholeMsg = '' # XXX fix decoder non-recursive return
            msgVersion = verdec.decodeMessageVersion(wholeMsg)
        except PySnmpError:
            snmpInAsn1ParseErrs, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInAsn1ParseErrs')
            snmpInAsn1ParseErrs.syntax = snmpInAsn1ParseErrs.syntax + 1
            return ''  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger('receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion
        
        mpHandler = snmpEngine.messageProcessingSubsystems.get(
            int(messageProcessingModel)
            )
        if mpHandler is None:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols('__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax = snmpInBadVersions.syntax + 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            ( messageProcessingModel,
              securityModel,
              securityName,
              securityLevel,
              contextEngineId,
              contextName,
              pduVersion,
              PDU,
              pduType,
              sendPduHandle,
              maxSizeResponseScopedPDU,
              statusInformation,
              stateReference ) = mpHandler.prepareDataElements(
                snmpEngine,
                transportDomain,
                transportAddress,
                wholeMsg
                )
            debug.logger & debug.flagDsp and debug.logger('receiveMessage: MP succeded')
        except error.StatusInformation, statusInformation:
            if statusInformation.has_key('sendPduHandle'):
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger('receiveMessage: MP failed, statusInformation %s' % statusInformation)
                self.__expireRequest(
                    snmpEngine,
                    self.__cachePop(statusInformation['sendPduHandle']),
                    statusInformation
                    )
            return restOfWholeMsg
Example #8
0
    def receiveMessage(self, snmpEngine, transportDomain, transportAddress,
                       wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        # 4.2.1.1
        snmpInPkts, = self.mibInstrumController.mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts')
        snmpInPkts.syntax = snmpInPkts.syntax + 1

        # 4.2.1.2
        try:
            restOfWholeMsg = ''  # XXX fix decoder non-recursive return
            msgVersion = verdec.decodeMessageVersion(wholeMsg)
        except PySnmpError:
            snmpInAsn1ParseErrs, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInAsn1ParseErrs')
            snmpInAsn1ParseErrs.syntax = snmpInAsn1ParseErrs.syntax + 1
            return ''  # n.b the whole buffer gets dropped

        debug.logger & debug.flagDsp and debug.logger(
            'receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        mpHandler = snmpEngine.messageProcessingSubsystems.get(
            int(messageProcessingModel))
        if mpHandler is None:
            snmpInBadVersions, = self.mibInstrumController.mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax = snmpInBadVersions.syntax + 1
            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel, securityModel, securityName,
             securityLevel, contextEngineId, contextName, pduVersion, PDU,
             pduType, sendPduHandle, maxSizeResponseScopedPDU,
             statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                 snmpEngine, transportDomain, transportAddress, wholeMsg)
            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: MP succeded')
        except error.StatusInformation as statusInformation:
            if statusInformation.has_key('sendPduHandle'):
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s' %
                    statusInformation)
                self.__expireRequest(
                    snmpEngine,
                    self.__cachePop(statusInformation['sendPduHandle']),
                    statusInformation)
            return restOfWholeMsg

        debug.logger & debug.flagDsp and debug.logger(
            'receiveMessage: PDU %s' % PDU.prettyPrint())

        # 4.2.2
        if sendPduHandle is None:
            # 4.2.2.1 (request or notification)

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: pduType %s' % pduType)
            # 4.2.2.1.1
            processPdu = self.getRegisteredApp(contextEngineId, pduType)

            # 4.2.2.1.2
            if processPdu is None:
                # 4.2.2.1.2.a
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax = snmpUnknownPDUHandlers.syntax + 1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': 'unknownPDUHandler',
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                }

                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: unhandled PDU type')

                # XXX fails on unknown PDU

                try:
                    (destTransportDomain, destTransportAddress,
                     outgoingMessage) = mpHandler.prepareResponseMessage(
                         snmpEngine, messageProcessingModel, securityModel,
                         securityName, securityLevel, contextEngineId,
                         contextName, pduVersion, PDU,
                         maxSizeResponseScopedPDU, stateReference,
                         statusInformation)
                except error.StatusInformation as statusInformation:
                    debug.logger & debug.flagDsp and debug.logger(
                        'receiveMessage: report failed, statusInformation %s' %
                        statusInformation)
                    return restOfWholeMsg

                # 4.2.2.1.2.c
                try:
                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage, destTransportDomain,
                        destTransportAddress)
                except PySnmpError:  # XXX
                    pass

                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: reporting succeeded')

                # 4.2.2.1.2.d
                return restOfWholeMsg
            else:
                # Pass transport info to app
                if stateReference is not None:
                    self.__transportInfo[stateReference] = (transportDomain,
                                                            transportAddress)
                # 4.2.2.1.3
                processPdu(snmpEngine, messageProcessingModel, securityModel,
                           securityName, securityLevel, contextEngineId,
                           contextName, pduVersion, PDU,
                           maxSizeResponseScopedPDU, stateReference)
                if stateReference is not None:
                    del self.__transportInfo[stateReference]
                debug.logger & debug.flagDsp and debug.logger(
                    'receiveMessage: processPdu succeeded')
                return restOfWholeMsg
        else:
            # 4.2.2.2 (response)

            # 4.2.2.2.1
            cachedParams = self.__cachePop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = self.mibInstrumController.mibBuilder.importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax = snmpUnknownPDUHandlers.syntax + 1
                return restOfWholeMsg

            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: cache read by sendPduHandle %s' %
                sendPduHandle)

            # 4.2.2.2.3
            # no-op ? XXX

            # 4.2.2.2.4
            processResponsePdu, timeoutAt, cbCtx = cachedParams[
                'expectResponse']
            processResponsePdu(snmpEngine, messageProcessingModel,
                               securityModel, securityName, securityLevel,
                               contextEngineId, contextName, pduVersion, PDU,
                               statusInformation,
                               cachedParams['sendPduHandle'], cbCtx)
            debug.logger & debug.flagDsp and debug.logger(
                'receiveMessage: processResponsePdu succeeded')
            return restOfWholeMsg
Example #9
0
    def receiveMessage(self, snmpEngine, transportDomain,
                       transportAddress, wholeMsg):
        """Message dispatcher -- de-serialize message into PDU"""
        mibBuilder = self.mibInstrumController.mibBuilder

        # 4.2.1.1
        snmpInPkts, = mibBuilder.importSymbols(
            '__SNMPv2-MIB', 'snmpInPkts')
        snmpInPkts.syntax += 1

        restOfWholeMsg = null  # XXX fix decoder non-recursive return

        # 4.2.1.2
        try:
            msgVersion = verdec.decodeMessageVersion(wholeMsg)

        except error.ProtocolError:
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1

            return null  # n.b the whole buffer gets dropped

        debug.logger & debug.FLAG_DSP and debug.logger(
            'receiveMessage: msgVersion %s, msg decoded' % msgVersion)

        messageProcessingModel = msgVersion

        try:
            mpHandler = snmpEngine.messageProcessingSubsystems[
                int(messageProcessingModel)]

        except KeyError:
            snmpInBadVersions, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInBadVersions')
            snmpInBadVersions.syntax += 1

            return restOfWholeMsg

        # 4.2.1.3 -- no-op

        # 4.2.1.4
        try:
            (messageProcessingModel,
             securityModel,
             securityName,
             securityLevel,
             contextEngineId,
             contextName,
             pduVersion,
             PDU,
             pduType,
             sendPduHandle,
             maxSizeResponseScopedPDU,
             statusInformation,
             stateReference) = mpHandler.prepareDataElements(
                snmpEngine, transportDomain, transportAddress, wholeMsg)

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: MP succeded')

        except error.StatusInformation as exc:
            statusInformation = exc

            if 'sendPduHandle' in statusInformation:
                # Dropped REPORT -- re-run pending reqs queue as some
                # of them may be waiting for this REPORT
                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: MP failed, statusInformation %s, '
                    'forcing retry' % statusInformation)

                self.__expireRequest(
                    statusInformation['sendPduHandle'],
                    self._cache.pop(statusInformation['sendPduHandle']),
                    snmpEngine,
                    statusInformation)

            return restOfWholeMsg

        except PyAsn1Error as exc:
            debug.logger & debug.FLAG_MP and debug.logger(
                'receiveMessage: %s' % exc)
            snmpInASNParseErrs, = mibBuilder.importSymbols(
                '__SNMPv2-MIB', 'snmpInASNParseErrs')
            snmpInASNParseErrs.syntax += 1

            return restOfWholeMsg

        debug.logger & debug.FLAG_DSP and debug.logger(
            'receiveMessage: PDU %s' % PDU.prettyPrint())

        # 4.2.2
        if sendPduHandle is None:
            # 4.2.2.1 (request or notification)

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: pduType %s' % pduType)

            # 4.2.2.1.1
            processPdu = self.getRegisteredApp(contextEngineId, pduType)

            # 4.2.2.1.2
            if processPdu is None:
                # 4.2.2.1.2.a
                snmpUnknownPDUHandlers, = importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1

                # 4.2.2.1.2.b
                statusInformation = {
                    'errorIndication': errind.unknownPDUHandler,
                    'oid': snmpUnknownPDUHandlers.name,
                    'val': snmpUnknownPDUHandlers.syntax
                }

                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: unhandled PDU type')

                # 4.2.2.1.2.c
                try:
                    (destTransportDomain,
                     destTransportAddress,
                     outgoingMessage) = mpHandler.prepareResponseMessage(
                        snmpEngine, messageProcessingModel,
                        securityModel, securityName, securityLevel,
                        contextEngineId, contextName, pduVersion,
                        PDU, maxSizeResponseScopedPDU, stateReference,
                        statusInformation)

                    snmpEngine.transportDispatcher.sendMessage(
                        outgoingMessage, destTransportDomain,
                        destTransportAddress)

                except PySnmpError as exc:
                    debug.logger & debug.FLAG_DSP and debug.logger(
                        'receiveMessage: report failed, statusInformation %s' % exc)

                else:
                    debug.logger & debug.FLAG_DSP and debug.logger(
                        'receiveMessage: reporting succeeded')

                # 4.2.2.1.2.d
                return restOfWholeMsg

            else:
                snmpEngine.observer.storeExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request',
                    dict(transportDomain=transportDomain,
                         transportAddress=transportAddress,
                         wholeMsg=wholeMsg,
                         messageProcessingModel=messageProcessingModel,
                         securityModel=securityModel,
                         securityName=securityName,
                         securityLevel=securityLevel,
                         contextEngineId=contextEngineId,
                         contextName=contextName,
                         pdu=PDU))

                # pass transport info to app (legacy)
                if stateReference is not None:
                    self._transportInfo[stateReference] = (
                        transportDomain, transportAddress)

                # 4.2.2.1.3 (asynchronous function)
                processPdu(
                    snmpEngine, messageProcessingModel, securityModel,
                    securityName, securityLevel, contextEngineId,
                    contextName, pduVersion, PDU, maxSizeResponseScopedPDU,
                    stateReference)

                snmpEngine.observer.clearExecutionContext(
                    snmpEngine, 'rfc3412.receiveMessage:request')

                # legacy
                if stateReference is not None:
                    del self._transportInfo[stateReference]

                debug.logger & debug.FLAG_DSP and debug.logger(
                    'receiveMessage: processPdu initiated')

                return restOfWholeMsg

        else:
            # 4.2.2.2 (response)

            # 4.2.2.2.1
            cachedParams = self._cache.pop(sendPduHandle)

            # 4.2.2.2.2
            if cachedParams is None:
                snmpUnknownPDUHandlers, = mibBuilder.importSymbols(
                    '__SNMP-MPD-MIB', 'snmpUnknownPDUHandlers')
                snmpUnknownPDUHandlers.syntax += 1

                return restOfWholeMsg

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: cache read by sendPduHandle %s' % sendPduHandle)

            # 4.2.2.2.3
            # no-op ? XXX

            snmpEngine.observer.storeExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response',
                dict(transportDomain=transportDomain,
                     transportAddress=transportAddress,
                     wholeMsg=wholeMsg,
                     messageProcessingModel=messageProcessingModel,
                     securityModel=securityModel,
                     securityName=securityName,
                     securityLevel=securityLevel,
                     contextEngineId=contextEngineId,
                     contextName=contextName,
                     pdu=PDU))

            # 4.2.2.2.4
            processResponsePdu = cachedParams['cbFun']

            processResponsePdu(
                snmpEngine, messageProcessingModel, securityModel,
                securityName, securityLevel, contextEngineId, contextName,
                pduVersion, PDU, statusInformation,
                cachedParams['sendPduHandle'],
                cachedParams['cbCtx'])

            snmpEngine.observer.clearExecutionContext(
                snmpEngine, 'rfc3412.receiveMessage:response')

            debug.logger & debug.FLAG_DSP and debug.logger(
                'receiveMessage: processResponsePdu succeeded')

            return restOfWholeMsg