Exemplo n.º 1
0
Arquivo: snmp.py Projeto: sohonet/HEN
    def walk_v1(self, oid):
        def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
                  varBinds, cbCtx):
            cbCtx['errorIndication'] = errorIndication
            cbCtx['errorStatus'] = errorStatus
            cbCtx['errorIndex'] = errorIndex

            for varBindRow in varBinds:

                inTableFlag = 0
                for oi, val in varBindRow:
                    if val is None or not oid.isPrefixOf(oi):
                        continue
                    inTableFlag = 1
                if not inTableFlag:
                    return  # stop on end-of-table
                cbCtx['varBinds'].append(varBindRow)
            return 1  # continue walking

        cb = {}
        cb['varBinds'] = []
        #self.__lock.acquire()
        cmdgen.NextCommandGenerator().sendReq(self.__snmp_engine, 'myRouter',
                                              ((oid, None), ), cbFun, cb)
        self.__snmp_engine.transportDispatcher.runDispatcher()
        #self.__lock.release()
        self.__errorIndication = cb['errorIndication']
        self.__errorStatus = cb['errorStatus']
        self.__errorIndex = cb['errorIndex']
        self.__varBinds = cb['varBinds']
        if self.getErrorStatus():
            log.critical("Error in snmp walk (v1) " + str(self.showError()))
        return self.__varBinds
Exemplo n.º 2
0
    def nextCmd(self,
                authData,
                transportTarget,
                varNames,
                cbInfo,
                lookupNames=False,
                lookupValues=False,
                contextEngineId=None,
                contextName=null):
        def __cbFun(sendRequestHandle, errorIndication, errorStatus,
                    errorIndex, varBindTable, cbCtx):
            lookupNames, lookupValues, cbFun, cbCtx = cbCtx
            return cbFun(sendRequestHandle, errorIndication, errorStatus,
                         errorIndex, [
                             self.unmakeVarBinds(varBindTableRow, lookupNames,
                                                 lookupValues)
                             for varBindTableRow in varBindTable
                         ], cbCtx)

        # for backward compatibility
        if contextName is null and authData.contextName:
            contextName = authData.contextName

        (cbFun, cbCtx) = cbInfo
        addrName, paramsName = self.cfgCmdGen(authData, transportTarget)
        return cmdgen.NextCommandGenerator().sendReq(
            self.snmpEngine, addrName, self.makeReadVarBinds(varNames),
            __cbFun, (lookupNames, lookupValues, cbFun, cbCtx),
            contextEngineId, contextName)
Exemplo n.º 3
0
    def nextCmd(self, snmpEngine, authData, transportTarget, varNames, cbInfo,
                lookupNames=False, lookupValues=False,
                contextEngineId=None, contextName=null):
        def __cbFun(sendRequestHandle,
                    errorIndication, errorStatus, errorIndex,
                    varBindTable, cbCtx):
            lookupNames, lookupValues, cbFun, cbCtx = cbCtx
            return cbFun(
                sendRequestHandle,
                errorIndication,
                errorStatus,
                errorIndex,
                [ self.unmakeVarBinds(snmpEngine, varBindTableRow, lookupNames, lookupValues) for varBindTableRow in varBindTable ],
                cbCtx
            )

        (cbFun, cbCtx) = cbInfo
        addrName, paramsName = self.cfgCmdGen(
            snmpEngine, authData, transportTarget
        )
        return cmdgen.NextCommandGenerator().sendReq(
            snmpEngine,
            addrName,
            self.makeVarBinds(snmpEngine, [(x, self._null) for x in varNames]),
            __cbFun,
            (lookupNames, lookupValues, cbFun, cbCtx),
            contextEngineId, contextName
        )
Exemplo n.º 4
0
 def nextCmd(self, authData, transportTarget, varNames, cbInfo):
     (cbFun, cbCtx) = cbInfo
     addrName, paramsName = self.cfgCmdGen(authData, transportTarget)
     varBinds = self.makeReadVarBinds(varNames)
     return cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, addrName,
                                                  varBinds, cbFun, cbCtx,
                                                  authData.contextEngineId,
                                                  authData.contextName)
Exemplo n.º 5
0
 def walk_command(self, OID, callback=None):
     if not callback:
         callback = self.cbFun
     cmdgen.NextCommandGenerator().sendReq(
         self.snmpEngine,
         'my-router',
         (OID, ),
         callback,
     )
    def send_walk_var_binds(self, oid, cb_ctx):
        cmd_gen = cmdgen.NextCommandGenerator()

        cmd_gen.sendVarBinds(
            self.snmp_parameters.snmp_engine,
            'tgt',
            self.snmp_parameters.v3_context_engine_id, self.snmp_parameters.v3_context,
            [(oid, None)],
            self.cb_fun, cb_ctx
        )
Exemplo n.º 7
0
def snmp_getnext(config, oids, lookup_mib, ignore_nonincreasing_oid):
    # type: (InstanceConfig, list, bool, bool) -> Generator
    """Call SNMP GETNEXT on a list of oids. It will iterate on the results if it happens to be under the same prefix."""
    def callback(  # type: ignore
            snmpEngine, sendRequestHandle, errorIndication, errorStatus,
            errorIndex, varBindTable, cbCtx):
        var_bind_table = [
            vbProcessor.unmakeVarBinds(snmpEngine, row, lookup_mib)
            for row in varBindTable
        ]
        if ignore_nonincreasing_oid and errorIndication and isinstance(
                errorIndication, errind.OidNotIncreasing):
            errorIndication = None
        cbCtx['error'] = errorIndication
        cbCtx['var_bind_table'] = var_bind_table[0]

    ctx = {}  # type: Dict[str, Any]

    initial_vars = [
        x[0] for x in vbProcessor.makeVarBinds(config._snmp_engine, oids)
    ]

    var_binds = oids

    gen = cmdgen.NextCommandGenerator()

    while True:
        gen.sendVarBinds(
            config._snmp_engine,
            config._addr_name,
            config._context_data.contextEngineId,
            config._context_data.contextName,
            var_binds,
            callback,
            ctx,
        )

        config._snmp_engine.transportDispatcher.runDispatcher()

        _handle_error(ctx, config)

        var_binds = []

        new_initial_vars = []
        for col, var_bind in enumerate(ctx['var_bind_table']):
            name, val = var_bind
            if not isinstance(val,
                              Null) and initial_vars[col].isPrefixOf(name):
                var_binds.append(var_bind)
                new_initial_vars.append(initial_vars[col])
                yield var_bind
        if not var_binds:
            return
        initial_vars = new_initial_vars
Exemplo n.º 8
0
def createSNMP(host, community=None):
    if community is None:
        community = "public"

    ip = gethostbyname(host)
    snmpEngine = engine.SnmpEngine()
    config.addV1System(snmpEngine, 'my-area', community)
    config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv',
                           0)
    config.addTransport(snmpEngine, udp.domainName,
                        udp.UdpSocketTransport().openClientMode())
    config.addTargetAddr(snmpEngine, 'my-router', udp.domainName, (ip, 161),
                         'my-creds')

    cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine, 'my-router', None, '',
        [((1, 3, 6, 1, 2, 1, 1, 0, 0), None)], getHost)
    snmpEngine.transportDispatcher.runDispatcher()

    cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine, 'my-router', None, '',
        [((1, 3, 6, 1, 2, 1, 4, 34, 1, 3, 2, 16), None)], getAddrs)
    snmpEngine.transportDispatcher.runDispatcher()
Exemplo n.º 9
0
    def _send_walk_var_binds(self, oid, cb_fun=None):
        cmd_gen = cmdgen.NextCommandGenerator()
        if not cb_fun:
            cb_fun = self.cb_walk_fun

        cmd_gen.sendVarBinds(
            self._snmp_engine,
            "tgt",
            self._context_id,
            self._context_name,
            [(oid, None)],
            cb_fun,
            self.cb_ctx,
        )
Exemplo n.º 10
0
    def nextCmd(self, agent, context, host, port, *varNames):
        self._setup(agent, context, host, port)

        ## @brief call back function
        # @param sendRequestHandle
        # @param errorIndication indicates error
        # @param errorStatus status of error
        # @param errorIndex index of error
        # @param varBindTable table of variable bindings
        # @param cbCtx application state
        # @returns cbCtx application state
        def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
                  varBindTable, cbCtx):
            if errorIndication or errorStatus:
                cbCtx['errorIndication'] = errorIndication
                cbCtx['errorStatus'] = errorStatus
                cbCtx['errorIndex'] = errorIndex
                cbCtx['varBindTable'] = varBindTable
                return
            else:
                varBindTableRow = varBindTable[-1]
                for idx in range(len(varBindTableRow)):
                    _, val = varBindTableRow[idx]
                    # XXX extra rows
                    if val is not None:
                        continue
                else:
                    cbCtx['errorIndication'] = errorIndication
                    cbCtx['errorStatus'] = errorStatus
                    cbCtx['errorIndex'] = errorIndex
                    cbCtx['varBindTable'] = varBindTableRow
                    return

            return 1  # continue walking

        cbCtx = {}
        varBinds = []
        for varName in varNames:
            varBinds.append((varName, None))

        cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, 'myRouter',
                                              varBinds, cbFun, cbCtx)

        self.snmpEngine.transportDispatcher.runDispatcher()

        return (cbCtx['errorIndication'], cbCtx['errorStatus'],
                cbCtx['errorIndex'], cbCtx['varBindTable'])
Exemplo n.º 11
0
 def _onTabularResult(sendRequestHandle, errorIndication, errorStatus,
                      errorIndex, varBindTable, df):
     """Process a (partial) tabular result"""
     foundRoots = {}
     foundNonNull = False
     for row in varBindTable:
         foundNonNull = False
         for (key, value) in row:
             if value is not None:
                 foundNonNull = True
                 for r in roots:
                     if key[:len(r)] == r:
                         tbl = result.get(r)
                         if tbl is None:
                             tbl = result[r] = {}
                         tbl[key] = value
                         foundRoots[r] = key
     if not foundRoots or not foundNonNull:
         df.callback(result)
     else:
         roots[:] = foundRoots.keys()
         if self.snmpVersion != '1':
             cmdgen.BulkCommandGenerator().sendReq(
                 self.engine,
                 self.targetName,
                 0,  # nonRepeaters (count)
                 maxRepetitions,
                 [(r, None) for r in foundRoots.values()],  # varBinds
                 _onTabularResult,
                 df,
             )
         else:
             cmdgen.NextCommandGenerator().sendReq(
                 self.engine, self.targetName,
                 [(r, None) for r in foundRoots.values()],
                 _onTabularResult, df)
Exemplo n.º 12
0
def nextCmd(snmpEngine, authData, transportTarget, contextData,
            *varBinds, **options):
    """Performs SNMP GETNEXT query.

    Based on passed parameters, prepares SNMP GETNEXT packet
    (:RFC:`1905#section-4.2.2`) and schedules its transmission by
    :mod:`twisted` I/O framework at a later point of time.

    Parameters
    ----------
    snmpEngine : :class:`~pysnmp.hlapi.SnmpEngine`
        Class instance representing SNMP engine.

    authData : :class:`~pysnmp.hlapi.CommunityData` or :class:`~pysnmp.hlapi.UsmUserData`
        Class instance representing SNMP credentials.

    transportTarget : :class:`~pysnmp.hlapi.twisted.UdpTransportTarget` or :class:`~pysnmp.hlapi.twisted.Udp6TransportTarget`
        Class instance representing transport type along with SNMP peer address.

    contextData : :class:`~pysnmp.hlapi.ContextData`
        Class instance representing SNMP ContextEngineId and ContextName values.

    \*varBinds : :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`.
            * `ignoreNonIncreasingOid` - continue iteration even if response
              MIB variables (OIDs) are not greater then request MIB variables.
              Be aware that setting it to `True` may cause infinite loop between
              SNMP management and agent applications. Default is `False`.

    Returns
    -------
    deferred : :class:`~twisted.internet.defer.Deferred`
        Twisted Deferred object representing work-in-progress. User
        is expected to attach his own `success` and `error` callback
        functions to the Deferred object though
        :meth:`~twisted.internet.defer.Deferred.addCallbacks` method.

    Raises
    ------
    PySnmpError
        Or its derivative indicating that an error occurred while
        performing SNMP operation.

    Notes
    -----
    User `success` callback is called with the following tuple as
    its first argument:

    * 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.

    User `error` callback is called with `errorIndication` object wrapped
    in :class:`~twisted.python.failure.Failure` object.

    Examples
    --------
    >>> from twisted.internet.task import react
    >>> from pysnmp.hlapi.twisted import *
    >>>
    >>> def success(args):
    ...     (errorStatus, errorIndex, varBindTable) = args
    ...     print(errorStatus, errorIndex, varBindTable)
    ...
    >>> def failure(errorIndication):
    ...     print(errorIndication)
    ...
    >>> def run(reactor):
    ...     d = nextCmd(SnmpEngine(),
    ...                 CommunityData('public'),
    ...                 UdpTransportTarget(('demo.snmplabs.com', 161)),
    ...                 ContextData(),
    ...                 ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))
    ...     d.addCallback(success).addErrback(failure)
    ...     return d
    ...
    >>> react(run)
    (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, deferred = cbCtx
        if (options.get('ignoreNonIncreasingOid', False) and
                errorIndication and isinstance(errorIndication, errind.OidNotIncreasing)):
            errorIndication = None
        if errorIndication:
            deferred.errback(Failure(errorIndication))
        else:
            try:
                varBindsUnmade = [vbProcessor.unmakeVarBinds(snmpEngine.cache,
                                                             varBindTableRow,
                                                             lookupMib)
                                  for varBindTableRow in varBindTable]

            except Exception as e:
                deferred.errback(Failure(e))

            else:
                deferred.callback((errorStatus, errorIndex, varBindsUnmade))

    addrName, paramsName = lcd.configure(
        snmpEngine, authData, transportTarget, contextData.contextName)

    deferred = Deferred()

    cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine, addrName, contextData.contextEngineId,
        contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine.cache, varBinds), __cbFun,
        (options.get('lookupMib', True), deferred)
    )
    return deferred
Exemplo n.º 13
0
    'total': 0,
    'count': 0,
    'errors': 0,
    'iteration': 0,
    'reqTime': time.time(),
    'retries': continueOnErrors,
    'lastOID': startOID
}

if getBulkFlag:
    cmdGen = cmdgen.BulkCommandGenerator()

    cmdGen.sendVarBinds(snmpEngine, 'tgt', v3ContextEngineId, v3Context, 0,
                        getBulkRepetitions, [(startOID, None)], cbFun, cbCtx)
else:
    cmdGen = cmdgen.NextCommandGenerator()

    cmdGen.sendVarBinds(snmpEngine, 'tgt', v3ContextEngineId, v3Context,
                        [(startOID, None)], cbFun, cbCtx)

log.info('Sending initial %s request for %s (stop at %s)....' %
         (getBulkFlag and 'GETBULK' or 'GETNEXT', startOID, stopOID
          or '<end-of-mib>'))

t = time.time()

# Python 2.4 does not support the "finally" clause

exc_info = None

try:
Exemplo n.º 14
0
def nextCmd(snmpEngine, authData, transportTarget, contextData, *varBinds,
            **options):
    """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.hlapi.SnmpEngine`
        Class instance representing SNMP engine.

    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
        Class instance representing SNMP credentials.

    transportTarget : :py:class:`~pysnmp.hlapi.asyncore.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncore.Udp6TransportTarget`
        Class instance representing transport type along with SNMP peer
        address.

    contextData : :py:class:`~pysnmp.hlapi.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`.
            * `cbFun` (callable) - user-supplied callable that is invoked
               to pass SNMP response data or error to user at a later point
               of time. Default is `None`.
            * `cbCtx` (object) - user-supplied object passing additional
               parameters to/from `cbFun`. Default is `None`.

    Notes
    -----
    User-supplied `cbFun` callable must have the following call
    signature:

    * snmpEngine (:py:class:`~pysnmp.hlapi.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.hlapi.asyncore import *
    >>> def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus, errorIndex, varBinds, cbCtx):
    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
    >>>
    >>> snmpEngine = SnmpEngine()
    >>> nextCmd(snmpEngine,
    ...         CommunityData('public'),
    ...         UdpTransportTarget(('demo.snmplabs.com', 161)),
    ...         ContextData(),
    ...         ObjectType(ObjectIdentity('SNMPv2-MIB', 'system')),
    ...         cbFun=cbFun)
    >>> 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, [
                         vbProcessor.unmakeVarBinds(snmpEngine.cache,
                                                    varBindTableRow, lookupMib)
                         for varBindTableRow in varBindTable
                     ], cbCtx)

    addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget,
                                         contextData.contextName)

    return cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine, addrName, contextData.contextEngineId,
        contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine.cache, varBinds), __cbFun,
        (options.get('lookupMib',
                     True), options.get('cbFun'), options.get('cbCtx')))
config.addTargetAddr(snmpEngine, 'my-router', udp.domainName,
                     ('195.218.195.228', 161), 'my-creds')


# Error/response receiver
def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
          varBindTable, cbCtx):
    if errorIndication:
        print(errorIndication)
        return
    if errorStatus:
        print('%s at %s' %
              (errorStatus.prettyPrint(),
               errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
        return  # stop on error
    for varBindRow in varBindTable:
        for oid, val in varBindRow:
            if initialOID.isPrefixOf(oid):
                print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
            else:
                return False  # signal dispatcher to stop
    return True  # signal dispatcher to continue


# Prepare initial request to be sent
cmdgen.NextCommandGenerator().sendReq(snmpEngine, 'my-router',
                                      ((initialOID, None), ), cbFun)

# Run I/O dispatcher which would send pending queries and process responses
snmpEngine.transportDispatcher.runDispatcher()
                     ('195.218.195.228', 161), 'my-creds')


# Error/response receiver
def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
          varBindTable, cbCtx):
    if errorIndication:
        print(errorIndication)
        return
    # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception,
    # so we ignore noSuchName error here
    if errorStatus and errorStatus != 2:
        print('%s at %s' %
              (errorStatus.prettyPrint(),
               errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
        return  # stop on error
    for varBindRow in varBindTable:
        for oid, val in varBindRow:
            print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
    return 1  # signal dispatcher to continue


# Prepare initial request to be sent
cmdgen.NextCommandGenerator().sendReq(snmpEngine, 'my-router', (
    ((1, 3, 6, 1, 2, 1, 1), None),
    ((1, 3, 6, 1, 4, 1, 1), None),
), cbFun)

# Run I/O dispatcher which would send pending queries and process responses
snmpEngine.transportDispatcher.runDispatcher()
Exemplo n.º 17
0
    def getTable(
        self,
        roots,
        includeStart=0,
        recordCallback=None,
        retryCount=4,
        timeout=2.0,
        maxRepetitions=DEFAULT_BULK_REPETITION_SIZE,
        startOIDs=None,
    ):
        """Convenience method for creating and running a TableRetriever

		roots -- root OIDs to retrieve
		includeStart -- whether to include the starting OID
			in the set of results, by default, return the OID
			*after* the root oids.
			Note:  Only implemented for v1 protocols, and likely
				to be dropped eventually, as it seems somewhat
				superfluous.
		recordCallback -- called for each new record discovered
			recordCallback( root, oid, value )
		retryCount -- number of retries
		timeout -- initial timeout, is multipled by 1.5 on each
			timeout iteration.
		maxRepetitions -- size for each block requested from the
			server, i.e. how many records to download at a single
			time
		startOIDs -- optional OID markers to be used as starting point,
			i.e. if passed in, we retrieve the table from startOIDs to
			the end of the table excluding startOIDs themselves, rather 
			than from roots to the end of the table.

		Will use bulk downloading when available (i.e. if
		we have implementation v2c, not v1).

		return value is a defered for a { rootOID: { oid: value } } mapping
		"""
        df = defer.Deferred()
        result = {}
        if startOIDs is None:
            startOIDs = roots

        def _onTabularResult(sendRequestHandle, errorIndication, errorStatus,
                             errorIndex, varBindTable, df):
            """Process a (partial) tabular result"""
            foundRoots = {}
            foundNonNull = False
            for row in varBindTable:
                foundNonNull = False
                for (key, value) in row:
                    if value is not None:
                        foundNonNull = True
                        for r in roots:
                            if key[:len(r)] == r:
                                tbl = result.get(r)
                                if tbl is None:
                                    tbl = result[r] = {}
                                tbl[key] = value
                                foundRoots[r] = key
            if not foundRoots or not foundNonNull:
                df.callback(result)
            else:
                roots[:] = foundRoots.keys()
                if self.snmpVersion != '1':
                    cmdgen.BulkCommandGenerator().sendReq(
                        self.engine,
                        self.targetName,
                        0,  # nonRepeaters (count)
                        maxRepetitions,
                        [(r, None) for r in foundRoots.values()],  # varBinds
                        _onTabularResult,
                        df,
                    )
                else:
                    cmdgen.NextCommandGenerator().sendReq(
                        self.engine, self.targetName,
                        [(r, None) for r in foundRoots.values()],
                        _onTabularResult, df)

        if self.snmpVersion != '1':
            cmdgen.BulkCommandGenerator().sendReq(
                self.engine,
                self.targetName,
                0,  # nonRepeaters (count)
                maxRepetitions,
                [(r, None) for r in startOIDs],  # varBinds
                _onTabularResult,
                df,
            )
        else:
            cmdgen.NextCommandGenerator().sendReq(self.engine, self.targetName,
                                                  [(r, None)
                                                   for r in startOIDs],
                                                  _onTabularResult, df)
        return df
Exemplo n.º 18
0
def nextCmd(snmpEngine, authData, transportTarget, contextData,
            *varBinds, **options):
    """Creates a generator to perform SNMP GETNEXT query.

    When itereator gets advanced by :py:mod:`asyncio` main loop,
    SNMP GETNEXT request is send (:RFC:`1905#section-4.2.2`).
    The iterator yields :py:class:`asyncio.Future` which gets done whenever
    response arrives or error occurs.

    Parameters
    ----------
    snmpEngine : :py:class:`~pysnmp.hlapi.SnmpEngine`
        Class instance representing SNMP engine.

    authData : :py:class:`~pysnmp.hlapi.CommunityData` or :py:class:`~pysnmp.hlapi.UsmUserData`
        Class instance representing SNMP credentials.

    transportTarget : :py:class:`~pysnmp.hlapi.asyncio.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.asyncio.Udp6TransportTarget`
        Class instance representing transport type along with SNMP peer address.

    contextData : :py:class:`~pysnmp.hlapi.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 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.

    Raises
    ------
    PySnmpError
        Or its derivative indicating that an error occurred while
        performing SNMP operation.

    Examples
    --------
    >>> import asyncio
    >>> from pysnmp.hlapi.asyncio import *
    >>>
    >>> @asyncio.coroutine
    ... def run():
    ...     errorIndication, errorStatus, errorIndex, varBinds = yield from nextCmd(
    ...         SnmpEngine(),
    ...         CommunityData('public'),
    ...         UdpTransportTarget(('demo.snmplabs.com', 161)),
    ...         ContextData(),
    ...         ObjectType(ObjectIdentity('SNMPv2-MIB', 'system'))
    ...     )
    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
    >>>
    >>> asyncio.get_event_loop().run_until_complete(run())
    (None, 0, 0, [[ObjectType(ObjectIdentity('1.3.6.1.2.1.1.1.0'), DisplayString('Linux i386'))]])
    >>>

    """

    def __cbFun(snmpEngine, sendRequestHandle,
                errorIndication, errorStatus, errorIndex,
                varBindTable, cbCtx):
        lookupMib, future = cbCtx
        if future.cancelled():
            return
        try:
            varBindsUnmade = [vbProcessor.unmakeVarBinds(snmpEngine,
                                                         varBindTableRow,
                                                         lookupMib)
                              for varBindTableRow in varBindTable]
        except Exception as e:
            future.set_exception(e)
        else:
            future.set_result(
                (errorIndication, errorStatus, errorIndex, varBindsUnmade)
            )

    addrName, paramsName = lcd.configure(snmpEngine, authData, transportTarget)

    future = asyncio.Future()

    cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine, addrName, contextData.contextEngineId,
        contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun,
        (options.get('lookupMib', True), future)
    )
    return future
Exemplo n.º 19
0
# Error/response receiver
# noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal
def cbFun(snmpEngine, sendRequestHandle, errorIndication,
          errorStatus, errorIndex, varBindTable, cbCtx):
    if errorIndication:
        print(errorIndication)
        return
    if errorStatus:
        print('%s at %s' % (errorStatus.prettyPrint(),
                            errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
        return  # stop on error
    for varBindRow in varBindTable:
        for oid, val in varBindRow:
            print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
    return 1  # signal dispatcher to continue


# Prepare initial request to be sent
cmdgen.NextCommandGenerator().sendVarBinds(
    snmpEngine,
    'my-router',
    None, '',  # contextEngineId, contextName
    [((1, 3, 6, 1, 2, 1, 1), None),
     ((1, 3, 6, 1, 2, 1, 11), None)],
    cbFun
)

# Run I/O dispatcher which would send pending queries and process responses
snmpEngine.transportDispatcher.runDispatcher()
Exemplo n.º 20
0
    if errorStatus and errorStatus != 2:
        print('%s at %s' %
              (errorStatus.prettyPrint(),
               errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
        return  # stop on error
    for varBindRow in varBindTable:
        for varBind in varBindRow:
            print(
                rfc1902.ObjectType(rfc1902.ObjectIdentity(varBind[0]),
                                   varBind[1]).resolveWithMib(
                                       mibViewController).prettyPrint())
    return 1  # signal dispatcher to continue


# Prepare initial request to be sent
cmdgen.NextCommandGenerator().sendVarBinds(
    snmpEngine,
    'my-router',
    None,
    '',  # contextEngineId, contextName
    [
        rfc1902.ObjectType(rfc1902.ObjectIdentity(
            'iso.org.dod')).resolveWithMib(mibViewController),
        rfc1902.ObjectType(rfc1902.ObjectIdentity(
            'IF-MIB', 'ifMIB')).resolveWithMib(mibViewController)
    ],
    cbFun)

# Run I/O dispatcher which would send pending queries and process responses
snmpEngine.transportDispatcher.runDispatcher()
Exemplo n.º 21
0
def main():
    variation_module = None

    parser = argparse.ArgumentParser(description=DESCRIPTION)

    parser.add_argument(
        '-v', '--version', action='version',
        version=utils.TITLE)

    parser.add_argument(
        '--quiet', action='store_true',
        help='Do not print out informational messages')

    parser.add_argument(
        '--debug', choices=pysnmp_debug.flagMap,
        action='append', type=str, default=[],
        help='Enable one or more categories of SNMP debugging.')

    parser.add_argument(
        '--debug-asn1', choices=pyasn1_debug.FLAG_MAP,
        action='append', type=str, default=[],
        help='Enable one or more categories of ASN.1 debugging.')

    parser.add_argument(
        '--logging-method', type=lambda x: x.split(':'),
        metavar='=<%s[:args]>]' % '|'.join(log.METHODS_MAP),
        default='stderr', help='Logging method.')

    parser.add_argument(
        '--log-level', choices=log.LEVELS_MAP,
        type=str, default='info', help='Logging level.')

    v1arch_group = parser.add_argument_group('SNMPv1/v2c parameters')

    v1arch_group.add_argument(
        '--protocol-version', choices=['1', '2c'],
        default='2c', help='SNMPv1/v2c protocol version')

    v1arch_group.add_argument(
        '--community', type=str, default='public',
        help='SNMP community name')

    v3arch_group = parser.add_argument_group('SNMPv3 parameters')

    v3arch_group.add_argument(
        '--v3-user', metavar='<STRING>',
        type=functools.partial(_parse_sized_string, min_length=1),
        help='SNMPv3 USM user (security) name')

    v3arch_group.add_argument(
        '--v3-auth-key', type=_parse_sized_string,
        help='SNMPv3 USM authentication key (must be > 8 chars)')

    v3arch_group.add_argument(
        '--v3-auth-proto', choices=AUTH_PROTOCOLS,
        type=lambda x: x.upper(), default='NONE',
        help='SNMPv3 USM authentication protocol')

    v3arch_group.add_argument(
        '--v3-priv-key', type=_parse_sized_string,
        help='SNMPv3 USM privacy (encryption) key (must be > 8 chars)')

    v3arch_group.add_argument(
        '--v3-priv-proto', choices=PRIV_PROTOCOLS,
        type=lambda x: x.upper(), default='NONE',
        help='SNMPv3 USM privacy (encryption) protocol')

    v3arch_group.add_argument(
        '--v3-context-engine-id',
        type=lambda x: univ.OctetString(hexValue=x[2:]),
        help='SNMPv3 context engine ID')

    v3arch_group.add_argument(
        '--v3-context-name', type=str, default='',
        help='SNMPv3 context engine ID')

    parser.add_argument(
        '--use-getbulk', action='store_true',
        help='Use SNMP GETBULK PDU for mass SNMP managed objects retrieval')

    parser.add_argument(
        '--getbulk-repetitions', type=int, default=25,
        help='Use SNMP GETBULK PDU for mass SNMP managed objects retrieval')

    endpoint_group = parser.add_mutually_exclusive_group(required=True)

    endpoint_group.add_argument(
        '--agent-udpv4-endpoint', type=endpoints.parse_endpoint,
        metavar='<[X.X.X.X]:NNNNN>',
        help='SNMP agent UDP/IPv4 address to pull simulation data '
             'from (name:port)')

    endpoint_group.add_argument(
        '--agent-udpv6-endpoint',
        type=functools.partial(endpoints.parse_endpoint, ipv6=True),
        metavar='<[X:X:..X]:NNNNN>',
        help='SNMP agent UDP/IPv6 address to pull simulation data '
             'from ([name]:port)')

    parser.add_argument(
        '--timeout', type=int, default=3,
        help='SNMP command response timeout (in seconds)')

    parser.add_argument(
        '--retries', type=int, default=3,
        help='SNMP command retries')

    parser.add_argument(
        '--start-object', metavar='<MIB::Object|OID>', type=_parse_mib_object,
        default=univ.ObjectIdentifier('1.3.6'),
        help='Drop all simulation data records prior to this OID specified '
             'as MIB object (MIB::Object) or OID (1.3.6.)')

    parser.add_argument(
        '--stop-object', metavar='<MIB::Object|OID>',
        type=functools.partial(_parse_mib_object, last=True),
        help='Drop all simulation data records after this OID specified '
             'as MIB object (MIB::Object) or OID (1.3.6.)')

    parser.add_argument(
        '--mib-source', dest='mib_sources', metavar='<URI|PATH>',
        action='append', type=str,
        default=['http://mibs.snmplabs.com/asn1/@mib@'],
        help='One or more URIs pointing to a collection of ASN.1 MIB files.'
             'Optional "@mib@" token gets replaced with desired MIB module '
             'name during MIB search.')

    parser.add_argument(
        '--destination-record-type', choices=variation.RECORD_TYPES,
        default='snmprec',
        help='Produce simulation data with record of this type')

    parser.add_argument(
        '--output-file', metavar='<FILE>', type=str,
        help='SNMP simulation data file to write records to')

    parser.add_argument(
        '--continue-on-errors', metavar='<tolerance-level>',
        type=int, default=0,
        help='Keep on pulling SNMP data even if intermittent errors occur')

    variation_group = parser.add_argument_group(
        'Simulation data variation options')

    parser.add_argument(
        '--variation-modules-dir', action='append', type=str,
        help='Search variation module by this path')

    variation_group.add_argument(
        '--variation-module', type=str,
        help='Pass gathered simulation data through this variation module')

    variation_group.add_argument(
        '--variation-module-options', type=str, default='',
        help='Variation module options')

    args = parser.parse_args()

    if args.debug:
        pysnmp_debug.setLogger(pysnmp_debug.Debug(*args.debug))

    if args.debug_asn1:
        pyasn1_debug.setLogger(pyasn1_debug.Debug(*args.debug_asn1))

    if args.output_file:
        ext = os.path.extsep
        ext += variation.RECORD_TYPES[args.destination_record_type].ext

        if not args.output_file.endswith(ext):
            args.output_file += ext

        record = variation.RECORD_TYPES[args.destination_record_type]
        args.output_file = record.open(args.output_file, 'wb')

    else:
        args.output_file = sys.stdout

        if sys.version_info >= (3, 0, 0):
            # binary mode write
            args.output_file = sys.stdout.buffer

        elif sys.platform == "win32":
            import msvcrt

            msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)

    # Catch missing params

    if args.protocol_version == '3':
        if not args.v3_user:
            sys.stderr.write('ERROR: --v3-user is missing\r\n')
            parser.print_usage(sys.stderr)
            return 1

        if args.v3_priv_key and not args.v3_auth_key:
            sys.stderr.write('ERROR: --v3-auth-key is missing\r\n')
            parser.print_usage(sys.stderr)
            return 1

        if AUTH_PROTOCOLS[args.v3_auth_proto] == config.usmNoAuthProtocol:
            if args.v3_auth_key:
                args.v3_auth_proto = 'MD5'

        else:
            if not args.v3_auth_key:
                sys.stderr.write('ERROR: --v3-auth-key is missing\r\n')
                parser.print_usage(sys.stderr)
                return 1

        if PRIV_PROTOCOLS[args.v3_priv_proto] == config.usmNoPrivProtocol:
            if args.v3_priv_key:
                args.v3_priv_proto = 'DES'

        else:
            if not args.v3_priv_key:
                sys.stderr.write('ERROR: --v3-priv-key is missing\r\n')
                parser.print_usage(sys.stderr)
                return 1

    proc_name = os.path.basename(sys.argv[0])

    try:
        log.set_logger(proc_name, *args.logging_method, force=True)

        if args.log_level:
            log.set_level(args.log_level)

    except error.SnmpsimError as exc:
        sys.stderr.write('%s\r\n' % exc)
        parser.print_usage(sys.stderr)
        return 1

    if args.use_getbulk and args.protocol_version == '1':
        log.info('will be using GETNEXT with SNMPv1!')
        args.use_getbulk = False

    # Load variation module

    if args.variation_module:

        for variation_modules_dir in (
                args.variation_modules_dir or confdir.variation):
            log.info(
                'Scanning "%s" directory for variation '
                'modules...' % variation_modules_dir)

            if not os.path.exists(variation_modules_dir):
                log.info('Directory "%s" does not exist' % variation_modules_dir)
                continue

            mod = os.path.join(variation_modules_dir, args.variation_module + '.py')
            if not os.path.exists(mod):
                log.info('Variation module "%s" not found' % mod)
                continue

            ctx = {'path': mod, 'moduleContext': {}}

            try:
                with open(mod) as fl:
                    exec (compile(fl.read(), mod, 'exec'), ctx)

            except Exception as exc:
                log.error('Variation module "%s" execution failure: '
                          '%s' % (mod, exc))
                return 1

            variation_module = ctx
            log.info('Variation module "%s" loaded' % args.variation_module)
            break

        else:
            log.error('variation module "%s" not found' % args.variation_module)
            return 1

    # SNMP configuration

    snmp_engine = engine.SnmpEngine()

    if args.protocol_version == '3':

        if args.v3_priv_key is None and args.v3_auth_key is None:
            secLevel = 'noAuthNoPriv'

        elif args.v3_priv_key is None:
            secLevel = 'authNoPriv'

        else:
            secLevel = 'authPriv'

        config.addV3User(
            snmp_engine, args.v3_user,
            AUTH_PROTOCOLS[args.v3_auth_proto], args.v3_auth_key,
            PRIV_PROTOCOLS[args.v3_priv_proto], args.v3_priv_key)

        log.info(
            'SNMP version 3, Context EngineID: %s Context name: %s, SecurityName: %s, '
            'SecurityLevel: %s, Authentication key/protocol: %s/%s, Encryption '
            '(privacy) key/protocol: '
            '%s/%s' % (
                args.v3_context_engine_id and args.v3_context_engine_id.prettyPrint() or '<default>',
                args.v3_context_name and args.v3_context_name.prettyPrint() or '<default>', args.v3_user,
                secLevel, args.v3_auth_key is None and '<NONE>' or args.v3_auth_key,
                args.v3_auth_proto,
                args.v3_priv_key is None and '<NONE>' or args.v3_priv_key, args.v3_priv_proto))

    else:

        args.v3_user = '******'
        secLevel = 'noAuthNoPriv'

        config.addV1System(snmp_engine, args.v3_user, args.community)

        log.info(
            'SNMP version %s, Community name: '
            '%s' % (args.protocol_version, args.community))

    config.addTargetParams(
        snmp_engine, 'pms', args.v3_user, secLevel, VERSION_MAP[args.protocol_version])

    if args.agent_udpv6_endpoint:
        config.addSocketTransport(
            snmp_engine, udp6.domainName,
            udp6.Udp6SocketTransport().openClientMode())

        config.addTargetAddr(
            snmp_engine, 'tgt', udp6.domainName, args.agent_udpv6_endpoint, 'pms',
            args.timeout * 100, args.retries)

        log.info('Querying UDP/IPv6 agent at [%s]:%s' % args.agent_udpv6_endpoint)

    elif args.agent_udpv4_endpoint:
        config.addSocketTransport(
            snmp_engine, udp.domainName,
            udp.UdpSocketTransport().openClientMode())

        config.addTargetAddr(
            snmp_engine, 'tgt', udp.domainName, args.agent_udpv4_endpoint, 'pms',
            args.timeout * 100, args.retries)

        log.info('Querying UDP/IPv4 agent at %s:%s' % args.agent_udpv4_endpoint)

    log.info('Agent response timeout: %d secs, retries: '
             '%s' % (args.timeout, args.retries))

    if (isinstance(args.start_object, ObjectIdentity) or
            isinstance(args.stop_object, ObjectIdentity)):

        compiler.addMibCompiler(
            snmp_engine.getMibBuilder(), sources=args.mib_sources)

        mib_view_controller = view.MibViewController(
            snmp_engine.getMibBuilder())

        try:
            if isinstance(args.start_object, ObjectIdentity):
                args.start_object.resolveWithMib(mib_view_controller)

            if isinstance(args.stop_object, ObjectIdentity):
                args.stop_object.resolveWithMib(mib_view_controller)

        except PySnmpError as exc:
            sys.stderr.write('ERROR: %s\r\n' % exc)
            return 1

    # Variation module initialization

    if variation_module:
        log.info('Initializing variation module...')

        for x in ('init', 'record', 'shutdown'):
            if x not in variation_module:
                log.error('missing "%s" handler at variation module '
                          '"%s"' % (x, args.variation_module))
                return 1

        try:
            handler = variation_module['init']

            handler(snmpEngine=snmp_engine, options=args.variation_module_options,
                    mode='recording', startOID=args.start_object,
                    stopOID=args.stop_object)

        except Exception as exc:
            log.error(
                'Variation module "%s" initialization FAILED: '
                '%s' % (args.variation_module, exc))

        else:
            log.info(
                'Variation module "%s" initialization OK' % args.variation_module)

    data_file_handler = variation.RECORD_TYPES[args.destination_record_type]


    # SNMP worker

    def cbFun(snmp_engine, send_request_handle, error_indication,
              error_status, error_index, var_bind_table, cb_ctx):

        if error_indication and not cb_ctx['retries']:
            cb_ctx['errors'] += 1
            log.error('SNMP Engine error: %s' % error_indication)
            return

        # SNMPv1 response may contain noSuchName error *and* SNMPv2c exception,
        # so we ignore noSuchName error here
        if error_status and error_status != 2 or error_indication:
            log.error(
                'Remote SNMP error %s' % (
                        error_indication or error_status.prettyPrint()))

            if cb_ctx['retries']:
                try:
                    next_oid = var_bind_table[-1][0][0]

                except IndexError:
                    next_oid = cb_ctx['lastOID']

                else:
                    log.error('Failed OID: %s' % next_oid)

                # fuzzy logic of walking a broken OID
                if len(next_oid) < 4:
                    pass

                elif (args.continue_on_errors - cb_ctx['retries']) * 10 / args.continue_on_errors > 5:
                    next_oid = next_oid[:-2] + (next_oid[-2] + 1,)

                elif next_oid[-1]:
                    next_oid = next_oid[:-1] + (next_oid[-1] + 1,)

                else:
                    next_oid = next_oid[:-2] + (next_oid[-2] + 1, 0)

                cb_ctx['retries'] -= 1
                cb_ctx['lastOID'] = next_oid

                log.info(
                    'Retrying with OID %s (%s retries left)'
                    '...' % (next_oid, cb_ctx['retries']))

                # initiate another SNMP walk iteration
                if args.use_getbulk:
                    cmd_gen.sendVarBinds(
                        snmp_engine,
                        'tgt',
                        args.v3_context_engine_id, args.v3_context_name,
                        0, args.getbulk_repetitions,
                        [(next_oid, None)],
                        cbFun, cb_ctx)

                else:
                    cmd_gen.sendVarBinds(
                        snmp_engine,
                        'tgt',
                        args.v3_context_engine_id, args.v3_context_name,
                        [(next_oid, None)],
                        cbFun, cb_ctx)

            cb_ctx['errors'] += 1

            return

        if args.continue_on_errors != cb_ctx['retries']:
            cb_ctx['retries'] += 1

        if var_bind_table and var_bind_table[-1] and var_bind_table[-1][0]:
            cb_ctx['lastOID'] = var_bind_table[-1][0][0]

        stop_flag = False

        # Walk var-binds
        for var_bind_row in var_bind_table:
            for oid, value in var_bind_row:

                # EOM
                if args.stop_object and oid >= args.stop_object:
                    stop_flag = True  # stop on out of range condition

                elif (value is None or
                          value.tagSet in (rfc1905.NoSuchObject.tagSet,
                                           rfc1905.NoSuchInstance.tagSet,
                                           rfc1905.EndOfMibView.tagSet)):
                    stop_flag = True

                # remove value enumeration
                if value.tagSet == rfc1902.Integer32.tagSet:
                    value = rfc1902.Integer32(value)

                if value.tagSet == rfc1902.Unsigned32.tagSet:
                    value = rfc1902.Unsigned32(value)

                if value.tagSet == rfc1902.Bits.tagSet:
                    value = rfc1902.OctetString(value)

                # Build .snmprec record

                context = {
                    'origOid': oid,
                    'origValue': value,
                    'count': cb_ctx['count'],
                    'total': cb_ctx['total'],
                    'iteration': cb_ctx['iteration'],
                    'reqTime': cb_ctx['reqTime'],
                    'args.start_object': args.start_object,
                    'stopOID': args.stop_object,
                    'stopFlag': stop_flag,
                    'variationModule': variation_module
                }

                try:
                    line = data_file_handler.format(oid, value, **context)

                except error.MoreDataNotification as exc:
                    cb_ctx['count'] = 0
                    cb_ctx['iteration'] += 1

                    more_data_notification = exc

                    if 'period' in more_data_notification:
                        log.info(
                            '%s OIDs dumped, waiting %.2f sec(s)'
                            '...' % (cb_ctx['total'],
                                     more_data_notification['period']))

                        time.sleep(more_data_notification['period'])

                    # initiate another SNMP walk iteration
                    if args.use_getbulk:
                        cmd_gen.sendVarBinds(
                            snmp_engine,
                            'tgt',
                            args.v3_context_engine_id, args.v3_context_name,
                            0, args.getbulk_repetitions,
                            [(args.start_object, None)],
                            cbFun, cb_ctx)

                    else:
                        cmd_gen.sendVarBinds(
                            snmp_engine,
                            'tgt',
                            args.v3_context_engine_id, args.v3_context_name,
                            [(args.start_object, None)],
                            cbFun, cb_ctx)

                    stop_flag = True  # stop current iteration

                except error.NoDataNotification:
                    pass

                except error.SnmpsimError as exc:
                    log.error(exc)
                    continue

                else:
                    args.output_file.write(line)

                    cb_ctx['count'] += 1
                    cb_ctx['total'] += 1

                    if cb_ctx['count'] % 100 == 0:
                        log.info('OIDs dumped: %s/%s' % (
                            cb_ctx['iteration'], cb_ctx['count']))

        # Next request time
        cb_ctx['reqTime'] = time.time()

        # Continue walking
        return not stop_flag

    cb_ctx = {
        'total': 0,
        'count': 0,
        'errors': 0,
        'iteration': 0,
        'reqTime': time.time(),
        'retries': args.continue_on_errors,
        'lastOID': args.start_object
    }

    if args.use_getbulk:
        cmd_gen = cmdgen.BulkCommandGenerator()

        cmd_gen.sendVarBinds(
            snmp_engine,
            'tgt',
            args.v3_context_engine_id, args.v3_context_name,
            0, args.getbulk_repetitions,
            [(args.start_object, rfc1902.Null(''))],
            cbFun, cb_ctx)

    else:
        cmd_gen = cmdgen.NextCommandGenerator()

        cmd_gen.sendVarBinds(
            snmp_engine,
            'tgt',
            args.v3_context_engine_id, args.v3_context_name,
            [(args.start_object, rfc1902.Null(''))],
            cbFun, cb_ctx)

    log.info(
        'Sending initial %s request for %s (stop at %s)'
        '....' % (args.use_getbulk and 'GETBULK' or 'GETNEXT',
                  args.start_object, args.stop_object or '<end-of-mib>'))

    started = time.time()

    try:
        snmp_engine.transportDispatcher.runDispatcher()

    except KeyboardInterrupt:
        log.info('Shutting down process...')

    finally:
        if variation_module:
            log.info('Shutting down variation module '
                     '%s...' % args.variation_module)

            try:
                handler = variation_module['shutdown']

                handler(snmpEngine=snmp_engine,
                        options=args.variation_module_options,
                        mode='recording')

            except Exception as exc:
                log.error(
                    'Variation module %s shutdown FAILED: '
                    '%s' % (args.variation_module, exc))

            else:
                log.info(
                    'Variation module %s shutdown OK' % args.variation_module)

        snmp_engine.transportDispatcher.closeDispatcher()

        started = time.time() - started

        cb_ctx['total'] += cb_ctx['count']

        log.info(
            'OIDs dumped: %s, elapsed: %.2f sec, rate: %.2f OIDs/sec, errors: '
            '%d' % (cb_ctx['total'], started,
                    started and cb_ctx['count'] // started or 0,
                    cb_ctx['errors']))

        args.output_file.flush()
        args.output_file.close()

        return cb_ctx.get('errors', 0) and 1 or 0
Exemplo n.º 22
0
                if syntax is None:
                    raise error.PySnmpError(
                        'Value type MIB lookup failed for %s' % repr(varName))
                varVal = syntax.clone(varVal)
            __varBinds.append((name + oid, varVal))
        return cmdgen.SetCommandGenerator().sendReq(self.snmpEngine, addrName,
                                                    __varBinds, cbFun, cbCtx)

    def asyncNextCmd(self, authData, transportTarget, varNames, (cbFun,
                                                                 cbCtx)):
        addrName, paramsName = self.cfgCmdGen(authData, transportTarget)
        varBinds = []
        for varName in varNames:
            name, oid = mibvar.mibNameToOid(self.mibViewController, varName)
            varBinds.append((name + oid, self._null))
        return cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, addrName,
                                                     varBinds, cbFun, cbCtx)

    def asyncBulkCmd(self, authData, transportTarget, nonRepeaters,
                     maxRepetitions, varNames, (cbFun, cbCtx)):
        addrName, paramsName = self.cfgCmdGen(authData, transportTarget)
        varBinds = []
        for varName in varNames:
            name, oid = mibvar.mibNameToOid(self.mibViewController, varName)
            varBinds.append((name + oid, self._null))
        return cmdgen.BulkCommandGenerator().sendReq(self.snmpEngine, addrName,
                                                     nonRepeaters,
                                                     maxRepetitions, varBinds,
                                                     cbFun, cbCtx)


class CommandGenerator(AsynCommandGenerator):
Exemplo n.º 23
0
def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
          errorIndex, varBindTable, cbCtx):
    if errorIndication:
        print(errorIndication)
        return
    if errorStatus:
        print('%s at %s' %
              (errorStatus.prettyPrint(),
               errorIndex and varBindTable[-1][int(errorIndex) - 1][0] or '?'))
        return  # stop on error
    for varBindRow in varBindTable:
        for oid, val in varBindRow:
            if initialOID.isPrefixOf(oid):
                print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
            else:
                return False  # signal dispatcher to stop
    return True  # signal dispatcher to continue


# Prepare initial request to be sent
cmdgen.NextCommandGenerator().sendVarBinds(
    snmpEngine,
    'my-router',
    None,
    '',  # contextEngineId, contextName
    [(initialOID, None)],
    cbFun)

# Run I/O dispatcher which would send pending queries and process responses
snmpEngine.transportDispatcher.runDispatcher()
Exemplo n.º 24
0
    # Apply configuration to SNMP entity
    main.generator((snmpEngine, ctx), ast)
    msgmod.generator((snmpEngine, ctx), ast)
    secmod.generator((snmpEngine, ctx), ast)    
    mibview.generator((snmpEngine, ctx), ast)
    target.generator((snmpEngine, ctx), ast)
    pdu.readPduGenerator((snmpEngine, ctx), ast)
    generator((snmpEngine, ctx), ast)
    
    ctx['myHeadVars'] = [ rfc1902.ObjectName(x[0]) for x in ctx['varBinds'] ]

    cmdgen.NextCommandGenerator().sendVarBinds(
        snmpEngine,
        ctx['addrName'],
        ctx.get('contextEngineId'), ctx.get('contextName', ''),
        ctx['varBinds'],
        cbFun, ctx
    )

    snmpEngine.transportDispatcher.runDispatcher()

except KeyboardInterrupt:
    sys.stderr.write('Shutting down...\n')

except error.PySnmpError:
    sys.stderr.write('Error: %s\n%s' % (sys.exc_info()[1], getUsage()))
    sys.exit(-1)

except Exception:
    sys.stderr.write('Process terminated: %s\n' % sys.exc_info()[1])
Exemplo n.º 25
0
class MyCmdGen(object):

    DEBUG = False

    ## @brief the constructor
    # @param self The object pointer
    # @returns None
    def __init__(self):
        self.snmpEngine = None

    ## @brief Set up the SNMP engine, user or system, address and socket
    # @param self The object pointer
    # @param agent Information about the agent to add
    # @param context context information (to add V1 system)
    # @param host Host address
    # @param port port number
    # @returns None
    # @todo support changes to context etc and make a new connection???
    def _setup(self, agent, context, host, port):
        # TODO support changes to context etc and make a new connection???
        if self.snmpEngine is None:
            self.snmpEngine = engine.SnmpEngine()
        else:
            return  # already setup

        if isinstance(agent, UsmUserData):
            config.addV3User(self.snmpEngine, agent.securityName,
                             agent.authProtocol, agent.authKey,
                             agent.privProtocol, agent.privKey)
            config.addTargetParams(self.snmpEngine, 'myParams',
                                   agent.securityName, agent.securityLevel)
        else:
            config.addV1System(self.snmpEngine, agent, context)
            config.addTargetParams(self.snmpEngine, 'myParams', agent,
                                   'noAuthNoPriv', 1)

        config.addTargetAddr(self.snmpEngine,
                             'myRouter',
                             config.snmpUDPDomain, (host, port),
                             'myParams',
                             timeout=900)
        config.addSocketTransport(self.snmpEngine, udp.domainName,
                                  udp.UdpSocketTransport().openClientMode())

    ## @brief call for pysnmp method for traps
    # @param port the port number to use
    # @param intWaitSec time to wait
    # @returns the trap collection
    def trapCmd(self, port, intWaitSec):

        ## @brief print/log trap data nicely
        # @param varBinds variable bindings (object ID and value)
        # @param transportAddress IP address to identify by
        # @param strFname file name to open
        # @returns none
        def printItNice(varBinds, transportAddress, strFname):

            fHandle = open(sys.path[0] + '//' + strFname, 'a')
            timeMilli = datetime.datetime.now().microsecond / 1000
            timeTrapTime = strftime("%Y-%b-%d %H:%M:%S.") + str(timeMilli)
            strPrintTxt = '\n\n%s :TRAP RECEIVED from %s: ' % (
                timeTrapTime, transportAddress[0])
            fHandle.write(strPrintTxt)
            if self.DEBUG:
                print strPrintTxt
            dicTrapData = {}
            dicTrapData['IP'] = transportAddress[0]
            for strOid, strVal in varBinds:
                strOid = strOid.prettyPrint()
                strVal = strVal.getComponent().getComponent().getComponent(
                ).prettyPrint()
                strPrintTxt = strOid + ' ' * (45 - len(strOid)) + strVal
                fHandle.write('\n' + strPrintTxt)
                if self.DEBUG:
                    print strPrintTxt
                dicTrapData[strOid] = strVal
            dicTrapCollection[timeTrapTime] = dicTrapData
            fHandle.close()

        ## @brief function handler timer
        # @param timeTick time between events (reference period)
        # @returns none
        def timeFun(timeTick):

            timeNewTime = datetime.datetime.now()
            timeDelta = timeNewTime - timeReference
            if int(timeDelta.seconds) >= intWaitSec:
                transportDispatcher.jobFinished(1)
                transportDispatcher.closeDispatcher()

        ## @brief function handler for data processing
        # @param transportDispatcher I/O dispatcher
        # @param transportDomain transport domain
        # @param transportAddress destination address
        # @param wholeMsg data to process
        # @returns the processed data
        def cbFun(transportDispatcher, transportDomain, transportAddress,
                  wholeMsg):

            strFname = 'Trap_' + str(
                transportAddress[0]) + '_' + str(port) + '.log'
            while wholeMsg:
                msgVer = int(api.decodeMessageVersion(wholeMsg))
                if api.protoModules.has_key(msgVer):
                    pMod = api.protoModules[msgVer]
                else:
                    print 'Unsupported SNMP version %s' % msgVer
                    return
                reqMsg, wholeMsg = decoder.decode(
                    wholeMsg,
                    asn1Spec=pMod.Message(),
                )
                reqPDU = pMod.apiMessage.getPDU(reqMsg)
                if reqPDU.isSameTypeWith(pMod.TrapPDU()):
                    if msgVer == api.protoVersion1:
                        varBinds = pMod.apiTrapPDU.getVarBindList(reqPDU)
                    else:
                        varBinds = pMod.apiPDU.getVarBindList(reqPDU)
                    printItNice(varBinds, transportAddress, strFname)

            return wholeMsg

        dicTrapCollection = {}
        timeReference = datetime.datetime.now()
        transportDispatcher = AsynsockDispatcher()
        transportDispatcher.timeout = 0.3
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openServerMode(('0.0.0.0', port)))
        transportDispatcher.registerRecvCbFun(cbFun)
        transportDispatcher.registerTimerCbFun(timeFun)
        transportDispatcher.jobStarted(1)
        transportDispatcher.runDispatcher()
        return dicTrapCollection

    ## @brief  Prepare SNMP get request
    # @param self The object pointer
    # @param agent Information about the agent to add
    # @param context context information
    # @param host Host address
    # @param port port number
    # @param *varNames names of variables
    # @returns data from the callback function (application state)
    def getCmd(self, agent, context, host, port, *varNames):
        self._setup(agent, context, host, port)

        ## @brief call back function
        # @param sendRequestHandle
        # @param errorIndication indicates error
        # @param errorStatus status of error
        # @param errorIndex index of error
        # @param varBinds variable bindings (sequence)
        # @param cbCtx application state
        # @returns cbCtx application state
        def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
                  varBinds, cbCtx):
            cbCtx['errorIndication'] = errorIndication
            cbCtx['errorStatus'] = errorStatus
            cbCtx['errorIndex'] = errorIndex
            cbCtx['varBinds'] = varBinds

        # Used to pass data from callback function
        cbCtx = {}
        varBinds = []
        for varName in varNames:
            varBinds.append((varName, None))

        cmdgen.GetCommandGenerator().sendReq(self.snmpEngine, 'myRouter',
                                             varBinds, cbFun, cbCtx)
        self.snmpEngine.transportDispatcher.runDispatcher()

        return (cbCtx['errorIndication'], cbCtx['errorStatus'],
                cbCtx['errorIndex'], cbCtx['varBinds'])

    ## @brief Prepare SNMP set request
    # @param self The object pointer
    # @param agent Information about the agent to add
    # @param context context information
    # @param host Host address
    # @param port port number
    # @param *varBinds variable bindings (sequence)
    # @returns data from the callback function (application state)
    def setCmd(self, agent, context, host, port, *varBinds):
        self._setup(agent, context, host, port)

        ## @brief call back function
        # @param sendRequestHandle
        # @param errorIndication indicates error
        # @param errorStatus status of error
        # @param errorIndex index of error
        # @param varBinds variable bindings (sequence)
        # @param cbCtx application state
        # @returns cbCtx application state
        def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
                  varBinds, cbCtx):
            cbCtx['errorIndication'] = errorIndication
            cbCtx['errorStatus'] = errorStatus
            cbCtx['errorIndex'] = errorIndex
            cbCtx['varBinds'] = varBinds

        cbCtx = {}

        __varBinds = []
        for varName, varVal in varBinds:
            __varBinds.append((varName, varVal))

        cmdgen.SetCommandGenerator().sendReq(self.snmpEngine, 'myRouter',
                                             __varBinds, cbFun, cbCtx)

        self.snmpEngine.transportDispatcher.runDispatcher()
        #the 'getColumn' SNMP command
        return (cbCtx['errorIndication'], cbCtx['errorStatus'],
                cbCtx['errorIndex'], cbCtx['varBinds'])

    ## @brief wraps the SNMP get request for columns
    # @param self The object pointer
    # @param agent Information about the agent to add
    # @param context context information
    # @param host Host address
    # @param port port number
    # @param *varNames variable names
    # @returns data from the callback function (application state)
    def getColumn(self, agent, context, host, port, *varNames):
        self._setup(agent, context, host, port)

        ## @brief call back function
        # @param sendRequestHandle
        # @param errorIndication indicates error
        # @param errorStatus status of error
        # @param errorIndex index of error
        # @param varBindTable table of variable bindings
        # @param varBindHead variable bindings table header
        # @param varBindTotalTable table of variable bindings total
        # @param cbCtx application state
        # @returns cbCtx application state
        def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
                  varBindTable, (varBindHead, varBindTotalTable, cbCtx)):
            if errorIndication or errorStatus:
                cbCtx['errorIndication'] = errorIndication
                cbCtx['errorStatus'] = errorStatus
                cbCtx['errorIndex'] = errorIndex
                cbCtx['varBindTable'] = varBindTotalTable
                return
            else:
                varBindTableRow = varBindTable[-1]
                for idx in range(len(varBindTableRow)):
                    name, val = varBindTableRow[idx]
                    # XXX extra rows
                    if val is not None and varBindHead[idx].isPrefixOf(name):
                        break
                else:
                    cbCtx['errorIndication'] = errorIndication
                    cbCtx['errorStatus'] = errorStatus
                    cbCtx['errorIndex'] = errorIndex
                    cbCtx['varBindTable'] = varBindTotalTable
                    return
                varBindTotalTable.extend(varBindTable)

            return 1  # continue walking

        cbCtx = {}
        varBinds = []
        for varName in varNames:
            varBinds.append((varName, None))
        varBindHead = map(lambda (x): univ.ObjectIdentifier(x), varNames)

        cmdgen.NextCommandGenerator().sendReq(self.snmpEngine, 'myRouter',
                                              varBinds, cbFun,
                                              (varBindHead, [], cbCtx))

        self.snmpEngine.transportDispatcher.runDispatcher()

        return (cbCtx['errorIndication'], cbCtx['errorStatus'],
                cbCtx['errorIndex'], cbCtx['varBindTable'])