summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelie <elie>2015-09-20 18:40:58 +0000
committerelie <elie>2015-09-20 18:40:58 +0000
commit8ede39948b4f6037012552bab20da2ff8376d715 (patch)
treede0b67c276ef98e347fbbe3381c5820cc5ad5446
parent75905be006cc82d0880d5c01c35f8457726ac4ee (diff)
downloadpysnmp-8ede39948b4f6037012552bab20da2ff8376d715.tar.gz
major revamp:
* oneliner API moved to pysnmp.hlapi.asyncore location * all hlapi components now pulled from inner modules to into pysnmp.hlapi.asyncore. * LCD configuration moved from SNMP apps classes to be stand-alone * var-binds MIB<->protocol representation code moved from SNMP apps classes to be stand-alone
-rw-r--r--pysnmp/hlapi/asyncore/__init__.py16
-rw-r--r--pysnmp/hlapi/asyncore/_sync/cmdgen.py613
-rw-r--r--pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py266
-rw-r--r--pysnmp/hlapi/asyncore/_sync/compat/ntforg.py52
-rw-r--r--pysnmp/hlapi/asyncore/_sync/ntforg.py124
-rw-r--r--pysnmp/hlapi/asyncore/cmdgen.py529
-rw-r--r--pysnmp/hlapi/asyncore/ntforg.py169
-rw-r--r--pysnmp/hlapi/asyncore/transport.py150
-rw-r--r--pysnmp/hlapi/auth.py278
-rw-r--r--pysnmp/hlapi/context.py48
-rw-r--r--pysnmp/hlapi/lcd.py259
-rw-r--r--pysnmp/hlapi/varbinds.py62
-rw-r--r--pysnmp/proto/rfc1155.py3
-rw-r--r--pysnmp/proto/rfc1157.py3
-rw-r--r--pysnmp/proto/rfc1902.py4
-rw-r--r--pysnmp/proto/rfc1905.py6
-rw-r--r--pysnmp/smi/rfc1902.py15
17 files changed, 2582 insertions, 15 deletions
diff --git a/pysnmp/hlapi/asyncore/__init__.py b/pysnmp/hlapi/asyncore/__init__.py
new file mode 100644
index 0000000..2f815b6
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/__init__.py
@@ -0,0 +1,16 @@
+# This file is necessary to make this directory a package.
+from pysnmp.proto.rfc1902 import *
+from pysnmp.smi.rfc1902 import *
+from pysnmp.hlapi.auth import *
+from pysnmp.hlapi.context import *
+from pysnmp.hlapi.asyncore.transport import *
+from pysnmp.hlapi.asyncore.cmdgen import *
+from pysnmp.hlapi.asyncore.ntforg import *
+from pysnmp.entity.engine import SnmpEngine
+
+try:
+ from pysnmp.hlapi.asyncore._sync.cmdgen import *
+ from pysnmp.hlapi.asyncore._sync.ntforg import *
+except SyntaxError:
+ from pysnmp.hlapi.asyncore._sync.compat.cmdgen import *
+ from pysnmp.hlapi.asyncore._sync.compat.ntforg import *
diff --git a/pysnmp/hlapi/asyncore/_sync/cmdgen.py b/pysnmp/hlapi/asyncore/_sync/cmdgen.py
new file mode 100644
index 0000000..357cc52
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/_sync/cmdgen.py
@@ -0,0 +1,613 @@
+from pysnmp.hlapi.asyncore.cmdgen import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.proto.rfc1905 import endOfMibView
+from pysnmp.proto.errind import *
+from pyasn1.type.univ import Null
+
+__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd']
+
+def getCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+ """Creates a generator to perform one or more SNMP GET queries.
+
+ On each iteration, new SNMP GET request is send (:RFC:`1905#section-4.2.1`).
+ The iterator blocks waiting for response to arrive or error to occur.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName values.
+
+ \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Yields
+ ------
+ errorIndication : str
+ True value indicates SNMP engine error.
+ errorStatus : str
+ True value indicates SNMP PDU error.
+ errorIndex : int
+ Non-zero value refers to `varBinds[errorIndex-1]`
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables returned in SNMP response.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Notes
+ -----
+ The `getCmd` generator will be exhausted immidiately unless
+ a new sequence of `varBinds` are send back into running generator
+ (supported since Python 2.6).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> g = getCmd(SnmpEngine(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)))
+ >>> next(g)
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
+ >>>
+
+ """
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ cmdGen = AsyncCommandGenerator()
+
+ while True:
+ if varBinds:
+ cmdGen.getCmd(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ varBinds,
+ (cbFun, cbCtx),
+ options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+ varBinds = cbCtx['varBinds']
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds )
+
+ if not varBinds:
+ break
+
+def setCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+ """Creates a generator to perform one or more SNMP SET queries.
+
+ On each iteration, new SNMP SET request is send (:RFC:`1905#section-4.2.5`).
+ The iterator blocks waiting for response to arrive or error to occur.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName values.
+
+ \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+ Default is `True`.
+
+ Yields
+ ------
+ errorIndication : str
+ True value indicates SNMP engine error.
+ errorStatus : str
+ True value indicates SNMP PDU error.
+ errorIndex : int
+ Non-zero value refers to `varBinds[errorIndex-1]`
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables returned in SNMP response.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Notes
+ -----
+ The `setCmd` generator will be exhausted immidiately unless
+ a new sequence of `varBinds` are send back into running generator
+ (supported since Python 2.6).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> g = setCmd(SnmpEngine(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0), 'Linux i386'))
+ >>> next(g)
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('Linux i386'))])
+ >>>
+
+ """
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ cmdGen = AsyncCommandGenerator()
+
+ while True:
+ if varBinds:
+ cmdGen.setCmd(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ varBinds,
+ (cbFun, cbCtx),
+ options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+ varBinds = cbCtx['varBinds']
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds )
+
+ if not varBinds:
+ break
+
+def nextCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+ """Creates a generator to perform one or more SNMP GETNEXT queries.
+
+ On each iteration, new SNMP GETNEXT request is send
+ (:RFC:`1905#section-4.2.2`). The iterator blocks waiting for response
+ to arrive or error to occur.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName values.
+
+ \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+ Default is `True`.
+ * `lexicographicMode` - stop iteration when all response MIB
+ variables leave the scope of initial MIB variables in
+ `varBinds`. Default is `True`.
+ * `ignoreNonIncreasingOid` - continue iteration even if response
+ MIB variables (OIDs) are not greater then request MIB variables.
+ Default is `False`.
+ * `maxRows` - stop iteration once this generator instance processed
+ `maxRows` of SNMP conceptual table. Default is `0` (no limit).
+ * `maxCalls` - stop iteration once this generator instance processed
+ `maxCalls` responses. Default is 0 (no limit).
+
+ Yields
+ ------
+ errorIndication : str
+ True value indicates SNMP engine error.
+ errorStatus : str
+ True value indicates SNMP PDU error.
+ errorIndex : int
+ Non-zero value refers to `varBinds[errorIndex-1]`
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables returned in SNMP response.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Notes
+ -----
+ The `nextCmd` generator will be exhausted on any of the following
+ conditions:
+
+ * SNMP engine error occurs thus `errorIndication` is `True`
+ * SNMP PDU `errorStatus` is reported as `True`
+ * SNMP :py:class:`~pysnmp.proto.rfc1905.EndOfMibView` values
+ (also known as *SNMP exception values*) are reported for all
+ MIB variables in `varBinds`
+ * *lexicographicMode* option is set to `False` and all
+ response MIB variables leave the scope of `varBinds`
+
+ At any moment a new sequence of `varBinds` could be send back into
+ running generator (supported since Python 2.6).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> g = nextCmd(SnmpEngine(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr')))
+ >>> next(g)
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
+ >>> g.send( [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets')) ] )
+ (None, 0, 0, [(ObjectName('1.3.6.1.2.1.2.2.1.10.1'), Counter32(284817787))])
+ """
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBindTable'] = varBindTable
+
+ lookupMib = options.get('lookupMib', True)
+ lexicographicMode = options.get('lexicographicMode', True)
+ ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False)
+ maxRows = options.get('maxRows', 0)
+ maxCalls = options.get('maxCalls', 0)
+
+ cbCtx = {}
+
+ vbProcessor = CommandGeneratorVarBinds()
+
+ cmdGen = AsyncCommandGenerator()
+
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ]
+
+ totalRows = totalCalls = 0
+
+ while True:
+ if varBinds:
+ cmdGen.nextCmd(snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ [ (x[0], Null()) for x in varBinds ],
+ (cbFun, cbCtx),
+ lookupMib)
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+
+ if ignoreNonIncreasingOid and errorIndication and \
+ isinstance(errorIndication, errind.OidNotIncreasing):
+ errorIndication = None
+
+ if errorIndication:
+ yield errorIndication, errorStatus, errorIndex, varBinds
+ return
+ elif errorStatus:
+ if errorStatus == 2:
+ # Hide SNMPv1 noSuchName error which leaks in here
+ # from SNMPv1 Agent through internal pysnmp proxy.
+ errorStatus = errorStatus.clone(0)
+ errorIndex = errorIndex.clone(0)
+ yield errorIndication, errorStatus, errorIndex, varBinds
+ return
+ else:
+ varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0]
+ for idx, varBind in enumerate(varBinds):
+ name, val = varBind
+ if not isinstance(val, Null):
+ if lexicographicMode or initialVars[idx].isPrefixOf(name):
+ break
+ else:
+ return
+
+ totalRows += 1
+ totalCalls += 1
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ initialVarBinds = ( yield errorIndication, errorStatus,
+ errorIndex, varBinds )
+
+ if initialVarBinds:
+ varBinds = initialVarBinds
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine,
+ varBinds) ]
+
+ if maxRows and totalRows >= maxRows or \
+ maxCalls and totalCalls >= maxCalls:
+ return
+
+def bulkCmd(snmpEngine, authData, transportTarget, contextData,
+ nonRepeaters, maxRepetitions, *varBinds, **options):
+ """Creates a generator to perform one or more SNMP GETBULK queries.
+
+ On each iteration, new SNMP GETBULK request is send
+ (:RFC:`1905#section-4.2.3`). The iterator blocks waiting for response
+ to arrive or error to occur.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName values.
+
+ nonRepeaters : int
+ One MIB variable is requested in response for the first
+ `nonRepeaters` MIB variables in request.
+
+ maxRepetitions : int
+ `maxRepetitions` MIB variables are requested in response for each
+ of the remaining MIB variables in the request (e.g. excluding
+ `nonRepeaters`). Remote SNMP engine may choose lesser value than
+ requested.
+
+ \*varBinds : :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ One or more class instances representing MIB variables to place
+ into SNMP request.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+ Default is `True`.
+ * `lexicographicMode` - stop iteration when all response MIB
+ variables leave the scope of initial MIB variables in
+ `varBinds`. Default is `True`.
+ * `ignoreNonIncreasingOid` - continue iteration even if response
+ MIB variables (OIDs) are not greater then request MIB variables.
+ Default is `False`.
+ * `maxRows` - stop iteration once this generator instance processed
+ `maxRows` of SNMP conceptual table. Default is `0` (no limit).
+ * `maxCalls` - stop iteration once this generator instance processed
+ `maxCalls` responses. Default is 0 (no limit).
+
+ Yields
+ ------
+ errorIndication : str
+ True value indicates SNMP engine error.
+ errorStatus : str
+ True value indicates SNMP PDU error.
+ errorIndex : int
+ Non-zero value refers to *varBinds[errorIndex-1]
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables returned in SNMP response.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Notes
+ -----
+ The `bulkCmd` generator will be exhausted on any of the following
+ conditions:
+
+ * SNMP engine error occurs thus `errorIndication` is `True`
+ * SNMP PDU `errorStatus` is reported as `True`
+ * SNMP :py:class:`~pysnmp.proto.rfc1905.EndOfMibView` values
+ (also known as *SNMP exception values*) are reported for all
+ MIB variables in `varBinds`
+ * *lexicographicMode* option is set to `False` and all
+ response MIB variables leave the scope of `varBinds`
+
+ At any moment a new sequence of `varBinds` could be send back into
+ running generator (supported since Python 2.6).
+
+ Setting `maxRepetitions` value to 15..50 might significantly improve
+ system performance, as many MIB variables get packed into a single
+ response message at once.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> g = bulkCmd(SnmpEngine(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... 0, 25,
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr')))
+ >>> next(g)
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
+ >>> g.send( [ ObjectType(ObjectIdentity('IF-MIB', 'ifInOctets')) ] )
+ (None, 0, 0, [(ObjectName('1.3.6.1.2.1.2.2.1.10.1'), Counter32(284817787))])
+ """
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBindTable'] = varBindTable
+
+ lookupMib = options.get('lookupMib', True)
+ lexicographicMode = options.get('lexicographicMode', True)
+ ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False)
+ maxRows = options.get('maxRows', 0)
+ maxCalls = options.get('maxCalls', 0)
+
+ cbCtx = {}
+
+ vbProcessor = CommandGeneratorVarBinds()
+
+ cmdGen = AsyncCommandGenerator()
+
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ]
+ nullVarBinds = [ False ] * len(initialVars)
+
+ totalRows = totalCalls = 0
+ stopFlag = False
+
+ while not stopFlag:
+ if maxRows and totalRows < maxRows:
+ maxRepetitions = min(maxRepetitions, maxRows-totalRows)
+
+ cmdGen.bulkCmd(snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ nonRepeaters, maxRepetitions,
+ [ (x[0], Null()) for x in varBinds ],
+ (cbFun, cbCtx),
+ lookupMib)
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+ varBindTable = cbCtx['varBindTable']
+
+ if ignoreNonIncreasingOid and errorIndication and \
+ isinstance(errorIndication, errind.OidNotIncreasing):
+ errorIndication = None
+
+ if errorIndication:
+ yield errorIndication, errorStatus, errorIndex, \
+ varBindTable and varBindTable[0] or []
+ if errorIndication != errind.requestTimedOut:
+ return
+ elif errorStatus:
+ if errorStatus == 2:
+ # Hide SNMPv1 noSuchName error which leaks in here
+ # from SNMPv1 Agent through internal pysnmp proxy.
+ errorStatus = errorStatus.clone(0)
+ errorIndex = errorIndex.clone(0)
+ yield errorIndication, errorStatus, errorIndex, \
+ varBindTable and varBindTable[0] or []
+ return
+ else:
+ for i in range(len(varBindTable)):
+ stopFlag = True
+ if len(varBindTable[i]) != len(initialVars):
+ varBindTable = i and varBindTable[:i-1] or []
+ break
+ for j in range(len(varBindTable[i])):
+ name, val = varBindTable[i][j]
+ if nullVarBinds[j]:
+ varBindTable[i][j] = name, endOfMibView
+ continue
+ stopFlag = False
+ if isinstance(val, Null):
+ nullVarBinds[j] = True
+ elif not lexicographicMode and \
+ not initialVars[j].isPrefixOf(name):
+ varBindTable[i][j] = name, endOfMibView
+ nullVarBinds[j] = True
+ if stopFlag:
+ varBindTable = i and varBindTable[:i-1] or []
+ break
+
+ totalRows += len(varBindTable)
+ totalCalls += 1
+
+ if maxRows and totalRows >= maxRows:
+ if totalRows > maxRows:
+ varBindTable = varBindTable[:-(totalRows-maxRows)]
+ stopFlag = True
+
+ if maxCalls and totalCalls >= maxCalls:
+ stopFlag = True
+
+ for varBinds in varBindTable:
+ initialVarBinds = ( yield errorIndication, errorStatus,
+ errorIndex, varBinds )
+
+ if initialVarBinds:
+ varBinds = initialVarBinds
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ]
diff --git a/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py b/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py
new file mode 100644
index 0000000..530c376
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/_sync/compat/cmdgen.py
@@ -0,0 +1,266 @@
+#
+# This is a Python 2.6- version of the same file at level up
+#
+from pysnmp.hlapi.asyncore.cmdgen import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.proto.rfc1905 import endOfMibView
+from pysnmp.proto.errind import *
+from pyasn1.type.univ import Null
+
+__all__ = ['getCmd', 'nextCmd', 'setCmd', 'bulkCmd', 'next']
+
+def next(iter):
+ return iter.next()
+
+def getCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ cmdGen = AsyncCommandGenerator()
+
+ if varBinds:
+ cmdGen.getCmd(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ varBinds,
+ (cbFun, cbCtx),
+ options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+ varBinds = cbCtx['varBinds']
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ yield errorIndication, errorStatus, errorIndex, varBinds
+
+def setCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ cmdGen = AsyncCommandGenerator()
+
+ while True:
+ cmdGen.setCmd(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ varBinds,
+ (cbFun, cbCtx),
+ options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ yield cbCtx['errorIndication'], \
+ cbCtx['errorStatus'], cbCtx['errorIndex'], \
+ cbCtx['varBinds']
+
+ if cbCtx['errorIndication'] != errind.requestTimedOut:
+ break
+
+def nextCmd(snmpEngine, authData, transportTarget, contextData,
+ *varBinds, **options):
+
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBindTable'] = varBindTable
+
+ lookupMib = options.get('lookupMib', True)
+ lexicographicMode = options.get('lexicographicMode', True)
+ ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False)
+ maxRows = options.get('maxRows', 0)
+ maxCalls = options.get('maxCalls', 0)
+
+ cbCtx = {}
+
+ vbProcessor = CommandGeneratorVarBinds()
+
+ cmdGen = AsyncCommandGenerator()
+
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ]
+
+ totalRows = totalCalls = 0
+
+ while True:
+ cmdGen.nextCmd(snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ [ (x[0], Null()) for x in varBinds ],
+ (cbFun, cbCtx),
+ lookupMib)
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+
+ if ignoreNonIncreasingOid and errorIndication and \
+ isinstance(errorIndication, errind.OidNotIncreasing):
+ errorIndication = None
+
+ if errorIndication:
+ yield errorIndication, errorStatus, errorIndex, varBinds
+ if errorIndication != errind.requestTimedOut:
+ return
+ elif errorStatus:
+ if errorStatus == 2:
+ # Hide SNMPv1 noSuchName error which leaks in here
+ # from SNMPv1 Agent through internal pysnmp proxy.
+ errorStatus = errorStatus.clone(0)
+ errorIndex = errorIndex.clone(0)
+ yield errorIndication, errorStatus, errorIndex, varBinds
+ return
+ else:
+ varBinds = cbCtx['varBindTable'] and cbCtx['varBindTable'][0]
+ for idx, varBind in enumerate(varBinds):
+ name, val = varBind
+ if not isinstance(val, Null):
+ if lexicographicMode or initialVars[idx].isPrefixOf(name):
+ break
+ else:
+ return
+
+ totalRows += 1
+ totalCalls += 1
+
+ yield errorIndication, errorStatus, errorIndex, varBinds
+
+ if maxRows and totalRows >= maxRows or \
+ maxCalls and totalCalls >= maxCalls:
+ return
+
+def bulkCmd(snmpEngine, authData, transportTarget, contextData,
+ nonRepeaters, maxRepetitions, *varBinds, **options):
+
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBindTable'] = varBindTable
+
+ lookupMib = options.get('lookupMib', True)
+ lexicographicMode = options.get('lexicographicMode', True)
+ ignoreNonIncreasingOid = options.get('ignoreNonIncreasingOid', False)
+ maxRows = options.get('maxRows', 0)
+ maxCalls = options.get('maxCalls', 0)
+
+ cbCtx = {}
+
+ vbProcessor = CommandGeneratorVarBinds()
+
+ cmdGen = AsyncCommandGenerator()
+
+ initialVars = [ x[0] for x in vbProcessor.makeVarBinds(snmpEngine, varBinds) ]
+ nullVarBinds = [ False ] * len(initialVars)
+
+ totalRows = totalCalls = 0
+ stopFlag = False
+
+ while not stopFlag:
+ if maxRows and totalRows < maxRows:
+ maxRepetitions = min(maxRepetitions, maxRows-totalRows)
+
+ cmdGen.bulkCmd(snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ nonRepeaters, maxRepetitions,
+ [ (x[0], Null()) for x in varBinds ],
+ (cbFun, cbCtx),
+ lookupMib)
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx['errorIndication']
+ errorStatus = cbCtx['errorStatus']
+ errorIndex = cbCtx['errorIndex']
+ varBindTable = cbCtx['varBindTable']
+
+ if ignoreNonIncreasingOid and errorIndication and \
+ isinstance(errorIndication, errind.OidNotIncreasing):
+ errorIndication = None
+
+ if errorIndication:
+ yield errorIndication, errorStatus, errorIndex, \
+ varBindTable and varBindTable[0] or []
+ if errorIndication != errind.requestTimedOut:
+ return
+ elif errorStatus:
+ if errorStatus == 2:
+ # Hide SNMPv1 noSuchName error which leaks in here
+ # from SNMPv1 Agent through internal pysnmp proxy.
+ errorStatus = errorStatus.clone(0)
+ errorIndex = errorIndex.clone(0)
+ yield errorIndication, errorStatus, errorIndex, \
+ varBindTable and varBindTable[0] or []
+ return
+ else:
+ for i in range(len(varBindTable)):
+ stopFlag = True
+ if len(varBindTable[i]) != len(initialVars):
+ varBindTable = i and varBindTable[:i-1] or []
+ break
+ for j in range(len(varBindTable[i])):
+ name, val = varBindTable[i][j]
+ if nullVarBinds[j]:
+ varBindTable[i][j] = name, endOfMibView
+ continue
+ stopFlag = False
+ if isinstance(val, Null):
+ nullVarBinds[j] = True
+ elif not lexicographicMode and \
+ not initialVars[j].isPrefixOf(name):
+ varBindTable[i][j] = name, endOfMibView
+ nullVarBinds[j] = True
+ if stopFlag:
+ varBindTable = i and varBindTable[:i-1] or []
+ break
+
+ totalRows += len(varBindTable)
+ totalCalls += 1
+
+ if maxRows and totalRows >= maxRows:
+ if totalRows > maxRows:
+ varBindTable = varBindTable[:-(totalRows-maxRows)]
+ stopFlag = True
+
+ if maxCalls and totalCalls >= maxCalls:
+ stopFlag = True
+
+ for varBinds in varBindTable:
+ yield errorIndication, errorStatus, errorIndex, varBinds
diff --git a/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py b/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py
new file mode 100644
index 0000000..420b3b6
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/_sync/compat/ntforg.py
@@ -0,0 +1,52 @@
+#
+# This is a Python 2.6- version of the same file at level up
+#
+from pysnmp.hlapi.asyncore.ntforg import *
+
+__all__ = ['sendNotification', 'next']
+
+def next(iter):
+ return iter.next()
+
+#
+# Synchronous one-liner SNMP Notification Originator application
+#
+
+def sendNotification(snmpEngine, authData, transportTarget, contextData,
+ notifyType, varBinds, **options):
+
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ ntfOrg = AsyncNotificationOriginator()
+
+ if varBinds:
+ ntfOrg.sendNotification(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ notifyType,
+ varBinds,
+ (cbFun, cbCtx),
+ options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx.get('errorIndication')
+ errorStatus = cbCtx.get('errorStatus')
+ errorIndex = cbCtx.get('errorIndex')
+ varBinds = cbCtx.get('varBinds', [])
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ yield errorIndication, errorStatus, errorIndex, varBinds
diff --git a/pysnmp/hlapi/asyncore/_sync/ntforg.py b/pysnmp/hlapi/asyncore/_sync/ntforg.py
new file mode 100644
index 0000000..bec88cf
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/_sync/ntforg.py
@@ -0,0 +1,124 @@
+from pysnmp.hlapi.asyncore.ntforg import *
+
+__all__ = ['sendNotification']
+
+def sendNotification(snmpEngine, authData, transportTarget, contextData,
+ notifyType, varBinds, **options):
+ """Creates a generator to send one or more SNMP notifications.
+
+ On each iteration, new SNMP TRAP or INFORM notification is send
+ (:RFC:`1905#section-4,2,6`). The iterator blocks waiting for
+ INFORM acknowlegement to arrive or error to occur.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName values.
+
+ notifyType : str
+ Indicates type of notification to be sent. Recognized literal
+ values are *trap* or *inform*.
+
+ varBinds: tuple
+ Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class instance
+ representing a minimum sequence of MIB variables required for
+ particular notification type.
+ Alternatively, a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ objects could be passed instead. In the latter case it is up to
+ the user to ensure proper Notification PDU contents.
+
+ Other Parameters
+ ----------------
+ \*\*options :
+ Request options:
+
+ * `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Yields
+ ------
+ errorIndication : str
+ True value indicates SNMP engine error.
+ errorStatus : str
+ True value indicates SNMP PDU error.
+ errorIndex : int
+ Non-zero value refers to `varBinds[errorIndex-1]`
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables returned in SNMP response.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Notes
+ -----
+ The `sendNotification` generator will be exhausted immidiately unless
+ an instance of :py:class:`~pysnmp.smi.rfc1902.NotificationType` class
+ or a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` `varBinds`
+ are send back into running generator (supported since Python 2.6).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.ntforg import *
+ >>> g = sendNotification(SnmpEngine(),
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 162)),
+ ... ContextData(),
+ ... 'trap',
+ ... NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
+ >>> next(g)
+ (None, 0, 0, [])
+ >>>
+
+ """
+ def cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ cbCtx['errorIndication'] = errorIndication
+ cbCtx['errorStatus'] = errorStatus
+ cbCtx['errorIndex'] = errorIndex
+ cbCtx['varBinds'] = varBinds
+
+ cbCtx = {}
+
+ ntfOrg = AsyncNotificationOriginator()
+
+ while True:
+ if varBinds:
+ ntfOrg.sendNotification(
+ snmpEngine,
+ authData,
+ transportTarget,
+ contextData,
+ notifyType,
+ varBinds,
+ cbInfo=(cbFun, cbCtx),
+ lookupMib=options.get('lookupMib', True)
+ )
+
+ snmpEngine.transportDispatcher.runDispatcher()
+
+ errorIndication = cbCtx.get('errorIndication')
+ errorStatus = cbCtx.get('errorStatus')
+ errorIndex = cbCtx.get('errorIndex')
+ varBinds = cbCtx.get('varBinds', [])
+ else:
+ errorIndication = errorStatus = errorIndex = None
+ varBinds = []
+
+ varBinds = ( yield errorIndication, errorStatus, errorIndex, varBinds )
+
+ if not varBinds:
+ break
diff --git a/pysnmp/hlapi/asyncore/cmdgen.py b/pysnmp/hlapi/asyncore/cmdgen.py
new file mode 100644
index 0000000..850dade
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/cmdgen.py
@@ -0,0 +1,529 @@
+from sys import version_info
+from pysnmp.entity import config
+from pysnmp.entity.rfc3413 import cmdgen
+from pysnmp.smi.rfc1902 import *
+from pysnmp.hlapi.auth import *
+from pysnmp.hlapi.context import *
+from pysnmp.hlapi.lcd import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.hlapi.asyncore.transport import *
+from pysnmp.proto import rfc1905, errind
+from pyasn1.type import univ, base
+
+__all__ = ['AsyncCommandGenerator']
+
+class AsyncCommandGenerator:
+ """Creates asyncore-based SNMP Command Generator object.
+
+ This is a high-level wrapper around pure Command Generator
+ impementation that aims at simplyfing
+ :py:class:`pysnmp.entity.engine.SnmpEngine`'s Local Configuration
+ Datastore (:RFC:`2271#section-3.4.2`) management. Typically,
+ users instantiate `AsyncCommandGenerator` and call its
+ commmand-specific methods passing them canned Security,
+ Transport and SNMP Context parameters along with
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` object carrying
+ MIB variables to include with SNMP request. `AsyncCommandGenerator`
+ will manage LCD by applying user-supplied configuratoin parameters
+ and running requested operation.
+
+ See :RFC:`3413#section-3.1` for more information on SNMP
+ Command Generator purpose, design and supported operations.
+
+ """
+ vbProcessor = CommandGeneratorVarBinds()
+ lcd = CommandGeneratorLcdConfigurator()
+
+ def getCmd(self, snmpEngine, authData, transportTarget, contextData,
+ varBinds, cbInfo, lookupMib=True):
+ """Performs SNMP GET query.
+
+ Based on passed parameters, prepares SNMP GET packet
+ (:RFC:`1905#section-4.2.1`) and schedules its transmission by
+ I/O framework at a later point of time.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer
+ address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName
+ values.
+
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables to place into SNMP request.
+
+ cbInfo : tuple
+
+ * `cbFun` - user-supplied callable that is invoked to pass
+ SNMP response data or error to user at a later point of time.
+ * `cbCtx` - user-supplied object passing additional parameters
+ to/from `cbFun`. Default is `None`.
+
+ Other Parameters
+ ----------------
+ lookupMib : bool
+ `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Notes
+ -----
+ User-supplied `cbFun` callable must have the following call
+ signature:
+
+ * snmpEngine (:py:class:`~pysnmp.entity.engine.SnmpEngine`):
+ Class instance representing SNMP engine.
+ * sendRequestHandle (int): Unique request identifier. Can be used
+ for matching multiple ongoing requests with received responses.
+ * errorIndication (str): True value indicates SNMP engine error.
+ * errorStatus (str): True value indicates SNMP PDU error.
+ * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
+ * varBinds (tuple): A sequence of
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ representing MIB variables returned in SNMP response in exactly
+ the same order as `varBinds` in request.
+ * `cbCtx` : Original user-supplied object.
+
+ Returns
+ -------
+ sendRequestHandle : int
+ Unique request identifier. Can be used for matching received
+ responses with ongoing requests.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
+ ... print(errorIndication, errorStatus, errorIndex, varBinds)
+ >>>
+ >>> snmpEngine = SnmpEngine()
+ >>> g = AsyncCommandGenerator()
+ >>> g.getCmd(snmpEngine,
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysDescr', 0)),
+ ... (cbFun, None))
+ >>> snmpEngine.transportDispatcher.runDispatcher()
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))])
+ >>>
+
+ """
+ def __cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ lookupMib, cbFun, cbCtx = cbCtx
+ return cbFun(
+ snmpEngine,
+ sendRequestHandle,
+ errorIndication,
+ errorStatus,
+ errorIndex,
+ self.vbProcessor.unmakeVarBinds(
+ snmpEngine, varBinds, lookupMib
+ ),
+ cbCtx
+ )
+
+ (cbFun, cbCtx) = cbInfo
+ addrName, paramsName = self.lcd.configure(
+ snmpEngine, authData, transportTarget
+ )
+
+ return cmdgen.GetCommandGenerator().sendVarBinds(
+ snmpEngine,
+ addrName,
+ contextData.contextEngineId,
+ contextData.contextName,
+ self.vbProcessor.makeVarBinds(snmpEngine, varBinds),
+ __cbFun,
+ (lookupMib, cbFun, cbCtx)
+ )
+
+ def setCmd(self, snmpEngine, authData, transportTarget, contextData,
+ varBinds, cbInfo, lookupMib=True):
+ """Performs SNMP SET query.
+
+ Based on passed parameters, prepares SNMP SET packet
+ (:RFC:`1905#section-4.2.5`) and schedules its transmission by
+ I/O framework at a later point of time.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer
+ address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName
+ values.
+
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables to place into SNMP request.
+
+ cbInfo : tuple
+
+ * `cbFun` - user-supplied callable that is invoked to pass
+ SNMP response data or error to user at a later point of time.
+ * `cbCtx` - user-supplied object passing additional parameters
+ to/from `cbFun`. Default is `None`.
+
+ Other Parameters
+ ----------------
+ lookupMib : bool
+ `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Notes
+ -----
+ User-supplied `cbFun` callable must have the following call
+ signature:
+
+ * snmpEngine (:py:class:`~pysnmp.entity.engine.SnmpEngine`):
+ Class instance representing SNMP engine.
+ * sendRequestHandle (int): Unique request identifier. Can be used
+ for matching multiple ongoing requests with received responses.
+ * errorIndication (str): True value indicates SNMP engine error.
+ * errorStatus (str): True value indicates SNMP PDU error.
+ * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
+ * varBinds (tuple): A sequence of
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ representing MIB variables returned in SNMP response in exactly
+ the same order as `varBinds` in request.
+ * `cbCtx` : Original user-supplied object.
+
+ Returns
+ -------
+ sendRequestHandle : int
+ Unique request identifier. Can be used for matching received
+ responses with ongoing requests.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
+ ... print(errorIndication, errorStatus, errorIndex, varBinds)
+ >>>
+ >>> snmpEngine = SnmpEngine()
+ >>> g = AsyncCommandGenerator()
+ >>> g.setCmd(snmpEngine,
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'sysContact', 0), 'info@snmplabs.com'),
+ ... (cbFun, None))
+ >>> snmpEngine.transportDispatcher.runDispatcher()
+ (None, 0, 0, [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.4.0')), DisplayString('info@snmplabs.com'))])
+ >>>
+
+ """
+ def __cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBinds, cbCtx):
+ lookupMib, cbFun, cbCtx = cbCtx
+ return cbFun(
+ snmpEngine,
+ sendRequestHandle,
+ errorIndication,
+ errorStatus,
+ errorIndex,
+ self.vbProcessor.unmakeVarBinds(
+ snmpEngine, varBinds, lookupMib
+ ),
+ cbCtx
+ )
+
+ (cbFun, cbCtx) = cbInfo
+ addrName, paramsName = self.lcd.configure(
+ snmpEngine, authData, transportTarget
+ )
+
+ return cmdgen.SetCommandGenerator().sendVarBinds(
+ snmpEngine,
+ addrName,
+ contextData.contextEngineId,
+ contextData.contextName,
+ self.vbProcessor.makeVarBinds(snmpEngine, varBinds),
+ __cbFun,
+ (lookupMib, cbFun, cbCtx)
+ )
+
+ def nextCmd(self, snmpEngine, authData, transportTarget, contextData,
+ varBinds, cbInfo, lookupMib=True):
+ """Performs SNMP GETNEXT query.
+
+ Based on passed parameters, prepares SNMP GETNEXT packet
+ (:RFC:`1905#section-4.2.2`) and schedules its transmission by
+ I/O framework at a later point of time.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer
+ address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName
+ values.
+
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables to place into SNMP request.
+
+ cbInfo : tuple
+
+ * `cbFun` - user-supplied callable that is invoked to pass
+ SNMP response data or error to user at a later point of time.
+ * `cbCtx` - user-supplied object passing additional parameters
+ to/from `cbFun`. Default is `None`.
+
+ Other Parameters
+ ----------------
+ lookupMib : bool
+ `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Notes
+ -----
+ User-supplied `cbFun` callable must have the following call
+ signature:
+
+ * snmpEngine (:py:class:`~pysnmp.entity.engine.SnmpEngine`):
+ Class instance representing SNMP engine.
+ * sendRequestHandle (int): Unique request identifier. Can be used
+ for matching multiple ongoing requests with received responses.
+ * errorIndication (str): True value indicates SNMP engine error.
+ * errorStatus (str): True value indicates SNMP PDU error.
+ * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
+ * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ representing a table of MIB variables returned in SNMP response.
+ Inner sequences represent table rows and ordered exactly the same
+ as `varBinds` in request. Response to GETNEXT always contain a
+ single row.
+ * `cbCtx` : Original user-supplied object.
+
+ Returns
+ -------
+ sendRequestHandle : int
+ Unique request identifier. Can be used for matching received
+ responses with ongoing requests.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
+ ... print(errorIndication, errorStatus, errorIndex, varBinds)
+ >>>
+ >>> snmpEngine = SnmpEngine()
+ >>> g = AsyncCommandGenerator()
+ >>> g.nextCmd(snmpEngine,
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
+ ... (cbFun, None))
+ >>> snmpEngine.transportDispatcher.runDispatcher()
+ (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m'))] ])
+ >>>
+
+ """
+ def __cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ lookupMib, cbFun, cbCtx = cbCtx
+ return cbFun(
+ snmpEngine,
+ sendRequestHandle,
+ errorIndication,
+ errorStatus,
+ errorIndex,
+ [ self.vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ],
+ cbCtx
+ )
+
+ (cbFun, cbCtx) = cbInfo
+ addrName, paramsName = self.lcd.configure(
+ snmpEngine, authData, transportTarget
+ )
+ return cmdgen.NextCommandGenerator().sendVarBinds(
+ snmpEngine,
+ addrName,
+ contextData.contextEngineId, contextData.contextName,
+ self.vbProcessor.makeVarBinds(snmpEngine, varBinds),
+ __cbFun,
+ (lookupMib, cbFun, cbCtx)
+ )
+
+ def bulkCmd(self, snmpEngine, authData, transportTarget, contextData,
+ nonRepeaters, maxRepetitions, varBinds, cbInfo,
+ lookupMib=True):
+ """Performs SNMP GETBULK query.
+
+ Based on passed parameters, prepares SNMP GETBULK packet
+ (:RFC:`1905#section-4.2.3`) and schedules its transmission by
+ I/O framework at a later point of time.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer
+ address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName
+ values.
+
+ nonRepeaters : int
+ One MIB variable is requested in response for the first
+ `nonRepeaters` MIB variables in request.
+
+ maxRepetitions : int
+ `maxRepetitions` MIB variables are requested in response for each
+ of the remaining MIB variables in the request (e.g. excluding
+ `nonRepeaters`). Remote SNMP engine may choose lesser value than
+ requested.
+
+ varBinds : tuple
+ A sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType` class
+ instances representing MIB variables to place into SNMP request.
+
+ cbInfo : tuple
+
+ * `cbFun` - user-supplied callable that is invoked to pass
+ SNMP response data or error to user at a later point of time.
+ * `cbCtx` - user-supplied object passing additional parameters
+ to/from `cbFun`. Default is `None`.
+
+ Other Parameters
+ ----------------
+ lookupMib : bool
+ `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Notes
+ -----
+ User-supplied `cbFun` callable must have the following call
+ signature:
+
+ * snmpEngine (:py:class:`~pysnmp.entity.engine.SnmpEngine`):
+ Class instance representing SNMP engine.
+ * sendRequestHandle (int): Unique request identifier. Can be used
+ for matching multiple ongoing requests with received responses.
+ * errorIndication (str): True value indicates SNMP engine error.
+ * errorStatus (str): True value indicates SNMP PDU error.
+ * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
+ * varBinds (tuple): A sequence of sequences (e.g. 2-D array) of
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ representing a table of MIB variables returned in SNMP response.
+ Inner sequences represent table rows and ordered exactly the same
+ as `varBinds` in request. Number of rows might be less or equal
+ to `maxRepetitions` value in request.
+ * `cbCtx` : Original user-supplied object.
+
+ Returns
+ -------
+ sendRequestHandle : int
+ Unique request identifier. Can be used for matching received
+ responses with ongoing requests.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.cmdgen import *
+ >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
+ ... print(errorIndication, errorStatus, errorIndex, varBinds)
+ >>>
+ >>> snmpEngine = SnmpEngine()
+ >>> g = AsyncCommandGenerator()
+ >>> g.bulkCmd(snmpEngine,
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 161)),
+ ... ContextData(),
+ ... 0, 2,
+ ... ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
+ ... (cbFun, None))
+ >>> snmpEngine.transportDispatcher.runDispatcher()
+ (None, 0, 0, [ [ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.1.0')), DisplayString('SunOS zeus.snmplabs.com 4.1.3_U1 1 sun4m')), ObjectType(ObjectIdentity(ObjectName('1.3.6.1.2.1.1.2.0')), ObjectIdentifier('1.3.6.1.4.1.424242.1.1')] ])
+ >>>
+
+ """
+ def __cbFun(snmpEngine, sendRequestHandle,
+ errorIndication, errorStatus, errorIndex,
+ varBindTable, cbCtx):
+ lookupMib, cbFun, cbCtx = cbCtx
+ return cbFun(
+ snmpEngine,
+ sendRequestHandle,
+ errorIndication,
+ errorStatus,
+ errorIndex,
+ [ self.vbProcessor.unmakeVarBinds(snmpEngine, varBindTableRow, lookupMib) for varBindTableRow in varBindTable ],
+ cbCtx
+ )
+
+ (cbFun, cbCtx) = cbInfo
+ addrName, paramsName = self.lcd.configure(
+ snmpEngine, authData, transportTarget
+ )
+ return cmdgen.BulkCommandGenerator().sendVarBinds(
+ snmpEngine,
+ addrName,
+ contextData.contextEngineId,
+ contextData.contextName,
+ nonRepeaters, maxRepetitions,
+ self.vbProcessor.makeVarBinds(snmpEngine, varBinds),
+ __cbFun,
+ (lookupMib, cbFun, cbCtx)
+ )
diff --git a/pysnmp/hlapi/asyncore/ntforg.py b/pysnmp/hlapi/asyncore/ntforg.py
new file mode 100644
index 0000000..6536b9c
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/ntforg.py
@@ -0,0 +1,169 @@
+from pysnmp.entity import engine, config
+from pysnmp.smi.rfc1902 import *
+from pysnmp.entity.rfc3413 import ntforg, context
+from pysnmp.hlapi.auth import *
+from pysnmp.hlapi.context import *
+from pysnmp.hlapi.lcd import *
+from pysnmp.hlapi.varbinds import *
+from pysnmp.hlapi.asyncore.transport import *
+from pysnmp.hlapi.asyncore import cmdgen
+from pysnmp import error
+
+__all__ = ['AsyncNotificationOriginator']
+
+class AsyncNotificationOriginator:
+ """Creates asyncore-based SNMP Notification Originator object.
+
+ This is a high-level wrapper around pure Notification Originator
+ impementation that aims at simplyfing
+ :py:class:`pysnmp.entity.engine.SnmpEngine`'s Local Configuration
+ Datastore (:RFC:`2271#section-3.4.2`) management. Typically,
+ users instantiate `AsyncNotificationOriginator` and call its
+ commmand-specific methods passing them canned Security,
+ Transport and SNMP Context parameters along with
+ :py:class:`~pysnmp.smi.rfc1902.NotificationType` object carrying
+ MIB variables to include with Notification. `AsyncNotificationOriginator`
+ will manage LCD by applying user-supplied configuratoin parameters
+ and running requested operation.
+
+ See :RFC:`3413#section-3.2` for more information on SNMP
+ Notification Originator purpose, design and supported operations.
+
+ """
+ vbProcessor = NotificationOriginatorVarBinds()
+ lcd = NotificationOriginatorLcdConfigurator()
+
+ def sendNotification(self, snmpEngine,
+ authData, transportTarget, contextData,
+ notifyType,
+ varBinds,
+ cbInfo=(None, None),
+ lookupMib=False):
+ """Send SNMP notification.
+
+ Based on passed parameters, prepares SNMP TRAP or INFORM
+ notification (:RFC:`1905#section-4.2.6`) and schedules its
+ transmission by I/O framework at a later point of time.
+
+ Parameters
+ ----------
+ snmpEngine : :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ Class instance representing SNMP engine.
+
+ authData : :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.CommunityData` or :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.UsmUserData`
+ Class instance representing SNMP credentials.
+
+ transportTarget : :py:class:`~pysnmp.entity.rfc3413.oneliner.target.UdpTransportTarget` or :py:class:`~pysnmp.entity.rfc3413.oneliner.target.Udp6TransportTarget`
+ Class instance representing transport type along with SNMP peer
+ address.
+
+ contextData : :py:class:`~pysnmp.entity.rfc3413.oneliner.ctx.ContextData`
+ Class instance representing SNMP ContextEngineId and ContextName
+ values.
+
+ notifyType : str
+ Indicates type of notification to be sent. Recognized literal
+ values are *trap* or *inform*.
+
+ varBinds: tuple
+ Single :py:class:`~pysnmp.smi.rfc1902.NotificationType` class
+ instance representing a minimum sequence of MIB variables
+ required for particular notification type. Alternatively,
+ a sequence of :py:class:`~pysnmp.smi.rfc1902.ObjectType`
+ objects could be passed instead. In the latter case it is up to
+ the user to ensure proper Notification PDU contents.
+
+ cbInfo : tuple
+
+ * `cbFun` - user-supplied callable that is invoked to pass
+ SNMP response to *INFORM* notification or error to user at
+ a later point of time. The `cbFun` callable is never invoked
+ for *TRAP* notifications.
+ * `cbCtx` - user-supplied object passing additional parameters
+ to/from `cbFun`. Default is `None`.
+
+ Other Parameters
+ ----------------
+ lookupMib : bool
+ `lookupMib` - load MIB and resolve response MIB variables at
+ the cost of slightly reduced performance. Default is `True`.
+
+ Notes
+ -----
+ User-supplied `cbFun` callable must have the following call
+ signature:
+
+ * snmpEngine (:py:class:`~pysnmp.entity.engine.SnmpEngine`):
+ Class instance representing SNMP engine.
+ * sendRequestHandle (int): Unique request identifier. Can be used
+ for matching multiple ongoing *INFORM* notifications with received
+ responses.
+ * errorIndication (str): True value indicates SNMP engine error.
+ * errorStatus (str): True value indicates SNMP PDU error.
+ * errorIndex (int): Non-zero value refers to `varBinds[errorIndex-1]`
+ * varBinds (tuple): A sequence of
+ :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
+ representing MIB variables returned in SNMP response in exactly
+ the same order as `varBinds` in request.
+ * `cbCtx` : Original user-supplied object.
+
+ Returns
+ -------
+ sendRequestHandle : int
+ Unique request identifier. Can be used for matching received
+ responses with ongoing *INFORM* requests. Returns `None` for
+ *TRAP* notifications.
+
+ Raises
+ ------
+ PySnmpError
+ Or its derivative indicating that an error occurred while
+ performing SNMP operation.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.ntforg import *
+ >>>
+ >>> snmpEngine = SnmpEngine()
+ >>> n = AsyncNotificationOriginator()
+ >>> n.sendNotification(
+ ... snmpEngine,
+ ... CommunityData('public'),
+ ... UdpTransportTarget(('demo.snmplabs.com', 162)),
+ ... ContextData(),
+ ... 'trap',
+ ... NotificationType(ObjectIdentity('SNMPv2-MIB', 'coldStart')),
+ ... )
+ >>> snmpEngine.transportDispatcher.runDispatcher()
+ >>>
+
+ """
+ def __cbFun(snmpEngine, sendRequestHandle, errorIndication,
+ errorStatus, errorIndex, varBinds, cbCtx):
+ lookupMib, cbFun, cbCtx = cbCtx
+ return cbFun and cbFun(
+ snmpEngine,
+ sendRequestHandle,
+ errorIndication,
+ errorStatus, errorIndex,
+ self.vbProcessor.unmakeVarBinds(
+ snmpEngine, varBinds, lookupMib
+ ),
+ cbCtx
+ )
+
+ cbFun, cbCtx = cbInfo
+
+ # Create matching transport tags if not given by user
+ if not transportTarget.tagList:
+ transportTarget.tagList = str(
+ hash((authData.securityName, transportTarget.transportAddr))
+ )
+ if isinstance(authData, CommunityData) and not authData.tag:
+ authData.tag = transportTarget.tagList.split()[0]
+
+ notifyName = self.lcd.configure(
+ snmpEngine, authData, transportTarget, notifyType
+ )
+
+ return ntforg.NotificationOriginator().sendVarBinds(snmpEngine, notifyName, contextData.contextEngineId, contextData.contextName, self.vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun, (lookupMib, cbFun, cbCtx))
diff --git a/pysnmp/hlapi/asyncore/transport.py b/pysnmp/hlapi/asyncore/transport.py
new file mode 100644
index 0000000..f77f575
--- /dev/null
+++ b/pysnmp/hlapi/asyncore/transport.py
@@ -0,0 +1,150 @@
+import socket, sys
+from pysnmp.carrier.asyncore.dgram import udp, udp6, unix
+from pysnmp import error
+from pyasn1.compat.octets import null
+
+__all__ = ['UnixTransportTarget', 'Udp6TransportTarget', 'UdpTransportTarget']
+
+class _AbstractTransportTarget:
+ transportDomain = None
+ protoTransport = NotImplementedError
+ def __init__(self, transportAddr, timeout=1, retries=5, tagList=null):
+ self.transportAddr = self._resolveAddr(transportAddr)
+ self.timeout = timeout
+ self.retries = retries
+ self.tagList = tagList
+ self.iface = None
+
+ def __repr__(self):
+ return '%s(%r, timeout=%r, retries=%r, tagList=%r)' % (
+ self.__class__.__name__, self.transportAddr,
+ self.timeout, self.retries, self.tagList
+ )
+
+ def getTransportInfo(self):
+ return self.transportDomain, self.transportAddr
+
+ def setLocalAddress(self, iface):
+ self.iface = iface
+ return self
+
+ def openClientMode(self):
+ self.transport = self.protoTransport().openClientMode(self.iface)
+ return self.transport
+
+ def verifyDispatcherCompatibility(self, snmpEngine):
+ if not self.protoTransport.isCompatibleWithDispatcher(snmpEngine.transportDispatcher):
+ raise error.PySnmpError('Transport %r is not compatible with dispatcher %r' % (self.protoTransport, snmpEngine.transportDispatcher))
+
+ def _resolveAddr(self, transportAddr): raise NotImplementedError()
+
+class UdpTransportTarget(_AbstractTransportTarget):
+ """Creates UDP/IPv4 configuration entry and initialize socket API if needed.
+
+ This object can be used by
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator`
+ and their derevatives for adding new entries to Local Configuration
+ Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ class instance.
+
+ See :RFC:`1906#section-3` for more information on the UDP transport mapping.
+
+ Parameters
+ ----------
+ transportAddr : tuple
+ Indicates remote address in Python :py:mod:`socket` module format
+ which is a tuple of FQDN, port where FQDN is a string representing
+ either hostname or IPv4 address in quad-dotted form, port is an
+ integer.
+ timeout : int
+ Response timeout in seconds.
+ retries : int
+ Maximum number of request retries, 0 retries means just a single
+ request.
+ tagList : str
+ Arbitrary string that contains a list of tag values which are used
+ to select target addresses for a particular operation
+ (:RFC:`3413#section-4.1.4`).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.target import UdpTransportTarget
+ >>> UdpTransportTarget(('demo.snmplabs.com', 161))
+ UdpTransportTarget(('195.218.195.228', 161), timeout=1, retries=5, tagList='')
+ >>>
+
+ """
+ transportDomain = udp.domainName
+ protoTransport = udp.UdpSocketTransport
+ def _resolveAddr(self, transportAddr):
+ try:
+ return socket.getaddrinfo(transportAddr[0],
+ transportAddr[1],
+ socket.AF_INET,
+ socket.SOCK_DGRAM,
+ socket.IPPROTO_UDP)[0][4][:2]
+ except socket.gaierror:
+ raise error.PySnmpError('Bad IPv4/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1]))
+
+class Udp6TransportTarget(_AbstractTransportTarget):
+ """Creates UDP/IPv6 configuration entry and initialize socket API if needed.
+
+ This object can be used by
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator`
+ and their derevatives for adding new entries to Local Configuration
+ Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ class instance.
+
+ See :RFC:`1906#section-3`, :RFC:`2851#section-4` for more information
+ on the UDP and IPv6 transport mapping.
+
+ Parameters
+ ----------
+ transportAddr : tuple
+ Indicates remote address in Python :py:mod:`socket` module format
+ which is a tuple of FQDN, port where FQDN is a string representing
+ either hostname or IPv6 address in one of three conventional forms
+ (:RFC:`1924#section-3`), port is an integer.
+ timeout : int
+ Response timeout in seconds.
+ retries : int
+ Maximum number of request retries, 0 retries means just a single
+ request.
+ tagList : str
+ Arbitrary string that contains a list of tag values which are used
+ to select target addresses for a particular operation
+ (:RFC:`3413#section-4.1.4`).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.target import Udp6TransportTarget
+ >>> Udp6TransportTarget(('google.com', 161))
+ Udp6TransportTarget(('2a00:1450:4014:80a::100e', 161), timeout=1, retries=5, tagList='')
+ >>> Udp6TransportTarget(('FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', 161))
+ Udp6TransportTarget(('fedc:ba98:7654:3210:fedc:ba98:7654:3210', 161), timeout=1, retries=5, tagList='')
+ >>> Udp6TransportTarget(('1080:0:0:0:8:800:200C:417A', 161))
+ Udp6TransportTarget(('1080::8:800:200c:417a', 161), timeout=1, retries=5, tagList='')
+ >>> Udp6TransportTarget(('::0', 161))
+ Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='')
+ >>> Udp6TransportTarget(('::', 161))
+ Udp6TransportTarget(('::', 161), timeout=1, retries=5, tagList='')
+ >>>
+
+ """
+ transportDomain = udp6.domainName
+ protoTransport = udp6.Udp6SocketTransport
+ def _resolveAddr(self, transportAddr):
+ try:
+ return socket.getaddrinfo(transportAddr[0],
+ transportAddr[1],
+ socket.AF_INET6,
+ socket.SOCK_DGRAM,
+ socket.IPPROTO_UDP)[0][4][:2]
+ except socket.gaierror:
+ raise error.PySnmpError('Bad IPv6/UDP transport address %s: %s' % ('@'.join([ str(x) for x in transportAddr ]), sys.exc_info()[1]))
+
+class UnixTransportTarget(_AbstractTransportTarget):
+ transportDomain = unix.domainName
+ protoTransport = unix.UnixSocketTransport
diff --git a/pysnmp/hlapi/auth.py b/pysnmp/hlapi/auth.py
new file mode 100644
index 0000000..5108a21
--- /dev/null
+++ b/pysnmp/hlapi/auth.py
@@ -0,0 +1,278 @@
+from pysnmp.entity import config
+from pysnmp import error
+from pyasn1.compat.octets import null
+
+__all__ = ['CommunityData', 'UsmUserData',
+ 'usm3DESEDEPrivProtocol', 'usmAesCfb128Protocol',
+ 'usmAesCfb192Protocol', 'usmAesCfb256Protocol',
+ 'usmDESPrivProtocol', 'usmHMACMD5AuthProtocol',
+ 'usmHMACSHAAuthProtocol', 'usmNoAuthProtocol',
+ 'usmNoPrivProtocol']
+
+class CommunityData:
+ """Creates SNMP v1/v2c configuration entry.
+
+ This object can be used by
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator`
+ and their derivatives for adding new entries to Local Configuration
+ Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ class instance.
+
+ See :RFC:`2576#section-5.3` for more information on the
+ *SNMP-COMMUNITY-MIB::snmpCommunityTable*.
+
+ Parameters
+ ----------
+ communityIndex : str
+ Unique index value of a row in snmpCommunityTable. If it is the
+ only positional parameter, it is taken as *communityName*.
+ communityName : str
+ SNMP v1/v2c community string.
+ mpModel : int
+ SNMP version - 0 for SNMPv1 and 1 for SNMPv2c.
+ contextEngineId : str
+ Indicates the location of the context in which management
+ information is accessed when using the community string
+ specified by the above communityName.
+ contextName : str
+ The context in which management information is accessed when
+ using the above communityName.
+ tag : str
+ Arbitrary string that specifies a set of transport endpoints
+ to which a notification may be sent using communityName above
+ (see also :RFC:`3413#section-4.1.4`).
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.auth import CommunityData
+ >>> CommunityData('public')
+ CommunityData(communityIndex='s1410706889', communityName=<COMMUNITY>, mpModel=1, contextEngineId=None, contextName='', tag='')
+ >>> CommunityData('public', 'public')
+ CommunityData(communityIndex='public', communityName=<COMMUNITY>, mpModel=1, contextEngineId=None, contextName='', tag='')
+ >>>
+
+ """
+ mpModel = 1 # Default is SMIv2
+ securityModel = mpModel + 1
+ securityLevel = 'noAuthNoPriv'
+ contextName = null
+ tag = null
+ def __init__(self, communityIndex, communityName=None, mpModel=None,
+ contextEngineId=None, contextName=None, tag=None,
+ securityName=None):
+ if mpModel is not None:
+ self.mpModel = mpModel
+ self.securityModel = mpModel + 1
+ self.contextEngineId = contextEngineId
+ if contextName is not None:
+ self.contextName = contextName
+ if tag is not None:
+ self.tag = tag
+ # a single arg is considered as a community name
+ if communityName is None:
+ communityName, communityIndex = communityIndex, None
+ self.communityName = communityName
+ # Autogenerate communityIndex if not specified
+ if communityIndex is None:
+ self.communityIndex = self.securityName = 's%s' % hash(
+ ( self.communityName,
+ self.mpModel,
+ self.contextEngineId,
+ self.contextName,
+ self.tag )
+ )
+ else:
+ self.communityIndex = communityIndex
+ self.securityName = securityName is not None and securityName or communityIndex
+
+ def __hash__(self):
+ raise TypeError('%s is not hashable' % self.__class__.__name__)
+
+ def __repr__(self):
+ return '%s(communityIndex=%r, communityName=<COMMUNITY>, mpModel=%r, contextEngineId=%r, contextName=%r, tag=%r, securityName=%r)' % (
+ self.__class__.__name__,
+ self.communityIndex,
+ self.mpModel,
+ self.contextEngineId,
+ self.contextName,
+ self.tag,
+ self.securityName
+ )
+
+ def clone(self, communityIndex=None, communityName=None,
+ mpModel=None, contextEngineId=None,
+ contextName=None, tag=None, securityName=None):
+ # a single arg is considered as a community name
+ if communityName is None:
+ communityName, communityIndex = communityIndex, None
+ return self.__class__(
+ communityIndex,
+ communityName is None and self.communityName or communityName,
+ mpModel is None and self.mpModel or mpModel,
+ contextEngineId is None and self.contextEngineId or contextEngineId,
+ contextName is None and self.contextName or contextName,
+ tag is None and self.tag or tag,
+ securityName is None and self.securityName or securityName
+ )
+
+#: No Authentication Protocol.
+usmNoAuthProtocol = config.usmNoAuthProtocol
+#: The HMAC-MD5-96 Digest Authentication Protocol (:RFC:`3414#section-6`)
+usmHMACMD5AuthProtocol = config.usmHMACMD5AuthProtocol
+#: The HMAC-SHA-96 Digest Authentication Protocol (:RFC:`3414#section-7`)
+usmHMACSHAAuthProtocol = config.usmHMACSHAAuthProtocol
+
+#: No Privacy Protocol.
+usmNoPrivProtocol = config.usmNoPrivProtocol
+#: The CBC-DES Symmetric Encryption Protocol (:RFC:`3414#section-8`)
+usmDESPrivProtocol = config.usmDESPrivProtocol
+#: The 3DES-EDE Symmetric Encryption Protocol (`draft-reeder-snmpv3-usm-3desede-00 <https://tools.ietf.org/html/draft-reeder-snmpv3-usm-3desede-00#section-5>`_)
+usm3DESEDEPrivProtocol = config.usm3DESEDEPrivProtocol
+#: The CFB128-AES-128 Symmetric Encryption Protocol (:RFC:`3826#section-3`)
+usmAesCfb128Protocol = config.usmAesCfb128Protocol
+#: The CFB128-AES-192 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)
+usmAesCfb192Protocol = config.usmAesCfb192Protocol
+#: The CFB128-AES-256 Symmetric Encryption Protocol (`draft-blumenthal-aes-usm-04 <https://tools.ietf.org/html/draft-blumenthal-aes-usm-04#section-3>`_)
+usmAesCfb256Protocol = config.usmAesCfb256Protocol
+
+class UsmUserData:
+ """Creates SNMP v3 User Security Model (USM) configuration entry.
+
+ This object can be used by
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator`
+ and their derivatives for adding new entries to Local Configuration
+ Datastore (LCD) managed by :py:class:`~pysnmp.entity.engine.SnmpEngine`
+ class instance.
+
+ See :RFC:`3414#section-5` for more information on the
+ *SNMP-USER-BASED-SM-MIB::usmUserTable*.
+
+ Parameters
+ ----------
+ userName : str
+ A human readable string representing the name of the SNMP USM user.
+ authKey : str
+ Initial value of the secret authentication key. If not set,
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoAuthProtocol`
+ is implied. If set and no *authProtocol* is specified,
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACMD5AuthProtocol`
+ takes effect.
+ privKey : str
+ Initial value of the secret encryption key. If not set,
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoPrivProtocol`
+ is implied. If set and no *privProtocol* is specified,
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmDESPrivProtocol`
+ takes effect.
+ authProtocol : tuple
+ An indication of whether messages sent on behalf of this USM user
+ can be authenticated, and if so, the type of authentication protocol
+ which is used.
+
+ Supported authentication protocol identifiers are:
+
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoAuthProtocol` (default is *authKey* not given)
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACMD5AuthProtocol` (default if *authKey* is given)
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmHMACSHAAuthProtocol`
+ privProtocol : tuple
+ An indication of whether messages sent on behalf of this USM user
+ be encrypted, and if so, the type of encryption protocol which is used.
+
+ Supported encryption protocol identifiers are:
+
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmNoPrivProtocol` (default is *authKey* not given)
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmDESPrivProtocol` (default if *authKey* is given)
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usm3DESEDEPrivProtocol`
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb128Protocol`
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb192Protocol`
+ * :py:class:`~pysnmp.entity.rfc3413.oneliner.auth.usmAesCfb256Protocol`
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.auth import UsmUserData
+ >>> UsmUserData('testuser', authKey='authenticationkey')
+ UsmUserData(userName='testuser', authKey=<AUTHKEY>, privKey=<PRIVKEY>, authProtocol=(1,3,6,1,6,3,10,1,1,2), privProtocol=(1,3,6,1,6,3,10,1,2,1))
+ >>> UsmUserData('testuser', authKey='authenticationkey', privKey='encryptionkey')
+ UsmUserData(userName='testuser', authKey=<AUTHKEY>, privKey=<PRIVKEY>, authProtocol=(1,3,6,1,6,3,10,1,1,2), privProtocol=(1,3,6,1,6,3,10,1,2,2))
+ >>>
+
+ """
+ authKey = privKey = None
+ authProtocol = config.usmNoAuthProtocol
+ privProtocol = config.usmNoPrivProtocol
+ securityLevel = 'noAuthNoPriv'
+ securityModel = 3
+ mpModel = 3
+ contextName = null
+ # the contextEngineId/contextName values stored here should
+ # be used for USM configuration only, not for PDU contents
+ def __init__(self, userName,
+ authKey=None, privKey=None,
+ authProtocol=None, privProtocol=None,
+ securityEngineId=None,
+ # deprecated parameters begin
+ contextName=None,
+ contextEngineId=None,
+ # deprecated parameters end
+ securityName=None):
+ self.userName = userName
+ if securityName is None:
+ self.securityName = userName
+ else:
+ self.securityName = securityName
+
+ if authKey is not None:
+ self.authKey = authKey
+ if authProtocol is None:
+ self.authProtocol = config.usmHMACMD5AuthProtocol
+ else:
+ self.authProtocol = authProtocol
+ if self.securityLevel != 'authPriv':
+ self.securityLevel = 'authNoPriv'
+
+ if privKey is not None:
+ self.privKey = privKey
+ if self.authProtocol == config.usmNoAuthProtocol:
+ raise error.PySnmpError('Privacy implies authenticity')
+ self.securityLevel = 'authPriv'
+ if privProtocol is None:
+ self.privProtocol = config.usmDESPrivProtocol
+ else:
+ self.privProtocol = privProtocol
+
+ # the contextEngineId parameter is actually a securityEngineId
+ if securityEngineId is None:
+ securityEngineId = contextEngineId
+ self.contextEngineId = self.securityEngineId = securityEngineId
+
+ # the contextName parameter should never be used here
+ if contextName is not None:
+ self.contextName = contextName
+
+ def __hash__(self):
+ raise TypeError('%s is not hashable' % self.__class__.__name__)
+
+ def __repr__(self):
+ return '%s(userName=%r, authKey=<AUTHKEY>, privKey=<PRIVKEY>, authProtocol=%r, privProtocol=%r, securityEngineId=%r, securityName=%r)'%(
+ self.__class__.__name__,
+ self.userName,
+ self.authProtocol,
+ self.privProtocol,
+ self.securityEngineId is None and '<DEFAULT>' or self.securityEngineId,
+ self.securityName
+ )
+
+ def clone(self, userName=None,
+ authKey=None, privKey=None,
+ authProtocol=None, privProtocol=None,
+ securityEngineId=None, securityName=None):
+ return self.__class__(
+ userName is None and self.userName or userName,
+ authKey is None and self.authKey or authKey,
+ privKey is None and self.privKey or privKey,
+ authProtocol is None and self.authProtocol or authProtocol,
+ privProtocol is None and self.privProtocol or privProtocol,
+ securityEngineId is None and self.securityEngineId or securityEngineId,
+ securityName=securityName is None and self.securityName or securityName
+ )
diff --git a/pysnmp/hlapi/context.py b/pysnmp/hlapi/context.py
new file mode 100644
index 0000000..0d86480
--- /dev/null
+++ b/pysnmp/hlapi/context.py
@@ -0,0 +1,48 @@
+from pyasn1.compat.octets import null
+
+__all__ = ['ContextData']
+
+class ContextData:
+ """Creates UDP/IPv6 configuration entry and initialize socket API if needed.
+
+ This object can be used by
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.cmdgen.AsyncCommandGenerator` or
+ :py:class:`~pysnmp.entity.rfc3413.oneliner.ntforg.AsyncNotificationOriginator`
+ and their derevatives for forming SNMP PDU and also adding new entries to
+ Local Configuration Datastore (LCD) in order to support SNMPv1/v2c with
+ SNMPv3 interoperability.
+
+ See :RFC:`3411#section-4.1` for SNMP Context details.
+
+ Parameters
+ ----------
+ contextEngineId : str
+ Uniquely identifies an SNMP entity that may realize an instance of
+ a MIB with a particular contextName (:RFC:`3411#section-3.3.2`).
+ More frequently than not, ContextEngineID is the same as
+ authoritative SnmpEngineID, however if SNMP Engine serves multiple
+ SNMP Entities, their ContextEngineIDs would be distinct.
+ Default is authoritative SNMP Engine ID.
+ contextName : str
+ Used to name an instance of MIB (:RFC:`3411#section-3.3.3`).
+ Default is empty string.
+
+ Examples
+ --------
+ >>> from pysnmp.entity.rfc3413.oneliner.ctx import ContextData
+ >>> ContextData()
+ ContextData(contextEngineId=None, contextName='')
+ >>> ContextData(OctetString(hexValue='01020ABBA0'))
+ ContextData(contextEngineId=OctetString(hexValue='01020abba0'), contextName='')
+ >>> ContextData(contextName='mycontext')
+ ContextData(contextEngineId=None, contextName='mycontext')
+
+ """
+ def __init__(self, contextEngineId=None, contextName=null):
+ self.contextEngineId = contextEngineId
+ self.contextName = contextName
+
+ def __repr__(self):
+ return '%s(contextEngineId=%r, contextName=%r)' % (
+ self.__class__.__name__, self.contextEngineId, self.contextName
+ )
diff --git a/pysnmp/hlapi/lcd.py b/pysnmp/hlapi/lcd.py
new file mode 100644
index 0000000..e62eaf1
--- /dev/null
+++ b/pysnmp/hlapi/lcd.py
@@ -0,0 +1,259 @@
+from pysnmp.entity import config
+from pysnmp import nextid, error
+from pysnmp.hlapi.auth import *
+
+__all__ = ['CommandGeneratorLcdConfigurator',
+ 'NotificationOriginatorLcdConfigurator' ]
+
+class AbstractLcdConfigurator:
+ nextID = nextid.Integer(0xffffffff)
+
+ def _getCache(self, snmpEngine):
+ cache = snmpEngine.getUserContext(self.__class__.__name__)
+ if cache is None:
+ cache = {
+ 'auth': {}, 'parm': {}, 'tran': {}, 'addr': {}
+ }
+ snmpEngine.setUserContext(cmdgen_cache=cache)
+ return cache
+
+ def configure(self, snmpEngine, authData, transportTarget): pass
+ def unconfigure(self, snmpEngine, authData=None): pass
+
+class CommandGeneratorLcdConfigurator(AbstractLcdConfigurator):
+ def configure(self, snmpEngine, authData, transportTarget):
+ cache = self._getCache(snmpEngine)
+ if isinstance(authData, CommunityData):
+ if authData.communityIndex not in cache['auth']:
+ config.addV1System(
+ snmpEngine,
+ authData.communityIndex,
+ authData.communityName,
+ authData.contextEngineId,
+ authData.contextName,
+ authData.tag,
+ authData.securityName
+ )
+ cache['auth'][authData.communityIndex] = authData
+ elif isinstance(authData, UsmUserData):
+ authDataKey = authData.userName, authData.securityEngineId
+ if authDataKey not in cache['auth']:
+ config.addV3User(
+ snmpEngine,
+ authData.userName,
+ authData.authProtocol, authData.authKey,
+ authData.privProtocol, authData.privKey,
+ authData.securityEngineId,
+ securityName=authData.securityName
+ )
+ cache['auth'][authDataKey] = authData
+ else:
+ raise error.PySnmpError('Unsupported authentication object')
+
+ paramsKey = authData.securityName, \
+ authData.securityLevel, \
+ authData.mpModel
+ if paramsKey in cache['parm']:
+ paramsName, useCount = cache['parm'][paramsKey]
+ cache['parm'][paramsKey] = paramsName, useCount + 1
+ else:
+ paramsName = 'p%s' % self.nextID()
+ config.addTargetParams(
+ snmpEngine, paramsName,
+ authData.securityName, authData.securityLevel, authData.mpModel
+ )
+ cache['parm'][paramsKey] = paramsName, 1
+
+ if transportTarget.transportDomain in cache['tran']:
+ transport, useCount = cache['tran'][transportTarget.transportDomain]
+ transportTarget.verifyDispatcherCompatibility(snmpEngine)
+ cache['tran'][transportTarget.transportDomain] = transport, useCount + 1
+ elif config.getTransport(snmpEngine, transportTarget.transportDomain):
+ transportTarget.verifyDispatcherCompatibility(snmpEngine)
+ else:
+ transport = transportTarget.openClientMode()
+ config.addTransport(
+ snmpEngine,
+ transportTarget.transportDomain,
+ transport
+ )
+ cache['tran'][transportTarget.transportDomain] = transport, 1
+
+ transportKey = ( paramsName,
+ transportTarget.transportDomain,
+ transportTarget.transportAddr,
+ transportTarget.tagList )
+
+ if transportKey in cache['addr']:
+ addrName, useCount = cache['addr'][transportKey]
+ cache['addr'][transportKey] = addrName, useCount + 1
+ else:
+ addrName = 'a%s' % self.nextID()
+ config.addTargetAddr(
+ snmpEngine, addrName,
+ transportTarget.transportDomain,
+ transportTarget.transportAddr,
+ paramsName,
+ transportTarget.timeout * 100,
+ transportTarget.retries,
+ transportTarget.tagList
+ )
+ cache['addr'][transportKey] = addrName, 1
+
+ return addrName, paramsName
+
+ def unconfigure(self, snmpEngine, authData=None):
+ cache = _getCache(snmpEngine)
+ if authData:
+ if isinstance(authData, CommunityData):
+ authDataKey = authData.communityIndex
+ elif isinstance(authData, UsmUserData):
+ authDataKey = authData.userName, authData.securityEngineId
+ else:
+ raise error.PySnmpError('Unsupported authentication object')
+ if authDataKey in cache['auth']:
+ authDataKeys = ( authDataKey, )
+ else:
+ raise error.PySnmpError('Unknown authData %s' % (authData,))
+ else:
+ authDataKeys = list(cache['auth'].keys())
+
+ addrNames, paramsNames = set(), set()
+
+ for authDataKey in authDataKeys:
+ authDataX = cache['auth'][authDataKey]
+ del cache['auth'][authDataKey]
+ if isinstance(authDataX, CommunityData):
+ config.delV1System(
+ snmpEngine,
+ authDataX.communityIndex
+ )
+ elif isinstance(authDataX, UsmUserData):
+ config.delV3User(
+ snmpEngine,
+ authDataX.userName,
+ authDataX.securityEngineId
+ )
+ else:
+ raise error.PySnmpError('Unsupported authentication object')
+
+ paramsKey = authDataX.securityName, \
+ authDataX.securityLevel, \
+ authDataX.mpModel
+ if paramsKey in cache['parm']:
+ paramsName, useCount = cache['parm'][paramsKey]
+ useCount -= 1
+ if useCount:
+ cache['parm'][paramsKey] = paramsName, useCount
+ else:
+ del cache['parm'][paramsKey]
+ config.delTargetParams(
+ snmpEngine, paramsName
+ )
+ paramsNames.add(paramsName)
+ else:
+ raise error.PySnmpError('Unknown target %s' % (paramsKey,))
+
+ addrKeys = [ x for x in cache['addr'] if x[0] == paramsName ]
+
+ for addrKey in addrKeys:
+ addrName, useCount = cache['addr'][addrKey]
+ useCount -= 1
+ if useCount:
+ cache['addr'][addrKey] = addrName, useCount
+ else:
+ config.delTargetAddr(snmpEngine, addrName)
+
+ addrNames.add(addrKey)
+
+ if addrKey[1] in cache['tran']:
+ transport, useCount = cache['tran'][addrKey[1]]
+ if useCount > 1:
+ useCount -= 1
+ cache['tran'][addrKey[1]] = transport, useCount
+ else:
+ config.delTransport(snmpEngine, addrKey[1])
+ transport.closeTransport()
+ del cache['tran'][addrKey[1]]
+
+ return addrNames, paramsNames
+
+class NotificationOriginatorLcdConfigurator(CommandGeneratorLcdConfigurator):
+ def configure(self, snmpEngine, authData, transportTarget, notifyType):
+ cache = self._getCache(snmpEngine)
+ addrName, paramsName = CommandGeneratorLcdConfigurator.configure(self, snmpEngine, authData, transportTarget)
+ tagList = transportTarget.tagList.split()
+ if not tagList:
+ tagList = ['']
+ for tag in tagList:
+ notifyNameKey = paramsName, tag, notifyType
+ if notifyNameKey in cache['name']:
+ notifyName, paramsName, useCount = cache['name'][notifyNameKey]
+ cache['name'][notifyNameKey] = notifyName, paramsName, useCount + 1
+ else:
+ notifyName = 'n%s' % self.nextID()
+ config.addNotificationTarget(
+ snmpEngine,
+ notifyName,
+ paramsName,
+ tag,
+ notifyType
+ )
+ cache['name'][notifyNameKey] = notifyName, paramsName, 1
+ authDataKey = authData.securityName, authData.securityModel
+ if authDataKey in cache['auth']:
+ authDataX, subTree, useCount = cache['auth'][authDataKey]
+ cache['auth'][authDataKey] = authDataX, subTree, useCount + 1
+ else:
+ subTree = (1,3,6)
+ config.addTrapUser(
+ snmpEngine,
+ authData.securityModel,
+ authData.securityName,
+ authData.securityLevel,
+ subTree
+ )
+ cache['auth'][authDataKey] = authData, subTree, 1
+
+ return notifyName
+
+ def unconfigure(self, snmpEngine, authData=None):
+ cache = _getCache(snmpEngine)
+ if authData:
+ authDataKey = authData.securityName, authData.securityModel
+ if authDataKey in cache['auth']:
+ authDataKeys = ( authDataKey, )
+ else:
+ raise error.PySnmpError('Unknown authData %s' % (authData,))
+ else:
+ authDataKeys = tuple(cache['auth'].keys())
+
+ addrNames, paramsNames = CommandGeneratorLcdConfigurator.unconfigure(self, snmpEngine, authData)
+
+ notifyAndParamsNames = [ (cache['name'][x], x) for x in cache['name'].keys() if x[0] in paramsNames ]
+
+ for (notifyName, paramsName, useCount), notifyNameKey in notifyAndParamsNames:
+ useCount -= 1
+ if useCount:
+ cache['name'][notifyNameKey] = notifyName, paramsName, useCount
+ else:
+ config.delNotificationTarget(
+ snmpEngine, notifyName, paramsName
+ )
+ del cache['name'][notifyNameKey]
+
+ for authDataKey in authDataKeys:
+ authDataX, subTree, useCount = cache['auth'][authDataKey]
+ useCount -= 1
+ if useCount:
+ cache['auth'][authDataKey] = authDataX, subTree, useCount
+ else:
+ config.delTrapUser(
+ snmpEngine,
+ authDataX.securityModel,
+ authDataX.securityName,
+ authDataX.securityLevel,
+ subTree
+ )
+ del cache['auth'][authDataKey]
+
diff --git a/pysnmp/hlapi/varbinds.py b/pysnmp/hlapi/varbinds.py
new file mode 100644
index 0000000..1f32847
--- /dev/null
+++ b/pysnmp/hlapi/varbinds.py
@@ -0,0 +1,62 @@
+from pysnmp.smi import view
+from pysnmp.smi.rfc1902 import *
+
+__all__ = ['CommandGeneratorVarBinds', 'NotificationOriginatorVarBinds']
+
+class AbstractVarBinds:
+ def getMibViewController(self, snmpEngine):
+ mibViewController = snmpEngine.getUserContext('mibViewController')
+ if not mibViewController:
+ mibViewController = view.MibViewController(
+ snmpEngine.getMibBuilder()
+ )
+ snmpEngine.setUserContext(mibViewController=mibViewController)
+ return mibViewController
+
+class CommandGeneratorVarBinds(AbstractVarBinds):
+ def makeVarBinds(self, snmpEngine, varBinds):
+ mibViewController = self.getMibViewController(snmpEngine)
+ __varBinds = []
+ for varBind in varBinds:
+ if isinstance(varBind, ObjectType):
+ pass
+ elif isinstance(varBind[0], ObjectIdentity):
+ varBind = ObjectType(*varBind)
+ elif isinstance(varBind[0][0], tuple): # legacy
+ varBind = ObjectType(ObjectIdentity(varBind[0][0][0], varBind[0][0][1], *varBind[0][1:]), varBind[1])
+ else:
+ varBind = ObjectType(ObjectIdentity(varBind[0]), varBind[1])
+
+ __varBinds.append(varBind.resolveWithMib(mibViewController))
+
+ return __varBinds
+
+ def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=True):
+ if lookupMib:
+ mibViewController = self.getMibViewController(snmpEngine)
+ varBinds = [ ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds ]
+
+ return varBinds
+
+class NotificationOriginatorVarBinds(AbstractVarBinds):
+ def makeVarBinds(self, snmpEngine, varBinds):
+ mibViewController = self.getMibViewController(snmpEngine)
+ if isinstance(varBinds, NotificationType):
+ varBinds.resolveWithMib(mibViewController)
+ __varBinds = []
+ for varBind in varBinds:
+ if isinstance(varBind, ObjectType):
+ pass
+ elif isinstance(varBind[0], ObjectIdentity):
+ varBind = ObjectType(*varBind)
+ else:
+ varBind = ObjectType(ObjectIdentity(varBind[0]), varBind[1])
+ __varBinds.append(varBind.resolveWithMib(mibViewController))
+ return __varBinds
+
+ def unmakeVarBinds(self, snmpEngine, varBinds, lookupMib=False):
+ if lookupMib:
+ mibViewController = self.getMibViewController(snmpEngine)
+ varBinds = [ ObjectType(ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController) for x in varBinds ]
+ return varBinds
+
diff --git a/pysnmp/proto/rfc1155.py b/pysnmp/proto/rfc1155.py
index 6f67f0a..4fb9aec 100644
--- a/pysnmp/proto/rfc1155.py
+++ b/pysnmp/proto/rfc1155.py
@@ -2,6 +2,9 @@ from pyasn1.type import univ, tag, constraint, namedtype
from pyasn1.error import PyAsn1Error
from pysnmp.proto import error
+__all__ = ['Opaque', 'NetworkAddress', 'ObjectName', 'TimeTicks',
+ 'Counter', 'Gauge', 'IpAddress']
+
class IpAddress(univ.OctetString):
tagSet = univ.OctetString.tagSet.tagImplicitly(
tag.Tag(tag.tagClassApplication, tag.tagFormatSimple, 0x00)
diff --git a/pysnmp/proto/rfc1157.py b/pysnmp/proto/rfc1157.py
index 4483cf1..6fd1643 100644
--- a/pysnmp/proto/rfc1157.py
+++ b/pysnmp/proto/rfc1157.py
@@ -1,6 +1,9 @@
from pyasn1.type import univ, tag, namedtype, namedval
from pysnmp.proto import rfc1155
+__all__ = ['GetNextRequestPDU', 'GetResponsePDU', 'SetRequestPDU',
+ 'TrapPDU', 'GetRequestPDU']
+
class VarBind(univ.Sequence):
componentType = namedtype.NamedTypes(
namedtype.NamedType('name', rfc1155.ObjectName()),
diff --git a/pysnmp/proto/rfc1902.py b/pysnmp/proto/rfc1902.py
index b284140..08e64ab 100644
--- a/pysnmp/proto/rfc1902.py
+++ b/pysnmp/proto/rfc1902.py
@@ -1,6 +1,10 @@
from pyasn1.type import univ, tag, constraint, namedtype, namedval
from pysnmp.proto import rfc1155, error
+__all__ = ['Opaque', 'TimeTicks', 'Bits', 'Integer', 'OctetString',
+ 'IpAddress', 'Counter64', 'Unsigned32', 'Gauge32', 'Integer32',
+ 'ObjectIdentifier', 'Counter32']
+
class Integer32(univ.Integer):
"""Creates an instance of SNMP Integer32 class.
diff --git a/pysnmp/proto/rfc1905.py b/pysnmp/proto/rfc1905.py
index e77912f..945b32b 100644
--- a/pysnmp/proto/rfc1905.py
+++ b/pysnmp/proto/rfc1905.py
@@ -1,6 +1,12 @@
from pyasn1.type import univ, tag, constraint, namedtype, namedval
from pysnmp.proto import rfc1902
+__all__ = ['unSpecified', 'EndOfMibView', 'ReportPDU', 'UnSpecified',
+ 'BulkPDU', 'SNMPv2TrapPDU', 'GetRequestPDU', 'NoSuchObject',
+ 'GetNextRequestPDU', 'GetBulkRequestPDU', 'NoSuchInstance',
+ 'ResponsePDU', 'noSuchObject', 'InformRequestPDU', 'endOfMibView',
+ 'SetRequestPDU', 'noSuchInstance']
+
# Value reference -- max bindings in VarBindList
max_bindings = rfc1902.Integer(2147483647)
diff --git a/pysnmp/smi/rfc1902.py b/pysnmp/smi/rfc1902.py
index b61f5a0..2ab5a8c 100644
--- a/pysnmp/smi/rfc1902.py
+++ b/pysnmp/smi/rfc1902.py
@@ -8,21 +8,6 @@ from pyasn1.type.base import AbstractSimpleAsn1Item
from pyasn1.error import PyAsn1Error
from pysnmp import debug
-# expose SNMP types in this namespace for convenience
-Integer = rfc1902.Integer
-Integer32 = rfc1902.Integer32
-OctetString = rfc1902.OctetString
-ObjectIdentifier = rfc1902.ObjectIdentifier
-IpAddress = rfc1902.IpAddress
-Counter32 = rfc1902.Counter32
-Gauge32 = rfc1902.Gauge32
-Unsigned32 = rfc1902.Unsigned32
-TimeTicks = rfc1902.TimeTicks
-Opaque = rfc1902.Opaque
-Counter64 = rfc1902.Counter64
-Bits = rfc1902.Bits
-ObjectName = rfc1902.ObjectName
-
class ObjectIdentity:
"""Create an object representing MIB variable ID.