class AbstractLcdConfigurator: nextID = nextid.Integer(0xffffffff) cacheKeys = [] def _getCache(self, snmpEngine): cacheId = self.__class__.__name__ cache = snmpEngine.getUserContext(cacheId) if cache is None: cache = dict([(x,{}) for x in self.cacheKeys]) snmpEngine.setUserContext(**{cacheId: cache}) return cache def configure(self, snmpEngine, authData, transportTarget): pass def unconfigure(self, snmpEngine, authData=None): pass
class Cache(object): __stateReference = nextid.Integer(0xffffff) def __init__(self): self.__cacheEntries = {} def push(self, **securityData): stateReference = self.__stateReference() self.__cacheEntries[stateReference] = securityData return stateReference def pop(self, stateReference): if stateReference in self.__cacheEntries: return self.__cacheEntries.pop(stateReference) raise error.ProtocolError( 'Cache miss for stateReference=%s at ' '%s' % (stateReference, self))
def __init__(self, mibInstrumController=None): if mibInstrumController is None: self.mibInstrumController = instrum.MibInstrumController( builder.MibBuilder()) else: self.mibInstrumController = mibInstrumController self.mibInstrumController.mibBuilder.loadModules( 'SNMPv2-MIB', 'SNMP-MPD-MIB', 'SNMP-COMMUNITY-MIB', 'SNMP-TARGET-MIB', 'SNMP-USER-BASED-SM-MIB') # Requests cache self.__cache = cache.Cache() # Registered context engine IDs self.__appsRegistration = {} # Source of sendPduHandle and cache of requesting apps self.__sendPduHandle = nextid.Integer(0xffffff) # To pass transport info to app (legacy) self.__transportInfo = {}
import sys from pyasn1.compat.octets import null from pysnmp.entity.rfc3413 import config from pysnmp.proto.proxy import rfc2576 from pysnmp.proto import rfc3411 from pysnmp.proto.api import v2c from pysnmp.proto import error from pysnmp.smi import view, rfc1902 from pysnmp import nextid from pysnmp import debug getNextHandle = nextid.Integer(0x7fffffff) class NotificationOriginator: acmID = 3 # default MIB access control method to use def __init__(self, snmpContext=None): self.__pendingReqs = {} self.__pendingNotifications = {} self.snmpContext = snmpContext # this is deprecated def processResponsePdu(self, snmpEngine, messageProcessingModel, securityModel, securityName, securityLevel, contextEngineId, contextName, pduVersion, PDU, statusInformation,
1).setComponentByType(val.getTagSet(), val, verifyConstraints=False, matchTags=False, matchConstraints=False, innerFlag=True) return varBind @staticmethod def getOIDVal(varBind): return varBind[0], varBind[1].getComponent(1) apiVarBind = VarBindAPI() getNextRequestID = nextid.Integer(0xffffff) class PDUAPI(object): _errorStatus = rfc1157.errorStatus.clone(0) _errorIndex = Integer(0) def setDefaults(self, pdu): pdu.setComponentByPosition(0, getNextRequestID(), verifyConstraints=False, matchTags=False, matchConstraints=False) pdu.setComponentByPosition(1, self._errorStatus, verifyConstraints=False,
from pysnmp.entity.rfc3413.oneliner import cmdgen # Auth protocol usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol usmNoAuthProtocol = config.usmNoAuthProtocol # Privacy protocol usmDESPrivProtocol = config.usmDESPrivProtocol usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol usmAesCfb128Protocol = config.usmAesCfb128Protocol usmAesCfb192Protocol = config.usmAesCfb192Protocol usmAesCfb256Protocol = config.usmAesCfb256Protocol usmNoPrivProtocol = config.usmNoPrivProtocol nextID = nextid.Integer(0xffffffff) class AsynNotificationOriginator(cmdgen.AsynCommandGenerator): def __init__(self, snmpEngine=None, snmpContext=None): cmdgen.AsynCommandGenerator.__init__(self, snmpEngine) self.snmpContext = snmpContext self.__knownNotifyNames = {} self.__knownAuths = {} def __del__(self): self.uncfgNtfOrg() def cfgNtfOrg(self, authData, transportTarget, notifyType): addrName, paramsName = self.cfgCmdGen(authData, transportTarget) tagList = transportTarget.tagList.split()
class MibInstrumController(AbstractMibInstrumController): STATUS_OK = 'ok' STATUS_ERROR = 'err' STATE_START = 'start' STATE_STOP = 'stop' STATE_ANY = '*' # These states are actually methods of the MIB objects STATE_READ_TEST = 'readTest' STATE_READ_GET = 'readGet' STATE_READ_TEST_NEXT = 'readTestNext' STATE_READ_GET_NEXT = 'readGetNext' STATE_WRITE_TEST = 'writeTest' STATE_WRITE_COMMIT = 'writeCommit' STATE_WRITE_CLEANUP = 'writeCleanup' STATE_WRITE_UNDO = 'writeUndo' fsmReadVar = { # ( state, status ) -> newState (STATE_START, STATUS_OK): STATE_READ_TEST, (STATE_READ_TEST, STATUS_OK): STATE_READ_GET, (STATE_READ_GET, STATUS_OK): STATE_STOP, (STATE_ANY, STATUS_ERROR): STATE_STOP } fsmReadNextVar = { # ( state, status ) -> newState (STATE_START, STATUS_OK): STATE_READ_TEST_NEXT, (STATE_READ_TEST_NEXT, STATUS_OK): STATE_READ_GET_NEXT, (STATE_READ_GET_NEXT, STATUS_OK): STATE_STOP, (STATE_ANY, STATUS_ERROR): STATE_STOP } fsmWriteVar = { # ( state, status ) -> newState (STATE_START, STATUS_OK): STATE_WRITE_TEST, (STATE_WRITE_TEST, STATUS_OK): STATE_WRITE_COMMIT, (STATE_WRITE_COMMIT, STATUS_OK): STATE_WRITE_CLEANUP, (STATE_WRITE_CLEANUP, STATUS_OK): STATE_READ_TEST, # Do read after successful write (STATE_READ_TEST, STATUS_OK): STATE_READ_GET, (STATE_READ_GET, STATUS_OK): STATE_STOP, # Error handling (STATE_WRITE_TEST, STATUS_ERROR): STATE_WRITE_CLEANUP, (STATE_WRITE_COMMIT, STATUS_ERROR): STATE_WRITE_UNDO, (STATE_WRITE_UNDO, STATUS_OK): STATE_READ_TEST, # Ignore read errors (removed columns) (STATE_READ_TEST, STATUS_ERROR): STATE_STOP, (STATE_READ_GET, STATUS_ERROR): STATE_STOP, (STATE_ANY, STATUS_ERROR): STATE_STOP } FSM_CONTEXT = '_fsmContext' FSM_SESSION_ID = nextid.Integer(0xffffffff) def __init__(self, mibBuilder): self.mibBuilder = mibBuilder self.lastBuildId = -1 self.lastBuildSyms = {} def getMibBuilder(self): return self.mibBuilder # MIB indexing def __indexMib(self): # Build a tree from MIB objects found at currently loaded modules if self.lastBuildId == self.mibBuilder.lastBuildId: return (MibScalarInstance, MibScalar, MibTableColumn, MibTableRow, MibTable) = self.mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibScalarInstance', 'MibScalar', 'MibTableColumn', 'MibTableRow', 'MibTable' ) mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso') # # Management Instrumentation gets organized as follows: # # MibTree # | # +----MibScalar # | | # | +-----MibScalarInstance # | # +----MibTable # | # +----MibTableRow # | # +-------MibTableColumn # | # +------MibScalarInstance(s) # # Mind you, only Managed Objects get indexed here, various MIB defs and # constants can't be SNMP managed so we drop them. # scalars = {} instances = {} tables = {} rows = {} cols = {} # Sort by module name to give user a chance to slip-in # custom MIB modules (that would be sorted out first) mibSymbols = list(self.mibBuilder.mibSymbols.items()) mibSymbols.sort(key=lambda x: x[0], reverse=True) for modName, mibMod in mibSymbols: for symObj in mibMod.values(): if isinstance(symObj, MibTable): tables[symObj.name] = symObj elif isinstance(symObj, MibTableRow): rows[symObj.name] = symObj elif isinstance(symObj, MibTableColumn): cols[symObj.name] = symObj elif isinstance(symObj, MibScalarInstance): instances[symObj.name] = symObj elif isinstance(symObj, MibScalar): scalars[symObj.name] = symObj # Detach items from each other for symName, parentName in self.lastBuildSyms.items(): if parentName in scalars: scalars[parentName].unregisterSubtrees(symName) elif parentName in cols: cols[parentName].unregisterSubtrees(symName) elif parentName in rows: rows[parentName].unregisterSubtrees(symName) else: mibTree.unregisterSubtrees(symName) lastBuildSyms = {} # Attach Managed Objects Instances to Managed Objects for inst in instances.values(): if inst.typeName in scalars: scalars[inst.typeName].registerSubtrees(inst) elif inst.typeName in cols: cols[inst.typeName].registerSubtrees(inst) else: raise error.SmiError( 'Orphan MIB scalar instance %r at %r' % (inst, self) ) lastBuildSyms[inst.name] = inst.typeName # Attach Table Columns to Table Rows for col in cols.values(): rowName = col.name[:-1] # XXX if rowName in rows: rows[rowName].registerSubtrees(col) else: raise error.SmiError( 'Orphan MIB table column %r at %r' % (col, self) ) lastBuildSyms[col.name] = rowName # Attach Table Rows to MIB tree for row in rows.values(): mibTree.registerSubtrees(row) lastBuildSyms[row.name] = mibTree.name # Attach Tables to MIB tree for table in tables.values(): mibTree.registerSubtrees(table) lastBuildSyms[table.name] = mibTree.name # Attach Scalars to MIB tree for scalar in scalars.values(): mibTree.registerSubtrees(scalar) lastBuildSyms[scalar.name] = mibTree.name self.lastBuildSyms = lastBuildSyms self.lastBuildId = self.mibBuilder.lastBuildId debug.logger & debug.flagIns and debug.logger('__indexMib: rebuilt') # MIB instrumentation def _flipFlopFsmCb(self, varBind, **context): fsmContext = context[self.FSM_CONTEXT] varBinds = fsmContext['varBinds'] idx = context.pop('idx') if idx >= 0: fsmContext['count'] += 1 varBinds[idx] = varBind debug.logger & debug.flagIns and debug.logger( '_flipFlopFsmCb: var-bind %d, processed %d, expected %d' % (idx, fsmContext['count'], len(varBinds))) if fsmContext['count'] < len(varBinds): return debug.logger & debug.flagIns and debug.logger( '_flipFlopFsmCb: finished, output %r' % (varBinds,)) fsmCallable = fsmContext['fsmCallable'] fsmCallable(**context) def flipFlopFsm(self, fsmTable, *varBinds, **context): try: fsmContext = context[self.FSM_CONTEXT] except KeyError: self.__indexMib() fsmContext = context[self.FSM_CONTEXT] = dict( sessionId=self.FSM_SESSION_ID(), varBinds=list(varBinds[:]), fsmCallable=functools.partial(self.flipFlopFsm, fsmTable, *varBinds), state=self.STATE_START, status=self.STATUS_OK ) debug.logger & debug.flagIns and debug.logger('flipFlopFsm: input var-binds %r' % (varBinds,)) mibTree, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'iso') state = fsmContext['state'] status = fsmContext['status'] debug.logger & debug.flagIns and debug.logger( 'flipFlopFsm: current state %s, status %s' % (state, status)) try: newState = fsmTable[(state, status)] except KeyError: try: newState = fsmTable[(self.STATE_ANY, status)] except KeyError: raise error.SmiError('Unresolved FSM state %s, %s' % (state, status)) debug.logger & debug.flagIns and debug.logger( 'flipFlopFsm: state %s status %s -> new state %s' % (state, status, newState)) state = newState if state == self.STATE_STOP: context.pop(self.FSM_CONTEXT, None) cbFun = context.get('cbFun') if cbFun: varBinds = fsmContext['varBinds'] cbFun(varBinds, **context) return fsmContext.update(state=state, count=0) # the case of no var-binds if not varBinds: return self._flipFlopFsmCb(None, idx=-1, **context) mgmtFun = getattr(mibTree, state, None) if not mgmtFun: raise error.SmiError( 'Unsupported state handler %s at %s' % (state, self) ) for idx, varBind in enumerate(varBinds): try: # TODO: managed objects to run asynchronously #mgmtFun(varBind, idx=idx, **context) self._flipFlopFsmCb(mgmtFun(varBind, idx=idx, **context), idx=idx, **context) except error.SmiError: exc = sys.exc_info() debug.logger & debug.flagIns and debug.logger( 'flipFlopFsm: fun %s exception %s for %r with traceback: %s' % ( mgmtFun, exc[0], varBind, traceback.format_exception(*exc))) varBind = varBind[0], exc fsmContext['status'] = self.STATUS_ERROR self._flipFlopFsmCb(varBind, idx=idx, **context) return else: debug.logger & debug.flagIns and debug.logger( 'flipFlopFsm: func %s initiated for %r' % (mgmtFun, varBind)) def readVars(self, *varBinds, **context): self.flipFlopFsm(self.fsmReadVar, *varBinds, **context) def readNextVars(self, *varBinds, **context): self.flipFlopFsm(self.fsmReadNextVar, *varBinds, **context) def writeVars(self, *varBinds, **context): self.flipFlopFsm(self.fsmWriteVar, *varBinds, **context)
class Cache(object): __stateReference = nextid.Integer(0xffffff) __msgID = nextid.Integer(0xffffff) def __init__(self): self.__msgIdIndex = {} self.__stateReferenceIndex = {} self.__sendPduHandleIdx = {} # Message expiration mechanics self.__expirationQueue = {} self.__expirationTimer = 0 # Server mode cache handling def newStateReference(self): return self.__stateReference() def pushByStateRef(self, stateReference, **msgInfo): if stateReference in self.__stateReferenceIndex: raise error.ProtocolError('Cache dup for stateReference=%s at %s' % (stateReference, self)) expireAt = self.__expirationTimer + 600 self.__stateReferenceIndex[stateReference] = msgInfo, expireAt # Schedule to expire if expireAt not in self.__expirationQueue: self.__expirationQueue[expireAt] = {} if 'stateReference' not in self.__expirationQueue[expireAt]: self.__expirationQueue[expireAt]['stateReference'] = {} self.__expirationQueue[expireAt]['stateReference'][stateReference] = 1 def popByStateRef(self, stateReference): if stateReference in self.__stateReferenceIndex: cacheInfo = self.__stateReferenceIndex[stateReference] else: raise error.ProtocolError( 'Cache miss for stateReference=%s at %s' % (stateReference, self)) del self.__stateReferenceIndex[stateReference] cacheEntry, expireAt = cacheInfo del self.__expirationQueue[expireAt]['stateReference'][stateReference] return cacheEntry # Client mode cache handling def newMsgID(self): return self.__msgID() def pushByMsgId(self, msgId, **msgInfo): if msgId in self.__msgIdIndex: raise error.ProtocolError('Cache dup for msgId=%s at %s' % (msgId, self)) expireAt = self.__expirationTimer + 600 self.__msgIdIndex[msgId] = msgInfo, expireAt self.__sendPduHandleIdx[msgInfo['sendPduHandle']] = msgId # Schedule to expire if expireAt not in self.__expirationQueue: self.__expirationQueue[expireAt] = {} if 'msgId' not in self.__expirationQueue[expireAt]: self.__expirationQueue[expireAt]['msgId'] = {} self.__expirationQueue[expireAt]['msgId'][msgId] = 1 def popByMsgId(self, msgId): if msgId in self.__msgIdIndex: cacheInfo = self.__msgIdIndex[msgId] else: raise error.ProtocolError('Cache miss for msgId=%s at %s' % (msgId, self)) msgInfo, expireAt = cacheInfo del self.__sendPduHandleIdx[msgInfo['sendPduHandle']] del self.__msgIdIndex[msgId] cacheEntry, expireAt = cacheInfo del self.__expirationQueue[expireAt]['msgId'][msgId] return cacheEntry def popBySendPduHandle(self, sendPduHandle): if sendPduHandle in self.__sendPduHandleIdx: self.popByMsgId(self.__sendPduHandleIdx[sendPduHandle]) def expireCaches(self): # Uses internal clock to expire pending messages if self.__expirationTimer in self.__expirationQueue: cacheInfo = self.__expirationQueue[self.__expirationTimer] if 'stateReference' in cacheInfo: for stateReference in cacheInfo['stateReference']: del self.__stateReferenceIndex[stateReference] if 'msgId' in cacheInfo: for msgId in cacheInfo['msgId']: del self.__msgIdIndex[msgId] del self.__expirationQueue[self.__expirationTimer] self.__expirationTimer += 1