Beispiel #1
0
    def __init__(self, objects):

        self._snmpEngine = engine.SnmpEngine()

        config.addSocketTransport( self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((_addr, _port)))
        config.addV3User(self._snmpEngine,_account,config.usmHMACMD5AuthProtocol,_auth_key,config.usmDESPrivProtocol,_priv_key)
        config.addVacmUser(self._snmpEngine, 3, _account, "authPriv",(1,3,6,1,4,1), (1,3,6,1,4,1))

        self._snmpContext = context.SnmpContext(self._snmpEngine)


        #builder create
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'),)+(builder.DirMibSource(filepath),)
        mibBuilder.setMibSources(*mibSources)


        MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI','MibScalarInstance')

        for mibObject in objects:
            nextVar, = mibBuilder.importSymbols(mibObject.mibName,
                                                mibObject.objectType)
            instance = createVariable(MibScalarInstance, mibObject.valueGetFunc, nextVar.name, (0,),  nextVar.syntax)
            #need to export as <var name>Instance
            instanceDict = {str(nextVar.name)+"Instance":instance}
            mibBuilder.exportSymbols(mibObject.mibName, **instanceDict)

        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #2
0
 def __one_time_init(self):
     self.listen_address = '0.0.0.0' # Set by TrapEngine
     self.listen_port = 162          # Set by TrapEngine
     self.owner = None               # Set by TrapEngine
     self.trap_view = None           # Set by TrapEngine
     self.trap_log = None            # Set by TrapEngine
     self.socket_map = socketmap.SocketMap()
     self.snmpEngine = engine.SnmpEngine()
     transportDispatcher = dispatch.AsynsockDispatcher()
     transportDispatcher.setSocketMap(self.socket_map)
     self.snmpEngine.registerTransportDispatcher(transportDispatcher)
     # @note As of PySNMP 4.1.9a, receipt of a V3 notification with out
     #       any registerred V3 users results in a traceback.
     self.addV3User('\0',
                    config.usmNoAuthProtocol, '\0'*8,
                    config.usmNoPrivProtocol, '\0'*8)
     def cbFun(snmpEngine,
               contextEngineId,
               contextName,
               varBinds,
               trap_thread):
         trap_thread._TrapThread__callback(contextEngineId, contextName,
                                           varBinds)
         return
     self.receiver = ntfrcv.NotificationReceiver(self.snmpEngine,
                                                 cbFun, self)
     # Setup transport endpoint
     config.addSocketTransport(
         self.snmpEngine,
         udp.domainName,
         udp.UdpSocketTransport().openServerMode((self.listen_address,
                                                  self.listen_port))
         )
     return
     def run(self):
         
        snmpEngine = engine.SnmpEngine()
        
        if self.ipv6:
            domainName = udp6.domainName
            config.addSocketTransport(snmpEngine,domainName,udp6.Udp6Transport().openServerMode((self.host, self.port)))
        else:
            domainName = udp.domainName
            config.addSocketTransport(snmpEngine,domainName,udp.UdpTransport().openServerMode((self.host, self.port))) 
            
        config.addV3User(snmpEngine, self.user,self.auth_proto, self.auth_key,self.priv_proto,self.priv_key)
  
        # Register SNMP Application at the SNMP engine
        ntfrcv.NotificationReceiver(snmpEngine, v3trapCallback)

        snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish

        # Run I/O dispatcher which would receive queries and send confirmations
        try:
            snmpEngine.transportDispatcher.runDispatcher()
        except: # catch *all* exceptions
            e = sys.exc_info()[1]
            snmpEngine.transportDispatcher.closeDispatcher()
            logging.error("Looks like an error: %s" % str(e))
            sys.exit(1)
Beispiel #4
0
    def __init__(self, client_config=None):
        if not client_config:
            client_config = conpot_config
        # Create SNMP engine instance
        self.snmpEngine = engine.SnmpEngine()

        # user: usr-sha-aes, auth: SHA, priv AES
        config.addV3User(
            self.snmpEngine, 'usr-sha-aes128',
            config.usmHMACSHAAuthProtocol, 'authkey1',
            config.usmAesCfb128Protocol, 'privkey1'
        )
        config.addTargetParams(self.snmpEngine, 'my-creds', 'usr-sha-aes128', 'authPriv')

        # Setup transport endpoint and bind it with security settings yielding
        # a target name (choose one entry depending of the transport needed).

        # UDP/IPv4
        config.addSocketTransport(
            self.snmpEngine,
            udp.domainName,
            udp.UdpSocketTransport().openClientMode()
        )
        config.addTargetAddr(
            self.snmpEngine, 'my-router',
            udp.domainName, (client_config.snmp_host, client_config.snmp_port),
            'my-creds'
        )
    def __init__(self, udpIp, udpPort):
        # Create SNMP engine with autogenernated engineID and pre-bound
        # to socket transport dispatcher
        self.snmpEngine = engine.SnmpEngine()
        self.mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        mibPath = self.mibBuilder.getMibPath() + ('.',)
        self.mibBuilder.setMibPath(*mibPath)

        # Setup UDP over IPv4 transport endpoint
        config.addSocketTransport(
            self.snmpEngine,
            udp.domainName,
            udp.UdpSocketTransport().openServerMode((udpIp, udpPort))
        )

        print 'Publishing readings via SNMP'
        print 'Agent address {}:{}'.format(udpIp, udpPort)
        print 'Community name public'

        # v1/2 setup
        config.addV1System(self.snmpEngine, 'test-agent', 'public')

        # v3 setup
        config.addV3User(
            self.snmpEngine, 'test-user'
        )

        # VACM setup
        config.addContext(self.snmpEngine, '')
        config.addRwUser(self.snmpEngine, 1, 'test-agent', 'noAuthNoPriv', (1,3,6)) # v1
        config.addRwUser(self.snmpEngine, 2, 'test-agent', 'noAuthNoPriv', (1,3,6)) # v2c
        config.addRwUser(self.snmpEngine, 3, 'test-user', 'noAuthNoPriv', (1,3,6)) # v3

        # SNMP context
        snmpContext = context.SnmpContext(self.snmpEngine)

        # Apps registration
        cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.SetCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.NextCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.BulkCommandResponder(self.snmpEngine, snmpContext)

        MibScalarInstance, = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance')

        class ScalarFromCallback(MibScalarInstance):
            def __init__(self, sensorId, valueGetter, typeName, instId, syntax):
                MibScalarInstance.__init__(self, typeName, instId, syntax)
                self.valueGetter = valueGetter

            def readTest(self, name, val, idx, (acFun, acCtx)):
                if not self.valueGetter():
                    raise error.NoAccessError(idx=idx, name=name)

            def readGet(self, name, val, idx, (acFun, acCtx)):
                value = self.valueGetter()
                if not value:
                    raise error.NoAccessError(idx=idx, name=name)
                else:
                    return name, self.syntax.clone(value)
Beispiel #6
0
    def __init__(self, mibObjects, sqlObject, _rootDir, server_options):
        """
        mibObjects - a list of MibObject tuples that this agent
        will serve
        """
        #each SNMP-based application has an engine
        self._snmpEngine = engine.SnmpEngine()

        #open a UDP socket to listen for snmp requests
        config.addSocketTransport(self._snmpEngine, udp.domainName,
                                  udp.UdpTransport().openServerMode(('', int(server_options['port']))))

        #add a v2 user with the community string public
        config.addV1System(self._snmpEngine, "agent", server_options['community'])
        #let anyone accessing 'public' read anything in the subtree below,
        #which is the enterprises subtree that we defined our MIB to be in
        config.addVacmUser(self._snmpEngine, int(server_options['version']), "agent", "noAuthNoPriv", readSubTree=(1,3,6,1,4,1))

        #each app has one or more contexts
        self._snmpContext = context.SnmpContext(self._snmpEngine)

        #the builder is used to load mibs. tell it to look in the
        #current directory for our new MIB. We'll also use it to
        #export our symbols later
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource(os.path.join(_rootDir, 'lib_mib_py')),)
        mibBuilder.setMibSources(*mibSources)

        #our variables will subclass this since we only have scalar types
        #can't load this type directly, need to import it
        MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalarInstance')

        #export our custom mib
        for mibObject in mibObjects:
            nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType)
            if mibObject.objMib.flag:
		#je suis une table

		for client in sqlObject.getClientsId():
		    instance = createVariable(MibScalarInstance, mibObject.objMib, mibObject.valueFunc, nextVar.name,(client['ClientId'],), nextVar.syntax)
		    listName = list(nextVar.name)
		    listName.append(client['ClientId'] )
		    newName = tuple(listName)
	    	    instanceDict = {str(newName)+"Instance":instance}
           	    mibBuilder.exportSymbols(mibObject.mibName, **instanceDict)

	    else :
		instance = createVariable(MibScalarInstance, mibObject.objMib, mibObject.valueFunc, nextVar.name,(0,), nextVar.syntax)
                                             #class         ,class with fonc , nom de la fonction , oid               , type d'oid

            	#need to export as <var name>Instance
	        instanceDict = {str(nextVar.name)+"Instance":instance}
	   	mibBuilder.exportSymbols(mibObject.mibName, **instanceDict)


        # tell pysnmp to respotd to get, getnext, and getbulk
        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #7
0
    def cfgCmdGen(self, authData, transportTarget, tagList=''):
        if self.__knownAuths.has_key(authData):
            paramsName = self.__knownAuths[authData]
        else:
            paramsName = 'p%s' % nextID()
            if isinstance(authData, CommunityData):
                config.addV1System(
                    self.snmpEngine,
                    authData.securityName,
                    authData.communityName
                    )
                config.addTargetParams(
                    self.snmpEngine, paramsName,
                    authData.securityName, authData.securityLevel,
                    authData.mpModel
                    )
            elif isinstance(authData, UsmUserData):
                config.addV3User(
                    self.snmpEngine,
                    authData.securityName,
                    authData.authProtocol, authData.authKey,
                    authData.privProtocol, authData.privKey
                    )
                config.addTargetParams(
                    self.snmpEngine, paramsName,
                    authData.securityName, authData.securityLevel
                    )
            else:
                raise error.PySnmpError('Unsupported SNMP version')
            self.__knownAuths[authData] = paramsName

        if not self.__knownTransports.has_key(transportTarget.transportDomain):
            transport = transportTarget.openClientMode()
            config.addSocketTransport(
                self.snmpEngine,
                transportTarget.transportDomain,
                transport
                )
            self.__knownTransports[transportTarget.transportDomain] = transport

        k = transportTarget, tagList
        if self.__knownTransportAddrs.has_key(k):
            addrName = self.__knownTransportAddrs[k]
        else:
            addrName = 'a%s' % nextID()
            config.addTargetAddr(
                self.snmpEngine, addrName,
                transportTarget.transportDomain,
                transportTarget.transportAddr,
                paramsName,
                transportTarget.timeout * 100,
                transportTarget.retries,
                tagList                
                )
            self.__knownTransportAddrs[k] = addrName

        return addrName, paramsName
def test2():
    from pysnmp.v4.proto.rfc1902 import ObjectName
    from pysnmp.entity import engine, config
    from pysnmp.carrier.asynsock.dgram import udp
    from pysnmp.entity.rfc3413 import cmdgen
    
    sysName = ObjectName("1.3.6.1.2.1.1.5.0")
    ip = "192.168.1.9"
    snmp_engine = engine.SnmpEngine()
    config.addV1System(snmp_engine, 'test-agent', "public")
    config.addTargetParams(snmp_engine, 'myParams', 'test-agent', 'noAuthNoPriv', 0)
    config.addTargetAddr(
        snmp_engine, 'myRouter', config.snmpUDPDomain,
        (ip, 161), 'myParams'
        )
    config.addSocketTransport(
        snmp_engine,
        udp.domainName,
        udp.UdpSocketTransport().openClientMode()
        )

    cb = {}
    
    def cbFun(sendRequestHandle, errorIndication, errorStatus, errorIndex,
              varBinds, cbCtx):
        cbCtx['errorIndication'] = errorIndication
        cbCtx['errorStatus'] = errorStatus
        cbCtx['errorIndex'] = errorIndex
        cbCtx['varBinds'] = varBinds
        

    cmdgen.GetCommandGenerator().sendReq(snmp_engine, 'myRouter', ((sysName, None),), cbFun, cb)
        
        
    lastmemusage = 0
    lastrefs = None
    errors = 0
    while (errors < 2):
        snmp_engine.transportDispatcher.runDispatcher()
        print cb['varBinds'][0][1]
        snmp_engine.transportDispatcher.closeDispatcher()
        #asynCommandGenerator.flushConfig()
        newmemusage = resource.getrusage(resource.RUSAGE_SELF)[2]
        memdiff = (newmemusage - lastmemusage)
        newrefs = get_refcounts()
        if memdiff > 0:
            print "Leaked %d Kb... printing refcount diff" % memdiff
            if lastrefs == None:
                print "No previous refcount, skipping"
            else:
                print_ref_diffs(lastrefs, newrefs)
                errors = errors + 1
        gc.collect()
        lastrefs = newrefs
        lastmemusage = newmemusage
        #print resource.getrusage(resource.RUSAGE_SELF)[3]
        time.sleep(1)
 def __init__(self, host, port, rcommunity):
     self.snmpEngine = engine.SnmpEngine()
     config.addSocketTransport(self.snmpEngine, udp.domainName, udp.UdpTransport().openServerMode((host, port)))
     config.addV1System(self.snmpEngine, 'my-area', rcommunity)
     config.addVacmUser(self.snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 3, 6))
     self.snmpContext = context.SnmpContext(self.snmpEngine)
     self.mibBuilder = self.snmpContext.getMibInstrum().getMibBuilder()
     self.MibScalar, self.MibScalarInstance = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalar', 'MibScalarInstance')
     cmdrsp.GetCommandResponder(self.snmpEngine, self.snmpContext)
     cmdrsp.NextCommandResponder(self.snmpEngine, self.snmpContext)
     cmdrsp.BulkCommandResponder(self.snmpEngine, self.snmpContext)
Beispiel #10
0
    def __init__(self, host, port, community):
        self.snmp = engine.SnmpEngine()
        self.snmp.registerTransportDispatcher(dispatch.TwistedDispatcher())

        config.addV1System(self.snmp, 'my-area', community)
        config.addTargetParams(self.snmp,
            'my-creds', 'my-area', 'noAuthNoPriv', 0)
        config.addSocketTransport(self.snmp,
            udp.domainName, udp.UdpTwistedTransport().openClientMode()
        )
        config.addTargetAddr(self.snmp, 'my-router', udp.domainName,
            (host, port), 'my-creds')
Beispiel #11
0
    def __init__(self, host, port, users, naming_scheme):
        """
        host = public ip to listen on
        port = port to listen on (usually 161)
        users = list of ('username', 'password', 'privatekey', 'authPriv') #authentication method for snmp v3
        if users is None, authentication will be snmp v1 public community string, read only
        """
        self.naming_scheme = naming_scheme

        self.run = True
        self.users = users
        # Create SNMP engine
        self.snmpEngine = engine.SnmpEngine()
        # Get default SNMP context this SNMP engine serves
        self.snmpContext = context.SnmpContext(self.snmpEngine)
        # MIB builder
        self.mibBuilder = self.snmpContext.getMibInstrum().getMibBuilder()
        self.MibScalar, self.MibScalarInstance = self.mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalar', 'MibScalarInstance')

        # Transport setup
        # UDP over IPv4
        try:
            config.addSocketTransport(self.snmpEngine,
                                      udp.domainName,
                                      udp.UdpTransport().openServerMode((host, port)))
            print('Serving on port %s' % port)
        except error.CarrierError as carrier_error :
            if "[Errno 98]" in carrier_error.message:
                raise RuntimeError('Port %s is in use' % port)

        # SNMPv3/USM setup
        # user: usr-md5-des, auth: MD5, priv DES
        if users:
            for user in users:
                self._add_v3_md5_des_user(user)
                # Allow full MIB access for each user at VACM
        else:
            # SNMPv1 public community string setup
            config.addV1System(self.snmpEngine, 'my-read-area', 'public')

        self._add_user_permission("1.3.6.1.2.1") #full walk permission, without this snmpwalk returns None

        # Overwrite default strings with custom name
        sysDescr, = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols('SNMPv2-MIB', 'sysDescr')
        sysDescr = self.MibScalarInstance(sysDescr.name,
                                          (0,),
                                          sysDescr.syntax.clone("PySNMP engine - OVS 1.2.0 SNMP Agent")) # Get from config?
        self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.exportSymbols('SNMPv2-MIB', sysDescr)
        self._add_user_permission(self.naming_scheme.replace('.%s', ''))
Beispiel #12
0
    def __init__(self, community, ip, version=1):
        self.__community = community
        self.__ip = ip
        self.__version = version
        self.__errorIndication = None
        self.__errorStatus = None
        self.__errorIndex = None
        self.__varBinds = None
        # self.__lock = threading.Lock()

        self.__snmp_engine = engine.SnmpEngine()
        config.addV1System(self.__snmp_engine, "test-agent", self.__community)
        config.addTargetParams(self.__snmp_engine, "myParams", "test-agent", "noAuthNoPriv", self.__version)
        config.addTargetAddr(self.__snmp_engine, "myRouter", config.snmpUDPDomain, (self.__ip, 161), "myParams")
        config.addSocketTransport(self.__snmp_engine, udp.domainName, udp.UdpSocketTransport().openClientMode())
Beispiel #13
0
def initTarget(host='127.0.0.1', port=162, community='LIC_OSS'):
    #global snmpEngine, snmpContext, ntfOrg
    # Create SNMP engine instance
    snmpEngine = engine.SnmpEngine()
    
    # SecurityName <-> CommunityName mapping
    config.addV1System(snmpEngine, 'my-area', community)
    
    # 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, (host, port),
        '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)
    return snmpEngine, ntfOrg
Beispiel #14
0
	def __init__(self):
		self.unReadyNodes = list()
		self.identifiers  = dict()
		self.snmpEngine   = engine.SnmpEngine()
		self.bcmdgen      = cmdgen.BulkCommandGenerator()

		self.snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
		config.addV1System(self.snmpEngine, 'test-agent', SNMP_COMMUNITY)
		config.addTargetParams(self.snmpEngine, 'myParams', 'test-agent', 'noAuthNoPriv', 1)

		config.addSocketTransport(
	        self.snmpEngine,
	        udp.domainName,
	        udp.UdpTwistedTransport().openClientMode()
	        )

		self.carbonFact = CarbonFactory(self)
		reactor.connectTCP(GRAPHITE_HOST, 2003, self.carbonFact)
Beispiel #15
0
 def __init__(self):
     self.snmpEngine = engine.SnmpEngine()
     
     config.addSocketTransport(
         self.snmpEngine,
         udp.domainName,
         udp.UdpSocketTransport().openServerMode(('0.0.0.0', 162))
         )
         
     config.addV1System(self.snmpEngine, 'test-agent', 'public')
     
     config.addV3User(
         self.snmpEngine, 'test-user',
         config.usmHMACMD5AuthProtocol, 'authkey1',
         config.usmDESPrivProtocol, 'privkey1'
         #    '80004fb81c3dafe69'   # ContextEngineID of Notification Originator
         )
     # Apps registration
     ntfrcv.NotificationReceiver(self.snmpEngine, self.recvcallback)
     self.snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
     self.snmpEngine.transportDispatcher.runDispatcher()
def main(argv):
    # Create SNMP engine instance
    snmpEngine = engine.SnmpEngine()
    dispatcher = TornadoDispatcher()
    snmpEngine.registerTransportDispatcher(dispatcher)

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

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

    # UDP/IPv4
    config.addSocketTransport(
        snmpEngine,
        udp.domainName,
        udp.UdpSocketTransport().openClientMode()
    )
    config.addTargetAddr(
        snmpEngine,
        'my-router',
        udp.domainName,
        (argv[0], 161),
        'my-creds',
        timeout=3.0,
        retryCount=1
    )

    cbCtx = dict(dispatcher=dispatcher)

    cmdGen = cmdgen.GetCommandGenerator()
    cmdGen.sendReq(
        snmpEngine,
        'my-router',
        ( ('1.3.6.1.2.1.1.1.0', None), ),
        cbFun,
        cbCtx
    )

    IOLoop.instance().start()
Beispiel #17
0
    def run(self):
        snmpEngine = engine.SnmpEngine()

        config.addSocketTransport(
            snmpEngine,
            udp.domainName,
            udp.UdpTransport().openServerMode(('127.0.0.1',
                                               self.__listening_port))
        )

        config.addV1System(
                     snmpEngine, 'my-area', 'public', contextName='my-context')

        config.addVacmUser(snmpEngine=snmpEngine,
                           securityModel=2,
                           securityName='my-area',
                           securityLevel='noAuthNoPriv',
                           readSubTree=SNMPAgentResponder.OID_PREFIX,
                           writeSubTree=(),
                           notifySubTree=())

        snmpContext = context.SnmpContext(snmpEngine)

        snmpContext.registerContextName(
            v2c.OctetString('my-context'),         # Context Name
            self.__responder                       # Management Instrumentation
        )

        cmdrsp.GetCommandResponder(snmpEngine, snmpContext)

        snmpEngine.transportDispatcher.jobStarted(1)
        self.__barrier.wait()

        # TODO with statement here!
        try:
            snmpEngine.transportDispatcher.runDispatcher()
        except:
            snmpEngine.transportDispatcher.closeDispatcher()
            raise
    def __init__(self, mibObjects):
        # Each SNMP-based application has an engine
        self._snmpEngine = engine.SnmpEngine()

        # Open a UDP socket to listen for snmp requests (requset sudo command)
        config.addSocketTransport(self._snmpEngine,
                                  udp.domainName,
                                  udp.UdpTransport().openServerMode(('', 161)))
        config.addV1System(self._snmpEngine, 'agent', 'public')
        # add a v2 user with the community string public
        config.addVacmUser(self._snmpEngine, 2, 'agent', 'noAuthNoPriv',
                           readSubTree=(1, 3, 6, 1, 4, 1),
                           writeSubTree=(1, 3, 6, 1, 4, 1))
        # each app has one or more contexts
        self._snmpContext = context.SnmpContext(self._snmpEngine)
        # the builder is used to load mibs. tell it to look in the
        # current directory for our new MIB. We'll also use it to
        # export our symbols later
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'),)
        mibBuilder.setMibSources(*mibSources)
        # our variables will subclass this since we only have scalar types
        # can't load this type directly, need to import it
        (MibTable, MibTableRow, MibTableColumn,
         MibScalarInstance) = mibBuilder.importSymbols('SNMPv2-SMI',
                                                       'MibTable',
                                                       'MibTableRow',
                                                       'MibTableColumn',
                                                       'MibScalarInstance')
        # import and maintain Table
        maintaintable = maintainTableThread(0, mibObjects, mibBuilder,
                                            MibScalarInstance)
        maintaintable.start()
        # tell pysnmp to respotd to get, getnext, and getbulk
        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #19
0
  def __init__(self, mibObjects):
    self._snmpEngine = engine.SnmpEngine()
    config.addSocketTransport(self._snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('',165)))
    config.addV1System(self._snmpEngine,"my-read-area","public")
    config.addV1System(self._snmpEngine,"my-write-area","private")
    config.addVacmUser(self._snmpEngine, 2,"my-read-area",'noAuthNoPriv',readSubTree=(1,3,6,1,4,1))
    config.addVacmUser(self._snmpEngine, 2,"my-write-area",'noAuthNoPriv',readSubTree=(1,3,6,1,4,1), writeSubTree=(1,3,6,1,4,1))
    self._snmpContext = context.SnmpContext(self._snmpEngine)

    mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
    mibSources = mibBuilder.getMibSources()+(builder.DirMibSource('.'),)+(builder.DirMibSource('./pysnmp_mibs'),)
    mibBuilder.setMibSources(*mibSources)

    MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI','MibScalarInstance')
    for mibObject in mibObjects:
      nextVar, = mibBuilder.importSymbols(mibObject.mibName, mibObject.objectType)
      instance = createVariable(MibScalarInstance, mibObject.valueGetFunc, mibObject.valueSetFunc, nextVar.name, (0,), nextVar.syntax)
      instanceDict ={ str(nextVar.name)+"Instance":instance }
      mibBuilder.exportSymbols(mibObject.mibName, **instanceDict)

    cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
    cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
    cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #20
0
    def __init__(self, host, port, username, password, snmp_context):
        self.snmp_context = snmp_context

        self.snmp_engine = engine.SnmpEngine()
        # HiT7300 uses the user password for encryption (privacy protocol) pass phrase (PSK?)
        config.addV3User(
            self.snmp_engine, username, config.usmHMACMD5AuthProtocol, password, config.usmAesCfb128Protocol, password
        )

        # pysnmp bug?
        # setting context doesn't affect the getCommandGenerator, so we don't set it
        # FIXME: report upstream and have cmdgen use context of snmpEngine!?
        # config.addContext(self.snmp_engine, 'tnms')
        # snmp_context = context.SnmpContext(self.snmp_engine)

        config.addTargetParams(self.snmp_engine, "myParams", username, "authPriv")
        # config.addTargetParams(self.snmp_engine, 'myParams', username, 'authPriv')

        config.addTargetAddr(self.snmp_engine, "myTarget", config.snmpUDPDomain, (host, int(port)), "myParams")

        config.addSocketTransport(self.snmp_engine, udp.domainName, udp.UdpSocketTransport().openClientMode())

        self.cbCtx = {}
Beispiel #21
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()
Beispiel #22
0
    def __init__(self, mibObjects):
        """
        mibObjects - a list of MibObject tuples that this agent
        will serve
        """

        #each SNMP-based application has an engine
        self._snmpEngine = engine.SnmpEngine()

        #open a UDP socket to listen for snmp requests
        config.addSocketTransport(self._snmpEngine, udp.domainName,
                                  udp.UdpTransport().openServerMode(('', 161)))

        #add a v2 user with the community string public
        config.addV1System(self._snmpEngine, "agent", "public")
        config.addV1System(self._snmpEngine, 'write-area', 'private')
        #let anyone accessing 'public' read anything in the subtree below,
        #which is the enterprises subtree that we defined our MIB to be in
        config.addVacmUser(self._snmpEngine, 2, "agent", "noAuthNoPriv",
                           readSubTree=(1,3,6,1,4,1))
                           
        config.addVacmUser(self._snmpEngine, 2, 'write-area', 'noAuthNoPriv',
            readSubTree=(1,3,6,1,4,1), writeSubTree=(1,3,6,1,4,1))

        #each app has one or more contexts
        self._snmpContext = context.SnmpContext(self._snmpEngine)

        #the builder is used to load mibs. tell it to look in the
        #current directory for our new MIB. We'll also use it to
        #export our symbols later
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'),)
        mibBuilder.setMibSources(*mibSources)
        
        Integer, ObjectIdentifier, OctetString = mibBuilder.importSymbols("ASN1", "Integer", "ObjectIdentifier", "OctetString")
        MibScalar, MibScalarInstance = mibBuilder.importSymbols(
            'SNMPv2-SMI', 'MibScalar', 'MibScalarInstance'
        )
        
        NamedValues, = mibBuilder.importSymbols("ASN1-ENUMERATION", "NamedValues")
        ConstraintsUnion, SingleValueConstraint, ConstraintsIntersection, ValueSizeConstraint, ValueRangeConstraint = mibBuilder.importSymbols("ASN1-REFINEMENT", "ConstraintsUnion", "SingleValueConstraint", "ConstraintsIntersection", "ValueSizeConstraint", "ValueRangeConstraint")
        NotificationGroup, ModuleCompliance, ObjectGroup = mibBuilder.importSymbols("SNMPv2-CONF", "NotificationGroup", "ModuleCompliance", "ObjectGroup")
        Integer32, MibScalar, MibTable, MibTableRow, MibTableColumn, NotificationType, MibIdentifier, IpAddress, TimeTicks, Counter64, Unsigned32, enterprises, iso, Gauge32, ModuleIdentity, ObjectIdentity, Bits, Counter32 = mibBuilder.importSymbols("SNMPv2-SMI", "Integer32", "MibScalar", "MibTable", "MibTableRow", "MibTableColumn", "NotificationType", "MibIdentifier", "IpAddress", "TimeTicks", "Counter64", "Unsigned32", "enterprises", "iso", "Gauge32", "ModuleIdentity", "ObjectIdentity", "Bits", "Counter32")
        DisplayString, TextualConvention = mibBuilder.importSymbols("SNMPv2-TC", "DisplayString", "TextualConvention")
        dockerRoot = ObjectIdentity((1, 3, 6, 1, 4, 1, 12345))
        if mibBuilder.loadTexts: dockerRoot.setStatus('current')
        dockerDaemon = MibIdentifier((1, 3, 6, 1, 4, 1, 12345, 1))
        dockerDaemonUptime = MibScalar((1, 3, 6, 1, 4, 1, 12345, 1, 1), TimeTicks()).setMaxAccess("readonly")
        dockerDaemonRestart = MibScalar((1, 3, 6, 1, 4, 1, 12345, 1, 2), Integer32().subtype(subtypeSpec=SingleValueConstraint(0, 1)).clone(namedValues=NamedValues(("notRestarting", 0), ("restaring", 1)))).setMaxAccess("readwrite")
        if mibBuilder.loadTexts: dockerDaemonRestart.setStatus('current')
        dockerDaemonMandatoryImplementations = ObjectGroup((1, 3, 6, 1, 4, 1, 12345, 1, 3)).setObjects(("ANDRE-GLOBAL-REG", "dockerDaemonUptime"), ("ANDRE-GLOBAL-REG", "dockerDaemonRestart"))
        if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
            dockerDaemonMandatoryImplementations = dockerDaemonMandatoryImplementations.setStatus('current')
        dockerContainers = MibIdentifier((1, 3, 6, 1, 4, 1, 12345, 2))
        containeListTable = MibTable((1, 3, 6, 1, 4, 1, 12345, 2, 1), )
        if mibBuilder.loadTexts: containeListTable.setStatus('current')
        containeListEntry = MibTableRow((1, 3, 6, 1, 4, 1, 12345, 2, 1, 1), ).setIndexNames((0, "ANDRE-GLOBAL-REG", "containeListHashIdentifier"), (0, "ANDRE-GLOBAL-REG", "containeListUptime"), (0, "ANDRE-GLOBAL-REG", "containeListName"), (0, "ANDRE-GLOBAL-REG", "containeListStatus"))
        if mibBuilder.loadTexts: containeListEntry.setStatus('current')
        containeListHashIdentifier = MibTableColumn((1, 3, 6, 1, 4, 1, 12345, 2, 1, 1, 1), OctetString()).setMaxAccess("readonly")
        if mibBuilder.loadTexts: containeListHashIdentifier.setStatus('current')
        containeListImageID = MibTableColumn((1, 3, 6, 1, 4, 1, 12345, 2, 1, 1, 2), OctetString()).setMaxAccess("readonly")
        if mibBuilder.loadTexts: containeListUptime.setStatus('current')
        containeListName = MibTableColumn((1, 3, 6, 1, 4, 1, 12345, 2, 1, 1, 3), OctetString()).setMaxAccess("readonly")
        if mibBuilder.loadTexts: containeListName.setStatus('current')
        containeListStatus = MibTableColumn((1, 3, 6, 1, 4, 1, 12345, 2, 1, 1, 4), OctetString()).setMaxAccess("readonly")
        if mibBuilder.loadTexts: containeListStatus.setStatus('current')
        mibBuilder.exportSymbols("ANDRE-GLOBAL-REG", dockerContainers=dockerContainers, containeListName=containeListName, dockerRoot=dockerRoot, containeListEntry=containeListEntry, containeListImageID=containeListImageID, dockerDaemonUptime=dockerDaemonUptime, dockerDaemonRestart=dockerDaemonRestart, containeListStatus=containeListStatus, dockerDaemon=dockerDaemon, dockerDaemonMandatoryImplementations=dockerDaemonMandatoryImplementations, containeListHashIdentifier=containeListHashIdentifier, containeListTable=containeListTable)
        
        container_info = getDockerProcesses()
        docker_informations = loads(check_output(['curl','--unix-socket','/var/run/docker.sock', 'http://localhost/containers/json']))
        print docker_informations[0]
        
        
        
        class DockerDaemonUpTimeMibScalarInstance(MibScalarInstance):
            def getValue(self, name, idx):
                out = check_output(['ps', 'aux'])
                res = [line for line in  out.split('\n') if 'MacOS/Docker' in line][0].split()[1]
                print res
                if res == [] or res == '':
                    result = 0
                    return self.getSyntax().clone(result)
                    
                out = check_output(['ps', '-o', 'etime=','-p',res])
                print out
                try:
                    try:
                        t=datetime.datetime.strptime(out,'%H:%M:%S\n')
                    except:
                        t=datetime.datetime.strptime(out,'%M:%S\n')
                except:
                    result = 0
                    return self.getSyntax().clone(result)
                result =  (((t.hour * 60) + t.minute) * 60 + t.second) * 100
                return self.getSyntax().clone(result)
                
                dockerDaemonRestart
                
        class DockerDaemonRestartMibScalarInstance(MibScalarInstance):
            
            MaxAccess = "readwrite"
            def getValue(self, name, idx):
                return self.getSyntax().clone(0)
                
            def setValue(self, value, name, idx):
                if value == 1:
                    for i in range(len(container_info) - 1):
                        print i
                        Popen(["curl", "-d", "''", "--unix-socket", "/var/run/docker.sock", "http://localhost/containers/" + docker_informations[i]["Id"] + "/restart"])
                if hasattr(self.syntax, 'setValue'):
                    return self.syntax.setValue(value)
                else:
                    return self.syntax.clone(value)
                    
        class ContaineListHashIdentifierStateInstance(MibScalarInstance):
          def readGet(self, name, val, *args):
            try:
                docker_informations = loads(check_output(['curl','--unix-socket','/var/run/docker.sock', 'http://localhost/containers/json']))
                return self.name, self.syntax.clone(docker_informations[name[-1] - 1]["Id"])
            except:
              MibScalarInstance.readGet(self, name, val, *args)
              
        class ContaineListNameStateInstance(MibScalarInstance):
          def readGet(self, name, val, *args):
            docker_informations = loads(check_output(['curl','--unix-socket','/var/run/docker.sock', 'http://localhost/containers/json']))
            return self.name, self.syntax.clone(docker_informations[name[-1] - 1]["Image"])
            
        class ContaineListStatusStateInstance(MibScalarInstance):
          def readGet(self, name, val, *args):
            docker_informations = loads(check_output(['curl','--unix-socket','/var/run/docker.sock', 'http://localhost/containers/json']))
            return self.name, self.syntax.clone(docker_informations[name[-1] - 1]["Status"])

        class ContaineListImageIDStateInstance(MibScalarInstance):
          def readGet(self, name, val, *args):
            docker_informations = loads(check_output(['curl','--unix-socket','/var/run/docker.sock', 'http://localhost/containers/json']))
            return self.name, self.syntax.clone(docker_informations[name[-1] - 1]["ImageID"])
                
                
        mibBuilder.exportSymbols("ANDRE-GLOBAL-REG",dockerDaemonUptime, DockerDaemonUpTimeMibScalarInstance((1, 3, 6, 1, 4, 1, 12345, 1, 1),(0,),TimeTicks()))
        mibBuilder.exportSymbols("ANDRE-GLOBAL-REG",dockerDaemonRestart, DockerDaemonRestartMibScalarInstance(dockerDaemonRestart.getName(),(0,),dockerDaemonRestart.getSyntax()).setMaxAccess("readwrite"))
        for i in range(len(docker_informations)):                
            mibBuilder.exportSymbols("ANDRE-GLOBAL-REG",
                ContaineListNameStateInstance(containeListName.getName(), (i+1,), containeListName.getSyntax()),
                ContaineListHashIdentifierStateInstance(containeListHashIdentifier.getName(), (i+1,), containeListHashIdentifier.getSyntax()),
                ContaineListStatusStateInstance(containeListStatus.getName(), (i+1,), containeListStatus.getSyntax()),
                ContaineListImageIDStateInstance(containeListImageID.getName(), (i+1,), containeListImageID.getSyntax()),
            )
        
        #Export Test Table
        

        #our variables will subclass this since we only have scalar types
        #can't load this type directly, need to import it
        MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI',
                                                      'MibScalarInstance')


        # tell pysnmp to respotd to get, getnext, and getbulk
        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
    def __init__(self, udpIp, udpPort):
        # Create SNMP engine with autogenernated engineID and pre-bound
        # to socket transport dispatcher
        self.snmpEngine = engine.SnmpEngine()
        self.mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        mibPath = self.mibBuilder.getMibPath() + ('.', )
        self.mibBuilder.setMibPath(*mibPath)

        # Setup UDP over IPv4 transport endpoint
        config.addSocketTransport(
            self.snmpEngine, udp.domainName,
            udp.UdpSocketTransport().openServerMode((udpIp, udpPort)))

        print 'Publishing readings via SNMP'
        print 'Agent address {}:{}'.format(udpIp, udpPort)
        print 'Community name public'

        # v1/2 setup
        config.addV1System(self.snmpEngine, 'test-agent', 'public')

        # v3 setup
        config.addV3User(self.snmpEngine, 'test-user')

        # VACM setup
        config.addContext(self.snmpEngine, '')
        config.addRwUser(self.snmpEngine, 1, 'test-agent', 'noAuthNoPriv',
                         (1, 3, 6))  # v1
        config.addRwUser(self.snmpEngine, 2, 'test-agent', 'noAuthNoPriv',
                         (1, 3, 6))  # v2c
        config.addRwUser(self.snmpEngine, 3, 'test-user', 'noAuthNoPriv',
                         (1, 3, 6))  # v3

        # SNMP context
        snmpContext = context.SnmpContext(self.snmpEngine)

        # Apps registration
        cmdrsp.GetCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.SetCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.NextCommandResponder(self.snmpEngine, snmpContext)
        cmdrsp.BulkCommandResponder(self.snmpEngine, snmpContext)

        MibScalarInstance, = self.mibBuilder.importSymbols(
            'SNMPv2-SMI', 'MibScalarInstance')

        class ScalarFromCallback(MibScalarInstance):
            def __init__(self, sensorId, valueGetter, typeName, instId,
                         syntax):
                MibScalarInstance.__init__(self, typeName, instId, syntax)
                self.valueGetter = valueGetter

            def readTest(self, name, val, idx, (acFun, acCtx)):
                if not self.valueGetter():
                    raise error.NoAccessError(idx=idx, name=name)

            def readGet(self, name, val, idx, (acFun, acCtx)):
                value = self.valueGetter()
                if not value:
                    raise error.NoAccessError(idx=idx, name=name)
                else:
                    return name, self.syntax.clone(value)
Beispiel #24
0
    def do_run(self):
        '''
        Run sensor.
        '''
        # Too many branches.
        # pylint: disable=R0912

        from pysnmp.error import PySnmpError
        from pysnmp.entity import engine, config
        from pysnmp.carrier.asynsock.dgram import udp, udp6
        from pysnmp.entity.rfc3413 import ntfrcv
        from pysnmp.proto.api import v2c

        # Create SNMP engine with autogenernated engineID and pre-bound
        # to socket transport dispatcher.
        snmp_engine = engine.SnmpEngine()

        # Transport setup.
        try:
            socket.inet_pton(socket.AF_INET, self.config['interface_ip'])
            # UDP over IPv4.
            config.addSocketTransport(
                snmp_engine,
                udp.domainName,
                udp.UdpTransport().openServerMode(
                    (self.config['interface_ip'], self.config['port'])
                )
            )
        except socket.error:
            try:
                socket.inet_pton(socket.AF_INET6, self.config['interface_ip'])
                # UDP over IPv6.
                config.addSocketTransport(
                    snmp_engine,
                    udp6.domainName,
                    udp6.Udp6Transport().openServerMode(
                        (self.config['interface_ip'], self.config['port'])
                    )
                )
            except socket.error:
                self.log('given interface_ip is neither IPv4 nor IPv6 address')
                return
        snmpv3_protocols = {
            'MD5': config.usmHMACMD5AuthProtocol,
            'SHA': config.usmHMACSHAAuthProtocol,
            'DES': config.usmDESPrivProtocol,
            '3DES': config.usm3DESEDEPrivProtocol,
            'AES128': config.usmAesCfb128Protocol,
            'AES192': config.usmAesCfb192Protocol,
            'AES256': config.usmAesCfb256Protocol
        }

        def snmpv3_setup_args(version, authentication=None, encryption=None,
                              auth_key=None, encrypt_key=None, device_id=None):
            '''
            Helper function, parses args.
            '''
            # R0913: Too many arguments
            # pylint: disable=R0913
            del version
            del device_id
            args = [snmp_engine, 'usr-{}-{}'.format(
                authentication.lower() if authentication else 'none',
                encryption.lower() if encryption else 'none'
            )]
            if authentication:
                # Expression not assigned
                # pylint: disable=W0106
                args.append(snmpv3_protocols[authentication]),
                args.append(auth_key)
            if encryption:
                # Expression not assigned
                # pylint: disable=W0106
                args.append(snmpv3_protocols[encryption]),
                args.append(encrypt_key)
            return args
        # Setup devices.
        for device in self.config['devices']:
            if device['version'] == 'v3':
                # SNMPv3 setup.
                if 'device_id' in device:
                    config.addV3User(
                        *snmpv3_setup_args(**device),
                        contextEngineId=v2c.OctetString(hexValue=device['device_id'])
                    )
                else:
                    config.addV3User(*snmpv3_setup_args(**device))
            else:
                # SNMPv1/2c setup.
                # SecurityName <-> CommunityName mapping.
                config.addV1System(
                    snmp_engine,
                    device['index'],
                    device['name']
                )

        def cb_fun(snmp_engine, state_reference, context_engine_id,
                   context_name, var_binds, cb_ctx):
            # Too many arguments
            # pylint: disable=R0913
            '''
            Callback function for receiving notifications.
            '''
            _, transport_address = snmp_engine.msgAndPduDsp.getTransportInfo(
                state_reference
            )
            for name, val in var_binds:
                self.send_results(datetime.utcnow(), (
                    ('sender', transport_address),
                    ('context_engine_id', context_engine_id.prettyPrint()),
                    ('context_name', context_name.prettyPrint()),
                    ('variable_name', name.prettyPrint()),
                    ('variable_value', val.prettyPrint())
                ))

        # Register SNMP Application at the SNMP engine.
        ntfrcv.NotificationReceiver(snmp_engine, cb_fun)

        # This job would never finish.
        snmp_engine.transportDispatcher.jobStarted(1)

        # Run I/O dispatcher which would receive queries and send confirmations.
        try:
            snmp_engine.transportDispatcher.runDispatcher()
        except PySnmpError as err:
            snmp_engine.transportDispatcher.closeDispatcher()
            self.send_results(datetime.utcnow(), (('error', err.message),))
            return
Beispiel #25
0
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdgen
from pysnmp.carrier.asynsock.dgram import udp
import sys
from io import StringIO
oid_list = []
maxRepetitions = 0
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()#添加SNMP引擎实例

# Setup transport endpoint and bind it with security settings yielding
# a target name (choose one entry depending of the transport needed).
# UDP/IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpSocketTransport().openClientMode()
)

# Error/response reciever
def cbFun(sendRequesthandle, errorIndication, errorStatus, errorIndex,
          varBindTable, cbCtx):
    global oid_list
    global maxRepetitions
    if errorIndication:
        print(errorIndication)
        return  # stop on error
    if errorStatus:
        print('%s at %s' % (
            errorStatus.prettyPrint(),
            errorIndex and varBindTable[-1][int(errorIndex)-1] or '?'
except Exception as e:
    logger.error('Some error in configfile %s' % (e))

SENDER = os.environ.get('SENDER')
SENDER_PWD = os.environ.get('SENDER_PWD')

if not SENDER or not SENDER_PWD:
    logger.warn('Either smtp env not set ')

Send_mail = Async_smtp(mail_host=mail_host,
                       sender=SENDER,
                       sender_pwd=SENDER_PWD)
# Transport setup

# UDP over IPv4
config.addSocketTransport(snmpEngine, udp.domainName,
                          udp.UdpTransport().openServerMode(('0.0.0.0', 162)))

# SNMPv3/USM setup

# user: usr-sha-aes128, auth: SHA, priv AES
config.addV3User(
    #snmpEngine, 'usr-sha-aes128',
    snmpEngine,
    snmp_user,
    #Add snmpv3 user
    config.usmHMACSHAAuthProtocol,
    snmp_pwd,
    #Auth SHA			    #password
    config.usmAesCfb128Protocol,
    snmp_pwd
    #Use Aes 			    #password
Beispiel #27
0
# Transport addresses
config.addTargetAddr(
    snmpEngine, 'myNMS', config.snmpUDPDomain,
    ('127.0.0.1', 162), 'myParams', tagList='myManagementStations'
    )

# Notification targets
config.addNotificationTarget(
#    snmpEngine, 'myNotifyName', 'myParams', 'myManagementStations', 'trap'
    snmpEngine, 'myNotifyName', 'myParams', 'myManagementStations', 'inform'
    )

# Setup transport endpoint
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpSocketTransport().openClientMode()
    )

# Agent-side VACM setup
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)
Beispiel #28
0
def main():
    class CommandResponder(cmdrsp.CommandResponderBase):
        pduTypes = (rfc1905.SetRequestPDU.tagSet, rfc1905.GetRequestPDU.tagSet,
                    rfc1905.GetNextRequestPDU.tagSet,
                    rfc1905.GetBulkRequestPDU.tagSet)

        def handleMgmtOperation(self, snmpEngine, stateReference, contextName,
                                pdu, acInfo):
            trunkReq = gCurrentRequestContext.copy()

            trunkReq['snmp-pdu'] = pdu

            pluginIdList = trunkReq['plugins-list']

            logCtx = LogString(trunkReq)

            reqCtx = {}

            for pluginNum, pluginId in enumerate(pluginIdList):

                st, pdu = pluginManager.processCommandRequest(
                    pluginId, snmpEngine, pdu, trunkReq, reqCtx)

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

                elif st == status.DROP:
                    log.debug(
                        'received SNMP message, plugin %s muted request' %
                        pluginId,
                        ctx=logCtx)
                    self.releaseStateInformation(stateReference)
                    return

                elif st == status.RESPOND:
                    log.debug(
                        'received SNMP message, plugin %s forced immediate response'
                        % pluginId,
                        ctx=logCtx)

                    try:
                        self.sendPdu(snmpEngine, stateReference, pdu)

                    except PySnmpError:
                        log.error('failure sending SNMP response', ctx=logCtx)

                    else:
                        self.releaseStateInformation(stateReference)

                    return

            # pass query to trunk

            trunkIdList = trunkReq['trunk-id-list']
            if trunkIdList is None:
                log.error('no route configured', ctx=logCtx)
                self.releaseStateInformation(stateReference)
                return

            for trunkId in trunkIdList:

                cbCtx = pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx

                try:
                    msgId = trunkingManager.sendReq(trunkId, trunkReq,
                                                    self.trunkCbFun, cbCtx)

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

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

        def trunkCbFun(self, msgId, trunkRsp, cbCtx):
            pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx = cbCtx

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

            trunkRsp['callflow-id'] = trunkReq['callflow-id']

            logCtx = LogString(trunkRsp)

            if trunkRsp['client-error-indication']:
                log.info(
                    'received trunk message #%s, remote end reported error-indication "%s", NOT responding'
                    % (msgId, trunkRsp['client-error-indication']),
                    ctx=logCtx)

            elif 'client-snmp-pdu' not in trunkRsp:
                log.info(
                    'received trunk message #%s, remote end does not send SNMP PDU, NOT responding'
                    % msgId,
                    ctx=logCtx)

            else:
                pdu = trunkRsp['client-snmp-pdu']

                for pluginId in pluginIdList:
                    st, pdu = pluginManager.processCommandResponse(
                        pluginId, snmpEngine, pdu, trunkReq, reqCtx)

                    if st == status.BREAK:
                        log.debug('plugin %s inhibits other plugins' %
                                  pluginId,
                                  ctx=logCtx)
                        break
                    elif st == status.DROP:
                        log.debug('plugin %s muted response' % pluginId,
                                  ctx=logCtx)
                        self.releaseStateInformation(stateReference)
                        return

                try:
                    self.sendPdu(snmpEngine, stateReference, pdu)

                except PySnmpError:
                    log.error('failure sending SNMP response', ctx=logCtx)

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

            self.releaseStateInformation(stateReference)

    #
    # SNMPv3 NotificationReceiver implementation
    #

    class NotificationReceiver(ntfrcv.NotificationReceiver):
        pduTypes = (rfc1157.TrapPDU.tagSet, rfc1905.SNMPv2TrapPDU.tagSet)

        def processPdu(self, snmpEngine, messageProcessingModel, securityModel,
                       securityName, securityLevel, contextEngineId,
                       contextName, pduVersion, pdu, maxSizeResponseScopedPDU,
                       stateReference):

            trunkReq = gCurrentRequestContext.copy()

            if messageProcessingModel == 0:
                pdu = rfc2576.v1ToV2(pdu)

                # TODO: why this is not automatic?
                v2c.apiTrapPDU.setDefaults(pdu)

            trunkReq['snmp-pdu'] = pdu

            pluginIdList = trunkReq['plugins-list']

            logCtx = LogString(trunkReq)

            reqCtx = {}

            for pluginNum, pluginId in enumerate(pluginIdList):

                st, pdu = pluginManager.processNotificationRequest(
                    pluginId, snmpEngine, pdu, trunkReq, reqCtx)

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

                elif st == status.DROP:
                    log.debug('plugin %s muted request' % pluginId, ctx=logCtx)
                    return

                elif st == status.RESPOND:
                    log.debug('plugin %s NOT forced immediate response' %
                              pluginId,
                              ctx=logCtx)
                    # TODO: implement immediate response for confirmed-class PDU
                    return

            # pass query to trunk

            trunkIdList = trunkReq['trunk-id-list']
            if trunkIdList is None:
                log.error('no route configured', ctx=logCtx)
                return

            for trunkId in trunkIdList:

                # TODO: pass messageProcessingModel to respond
                cbCtx = pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx

                try:
                    msgId = trunkingManager.sendReq(trunkId, trunkReq,
                                                    self.trunkCbFun, cbCtx)

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

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

        def trunkCbFun(self, msgId, trunkRsp, cbCtx):
            pluginIdList, trunkId, trunkReq, snmpEngine, stateReference, reqCtx = cbCtx

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

            trunkRsp['callflow-id'] = trunkReq['callflow-id']

            logCtx = LazyLogString(trunkReq, trunkRsp)

            if trunkRsp['client-error-indication']:
                log.info(
                    'received trunk message #%s, remote end reported error-indication "%s", NOT responding'
                    % (msgId, trunkRsp['client-error-indication']),
                    ctx=logCtx)
            else:
                if 'client-snmp-pdu' not in trunkRsp:
                    log.debug(
                        'received trunk message #%s -- unconfirmed SNMP message'
                        % msgId,
                        ctx=logCtx)
                    return

                pdu = trunkRsp['client-snmp-pdu']

                for pluginId in pluginIdList:
                    st, pdu = pluginManager.processNotificationResponse(
                        pluginId, snmpEngine, pdu, trunkReq, reqCtx)

                    if st == status.BREAK:
                        log.debug('plugin %s inhibits other plugins' %
                                  pluginId,
                                  ctx=logCtx)
                        break
                    elif st == status.DROP:
                        log.debug(
                            'received trunk message #%s, plugin %s muted response'
                            % (msgId, pluginId),
                            ctx=logCtx)
                        return

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

                # TODO: implement response part

                # # Agent-side API complies with SMIv2
                # if messageProcessingModel == 0:
                #     PDU = rfc2576.v2ToV1(PDU, origPdu)
                #
                # statusInformation = {}
                #
                # # 3.4.3
                # try:
                #     snmpEngine.msgAndPduDsp.returnResponsePdu(
                #         snmpEngine, messageProcessingModel, securityModel,
                #         securityName, securityLevel, contextEngineId,
                #         contextName, pduVersion, rspPDU, maxSizeResponseScopedPDU,
                #         stateReference, statusInformation)
                #
                # except error.StatusInformation:
                #         log.error('processPdu: stateReference %s, statusInformation %s' % (stateReference, sys.exc_info()[1]))

    class LogString(LazyLogString):

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

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

    def securityAuditObserver(snmpEngine, execpoint, variables, cbCtx):
        securityModel = variables.get('securityModel', 0)

        logMsg = 'SNMPv%s auth failure' % securityModel
        logMsg += ' at %s:%s' % variables['transportAddress'].getLocalAddress()
        logMsg += ' from %s:%s' % variables['transportAddress']

        statusInformation = variables.get('statusInformation', {})

        if securityModel in (1, 2):
            logMsg += ' using snmp-community-name "%s"' % statusInformation.get(
                'communityName', '?')
        elif securityModel == 3:
            logMsg += ' using snmp-usm-user "%s"' % statusInformation.get(
                'msgUserName', '?')

        try:
            logMsg += ': %s' % statusInformation['errorIndication']

        except KeyError:
            pass

        log.error(logMsg)

    def requestObserver(snmpEngine, execpoint, variables, cbCtx):

        trunkReq = {
            'callflow-id': '%10.10x' % random.randint(0, 0xffffffffff),
            'snmp-engine-id': snmpEngine.snmpEngineID,
            'snmp-transport-domain': variables['transportDomain'],
            'snmp-peer-address': variables['transportAddress'][0],
            'snmp-peer-port': variables['transportAddress'][1],
            'snmp-bind-address':
            variables['transportAddress'].getLocalAddress()[0],
            'snmp-bind-port':
            variables['transportAddress'].getLocalAddress()[1],
            'snmp-security-model': variables['securityModel'],
            'snmp-security-level': variables['securityLevel'],
            'snmp-security-name': variables['securityName'],
            'snmp-context-engine-id': variables['contextEngineId'],
            'snmp-context-name': variables['contextName'],
        }

        trunkReq['snmp-credentials-id'] = macro.expandMacro(
            credIdMap.get(
                (str(snmpEngine.snmpEngineID), variables['transportDomain'],
                 variables['securityModel'], variables['securityLevel'],
                 str(variables['securityName']))), trunkReq)

        k = '#'.join([
            str(x)
            for x in (variables['contextEngineId'], variables['contextName'])
        ])
        for x, y in contextIdList:
            if y.match(k):
                trunkReq['snmp-context-id'] = macro.expandMacro(x, trunkReq)
                break
            else:
                trunkReq['snmp-context-id'] = None

        addr = '%s:%s#%s:%s' % (
            variables['transportAddress'][0], variables['transportAddress'][1],
            variables['transportAddress'].getLocalAddress()[0],
            variables['transportAddress'].getLocalAddress()[1])

        for pat, peerId in peerIdMap.get(str(variables['transportDomain']),
                                         ()):
            if pat.match(addr):
                trunkReq['snmp-peer-id'] = macro.expandMacro(peerId, trunkReq)
                break
        else:
            trunkReq['snmp-peer-id'] = None

        pdu = variables['pdu']
        if pdu.tagSet == v1.TrapPDU.tagSet:
            pdu = rfc2576.v1ToV2(pdu)
            v2c.apiTrapPDU.setDefaults(pdu)

        k = '#'.join([
            snmpPduTypesMap.get(variables['pdu'].tagSet, '?'),
            '|'.join([str(x[0]) for x in v2c.apiTrapPDU.getVarBinds(pdu)])
        ])

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

        trunkReq['plugins-list'] = pluginIdMap.get(
            (trunkReq['snmp-credentials-id'], trunkReq['snmp-context-id'],
             trunkReq['snmp-peer-id'], trunkReq['snmp-content-id']), [])
        trunkReq['trunk-id-list'] = trunkIdMap.get(
            (trunkReq['snmp-credentials-id'], trunkReq['snmp-context-id'],
             trunkReq['snmp-peer-id'], trunkReq['snmp-content-id']))

        cbCtx.clear()
        cbCtx.update(trunkReq)

    #
    # main script 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 pysnmp_debug.flagMap.keys() if x != 'mibview'
    ]), '|'.join([x for x in pyasn1_debug.flagMap.keys()]), '|'.join(
        log.methodsMap.keys()), '|'.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: server part. Receives SNMP requests at one or many
          built-in SNMP Agents and routes them to encrypted trunks established with
          Forwarder's Manager part(s) running elsewhere.
          Can implement complex routing logic through analyzing parts of SNMP messages
          and matching them against proxying rules.

        Documentation:
          http://snmpfwd.sourceforge.io/

    %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 https://github.com/etingof/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]

    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()

    gCurrentRequestContext = {}

    credIdMap = {}
    peerIdMap = {}
    contextIdList = []
    contentIdList = []
    pluginIdMap = {}
    trunkIdMap = {}
    engineIdMap = {}

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

    #
    # Initialize plugin modules
    #

    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>'))

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

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

    for configEntryPath in cfgTree.getPathsToAttr('snmp-credentials-id'):
        credId = cfgTree.getAttrValue('snmp-credentials-id', *configEntryPath)
        configKey = []
        log.info('configuring snmp-credentials %s (at %s)...' %
                 (credId, '.'.join(configEntryPath)))

        engineId = cfgTree.getAttrValue('snmp-engine-id', *configEntryPath)

        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': {}}

            snmpEngine.observer.registerObserver(
                securityAuditObserver,
                'rfc2576.prepareDataElements:sm-failure',
                'rfc3412.prepareDataElements:sm-failure',
                cbCtx=gCurrentRequestContext)

            snmpEngine.observer.registerObserver(
                requestObserver,
                'rfc3412.receiveMessage:request',
                cbCtx=gCurrentRequestContext)

            CommandResponder(snmpEngine, snmpContext)

            NotificationReceiver(snmpEngine, None)

            engineIdMap[engineId] = snmpEngine, snmpContext, snmpEngineMap

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

        configKey.append(str(snmpEngine.snmpEngineID))

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

        if transportDomain in snmpEngineMap['transportDomain']:
            h, p, transportDomain = snmpEngineMap['transportDomain'][
                transportDomain]
            log.info('using transport endpoint %s:%s, transport ID %s' %
                     (h, p, transportDomain))
        else:
            if transportDomain[:len(udp.domainName)] == udp.domainName:
                transport = udp.UdpTransport()
            elif transportDomain[:len(udp6.domainName)] == udp6.domainName:
                transport = udp6.Udp6Transport()
            else:
                log.error('unknown transport domain %s' % (transportDomain, ))
                return

            h, p = cfgTree.getAttrValue('snmp-bind-address',
                                        *configEntryPath).split(':', 1)

            snmpEngine.registerTransportDispatcher(transportDispatcher,
                                                   transportDomain)

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

            t = transport.openServerMode((h, int(p)))

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

            config.addSocketTransport(snmpEngine, transportDomain, t)

            snmpEngineMap['transportDomain'][
                transportDomain] = h, p, transportDomain

            log.info(
                'new transport endpoint %s:%s, options %s, transport ID %s' %
                (h, p, transportOptions and '/'.join(transportOptions)
                 or '<none>', transportDomain))

        configKey.append(transportDomain)

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

        if securityModel in (1, 2):
            if securityName in snmpEngineMap['securityName']:
                if snmpEngineMap['securityName'][
                        securityModel] == securityModel:
                    log.info('using security-name %s' % securityName)
                else:
                    raise SnmpfwdError(
                        'snmp-security-name %s already in use at snmp-security-model %s'
                        % (securityName, securityModel))
            else:
                communityName = cfgTree.getAttrValue('snmp-community-name',
                                                     *configEntryPath)
                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

            configKey.append(securityModel)
            configKey.append(securityLevel)
            configKey.append(securityName)

        elif securityModel == 3:
            if securityName in snmpEngineMap['securityName']:
                log.info('using USM security-name: %s' % securityName)
            else:
                usmUser = cfgTree.getAttrValue('snmp-usm-user',
                                               *configEntryPath)
                log.info(
                    'new USM user %s, security-model %s, security-level %s, security-name %s'
                    % (usmUser, securityModel, securityLevel, securityName))

                if securityLevel in (2, 3):
                    usmAuthProto = cfgTree.getAttrValue(
                        'snmp-usm-auth-protocol', *configEntryPath,
                        **dict(default=config.usmHMACMD5AuthProtocol))
                    usmAuthProto = rfc1902.ObjectName(usmAuthProto)
                    usmAuthKey = cfgTree.getAttrValue('snmp-usm-auth-key',
                                                      *configEntryPath)
                    log.info(
                        'new USM authentication key: %s, authentication protocol: %s'
                        % (usmAuthKey, usmAuthProto))

                    if securityLevel == 3:
                        usmPrivProto = cfgTree.getAttrValue(
                            'snmp-usm-priv-protocol', *configEntryPath,
                            **dict(default=config.usmDESPrivProtocol))
                        usmPrivProto = rfc1902.ObjectName(usmPrivProto)
                        usmPrivKey = cfgTree.getAttrValue(
                            'snmp-usm-priv-key', *configEntryPath,
                            **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)

                else:
                    config.addV3User(snmpEngine, usmUser)

                snmpEngineMap['securityName'][securityName] = securityModel

            configKey.append(securityModel)
            configKey.append(securityLevel)
            configKey.append(securityName)

        else:
            raise SnmpfwdError('unknown snmp-security-model: %s' %
                               securityModel)

        configKey = tuple(configKey)
        if configKey in credIdMap:
            log.error(
                'ambiguous configuration for key snmp-credentials-id=%s at %s'
                % (credId, '.'.join(configEntryPath)))
            return

        credIdMap[configKey] = credId

    duplicates = {}

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

        duplicates[peerId] = peerCfgPath

        log.info('configuring peer ID %s (at %s)...' %
                 (peerId, '.'.join(peerCfgPath)))
        transportDomain = cfgTree.getAttrValue('snmp-transport-domain',
                                               *peerCfgPath)
        if transportDomain not in peerIdMap:
            peerIdMap[transportDomain] = []
        for peerAddress in cfgTree.getAttrValue(
                'snmp-peer-address-pattern-list', *peerCfgPath,
                **dict(vector=True)):
            for bindAddress in cfgTree.getAttrValue(
                    'snmp-bind-address-pattern-list', *peerCfgPath,
                    **dict(vector=True)):
                peerIdMap[transportDomain].append(
                    (re.compile(peerAddress + '#' + bindAddress), peerId))

    duplicates = {}

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

        duplicates[contextId] = contextCfgPath

        k = '#'.join((cfgTree.getAttrValue('snmp-context-engine-id-pattern',
                                           *contextCfgPath),
                      cfgTree.getAttrValue('snmp-context-name-pattern',
                                           *contextCfgPath)))

        log.info('configuring context ID %s (at %s), composite key: %s' %
                 (contextId, '.'.join(contextCfgPath), k))

        contextIdList.append((contextId, re.compile(k)))

    duplicates = {}

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

        duplicates[contentId] = contentCfgPath

        for x in cfgTree.getAttrValue('snmp-pdu-oid-prefix-pattern-list',
                                      *contentCfgPath, **dict(vector=True)):
            k = '#'.join([
                cfgTree.getAttrValue('snmp-pdu-type-pattern', *contentCfgPath),
                x
            ])

            log.info('configuring content ID %s (at %s), composite key: %s' %
                     (contentId, '.'.join(contentCfgPath), k))

            contentIdList.append((contentId, 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-snmp-credentials-id-list',
                                           *pluginCfgPath,
                                           **dict(vector=True)):
            for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list',
                                               *pluginCfgPath,
                                               **dict(vector=True)):
                for contextId in cfgTree.getAttrValue(
                        'matching-snmp-context-id-list', *pluginCfgPath,
                        **dict(vector=True)):
                    for contentId in cfgTree.getAttrValue(
                            'matching-snmp-content-id-list', *pluginCfgPath,
                            **dict(vector=True)):
                        k = credId, contextId, peerId, contentId
                        if k in pluginIdMap:
                            log.error(
                                'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at plugin-id(s) %s'
                                % (credId, contextId, peerId, contentId,
                                   ','.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-trunk-id-list'):
        trunkIdList = cfgTree.getAttrValue('using-trunk-id-list',
                                           *routeCfgPath, **dict(vector=True))
        log.info('configuring destination trunk ID(s) %s (at %s)...' %
                 (','.join(trunkIdList), '.'.join(routeCfgPath)))
        for credId in cfgTree.getAttrValue('matching-snmp-credentials-id-list',
                                           *routeCfgPath, **dict(vector=True)):
            for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list',
                                               *routeCfgPath,
                                               **dict(vector=True)):
                for contextId in cfgTree.getAttrValue(
                        'matching-snmp-context-id-list', *routeCfgPath,
                        **dict(vector=True)):
                    for contentId in cfgTree.getAttrValue(
                            'matching-snmp-content-id-list', *routeCfgPath,
                            **dict(vector=True)):
                        k = credId, contextId, peerId, contentId
                        if k in trunkIdMap:
                            log.error(
                                'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at trunk-id(s) %s'
                                % (credId, contextId, peerId, contentId,
                                   ','.join(trunkIdList)))
                            return
                        else:
                            trunkIdMap[k] = trunkIdList

                        log.info(
                            'configuring trunk routing to %s (at %s), composite key: %s'
                            % (','.join(trunkIdList), '.'.join(routeCfgPath),
                               '/'.join(k)))

    def dataCbFun(trunkId, msgId, msg):
        log.debug('message ID %s received from trunk %s' % (msgId, trunkId))

    trunkingManager = TrunkingManager(dataCbFun)

    def getTrunkAddr(a, port=0):
        f = lambda h, p=port: (h, int(p))
        try:
            return f(*a.split(':'))

        except Exception:
            raise SnmpfwdError('improper IPv4 endpoint %s' % a)

    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,
                getTrunkAddr(
                    cfgTree.getAttrValue('trunk-bind-address', *trunkCfgPath)),
                getTrunkAddr(
                    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(
                getTrunkAddr(
                    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))

    try:
        daemon.dropPrivileges(procUser, procGroup)

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

    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

    while True:
        try:
            transportDispatcher.runDispatcher()

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

        except Exception:
            transportDispatcher.closeDispatcher()
            raise
Beispiel #29
0
#debug.setLogger(debug.Debug('io', 'dsp', 'msgproc', 'secmod', 'app'))

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

#
# Transport setup
#

# Agent section

# UDP over IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName + (1,),
    udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)

# UDP over IPv6
config.addSocketTransport(
    snmpEngine,
    udp6.domainName + (1,),
    udp6.Udp6Transport().openServerMode(('::1', 161))
    )

# Manager section

# UDP over IPv4
config.addSocketTransport(
    snmpEngine,
Beispiel #30
0
# Command Responder
from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp import debug

# Optionally enable stdout debugging
#debug.setLogger(debug.Debug('all'))

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Setup transport endpoint
config.addSocketTransport(
    snmpEngine, udp.domainName,
    udp.UdpSocketTransport().openServerMode(('127.0.0.1', 161)))

# Create and put on-line my managed object
sysDescr, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
    'SNMPv2-MIB', 'sysDescr')
MibScalarInstance, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
    'SNMPv2-SMI', 'MibScalarInstance')
sysDescrInstance = MibScalarInstance(
    sysDescr.name, (0, ), sysDescr.syntax.clone('Example Command Responder'))
snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.exportSymbols(
    'PYSNMP-EXAMPLE-MIB',
    sysDescrInstance)  # add anonymous Managed Object Instance

# v1/2 setup
config.addV1System(snmpEngine, 'test-agent', 'public')
Beispiel #31
0
    def start_listener(self,
                       callback,
                       address=None,
                       port=1162,
                       community='public',
                       timeout=TIMEOUT):
        '''
        Start a TRAP v1/v2c/v3 notification receiver with predefined users.

        @param callback: Takes these args snmpEngine, stateReference,
                         contextEngineId, contextName, varBinds, cbCtx
        @param address: The address to listen to
        @param port: The port to listen to
        @param community: The community name for v2c

        Predefined users:
        usr-md5-des
        usr-md5-none
        usr-sha-aes128

        Auth: authkey1
        Priv: privkey1
        '''
        if not address:
            address = get_local_ip(self.host)
        if timeout < 0:
            timeout = 10**10
        # Create SNMP engine with auto-generated engineID and pre-bound
        # to socket transport dispatcher
        snmpEngine = engine.SnmpEngine()

        # Transport setup
        if IPAddress(address).version == 4:
            # UDP over IPv4
            domain_oid = udp.domainName
            transport = udp.UdpTransport()
        else:
            # UDP over IPv6
            domain_oid = udp6.domainName
            transport = udp6.Udp6Transport()

        # Waiting up to TIMEOUT seconds for the port to be released
        LOG.debug('Waiting for port %s:%d to become available...', address,
                  port)
        transport = wait(lambda: transport.openServerMode((address, port)),
                         timeout=TIMEOUT,
                         interval=1)
        LOG.info('Listening for traps on %s:%d...', address, port)

        config.addSocketTransport(snmpEngine, domain_oid, transport)

        # Terrible monkey patching!!
        # But there's no other way to cause the dispatcher loop to end if we
        # don't get what we expect in a given amount of time. For now that time
        # is limited to TIMEOUT seconds.
        end = time.time() + timeout

        def jobsArePending(self):
            if self._AbstractTransportDispatcher__jobs and time.time() < end:
                return 1
            else:
                return 0

        snmpEngine.transportDispatcher.__class__.jobsArePending = jobsArePending

        # SNMPv1/2 setup
        config.addV1System(snmpEngine, 'test-agent', community)

        # SNMPv3/USM setup
        # user: usr-md5-des, auth: MD5, priv DES
        config.addV3User(snmpEngine, 'usr-md5-des',
                         config.usmHMACMD5AuthProtocol, 'authkey1',
                         config.usmDESPrivProtocol, 'privkey1')

        # user: usr-md5-des, auth: MD5, priv DES, contextEngineId: 8000000001020304
        # this USM entry is used for TRAP receiving purposes
        config.addV3User(
            snmpEngine,
            'usr-md5-des',
            config.usmHMACMD5AuthProtocol,
            'authkey1',
            config.usmDESPrivProtocol,
            'privkey1',
            contextEngineId=v2c.OctetString(hexValue='8000000001020304'))

        # user: usr-md5-none, auth: MD5, priv NONE
        config.addV3User(snmpEngine, 'usr-md5-none',
                         config.usmHMACMD5AuthProtocol, 'authkey1')

        # user: usr-md5-none, auth: MD5, priv NONE, contextEngineId: 8000000001020304
        # this USM entry is used for TRAP receiving purposes
        config.addV3User(
            snmpEngine,
            'usr-md5-none',
            config.usmHMACMD5AuthProtocol,
            'authkey1',
            contextEngineId=v2c.OctetString(hexValue='8000000001020304'))

        # user: usr-sha-aes128, auth: SHA, priv AES
        config.addV3User(snmpEngine, 'usr-sha-aes128',
                         config.usmHMACSHAAuthProtocol, 'authkey1',
                         config.usmAesCfb128Protocol, 'privkey1')
        # user: usr-sha-aes128, auth: SHA, priv AES, contextEngineId: 8000000001020304
        # this USM entry is used for TRAP receiving purposes
        config.addV3User(
            snmpEngine,
            'usr-sha-aes128',
            config.usmHMACSHAAuthProtocol,
            'authkey1',
            config.usmAesCfb128Protocol,
            'privkey1',
            contextEngineId=v2c.OctetString(hexValue='8000000001020304'))

        #         def sample_callback(snmpEngine, stateReference, contextEngineId, contextName,
        #                             varBinds, cbCtx):
        #             print('Notification received, ContextEngineId "%s", ContextName "%s"' % (
        #                   contextEngineId.prettyPrint(), contextName.prettyPrint())
        #             )
        #             for name, val in varBinds:
        #                 print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
        #             print

        # If callback() returns True we'll stop the loop
        def callback_wrapper(*args, **kwargs):
            if callback(*args, **kwargs):
                snmpEngine.transportDispatcher.jobFinished(DEFAULT_JOB)

        # Register SNMP Application at the SNMP engine
        ntfrcv.NotificationReceiver(snmpEngine, callback_wrapper)

        #return address, port
        t = TrapListener(snmpEngine)
        t.start()
        return address, port, t
Beispiel #32
0
    def __init__(self,
                 mibPath,
                 temperatureValue,
                 snmpRelays,
                 criticalStatus=True):
        from types import ListType, TupleType, StringTypes
        from re import compile, search
        from socket import gethostbyname

        extractPaths = compile(r'[,:]')
        checkIP = compile(r'(\d{1,3}\.){3}\d{1,3}')

        # Create SNMP engine instance
        self.snmpEngine = engine.SnmpEngine()

        if not temperatureValue:
            raise ValueError, 'A temperature must be provided'

        self.temperature = temperatureValue
        #print "============>mibPath type: %s" %type(mibPath)
        if type(mibPath) in StringTypes:
            mibPathTuple = tuple(extractPaths.split(mibPath))
        elif type(mibPath) in (ListType, TupleType):
            mibPathTuple = tuple(mibPath)
        else:
            mibPathTuple = ('/usr/local/share/snmp/python/', )

        mibBuilder = self.snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder

        #print mibPathTuple
        mibSources = mibBuilder.getMibPath() + mibPathTuple
        mibBuilder.setMibPath(*mibSources)

        mibBuilder.loadModules('USC-IGFAE-MIB')

        if type(snmpRelays) in StringTypes:
            snmpRelays = snmpRelays.split(',')
        elif not type(snmpRelays) in (ListType, TupleType):
            raise TypeError, 'The list of SNMP relays must be a string or a list or tuple of strings'

        (temperatureCritical, temperatureOK,
         self.roomTemp) = mibBuilder.importSymbols('USC-IGFAE-MIB',
                                                   'temperatureCritical',
                                                   'temperatureOK', 'roomTemp')

        # SecurityName <-> CommunityName mapping
        config.addV1System(self.snmpEngine, 'Arduino', 'ups')

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

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

        index = 0
        for machine in snmpRelays:
            index = index + 1
            if not checkIP.match(machine):
                try:
                    machine = gethostbyname(machine)
                except:
                    continue

            #print "==============>SNMP relay  IP: %s" % machine
            config.addTargetAddr(self.snmpEngine,
                                 'NMS%s' % index,
                                 udp.domainName, (machine, 162),
                                 'creds',
                                 tagList='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(self.snmpEngine, 'sendShutdownTrap',
                                     'my-filter', 'managers', 'trap')

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

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

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

        if criticalStatus:
            self.trap = temperatureCritical
        else:
            self.trap = temperatureOK

        # Create Notification Originator App instance.
        ntforg.NotificationOriginator.__init__(self, snmpContext)
Beispiel #33
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()
Beispiel #34
0
def snmpv3_trap(user='', hash_meth=None, hash_key=None, cry_meth=None, cry_key=None, engineid='', ip='127.0.0.1',
                port=162):
    # Create SNMP engine with autogenernated engineID and pre-bound
    snmpEngine = engine.SnmpEngine()

    config.addSocketTransport(
        snmpEngine,
        udp.domainName,
        udp.UdpTransport().openServerMode((ip, port))
    )

    # usmHMACMD5AuthProtocol - MD5 hashing
    # usmHMACSHAAuthProtocol - SHA hashing
    # usmNoAuthProtocol - no authentication
    # usmDESPrivProtocol - DES encryption
    # usm3DESEDEPrivProtocol - triple-DES encryption
    # usmAesCfb128Protocol - AES encryption, 128-bit
    # usmAesCfb192Protocol - AES encryption, 192-bit
    # usmAesCfb256Protocol - AES encryption, 256-bit
    # usmNoPrivProtocol - no encryption

    # NoAuthNoPriv
    if hash_meth is None and cry_meth is None:
        hashval = config.usmNoAuthProtocol
        cryval = config.usmNoPrivProtocol
    # AuthNoPriv
    elif hash_meth is not None and cry_meth is None:
        if hash_meth == 'md5':
            hashval = config.usmHMACMD5AuthProtocol
        elif hash_meth == 'sha':
            hashval = config.usmHMACSHAAuthProtocol
        else:
            print('哈希算法必须是md5 or sha!')
            return
        cryval = config.usmNoPrivProtocol
    # AuthPriv
    elif hash_meth is not None and cry_meth is not None:
        if hash_meth == 'md5':
            hashval = config.usmHMACMD5AuthProtocol
        elif hash_meth == 'sha':
            hashval = config.usmHMACSHAAuthProtocol
        else:
            print('哈希算法必须是md5 or sha!')
            return
        if cry_meth == '3des':
            cryval = config.usm3DESEDEPrivProtocol
        elif cry_meth == 'des':
            cryval = config.usmDESPrivProtocol
        elif cry_meth == 'aes128':
            cryval = config.usmAesCfb128Protocol
        elif cry_meth == 'aes192':
            cryval = config.usmAesCfb192Protocol
        elif cry_meth == 'aes256':
            cryval = config.usmAesCfb256Protocol
        else:
            print('加密算法必须是3des, des, aes128, aes192 or aes256 !')
            return
    # 提供的参数不符合标准时给出提示
    else:
        print('三种USM: NoAuthNoPriv, AuthNoPriv, AuthPriv.。请选择其中一种。')
        return

    config.addV3User(
        snmpEngine, user,
        hashval, hash_key,
        cryval, cry_key,
        contextEngineId=v2c.OctetString(hexValue=engineid)
    )

    # Register SNMP Application at the SNMP engine
    ntfrcv.NotificationReceiver(snmpEngine, cbFun)

    snmpEngine.transportDispatcher.jobStarted(1)  # this job would never finish

    # Run I/O dispatcher which would receive queries and send confirmations
    try:
        snmpEngine.transportDispatcher.runDispatcher()
    except:
        snmpEngine.transportDispatcher.closeDispatcher()
        raise
Beispiel #35
0
    def __init__(self, mibObjects):
        self._snmpEngine = engine.SnmpEngine()

        # open a UDP socket to listen for snmp requests
        config.addSocketTransport(
            self._snmpEngine, udp.domainName,
            udp.UdpTransport().openServerMode(('', 7757)))

        # add a v2 user with the community string public
        config.addV1System(self._snmpEngine, "agent", "public")
        # let anyone accessing 'public' read anything in the subtree below,
        # which is the enterprises subtree that we defined our MIB to be in
        config.addVacmUser(self._snmpEngine,
                           2,
                           "agent",
                           "noAuthNoPriv",
                           readSubTree=(1, 3, 6, 1, 4, 1))

        # each app has one or more contexts
        self._snmpContext = context.SnmpContext(self._snmpEngine)

        # the builder is used to load mibs. tell it to look in the
        # current directory for our new MIB. We'll also use it to
        # export our symbols later
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), )
        mibBuilder.setMibSources(*mibSources)

        # our variables will subclass this since we only have scalar types
        # can't load this type directly, need to import it
        MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI', 'MibTable')

        mib = Mib()

        (nodeEntry, profileEntry, nodeIdxColumn, profileIdxColumn, dcdColumn,
         profileNameColumn) = mibBuilder.importSymbols('AKSION-CONTROL-MIB',
                                                       'nodeEntry',
                                                       'profileEntry',
                                                       'nodeIdx', 'profileIdx',
                                                       'dcd', 'profileName')
        rowInstanceId = nodeEntry.getInstIdFromIndices(1)
        mibInstrumentation = self._snmpContext.getMibInstrum()
        mibInstrumentation.writeVars(
            ((dcdColumn.name + rowInstanceId, 'xx1'), ))

        rowProfileInstanceId = profileEntry.getInstIdFromIndices(1)
        mibInstrumentation = self._snmpContext.getMibInstrum()
        mibInstrumentation.writeVars(
            ((profileNameColumn.name + rowInstanceId + rowProfileInstanceId,
              'ProfileNode1'), ))

        #
        rowInstanceId = nodeEntry.getInstIdFromIndices(2)
        mibInstrumentation = self._snmpContext.getMibInstrum()
        mibInstrumentation.writeVars(
            ((dcdColumn.name + rowInstanceId, 'xx 2'), ))

        rowProfileInstanceId = profileEntry.getInstIdFromIndices(2)
        mibInstrumentation = self._snmpContext.getMibInstrum()
        mibInstrumentation.writeVars(
            ((profileNameColumn.name + rowInstanceId + rowProfileInstanceId,
              'ProfileNode2'), ))

        # tell pysnmp to respotd to get, getnext, and getbulk
        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #36
0
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context
from pysnmp.proto.api import v2c
from pysnmp.proto.acmod import void
from pysnmp.carrier.asynsock.dgram import udp

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Setup UDP over IPv4 transport endpoints

# Agent will listen here
config.addSocketTransport(
    snmpEngine,
    udp.domainName + (1,),  # use transport domain's sub-name
    udp.UdpTransport().openServerMode(('127.0.0.1', 1161))
    )

# Manager will send packets there
config.addSocketTransport(
    snmpEngine,
    udp.domainName + (2,), # use transport domain's sub-name
    udp.UdpTransport().openClientMode()
    )

# SNMP credentials used by Manager

# v1/2 setup
config.addV1System(snmpEngine, 'dest-cmt', 'public')
Beispiel #37
0
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
Beispiel #38
0
    def start(self):
        if self._engine is None:
            # Create SNMP engine with autogenernated engineID and pre-bound
            # to socket transport dispatcher
            self._engine = engine.SnmpEngine()

            # Setup UDP over IPv4 transport endpoint
        try:
            iface = ('0.0.0.0', self.port)
            self._logger.info("[pid: %d] Starting SNMP server on %s:%d",  os.getpid(), iface[0], iface[1])
            config.addSocketTransport(
            self._engine,
            udp.domainName,
            udp.UdpSocketTransport().openServerMode(iface)
            )
        except CarrierError:
            self._logger.error('Can\'t run SNMP agent on port %d: Address already in use', self.port)
            raise

        mibBuilder = self._engine.msgAndPduDsp.mibInstrumController.mibBuilder

        MibSources = mibBuilder.getMibPath()
        sources =  ['/mibs','/mibs/instances']
        for source in sources:
            MibSources += ((os.path.realpath(os.path.dirname(__file__) + source), ))
        apply(mibBuilder.setMibPath, MibSources)

        try:
            mibBuilder.loadModules(*self._modules)
        except SmiError:
            self._logger.warn('Can\'t load modules')
            raise

        config.addV1System(self._engine, self._security_name, self._community_name)

        # VACM setup
        config.addContext(self._engine, '')
        config.addRwUser(self._engine, 1, self._security_name, 'noAuthNoPriv', (1,3,6)) # v1
        config.addRwUser(self._engine, 2, self._security_name, 'noAuthNoPriv', (1,3,6)) # v2c

        # SNMP context
        snmpContext = context.SnmpContext(self._engine)
        # Apps registration
        cmdrsp.GetCommandResponder(self._engine, snmpContext)
        cmdrsp.SetCommandResponder(self._engine, snmpContext)
        cmdrsp.NextCommandResponder(self._engine, snmpContext)
        cmdrsp.BulkCommandResponder(self._engine, snmpContext)

        # Start server
        self._logger.debug('Starting transport dispatcher')
        self._engine.transportDispatcher.jobStarted(1)
        try:
            self._logger.debug('Run transport dispatcher')
            self._engine.transportDispatcher.runDispatcher()
        except select.error, e:
            if e.args[0] == 9:
                # 'Bad file descriptor'
                # Throws when dispatcher closed from another thread
                pass
            else:
                raise
    def __init__(self, mibObjects):
        """
        mibObjects - a list of MibObject tuples that this agent
        will serve
        """

        #each SNMP-based application has an engine
        self._snmpEngine = engine.SnmpEngine()

        #open a UDP socket on port 161 to listen for snmp requests
        config.addSocketTransport(self._snmpEngine, udp.domainName,
                                  udp.UdpTransport().openServerMode(('', 161)))

        #Here we configure two distinct Community Strings to control read and write
        #operations. public --> Read only, private --> Read/Write
        config.addV1System(self._snmpEngine, "agent", "public")
        config.addV1System(self._snmpEngine, 'my-write-area', 'private')

        #let anyone accessing 'public' read anything in the subtree below,
        #which is the enterprises subtree that we defined our MIB to be in
        config.addVacmUser(self._snmpEngine,
                           2,
                           "agent",
                           "noAuthNoPriv",
                           readSubTree=(1, 3, 6, 1, 4, 1))

        #let anyone accessing 'private' read and write anything in the subtree below,
        #which is the enterprises subtree that we defined our MIB to be in
        config.addVacmUser(self._snmpEngine,
                           2,
                           'my-write-area',
                           'noAuthNoPriv',
                           readSubTree=(1, 3, 6, 1, 4, 1),
                           writeSubTree=(1, 3, 6, 1, 4, 1))

        #Create Agent context
        self._snmpContext = context.SnmpContext(self._snmpEngine)

        #the builder is used to load mibs. tell it to look in the
        #current directory for our new MIB. We'll also use it to
        #export our symbols later
        mibBuilder = self._snmpContext.getMibInstrum().getMibBuilder()
        mibSources = mibBuilder.getMibSources() + (builder.DirMibSource('.'), )
        mibBuilder.setMibSources(*mibSources)

        MibScalarInstance, = mibBuilder.importSymbols('SNMPv2-SMI',
                                                      'MibScalarInstance')
        #export our custom mib
        for mibObject in mibObjects:
            nextVar, = mibBuilder.importSymbols(mibObject.mibName,
                                                mibObject.objectType)
            instance = createVariable(MibScalarInstance, mibObject.valueFunc,
                                      mibObject.valueSetFunc, nextVar.name,
                                      (0, ), nextVar.syntax)
            #need to export as <var name>Instance
            instanceDict = {str(nextVar.name) + "Instance": instance}
            mibBuilder.exportSymbols(mibObject.mibName, **instanceDict)

        # tell pysnmp to respond to get, set, getnext, and getbulk
        cmdrsp.GetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.SetCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.NextCommandResponder(self._snmpEngine, self._snmpContext)
        cmdrsp.BulkCommandResponder(self._snmpEngine, self._snmpContext)
Beispiel #40
0
#from pysnmp import debug

## Optional debugging ('all' enables full debugging)
#debug.setLogger(debug.Debug('io', 'dsp', 'msgproc', 'secmod', 'app'))

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

#
# Transport setup
#

# UDP over IPv4
config.addSocketTransport(
    snmpEngine, udp.domainName,
    udp.UdpTransport().openServerMode(('127.0.0.1', 161)))

# UDP over IPv6
config.addSocketTransport(snmpEngine, udp6.domainName,
                          udp6.Udp6Transport().openServerMode(('::1', 161)))

# Local domain sockets
config.addSocketTransport(
    snmpEngine, unix.domainName,
    unix.UnixTransport().openServerMode('/tmp/snmp-agent'))

#
# SNMPv1/2c setup (if you need to handle SNMPv1/v2c messages)
#
Beispiel #41
0
from pysnmp import debug
#from mysnmp_debug import debug
#sys.stderr = open('kojoney_snmpd.log', 'w')
debug.setLogger(debug.Debug('all'))
#sys.stderr = open('kojoney_snmpd.log', 'w')
#fpout = open("snmpd.log","w")
#debug.Debug.defaultPrinter = fpout

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Setup UDP over IPv4 transport endpoint
#config.addSocketTransport(snmpEngine,udp.domainName,udp.UdpSocketTransport().openServerMode(('127.0.0.1', 161)))
config.addSocketTransport(
    snmpEngine, udp.domainName,
    udp.UdpSocketTransport().openServerMode(('192.168.1.68', 161)))

# Setup UDP over IPv6 transport endpoint
#config.addSocketTransport(
#    snmpEngine,
#    udp6.domainName,
#    udp6.Udp6Transport().openServerMode(('::1', 161))
#    )

# Create and put on-line my managed object
sysDescr, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
    'SNMPv2-MIB', 'sysDescr')
MibScalarInstance, = snmpEngine.msgAndPduDsp.mibInstrumController.mibBuilder.importSymbols(
    'SNMPv2-SMI', 'MibScalarInstance')
#sysDescrInstance = MibScalarInstance(sysDescr.name, (0,), sysDescr.syntax.clone('Example Command Responder'))
Beispiel #42
0
# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Transport setup
port = 11162
if 1 < len(sys.argv):
    try:
        port = int(sys.argv[1])
    except Exception:
        pass

# UDP over IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('0.0.0.0', port))
)

# SNMPv3/USM setup

# user: usr-md5-des, auth: MD5, priv DES
config.addV3User(
    snmpEngine, 'user',
    config.usmHMACMD5AuthProtocol, 'mypasswd',
    config.usmDESPrivProtocol, 'mypasswd'
)

# user: usr-md5-des, auth: MD5, priv DES, contextEngineId: 8000000001020304
# this USM entry is used for TRAP receiving purposes
config.addV3User(
Beispiel #43
0
def main():
    variation_module = None

    parser = argparse.ArgumentParser(description=DESCRIPTION)

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

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

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

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

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

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

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

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

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

    v3arch_group = parser.add_argument_group('SNMPv3 parameters')

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

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

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

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

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

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

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

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

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

    endpoint_group = parser.add_mutually_exclusive_group(required=True)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    args = parser.parse_args()

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

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

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

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

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

    else:
        args.output_file = sys.stdout

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

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

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

    # Catch missing params

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

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

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

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

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

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

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

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

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

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

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

    # Load variation module

    if args.variation_module:

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

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

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

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

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

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

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

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

    # SNMP configuration

    snmp_engine = engine.SnmpEngine()

    if args.protocol_version == '3':

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

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

        else:
            secLevel = 'authPriv'

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

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

    else:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # Variation module initialization

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

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

        try:
            handler = variation_module['init']

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

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

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

    data_file_handler = variation.RECORD_TYPES[args.destination_record_type]


    # SNMP worker

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

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

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

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

                except IndexError:
                    next_oid = cb_ctx['lastOID']

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

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

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

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

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

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

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

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

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

            cb_ctx['errors'] += 1

            return

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

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

        stop_flag = False

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

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

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

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

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

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

                # Build .snmprec record

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

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

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

                    more_data_notification = exc

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

                        time.sleep(more_data_notification['period'])

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

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

                    stop_flag = True  # stop current iteration

                except error.NoDataNotification:
                    pass

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

                else:
                    args.output_file.write(line)

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

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

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

        # Continue walking
        return not stop_flag

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

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

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

    else:
        cmd_gen = cmdgen.NextCommandGenerator()

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

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

    started = time.time()

    try:
        snmp_engine.transportDispatcher.runDispatcher()

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

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

            try:
                handler = variation_module['shutdown']

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

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

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

        snmp_engine.transportDispatcher.closeDispatcher()

        started = time.time() - started

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

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

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

        return cb_ctx.get('errors', 0) and 1 or 0
Beispiel #44
0
sys.path.append('/usr/lib/python3.4/site-packages/PyQYT/ExtentionPackages')
sys.path.append('../../ExtentionPackages')

from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c
#from sendmail import sendTrapInfo
import sys
import re

# Create SNMP engine with autogenernated engineID and pre-bound
snmpEngine = engine.SnmpEngine()

config.addSocketTransport(
    snmpEngine, udp.domainName,
    udp.UdpTransport().openServerMode(('202.100.1.138', 162)))


#Callback function for receiving notifications
def cbFun(snmpEngine, stateReference, contextEngineId, contextName, varBinds,
          cbCtx):
    #    print('Notification received, ContextEngineId "%s", ContextName "%s"' % (
    #        contextEngineId.prettyPrint(), contextName.prettyPrint()
    #        )
    #    )
    for name, val in varBinds:
        #        print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
        name = str(name)
        val = str(val)
        trapInfo = ''
Beispiel #45
0
	def start(self):
		if self._engine is None:
			# Create SNMP engine with autogenernated engineID and pre-bound
			# to socket transport dispatcher
			self._engine = engine.SnmpEngine()
			
			# Setup UDP over IPv4 transport endpoint
		try:
			iface = ('0.0.0.0', self.port)
			self._logger.info("[pid: %d] Starting SNMP server on %s:%d",  os.getpid(), iface[0], iface[1])
			config.addSocketTransport(
			self._engine,
			udp.domainName,
			udp.UdpSocketTransport().openServerMode(iface)
			)
		except CarrierError:
			self._logger.error('Can\'t run SNMP agent on port %d: Address already in use', self.port)
			raise
		
		mibBuilder = self._engine.msgAndPduDsp.mibInstrumController.mibBuilder
			
		MibSources = mibBuilder.getMibPath()
		sources =  ['/mibs','/mibs/instances']
		for source in sources:
			MibSources += ((os.path.realpath(os.path.dirname(__file__) + source), ))
		apply(mibBuilder.setMibPath, MibSources)
			
		try:
			mibBuilder.loadModules(*self._modules)
		except SmiError:
			self._logger.warn('Can\'t load modules')
			raise

		config.addV1System(self._engine, self._security_name, self._community_name)
			
		# VACM setup
		config.addContext(self._engine, '')
		config.addRwUser(self._engine, 1, self._security_name, 'noAuthNoPriv', (1,3,6)) # v1
		config.addRwUser(self._engine, 2, self._security_name, 'noAuthNoPriv', (1,3,6)) # v2c
			
		# SNMP context
		snmpContext = context.SnmpContext(self._engine)
		# Apps registration
		cmdrsp.GetCommandResponder(self._engine, snmpContext)
		cmdrsp.SetCommandResponder(self._engine, snmpContext)
		cmdrsp.NextCommandResponder(self._engine, snmpContext)
		cmdrsp.BulkCommandResponder(self._engine, snmpContext)
			
		# Start server
		self._logger.debug('Starting transport dispatcher')
		self._engine.transportDispatcher.jobStarted(1)
		try:
			self._logger.debug('Run transport dispatcher')
			self._engine.transportDispatcher.runDispatcher()
		except select.error, e:
			if e.args[0] == 9: 
				# 'Bad file descriptor'
				# Throws when dispatcher closed from another thread
				pass
			else:
				raise
Beispiel #46
0
    def _setup(self, q, port):
        """Setup a new agent in a separate process.

        The port the agent is listening too will be returned using the
        provided queue.
        """
        snmpEngine = engine.SnmpEngine()
        if self.ipv6:
            config.addSocketTransport(
                snmpEngine,
                udp6.domainName,
                udp6.Udp6Transport().openServerMode(('::1', port)))
        else:
            config.addSocketTransport(
                snmpEngine,
                udp.domainName,
                udp.UdpTransport().openServerMode(('127.0.0.1', port)))
        # Community is public and MIB is writable
        config.addV1System(snmpEngine, 'read-write', self.community)
        config.addVacmUser(snmpEngine, 1, 'read-write', 'noAuthNoPriv',
                           (1, 3, 6), (1, 3, 6))
        config.addVacmUser(snmpEngine, 2, 'read-write', 'noAuthNoPriv',
                           (1, 3, 6), (1, 3, 6))
        config.addV3User(
            snmpEngine, 'read-write',
            config.usmHMACMD5AuthProtocol, self.authpass,
            config.usmAesCfb128Protocol, self.privpass)
        config.addVacmUser(snmpEngine, 3, 'read-write', 'authPriv',
                           (1, 3, 6), (1, 3, 6))

        # Build MIB
        def stringToOid(string):
            return [ord(x) for x in string]

        def flatten(*args):
            result = []
            for el in args:
                if isinstance(el, (list, tuple)):
                    for sub in el:
                        result.append(sub)
                else:
                    result.append(el)
            return tuple(result)
        snmpContext = context.SnmpContext(snmpEngine)
        mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
        (MibTable, MibTableRow, MibTableColumn,
         MibScalar, MibScalarInstance) = mibBuilder.importSymbols(
            'SNMPv2-SMI',
            'MibTable', 'MibTableRow', 'MibTableColumn',
            'MibScalar', 'MibScalarInstance')

        class RandomMibScalarInstance(MibScalarInstance):
            previous_value = 0

            def getValue(self, name, idx):
                self.previous_value += random.randint(1, 2000)
                return self.getSyntax().clone(self.previous_value)

        mibBuilder.exportSymbols(
            '__MY_SNMPv2_MIB',
            # SNMPv2-MIB::sysDescr
            MibScalar((1, 3, 6, 1, 2, 1, 1, 1), v2c.OctetString()),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 1, 1), (0,),
                              v2c.OctetString(
                                  "Snimpy Test Agent {0}".format(
                                      self.community))),
            # SNMPv2-MIB::sysObjectID
            MibScalar((1, 3, 6, 1, 2, 1, 1, 2), v2c.ObjectIdentifier()),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 1, 2), (0,),
                              v2c.ObjectIdentifier((1, 3, 6, 1, 4,
                                                    1, 9, 1, 1208))))
        mibBuilder.exportSymbols(
            '__MY_IF_MIB',
            # IF-MIB::ifNumber
            MibScalar((1, 3, 6, 1, 2, 1, 2, 1), v2c.Integer()),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 1), (0,), v2c.Integer(3)),
            # IF-MIB::ifTable
            MibTable((1, 3, 6, 1, 2, 1, 2, 2)),
            MibTableRow((1, 3, 6, 1, 2, 1, 2, 2, 1)).setIndexNames(
                (0, '__MY_IF_MIB', 'ifIndex')),
            # IF-MIB::ifIndex
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (1,), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (2,), v2c.Integer(2)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (3,), v2c.Integer(3)),
            # IF-MIB::ifDescr
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), v2c.OctetString()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (1,), v2c.OctetString("lo")),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (2,), v2c.OctetString("eth0")),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (3,), v2c.OctetString("eth1")),
            # IF-MIB::ifType
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), v2c.Integer()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (1,), v2c.Integer(24)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (2,), v2c.Integer(6)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (3,), v2c.Integer(6)),
            # IF-MIB::ifInOctets
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 10), v2c.Integer()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (1,), v2c.Gauge32()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (2,), v2c.Gauge32()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (3,), v2c.Gauge32()),

            # IF-MIB::ifRcvAddressTable
            MibTable((1, 3, 6, 1, 2, 1, 31, 1, 4)),
            MibTableRow((1, 3, 6, 1, 2, 1, 31, 1, 4, 1)).setIndexNames(
                (0, '__MY_IF_MIB', 'ifIndex'),
                (1, '__MY_IF_MIB', 'ifRcvAddressAddress')),
            # IF-MIB::ifRcvAddressStatus
            MibTableColumn((1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 2), v2c.Integer()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 2),
                flatten(2, 6, stringToOid("abcdef")), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 2),
                flatten(2, 6, stringToOid("ghijkl")), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 2),
                flatten(3, 6, stringToOid("mnopqr")), v2c.Integer(1)),
            # IF-MIB::ifRcvAddressType
            MibTableColumn((1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 3), v2c.Integer()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 3),
                flatten(2, 6, stringToOid("abcdef")), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 3),
                flatten(2, 6, stringToOid("ghijkl")), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 31, 1, 4, 1, 3),
                flatten(3, 6, stringToOid("mnopqr")), v2c.Integer(1)),

            # IF-MIB::ifIndex
            ifIndex=MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 1),
                                   v2c.Integer()),
            # IF-MIB::ifRcvAddressAddress
            ifRcvAddressAddress=MibTableColumn((1, 3, 6, 1, 2, 1, 31,
                                                1, 4, 1, 1),
                                               v2c.OctetString()))

        args = (
            '__MY_SNIMPY-MIB',
            # SNIMPY-MIB::snimpyIpAddress
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 1),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 1), (0,),
                v2c.OctetString("AAAA")),
            # SNIMPY-MIB::snimpyString
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 2),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 2), (0,), v2c.OctetString("bye")),
            # SNIMPY-MIB::snimpyInteger
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 3),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 3), (0,), v2c.Integer(19)),
            # SNIMPY-MIB::snimpyEnum
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 4),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 4), (0,), v2c.Integer(2)),
            # SNIMPY-MIB::snimpyObjectId
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 5),
                      v2c.ObjectIdentifier()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 5), (
                0,), v2c.ObjectIdentifier((1, 3, 6, 4454, 0, 0))),
            # SNIMPY-MIB::snimpyBoolean
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 6),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 6), (0,), v2c.Integer(1)),
            # SNIMPY-MIB::snimpyCounter
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 7),
                      v2c.Counter32()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 7), (0,), v2c.Counter32(47)),
            # SNIMPY-MIB::snimpyGauge
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 8),
                      v2c.Gauge32()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 8), (0,), v2c.Gauge32(18)),
            # SNIMPY-MIB::snimpyTimeticks
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 9),
                      v2c.TimeTicks()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 9), (0,),
                v2c.TimeTicks(12111100)),
            # SNIMPY-MIB::snimpyCounter64
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 10),
                      v2c.Counter64()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 10), (0,),
                v2c.Counter64(2 ** 48 + 3)),
            # SNIMPY-MIB::snimpyBits
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 11),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 11), (0,),
                v2c.OctetString(b"\xa0")),
            # SNIMPY-MIB::snimpyMacAddress
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 15),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 15), (
                0,), v2c.OctetString(b"\x11\x12\x13\x14\x15\x16")),
            # SNIMPY-MIB::snimpyMacAddressInvalid
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 16),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 16), (
                0,), v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")),

            # SNIMPY-MIB::snimpyIndexTable
            MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 3)),
            MibTableRow(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1)).setIndexNames(
                (0, "__MY_SNIMPY-MIB", "snimpyIndexVarLen"),
                (0, "__MY_SNIMPY-MIB", "snimpyIndexOidVarLen"),
                (0, "__MY_SNIMPY-MIB", "snimpyIndexFixedLen"),
                (1, "__MY_SNIMPY-MIB", "snimpyIndexImplied")),
            # SNIMPY-MIB::snimpyIndexVarLen
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row1'),
                                      3, 1, 2, 3,
                                      stringToOid('alpha5'),
                                      stringToOid('end of row1')),
                              v2c.OctetString(b"row1")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row2'),
                                      4, 1, 0, 2, 3,
                                      stringToOid('beta32'),
                                      stringToOid('end of row2')),
                              v2c.OctetString(b"row2")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row3'),
                                      4, 120, 1, 2, 3,
                                      stringToOid('gamma7'),
                                      stringToOid('end of row3')),
                              v2c.OctetString(b"row3")),
            # SNIMPY-MIB::snimpyIndexInt
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row1'),
                                      3, 1, 2, 3,
                                      stringToOid('alpha5'),
                                      stringToOid('end of row1')),
                              v2c.Integer(4571)),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row2'),
                                      4, 1, 0, 2, 3,
                                      stringToOid('beta32'),
                                      stringToOid('end of row2')),
                              v2c.Integer(78741)),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row3'),
                                      4, 120, 1, 2, 3,
                                      stringToOid('gamma7'),
                                      stringToOid('end of row3')),
                              v2c.Integer(4110)),

            # SNIMPY-MIB::snimpyInvalidTable
            MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 5)),
            MibTableRow(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1)).setIndexNames(
                (0, "__MY_SNIMPY-MIB", "snimpyInvalidIndex")),
            # SNIMPY-MIB::snimpyInvalidDescr
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                              (1,),
                              v2c.OctetString(b"Hello")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                              (2,),
                              v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")))

        if self.emptyTable:
            args += (
                # SNIMPY-MIB::snimpyEmptyTable
                MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 6)),
                MibTableRow(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1)).setIndexNames(
                        (0, "__MY_SNIMPY-MIB", "snimpyEmptyIndex")))

        kwargs = dict(
            # Indexes
            snimpyIndexVarLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                v2c.OctetString(
                )),
            snimpyIndexIntIndex=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 2),
                v2c.Integer(
                )).setMaxAccess(
                "noaccess"),
            snimpyIndexOidVarLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 3),
                v2c.ObjectIdentifier(
                )).setMaxAccess(
                "noaccess"),
            snimpyIndexFixedLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 4),
                v2c.OctetString(
                ).setFixedLength(
                    6)).setMaxAccess(
                "noaccess"),
            snimpyIndexImplied=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 5),
                v2c.OctetString(
                )).setMaxAccess("noaccess"),
            snimpyIndexInt=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                v2c.Integer()).setMaxAccess("readwrite"),
            snimpyInvalidIndex=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 1),
                v2c.Integer()).setMaxAccess("noaccess"),
            snimpyInvalidDescr=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                v2c.OctetString()).setMaxAccess("readwrite")
        )

        if self.emptyTable:
            kwargs.update(dict(
                snimpyEmptyIndex=MibTableColumn(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1, 1),
                    v2c.Integer()).setMaxAccess("noaccess"),
                snimpyEmptyDescr=MibTableColumn(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1, 2),
                    v2c.OctetString()).setMaxAccess("readwrite")))

        mibBuilder.exportSymbols(*args, **kwargs)

        # Start agent
        cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
        cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
        cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
        cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
        q.put(port)
        snmpEngine.transportDispatcher.jobStarted(1)
        snmpEngine.transportDispatcher.runDispatcher()
Beispiel #47
0
from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp import debug

# Optionally enable stdout debugging
#debug.setLogger(debug.Debug('all'))

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Setup transport endpoint
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpSocketTransport().openServerMode(('127.0.0.1', 162))
    )

# v1/2 setup
config.addV1System(snmpEngine, 'test-agent', 'public')

# v3 setup
config.addV3User(
    snmpEngine, 'test-user',
    config.usmHMACMD5AuthProtocol, 'authkey1',
    config.usmDESPrivProtocol, 'privkey1'
#   '\x80\x00\x4f\xb8\x1c\x3d\xaf\xe6'   # ContextEngineID of
                                         # Notification Originator
    )
    
Beispiel #48
0
def main():
    class MibTreeProxyMixIn(object):

        MIB_INTRUMENTATION_CALL = None

        def _getMgmtFun(self, contextName):
            return self._routeToMibTree

        def _routeToMibTree(self, *varBinds, **context):

            cbFun = context['cbFun']

            mibTreeReq = gCurrentRequestContext.copy()

            pdu = mibTreeReq['snmp-pdu']

            pluginIdList = mibTreeReq['plugins-list']

            logCtx = LogString(mibTreeReq)

            reqCtx = {}

            for pluginNum, pluginId in enumerate(pluginIdList):

                st, pdu = pluginManager.processCommandRequest(
                    pluginId, snmpEngine, pdu, mibTreeReq, reqCtx)

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

                elif st == status.DROP:
                    log.debug(
                        'received SNMP message, plugin %s muted request' %
                        pluginId,
                        ctx=logCtx)
                    # TODO: need to report some special error to drop request
                    cbFun(varBinds, **context)
                    return

                elif st == status.RESPOND:
                    log.debug(
                        'received SNMP message, plugin %s forced immediate response'
                        % pluginId,
                        ctx=logCtx)
                    # TODO: should we respond something other than request?
                    cbFun(varBinds, **context)
                    return

            # Apply PDU to MIB(s)

            mibTreeId = mibTreeReq['mib-tree-id']
            if not mibTreeId:
                log.error('no matching MIB tree route for the request',
                          ctx=logCtx)
                cbFun(varBinds, **dict(context, error=smi_error.GenError()))
                return

            mibInstrum = mibTreeIdMap.get(mibTreeId)
            if not mibInstrum:
                log.error('MIB tree ID %s does not exist' % mibTreeId,
                          ctx=logCtx)
                cbFun(varBinds, **dict(context, error=smi_error.GenError()))
                return

            log.debug('received SNMP message, applied on mib-tree-id %s' %
                      mibTreeId,
                      ctx=logCtx)

            cbCtx = pluginIdList, mibTreeId, mibTreeReq, snmpEngine, reqCtx, context[
                'cbFun']

            mgmtFun = getattr(mibInstrum, self.MIB_INTRUMENTATION_CALL)

            mgmtFun(
                *varBinds,
                **dict(context,
                       cbFun=self._mibTreeCbFun,
                       cbCtx=cbCtx,
                       acFun=None))

        # TODO: it just occurred to me that `*varBinds` would look more consistent
        def _mibTreeCbFun(self, varBinds, **context):
            pluginIdList, mibTreeId, mibTreeReq, snmpEngine, reqCtx, cbFun = context[
                'cbCtx']

            logCtx = LogString(mibTreeReq)

            err = context.get('error')
            if err:
                log.info('MIB operation resulted in error: %s' % err,
                         ctx=logCtx)

            cbFun(varBinds, **dict(context, cbFun=cbFun))

            # plugins need to work at var-binds level
            #
            # for key in tuple(mibTreeRsp):
            #     pdu = mibTreeRsp['client-snmp-pdu']
            #
            #     for pluginId in pluginIdList:
            #         st, pdu = pluginManager.processCommandResponse(
            #             pluginId, snmpEngine, pdu, mibTreeReq, reqCtx
            #         )
            #
            #         if st == status.BREAK:
            #             log.debug('plugin %s inhibits other plugins' % pluginId, ctx=logCtx)
            #             break
            #         elif st == status.DROP:
            #             log.debug('plugin %s muted response' % pluginId, ctx=logCtx)
            #             self.releaseStateInformation(stateReference)
            #             return
            #
            #     try:
            #         self.sendPdu(snmpEngine, stateReference, pdu)
            #
            #     except PySnmpError:
            #         log.error('mibTree message #%s, SNMP response error: %s' % (msgId, sys.exc_info()[1]),
            #                   ctx=logCtx)
            #
            #     else:
            #         log.debug('received mibTree message #%s, forwarded as SNMP message' % msgId, ctx=logCtx)

    class GetCommandResponder(MibTreeProxyMixIn, cmdrsp.GetCommandResponder):
        MIB_INTRUMENTATION_CALL = 'readMibObjects'

    class GetNextCommandResponder(MibTreeProxyMixIn,
                                  cmdrsp.NextCommandResponder):
        MIB_INTRUMENTATION_CALL = 'readNextMibObjects'

    class GetBulkCommandResponder(MibTreeProxyMixIn,
                                  cmdrsp.BulkCommandResponder):
        MIB_INTRUMENTATION_CALL = 'readNextMibObjects'

    class SetCommandResponder(MibTreeProxyMixIn, cmdrsp.SetCommandResponder):
        MIB_INTRUMENTATION_CALL = 'writeMibObjects'

    class LogString(LazyLogString):

        GROUPINGS = [
            ['callflow-id'],
            [
                'snmp-engine-id', 'snmp-transport-domain', 'snmp-bind-address',
                'snmp-bind-port', 'snmp-security-model', 'snmp-security-level',
                'snmp-security-name', 'snmp-credentials-id'
            ],
            ['snmp-context-engine-id', 'snmp-context-name', 'snmp-context-id'],
            ['snmp-pdu', 'snmp-content-id'],
            ['snmp-peer-address', 'snmp-peer-port', 'snmp-peer-id'],
            ['mib-tree-id'],
            ['client-snmp-pdu'],
        ]

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

    def securityAuditObserver(snmpEngine, execpoint, variables, cbCtx):
        securityModel = variables.get('securityModel', 0)

        logMsg = 'SNMPv%s auth failure' % securityModel
        logMsg += ' at %s:%s' % variables['transportAddress'].getLocalAddress()
        logMsg += ' from %s:%s' % variables['transportAddress']

        statusInformation = variables.get('statusInformation', {})

        if securityModel in (1, 2):
            logMsg += ' using snmp-community-name "%s"' % statusInformation.get(
                'communityName', '?')
        elif securityModel == 3:
            logMsg += ' using snmp-usm-user "%s"' % statusInformation.get(
                'msgUserName', '?')

        try:
            logMsg += ': %s' % statusInformation['errorIndication']

        except KeyError:
            pass

        log.error(logMsg)

    def usmRequestObserver(snmpEngine, execpoint, variables, cbCtx):

        mibTreeReq = {'snmp-security-engine-id': variables['securityEngineId']}

        cbCtx.clear()
        cbCtx.update(mibTreeReq)

    def requestObserver(snmpEngine, execpoint, variables, cbCtx):

        mibTreeReq = {
            'callflow-id': '%10.10x' % random.randint(0, 0xffffffffff),
            'snmp-engine-id': snmpEngine.snmpEngineID,
            'snmp-transport-domain': variables['transportDomain'],
            'snmp-peer-address': variables['transportAddress'][0],
            'snmp-peer-port': variables['transportAddress'][1],
            'snmp-bind-address':
            variables['transportAddress'].getLocalAddress()[0],
            'snmp-bind-port':
            variables['transportAddress'].getLocalAddress()[1],
            'snmp-security-model': variables['securityModel'],
            'snmp-security-level': variables['securityLevel'],
            'snmp-security-name': variables['securityName'],
            'snmp-context-engine-id': variables['contextEngineId'],
            'snmp-context-name': variables['contextName'],
        }

        try:
            mibTreeReq['snmp-security-engine-id'] = cbCtx.pop(
                'snmp-security-engine-id')

        except KeyError:
            # SNMPv1/v2c
            mibTreeReq['snmp-security-engine-id'] = mibTreeReq[
                'snmp-engine-id']

        mibTreeReq['snmp-credentials-id'] = macro.expandMacro(
            credIdMap.get(
                (str(snmpEngine.snmpEngineID), variables['transportDomain'],
                 variables['securityModel'], variables['securityLevel'],
                 str(variables['securityName']))), mibTreeReq)

        k = '#'.join([
            str(x)
            for x in (variables['contextEngineId'], variables['contextName'])
        ])
        for x, y in contextIdList:
            if y.match(k):
                mibTreeReq['snmp-context-id'] = macro.expandMacro(
                    x, mibTreeReq)
                break
            else:
                mibTreeReq['snmp-context-id'] = None

        addr = '%s:%s#%s:%s' % (
            variables['transportAddress'][0], variables['transportAddress'][1],
            variables['transportAddress'].getLocalAddress()[0],
            variables['transportAddress'].getLocalAddress()[1])

        for pat, peerId in peerIdMap.get(str(variables['transportDomain']),
                                         ()):
            if pat.match(addr):
                mibTreeReq['snmp-peer-id'] = macro.expandMacro(
                    peerId, mibTreeReq)
                break
        else:
            mibTreeReq['snmp-peer-id'] = None

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

        for x, y in contentIdList:
            if y.match(k):
                mibTreeReq['snmp-content-id'] = macro.expandMacro(
                    x, mibTreeReq)
                break
            else:
                mibTreeReq['snmp-content-id'] = None

        mibTreeReq['plugins-list'] = pluginIdMap.get(
            (mibTreeReq['snmp-credentials-id'], mibTreeReq['snmp-context-id'],
             mibTreeReq['snmp-peer-id'], mibTreeReq['snmp-content-id']), [])
        mibTreeReq['mib-tree-id'] = routingMap.get(
            (mibTreeReq['snmp-credentials-id'], mibTreeReq['snmp-context-id'],
             mibTreeReq['snmp-peer-id'], mibTreeReq['snmp-content-id']))

        mibTreeReq['snmp-pdu'] = pdu

        cbCtx.clear()
        cbCtx.update(mibTreeReq)

    #
    # main script 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 Command Responder. Runs one or more SNMP command responders (agents)
  and one or more trees of MIB objects representing SNMP-managed entities.
  The tool applies received messages onto one of the MIB trees chosen by
  tool's configuration.

Documentation:
  http://snmplabs.com/snmpresponder/

%s
""" % helpMessage)
            return
        if opt[0] == '-v' or opt[0] == '--version':
            import snmpresponder
            import pysnmp
            import pyasn1
            sys.stderr.write("""\
SNMP Command Responder version %s, written by Ilya Etingof <*****@*****.**>
Using foundation libraries: pysnmp %s, pyasn1 %s.
Python interpreter: %s
Software documentation and support at http://snmplabs.com/snmpresponder/
%s
""" % (snmpresponder.__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(','),
                                   loggerName=PROGRAM_NAME + '.pysnmp'))
        elif opt[0] == '--debug-asn1':
            pyasn1_debug.setLogger(
                pyasn1_debug.Debug(*opt[1].split(','),
                                   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, force=True)

            if loggingLevel:
                log.setLevel(loggingLevel)

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

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

    except SnmpResponderError:
        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()

    gCurrentRequestContext = {}

    credIdMap = {}
    peerIdMap = {}
    contextIdList = []
    contentIdList = []
    pluginIdMap = {}
    routingMap = {}
    mibTreeIdMap = {}
    engineIdMap = {}

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

    #
    # Initialize plugin modules
    #

    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,
                                 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 SnmpResponderError:
                log.error('plugin %s not loaded: %s' %
                          (pluginId, sys.exc_info()[1]))
                return

    for configEntryPath in cfgTree.getPathsToAttr('snmp-credentials-id'):
        credId = cfgTree.getAttrValue('snmp-credentials-id', *configEntryPath)
        configKey = []
        log.info('configuring snmp-credentials %s (at %s)...' %
                 (credId, '.'.join(configEntryPath)))

        engineId = cfgTree.getAttrValue('snmp-engine-id', *configEntryPath)

        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': {}}

            snmpEngine.observer.registerObserver(
                securityAuditObserver,
                'rfc2576.prepareDataElements:sm-failure',
                'rfc3412.prepareDataElements:sm-failure',
                cbCtx=gCurrentRequestContext)

            snmpEngine.observer.registerObserver(
                requestObserver,
                'rfc3412.receiveMessage:request',
                cbCtx=gCurrentRequestContext)

            snmpEngine.observer.registerObserver(usmRequestObserver,
                                                 'rfc3414.processIncomingMsg',
                                                 cbCtx=gCurrentRequestContext)

            GetCommandResponder(snmpEngine, snmpContext)
            GetNextCommandResponder(snmpEngine, snmpContext)
            GetBulkCommandResponder(snmpEngine, snmpContext)
            SetCommandResponder(snmpEngine, snmpContext)

            engineIdMap[engineId] = snmpEngine, snmpContext, snmpEngineMap

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

        configKey.append(str(snmpEngine.snmpEngineID))

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

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

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

        else:
            bindAddr = cfgTree.getAttrValue('snmp-bind-address',
                                            *configEntryPath)

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

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

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

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

            t = transport.openServerMode(bindAddr)

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

            elif 'virtual-interface' in transportOptions:
                t.enablePktInfo()

            snmpEngine.registerTransportDispatcher(transportDispatcher,
                                                   transportDomain)

            config.addSocketTransport(snmpEngine, transportDomain, t)

            snmpEngineMap['transportDomain'][
                transportDomain] = bindAddr, transportDomain

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

        configKey.append(transportDomain)

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

        if securityModel in (1, 2):
            if securityName in snmpEngineMap['securityName']:
                if snmpEngineMap['securityName'][
                        securityModel] == securityModel:
                    log.info('using security-name %s' % securityName)
                else:
                    raise SnmpResponderError(
                        'snmp-security-name %s already in use at snmp-security-model %s'
                        % (securityName, securityModel))
            else:
                communityName = cfgTree.getAttrValue('snmp-community-name',
                                                     *configEntryPath)
                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

            configKey.append(securityModel)
            configKey.append(securityLevel)
            configKey.append(securityName)

        elif securityModel == 3:
            if securityName in snmpEngineMap['securityName']:
                log.info('using USM security-name: %s' % securityName)
            else:
                usmUser = cfgTree.getAttrValue('snmp-usm-user',
                                               *configEntryPath)
                securityEngineId = cfgTree.getAttrValue(
                    'snmp-security-engine-id', *configEntryPath, 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',
                        *configEntryPath,
                        default=config.USM_AUTH_HMAC96_MD5)
                    try:
                        usmAuthProto = authProtocols[usmAuthProto.upper()]
                    except KeyError:
                        pass
                    usmAuthProto = rfc1902.ObjectName(usmAuthProto)
                    usmAuthKey = cfgTree.getAttrValue('snmp-usm-auth-key',
                                                      *configEntryPath)
                    log.info(
                        'new USM authentication key: %s, authentication protocol: %s'
                        % (usmAuthKey, usmAuthProto))

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

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

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

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

                snmpEngineMap['securityName'][securityName] = securityModel

            configKey.append(securityModel)
            configKey.append(securityLevel)
            configKey.append(securityName)

        else:
            raise SnmpResponderError('unknown snmp-security-model: %s' %
                                     securityModel)

        configKey = tuple(configKey)
        if configKey in credIdMap:
            log.error(
                'ambiguous configuration for key snmp-credentials-id=%s at %s'
                % (credId, '.'.join(configEntryPath)))
            return

        credIdMap[configKey] = credId

    duplicates = {}

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

        duplicates[peerId] = peerCfgPath

        log.info('configuring peer ID %s (at %s)...' %
                 (peerId, '.'.join(peerCfgPath)))
        transportDomain = cfgTree.getAttrValue('snmp-transport-domain',
                                               *peerCfgPath)
        if transportDomain not in peerIdMap:
            peerIdMap[transportDomain] = []
        for peerAddress in cfgTree.getAttrValue(
                'snmp-peer-address-pattern-list', *peerCfgPath, vector=True):
            for bindAddress in cfgTree.getAttrValue(
                    'snmp-bind-address-pattern-list', *peerCfgPath,
                    vector=True):
                peerIdMap[transportDomain].append(
                    (re.compile(peerAddress + '#' + bindAddress), peerId))

    duplicates = {}

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

        duplicates[contextId] = contextCfgPath

        k = '#'.join((cfgTree.getAttrValue('snmp-context-engine-id-pattern',
                                           *contextCfgPath),
                      cfgTree.getAttrValue('snmp-context-name-pattern',
                                           *contextCfgPath)))

        log.info('configuring context ID %s (at %s), composite key: %s' %
                 (contextId, '.'.join(contextCfgPath), k))

        contextIdList.append((contextId, re.compile(k)))

    duplicates = {}

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

        duplicates[contentId] = contentCfgPath

        for x in cfgTree.getAttrValue('snmp-pdu-oid-prefix-pattern-list',
                                      *contentCfgPath,
                                      vector=True):
            k = '#'.join([
                cfgTree.getAttrValue('snmp-pdu-type-pattern', *contentCfgPath),
                x
            ])

            log.info('configuring content ID %s (at %s), composite key: %s' %
                     (contentId, '.'.join(contentCfgPath), k))

            contentIdList.append((contentId, re.compile(k)))

    del duplicates

    for pluginCfgPath in cfgTree.getPathsToAttr('using-plugin-id-list'):
        pluginIdList = cfgTree.getAttrValue('using-plugin-id-list',
                                            *pluginCfgPath,
                                            vector=True)
        log.info('configuring plugin ID(s) %s (at %s)...' %
                 (','.join(pluginIdList), '.'.join(pluginCfgPath)))
        for credId in cfgTree.getAttrValue('matching-snmp-credentials-id-list',
                                           *pluginCfgPath,
                                           vector=True):
            for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list',
                                               *pluginCfgPath,
                                               vector=True):
                for contextId in cfgTree.getAttrValue(
                        'matching-snmp-context-id-list',
                        *pluginCfgPath,
                        vector=True):
                    for contentId in cfgTree.getAttrValue(
                            'matching-snmp-content-id-list',
                            *pluginCfgPath,
                            vector=True):
                        k = credId, contextId, peerId, contentId
                        if k in pluginIdMap:
                            log.error(
                                'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at plugin-id(s) %s'
                                % (credId, contextId, peerId, contentId,
                                   ','.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-mib-tree-id'):
        mibTreeId = cfgTree.getAttrValue('using-mib-tree-id', *routeCfgPath)
        log.info('configuring destination MIB tree ID(s) %s (at %s)...' %
                 (mibTreeId, '.'.join(routeCfgPath)))
        for credId in cfgTree.getAttrValue('matching-snmp-credentials-id-list',
                                           *routeCfgPath,
                                           vector=True):
            for peerId in cfgTree.getAttrValue('matching-snmp-peer-id-list',
                                               *routeCfgPath,
                                               vector=True):
                for contextId in cfgTree.getAttrValue(
                        'matching-snmp-context-id-list',
                        *routeCfgPath,
                        vector=True):
                    for contentId in cfgTree.getAttrValue(
                            'matching-snmp-content-id-list',
                            *routeCfgPath,
                            vector=True):
                        k = credId, contextId, peerId, contentId
                        if k in routingMap:
                            log.error(
                                'duplicate snmp-credentials-id %s, snmp-context-id %s, snmp-peer-id %s, snmp-content-id %s at mib-tree-id(s) %s'
                                % (credId, contextId, peerId, contentId,
                                   ','.join(mibTreeIdList)))
                            return
                        else:
                            routingMap[k] = mibTreeId

                        log.info(
                            'configuring MIB tree routing to %s (at %s), composite key: %s'
                            % (mibTreeId, '.'.join(routeCfgPath), '/'.join(k)))

    for mibTreeCfgPath in cfgTree.getPathsToAttr('mib-tree-id'):

        mibTreeId = cfgTree.getAttrValue('mib-tree-id', *mibTreeCfgPath)

        log.info('configuring MIB tree ID %s (at %s)...' %
                 (mibTreeId, '.'.join(mibTreeCfgPath)))

        mibTextPaths = cfgTree.getAttrValue('mib-text-search-path-list',
                                            *mibTreeCfgPath,
                                            default=[],
                                            vector=True)

        mibCodePatternPaths = macro.expandMacros(
            cfgTree.getAttrValue('mib-code-modules-pattern-list',
                                 *mibTreeCfgPath,
                                 default=[],
                                 vector=True),
            {'config-dir': os.path.dirname(cfgFile)})

        mibBuilder = builder.MibBuilder()

        compiler.addMibCompiler(mibBuilder, sources=mibTextPaths)

        for topDir in mibCodePatternPaths:

            filenameRegExp = re.compile(os.path.basename(topDir))
            topDir = os.path.dirname(topDir)

            for root, dirs, files in os.walk(topDir):

                if not files or root.endswith('__pycache__'):
                    continue

                mibBuilder.setMibSources(builder.DirMibSource(root),
                                         *mibBuilder.getMibSources())

                for filename in files:

                    if not filenameRegExp.match(filename):
                        log.debug(
                            'skipping non-matching file %s while loading '
                            'MIB tree ID %s' % (filename, mibTreeId))
                        continue

                    module, _ = os.path.splitext(filename)

                    try:
                        mibBuilder.loadModule(module)

                    except PySnmpError as ex:
                        log.error('fail to load MIB implementation from file '
                                  '%s into MIB tree ID %s' %
                                  (os.path.join(root, filename), mibTreeId))
                        raise SnmpResponderError(str(ex))

                    log.info('loaded MIB implementation file %s into MIB tree '
                             'ID %s' %
                             (os.path.join(root, filename), mibTreeId))

        mibCodePackages = macro.expandMacros(
            cfgTree.getAttrValue('mib-code-packages-pattern-list',
                                 *mibTreeCfgPath,
                                 default=[],
                                 vector=True),
            {'config-dir': os.path.dirname(cfgFile)})

        for mibCodePackage in mibCodePackages:

            mibCodePackageRegExp = re.compile(mibCodePackage)

            for entryPoint in pkg_resources.iter_entry_points(
                    'snmpresponder.mibs'):
                log.debug('found extension entry point %s' % entryPoint.name)

                mibPackage = entryPoint.load()

                root = os.path.dirname(mibPackage.__file__)

                mibPathSet = False

                for filename in os.listdir(root):

                    if filename.startswith('__init__'):
                        continue

                    if not os.path.isfile(os.path.join(root, filename)):
                        continue

                    mibPath = '.'.join((entryPoint.name, filename))

                    if not mibCodePackageRegExp.match(mibPath):
                        log.debug(
                            'extension MIB %s from %s is NOT configured, '
                            'skipping' % (mibPath, entryPoint.name))
                        continue

                    if not mibPathSet:
                        mibBuilder.setMibSources(builder.DirMibSource(root),
                                                 *mibBuilder.getMibSources())
                        mibPathSet = True

                    log.debug('loading extension MIB %s from %s into MIB tree '
                              'ID %s' % (mibPath, entryPoint.name, mibTreeId))

                    module, _ = os.path.splitext(filename)

                    try:
                        mibBuilder.loadModule(module)

                    except PySnmpError as ex:
                        log.error('fail to load MIB implementation %s from '
                                  '%s into MIB tree ID %s' %
                                  (mibPath, entryPoint.name, mibTreeId))
                        raise SnmpResponderError(str(ex))

                    log.info(
                        'loaded MIB implementation %s from %s into MIB tree '
                        'ID %s' % (mibPath, entryPoint.name, mibTreeId))

        mibTreeIdMap[mibTreeId] = instrum.MibInstrumController(mibBuilder)

        log.info('loaded new MIB tree ID %s' % mibTreeId)

    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

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

        while True:
            try:
                transportDispatcher.runDispatcher()

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

            except Exception:
                transportDispatcher.closeDispatcher()
                raise
Beispiel #49
0
    def cfgCmdGen(self, authData, transportTarget, tagList=null):
        if authData not in self.__knownAuths:
            if isinstance(authData, CommunityData):
                config.addV1System(
                    self.snmpEngine,
                    authData.securityName,
                    authData.communityName,
                    authData.contextEngineId,
                    authData.contextName,
                    tagList
                    )
            elif isinstance(authData, UsmUserData):
                config.addV3User(
                    self.snmpEngine,
                    authData.securityName,
                    authData.authProtocol, authData.authKey,
                    authData.privProtocol, authData.privKey,
                    authData.contextEngineId
                    )
            else:
                raise error.PySnmpError('Unsupported authentication object')

            self.__knownAuths[authData] = 1

        k = authData.securityName, authData.securityLevel, authData.mpModel
        if k in self.__knownParams:
            paramsName = self.__knownParams[k]
        else:
            paramsName = 'p%s' % nextID()
            config.addTargetParams(
                self.snmpEngine, paramsName,
                authData.securityName, authData.securityLevel, authData.mpModel
                )
            self.__knownParams[k] = paramsName

        if transportTarget.transportDomain not in self.__knownTransports:
            transport = transportTarget.openClientMode()
            config.addSocketTransport(
                self.snmpEngine,
                transportTarget.transportDomain,
                transport
                )
            self.__knownTransports[transportTarget.transportDomain] = transport

        k = paramsName, transportTarget, tagList
        if k in self.__knownTransportAddrs:
            addrName = self.__knownTransportAddrs[k]
        else:
            addrName = 'a%s' % nextID()
            config.addTargetAddr(
                self.snmpEngine, addrName,
                transportTarget.transportDomain,
                transportTarget.transportAddr,
                paramsName,
                transportTarget.timeout * 100,
                transportTarget.retries,
                tagList                
                )
            self.__knownTransportAddrs[k] = addrName

        return addrName, paramsName
Beispiel #50
0
        snmpEngine.registerTransportDispatcher(transportDispatcher,
                                               transportDomain)

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

        t = transport.openServerMode((h, int(p)))

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

        config.addSocketTransport(snmpEngine, transportDomain, t)

        snmpEngineMap['transportDomain'][
            transportDomain] = h, p, transportDomain
        log.msg('new transport endpoint %s:%s, options %s, transport ID %s' %
                (h, p, transportOptions and '/'.join(transportOptions)
                 or '<none>', transportDomain))

    configKey.append(transportDomain)

    securityModel = cfgTree.getAttrValue('snmp-security-model',
                                         *configEntryPath)
    securityModel = rfc1902.Integer(securityModel)
    securityLevel = cfgTree.getAttrValue('snmp-security-level',
                                         *configEntryPath)
    securityLevel = rfc1902.Integer(securityLevel)
    def start(self):
        '''
        ' 启动监听进程
        ' raise Exception: 异常停止时抛出
        '''
        logger.info('Start trap listener...')
        # Create SNMP engine with autogenernated engineID and pre-bound
        # to socket transport dispatcher
        snmpEngine = engine.SnmpEngine()

        # Transport setup
        # UDP over IPv4
        config.addSocketTransport(
            snmpEngine,
            udp.domainName,
            udp.UdpTransport().openServerMode((self._configdata.Localaddress, \
                                             self._configdata.Listenport))
        )

        try:
            for agentip in self._configdata.Hostdata.keys():
                issuccess = self._configdata.Hostdata[agentip][
                    HOST_CFG_KEY_ISSUCCESS]
                if issuccess != True:
                    continue
                version = self._configdata.Hostdata[agentip][
                    HOST_CFG_KEY_TRAPSNMPVERSION]
                if 'V3' == version.upper():
                    # SNMPv3/USM setup
                    authProtocol = str(self._configdata.Hostdata[agentip]
                                       [HOST_CFG_KEY_AUTHPROTOCOL])
                    privProtocol = str(self._configdata.Hostdata[agentip]
                                       [HOST_CFG_KEY_PRIVPROTOCOL])
                    username = str(
                        self._configdata.Hostdata[agentip][HOST_CFG_KEY_USER])
                    password = str(
                        self._configdata.Hostdata[agentip][HOST_CFG_KEY_PASS])
                    enginid = str(self._configdata.Hostdata[agentip]
                                  [HOST_CFG_KEY_ENGINID])

                    if enginid is None or enginid == '':
                        logger.info(
                            "enginid is null,please check device,ipaddr :" +
                            str(agentip))
                        strEnginid = None
                    else:
                        strEnginid = v2c.OctetString(hexValue=enginid)

                    if authProtocol == 'MD5' and privProtocol == "DES":
                        config.addV3User(snmpEngine,
                                         username,
                                         config.usmHMACMD5AuthProtocol,
                                         password,
                                         config.usmDESPrivProtocol,
                                         password,
                                         contextEngineId=strEnginid)
                    elif authProtocol == 'MD5' and privProtocol == "AES":
                        config.addV3User(snmpEngine,
                                         username,
                                         config.usmHMACMD5AuthProtocol,
                                         password,
                                         config.usmAesCfb128Protocol,
                                         password,
                                         contextEngineId=strEnginid)
                    elif authProtocol == 'SHA' and privProtocol == "DES":
                        config.addV3User(snmpEngine,
                                         username,
                                         config.usmHMACSHAAuthProtocol,
                                         password,
                                         config.usmDESPrivProtocol,
                                         password,
                                         contextEngineId=strEnginid)
                    elif authProtocol == 'SHA' and privProtocol == "AES":
                        config.addV3User(snmpEngine,
                                         username,
                                         config.usmHMACSHAAuthProtocol,
                                         password,
                                         config.usmAesCfb128Protocol,
                                         password,
                                         contextEngineId=strEnginid)
                else:
                    # v1/2 setup
                    trapcommunity = str(self._configdata.Hostdata[agentip]
                                        [HOST_CFG_KEY_TRAPCOMMUNITY])
                    config.addV1System(snmpEngine, 'test-agent', trapcommunity)
        except Exception, err:
            logger.error("cache userinfor ,error :" + str(err))
            snmpEngine.transportDispatcher.closeDispatcher()
            raise
Beispiel #52
0
    def _setup(self, q, port):
        """Setup a new agent in a separate process.

        The port the agent is listening too will be returned using the
        provided queue.
        """
        snmpEngine = engine.SnmpEngine()
        if self.ipv6:
            config.addSocketTransport(
                snmpEngine,
                udp6.domainName,
                udp6.Udp6Transport().openServerMode(('::1', port)))
        else:
            config.addSocketTransport(
                snmpEngine,
                udp.domainName,
                udp.UdpTransport().openServerMode(('127.0.0.1', port)))
        # Community is public and MIB is writable
        config.addV1System(snmpEngine, 'read-write', self.community)
        config.addVacmUser(snmpEngine, 1, 'read-write', 'noAuthNoPriv',
                           (1, 3, 6), (1, 3, 6))
        config.addVacmUser(snmpEngine, 2, 'read-write', 'noAuthNoPriv',
                           (1, 3, 6), (1, 3, 6))
        config.addV3User(
            snmpEngine, 'read-write',
            config.usmHMACMD5AuthProtocol, self.authpass,
            config.usmAesCfb128Protocol, self.privpass)
        config.addVacmUser(snmpEngine, 3, 'read-write', 'authPriv',
                           (1, 3, 6), (1, 3, 6))

        # Build MIB
        def stringToOid(string):
            return [ord(x) for x in string]

        def flatten(*args):
            result = []
            for el in args:
                if isinstance(el, (list, tuple)):
                    for sub in el:
                        result.append(sub)
                else:
                    result.append(el)
            return tuple(result)
        snmpContext = context.SnmpContext(snmpEngine)
        mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
        (MibTable, MibTableRow, MibTableColumn,
         MibScalar, MibScalarInstance) = mibBuilder.importSymbols(
            'SNMPv2-SMI',
            'MibTable', 'MibTableRow', 'MibTableColumn',
            'MibScalar', 'MibScalarInstance')

        class RandomMibScalarInstance(MibScalarInstance):
            previous_value = 0

            def getValue(self, name, idx):
                self.previous_value += random.randint(1, 2000)
                return self.getSyntax().clone(self.previous_value)

        mibBuilder.exportSymbols(
            '__MY_SNMPv2_MIB',
            # SNMPv2-MIB::sysDescr
            MibScalar((1, 3, 6, 1, 2, 1, 1, 1), v2c.OctetString()),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 1, 1), (0,),
                              v2c.OctetString(
                                  "Snimpy Test Agent {0}".format(
                                      self.community))))
        mibBuilder.exportSymbols(
            '__MY_IF_MIB',
            # IF-MIB::ifNumber
            MibScalar((1, 3, 6, 1, 2, 1, 2, 1), v2c.Integer()),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 2, 1), (0,), v2c.Integer(3)),
            # IF-MIB::ifTable
            MibTable((1, 3, 6, 1, 2, 1, 2, 2)),
            MibTableRow((1, 3, 6, 1, 2, 1, 2, 2, 1)).setIndexNames(
                (0, '__MY_IF_MIB', 'ifIndex')),
            # IF-MIB::ifIndex
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (1,), v2c.Integer(1)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (2,), v2c.Integer(2)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), (3,), v2c.Integer(3)),
            # IF-MIB::ifDescr
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), v2c.OctetString()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (1,), v2c.OctetString("lo")),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (2,), v2c.OctetString("eth0")),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), (3,), v2c.OctetString("eth1")),
            # IF-MIB::ifType
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 3), v2c.Integer()),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (1,), v2c.Integer(24)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (2,), v2c.Integer(6)),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), (3,), v2c.Integer(6)),
            # IF-MIB::ifInOctets
            MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 10), v2c.Integer()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (1,), v2c.Gauge32()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (2,), v2c.Gauge32()),
            RandomMibScalarInstance(
                (1, 3, 6, 1, 2, 1, 2, 2, 1, 10), (3,), v2c.Gauge32()),
            # IF-MIB::ifIndex
            ifIndex=MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 1),
                                   v2c.Integer()))

        args = (
            '__MY_SNIMPY-MIB',
            # SNIMPY-MIB::snimpyIpAddress
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 1),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 1), (0,),
                v2c.OctetString("AAAA")),
            # SNIMPY-MIB::snimpyString
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 2),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 2), (0,), v2c.OctetString("bye")),
            # SNIMPY-MIB::snimpyInteger
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 3),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 3), (0,), v2c.Integer(19)),
            # SNIMPY-MIB::snimpyEnum
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 4),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 4), (0,), v2c.Integer(2)),
            # SNIMPY-MIB::snimpyObjectId
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 5),
                      v2c.ObjectIdentifier()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 5), (
                0,), v2c.ObjectIdentifier((1, 3, 6, 4454, 0, 0))),
            # SNIMPY-MIB::snimpyBoolean
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 6),
                      v2c.Integer()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 6), (0,), v2c.Integer(1)),
            # SNIMPY-MIB::snimpyCounter
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 7),
                      v2c.Counter32()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 7), (0,), v2c.Counter32(47)),
            # SNIMPY-MIB::snimpyGauge
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 8),
                      v2c.Gauge32()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 8), (0,), v2c.Gauge32(18)),
            # SNIMPY-MIB::snimpyTimeticks
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 9),
                      v2c.TimeTicks()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 9), (0,),
                v2c.TimeTicks(12111100)),
            # SNIMPY-MIB::snimpyCounter64
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 10),
                      v2c.Counter64()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 10), (0,),
                v2c.Counter64(2 ** 48 + 3)),
            # SNIMPY-MIB::snimpyBits
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 11),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance(
                (1, 3, 6, 1, 2, 1, 45121, 1, 11), (0,),
                v2c.OctetString(b"\xa0")),
            # SNIMPY-MIB::snimpyMacAddress
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 15),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 15), (
                0,), v2c.OctetString(b"\x11\x12\x13\x14\x15\x16")),
            # SNIMPY-MIB::snimpyMacAddressInvalid
            MibScalar((1, 3, 6, 1, 2, 1, 45121, 1, 16),
                      v2c.OctetString()).setMaxAccess("readwrite"),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 1, 16), (
                0,), v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")),

            # SNIMPY-MIB::snimpyIndexTable
            MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 3)),
            MibTableRow(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1)).setIndexNames(
                (0, "__MY_SNIMPY-MIB", "snimpyIndexVarLen"),
                (0, "__MY_SNIMPY-MIB", "snimpyIndexOidVarLen"),
                (0, "__MY_SNIMPY-MIB", "snimpyIndexFixedLen"),
                (1, "__MY_SNIMPY-MIB", "snimpyIndexImplied")),
            # SNIMPY-MIB::snimpyIndexVarLen
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row1'),
                                      3, 1, 2, 3,
                                      stringToOid('alpha5'),
                                      stringToOid('end of row1')),
                              v2c.OctetString(b"row1")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row2'),
                                      4, 1, 0, 2, 3,
                                      stringToOid('beta32'),
                                      stringToOid('end of row2')),
                              v2c.OctetString(b"row2")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                              flatten(4, stringToOid('row3'),
                                      4, 120, 1, 2, 3,
                                      stringToOid('gamma7'),
                                      stringToOid('end of row3')),
                              v2c.OctetString(b"row3")),
            # SNIMPY-MIB::snimpyIndexInt
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row1'),
                                      3, 1, 2, 3,
                                      stringToOid('alpha5'),
                                      stringToOid('end of row1')),
                              v2c.Integer(4571)),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row2'),
                                      4, 1, 0, 2, 3,
                                      stringToOid('beta32'),
                                      stringToOid('end of row2')),
                              v2c.Integer(78741)),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                              flatten(4, stringToOid('row3'),
                                      4, 120, 1, 2, 3,
                                      stringToOid('gamma7'),
                                      stringToOid('end of row3')),
                              v2c.Integer(4110)),

            # SNIMPY-MIB::snimpyInvalidTable
            MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 5)),
            MibTableRow(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1)).setIndexNames(
                (0, "__MY_SNIMPY-MIB", "snimpyInvalidIndex")),
            # SNIMPY-MIB::snimpyInvalidDescr
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                              (1,),
                              v2c.OctetString(b"Hello")),
            MibScalarInstance((1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                              (2,),
                              v2c.OctetString(b"\xf1\x12\x13\x14\x15\x16")))

        if self.emptyTable:
            args += (
                # SNIMPY-MIB::snimpyEmptyTable
                MibTable((1, 3, 6, 1, 2, 1, 45121, 2, 6)),
                MibTableRow(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1)).setIndexNames(
                        (0, "__MY_SNIMPY-MIB", "snimpyEmptyIndex")))

        kwargs = dict(
            # Indexes
            snimpyIndexVarLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 1),
                v2c.OctetString(
                )),
            snimpyIndexIntIndex=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 2),
                v2c.Integer(
                )).setMaxAccess(
                "noaccess"),
            snimpyIndexOidVarLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 3),
                v2c.ObjectIdentifier(
                )).setMaxAccess(
                "noaccess"),
            snimpyIndexFixedLen=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 4),
                v2c.OctetString(
                ).setFixedLength(
                    6)).setMaxAccess(
                "noaccess"),
            snimpyIndexImplied=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 5),
                v2c.OctetString(
                )).setMaxAccess("noaccess"),
            snimpyIndexInt=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 3, 1, 6),
                v2c.Integer()).setMaxAccess("readwrite"),
            snimpyInvalidIndex=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 1),
                v2c.Integer()).setMaxAccess("noaccess"),
            snimpyInvalidDescr=MibTableColumn(
                (1, 3, 6, 1, 2, 1, 45121, 2, 5, 1, 2),
                v2c.OctetString()).setMaxAccess("readwrite")
        )

        if self.emptyTable:
            kwargs.update(dict(
                snimpyEmptyIndex=MibTableColumn(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1, 1),
                    v2c.Integer()).setMaxAccess("noaccess"),
                snimpyEmptyDescr=MibTableColumn(
                    (1, 3, 6, 1, 2, 1, 45121, 2, 6, 1, 2),
                    v2c.OctetString()).setMaxAccess("readwrite")))

        mibBuilder.exportSymbols(*args, **kwargs)

        # Start agent
        cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
        cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
        cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
        cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)
        q.put(port)
        snmpEngine.transportDispatcher.jobStarted(1)
        snmpEngine.transportDispatcher.runDispatcher()
Beispiel #53
0
## Optional debugging ('all' enables full debugging)
#debug.setLogger(debug.Debug('io', 'dsp', 'msgproc', 'secmod', 'app'))

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()


#
# Transport setup
#

# UDP over IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('127.0.0.1', 161))
)

# UDP over IPv6
config.addSocketTransport(
    snmpEngine,
    udp6.domainName,
    udp6.Udp6Transport().openServerMode(('::1', 161))
    )

# Local domain sockets
config.addSocketTransport(
    snmpEngine,
    unix.domainName,
    unix.UnixTransport().openServerMode('/tmp/snmp-agent')
Beispiel #54
0
from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c

# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()

# Transport setup

# UDP over IPv4
config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('10.100.206.223', 162))
)

# SNMPv3/USM setup

config.addV3User(
    snmpEngine, 'Administrator',
    config.usmHMACSHAAuthProtocol,#authProtocol,sha
     'Admin@9000',#authKey
    config.usmAesCfb128Protocol,#privProtocol,aes
     'Admin@9000', #privKey
    contextEngineId=v2c.OctetString(hexValue='8000000001020304')
)

# Callback function for receiving notifications
def cbFun(snmpEngine,
Beispiel #55
0
#亁颐堂官网www.qytang.com
#乾颐盾课程包括传统网络安全(防火墙,IPS...)与Python语言和黑客渗透课程!
from pysnmp.entity import engine, config
from pysnmp.carrier.asynsock.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c
#from sendmail import sendTrapInfo
import sys
import re

# Create SNMP engine with autogenernated engineID and pre-bound
snmpEngine = engine.SnmpEngine()

config.addSocketTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('202.100.1.138', 162))
)

#Callback function for receiving notifications
def cbFun(snmpEngine,
          stateReference,
          contextEngineId, contextName,
          varBinds,
          cbCtx):
#    print('Notification received, ContextEngineId "%s", ContextName "%s"' % (
#        contextEngineId.prettyPrint(), contextName.prettyPrint()
#        )
#    )
    for name, val in varBinds:
#        print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
Beispiel #56
0
def main():

    parser = argparse.ArgumentParser(add_help=False)

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

    parser.add_argument(
        '-h', action='store_true', dest='usage',
        help='Brief usage message')

    parser.add_argument(
        '--help', action='store_true',
        help='Detailed help message')

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

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

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

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

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

    parser.add_argument(
        '--reporting-method', type=lambda x: x.split(':'),
        metavar='=<%s[:args]>]' % '|'.join(ReportingManager.REPORTERS),
        default='null', help='Activity metrics reporting method.')

    parser.add_argument(
        '--daemonize', action='store_true',
        help='Disengage from controlling terminal and become a daemon')

    parser.add_argument(
        '--process-user', type=str,
        help='If run as root, switch simulator daemon to this user right '
             'upon binding privileged ports')

    parser.add_argument(
        '--process-group', type=str,
        help='If run as root, switch simulator daemon to this group right '
             'upon binding privileged ports')

    parser.add_argument(
        '--pid-file', metavar='<FILE>', type=str,
        default='/var/run/%s/%s.pid' % (__name__, os.getpid()),
        help='SNMP simulation data file to write records to')

    parser.add_argument(
        '--cache-dir', metavar='<DIR>', type=str,
        help='Location for SNMP simulation data file indices to create')

    parser.add_argument(
        '--force-index-rebuild', action='store_true',
        help='Rebuild simulation data files indices even if they seem '
             'up to date')

    parser.add_argument(
        '--validate-data', action='store_true',
        help='Validate simulation data files on daemon start-up')

    parser.add_argument(
        '--variation-modules-dir', metavar='<DIR>', type=str,
        action='append', default=[],
        help='Variation modules search path(s)')

    parser.add_argument(
        '--variation-module-options', metavar='<module[=alias][:args]>',
        type=str, action='append', default=[],
        help='Options for a specific variation module')

    parser.add_argument(
        '--v3-only', action='store_true',
        help='Trip legacy SNMP v1/v2c support to gain a little lesser memory '
             'footprint')

    parser.add_argument(
        '--transport-id-offset', type=int, default=0,
        help='Start numbering the last sub-OID of transport endpoint OIDs '
             'starting from this ID')

    parser.add_argument(
        '--max-var-binds', type=int, default=64,
        help='Maximum number of variable bindings to include in a single '
             'response')

    parser.add_argument(
        '--args-from-file', metavar='<FILE>', type=str,
        help='Read SNMP engine(s) command-line configuration from this '
             'file. Can be useful when command-line is too long')

    # We do not parse SNMP params with argparse, but we want its -h/--help
    snmp_helper = argparse.ArgumentParser(
        description=DESCRIPTION, add_help=False, parents=[parser])

    v3_usage = """\
Configure one or more independent SNMP engines. Each SNMP engine has a
distinct engine ID, its own set of SNMP USM users, one or more network
transport endpoints to listen on and its own simulation data directory.

Each SNMP engine configuration starts with `--v3-engine-id <arg>` parameter
followed by other configuration options up to the next `--v3-engine-id`
option or end of command line

Example
-------

$ snmp-command-responder \\
    --v3-engine-id auto \\
        --data-dir ./data --agent-udpv4-endpoint=127.0.0.1:1024 \\
    --v3-engine-id auto \\
        --data-dir ./data --agent-udpv4-endpoint=127.0.0.1:1025 \\ 
        --data-dir ./data --agent-udpv4-endpoint=127.0.0.1:1026

Besides network endpoints, simulated agents can be addressed by SNMPv1/v2c
community name or SNMPv3 context engine ID/name. These parameters are
configured automatically based on simulation data file paths relative to
`--data-dir`.
"""
    v3_group = snmp_helper.add_argument_group(v3_usage)

    v3_group.add_argument(
        '--v3-engine-id', type=str, metavar='<HEX|auto>', default='auto',
        help='SNMPv3 engine ID')

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

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

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

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

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

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

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

    v3_group.add_argument(
        '--agent-udpv4-endpoint', type=endpoints.parse_endpoint,
        metavar='<[X.X.X.X]:NNNNN>',
        help='SNMP agent UDP/IPv4 address to listen on (name:port)')

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

    v3_group.add_argument(
        '--data-dir',
        type=str, metavar='<DIR>',
        help='SNMP simulation data recordings directory.')

    args, unparsed_args = parser.parse_known_args()

    if args.usage:
        snmp_helper.print_usage(sys.stderr)
        return 1

    if args.help:
        snmp_helper.print_help(sys.stderr)
        return 1

    _, unknown_args = snmp_helper.parse_known_args(unparsed_args)
    if unknown_args:
        sys.stderr.write(
            'ERROR: Unknown command-line parameter(s) '
            '%s\r\n' % ' '.join(unknown_args))
        snmp_helper.print_usage(sys.stderr)
        return 1

    # Reformat unparsed args into a list of (option, value) tuples
    snmp_args = []
    name = None

    for opt in unparsed_args:
        if '=' in opt:
            snmp_args.append(opt.split('='))

        elif name:
            snmp_args.append((name, opt))
            name = None

        else:
            name = opt

    if name:
        sys.stderr.write(
            'ERROR: Non-paired command-line key-value parameter '
            '%s\r\n' % name)
        snmp_helper.print_usage(sys.stderr)
        return 1

    if args.cache_dir:
        confdir.cache = args.cache_dir

    if args.variation_modules_dir:
        confdir.variation = args.variation_modules_dir

    variation_modules_options = variation.parse_modules_options(
        args.variation_module_options)

    if args.args_from_file:
        try:
            with open(args.args_from_file) as fl:
                snmp_args.extend([handler.split('=', 1) for handler in fl.read().split()])

        except Exception as exc:
            sys.stderr.write(
                'ERROR: file %s opening failure: '
                '%s\r\n' % (args.args_from_file, exc))
            snmp_helper.print_usage(sys.stderr)
            return 1

    with daemon.PrivilegesOf(args.process_user, args.process_group):

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

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

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

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

        try:
            ReportingManager.configure(*args.reporting_method)

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

    if args.daemonize:
        try:
            daemon.daemonize(args.pid_file)

        except Exception as exc:
            sys.stderr.write(
                'ERROR: cant daemonize process: %s\r\n' % exc)
            snmp_helper.print_usage(sys.stderr)
            return 1

    if not os.path.exists(confdir.cache):
        try:
            with daemon.PrivilegesOf(args.process_user, args.process_group):
                os.makedirs(confdir.cache)

        except OSError as exc:
            log.error('failed to create cache directory "%s": '
                      '%s' % (confdir.cache, exc))
            return 1

        else:
            log.info('Cache directory "%s" created' % confdir.cache)

    variation_modules = variation.load_variation_modules(
        confdir.variation, variation_modules_options)

    with daemon.PrivilegesOf(args.process_user, args.process_group):
        variation.initialize_variation_modules(
            variation_modules, mode='variating')

    def configure_managed_objects(
            data_dirs, data_index_instrum_controller, snmp_engine=None,
            snmp_context=None):
        """Build pysnmp Managed Objects base from data files information"""

        _mib_instrums = {}
        _data_files = {}

        for dataDir in data_dirs:

            log.info(
                'Scanning "%s" directory for %s data '
                'files...' % (dataDir, ','.join(
                    [' *%s%s' % (os.path.extsep, x.ext)
                     for x in variation.RECORD_TYPES.values()])))

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

            log.msg.inc_ident()

            for (full_path,
                 text_parser,
                 community_name) in datafile.get_data_files(dataDir):
                if community_name in _data_files:
                    log.error(
                        'ignoring duplicate Community/ContextName "%s" for data '
                        'file %s (%s already loaded)' % (community_name, full_path,
                                                         _data_files[community_name]))
                    continue

                elif full_path in _mib_instrums:
                    mib_instrum = _mib_instrums[full_path]
                    log.info('Configuring *shared* %s' % (mib_instrum,))

                else:
                    data_file = datafile.DataFile(
                        full_path, text_parser, variation_modules)
                    data_file.index_text(args.force_index_rebuild, args.validate_data)

                    MibController = controller.MIB_CONTROLLERS[data_file.layout]
                    mib_instrum = MibController(data_file)

                    _mib_instrums[full_path] = mib_instrum
                    _data_files[community_name] = full_path

                    log.info('Configuring %s' % (mib_instrum,))

                log.info('SNMPv1/2c community name: %s' % (community_name,))

                agent_name = md5(
                    univ.OctetString(community_name).asOctets()).hexdigest()

                context_name = agent_name

                if not args.v3_only:
                    # snmpCommunityTable::snmpCommunityIndex can't be > 32
                    config.addV1System(
                        snmp_engine, agent_name, community_name,
                        contextName=context_name)

                snmp_context.registerContextName(context_name, mib_instrum)

                if len(community_name) <= 32:
                    snmp_context.registerContextName(community_name, mib_instrum)

                data_index_instrum_controller.add_data_file(
                    full_path, community_name, context_name)

                log.info(
                    'SNMPv3 Context Name: %s'
                    '%s' % (context_name, len(community_name) <= 32 and
                            ' or %s' % community_name or ''))

            log.msg.dec_ident()

        del _mib_instrums
        del _data_files

    # Bind transport endpoints
    for idx, opt in enumerate(snmp_args):
        if opt[0] == '--agent-udpv4-endpoint':
            snmp_args[idx] = (
                opt[0], endpoints.IPv4TransportEndpoints().add(opt[1]))

        elif opt[0] == '--agent-udpv6-endpoint':
            snmp_args[idx] = (
                opt[0], endpoints.IPv6TransportEndpoints().add(opt[1]))

    # Start configuring SNMP engine(s)

    transport_dispatcher = AsyncoreDispatcher()

    transport_dispatcher.registerRoutingCbFun(lambda td, t, d: td)

    if not snmp_args or snmp_args[0][0] != '--v3-engine-id':
        snmp_args.insert(0, ('--v3-engine-id', 'auto'))

    if snmp_args and snmp_args[-1][0] != 'end-of-options':
        snmp_args.append(('end-of-options', ''))

    snmp_engine = None

    transport_index = {
        'udpv4': args.transport_id_offset,
        'udpv6': args.transport_id_offset,
    }

    for opt in snmp_args:

        if opt[0] in ('--v3-engine-id', 'end-of-options'):

            if snmp_engine:

                log.info('--- SNMP Engine configuration')

                log.info(
                    'SNMPv3 EngineID: '
                    '%s' % (hasattr(snmp_engine, 'snmpEngineID')
                            and snmp_engine.snmpEngineID.prettyPrint() or '<unknown>',))

                if not v3_context_engine_ids:
                    v3_context_engine_ids.append((None, []))

                log.msg.inc_ident()

                log.info('--- Simulation data recordings configuration')

                for v3_context_engine_id, ctx_data_dirs in v3_context_engine_ids:
                    snmp_context = context.SnmpContext(snmp_engine, v3_context_engine_id)
                    # unregister default context
                    snmp_context.unregisterContextName(null)

                    log.info(
                        'SNMPv3 Context Engine ID: '
                        '%s' % snmp_context.contextEngineId.prettyPrint())

                    data_index_instrum_controller = controller.DataIndexInstrumController()

                    with daemon.PrivilegesOf(args.process_user, args.process_group):
                        configure_managed_objects(
                            ctx_data_dirs or data_dirs or confdir.data,
                            data_index_instrum_controller,
                            snmp_engine,
                            snmp_context
                        )

                # Configure access to data index

                config.addV1System(snmp_engine, 'index',
                                   'index', contextName='index')

                log.info('--- SNMPv3 USM configuration')

                if not v3_users:
                    v3_users = ['simulator']
                    v3_auth_keys[v3_users[0]] = 'auctoritas'
                    v3_auth_protos[v3_users[0]] = 'MD5'
                    v3_priv_keys[v3_users[0]] = 'privatus'
                    v3_priv_protos[v3_users[0]] = 'DES'

                for v3User in v3_users:
                    if v3User in v3_auth_keys:
                        if v3User not in v3_auth_protos:
                            v3_auth_protos[v3User] = 'MD5'

                    elif v3User in v3_auth_protos:
                        log.error(
                            'auth protocol configured without key for user '
                            '%s' % v3User)
                        return 1

                    else:
                        v3_auth_keys[v3User] = None
                        v3_auth_protos[v3User] = 'NONE'

                    if v3User in v3_priv_keys:
                        if v3User not in v3_priv_protos:
                            v3_priv_protos[v3User] = 'DES'

                    elif v3User in v3_priv_protos:
                        log.error(
                            'privacy protocol configured without key for user '
                            '%s' % v3User)
                        return 1

                    else:
                        v3_priv_keys[v3User] = None
                        v3_priv_protos[v3User] = 'NONE'

                    if (AUTH_PROTOCOLS[v3_auth_protos[v3User]] == config.usmNoAuthProtocol and
                            PRIV_PROTOCOLS[v3_priv_protos[v3User]] != config.usmNoPrivProtocol):
                        log.error(
                            'privacy impossible without authentication for USM user '
                            '%s' % v3User)
                        return 1

                    try:
                        config.addV3User(
                            snmp_engine,
                            v3User,
                            AUTH_PROTOCOLS[v3_auth_protos[v3User]],
                            v3_auth_keys[v3User],
                            PRIV_PROTOCOLS[v3_priv_protos[v3User]],
                            v3_priv_keys[v3User])

                    except error.PySnmpError as exc:
                        log.error(
                            'bad USM values for user %s: '
                            '%s' % (v3User, exc))
                        return 1

                    log.info('SNMPv3 USM SecurityName: %s' % v3User)

                    if AUTH_PROTOCOLS[v3_auth_protos[v3User]] != config.usmNoAuthProtocol:
                        log.info(
                            'SNMPv3 USM authentication key: %s, '
                            'authentication protocol: '
                            '%s' % (v3_auth_keys[v3User], v3_auth_protos[v3User]))

                    if PRIV_PROTOCOLS[v3_priv_protos[v3User]] != config.usmNoPrivProtocol:
                        log.info(
                            'SNMPv3 USM encryption (privacy) key: %s, '
                            'encryption protocol: '
                            '%s' % (v3_priv_keys[v3User], v3_priv_protos[v3User]))

                snmp_context.registerContextName('index', data_index_instrum_controller)

                log.info(
                    'Maximum number of variable bindings in SNMP response: '
                    '%s' % local_max_var_binds)

                log.info('--- Transport configuration')

                if not agent_udpv4_endpoints and not agent_udpv6_endpoints:
                    log.error(
                        'agent endpoint address(es) not specified for SNMP '
                        'engine ID %s' % v3_engine_id)
                    return 1

                for agent_udpv4_endpoint in agent_udpv4_endpoints:
                    transport_domain = udp.domainName + (transport_index['udpv4'],)
                    transport_index['udpv4'] += 1

                    snmp_engine.registerTransportDispatcher(
                        transport_dispatcher, transport_domain)

                    config.addSocketTransport(
                        snmp_engine, transport_domain, agent_udpv4_endpoint[0])

                    log.info(
                        'Listening at UDP/IPv4 endpoint %s, transport ID '
                        '%s' % (agent_udpv4_endpoint[1],
                                '.'.join([str(handler) for handler in transport_domain])))

                for agent_udpv6_endpoint in agent_udpv6_endpoints:
                    transport_domain = udp6.domainName + (transport_index['udpv6'],)
                    transport_index['udpv6'] += 1

                    snmp_engine.registerTransportDispatcher(
                        transport_dispatcher, transport_domain)

                    config.addSocketTransport(
                        snmp_engine,
                        transport_domain, agent_udpv6_endpoint[0])

                    log.info(
                        'Listening at UDP/IPv6 endpoint %s, transport ID '
                        '%s' % (agent_udpv6_endpoint[1],
                                '.'.join([str(handler) for handler in transport_domain])))

                # SNMP applications
                GetCommandResponder(snmp_engine, snmp_context)
                SetCommandResponder(snmp_engine, snmp_context)
                NextCommandResponder(snmp_engine, snmp_context)
                BulkCommandResponder(
                    snmp_engine, snmp_context).maxVarBinds = local_max_var_binds

                log.msg.dec_ident()

                if opt[0] == 'end-of-options':
                    # Load up the rest of MIBs while running privileged
                    (snmp_engine
                     .msgAndPduDsp
                     .mibInstrumController
                     .mibBuilder.loadModules())
                    break

            # Prepare for next engine ID configuration

            v3_context_engine_ids = []
            data_dirs = []
            local_max_var_binds = args.max_var_binds
            v3_users = []
            v3_auth_keys = {}
            v3_auth_protos = {}
            v3_priv_keys = {}
            v3_priv_protos = {}
            agent_udpv4_endpoints = []
            agent_udpv6_endpoints = []

            try:
                v3_engine_id = opt[1]
                if not v3_engine_id or v3_engine_id.lower() == 'auto':
                    snmp_engine = engine.SnmpEngine()

                else:
                    snmp_engine = engine.SnmpEngine(
                        snmpEngineID=univ.OctetString(hexValue=v3_engine_id))

            except Exception as exc:
                log.error(
                    'SNMPv3 Engine initialization failed, EngineID "%s": '
                    '%s' % (v3_engine_id, exc))
                return 1

            config.addContext(snmp_engine, '')

        elif opt[0] == '--v3-context-engine-id':
            v3_context_engine_ids.append((univ.OctetString(hexValue=opt[1]), []))

        elif opt[0] == '--data-dir':
            if v3_context_engine_ids:
                v3_context_engine_ids[-1][1].append(opt[1])

            else:
                data_dirs.append(opt[1])

        elif opt[0] == '--max-varbinds':
            local_max_var_binds = opt[1]

        elif opt[0] == '--v3-user':
            v3_users.append(opt[1])

        elif opt[0] == '--v3-auth-key':
            if not v3_users:
                log.error('--v3-user should precede %s' % opt[0])
                return 1

            if v3_users[-1] in v3_auth_keys:
                log.error(
                    'repetitive %s option for user %s' % (opt[0], v3_users[-1]))
                return 1

            v3_auth_keys[v3_users[-1]] = opt[1]

        elif opt[0] == '--v3-auth-proto':
            if opt[1].upper() not in AUTH_PROTOCOLS:
                log.error('bad v3 auth protocol %s' % opt[1])
                return 1

            else:
                if not v3_users:
                    log.error('--v3-user should precede %s' % opt[0])
                    return 1

                if v3_users[-1] in v3_auth_protos:
                    log.error(
                        'repetitive %s option for user %s' % (opt[0], v3_users[-1]))
                    return 1

                v3_auth_protos[v3_users[-1]] = opt[1].upper()

        elif opt[0] == '--v3-priv-key':
            if not v3_users:
                log.error('--v3-user should precede %s' % opt[0])
                return 1

            if v3_users[-1] in v3_priv_keys:
                log.error(
                    'repetitive %s option for user %s' % (opt[0], v3_users[-1]))
                return 1

            v3_priv_keys[v3_users[-1]] = opt[1]

        elif opt[0] == '--v3-priv-proto':
            if opt[1].upper() not in PRIV_PROTOCOLS:
                log.error('bad v3 privacy protocol %s' % opt[1])
                return 1

            else:
                if not v3_users:
                    log.error('--v3-user should precede %s' % opt[0])
                    return 1

                if v3_users[-1] in v3_priv_protos:
                    log.error(
                        'repetitive %s option for user %s' % (opt[0], v3_users[-1]))
                    return 1

                v3_priv_protos[v3_users[-1]] = opt[1].upper()

        elif opt[0] == '--agent-udpv4-endpoint':
            agent_udpv4_endpoints.append(opt[1])

        elif opt[0] == '--agent-udpv6-endpoint':
            agent_udpv6_endpoints.append(opt[1])

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

    with daemon.PrivilegesOf(args.process_user, args.process_group, final=True):

        try:
            transport_dispatcher.runDispatcher()

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

        finally:
            if variation_modules:
                log.info('Shutting down variation modules:')

                for name, contexts in variation_modules.items():
                    body = contexts[0]
                    try:
                        body['shutdown'](options=body['args'], mode='variation')

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

                    else:
                        log.info('Variation module "%s" shutdown OK' % name)

            transport_dispatcher.closeDispatcher()

            log.info('Process terminated')

    return 0