コード例 #1
0
    def sendTrap(self, notification, trap_name, var_binds):
        ntfOrg = ntforg.NotificationOriginator(self._snmpContext)

        errorIndication = ntfOrg.sendNotification(
            self._snmpEngine,
            'test-notification',
            ( 'QUMULO-MIB', trap_name ), var_binds)
コード例 #2
0
 def sendTrap(self):
     print("Sending trap")
     ntfOrg = ntforg.NotificationOriginator(self._snmpContext)
     errorIndication = ntfOrg.sendNotification(self._snmpEngine,
                                               'test-notification',
                                               ('SABIH-MIB', 'testTrap'),
                                               ())
コード例 #3
0
    def sendNotification(self,
                         authData,
                         transportTarget,
                         notifyType,
                         notificationType,
                         varBinds=(),
                         cbInfo=(None, None),
                         lookupNames=False,
                         lookupValues=False,
                         contextName=null):
        def __cbFun(sendRequestHandle, errorIndication, errorStatus,
                    errorIndex, varBinds, cbCtx):
            lookupNames, lookupValues, cbFun, cbCtx = cbCtx
            if cbFun is None:  # user callback not supplied
                return
            try:
                # we need to pass response PDU information to user for INFORMs
                return cbFun(
                    sendRequestHandle, errorIndication, errorStatus,
                    errorIndex,
                    self.unmakeVarBinds(varBinds, lookupNames,
                                        lookupValues), cbCtx)
            except TypeError:
                # a backward compatible way of calling user function
                return cbFun(sendRequestHandle, errorIndication, cbCtx)

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

        (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.cfgNtfOrg(authData, transportTarget, notifyType)
        if isinstance(notificationType, MibVariable):
            notificationType = notificationType.resolveWithMib(
                self.mibViewController, oidOnly=True)
        elif isinstance(notificationType[0], tuple):  # legacy
            notificationType = MibVariable(
                notificationType[0][0], notificationType[0][1],
                *notificationType[1:]).resolveWithMib(self.mibViewController)

        return ntforg.NotificationOriginator(
            self.snmpContext).sendNotification(
                self.snmpEngine, notifyName, notificationType,
                self.makeVarBinds(varBinds), __cbFun,
                (lookupNames, lookupValues, cbFun, cbCtx), contextName)
コード例 #4
0
ファイル: ntforg.py プロジェクト: ithek/pysnmp
    def sendNotification(self,
                         authData,
                         transportTarget,
                         notifyType,
                         notificationType=None,
                         varBinds=None,
                         cbInfo=(None, None)):
        (cbFun, cbCtx) = cbInfo
        notifyName = self.cfgNtfOrg(authData, transportTarget, notifyType)
        if notificationType is not None:
            if isinstance(notificationType, MibVariable):
                notificationType = notificationType.resolveWithMib(
                    self.mibViewController, oidOnly=True)
            elif isinstance(notificationType[0], tuple):  # legacy
                notificationType = MibVariable(
                    notificationType[0][0], notificationType[0][1],
                    *notificationType[1:]).resolveWithMib(
                        self.mibViewController)
        if varBinds:
            __varBinds = []
            for varName, varVal in varBinds:
                if isinstance(varName, MibVariable):
                    varName.resolveWithMib(self.mibViewController)
                    if not isinstance(varVal, base.AbstractSimpleAsn1Item):
                        varVal = varName.getMibNode().getSyntax().clone(varVal)
                elif isinstance(varName[0], tuple):  # legacy
                    varName = MibVariable(varName[0][0], varName[0][1],
                                          *varName[1:]).resolveWithMib(
                                              self.mibViewController)
                    if not isinstance(varVal, base.AbstractSimpleAsn1Item):
                        varVal = varName.getMibNode().getSyntax().clone(varVal)
                else:
                    if isinstance(varVal, base.AbstractSimpleAsn1Item):
                        varName = MibVariable(varName).resolveWithMib(
                            self.mibViewController, oidOnly=True)
                    else:
                        varName = MibVariable(varName).resolveWithMib(
                            self.mibViewController)
                        varVal = varName.getMibNode().getSyntax().clone(varVal)

                __varBinds.append((varName, varVal))
        else:
            __varBinds = None

        return ntforg.NotificationOriginator(
            self.snmpContext).sendNotification(self.snmpEngine, notifyName,
                                               notificationType, __varBinds,
                                               cbFun, cbCtx)
コード例 #5
0
    def sendNotification(self,
                         snmpEngine,
                         snmpContext,
                         authData,
                         transportTarget,
                         notifyType,
                         notificationType,
                         varBinds=(),
                         cbInfo=(None, None),
                         lookupNames=False,
                         lookupValues=False,
                         contextName=null):
        def __cbFun(sendRequestHandle, errorIndication, errorStatus,
                    errorIndex, varBinds, cbCtx):
            lookupNames, lookupValues, cbFun, cbCtx = cbCtx
            return cbFun and cbFun(
                sendRequestHandle, errorIndication, errorStatus, errorIndex,
                self.unmakeVarBinds(snmpEngine, varBinds, lookupNames,
                                    lookupValues), cbCtx)

        cache = self._getCmdCache(snmpEngine)

        (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.cfgNtfOrg(snmpEngine, authData, transportTarget,
                                    notifyType)
        if isinstance(notificationType, MibVariable):
            notificationType = notificationType.resolveWithMib(
                cache['mibViewController'], oidOnly=True)

        return ntforg.NotificationOriginator(snmpContext).sendNotification(
            snmpEngine, notifyName, notificationType,
            self.makeVarBinds(snmpEngine, varBinds), __cbFun,
            (lookupNames, lookupValues, cbFun, cbCtx), contextName)
コード例 #6
0
def sendNotification(snmpEngine,
                     authData,
                     transportTarget,
                     contextData,
                     notifyType,
                     varBinds,
                     cbFun=None,
                     cbCtx=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.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.

    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
    ----------------
    cbFun : callable
        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 : object
        user-supplied object passing additional parameters to/from
        `cbFun`.
    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.hlapi.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.hlapi.asyncore import *
    >>>
    >>> snmpEngine = SnmpEngine()
    >>> sendNotification(
    ...     snmpEngine,
    ...     CommunityData('public'),
    ...     UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...     ContextData(),
    ...     'trap',
    ...     NotificationType(ObjectIdentity('SNMPv2-MIB', 'coldStart')),
    ... )
    >>> snmpEngine.transportDispatcher.runDispatcher()
    >>>

    """

    # noinspection PyShadowingNames
    def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
                errorIndex, varBinds, cbCtx):
        lookupMib, cbFun, cbCtx = cbCtx
        return cbFun and cbFun(
            snmpEngine, sendRequestHandle, errorIndication, errorStatus,
            errorIndex,
            vbProcessor.unmakeVarBinds(snmpEngine, varBinds, lookupMib), cbCtx)

    notifyName = lcd.configure(snmpEngine, authData, transportTarget,
                               notifyType)

    return ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine, notifyName,
        contextData.contextEngineId, contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine,
                                 varBinds), __cbFun, (lookupMib, cbFun, cbCtx))
コード例 #7
0
ファイル: ntforg.py プロジェクト: jiuzhuaxiong/pysnmp
def sendNotification(snmpEngine, authData, transportTarget, contextData,
                     notifyType, *varBinds, **options):
    """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.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.

    notifyType : str
        Indicates type of notification to be sent. Recognized literal
        values are *trap* or *inform*.

    \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType` or :py:class:`~pysnmp.smi.rfc1902.NotificationType`
        One or more objects representing MIB variables to place
        into SNMP notification. It could be tuples of OID-values
        or :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
        of :py:class:`~pysnmp.smi.rfc1902.NotificationType` objects.

        SNMP Notification PDU includes some housekeeping items that
        are required for SNMP to function.

        Agent information:

        * SNMPv2-MIB::sysUpTime.0 = <agent uptime>
        * SNMPv2-SMI::snmpTrapOID.0 = {SNMPv2-MIB::coldStart, ...}

        Applicable to SNMP v1 TRAP:

        * SNMP-COMMUNITY-MIB::snmpTrapAddress.0 = <agent-IP>
        * SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 = <snmp-community-name>
        * SNMP-COMMUNITY-MIB::snmpTrapEnterprise.0 = <enterprise-OID>

        .. note::

           Unless user passes some of these variable-bindings, `.sendNotification()`
           call will fill in the missing items.

        User variable-bindings:

        * SNMPv2-SMI::NOTIFICATION-TYPE
        * SNMPv2-SMI::OBJECT-TYPE

        .. note::

           The :py:class:`~pysnmp.smi.rfc1902.NotificationType` object ensures
           properly formed SNMP notification (to comply MIB definition). If you
           build notification PDU out of :py:class:`~pysnmp.smi.rfc1902.ObjectType`
           objects or simple tuples of OID-value objects, it is your responsibility
           to provide well-formed notificaton payload.

    Other Parameters
    ----------------
    \*\*options:

        * lookupMib: bool
            `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
            to *INFORM* notification or error to user at a later point of
            time. The `cbFun` callable is never invoked for *TRAP* notifications.
        * cbCtx: object
            user-supplied object passing additional parameters to/from
            `cbFun`

    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 *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.hlapi.asyncore import *
    >>>
    >>> snmpEngine = SnmpEngine()
    >>> sendNotification(
    ...     snmpEngine,
    ...     CommunityData('public'),
    ...     UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...     ContextData(),
    ...     'trap',
    ...     NotificationType(ObjectIdentity('SNMPv2-MIB', 'coldStart')),
    ... )
    >>> snmpEngine.transportDispatcher.runDispatcher()
    >>>

    """

    # noinspection PyShadowingNames
    def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
                errorIndex, varBinds, cbCtx):
        lookupMib, cbFun, cbCtx = cbCtx
        return cbFun and cbFun(
            snmpEngine, sendRequestHandle, errorIndication, errorStatus,
            errorIndex,
            vbProcessor.unmakeVarBinds(snmpEngine.cache, varBinds,
                                       lookupMib), cbCtx)

    notifyName = lcd.configure(snmpEngine, authData, transportTarget,
                               notifyType, contextData.contextName)

    return ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine, notifyName, contextData.contextEngineId,
        contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine.cache, varBinds), __cbFun,
        (options.get('lookupMib',
                     True), options.get('cbFun'), options.get('cbCtx')))
コード例 #8
0
ファイル: ntforg.py プロジェクト: rlaneyjr/cheaters
config.addContext(snmpEngine, '')
config.addVacmUser(snmpEngine, 1, 'test-agent', 'noAuthNoPriv',
                   (), (), (1,3,6)) # v1
config.addVacmUser(snmpEngine, 2, 'test-agent', 'noAuthNoPriv',
                   (), (), (1,3,6)) # v2c
config.addVacmUser(snmpEngine, 3, 'test-user', 'authPriv',
                   (), (), (1,3,6)) # v3

# SNMP context
snmpContext = context.SnmpContext(snmpEngine)

def cbFun(snmpEngine, errorIndication, cbCtx):
    if errorIndication:
        print errorIndication
        
errorIndication = ntforg.NotificationOriginator(snmpContext).sendNotification(
    snmpEngine,
    # Notification targets
    'myNotifyName',
    # Trap OID (SNMPv2-MIB::coldStart)
    (1,3,6,1,6,3,1,1,5,1),
    # ((oid, value), ... )
    (((1,3,6,1,2,1,1,5), v2c.OctetString('Example Notificator')),),
    cbFun
    )

if errorIndication:
    print errorIndication
else:
    snmpEngine.transportDispatcher.runDispatcher()
コード例 #9
0
# Specify what kind of notification should be sent (TRAP or INFORM),
# to what targets (chosen by tag) and what filter should apply to
# the set of targets (selected by tag)
config.addNotificationTarget(snmpEngine, 'my-notification', 'my-filter',
                             'all-my-managers', 'inform')

# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel
# and SecurityName
config.addContext(snmpEngine, '')
config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1, 3, 6))

# *** SNMP engine configuration is complete by this line ***

# Create Notification Originator App instance.
ntfOrg = ntforg.NotificationOriginator()


# Error/confirmation receiver
# noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal,PyUnusedLocal,PyUnusedLocal
def cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
          errorIndex, varBinds, cbCtx):
    print('Notification %s, status - %s' %
          (sendRequestHandle, errorIndication and errorIndication
           or 'delivered'))


# Build and submit notification message to dispatcher
sendRequestHandle = ntfOrg.sendVarBinds(
    snmpEngine,
    'my-notification',  # notification targets
コード例 #10
0
def sendTheTrap():
    uptime = getUptime()
    # Create SNMP engine instance with specific (and locally unique)
    # SnmpEngineId -- it must also be known to the receiving party
    # and configured at its VACM users table.
    snmpEngine = engine.SnmpEngine(snmpEngineID=v2c.OctetString(
        hexValue='0102030405060708'))

    # Add USM user
    config.addV3User(snmpEngine, userConfig['DEFAULT']['SNMPUSER'],
                     config.usmHMAC128SHA224AuthProtocol,
                     userConfig['DEFAULT']['SNMPAUTH'],
                     config.usmAesCfb192Protocol,
                     userConfig['DEFAULT']['SNMPPRIV'])

    config.addTargetParams(snmpEngine, userConfig['DEFAULT']['SNMPAUTH'],
                           userConfig['DEFAULT']['SNMPUSER'], 'authPriv')

    # Setup transport endpoint and bind it with security settings yielding
    # a target name
    config.addTransport(snmpEngine, udp.domainName,
                        udp.UdpSocketTransport().openClientMode())

    config.addTargetAddr(snmpEngine,
                         'my-nms',
                         udp.domainName,
                         (userConfig['DEFAULT']['SNMPMANAGERIP'],
                          int(userConfig['DEFAULT']['SNMPMANAGERPORT'])),
                         userConfig['DEFAULT']['SNMPAUTH'],
                         tagList='all-my-managers')

    # Specify what kind of notification should be sent (TRAP or INFORM),
    # to what targets (chosen by tag) and what filter should apply to
    # the set of targets (selected by tag)
    config.addNotificationTarget(snmpEngine, 'my-notification', 'my-filter',
                                 'all-my-managers', 'trap')

    # Allow NOTIFY access to Agent's MIB by this SNMP model (3), securityLevel
    # and SecurityName
    config.addContext(snmpEngine, '')
    config.addVacmUser(snmpEngine, 3, userConfig['DEFAULT']['SNMPUSER'],
                       'authPriv', (), (), (1, 3, 6), 'aContextName')

    # *** SNMP engine configuration is complete by this line ***

    # Create Notification Originator App instance.
    ntfOrg = ntforg.NotificationOriginator()

    # Build and submit notification message to dispatcher
    ntfOrg.sendVarBinds(
        snmpEngine,
        # Notification targets
        'my-notification',  # notification targets
        None,
        'aContextName',  # contextEngineId, contextName
        # var-binds
        [((1, 3, 6, 1, 2, 1, 1, 3, 0), v2c.OctetString(uptime)),
         ((1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0),
          v2c.ObjectIdentifier((1, 3, 6, 1, 6, 3, 1, 1, 5, 1))),
         ((1, 3, 6, 1, 2, 1, 1, 5, 0), v2c.OctetString(socket.getfqdn())),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 10, 0),
          v2c.OctetString('Application')),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 11, 0),
          v2c.OctetString('Performance')),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 12, 0),
          v2c.OctetString('critical')),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 19, 0),
          v2c.OctetString('health')),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 20, 0),
          v2c.OctetString('vROpsExternalMonitorService.py')),
         ((1, 3, 6, 1, 4, 1, 6876, 4, 50, 1, 2, 50, 0),
          v2c.OctetString(
              'vROps services are having issues, please check nodes'))])

    print('Notification is scheduled to be sent')

    # Run I/O dispatcher which would send pending message and process response
    snmpEngine.transportDispatcher.runDispatcher()
コード例 #11
0
                    ((symName, modName), suffix) = mibvar.oidToMibName(
                        self.mibViewController, name + oid
                        )
                    syntax = mibvar.cloneFromMibValue(
                        self.mibViewController, modName, symName, varVal
                        )
                    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))
        else:
            __varBinds = None

        return ntforg.NotificationOriginator(self.snmpContext).sendNotification(self.snmpEngine, notifyName, notificationType, __varBinds, cbFun, cbCtx)

class NotificationOriginator(AsynNotificationOriginator):
    def sendNotification(
        self, authData, transportTarget, notifyType,
        notificationType, *varBinds
        ):
        def __cbFun(sendRequestHandle, errorIndication, appReturn):
            appReturn['errorIndication'] = errorIndication

        appReturn = {}
        errorIndication = self.asyncSendNotification(
            authData, transportTarget, notifyType, notificationType, varBinds,
            (__cbFun, appReturn)
            )
        if errorIndication:
コード例 #12
0
ファイル: pysa.py プロジェクト: ggs134/pysnmp
 def sendTrap(self):
     print "Sending Trap"
     ntfOrg = ntforg.NotificationOriginator(self._snmpContext)
     errorIndication = ntfOrg.sendNotification(self._snmpEngine,
                                               'test-notification',
                                               ("MY-MIB", 'testTrap'), ())
コード例 #13
0
            inTableFlag = 1
        if not inTableFlag:
            return  # stop on end-of-table
    return 1  # continue walking


snmpContext = context.SnmpContext(snmpEngine)

# Agent-side VACM setup
config.addContext(snmpEngine, '')
config.addTrapUser(snmpEngine, 1, ctx['securityName'], 'noAuthNoPriv',
                   (1, 3, 6))  # v1
config.addTrapUser(snmpEngine, 2, ctx['securityName'], 'noAuthNoPriv',
                   (1, 3, 6))  # v2c
config.addTrapUser(snmpEngine, 3, ctx['securityName'], 'authPriv',
                   (1, 3, 6))  # v3

ctx['notificationName'] = 'myNotifyName'
config.addNotificationTarget(snmpEngine, ctx['notificationName'],
                             ctx['paramsName'], ctx['transportTag'], 'trap')

ntforg.NotificationOriginator(snmpContext).sendNotification(
    snmpEngine, ctx['notificationName'], ('SNMPv2-MIB', ctx['GenericTrap']),
    ctx['varBinds'], cbFun, ctx)

try:
    snmpEngine.transportDispatcher.runDispatcher()
except error.PySnmpError, why:
    sys.stderr.write('Error: %s\n' % why)
    sys.exit(-1)
コード例 #14
0
def trigger_trap(temp):
	# Create SNMP engine instance
	snmpEngine = engine.SnmpEngine()

	# SecurityName <-> CommunityName mapping
	config.addV1System(snmpEngine, 'my-area', 'federated')

	# Specify security settings per SecurityName (SNMPv2c -> 1)
	config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 1)

	# Setup transport endpoint and bind it with security settings yielding
	# a target name
	config.addSocketTransport(
	    snmpEngine,
	    udp.domainName,
	    udp.UdpSocketTransport().openClientMode()
	)
	config.addTargetAddr(
	    snmpEngine, 'my-nms',
	    udp.domainName, ('34.215.95.184', 162),
	    'my-creds',
	    tagList='all-my-managers'
	)

	# Specify what kind of notification should be sent (TRAP or INFORM),
	# to what targets (chosen by tag) and what filter should apply to
	# the set of targets (selected by tag)
	config.addNotificationTarget(
	    snmpEngine, 'my-notification', 'my-filter', 'all-my-managers', 'trap'
	)

	# Allow NOTIFY access to Agent's MIB by this SNMP model (2), securityLevel
	# and SecurityName
	config.addContext(snmpEngine, '')
	config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1,3,6))

	# *** SNMP engine configuration is complete by this line ***

	# Create default SNMP context where contextEngineId == SnmpEngineId
	snmpContext = context.SnmpContext(snmpEngine)

	# Create Notification Originator App instance.
	ntfOrg = ntforg.NotificationOriginator(snmpContext)

	# Build and submit notification message to dispatcher
	ntfOrg.sendNotification(
	    snmpEngine,
	    # Notification targets
	    'my-notification',
	    # Trap OID (SNMPv2-MIB::coldStart)
	    #(1,3,6,1,6,3,1,1,5,1),
            (1,3,6,1,4,1,8072,2,7,1,1,1,1,3,1),
	    # ( (oid, value), ... )
	    ( ((1,3,6,1,4,1,8072,2,7,1,1,1,1,3,1), v2c.OctetString(temp)),
            ((1,3,6,1,2,1,1,5,0), v2c.OctetString('Reason: Admin brought down')) )
	)

	print('Notification is scheduled to be sent')

	# Run I/O dispatcher which would send pending message and process response
	snmpEngine.transportDispatcher.runDispatcher()
コード例 #15
0
    def __init__(self, args, queue):
        configDict = loadConfig(args.config)

        self.moduleLogger = set_logging(configDict, __class__.__name__)

        self.moduleLogger.info(f'original configDict: {configDict}')

        self._queue = queue

        # temp lines for graylog client end #
        # configDict['usmUserDataMatrix'] = [ usmUserTuple.strip().split(',')
        # for usmUserTuple in configDict['usmUserTuples'].split(';') if len(usmUserTuple) > 0 ]
        # self.moduleLogger.debug('configDict['usmUserDataMatrix']: {}'.format(configDict['usmUserDataMatrix']))
        # configDict['usmUsers'] = []
        self.moduleLogger.info(f'modified configDict: {configDict}')

        self._snmpEngine = snmp_config.getSnmpEngine(
            engineId=configDict['snmp'].get('engineId'))

        engineBoots = snmp_config.setSnmpEngineBoots(
            self._snmpEngine, configDict.get('stateDir', '.'))

        self._targets = snmp_config.setTrapTypeForTag(self._snmpEngine, self.TARGETS_TAG)

        authEntries = {}

        for snmpVersion, snmpConfigEntries in configDict['snmp'].get(
                'versions', {}).items():

            snmpVersion = str(snmpVersion)

            if snmpVersion in ('1', '2c'):

                for security, snmpConfig in snmpConfigEntries.items():

                    community = snmpConfig['community']

                    authLevel = snmp_config.setCommunity(
                        self._snmpEngine, security, community, version=snmpVersion, tag=self.TARGETS_TAG)

                    self.moduleLogger.info(
                        f'Configuring SNMPv{snmpVersion} security name '
                        f'{security}, community name {community}')

                    authEntries[security] = snmpVersion, authLevel

            elif snmpVersion == '3':

                for security, usmCreds in snmpConfigEntries.get('usmUsers', {}).items():

                    authLevel = snmp_config.setUsmUser(
                        self._snmpEngine, security,
                        usmCreds.get('user'),
                        usmCreds.get('authKey'), usmCreds.get('authProtocol'),
                        usmCreds.get('privKey'), usmCreds.get('privProtocol'))

                    self.moduleLogger.info(
                        f'Configuring SNMPv3 USM security {security}, user '
                        f'{usmCreds.get("user")}, '
                        f'auth {usmCreds.get("authKey")}/{usmCreds.get("authProtocol")}, '
                        f'priv {usmCreds.get("privKey")}/{usmCreds.get("privProtocol")}')

                    authEntries[security] = snmpVersion, authLevel

            else:
                raise error.BdsError(f'Unknown SNMP version {snmpVersion}')

            self._birthday = time.time()

        snmpTrapTargets = configDict['notificator'].get('snmpTrapTargets', {}).items()

        for targetId, (targetName, targetConfig) in enumerate(snmpTrapTargets):

            bind_address = targetConfig.get('bind-address', '0.0.0.0'), 0

            security = targetConfig['security-name']

            transportDomain = snmp_config.setSnmpTransport(
                self._snmpEngine, iface=bind_address, iface_num=targetId)

            transportAddress = (targetConfig['address'],
                                int(targetConfig.get('port', 162)))

            snmp_config.setTrapTargetAddress(
                self._snmpEngine, security, transportDomain, transportAddress,
                tag=self.TARGETS_TAG)

            snmpVersion, authLevel = authEntries[security]

            snmp_config.setTrapVersion(
                self._snmpEngine, security, authLevel, snmpVersion)

            self.moduleLogger.info(
                f'Configuring target #{targetId}, transport domain '
                f'{transportDomain}, destination {transportAddress}, '
                f'bind address {bind_address} using security name {security}')

        self._configureMibObjects(configDict)

        self._ntfOrg = ntforg.NotificationOriginator()

        self._trapCounter = 0

        self.moduleLogger.info(
            f'Running SNMP engine ID {self._snmpEngine}, boots {engineBoots}')
コード例 #16
0
    def sendTrap(self,
                 version,
                 enterprise,
                 varList,
                 community=False,
                 destPort=False):
        if destPort:
            trapPort = destPort
        else:
            trapPort = TRAP_PORT
        if community:
            comm = community
        else:
            comm = DEFAULT_COMM
        snmpEngine = engine.SnmpEngine()
        # v1/2 setup
        config.addV1System(snmpEngine, TEST_AGENT, comm)
        # v3 setup
        config.addV3User(snmpEngine, TEST_USER, config.usmHMACMD5AuthProtocol,
                         'authKey1', config.usmDESPrivProtocol, 'privKey1')
        # Transport params
        config.addTargetParams(snmpEngine, PARAM, TEST_USER, AUTHPRIV)
        #config.addTargetParams(snmpEngine, 'myParams', 'test-agent', 'noAuthNoPriv', 0)
        # Transport addresses
        config.addTargetAddr(snmpEngine,
                             NMS,
                             config.snmpUDPDomain,
                             (self.dataCollector, trapPort),
                             PARAM,
                             tagList='myManagementStations')
        # Notification targets
        config.addNotificationTarget(
            #    snmpEngine, 'myNotifyName', 'myParams', 'myManagementStations', 'trap'
            snmpEngine,
            'myNotifyName',
            PARAM,
            'myManagementStations',
            'inform')
        # Setup transport endpoint
        config.addSocketTransport(snmpEngine, udp.domainName,
                                  udp.UdpSocketTransport().openClientMode())
        # Agent-side VACM setup
        config.addContext(snmpEngine, '')
        config.addTrapUser(snmpEngine, 1, 'test-agent', 'noAuthNoPriv',
                           (1, 3, 6))  # v1
        config.addTrapUser(snmpEngine, 2, 'test-agent', 'noAuthNoPriv',
                           (1, 3, 6))  # v2c
        config.addTrapUser(snmpEngine, 3, 'test-user', 'authPriv',
                           (1, 3, 6))  # v3

        # SNMP context
        snmpContext = context.SnmpContext(snmpEngine)

        def cbFun(sendRequestHandle, errorIndication, cbCtx):
            if errorIndication:
                print errorIndication

        ntforg.NotificationOriginator(snmpContext).sendNotification(
            snmpEngine, 'myNotifyName', ('SNMPv2-MIB', 'coldStart'),
            (((1, 3, 6, 1, 2, 1, 1, 5),
              v2c.OctetString('Example Notificator')), ), cbFun)

        snmpEngine.transportDispatcher.runDispatcher()
                             'all-my-managers', 'inform')

# Allow NOTIFY access to Agent's MIB by this SNMP model (2&3), securityLevel
# and SecurityName
config.addContext(snmpEngine, '')
config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (), (), (1, 3, 6))
config.addVacmUser(snmpEngine, 3, 'usr-md5-none', 'authNoPriv', (), (),
                   (1, 3, 6))

# *** SNMP engine configuration is complete by this line ***

# Create default SNMP context where contextEngineId == SnmpEngineId
snmpContext = context.SnmpContext(snmpEngine)

# Create Notification Originator App instance.
ntfOrg = ntforg.NotificationOriginator(snmpContext)


# Error/confirmation receiver
def cbFun(sendRequestHandle, errorIndication, cbCtx):
    print('Notification %s, status - %s' %
          (sendRequestHandle, errorIndication and errorIndication
           or 'delivered'))


# Build and submit notification message to dispatcher
ntfOrg.sendNotification(
    snmpEngine,
    # Notification targets
    'my-notification',
    # Trap OID (SNMPv2-MIB::coldStart)
コード例 #18
0
ファイル: ntforg.py プロジェクト: zxc159789/pysnmp
def sendNotification(snmpEngine, authData, transportTarget, contextData,
                     notifyType, *varBinds, **options):
    """Sends SNMP notification.

    Based on passed parameters, prepares SNMP TRAP or INFORM message
    (:RFC:`1905#section-4.2.6`) and schedules its transmission by
    :mod:`twisted` 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.twisted.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.twisted.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.

    notifyType: str
        Indicates type of notification to be sent. Recognized literal
        values are *trap* or *inform*.

    \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType` or :py:class:`~pysnmp.smi.rfc1902.NotificationType`
        One or more objects representing MIB variables to place
        into SNMP notification. It could be tuples of OID-values
        or :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
        of :py:class:`~pysnmp.smi.rfc1902.NotificationType` objects.

        SNMP Notification PDU includes some housekeeping items that
        are required for SNMP to function.

        Agent information:

        * SNMPv2-MIB::sysUpTime.0 = <agent uptime>
        * SNMPv2-SMI::snmpTrapOID.0 = {SNMPv2-MIB::coldStart, ...}

        Applicable to SNMP v1 TRAP:

        * SNMP-COMMUNITY-MIB::snmpTrapAddress.0 = <agent-IP>
        * SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 = <snmp-community-name>
        * SNMP-COMMUNITY-MIB::snmpTrapEnterprise.0 = <enterprise-OID>

        .. note::

           Unless user passes some of these variable-bindings, `.sendNotification()`
           call will fill in the missing items.

        User variable-bindings:

        * SNMPv2-SMI::NOTIFICATION-TYPE
        * SNMPv2-SMI::OBJECT-TYPE

        .. note::

           The :py:class:`~pysnmp.smi.rfc1902.NotificationType` object ensures
           properly formed SNMP notification (to comply MIB definition). If you
           build notification PDU out of :py:class:`~pysnmp.smi.rfc1902.ObjectType`
           objects or simple tuples of OID-value objects, it is your responsibility
           to provide well-formed notificaton payload.

    Other Parameters
    ----------------
    \*\*options :
        Request options:

            * `lookupMib` - load MIB and resolve response MIB variables at
              the cost of slightly reduced performance. Default is `True`.

    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
      :class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing
      MIB variables returned in SNMP response.

    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, varBinds) = args
    ...     print(errorStatus, errorIndex, varBind)
    ...
    >>> def failure(errorIndication):
    ...     print(errorIndication)
    ...
    >>> def run(reactor):
    ...     d = sendNotification(SnmpEngine(),
    ...                          CommunityData('public'),
    ...                          UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...                          ContextData(),
    ...                          'trap',
    ...                          NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
    ...     d.addCallback(success).addErrback(failure)
    ...     return d
    ...
    >>> react(run)
    (0, 0, [])
    >>>

    """
    def __cbFun(snmpEngine, sendRequestHandle,
                errorIndication, errorStatus, errorIndex,
                varBinds, cbCtx):
        lookupMib, deferred = cbCtx

        if errorIndication:
            deferred.errback(Failure(errorIndication))
        else:
            try:
                varBindsUnmade = vbProcessor.unmakeVarBinds(
                    snmpEngine.cache, varBinds, lookupMib
                )

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

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

    notifyName = lcd.configure(
        snmpEngine, authData, transportTarget, notifyType
    )

    def __trapFun(deferred):
        deferred.callback((0, 0, []))

    deferred = Deferred()

    ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine,
        notifyName,
        contextData.contextEngineId,
        contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine.cache, varBinds),
        __cbFun,
        (options.get('lookupMib', True), deferred)
    )

    if notifyType == 'trap':
        reactor.callLater(0, __trapFun, deferred)

    return deferred
コード例 #19
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.generatorTrap((snmpEngine, ctx), ast)
    pdu.writePduGenerator((snmpEngine, ctx), ast)
    generator((snmpEngine, ctx), ast)

    v2c.apiPDU.setVarBinds(
        ctx['pdu'],
        v2c.apiPDU.getVarBinds(ctx['pdu']) + ctx['varBinds'])

    ntforg.NotificationOriginator().sendPdu(snmpEngine, ctx['addrName'],
                                            ctx.get('contextEngineId'),
                                            ctx.get('contextName', ''),
                                            ctx['pdu'], 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])
    for line in traceback.format_exception(*sys.exc_info()):
        sys.stderr.write(line.replace('\n', ';'))
コード例 #20
0
ファイル: ntforg.py プロジェクト: k11a/snmp-simulator
def sendNotification(snmpEngine, authData, transportTarget, contextData,
                     notifyType, varBinds, **options):
    """Sends SNMP notification.

    Based on passed parameters, prepares SNMP TRAP or INFORM message
    (:RFC:`1905#section-4.2.6`) and schedules its transmission by
    :mod:`twisted` 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.twisted.UdpTransportTarget` or :py:class:`~pysnmp.hlapi.twisted.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.

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

    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
      :class:`~pysnmp.smi.rfc1902.ObjectType` class instances representing
      MIB variables returned in SNMP response.

    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, varBinds) = args
    ...     print(errorStatus, errorIndex, varBind)
    ...
    >>> def failure(errorIndication):
    ...     print(errorIndication)
    ...
    >>> def run(reactor):
    ...     d = sendNotification(SnmpEngine(),
    ...                          CommunityData('public'),
    ...                          UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...                          ContextData(),
    ...                          'trap',
    ...                          NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
    ...     d.addCallback(success).addErrback(failure)
    ...     return d
    ...
    >>> react(run)
    (0, 0, [])
    >>>

    """
    def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
                errorIndex, varBinds, cbCtx):
        lookupMib, deferred = cbCtx

        if errorIndication:
            deferred.errback(Failure(errorIndication))
        else:
            try:
                varBindsUnmade = vbProcessor.unmakeVarBinds(
                    snmpEngine, varBinds, lookupMib)

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

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

    notifyName = lcd.configure(snmpEngine, authData, transportTarget,
                               notifyType)

    def __trapFun(deferred):
        deferred.callback((0, 0, []))

    deferred = Deferred()

    ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine, notifyName,
        contextData.contextEngineId, contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun,
        (options.get('lookupMib', True), deferred))

    if notifyType == 'trap':
        reactor.callLater(0, __trapFun, deferred)

    return deferred
コード例 #21
0
def sendNotification(snmpEngine, authData, transportTarget, contextData,
                     notifyType, varBinds, **options):
    """Creates a generator to send SNMP notification.

    When itereator gets advanced by :py:mod:`asyncio` main loop,
    SNMP TRAP or INFORM notification is send (:RFC:`1905#section-4.2.6`).
    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.

    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
    --------
    >>> import asyncio
    >>> from pysnmp.hlapi.asyncio import *
    >>>
    >>> @asyncio.coroutine
    ... def run():
    ...     errorIndication, errorStatus, errorIndex, varBinds = yield from sendNotification(
    ...         SnmpEngine(),
    ...         CommunityData('public'),
    ...         UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...         ContextData(),
    ...         'trap',
    ...         NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
    ...
    >>> asyncio.get_event_loop().run_until_complete(run())
    (None, 0, 0, [])
    >>>

    """
    def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
                errorIndex, varBinds, cbCtx):
        lookupMib, future = cbCtx
        if future.cancelled():
            return
        try:
            varBindsUnmade = vbProcessor.unmakeVarBinds(
                snmpEngine, varBinds, lookupMib)
        except Exception as e:
            future.set_exception(e)
        else:
            future.set_result(
                (errorIndication, errorStatus, errorIndex, varBindsUnmade))

    notifyName = lcd.configure(snmpEngine, authData, transportTarget,
                               notifyType)

    future = asyncio.Future()

    ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine, notifyName,
        contextData.contextEngineId, contextData.contextName,
        vbProcessor.makeVarBinds(snmpEngine, varBinds), __cbFun,
        (options.get('lookupMib', True), future))

    if notifyType == 'trap':

        def __trapFun(future):
            if future.cancelled():
                return
            future.set_result((None, 0, 0, []))

        loop = asyncio.get_event_loop()
        loop.call_soon(__trapFun, future)

    return future
コード例 #22
0
ファイル: ntforg.py プロジェクト: zxx1819/pysnmp
def sendNotification(snmpEngine, authData, transportTarget, contextData,
                     notifyType, *varBinds, **options):
    """Creates a generator to send SNMP notification.

    When iterator gets advanced by :py:mod:`asyncio` main loop,
    SNMP TRAP or INFORM notification is send (:RFC:`1905#section-4.2.6`).
    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.

    notifyType : str
        Indicates type of notification to be sent. Recognized literal
        values are *trap* or *inform*.

    \*varBinds: :class:`tuple` of OID-value pairs or :py:class:`~pysnmp.smi.rfc1902.ObjectType` or :py:class:`~pysnmp.smi.rfc1902.NotificationType`
        One or more objects representing MIB variables to place
        into SNMP notification. It could be tuples of OID-values
        or :py:class:`~pysnmp.smi.rfc1902.ObjectType` class instances
        of :py:class:`~pysnmp.smi.rfc1902.NotificationType` objects.

        SNMP Notification PDU places rigid requirement on the ordering of
        the variable-bindings.

        Mandatory variable-bindings:

        0. SNMPv2-MIB::sysUpTime.0 = <agent uptime>
        1. SNMPv2-SMI::snmpTrapOID.0 = {SNMPv2-MIB::coldStart, ...}

        Optional variable-bindings (applicable to SNMP v1 TRAP):

        2. SNMP-COMMUNITY-MIB::snmpTrapAddress.0 = <agent-IP>
        3. SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 = <snmp-community-name>
        4. SNMP-COMMUNITY-MIB::snmpTrapEnterprise.0 = <enterprise-OID>

        Informational variable-bindings:

        * SNMPv2-SMI::NOTIFICATION-TYPE
        * SNMPv2-SMI::OBJECT-TYPE

    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.

    Examples
    --------
    >>> import asyncio
    >>> from pysnmp.hlapi.asyncio import *
    >>>
    >>> @asyncio.coroutine
    ... def run():
    ...     errorIndication, errorStatus, errorIndex, varBinds = yield from sendNotification(
    ...         SnmpEngine(),
    ...         CommunityData('public'),
    ...         UdpTransportTarget(('demo.snmplabs.com', 162)),
    ...         ContextData(),
    ...         'trap',
    ...         NotificationType(ObjectIdentity('IF-MIB', 'linkDown')))
    ...     print(errorIndication, errorStatus, errorIndex, varBinds)
    ...
    >>> asyncio.get_event_loop().run_until_complete(run())
    (None, 0, 0, [])
    >>>

    """
    def __cbFun(snmpEngine, sendRequestHandle, errorIndication, errorStatus,
                errorIndex, varBinds, cbCtx):
        lookupMib, future = cbCtx
        if future.cancelled():
            return
        try:
            varBindsUnmade = VB_PROCESSOR.unmakeVarBinds(
                snmpEngine.cache, varBinds, lookupMib)
        except Exception as e:
            future.set_exception(e)
        else:
            future.set_result(
                (errorIndication, errorStatus, errorIndex, varBindsUnmade))

    notifyName = LCD.configure(snmpEngine, authData, transportTarget,
                               notifyType, contextData.contextName)

    future = asyncio.Future()

    ntforg.NotificationOriginator().sendVarBinds(
        snmpEngine, notifyName, contextData.contextEngineId,
        contextData.contextName,
        VB_PROCESSOR.makeVarBinds(snmpEngine.cache, varBinds), __cbFun,
        (options.get('lookupMib', True), future))

    if notifyType == 'trap':

        def __trapFun(future):
            if future.cancelled():
                return
            future.set_result((None, 0, 0, []))

        loop = asyncio.get_event_loop()
        loop.call_soon(__trapFun, future)

    return future
コード例 #23
0
config.addVacmUser(snmpEngine, 3, 'usr-md5-3des', 'authPriv', (), (),
                   (1, 3, 6))

# SNMP context
snmpContext = context.SnmpContext(snmpEngine)


# # Error/confirmation reciever
def cbFun(sendRequestHandle, errorIndication, cbCtx):
    print('Notification %s, status - %s' %
          (sendRequestHandle, errorIndication and errorIndication
           or 'delivered'))


sendRequestHandle = ntforg.NotificationOriginator(
    snmpContext).sendNotification(
        snmpEngine,
        # Notification targets
        'my-notification',
        # Trap OID (SNMPv2-MIB::coldStart)
        (1, 3, 6, 1, 6, 3, 1, 1, 5, 1),
        # ((oid, value), ... )
        (((1, 3, 6, 1, 2, 1, 1, 1), v2c.OctetString('Example Notificator')),
         ((1, 3, 6, 1, 2, 1, 1, 5), v2c.OctetString('Notificator Example'))),
        cbFun)

print('Notification %s scheduled to be sent' % sendRequestHandle)

# Run I/O dispatcher which would send pending message and process response
snmpEngine.transportDispatcher.runDispatcher()
コード例 #24
0
ファイル: snmpfwd-client.py プロジェクト: sharty/snmpfwd
def main():
    class LogString(LazyLogString):

        GROUPINGS = [
            ['callflow-id'],
            ['trunk-id'],
            [
                'server-snmp-engine-id', 'server-snmp-transport-domain',
                'server-snmp-peer-address', 'server-snmp-peer-port',
                'server-snmp-bind-address', 'server-snmp-bind-port',
                'server-snmp-security-model', 'server-snmp-security-level',
                'server-snmp-security-name', 'server-snmp-context-engine-id',
                'server-snmp-context-name', 'server-snmp-pdu',
                'server-snmp-entity-id'
            ],
            [
                'server-snmp-credentials-id', 'server-snmp-context-id',
                'server-snmp-content-id', 'server-snmp-peer-id',
                'server-classification-id'
            ],
            [
                'snmp-peer-id', 'snmp-bind-address', 'snmp-bind-port',
                'snmp-peer-address', 'snmp-peer-port',
                'snmp-context-engine-id', 'snmp-context-name', 'snmp-pdu'
            ],
        ]

        FORMATTERS = {
            'server-snmp-pdu': LazyLogString.prettyVarBinds,
            'snmp-pdu': LazyLogString.prettyVarBinds,
        }

    def snmpCbFun(snmpEngine, sendRequestHandle, errorIndication, rspPDU,
                  cbCtx):

        trunkId, msgId, trunkReq, pluginIdList, reqCtx = cbCtx

        trunkRsp = {
            'callflow-id': trunkReq['callflow-id'],
            'snmp-pdu': rspPDU,
        }

        logCtx = LogString(trunkRsp)

        if errorIndication:
            log.info('received SNMP error-indication "%s"' % errorIndication,
                     ctx=logCtx)
            trunkRsp['error-indication'] = errorIndication

        if rspPDU:
            reqPdu = trunkReq['server-snmp-pdu']

            for pluginId in pluginIdList:
                if reqPdu.tagSet in rfc3411.notificationClassPDUs:
                    st, rspPDU = pluginManager.processNotificationResponse(
                        pluginId, snmpEngine, rspPDU, trunkReq, reqCtx)

                elif reqPdu.tagSet not in rfc3411.unconfirmedClassPDUs:
                    st, rspPDU = pluginManager.processCommandResponse(
                        pluginId, snmpEngine, rspPDU, trunkReq, reqCtx)
                else:
                    log.error('ignoring unsupported PDU', ctx=logCtx)
                    break

                if st == status.BREAK:
                    log.debug('plugin %s inhibits other plugins' % pluginId,
                              ctx=logCtx)
                    break

                elif st == status.DROP:
                    log.debug(
                        'received SNMP %s, plugin %s muted response' %
                        (errorIndication and 'error' or 'response', pluginId),
                        ctx=logCtx)
                    trunkRsp['snmp-pdu'] = None
                    break

        try:
            trunkingManager.sendRsp(trunkId, msgId, trunkRsp)

        except SnmpfwdError:
            log.error('received SNMP %s message, trunk message not sent "%s"' %
                      (msgId, sys.exc_info()[1]),
                      ctx=logCtx)
            return

        log.debug('received SNMP %s message, forwarded as trunk message #%s' %
                  (errorIndication and 'error' or 'response', msgId),
                  ctx=logCtx)

    #
    # The following needs proper support in pysnmp. Meanwhile - monkey patching!
    #

    def makeTargetAddrOverride(targetAddr):
        endpoints = []

        def getTargetAddr(snmpEngine, snmpTargetAddrName):
            addrInfo = list(targetAddr(snmpEngine, snmpTargetAddrName))

            if endpoints:
                peerAddr, bindAddr = endpoints.pop(), endpoints.pop()

                try:
                    addrInfo[1] = addrInfo[1].__class__(
                        peerAddr).setLocalAddress(bindAddr)

                except Exception:
                    raise PySnmpError(
                        'failure replacing bind address %s -> %s for transport '
                        'domain %s' % (addrInfo[1], bindAddr, addrInfo[0]))

            return addrInfo

        def updateEndpoints(bindAddr, peerAddr):
            endpoints.extend((bindAddr, peerAddr))

        return getTargetAddr, updateEndpoints

    lcd.getTargetAddr, updateEndpoints = makeTargetAddrOverride(
        lcd.getTargetAddr)

    def trunkCbFun(trunkId, msgId, trunkReq):

        for key in tuple(trunkReq):
            if key != 'callflow-id':
                trunkReq['server-' + key] = trunkReq[key]
                del trunkReq[key]

        trunkReq['trunk-id'] = trunkId

        k = [
            str(x) for x in (trunkReq['server-snmp-engine-id'],
                             trunkReq['server-snmp-transport-domain'],
                             trunkReq['server-snmp-peer-address'] + ':' +
                             str(trunkReq['server-snmp-peer-port']),
                             trunkReq['server-snmp-bind-address'] + ':' +
                             str(trunkReq['server-snmp-bind-port']),
                             trunkReq['server-snmp-security-model'],
                             trunkReq['server-snmp-security-level'],
                             trunkReq['server-snmp-security-name'],
                             trunkReq['server-snmp-context-engine-id'],
                             trunkReq['server-snmp-context-name'])
        ]

        k.append(snmpPduTypesMap.get(trunkReq['server-snmp-pdu'].tagSet, '?'))
        k.append('|'.join([
            str(x[0])
            for x in v2c.apiPDU.getVarBinds(trunkReq['server-snmp-pdu'])
        ]))
        k = '#'.join(k)

        for x, y in origCredIdList:
            if y.match(k):
                origPeerId = trunkReq[
                    'server-snmp-entity-id'] = macro.expandMacro(x, trunkReq)
                break
        else:
            origPeerId = None

        k = [
            str(x) for x in (trunkReq['server-snmp-credentials-id'],
                             trunkReq['server-snmp-context-id'],
                             trunkReq['server-snmp-content-id'],
                             trunkReq['server-snmp-peer-id'])
        ]
        k = '#'.join(k)

        for x, y in srvClassIdList:
            if y.match(k):
                srvClassId = trunkReq[
                    'server-classification-id'] = macro.expandMacro(
                        x, trunkReq)
                break
        else:
            srvClassId = None

        logCtx = LogString(trunkReq)

        errorIndication = None

        peerIdList = routingMap.get(
            (origPeerId, srvClassId, macro.expandMacro(trunkId, trunkReq)))
        if not peerIdList:
            log.error('unroutable trunk message #%s' % msgId, ctx=logCtx)
            errorIndication = 'no route to SNMP peer configured'

        cbCtx = trunkId, msgId, trunkReq, (), {}

        if errorIndication:
            snmpCbFun(None, None, errorIndication, None, cbCtx)
            return

        pluginIdList = pluginIdMap.get(
            (origPeerId, srvClassId, macro.expandMacro(trunkId, trunkReq)))
        for peerId in peerIdList:
            peerId = macro.expandMacro(peerId, trunkReq)

            trunkReqCopy = trunkReq.copy()

            (snmpEngine, contextEngineId, contextName, bindAddr, bindAddrMacro,
             peerAddr, peerAddrMacro) = peerIdMap[peerId]

            if bindAddrMacro:
                bindAddr = macro.expandMacro(bindAddrMacro, trunkReqCopy), 0

            if peerAddrMacro:
                peerAddr = macro.expandMacro(peerAddrMacro, trunkReqCopy), 161

            if bindAddr and peerAddr:
                updateEndpoints(bindAddr, peerAddr)

            trunkReqCopy['snmp-peer-id'] = peerId

            trunkReqCopy['snmp-context-engine-id'] = contextEngineId
            trunkReqCopy['snmp-context-name'] = contextName

            trunkReqCopy['snmp-bind-address'], trunkReqCopy[
                'snmp-bind-port'] = bindAddr
            trunkReqCopy['snmp-peer-address'], trunkReqCopy[
                'snmp-peer-port'] = peerAddr

            logCtx.update(trunkReqCopy)

            pdu = trunkReqCopy['server-snmp-pdu']

            if pluginIdList:
                reqCtx = {}

                cbCtx = trunkId, msgId, trunkReqCopy, pluginIdList, reqCtx

                for pluginNum, pluginId in enumerate(pluginIdList):

                    if pdu.tagSet in rfc3411.notificationClassPDUs:
                        st, pdu = pluginManager.processNotificationRequest(
                            pluginId, snmpEngine, pdu, trunkReqCopy, reqCtx)

                    elif pdu.tagSet not in rfc3411.unconfirmedClassPDUs:
                        st, pdu = pluginManager.processCommandRequest(
                            pluginId, snmpEngine, pdu, trunkReqCopy, reqCtx)

                    else:
                        log.error('ignoring unsupported PDU', ctx=logCtx)
                        break

                    if st == status.BREAK:
                        log.debug('plugin %s inhibits other plugins' %
                                  pluginId,
                                  ctx=logCtx)
                        cbCtx = trunkId, msgId, trunkReqCopy, pluginIdList[:
                                                                           pluginNum], reqCtx
                        break

                    elif st == status.DROP:
                        log.debug(
                            'received trunk message #%s, plugin %s muted request'
                            % (msgId, pluginId),
                            ctx=logCtx)
                        snmpCbFun(snmpEngine, None, None, None, cbCtx)
                        return

                    elif st == status.RESPOND:
                        log.debug(
                            'received trunk message #%s, plugin %s forced immediate response'
                            % (msgId, pluginId),
                            ctx=logCtx)
                        snmpCbFun(snmpEngine, None, None, pdu, cbCtx)
                        return

            snmpMessageSent = False

            if pdu.tagSet in rfc3411.notificationClassPDUs:
                if pdu.tagSet in rfc3411.unconfirmedClassPDUs:
                    try:
                        notificationOriginator.sendPdu(
                            snmpEngine, peerId,
                            macro.expandMacro(contextEngineId, trunkReq),
                            macro.expandMacro(contextName, trunkReq), pdu)

                        snmpMessageSent = True

                    except PySnmpError:
                        errorIndication = 'failure sending SNMP notification'
                        log.error('trunk message #%s, SNMP error: %s' %
                                  (msgId, sys.exc_info()[1]),
                                  ctx=logCtx)

                    else:
                        errorIndication = None

                    # respond to trunk right away
                    snmpCbFun(snmpEngine, None, errorIndication, None, cbCtx)

                else:
                    try:
                        notificationOriginator.sendPdu(
                            snmpEngine, peerId,
                            macro.expandMacro(contextEngineId, trunkReq),
                            macro.expandMacro(contextName, trunkReq), pdu,
                            snmpCbFun, cbCtx)

                        snmpMessageSent = True

                    except PySnmpError:
                        log.error('trunk message #%s, SNMP error: %s' %
                                  (msgId, sys.exc_info()[1]),
                                  ctx=logCtx)

            elif pdu.tagSet not in rfc3411.unconfirmedClassPDUs:
                try:
                    commandGenerator.sendPdu(
                        snmpEngine, peerId,
                        macro.expandMacro(contextEngineId, trunkReq),
                        macro.expandMacro(contextName, trunkReq), pdu,
                        snmpCbFun, cbCtx)

                    snmpMessageSent = True

                except PySnmpError:
                    errorIndication = 'failure sending SNMP command'
                    log.error('trunk message #%s, SNMP error: %s' %
                              (msgId, sys.exc_info()[1]),
                              ctx=logCtx)

                    # respond to trunk right away
                    snmpCbFun(snmpEngine, None, errorIndication, None, cbCtx)

            else:
                log.error('ignoring unsupported PDU', ctx=logCtx)

            if snmpMessageSent:
                log.debug(
                    'received trunk message #%s, forwarded as SNMP message' %
                    msgId,
                    ctx=logCtx)

    #
    # Main script body starts here
    #

    helpMessage = """\
Usage: %s [--help]
    [--version ]
    [--debug-snmp=<%s>]
    [--debug-asn1=<%s>]
    [--daemonize]
    [--process-user=<uname>] [--process-group=<gname>]
    [--pid-file=<file>]
    [--logging-method=<%s[:args>]>]
    [--log-level=<%s>]
    [--config-file=<file>]""" % (sys.argv[0], '|'.join([
        x for x in getattr(pysnmp_debug, 'FLAG_MAP',
                           getattr(pysnmp_debug, 'flagMap', ()))
        if x != 'mibview'
    ]), '|'.join([
        x for x in getattr(pyasn1_debug, 'FLAG_MAP',
                           getattr(pyasn1_debug, 'flagMap', ()))
    ]), '|'.join(log.methodsMap), '|'.join(log.levelsMap))
    try:
        opts, params = getopt.getopt(sys.argv[1:], 'hv', [
            'help', 'version', 'debug=', 'debug-snmp=', 'debug-asn1=',
            'daemonize', 'process-user='******'process-group=', 'pid-file=',
            'logging-method=', 'log-level=', 'config-file='
        ])

    except Exception:
        sys.stderr.write('ERROR: %s\r\n%s\r\n' %
                         (sys.exc_info()[1], helpMessage))
        return

    if params:
        sys.stderr.write('ERROR: extra arguments supplied %s\r\n%s\r\n' %
                         (params, helpMessage))
        return

    pidFile = ''
    cfgFile = CONFIG_FILE
    foregroundFlag = True
    procUser = procGroup = None

    loggingMethod = ['stderr']
    loggingLevel = None

    for opt in opts:
        if opt[0] == '-h' or opt[0] == '--help':
            sys.stderr.write("""\
Synopsis:
  SNMP Proxy Forwarder: client part. Receives SNMP PDUs via one or many
  encrypted trunks established with the Forwarder's Agent part(s) running
  elsewhere and routes PDUs to built-in SNMP Managers for further
  transmission towards SNMP Agents.
  Can implement complex routing and protocol conversion logic through
  analyzing parts of SNMP messages and matching them against proxying rules.

Documentation:
  http://snmplabs.com/snmpfwd/

%s
""" % helpMessage)
            return
        if opt[0] == '-v' or opt[0] == '--version':
            import snmpfwd
            import pysnmp
            import pyasn1
            sys.stderr.write("""\
SNMP Proxy Forwarder version %s, written by Ilya Etingof <*****@*****.**>
Using foundation libraries: pysnmp %s, pyasn1 %s.
Python interpreter: %s
Software documentation and support at http://snmplabs.com/snmpfwd/
%s
""" % (snmpfwd.__version__, hasattr(pysnmp, '__version__')
            and pysnmp.__version__ or 'unknown', hasattr(pyasn1, '__version__')
            and pyasn1.__version__ or 'unknown', sys.version, helpMessage))
            return
        elif opt[0] == '--debug-snmp':
            pysnmp_debug.setLogger(
                pysnmp_debug.Debug(*opt[1].split(','),
                                   **dict(loggerName=PROGRAM_NAME +
                                          '.pysnmp')))
        elif opt[0] == '--debug-asn1':
            pyasn1_debug.setLogger(
                pyasn1_debug.Debug(*opt[1].split(','),
                                   **dict(loggerName=PROGRAM_NAME +
                                          '.pyasn1')))
        elif opt[0] == '--daemonize':
            foregroundFlag = False
        elif opt[0] == '--process-user':
            procUser = opt[1]
        elif opt[0] == '--process-group':
            procGroup = opt[1]
        elif opt[0] == '--pid-file':
            pidFile = opt[1]
        elif opt[0] == '--logging-method':
            loggingMethod = opt[1].split(':')
        elif opt[0] == '--log-level':
            loggingLevel = opt[1]
        elif opt[0] == '--config-file':
            cfgFile = opt[1]

    with daemon.PrivilegesOf(procUser, procGroup):

        try:
            log.setLogger(PROGRAM_NAME, *loggingMethod, **dict(force=True))

            if loggingLevel:
                log.setLevel(loggingLevel)

        except SnmpfwdError:
            sys.stderr.write('%s\r\n%s\r\n' % (sys.exc_info()[1], helpMessage))
            return

    try:
        cfgTree = cparser.Config().load(cfgFile)

    except SnmpfwdError:
        log.error('configuration parsing error: %s' % sys.exc_info()[1])
        return

    if cfgTree.getAttrValue('program-name', '', default=None) != PROGRAM_NAME:
        log.error('config file %s does not match program name %s' %
                  (cfgFile, PROGRAM_NAME))
        return

    if cfgTree.getAttrValue('config-version', '',
                            default=None) != CONFIG_VERSION:
        log.error(
            'config file %s version is not compatible with program version %s'
            % (cfgFile, CONFIG_VERSION))
        return

    random.seed()

    #
    # SNMPv3 CommandGenerator & NotificationOriginator implementation
    #

    origCredIdList = []
    srvClassIdList = []
    peerIdMap = {}
    pluginIdMap = {}
    routingMap = {}
    engineIdMap = {}

    commandGenerator = cmdgen.CommandGenerator()

    notificationOriginator = ntforg.NotificationOriginator()

    transportDispatcher = AsynsockDispatcher()
    transportDispatcher.registerRoutingCbFun(lambda td, t, d: td)
    transportDispatcher.setSocketMap()  # use global asyncore socket map

    pluginManager = PluginManager(macro.expandMacros(
        cfgTree.getAttrValue('plugin-modules-path-list',
                             '',
                             default=[],
                             vector=True),
        {'config-dir': os.path.dirname(cfgFile)}),
                                  progId=PROGRAM_NAME,
                                  apiVer=PLUGIN_API_VERSION)

    for pluginCfgPath in cfgTree.getPathsToAttr('plugin-id'):
        pluginId = cfgTree.getAttrValue('plugin-id', *pluginCfgPath)
        pluginMod = cfgTree.getAttrValue('plugin-module', *pluginCfgPath)
        pluginOptions = macro.expandMacros(
            cfgTree.getAttrValue('plugin-options', *pluginCfgPath,
                                 **dict(default=[], vector=True)),
            {'config-dir': os.path.dirname(cfgFile)})

        log.info(
            'configuring plugin ID %s (at %s) from module %s with options %s...'
            % (pluginId, '.'.join(pluginCfgPath), pluginMod,
               ', '.join(pluginOptions) or '<none>'))

        with daemon.PrivilegesOf(procUser, procGroup):

            try:
                pluginManager.loadPlugin(pluginId, pluginMod, pluginOptions)

            except SnmpfwdError:
                log.error('plugin %s not loaded: %s' %
                          (pluginId, sys.exc_info()[1]))
                return

    for peerEntryPath in cfgTree.getPathsToAttr('snmp-peer-id'):
        peerId = cfgTree.getAttrValue('snmp-peer-id', *peerEntryPath)
        if peerId in peerIdMap:
            log.error('duplicate snmp-peer-id=%s at %s' %
                      (peerId, '.'.join(peerEntryPath)))
            return

        log.info('configuring SNMP peer %s (at %s)...' %
                 (peerId, '.'.join(peerEntryPath)))

        engineId = cfgTree.getAttrValue('snmp-engine-id', *peerEntryPath)
        if engineId in engineIdMap:
            snmpEngine, snmpContext, snmpEngineMap = engineIdMap[engineId]
            log.info('using engine-id: %s' %
                     snmpEngine.snmpEngineID.prettyPrint())
        else:
            snmpEngine = engine.SnmpEngine(snmpEngineID=engineId)
            snmpContext = context.SnmpContext(snmpEngine)
            snmpEngineMap = {
                'transportDomain': {},
                'securityName': {},
                'credIds': set()
            }

            engineIdMap[engineId] = snmpEngine, snmpContext, snmpEngineMap

            log.info('new engine-id %s' %
                     snmpEngine.snmpEngineID.prettyPrint())

        transportDomain = cfgTree.getAttrValue('snmp-transport-domain',
                                               *peerEntryPath)
        transportDomain = rfc1902.ObjectName(str(transportDomain))

        if (transportDomain[:len(udp.domainName)] != udp.domainName and udp6
                and transportDomain[:len(udp6.domainName)] != udp6.domainName):
            log.error('unknown transport domain %s' % (transportDomain, ))
            return

        transportOptions = cfgTree.getAttrValue(
            'snmp-transport-options', *peerEntryPath,
            **dict(default=[], vector=True))

        bindAddr = cfgTree.getAttrValue('snmp-bind-address', *peerEntryPath)

        try:
            bindAddr, bindAddrMacro = endpoint.parseTransportAddress(
                transportDomain, bindAddr, transportOptions)

        except SnmpfwdError:
            log.error('bad snmp-bind-address specification %s at %s' %
                      (bindAddr, '.'.join(peerEntryPath)))
            return

        if transportDomain in snmpEngineMap['transportDomain']:
            log.info('using transport endpoint with transport ID %s' %
                     (transportDomain, ))

        else:
            if transportDomain[:len(udp.domainName)] == udp.domainName:
                transport = udp.UdpTransport()
            else:
                transport = udp6.Udp6Transport()

            snmpEngine.registerTransportDispatcher(transportDispatcher,
                                                   transportDomain)

            t = transport.openClientMode(bindAddr)

            if 'transparent-proxy' in transportOptions:
                t.enablePktInfo()
                t.enableTransparent()
            elif 'virtual-interface' in transportOptions:
                t.enablePktInfo()

            config.addSocketTransport(snmpEngine, transportDomain, t)

            snmpEngineMap['transportDomain'][transportDomain] = bindAddr[
                0], bindAddr[1], transportDomain
            log.info(
                'new transport endpoint at bind address [%s]:%s, options %s, transport ID %s'
                %
                (bindAddr[0], bindAddr[1], transportOptions
                 and '/'.join(transportOptions) or '<none>', transportDomain))

        securityModel = cfgTree.getAttrValue('snmp-security-model',
                                             *peerEntryPath)
        securityModel = rfc1902.Integer(securityModel)
        securityLevel = cfgTree.getAttrValue('snmp-security-level',
                                             *peerEntryPath)
        securityLevel = rfc1902.Integer(securityLevel)
        securityName = cfgTree.getAttrValue('snmp-security-name',
                                            *peerEntryPath)

        contextEngineId = cfgTree.getAttrValue('snmp-context-engine-id',
                                               *peerEntryPath,
                                               **dict(default=None))
        contextName = cfgTree.getAttrValue('snmp-context-name', *peerEntryPath,
                                           **dict(default=''))

        if securityModel in (1, 2):
            if securityName in snmpEngineMap['securityName']:
                if snmpEngineMap['securityName'][
                        securityName] == securityModel:
                    log.info('using security-name %s' % securityName)
                else:
                    log.error(
                        'security-name %s already in use at security-model %s'
                        % (securityName, securityModel))
                    return
            else:
                communityName = cfgTree.getAttrValue('snmp-community-name',
                                                     *peerEntryPath)
                config.addV1System(snmpEngine,
                                   securityName,
                                   communityName,
                                   securityName=securityName)

                log.info(
                    'new community-name %s, security-model %s, security-name %s, security-level %s'
                    % (communityName, securityModel, securityName,
                       securityLevel))
                snmpEngineMap['securityName'][securityName] = securityModel

        elif securityModel == 3:
            if securityName in snmpEngineMap['securityName']:
                if snmpEngineMap['securityName'][
                        securityName] == securityModel:
                    log.info('using USM security-name: %s' % securityName)
                else:
                    raise SnmpfwdError(
                        'security-name %s already in use at security-model %s'
                        % (securityName, securityModel))
            else:
                usmUser = cfgTree.getAttrValue('snmp-usm-user', *peerEntryPath)
                securityEngineId = cfgTree.getAttrValue(
                    'snmp-security-engine-id', *peerEntryPath,
                    **dict(default=None))
                if securityEngineId:
                    securityEngineId = rfc1902.OctetString(securityEngineId)

                log.info(
                    'new USM user %s, security-model %s, security-level %s, '
                    'security-name %s, security-engine-id %s' %
                    (usmUser, securityModel, securityLevel, securityName,
                     securityEngineId and securityEngineId.prettyPrint()
                     or '<none>'))

                if securityLevel in (2, 3):
                    usmAuthProto = cfgTree.getAttrValue(
                        'snmp-usm-auth-protocol', *peerEntryPath,
                        **dict(default=config.usmHMACMD5AuthProtocol))
                    try:
                        usmAuthProto = authProtocols[usmAuthProto.upper()]
                    except KeyError:
                        pass
                    usmAuthProto = rfc1902.ObjectName(usmAuthProto)
                    usmAuthKey = cfgTree.getAttrValue('snmp-usm-auth-key',
                                                      *peerEntryPath)
                    log.info(
                        'new USM authentication key: %s, authentication protocol: %s'
                        % (usmAuthKey, usmAuthProto))

                    if securityLevel == 3:
                        usmPrivProto = cfgTree.getAttrValue(
                            'snmp-usm-priv-protocol', *peerEntryPath,
                            **dict(default=config.usmDESPrivProtocol))
                        try:
                            usmPrivProto = privProtocols[usmPrivProto.upper()]
                        except KeyError:
                            pass
                        usmPrivProto = rfc1902.ObjectName(usmPrivProto)
                        usmPrivKey = cfgTree.getAttrValue(
                            'snmp-usm-priv-key', *peerEntryPath,
                            **dict(default=None))
                        log.info(
                            'new USM encryption key: %s, encryption protocol: %s'
                            % (usmPrivKey, usmPrivProto))

                        config.addV3User(
                            snmpEngine,
                            usmUser,
                            usmAuthProto,
                            usmAuthKey,
                            usmPrivProto,
                            usmPrivKey,
                        )

                    else:
                        config.addV3User(snmpEngine,
                                         usmUser,
                                         usmAuthProto,
                                         usmAuthKey,
                                         securityEngineId=securityEngineId)

                else:
                    config.addV3User(snmpEngine,
                                     usmUser,
                                     securityEngineId=securityEngineId)

                snmpEngineMap['securityName'][securityName] = securityModel

        else:
            log.error('unknown security-model: %s' % securityModel)
            sys.exit(1)

        credId = '/'.join(
            [str(x) for x in (securityName, securityLevel, securityModel)])
        if credId in snmpEngineMap['credIds']:
            log.info('using credentials ID %s...' % credId)
        else:
            config.addTargetParams(
                snmpEngine, credId, securityName, securityLevel,
                securityModel == 3 and 3 or securityModel - 1)
            log.info(
                'new credentials %s, security-name %s, security-level %s, security-model %s'
                % (credId, securityName, securityLevel, securityModel))
            snmpEngineMap['credIds'].add(credId)

        peerAddr = cfgTree.getAttrValue('snmp-peer-address', *peerEntryPath)

        try:
            peerAddr, peerAddrMacro = endpoint.parseTransportAddress(
                transportDomain, peerAddr, transportOptions, defaultPort=161)

        except SnmpfwdError:
            log.error('bad snmp-peer-address specification %s at %s' %
                      (peerAddr, '.'.join(peerEntryPath)))
            return

        timeout = cfgTree.getAttrValue('snmp-peer-timeout', *peerEntryPath)
        retries = cfgTree.getAttrValue('snmp-peer-retries', *peerEntryPath)

        config.addTargetAddr(snmpEngine, peerId, transportDomain, peerAddr,
                             credId, timeout, retries)

        peerIdMap[
            peerId] = snmpEngine, contextEngineId, contextName, bindAddr, bindAddrMacro, peerAddr, peerAddrMacro

        log.info(
            'new peer ID %s, bind address %s, peer address %s, timeout %s*0.01 secs, retries %s, credentials ID %s'
            % (peerId, bindAddrMacro or '<default>', peerAddrMacro
               or '%s:%s' % peerAddr, timeout, retries, credId))

    duplicates = {}

    # TODO: rename orig-* into server-* and orig-snmp-peer-id into server-snmp-entity-id

    for origCredCfgPath in cfgTree.getPathsToAttr('orig-snmp-peer-id'):
        origCredId = cfgTree.getAttrValue('orig-snmp-peer-id',
                                          *origCredCfgPath)
        if origCredId in duplicates:
            log.error('duplicate orig-snmp-peer-id=%s at %s and %s' %
                      (origCredId, '.'.join(origCredCfgPath), '.'.join(
                          duplicates[origCredId])))
            return

        duplicates[origCredId] = origCredCfgPath

        k = '#'.join(
            (cfgTree.getAttrValue('orig-snmp-engine-id-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-transport-domain-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-peer-address-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-bind-address-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-security-model-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-security-level-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-security-name-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-context-engine-id-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-context-name-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-pdu-type-pattern',
                                  *origCredCfgPath),
             cfgTree.getAttrValue('orig-snmp-oid-prefix-pattern',
                                  *origCredCfgPath)))

        log.info(
            'configuring original SNMP peer ID %s (at %s), composite key: %s' %
            (origCredId, '.'.join(origCredCfgPath), k))

        origCredIdList.append((origCredId, re.compile(k)))

    duplicates = {}

    for srvClassCfgPath in cfgTree.getPathsToAttr('server-classification-id'):
        srvClassId = cfgTree.getAttrValue('server-classification-id',
                                          *srvClassCfgPath)
        if srvClassId in duplicates:
            log.error('duplicate server-classification-id=%s at %s and %s' %
                      (srvClassId, '.'.join(srvClassCfgPath), '.'.join(
                          duplicates[srvClassId])))
            return

        duplicates[srvClassId] = srvClassCfgPath

        k = '#'.join(
            (cfgTree.getAttrValue('server-snmp-credentials-id-pattern',
                                  *srvClassCfgPath),
             cfgTree.getAttrValue('server-snmp-context-id-pattern',
                                  *srvClassCfgPath),
             cfgTree.getAttrValue('server-snmp-content-id-pattern',
                                  *srvClassCfgPath),
             cfgTree.getAttrValue('server-snmp-peer-id-pattern',
                                  *srvClassCfgPath)))

        log.info(
            'configuring server classification ID %s (at %s), composite key: %s'
            % (srvClassId, '.'.join(srvClassCfgPath), k))

        srvClassIdList.append((srvClassId, re.compile(k)))

    del duplicates

    for pluginCfgPath in cfgTree.getPathsToAttr('using-plugin-id-list'):
        pluginIdList = cfgTree.getAttrValue('using-plugin-id-list',
                                            *pluginCfgPath,
                                            **dict(vector=True))
        log.info('configuring plugin ID(s) %s (at %s)...' %
                 (','.join(pluginIdList), '.'.join(pluginCfgPath)))
        for credId in cfgTree.getAttrValue('matching-orig-snmp-peer-id-list',
                                           *pluginCfgPath,
                                           **dict(vector=True)):
            for srvClassId in cfgTree.getAttrValue(
                    'matching-server-classification-id-list', *pluginCfgPath,
                    **dict(vector=True)):
                for trunkId in cfgTree.getAttrValue('matching-trunk-id-list',
                                                    *pluginCfgPath,
                                                    **dict(vector=True)):
                    k = credId, srvClassId, trunkId
                    if k in pluginIdMap:
                        log.error(
                            'duplicate snmp-credentials-id=%s and server-classification-id=%s and trunk-id=%s at plugin-id %s'
                            % (credId, srvClassId, trunkId,
                               ','.join(pluginIdList)))
                        return
                    else:
                        log.info(
                            'configuring plugin(s) %s (at %s), composite key: %s'
                            % (','.join(pluginIdList), '.'.join(pluginCfgPath),
                               '/'.join(k)))

                        for pluginId in pluginIdList:
                            if not pluginManager.hasPlugin(pluginId):
                                log.error(
                                    'undefined plugin ID %s referenced at %s' %
                                    (pluginId, '.'.join(pluginCfgPath)))
                                return

                        pluginIdMap[k] = pluginIdList

    for routeCfgPath in cfgTree.getPathsToAttr('using-snmp-peer-id-list'):
        peerIdList = cfgTree.getAttrValue('using-snmp-peer-id-list',
                                          *routeCfgPath, **dict(vector=True))
        log.info('configuring routing entry with peer IDs %s (at %s)...' %
                 (','.join(peerIdList), '.'.join(routeCfgPath)))
        for credId in cfgTree.getAttrValue('matching-orig-snmp-peer-id-list',
                                           *routeCfgPath, **dict(vector=True)):
            for srvClassId in cfgTree.getAttrValue(
                    'matching-server-classification-id-list', *routeCfgPath,
                    **dict(vector=True)):
                for trunkId in cfgTree.getAttrValue('matching-trunk-id-list',
                                                    *routeCfgPath,
                                                    **dict(vector=True)):
                    k = credId, srvClassId, trunkId
                    if k in routingMap:
                        log.error(
                            'duplicate snmp-credentials-id=%s and server-classification-id=%s and trunk-id=%s at snmp-peer-id %s'
                            % (credId, srvClassId, trunkId,
                               ','.join(peerIdList)))
                        return
                    else:
                        for peerId in peerIdList:
                            if peerId not in peerIdMap:
                                log.error('missing peer-id %s at %s' %
                                          (peerId, '.'.join(routeCfgPath)))
                                return

                        routingMap[k] = peerIdList

    trunkingManager = TrunkingManager(trunkCbFun)

    for trunkCfgPath in cfgTree.getPathsToAttr('trunk-id'):
        trunkId = cfgTree.getAttrValue('trunk-id', *trunkCfgPath)
        secret = cfgTree.getAttrValue('trunk-crypto-key', *trunkCfgPath,
                                      **dict(default=''))
        secret = secret and (secret * ((16 // len(secret)) + 1))[:16]
        log.info('configuring trunk ID %s (at %s)...' %
                 (trunkId, '.'.join(trunkCfgPath)))
        connectionMode = cfgTree.getAttrValue('trunk-connection-mode',
                                              *trunkCfgPath)
        if connectionMode == 'client':
            trunkingManager.addClient(
                trunkId,
                parseTrunkEndpoint(
                    cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath)),
                parseTrunkEndpoint(
                    cfgTree.getAttrValue('trunk-peer-address', *trunkCfgPath),
                    30201),
                cfgTree.getAttrValue('trunk-ping-period',
                                     *trunkCfgPath,
                                     default=0,
                                     expect=int), secret)
            log.info(
                'new trunking client from %s to %s' %
                (cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath),
                 cfgTree.getAttrValue('trunk-peer-address', *trunkCfgPath)))
        if connectionMode == 'server':
            trunkingManager.addServer(
                parseTrunkEndpoint(
                    cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath),
                    30201),
                cfgTree.getAttrValue('trunk-ping-period',
                                     *trunkCfgPath,
                                     default=0,
                                     expect=int), secret)
            log.info(
                'new trunking server at %s' %
                (cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath)))

    transportDispatcher.registerTimerCbFun(trunkingManager.setupTrunks,
                                           random.randrange(1, 5))
    transportDispatcher.registerTimerCbFun(trunkingManager.monitorTrunks,
                                           random.randrange(1, 5))

    if not foregroundFlag:
        try:
            daemon.daemonize(pidFile)

        except Exception:
            log.error('can not daemonize process: %s' % sys.exc_info()[1])
            return

    # Run mainloop

    log.info('starting I/O engine...')

    transportDispatcher.jobStarted(1)  # server job would never finish

    # Python 2.4 does not support the "finally" clause

    with daemon.PrivilegesOf(procUser, procGroup, final=True):

        while True:
            try:
                transportDispatcher.runDispatcher()

            except (PySnmpError, SnmpfwdError, socket.error):
                log.error(str(sys.exc_info()[1]))
                continue

            except Exception:
                transportDispatcher.closeDispatcher()
                raise