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.pull/45/head
parent
7a821af6de
commit
ce56f1b40f
|
@ -1,6 +1,12 @@
|
|||
Revision 4.2.6rc0
|
||||
-----------------
|
||||
|
||||
- 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.
|
||||
- Memory leak fixed in CommandForwarder examples.
|
||||
- Fix to CommandGenerator to make sendRequestHandle persistent across
|
||||
multiple iterations of GETNEXT/GETBULK queries.
|
||||
|
|
|
@ -23,28 +23,38 @@ cmdGen = cmdgen.CommandGenerator(snmpEngine)
|
|||
transportTarget = cmdgen.UdpTransportTarget(('demo.snmplabs.com', 161))
|
||||
|
||||
#
|
||||
# Discover remote SNMP EngineID
|
||||
# To discover remote SNMP EngineID we will tap on SNMP engine inner workings
|
||||
# by setting up execution point observer setup on INTERNAL class PDU processing
|
||||
#
|
||||
|
||||
observerContext = {}
|
||||
|
||||
# Register a callback to be invoked at specified execution point of
|
||||
# SNMP Engine and passed local variables at execution point's local scope
|
||||
snmpEngine.observer.registerObserver(
|
||||
lambda e,p,v,c: c.update(securityEngineId=v['securityEngineId']),
|
||||
'rfc3412.prepareDataElements:internal',
|
||||
cbCtx=observerContext
|
||||
)
|
||||
|
||||
# Send probe SNMP request with invalid credentials
|
||||
|
||||
authData = cmdgen.UsmUserData('non-existing-user')
|
||||
|
||||
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
|
||||
authData, transportTarget
|
||||
)
|
||||
|
||||
# Check for errors and print out results
|
||||
if errorIndication == 'unknownUserName':
|
||||
snmpV3MessageProcessor = snmpEngine.messageProcessingSubsystems[3]
|
||||
securityEngineId, contextEngineId, contextName = snmpV3MessageProcessor.getPeerEngineInfo(*transportTarget.getTransportInfo())
|
||||
if securityEngineId:
|
||||
print('securityEngineId = %s' % securityEngineId.prettyPrint())
|
||||
else:
|
||||
print('Peer EngineID not available')
|
||||
raise Exception()
|
||||
else:
|
||||
print('Can\'t discover peer EngineID', errorIndication)
|
||||
# See if our SNMP engine received REPORT PDU containing securityEngineId
|
||||
|
||||
if 'securityEngineId' not in observerContext:
|
||||
print("Can't discover peer EngineID, errorIndication: %s" % errorIndication)
|
||||
raise Exception()
|
||||
|
||||
securityEngineId = observerContext.pop('securityEngineId')
|
||||
|
||||
print('Remote securityEngineId = %s' % securityEngineId.prettyPrint())
|
||||
|
||||
#
|
||||
# Query remote SNMP Engine using usmUserTable entry configured for it
|
||||
#
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
#
|
||||
# Command Responder
|
||||
#
|
||||
# Listen and respond to SNMP GET/SET/GETNEXT/GETBULK queries with
|
||||
# the following options:
|
||||
#
|
||||
# * SNMPv3
|
||||
# * with USM user 'usr-md5-des', auth: MD5, priv DES or
|
||||
# * allow access to SNMPv2-MIB objects (1.3.6.1.2.1)
|
||||
# * over IPv4/UDP, listening at 127.0.0.1:161
|
||||
# * registers its own execution observer to snmpEngine
|
||||
#
|
||||
# Either of the following Net-SNMP's commands will walk this Agent:
|
||||
#
|
||||
# $ snmpwalk -v3 -u usr-md5-des -l authPriv -A authkey1 -X privkey1 localhost .1.3.6
|
||||
#
|
||||
from pysnmp.entity import engine, config
|
||||
from pysnmp.entity.rfc3413 import cmdrsp, context
|
||||
from pysnmp.carrier.asynsock.dgram import udp
|
||||
|
||||
# Create SNMP engine
|
||||
snmpEngine = engine.SnmpEngine()
|
||||
|
||||
# Execution point observer setup
|
||||
|
||||
# Register a callback to be invoked at specified execution point of
|
||||
# SNMP Engine and passed local variables at code point's local scope
|
||||
def requestObserver(snmpEngine, execpoint, variables, cbCtx):
|
||||
print('Execution point: %s' % execpoint)
|
||||
print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']]))
|
||||
print('* transportAddress: %s' % '@'.join([str(x) for x in variables['transportAddress']]))
|
||||
print('* securityModel: %s' % variables['securityModel'])
|
||||
print('* securityName: %s' % variables['securityName'])
|
||||
print('* securityLevel: %s' % variables['securityLevel'])
|
||||
print('* contextEngineId: %s' % variables['contextEngineId'].prettyPrint())
|
||||
print('* contextName: %s' % variables['contextName'].prettyPrint())
|
||||
print('* PDU: %s' % variables['pdu'].prettyPrint())
|
||||
|
||||
snmpEngine.observer.registerObserver(
|
||||
requestObserver,
|
||||
'rfc3412.receiveMessage:request',
|
||||
'rfc3412.returnResponsePdu'
|
||||
)
|
||||
|
||||
# Transport setup
|
||||
|
||||
# UDP over IPv4
|
||||
config.addTransport(
|
||||
snmpEngine,
|
||||
udp.domainName,
|
||||
udp.UdpTransport().openServerMode(('127.0.0.1', 161))
|
||||
)
|
||||
|
||||
# SNMPv3/USM setup
|
||||
|
||||
# user: usr-md5-des, auth: MD5, priv DES
|
||||
config.addV3User(
|
||||
snmpEngine, 'usr-md5-des',
|
||||
config.usmHMACMD5AuthProtocol, 'authkey1',
|
||||
config.usmDESPrivProtocol, 'privkey1'
|
||||
)
|
||||
|
||||
# Allow full MIB access for each user at VACM
|
||||
config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1,3,6,1,2,1), (1,3,6,1,2,1))
|
||||
|
||||
# Get default SNMP context this SNMP engine serves
|
||||
snmpContext = context.SnmpContext(snmpEngine)
|
||||
|
||||
# Register SNMP Applications at the SNMP engine for particular SNMP context
|
||||
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
|
||||
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
|
||||
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
|
||||
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
|
||||
|
||||
# Register an imaginary never-ending job to keep I/O dispatcher running forever
|
||||
snmpEngine.transportDispatcher.jobStarted(1)
|
||||
|
||||
# Run I/O dispatcher which would receive queries and send responses
|
||||
try:
|
||||
snmpEngine.transportDispatcher.runDispatcher()
|
||||
except:
|
||||
snmpEngine.observer.unregisterObserver()
|
||||
snmpEngine.transportDispatcher.closeDispatcher()
|
||||
raise
|
|
@ -0,0 +1,99 @@
|
|||
#
|
||||
# GET Command Generator
|
||||
#
|
||||
# Send a SNMP GET request
|
||||
# with SNMPv3 with user 'usr-sha-aes', SHA auth and AES128 privacy protocols
|
||||
# over IPv4/UDP
|
||||
# to an Agent at 195.218.195.228:161
|
||||
# for an OID in tuple form
|
||||
# also registers its own execution observer to snmpEngine
|
||||
#
|
||||
# This script performs similar to the following Net-SNMP command:
|
||||
#
|
||||
# $ snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0
|
||||
#
|
||||
from pysnmp.entity import engine, config
|
||||
from pysnmp.carrier.asynsock.dgram import udp
|
||||
from pysnmp.entity.rfc3413 import cmdgen
|
||||
|
||||
# Create SNMP engine instance
|
||||
snmpEngine = engine.SnmpEngine()
|
||||
|
||||
# Execution point observer setup
|
||||
|
||||
# Register a callback to be invoked at specified execution point of
|
||||
# SNMP Engine and passed local variables at code point's local scope
|
||||
def requestObserver(snmpEngine, execpoint, variables, cbCtx):
|
||||
print('Execution point: %s' % execpoint)
|
||||
print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']]))
|
||||
print('* transportAddress: %s' % '@'.join([str(x) for x in variables['transportAddress']]))
|
||||
print('* securityModel: %s' % variables['securityModel'])
|
||||
print('* securityName: %s' % variables['securityName'])
|
||||
print('* securityLevel: %s' % variables['securityLevel'])
|
||||
print('* contextEngineId: %s' % (variables['contextEngineId'] and variables['contextEngineId'].prettyPrint() or '<empty>',))
|
||||
print('* contextName: %s' % variables['contextName'].prettyPrint())
|
||||
print('* PDU: %s' % variables['pdu'].prettyPrint())
|
||||
|
||||
snmpEngine.observer.registerObserver(
|
||||
requestObserver,
|
||||
'rfc3412.sendPdu',
|
||||
'rfc3412.receiveMessage:response'
|
||||
)
|
||||
|
||||
#
|
||||
# SNMPv3/USM setup
|
||||
#
|
||||
|
||||
# user: usr-sha-aes, auth: SHA, priv AES
|
||||
config.addV3User(
|
||||
snmpEngine, 'usr-sha-aes',
|
||||
config.usmHMACSHAAuthProtocol, 'authkey1',
|
||||
config.usmAesCfb128Protocol, 'privkey1'
|
||||
)
|
||||
config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-aes', 'authPriv')
|
||||
|
||||
#
|
||||
# Setup transport endpoint and bind it with security settings yielding
|
||||
# a target name
|
||||
#
|
||||
|
||||
# UDP/IPv4
|
||||
config.addTransport(
|
||||
snmpEngine,
|
||||
udp.domainName,
|
||||
udp.UdpSocketTransport().openClientMode()
|
||||
)
|
||||
config.addTargetAddr(
|
||||
snmpEngine, 'my-router',
|
||||
udp.domainName, ('195.218.195.228', 161),
|
||||
'my-creds'
|
||||
)
|
||||
|
||||
# Error/response receiver
|
||||
def cbFun(sendRequestHandle,
|
||||
errorIndication, errorStatus, errorIndex,
|
||||
varBinds, cbCtx):
|
||||
if errorIndication:
|
||||
print(errorIndication)
|
||||
elif errorStatus:
|
||||
print('%s at %s' % (
|
||||
errorStatus.prettyPrint(),
|
||||
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
|
||||
)
|
||||
)
|
||||
else:
|
||||
for oid, val in varBinds:
|
||||
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
|
||||
|
||||
# Prepare and send a request message
|
||||
cmdgen.GetCommandGenerator().sendReq(
|
||||
snmpEngine,
|
||||
'my-router',
|
||||
( ((1,3,6,1,2,1,1,1,0), None), ),
|
||||
cbFun
|
||||
)
|
||||
|
||||
# Run I/O dispatcher which would send pending queries and process responses
|
||||
snmpEngine.transportDispatcher.runDispatcher()
|
||||
|
||||
snmpEngine.observer.unregisterObserver()
|
|
@ -0,0 +1,67 @@
|
|||
#
|
||||
# Notification Receiver
|
||||
#
|
||||
# Receive SNMP TRAP/INFORM messages with the following options:
|
||||
#
|
||||
# * SNMPv1/SNMPv2c
|
||||
# * with SNMP community "public"
|
||||
# * over IPv4/UDP, listening at 127.0.0.1:162
|
||||
# * use observer facility to pull lower-level request details from SNMP engine
|
||||
# * print received data on stdout
|
||||
#
|
||||
# Either of the following Net-SNMP's commands will send notifications to this
|
||||
# receiver:
|
||||
#
|
||||
# $ snmptrap -v2c -c public 127.0.0.1:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test
|
||||
#
|
||||
from pysnmp.entity import engine, config
|
||||
from pysnmp.carrier.asynsock.dgram import udp
|
||||
from pysnmp.entity.rfc3413 import ntfrcv
|
||||
|
||||
# Create SNMP engine with autogenernated engineID and pre-bound
|
||||
# to socket transport dispatcher
|
||||
snmpEngine = engine.SnmpEngine()
|
||||
|
||||
# Transport setup
|
||||
|
||||
# UDP over IPv4, first listening interface/port
|
||||
config.addTransport(
|
||||
snmpEngine,
|
||||
udp.domainName + (1,),
|
||||
udp.UdpTransport().openServerMode(('127.0.0.1', 162))
|
||||
)
|
||||
|
||||
# SNMPv1/2c setup
|
||||
|
||||
# SecurityName <-> CommunityName mapping
|
||||
config.addV1System(snmpEngine, 'my-area', 'public')
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
# Get an execution context...
|
||||
execContext = snmpEngine.observer.getExecutionContext(
|
||||
'rfc3412.receiveMessage:request'
|
||||
)
|
||||
|
||||
# ... and use inner SNMP engine data to figure out peer address
|
||||
print('Notification from %s, ContextEngineId "%s", ContextName "%s"' % (
|
||||
'@'.join([str(x) for x in execContext['transportAddress']]),
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
for name, val in varBinds:
|
||||
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
|
||||
|
||||
# Register SNMP Application at the SNMP engine
|
||||
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
|
||||
|
||||
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
|
||||
|
||||
# Run I/O dispatcher which would receive queries and send confirmations
|
||||
try:
|
||||
snmpEngine.transportDispatcher.runDispatcher()
|
||||
except:
|
||||
snmpEngine.transportDispatcher.closeDispatcher()
|
||||
raise
|
|
@ -45,14 +45,10 @@ config.addTransport(
|
|||
config.addV1System(snmpEngine, 'my-area', 'public')
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine,
|
||||
stateReference,
|
||||
contextEngineId, contextName,
|
||||
varBinds,
|
||||
cbCtx):
|
||||
transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)
|
||||
print('Notification from %s, ContextEngineId "%s", ContextName "%s"' % (
|
||||
transportAddress, contextEngineId.prettyPrint(),
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -46,14 +46,10 @@ config.addTransport(
|
|||
config.addV1System(snmpEngine, 'my-area', 'public')
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine,
|
||||
stateReference,
|
||||
contextEngineId, contextName,
|
||||
varBinds,
|
||||
cbCtx):
|
||||
transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)
|
||||
print('Notification from %s, ContextEngineId "%s", ContextName "%s"' % (
|
||||
transportAddress, contextEngineId.prettyPrint(),
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -84,13 +84,11 @@ config.addV3User(
|
|||
)
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine,
|
||||
stateReference,
|
||||
contextEngineId, contextName,
|
||||
varBinds,
|
||||
cbCtx):
|
||||
print('Notification received, ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(), contextName.prettyPrint()
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
for name, val in varBinds:
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
#
|
||||
# Notification Receiver
|
||||
#
|
||||
# Receive SNMP TRAP/INFORM messages with the following options:
|
||||
#
|
||||
# * SNMPv1/SNMPv2c
|
||||
# * with SNMP community "public"
|
||||
# * over IPv4/UDP, listening at 127.0.0.1:162
|
||||
# over IPv6/UDP, listening at [::1]:162
|
||||
# * registers its own execution observer to snmpEngine
|
||||
# * print received data on stdout
|
||||
#
|
||||
# Either of the following Net-SNMP's commands will send notifications to this
|
||||
# receiver:
|
||||
#
|
||||
# $ snmptrap -v1 -c public 127.0.0.1 1.3.6.1.4.1.20408.4.1.1.2 127.0.0.1 1 1 123 1.3.6.1.2.1.1.1.0 s test
|
||||
# $ snmptrap -v2c -c public udp6:[::1]:162 123 1.3.6.1.6.3.1.1.5.1 1.3.6.1.2.1.1.5.0 s test
|
||||
# $ snmpinform -v2c -c public 127.0.0.1 123 1.3.6.1.6.3.1.1.5.1
|
||||
#
|
||||
from pysnmp.entity import engine, config
|
||||
from pysnmp.carrier.asynsock.dgram import udp, udp6
|
||||
from pysnmp.entity.rfc3413 import ntfrcv
|
||||
|
||||
# Create SNMP engine with autogenernated engineID and pre-bound
|
||||
# to socket transport dispatcher
|
||||
snmpEngine = engine.SnmpEngine()
|
||||
|
||||
# Execution point observer setup
|
||||
|
||||
# Register a callback to be invoked at specified execution point of
|
||||
# SNMP Engine and passed local variables at code point's local scope
|
||||
def requestObserver(snmpEngine, execpoint, variables, cbCtx):
|
||||
print('Execution point: %s' % execpoint)
|
||||
print('* transportDomain: %s' % '.'.join([str(x) for x in variables['transportDomain']]))
|
||||
print('* transportAddress: %s' % '@'.join([str(x) for x in variables['transportAddress']]))
|
||||
print('* securityModel: %s' % variables['securityModel'])
|
||||
print('* securityName: %s' % variables['securityName'])
|
||||
print('* securityLevel: %s' % variables['securityLevel'])
|
||||
print('* contextEngineId: %s' % variables['contextEngineId'].prettyPrint())
|
||||
print('* contextName: %s' % variables['contextName'].prettyPrint())
|
||||
print('* PDU: %s' % variables['pdu'].prettyPrint())
|
||||
|
||||
snmpEngine.observer.registerObserver(
|
||||
requestObserver,
|
||||
'rfc3412.receiveMessage:request',
|
||||
'rfc3412.returnResponsePdu'
|
||||
)
|
||||
|
||||
# Transport setup
|
||||
|
||||
# UDP over IPv4
|
||||
config.addTransport(
|
||||
snmpEngine,
|
||||
udp.domainName,
|
||||
udp.UdpTransport().openServerMode(('127.0.0.1', 162))
|
||||
)
|
||||
|
||||
# UDP over IPv6
|
||||
config.addTransport(
|
||||
snmpEngine,
|
||||
udp6.domainName,
|
||||
udp6.Udp6Transport().openServerMode(('::1', 162))
|
||||
)
|
||||
|
||||
# SNMPv1/2c setup
|
||||
|
||||
# SecurityName <-> CommunityName mapping
|
||||
config.addV1System(snmpEngine, 'my-area', 'public')
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
for name, val in varBinds:
|
||||
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
|
||||
|
||||
# Register SNMP Application at the SNMP engine
|
||||
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
|
||||
|
||||
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
|
||||
|
||||
# Run I/O dispatcher which would receive queries and send confirmations
|
||||
try:
|
||||
snmpEngine.transportDispatcher.runDispatcher()
|
||||
except:
|
||||
snmpEngine.observer.unregisterObserver()
|
||||
snmpEngine.transportDispatcher.closeDispatcher()
|
||||
raise
|
|
@ -47,15 +47,11 @@ config.addTransport(
|
|||
config.addV1System(snmpEngine, 'my-area', 'public')
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine,
|
||||
stateReference,
|
||||
contextEngineId, contextName,
|
||||
varBinds,
|
||||
cbCtx):
|
||||
transportDomain, transportAddress = snmpEngine.msgAndPduDsp.getTransportInfo(stateReference)
|
||||
print('Notification from %s, SNMP Engine %s, Context %s' % (
|
||||
transportAddress, contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", Context "%s"' % (
|
||||
contextEngineId.prettyPrint(),
|
||||
contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
for name, val in varBinds:
|
||||
|
|
|
@ -89,12 +89,9 @@ config.addV3User(
|
|||
# -- end of SNMPv3/USM setup
|
||||
|
||||
# Callback function for receiving notifications
|
||||
def cbFun(snmpEngine,
|
||||
stateReference,
|
||||
contextEngineId, contextName,
|
||||
varBinds,
|
||||
cbCtx):
|
||||
print('Notification received, ContextEngineId "%s", ContextName "%s"' % (
|
||||
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
|
||||
varBinds, cbCtx):
|
||||
print('Notification from ContextEngineId "%s", ContextName "%s"' % (
|
||||
contextEngineId.prettyPrint(), contextName.prettyPrint()
|
||||
)
|
||||
)
|
||||
|
|
|
@ -7,12 +7,15 @@ from pysnmp.proto.secmod.rfc2576 import SnmpV1SecurityModel, \
|
|||
SnmpV2cSecurityModel
|
||||
from pysnmp.proto.secmod.rfc3414 import SnmpUSMSecurityModel
|
||||
from pysnmp.proto.acmod import rfc3415, void
|
||||
from pysnmp.entity import observer
|
||||
from pysnmp import error
|
||||
|
||||
class SnmpEngine:
|
||||
def __init__(self, snmpEngineID=None, maxMessageSize=65507,
|
||||
msgAndPduDsp=None):
|
||||
self.cache = {}
|
||||
|
||||
self.observer = observer.MetaObserver()
|
||||
|
||||
if msgAndPduDsp is None:
|
||||
self.msgAndPduDsp = MsgAndPduDispatcher()
|
||||
|
@ -63,14 +66,14 @@ class SnmpEngine:
|
|||
self.msgAndPduDsp.receiveMessage(
|
||||
self, transportDomain, transportAddress, wholeMsg
|
||||
)
|
||||
|
||||
|
||||
def __receiveTimerTickCbFun(self, timeNow):
|
||||
self.msgAndPduDsp.receiveTimerTick(self, timeNow)
|
||||
for mpHandler in self.messageProcessingSubsystems.values():
|
||||
mpHandler.receiveTimerTick(self, timeNow)
|
||||
for smHandler in self.securityModels.values():
|
||||
smHandler.receiveTimerTick(self, timeNow)
|
||||
|
||||
|
||||
def registerTransportDispatcher(self, transportDispatcher, recvId=None):
|
||||
if self.transportDispatcher is not None and \
|
||||
self.transportDispatcher is not transportDispatcher:
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue