def prepareResponseMessage(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference, statusInformation): snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineID = snmpEngineID.syntax # 7.1.2.b cachedParams = self._cache.popByStateRef(stateReference) msgID = cachedParams['msgID'] contextEngineId = cachedParams['contextEngineId'] contextName = cachedParams['contextName'] securityModel = cachedParams['securityModel'] securityName = cachedParams['securityName'] securityLevel = cachedParams['securityLevel'] securityStateReference = cachedParams['securityStateReference'] reportableFlag = cachedParams['reportableFlag'] maxMessageSize = cachedParams['msgMaxSize'] transportDomain = cachedParams['transportDomain'] 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 if pdu is None: pduType = None else: requestID = pdu.getComponentByPosition(0) pduType = pdu.tagSet # 7.1.3b if (pdu is None and not reportableFlag or pduType is not None and pduType not in rfc3411.confirmedClassPDUs): raise error.StatusInformation( errorIndication=errind.loopTerminated) # 7.1.3c reportPDU = rfc1905.ReportPDU() pMod.apiPDU.setVarBinds( reportPDU, ((statusInformation['oid'], statusInformation['val']), )) pMod.apiPDU.setErrorStatus(reportPDU, 0) pMod.apiPDU.setErrorIndex(reportPDU, 0) if pdu is None: pMod.apiPDU.setRequestID(reportPDU, 0) else: # noinspection PyUnboundLocalVariable pMod.apiPDU.setRequestID(reportPDU, requestID) # 7.1.3d.1 if 'securityLevel' in statusInformation: securityLevel = statusInformation['securityLevel'] else: securityLevel = 1 # 7.1.3d.2 if 'contextEngineId' in statusInformation: contextEngineId = statusInformation['contextEngineId'] else: contextEngineId = snmpEngineID # 7.1.3d.3 if 'contextName' in statusInformation: contextName = statusInformation['contextName'] else: contextName = "" # 7.1.3e pdu = reportPDU debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: prepare report PDU for statusInformation %s' % statusInformation) # 7.1.4 if not contextEngineId: contextEngineId = snmpEngineID # XXX impl-dep manner # 7.1.5 if not contextName: contextName = self._emptyStr debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: using contextEngineId %r, contextName %r' % (contextEngineId, contextName)) # 7.1.6 scopedPDU = self.__scopedPDU scopedPDU.setComponentByPosition(0, contextEngineId) scopedPDU.setComponentByPosition(1, contextName) scopedPDU.setComponentByPosition(2) scopedPDU.getComponentByPosition(2).setComponentByType( pdu.tagSet, pdu, verifyConstraints=False, matchTags=False, matchConstraints=False) # 7.1.7 msg = self._snmpMsgSpec # 7.1.7a msg.setComponentByPosition(0, self.messageProcessingModelID, verifyConstraints=False, matchTags=False, matchConstraints=False) headerData = msg.setComponentByPosition(1).getComponentByPosition(1) # 7.1.7b headerData.setComponentByPosition(0, msgID, verifyConstraints=False, matchTags=False, matchConstraints=False) snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') # 7.1.7c # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition(1, snmpEngineMaxMessageSize.syntax, verifyConstraints=False, matchTags=False, matchConstraints=False) # 7.1.7d msgFlags = 0 if securityLevel == 1: pass elif securityLevel == 2: msgFlags |= 0x01 elif securityLevel == 3: msgFlags |= 0x03 else: raise error.ProtocolError('Unknown securityLevel %s' % securityLevel) if pdu.tagSet in rfc3411.confirmedClassPDUs: # XXX not needed? msgFlags |= 0x04 headerData.setComponentByPosition(2, self._msgFlags[msgFlags], verifyConstraints=False, matchTags=False, matchConstraints=False) # 7.1.7e headerData.setComponentByPosition(3, securityModel, verifyConstraints=False, matchTags=False, matchConstraints=False) debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: %s' % (msg.prettyPrint(), )) if securityModel in snmpEngine.securityModels: smHandler = snmpEngine.securityModels[securityModel] else: raise error.StatusInformation( errorIndication=errind.unsupportedSecurityModel) debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: securityModel %r, securityEngineId %r, securityName %r, securityLevel %r' % (securityModel, snmpEngineID, securityName, securityLevel)) # 7.1.8a try: (securityParameters, wholeMsg) = smHandler.generateResponseMsg( snmpEngine, self.messageProcessingModelID, msg, snmpEngineMaxMessageSize.syntax, securityModel, snmpEngineID, securityName, securityLevel, scopedPDU, securityStateReference) except error.StatusInformation: # 7.1.8.b raise debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: SM finished') # Message size constraint verification 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
def prepareResponseMessage(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, pdu, maxSizeResponseScopedPDU, stateReference, statusInformation): snmpEngineID, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineID') snmpEngineID = snmpEngineID.syntax # 7.1.2.b cachedParams = self._cachePopByStateRef(stateReference) msgID = cachedParams['msgID'] contextEngineId = cachedParams['contextEngineId'] contextName = cachedParams['contextName'] securityModel = cachedParams['securityModel'] securityName = cachedParams['securityName'] securityLevel = cachedParams['securityLevel'] securityStateReference = cachedParams['securityStateReference'] reportableFlag = cachedParams['reportableFlag'] maxMessageSize = cachedParams['msgMaxSize'] transportDomain = cachedParams['transportDomain'] transportAddress = cachedParams['transportAddress'] debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: stateReference %s' % (stateReference)) # 7.1.3 if statusInformation is not None and statusInformation.has_key('oid'): # 7.1.3a if pdu is not None: requestID = pdu.getComponentByPosition(0) pduType = pdu.tagSet else: pduType = None # 7.1.3b if pdu is None and not reportableFlag or \ pduType is not None and \ not rfc3411.confirmedClassPDUs.has_key(pduType): raise error.StatusInformation(errorIndication='loopTerminated') # 7.1.3c reportPDU = rfc1905.ReportPDU() pMod.apiPDU.setVarBinds( reportPDU, ((statusInformation['oid'], statusInformation['val']), )) pMod.apiPDU.setErrorStatus(reportPDU, 0) pMod.apiPDU.setErrorIndex(reportPDU, 0) if pdu is None: pMod.apiPDU.setRequestID(reportPDU, 0) else: pMod.apiPDU.setRequestID(reportPDU, requestID) # 7.1.3d.1 if statusInformation.has_key('securityLevel'): securityLevel = statusInformation['securityLevel'] else: securityLevel = 1 # 7.1.3d.2 if statusInformation.has_key('contextEngineId'): contextEngineId = statusInformation['contextEngineId'] else: contextEngineId = snmpEngineID # 7.1.3d.3 if statusInformation.has_key('contextName'): contextName = statusInformation['contextName'] else: contextName = "" # 7.1.3e pdu = reportPDU debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: prepare report PDU for statusInformation %s' % statusInformation) # 7.1.4 if not contextEngineId: contextEngineId = snmpEngineID # XXX impl-dep manner # 7.1.5 if not contextName: contextName = '' debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: using contextEngineId %s, contextName %s' % (contextEngineId, contextName)) # 7.1.6 scopedPDU = ScopedPDU() scopedPDU.setComponentByPosition(0, contextEngineId) scopedPDU.setComponentByPosition(1, contextName) scopedPDU.setComponentByPosition(2) scopedPDU.getComponentByPosition(2).setComponentByType(pdu.tagSet, pdu) # 7.1.7 msg = SNMPv3Message() # 7.1.7a msg.setComponentByPosition(0, 3) # version headerData = msg.setComponentByPosition(1).getComponentByPosition(1) # 7.1.7b headerData.setComponentByPosition(0, msgID) snmpEngineMaxMessageSize, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols( '__SNMP-FRAMEWORK-MIB', 'snmpEngineMaxMessageSize') # 7.1.7c # XXX need to coerce MIB value as it has incompatible constraints set headerData.setComponentByPosition(1, int(snmpEngineMaxMessageSize.syntax)) # 7.1.7d msgFlags = 0 if securityLevel == 1: pass elif securityLevel == 2: msgFlags = msgFlags | 0x01 elif securityLevel == 3: msgFlags = msgFlags | 0x03 else: raise error.ProtocolError('Unknown securityLevel %s' % securityLevel) if rfc3411.confirmedClassPDUs.has_key(pdu.tagSet): # XXX not needed? msgFlags = msgFlags | 0x04 headerData.setComponentByPosition(2, chr(msgFlags)) # 7.1.7e headerData.setComponentByPosition(3, securityModel) debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: %s' % (msg.prettyPrint(), )) smHandler = snmpEngine.securityModels.get(securityModel) if smHandler is None: raise error.StatusInformation( errorIndication='unsupportedSecurityModel') # 7.1.8a try: (securityParameters, wholeMsg) = smHandler.generateResponseMsg( snmpEngine, self.messageProcessingModelID, msg, snmpEngineMaxMessageSize.syntax, securityModel, snmpEngineID, securityName, securityLevel, scopedPDU, securityStateReference) except error.StatusInformation as statusInformation: # 7.1.8.b raise debug.logger & debug.flagMP and debug.logger( 'prepareResponseMessage: SM finished') # Message size constraint verification if len(wholeMsg) > min(snmpEngineMaxMessageSize.syntax, maxMessageSize): raise error.StatusInformation(errorIndication='tooBig') return (transportDomain, transportAddress, wholeMsg)