diff options
author | elie <elie> | 2013-11-09 22:01:33 +0000 |
---|---|---|
committer | elie <elie> | 2013-11-09 22:01:33 +0000 |
commit | 704974e090122b73ef2ad59f23aa0b9e0e50023e (patch) | |
tree | f3331d4dcdd2f9aa3eb4e868410dc056e6dd660e /pysnmp/proto | |
parent | eb44ada0eb7aaeb6be4026abe89af8420a942a9a (diff) | |
download | pysnmp-704974e090122b73ef2ad59f23aa0b9e0e50023e.tar.gz |
Execution Observer facility implemented to give app an inside view
of SNMP engine inner workings. This is thought to be a generic
framework for viewing (and modifying) various internal states
of pysnmp engine. Previously introduced non-RFC APIs (like
getting peer's transport endpoint) will be gradually migrated to
this new framework.
Diffstat (limited to 'pysnmp/proto')
-rw-r--r-- | pysnmp/proto/mpmod/rfc2576.py | 125 | ||||
-rw-r--r-- | pysnmp/proto/mpmod/rfc3412.py | 108 | ||||
-rw-r--r-- | pysnmp/proto/rfc3412.py | 120 |
3 files changed, 314 insertions, 39 deletions
diff --git a/pysnmp/proto/mpmod/rfc2576.py b/pysnmp/proto/mpmod/rfc2576.py index d988496..03ad11f 100644 --- a/pysnmp/proto/mpmod/rfc2576.py +++ b/pysnmp/proto/mpmod/rfc2576.py @@ -33,8 +33,8 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): expectResponse, sendPduHandle ): - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') - snmpEngineID = snmpEngineID.syntax + snmpEngineId, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineId = snmpEngineId.syntax # rfc3412: 7.1.1b if pdu.tagSet in rfc3411.confirmedClassPDUs: @@ -45,7 +45,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # Since there's no SNMP engine identification in v1/2c, # set destination contextEngineId to ours if not contextEngineId: - contextEngineId = snmpEngineID + contextEngineId = snmpEngineId # rfc3412: 7.1.5 if not contextName: @@ -86,7 +86,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): globalData, snmpEngineMaxMessageSize.syntax, securityModel, - snmpEngineID, + snmpEngineId, securityName, securityLevel, scopedPDU @@ -99,7 +99,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): int(msgID), sendPduHandle=sendPduHandle, msgID=msgID, - snmpEngineID=snmpEngineID, + snmpEngineId=snmpEngineId, securityModel=securityModel, securityName=securityName, securityLevel=securityLevel, @@ -109,6 +109,26 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): transportAddress=transportAddress ) + communityName = msg.getComponentByPosition(1) # for observer + + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc2576.prepareOutgoingMessage', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + wholeMsg=wholeMsg, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + communityName=communityName, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc2576.prepareOutgoingMessage' + ) + return ( transportDomain, transportAddress, wholeMsg ) # rfc3412: 7.1 @@ -127,8 +147,8 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): stateReference, statusInformation ): - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') - snmpEngineID = snmpEngineID.syntax + snmpEngineId, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + snmpEngineId = snmpEngineId.syntax # rfc3412: 7.1.2.b if stateReference is None: @@ -162,7 +182,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # Since there's no SNMP engine identification in v1/2c, # set destination contextEngineId to ours if not contextEngineId: - contextEngineId = snmpEngineID + contextEngineId = snmpEngineId # rfc3412: 7.1.5 if not contextName: @@ -193,8 +213,6 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): errorIndication = errind.unsupportedSecurityModel ) - securityEngineId = snmpEngineID - # rfc3412: 7.1.8.a ( securityParameters, wholeMsg ) = smHandler.generateResponseMsg( @@ -203,13 +221,31 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): globalData, maxMessageSize, securityModel, - snmpEngineID, + snmpEngineId, securityName, securityLevel, scopedPDU, securityStateReference ) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc2576.prepareResponseMessage', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=snmpEngineId, + communityName=msg.getComponentByPosition(1), + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc2576.prepareResponseMessage' + ) + return ( transportDomain, transportAddress, wholeMsg ) # rfc3412: 7.2.1 @@ -241,8 +277,9 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # rfc2576: 5.2.1 snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') + communityName = msg.getComponentByPosition(1) securityParameters = ( - msg.getComponentByPosition(1), + communityName, # transportDomain identifies local enpoint (transportDomain, transportAddress) ) @@ -261,7 +298,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): ) # rfc3412: 7.2.6 - ( securityEngineID, + ( securityEngineId, securityName, scopedPDU, maxSizeResponseScopedPDU, @@ -276,7 +313,7 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): msg ) - debug.logger & debug.flagMP and debug.logger('prepareDataElements: SM returned securityEngineID %r securityName %r' % (securityEngineID, securityName)) + debug.logger & debug.flagMP and debug.logger('prepareDataElements: SM returned securityEngineId %r securityName %r' % (securityEngineId, securityName)) # rfc3412: 7.2.6a --> noop @@ -329,6 +366,24 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): stateReference = None + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc2576.prepareDataElements:response', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + communityName=communityName, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc2576.prepareDataElements:response' + ) + # rfc3412: 7.2.12c smHandler.releaseStateInformation(securityStateReference) @@ -353,12 +408,12 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): msgID = pdu.getComponentByPosition(0) # rfc3412: 7.2.13a - snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') - if securityEngineID != snmpEngineID.syntax: + snmpEngineId, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('__SNMP-FRAMEWORK-MIB', 'snmpEngineID') + if securityEngineId != snmpEngineId.syntax: smHandler.releaseStateInformation(securityStateReference) raise error.StatusInformation( errorIndication = errind.engineIDMismatch - ) + ) # rfc3412: 7.2.13b stateReference = self._cache.newStateReference() @@ -378,6 +433,24 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): transportAddress=transportAddress ) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc2576.prepareDataElements:confirmed', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + communityName=communityName, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc2576.prepareDataElements:confirmed' + ) + debug.logger & debug.flagMP and debug.logger('prepareDataElements: cached by new stateReference %s' % stateReference) # rfc3412: 7.2.13c @@ -400,6 +473,24 @@ class SnmpV1MessageProcessingModel(AbstractMessageProcessingModel): # Pass new stateReference to let app browse request details stateReference = self._cache.newStateReference() + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc2576.prepareDataElements:unconfirmed', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + communityName=communityName, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc2576.prepareDataElements:unconfirmed' + ) + # This is not specified explicitly in RFC smHandler.releaseStateInformation(securityStateReference) diff --git a/pysnmp/proto/mpmod/rfc3412.py b/pysnmp/proto/mpmod/rfc3412.py index f51033a..09779a4 100644 --- a/pysnmp/proto/mpmod/rfc3412.py +++ b/pysnmp/proto/mpmod/rfc3412.py @@ -259,6 +259,23 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): transportAddress=transportAddress ) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareOutgoingMessage', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + wholeMsg=wholeMsg, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareOutgoingMessage' + ) + return ( transportDomain, transportAddress, wholeMsg ) @@ -296,7 +313,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): transportAddress = cachedParams['transportAddress'] debug.logger & debug.flagMP and debug.logger('prepareResponseMessage: stateReference %s' % (stateReference)) - + # 7.1.3 if statusInformation is not None and 'oid' in statusInformation: # 7.1.3a @@ -389,7 +406,7 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition( 1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False - ) + ) # 7.1.7d msgFlags = 0 @@ -452,6 +469,23 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): if len(wholeMsg) > min(snmpEngineMaxMessageSize.syntax, maxMessageSize): raise error.StatusInformation(errorIndication=errind.tooBig) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareResponseMessage', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=snmpEngineID, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareResponseMessage' + ) + return ( transportDomain, transportAddress, wholeMsg ) # 7.2.1 @@ -674,6 +708,23 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): # 7.2.11b (incomplete implementation) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareDataElements:internal', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareDataElements:internal' + ) + # 7.2.11c smHandler.releaseStateInformation(securityStateReference) @@ -700,6 +751,23 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): errorIndication = errind.dataMismatch ) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareDataElements:response', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareDataElements:response' + ) + # 7.2.12c smHandler.releaseStateInformation(securityStateReference) stateReference = None @@ -749,6 +817,23 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): debug.logger & debug.flagMP and debug.logger('prepareDataElements: new stateReference %s' % stateReference) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareDataElements:confirmed', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareDataElements:confirmed' + ) + # 7.2.13c return ( messageProcessingModel, securityModel, @@ -768,7 +853,24 @@ class SnmpV3MessageProcessingModel(AbstractMessageProcessingModel): if pduType in rfc3411.unconfirmedClassPDUs: # Pass new stateReference to let app browse request details stateReference = self._cache.newStateReference() - + + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.prepareDataElements:unconfirmed', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + securityEngineId=securityEngineId, + pdu=pdu) + ) + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.prepareDataElements:unconfirmed' + ) + # This is not specified explicitly in RFC smHandler.releaseStateInformation(securityStateReference) diff --git a/pysnmp/proto/rfc3412.py b/pysnmp/proto/rfc3412.py index d18c74f..2aee1a6 100644 --- a/pysnmp/proto/rfc3412.py +++ b/pysnmp/proto/rfc3412.py @@ -33,9 +33,10 @@ class MsgAndPduDispatcher: # Source of sendPduHandle and cache of requesting apps self.__sendPduHandle = nextid.Integer(0xffffff) - # To pass transport info to app + # To pass transport info to app (legacy) self.__transportInfo = {} + # legacy def getTransportInfo(self, stateReference): if stateReference in self.__transportInfo: return self.__transportInfo[stateReference] @@ -135,14 +136,17 @@ class MsgAndPduDispatcher: debug.logger & debug.flagDsp and debug.logger('sendPdu: new sendPduHandle %s, timeout %s ticks, cbFun %s' % (sendPduHandle, timeout, cbFun)) + origTransportDomain = transportDomain + origTransportAddress = transportAddress + # 4.1.1.4 & 4.1.1.5 try: - ( destTransportDomain, - destTransportAddress, + ( transportDomain, + transportAddress, outgoingMessage ) = mpHandler.prepareOutgoingMessage( snmpEngine, - transportDomain, - transportAddress, + origTransportDomain, + origTransportAddress, messageProcessingModel, securityModel, securityName, @@ -168,21 +172,38 @@ class MsgAndPduDispatcher: self.__cache.pop(sendPduHandle) raise error.PySnmpError('Transport dispatcher not set') + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.sendPdu', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + outgoingMessage=outgoingMessage, + messageProcessingModel=messageProcessingModel, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + pdu=PDU) + ) + try: snmpEngine.transportDispatcher.sendMessage( - outgoingMessage, destTransportDomain, destTransportAddress + outgoingMessage, transportDomain, transportAddress ) except PySnmpError: if expectResponse: self.__cache.pop(sendPduHandle) raise + snmpEngine.observer.clearExecutionContext(snmpEngine, 'rfc3412.sendPdu') + # Update cache with orignal req params (used for retrying) if expectResponse: self.__cache.update( sendPduHandle, - transportDomain=transportDomain, - transportAddress=transportAddress, + transportDomain=origTransportDomain, + transportAddress=origTransportAddress, securityModel=securityModel, securityName=securityName, securityLevel=securityLevel, @@ -210,7 +231,6 @@ class MsgAndPduDispatcher: stateReference, statusInformation ): - """PDU dispatcher -- prepare and serialize a response""" # Extract input values and initialize defaults k = int(messageProcessingModel) if k in snmpEngine.messageProcessingSubsystems: @@ -224,8 +244,8 @@ class MsgAndPduDispatcher: # 4.1.2.2 try: - ( destTransportDomain, - destTransportAddress, + ( transportDomain, + transportAddress, outgoingMessage ) = mpHandler.prepareResponseMessage( snmpEngine, messageProcessingModel, @@ -239,7 +259,7 @@ class MsgAndPduDispatcher: maxSizeResponseScopedPDU, stateReference, statusInformation - ) + ) debug.logger & debug.flagDsp and debug.logger('returnResponsePdu: MP suceeded') except error.StatusInformation: # 4.1.2.3 @@ -253,12 +273,31 @@ class MsgAndPduDispatcher: snmpSilentDrops.syntax = snmpSilentDrops.syntax + 1 raise error.StatusInformation(errorIndication=errind.tooBig) + snmpEngine.observer.storeExecutionContext( + snmpEngine, + 'rfc3412.returnResponsePdu', + dict(transportDomain=transportDomain, + transportAddress=transportAddress, + outgoingMessage=outgoingMessage, + messageProcessingModel=messageProcessingModel, + securityModel=securityModel, + securityName=securityName, + securityLevel=securityLevel, + contextEngineId=contextEngineId, + contextName=contextName, + pdu=PDU) + ) + # 4.1.2.4 snmpEngine.transportDispatcher.sendMessage( outgoingMessage, - destTransportDomain, - destTransportAddress - ) + transportDomain, + transportAddress + ) + + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.returnResponsePdu' + ) # 4.2.1 def receiveMessage( @@ -396,11 +435,27 @@ class MsgAndPduDispatcher: # 4.2.2.1.2.d return restOfWholeMsg else: - # Pass transport info to app + 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, @@ -414,9 +469,16 @@ class MsgAndPduDispatcher: 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: @@ -436,6 +498,21 @@ class MsgAndPduDispatcher: # 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( @@ -451,7 +528,12 @@ class MsgAndPduDispatcher: statusInformation, cachedParams['sendPduHandle'], cachedParams['cbCtx'] - ) + ) + + snmpEngine.observer.clearExecutionContext( + snmpEngine, 'rfc3412.receiveMessage:response' + ) + debug.logger & debug.flagDsp and debug.logger('receiveMessage: processResponsePdu succeeded') return restOfWholeMsg |