Esempio n. 1
0
def escucharTrap():
    print("Escucho")
    # se queda escuchando, lanza callback (cb) cuando recibe paquyete
    transportDispatcher = AsyncoreDispatcher()

    transportDispatcher.registerRecvCbFun(cbFun)

    # UDP/IPv4
    transportDispatcher.registerTransport(
        udp.domainName,
        udp.UdpSocketTransport().openServerMode(('0.0.0.0', 162)))

    # UDP/IPv6
    transportDispatcher.registerTransport(
        udp6.domainName,
        udp6.Udp6SocketTransport().openServerMode(('::1', 162)))

    transportDispatcher.jobStarted(1)

    try:
        # Dispatcher will never finish as job#1 never reaches zero
        transportDispatcher.runDispatcher()
    except:
        transportDispatcher.closeDispatcher()

        raise
Esempio n. 2
0
    def run(self):
        super(SnmpParsingService, self).run()
        LOG.info("Vitrage SNMP Parsing Service - Starting...")

        transport_dispatcher = AsyncoreDispatcher()
        transport_dispatcher.registerRecvCbFun(self.callback_func)

        trans_udp = udp.UdpSocketTransport()
        udp_transport = \
            trans_udp.openServerMode(('0.0.0.0', self.listening_port))

        trans_udp6 = udp6.Udp6SocketTransport()
        udp6_transport = \
            trans_udp6.openServerMode(('::1', self.listening_port))

        transport_dispatcher.registerTransport(udp.domainName, udp_transport)
        transport_dispatcher.registerTransport(udp6.domainName, udp6_transport)
        LOG.info("Vitrage SNMP Parsing Service - Started!")

        transport_dispatcher.jobStarted(self.RUN_FOREVER)
        try:
            transport_dispatcher.runDispatcher()
        except Exception:
            LOG.error("Run transport dispatcher failed.")
            transport_dispatcher.closeDispatcher()
            raise
Esempio n. 3
0
    def __init__(self, data, timeout_func=None, receive_func=None, error_func=None):
        self.__dict__.update(data)

        self.timeout_func = timeout_func
        self.receive_func = receive_func
        self.error_func = error_func

        headVars = [v2c.ObjectIdentifier(oid) for oid in
                    map(lambda oid: (int(i) for i in oid.split('.')), self.oid_keys)]

        self.reqPDU = reqPDU = v2c.GetBulkRequestPDU()
        v2c.apiBulkPDU.setDefaults(reqPDU)
        v2c.apiBulkPDU.setNonRepeaters(reqPDU, self.non_repeaters)
        v2c.apiBulkPDU.setMaxRepetitions(reqPDU, self.max_repetitions)
        v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x in headVars])

        reqMsg = v2c.Message()
        v2c.apiMessage.setDefaults(reqMsg)
        v2c.apiMessage.setCommunity(reqMsg, self.community)
        v2c.apiMessage.setPDU(reqMsg, reqPDU)

        self.startedAt = time()

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(self.cbRecvFun)
        transportDispatcher.registerTimerCbFun(self.cbTimerFun)

        transportDispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openClientMode())
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName, (self.network_address, self.port))
        transportDispatcher.jobStarted(1)

        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
Esempio n. 4
0
class SNMPPDUHarness(threading.Thread):
    def __init__(self, pdu, listen_address, listen_port, community="public"):
        super(SNMPPDUHarness, self).__init__()
        self.logger = logging.getLogger(__name__)

        self.pdu = pdu

        self.snmp_handler = SNMPPDUHandler(self.pdu, community=community)

        self.listen_address = listen_address
        self.listen_port = listen_port
        self.transportDispatcher = AsyncoreDispatcher()

    def run(self):
        self.logger.info("Starting PDU '{}' on {}:{}".format(
            self.pdu.name, self.listen_address, self.listen_port))
        self.transportDispatcher.registerRecvCbFun(
            self.snmp_handler.message_handler)

        # UDP/IPv4
        self.transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openServerMode(
                (self.listen_address, self.listen_port)))

        self.transportDispatcher.jobStarted(1)

        try:
            # Dispatcher will never finish as job#1 never reaches zero
            self.transportDispatcher.runDispatcher()
        except Exception:
            self.transportDispatcher.closeDispatcher()

    def stop(self):
        self.transportDispatcher.jobFinished(1)
Esempio n. 5
0
    def __init__(self, data, timeout_func=None, receive_func=None, error_func=None):
        self.__dict__.update(data)

        self.timeout_func = timeout_func
        self.receive_func = receive_func
        self.error_func = error_func

        self.pMod = pMod = api.protoModules[api.protoVersion2c]
        self.reqPDU = reqPDU = pMod.GetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)

        pMod.apiPDU.setVarBinds(reqPDU, ((oid, pMod.Null('')) for oid in self.oid_keys))

        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        self.startedAt = time()

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(self.cbRecvFun)
        transportDispatcher.registerTimerCbFun(self.cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openClientMode())
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName, (self.network_address, self.port))
        transportDispatcher.jobStarted(1)

        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
Esempio n. 6
0
    def __init__(self, data, timeout_func=None, receive_func=None, error_func=None):
        self.__dict__.update(data)

        self.timeout_func = timeout_func
        self.receive_func = receive_func
        self.error_func = error_func

        self.pMod = pMod = api.protoModules[api.protoVersion2c]

        self.reqPDU = reqPDU = pMod.SetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)

        pMod.apiPDU.setVarBinds(reqPDU,
                                map(lambda a: (a[0], pMod.OctetString(str(a[2]))) if a[1] == 'str'
                                    else (a[0], pMod.Integer(int(a[2]))), self.oid_keys_enc_val))

        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        self.startedAt = time()

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(self.cbRecvFun)
        transportDispatcher.registerTimerCbFun(self.cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openClientMode())
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName, (self.network_address, self.port))
        transportDispatcher.jobStarted(1)

        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
Esempio n. 7
0
def main():

    logging.basicConfig(filename='traps.log',
                        filemode='w',
                        level=logging.ERROR,
                        format='%(asctime)s %(message)s',
                        datefmt='%m/%d/%Y %I:%M:%S %p')

    transportDispatcher = AsyncoreDispatcher()

    transportDispatcher.registerRecvCbFun(cbFun)

    # UDP/IPv4
    transportDispatcher.registerTransport(
        udp.domainName,
        udp.UdpSocketTransport().openServerMode(('0.0.0.0', 162)))

    # UDP/IPv6
    transportDispatcher.registerTransport(
        udp6.domainName,
        udp6.Udp6SocketTransport().openServerMode(('::1', 162)))

    ## Local domain socket
    # transportDispatcher.registerTransport(
    #    unix.domainName, unix.UnixSocketTransport().openServerMode('/tmp/snmp-manager')
    # )

    transportDispatcher.jobStarted(1)

    try:
        # Dispatcher will never finish as job#1 never reaches zero
        transportDispatcher.runDispatcher()
    except:
        transportDispatcher.closeDispatcher()
        raise
Esempio n. 8
0
 def __init__(self):
     transportDispatcher = AsyncoreDispatcher()
     transportDispatcher.registerRecvCbFun(self.cbFun)
     transportDispatcher.registerTransport(udp.domainName, udp.UdpSocketTransport().openServerMode(('192.168.1.111', 162))) #RASPBERRY   /   PC IP ADRESS
     transportDispatcher.jobStarted(1)
     try:
         transportDispatcher.runDispatcher()
     except:
         transportDispatcher.closeDispatcher()
         raise
Esempio n. 9
0
class SNMPPDUHarness(threading.Thread):
    def __init__(self, pdu, listen_address, listen_port, community="public"):
        super(SNMPPDUHarness, self).__init__()
        self.logger = logging.getLogger(__name__)

        self.pdu = pdu

        self.snmp_handler = SNMPPDUHandler(self.pdu, community=community)

        self.listen_address = listen_address
        self.listen_port = listen_port
        self.transportDispatcher = AsyncoreDispatcher()

        self._lock = threading.Lock()
        self._stop_requested = False

    def run(self):
        with self._lock:
            if self._stop_requested:
                return

            self.logger.info("Starting PDU '{}' on {}:{}".format(
                self.pdu.name, self.listen_address, self.listen_port)
            )
            self.transportDispatcher.registerRecvCbFun(
                self.snmp_handler.message_handler)

            # UDP/IPv4
            self.transportDispatcher.registerTransport(
                udp.domainName,
                udp.UdpSocketTransport().openServerMode(
                    (self.listen_address, self.listen_port))
            )

            self.transportDispatcher.jobStarted(1)

        try:
            # Dispatcher will never finish as job#1 never reaches zero
            self.transportDispatcher.runDispatcher()
        except Exception:
            self.transportDispatcher.closeDispatcher()

    def stop(self):
        with self._lock:
            self._stop_requested = True
            try:
                self.transportDispatcher.jobFinished(1)
            except KeyError:
                pass  # The job is not started yet and will not start
Esempio n. 10
0
    def listenForTraps(self):
        asyncF = asyncFunc()
        transportDispatcher = AsyncoreDispatcher()

        transportDispatcher.registerRecvCbFun(asyncF.cbFun)

        transportDispatcher.registerTransport(
            udp.domainName, udp.UdpSocketTransport().openServerMode((self.SNMP_HOST, self.SNMP_PORT))
        )

        transportDispatcher.jobStarted(1)

        try:
            # Dispatcher will never finish as job#1 never reaches zero
            transportDispatcher.runDispatcher()

        finally:
            transportDispatcher.closeDispatcher()
Esempio n. 11
0
def run_dispatcher(conf):
    transportDispatcher = AsyncoreDispatcher()
    transportDispatcher.registerRecvCbFun(callback)

    for num, cfg_string in enumerate(conf.alerts_interfaces):
        parsed = cfg_string.split(':')
        address = (parsed[0], int(parsed[1]) if len(parsed) == 2 else 162)
        transportDispatcher.registerTransport(
            udp.domainName + (num + 1, ),
            udp.UdpSocketTransport().openServerMode(address))

    transportDispatcher.jobStarted(1)

    try:
        # Dispatcher will never finish as job#1 never reaches zero
        transportDispatcher.runDispatcher()
    except:
        transportDispatcher.closeDispatcher()
    raise
Esempio n. 12
0
def run_dispatcher(conf):
    transportDispatcher = AsyncoreDispatcher()
    transportDispatcher.registerRecvCbFun(callback)

    for num, cfg_string in enumerate(conf.alerts_interfaces):
        parsed = cfg_string.split(':')
        address = (parsed[0], int(parsed[1]) if len(parsed) == 2 else 162)
        transportDispatcher.registerTransport(
            udp.domainName + (num + 1,),
            udp.UdpSocketTransport().openServerMode(address))

    transportDispatcher.jobStarted(1)

    try:
        # Dispatcher will never finish as job#1 never reaches zero
        transportDispatcher.runDispatcher()
    except:
        transportDispatcher.closeDispatcher()
    raise
def openServer():
    print "In Open server mode"

    transportDispatcher = AsyncoreDispatcher()
    transportDispatcher.registerRecvCbFun(newFn)
    # UDP/IPv4
    transportDispatcher.registerTransport(
    udp.domainName, udp.UdpSocketTransport().openServerMode(('localhost', 1171))
    )

    # UDP/IPv6
    transportDispatcher.registerTransport(
    udp6.domainName, udp6.Udp6SocketTransport().openServerMode(('::1', 1171))
    )

    transportDispatcher.jobStarted(1)
    print "job started"
    transportDispatcher.runDispatcher()

    transportDispatcher.closeDispatcher()
Esempio n. 14
0
def main():

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

    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(
        '--v2c-arch',
        action='store_true',
        help='Use lightweight, legacy SNMP architecture capable to support '
        'v1/v2c versions of SNMP')

    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('--data-dir',
                        type=str,
                        action='append',
                        metavar='<DIR>',
                        dest='data_dirs',
                        help='SNMP simulation data recordings directory.')

    endpoint_group = parser.add_mutually_exclusive_group(required=True)

    endpoint_group.add_argument(
        '--agent-udpv4-endpoint',
        type=str,
        action='append',
        metavar='<[X.X.X.X]:NNNNN>',
        dest='agent_udpv4_endpoints',
        default=[],
        help='SNMP agent UDP/IPv4 address to listen on (name:port)')

    endpoint_group.add_argument(
        '--agent-udpv6-endpoint',
        type=str,
        action='append',
        metavar='<[X:X:..X]:NNNNN>',
        dest='agent_udpv6_endpoints',
        default=[],
        help='SNMP agent UDP/IPv6 address to listen on ([name]:port)')

    args = parser.parse_args()

    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)

    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)
            parser.print_usage(sys.stderr)
            return 1

        try:
            ReportingManager.configure(*args.reporting_method)

        except SnmpsimError as exc:
            sys.stderr.write('%s\r\n' % exc)
            parser.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)
            parser.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, ))

                contexts[univ.OctetString(community_name)] = mib_instrum

                data_index_instrum_controller.add_data_file(
                    full_path, community_name)

            log.msg.dec_ident()

        del _mib_instrums
        del _data_files

    def get_bulk_handler(req_var_binds, non_repeaters, max_repetitions,
                         read_next_vars):
        """Only v2c arch GETBULK handler"""
        N = min(int(non_repeaters), len(req_var_binds))
        M = int(max_repetitions)
        R = max(len(req_var_binds) - N, 0)

        if R:
            M = min(M, int(args.max_var_binds / R))

        if N:
            rsp_var_binds = read_next_vars(req_var_binds[:N])

        else:
            rsp_var_binds = []

        var_binds = req_var_binds[-R:]

        while M and R:
            rsp_var_binds.extend(read_next_vars(var_binds))
            var_binds = rsp_var_binds[-R:]
            M -= 1

        return rsp_var_binds

    def commandResponderCbFun(transport_dispatcher, transport_domain,
                              transport_address, whole_msg):
        """v2c arch command responder request handling callback"""
        while whole_msg:
            msg_ver = api.decodeMessageVersion(whole_msg)

            if msg_ver in api.protoModules:
                p_mod = api.protoModules[msg_ver]

            else:
                log.error('Unsupported SNMP version %s' % (msg_ver, ))
                return

            req_msg, whole_msg = decoder.decode(whole_msg,
                                                asn1Spec=p_mod.Message())

            community_name = req_msg.getComponentByPosition(1)

            for candidate in datafile.probe_context(
                    transport_domain,
                    transport_address,
                    context_engine_id=datafile.SELF_LABEL,
                    context_name=community_name):
                if candidate in contexts:
                    log.info(
                        'Using %s selected by candidate %s; transport ID %s, '
                        'source address %s, context engine ID <empty>, '
                        'community name '
                        '"%s"' % (contexts[candidate], candidate,
                                  univ.ObjectIdentifier(transport_domain),
                                  transport_address[0], community_name))
                    community_name = candidate
                    break

            else:
                log.error('No data file selected for transport ID %s, source '
                          'address %s, community name '
                          '"%s"' % (univ.ObjectIdentifier(transport_domain),
                                    transport_address[0], community_name))
                return whole_msg

            rsp_msg = p_mod.apiMessage.getResponse(req_msg)
            rsp_pdu = p_mod.apiMessage.getPDU(rsp_msg)
            req_pdu = p_mod.apiMessage.getPDU(req_msg)

            if req_pdu.isSameTypeWith(p_mod.GetRequestPDU()):
                backend_fun = contexts[community_name].readVars

            elif req_pdu.isSameTypeWith(p_mod.SetRequestPDU()):
                backend_fun = contexts[community_name].writeVars

            elif req_pdu.isSameTypeWith(p_mod.GetNextRequestPDU()):
                backend_fun = contexts[community_name].readNextVars

            elif (hasattr(p_mod, 'GetBulkRequestPDU')
                  and req_pdu.isSameTypeWith(p_mod.GetBulkRequestPDU())):

                if not msg_ver:
                    log.info('GETBULK over SNMPv1 from %s:%s' %
                             (transport_domain, transport_address))
                    return whole_msg

                def backend_fun(var_binds):
                    return get_bulk_handler(
                        var_binds, p_mod.apiBulkPDU.getNonRepeaters(req_pdu),
                        p_mod.apiBulkPDU.getMaxRepetitions(req_pdu),
                        contexts[community_name].readNextVars)

            else:
                log.error('Unsupported PDU type %s from '
                          '%s:%s' % (req_pdu.__class__.__name__,
                                     transport_domain, transport_address))
                return whole_msg

            try:
                var_binds = backend_fun(p_mod.apiPDU.getVarBinds(req_pdu))

            except NoDataNotification:
                return whole_msg

            except Exception as exc:
                log.error('Ignoring SNMP engine failure: %s' % exc)
                return whole_msg

            if not msg_ver:

                for idx in range(len(var_binds)):

                    oid, val = var_binds[idx]

                    if val.tagSet in SNMP_2TO1_ERROR_MAP:
                        var_binds = p_mod.apiPDU.getVarBinds(req_pdu)

                        p_mod.apiPDU.setErrorStatus(
                            rsp_pdu, SNMP_2TO1_ERROR_MAP[val.tagSet])
                        p_mod.apiPDU.setErrorIndex(rsp_pdu, idx + 1)

                        break

            p_mod.apiPDU.setVarBinds(rsp_pdu, var_binds)

            transport_dispatcher.sendMessage(encoder.encode(rsp_msg),
                                             transport_domain,
                                             transport_address)

        return whole_msg

    # Configure access to data index

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

    data_index_instrum_controller = controller.DataIndexInstrumController()

    contexts = {univ.OctetString('index'): data_index_instrum_controller}

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

    contexts['index'] = data_index_instrum_controller

    # Configure socket server
    transport_dispatcher = AsyncoreDispatcher()

    transport_index = args.transport_id_offset
    for agent_udpv4_endpoint in args.agent_udpv4_endpoints:
        transport_domain = udp.domainName + (transport_index, )
        transport_index += 1

        agent_udpv4_endpoint = (
            endpoints.IPv4TransportEndpoints().add(agent_udpv4_endpoint))

        transport_dispatcher.registerTransport(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])))

    transport_index = args.transport_id_offset

    for agent_udpv6_endpoint in args.agent_udpv6_endpoints:
        transport_domain = udp6.domainName + (transport_index, )
        transport_index += 1

        agent_udpv6_endpoint = (
            endpoints.IPv4TransportEndpoints().add(agent_udpv6_endpoint))

        transport_dispatcher.registerTransport(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])))

    transport_dispatcher.registerRecvCbFun(commandResponderCbFun)

    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
Esempio n. 15
0
    def action(self, outlet, action, IP=None):
        '''Set parameter for PDU.'''
        if IP == None:
            IP = self.ip
        # Protocol version to use
        pMod = api.protoModules[api.protoVersion1]
        # Build PDU
        reqPDU = pMod.SetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)
        outlet = str(outlet)
        pMod.apiPDU.setVarBinds(reqPDU,
                                ((self.command['outlet_header'] + outlet,
                                  pMod.Integer(self.action_dict[action])), ))

        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        startedAt = time()

        def cbTimerFun(timeNow):
            if timeNow - startedAt > 2:
                raise Exception("Request timed out")

        # noinspection PyUnusedLocal,PyUnusedLocal
        def cbRecvFun(transportDispatcher,
                      transportDomain,
                      transportAddress,
                      wholeMsg,
                      reqPDU=reqPDU):
            while wholeMsg:
                rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                  asn1Spec=pMod.Message())
                rspPDU = pMod.apiMessage.getPDU(rspMsg)
                # Match response to request
                if pMod.apiPDU.getRequestID(
                        reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                    # Check for SNMP errors reported
                    errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
                    if errorStatus:
                        print(errorStatus.prettyPrint())
                    else:
                        for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                            print '-----OK-----'
                            #print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
            transportDispatcher.jobFinished(1)
            return wholeMsg

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(cbRecvFun)
        transportDispatcher.registerTimerCbFun(cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())

        # Pass message to dispatcher
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (IP, 161))
        transportDispatcher.jobStarted(1)
        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
Esempio n. 16
0
            key='.'.join([str(i) for i in v._value])
            value=b.getComponent('simple')._value

            parsed=ObjectType(ObjectIdentity(key), value)
            try: parsed.resolveWithMib(viewController)
            except Exception as e: 
                logger.warning("TRAP\tERROR | Failed to resolve symbol ({}={})".format(key,value))
                continue
            key,value=parsed.prettyPrint().split(" = ")
            logger.info("TRAP\t{} | {}".format(key,value))

            if key=="PowerNet-MIB::mtrapargsString.0":
                message=value
                for contact in contacts['contacts']:
                    phoneNumber=contact['phoneNumber']
                    _redis.publish('sms', json.dumps(dict(phoneNumber=phoneNumber, message=message)))

    return msg

dispatcher=AsyncoreDispatcher()
dispatcher.registerRecvCbFun(snmpRecvCallback)
dispatcher.registerTransport(
    udp.domainName, udp.UdpSocketTransport().openServerMode((TRAP_IP_ADDRESS, TRAP_PORT))
)
dispatcher.jobStarted(1)
print("Starting...")
try: dispatcher.runDispatcher()
except:
    dispatcher.closeDispatcher()
    raise
def snmpgetint(self, host, check):
    global checkname
    global hostname
    global res
    try:
        print('doing ' + check + ' on ' + host)
        hostname = Hosts.objects.get(name=host)
        if hostname.enabled is True:
            checkname = HostChecks.objects.get(name=check)
            address = hostname.address
            community = hostname.community
            oid = checkname.arg
            # res = str(float(snmp_get(oid, hostname=address, community=community, version=1).value) * float(check.quotient))
            # from pysnmp import debug
            # debug.setLogger(debug.Debug('msgproc'))

            # Protocol version to use
            pMod = api.protoModules[api.protoVersion1]
            # pMod = api.protoModules[api.protoVersion2c]

            # Build PDU
            reqPDU = pMod.GetRequestPDU()
            pMod.apiPDU.setDefaults(reqPDU)
            pMod.apiPDU.setVarBinds(reqPDU, (((oid), pMod.Null()), ))

            # Build message
            reqMsg = pMod.Message()
            pMod.apiMessage.setDefaults(reqMsg)
            pMod.apiMessage.setCommunity(reqMsg, community)
            pMod.apiMessage.setPDU(reqMsg, reqPDU)

            startedAt = time()

            def cbTimerFun(timeNow):
                if timeNow - startedAt > 3:
                    raise Exception("Request timed out")

            # noinspection PyUnusedLocal,PyUnusedLocal
            def cbRecvFun(transportDispatcher,
                          transportDomain,
                          transportAddress,
                          wholeMsg,
                          reqPDU=reqPDU):
                while wholeMsg:
                    rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                      asn1Spec=pMod.Message())
                    rspPDU = pMod.apiMessage.getPDU(rspMsg)
                    # Match response to request
                    if pMod.apiPDU.getRequestID(
                            reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                        # Check for SNMP errors reported
                        errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
                        if errorStatus:
                            print(errorStatus.prettyPrint())
                        else:
                            for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                                # print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
                                # res = str(float(val.prettyPrint() * float(check.quotient)))
                                global checkname
                                global hostname
                                global res
                                res = str(
                                    float(val * float(checkname.quotient)))
                                computeint(checkname, hostname, res)
                        transportDispatcher.jobFinished(1)
                return wholeMsg

            transportDispatcher = AsyncoreDispatcher()

            transportDispatcher.registerRecvCbFun(cbRecvFun)
            # transportDispatcher.registerTimerCbFun(cbTimerFun)

            # UDP/IPv4
            transportDispatcher.registerTransport(
                udp.domainName,
                udp.UdpSocketTransport().openClientMode())

            # Pass message to dispatcher
            transportDispatcher.sendMessage(encoder.encode(reqMsg),
                                            udp.domainName, (address, 161))
            transportDispatcher.jobStarted(1)

            ## UDP/IPv6 (second copy of the same PDU will be sent)
            # transportDispatcher.registerTransport(
            #    udp6.domainName, udp6.Udp6SocketTransport().openClientMode()
            # )

            # Pass message to dispatcher
            # transportDispatcher.sendMessage(
            #    encoder.encode(reqMsg), udp6.domainName, ('::1', 161)
            # )
            # transportDispatcher.jobStarted(1)

            ## Local domain socket
            # transportDispatcher.registerTransport(
            #    unix.domainName, unix.UnixSocketTransport().openClientMode()
            # )
            #
            # Pass message to dispatcher
            # transportDispatcher.sendMessage(
            #    encoder.encode(reqMsg), unix.domainName, '/tmp/snmp-agent'
            # )
            # transportDispatcher.jobStarted(1)

            # Dispatcher will finish as job#1 counter reaches zero
            transportDispatcher.runDispatcher()

            transportDispatcher.closeDispatcher()
            # print(transportDispatcher)
            del transportDispatcher
            del pMod
            del reqPDU
            del reqMsg
            del startedAt
            del cbTimerFun
            del cbRecvFun

            # computeint(check, host, res)
            # print(oid + ' on ' + address + ' equals ' + res)
    except Exception as e:
        print('doing ' + checkname.name + ' on ' + hostname.name + ' failed')
        print(traceback.format_exc())
        # update the error count
        setMetadata(hostname.name + ':' + checkname.name + '::lasterror',
                    str(timezone.now()))
        setMetadata(
            hostname.name + ':' + checkname.name + '::nberror',
            int(
                getMetadata(hostname.name + ':' + checkname.name + '::nberror',
                            0)) + 1)
        # Log the error to the database.
        ErrorLog(hostcheck=checkname,
                 host=hostname,
                 event=e.__class__.__name__,
                 error=str(e),
                 value=res).save()
    return res
Esempio n. 18
0
def SnmpwalkAsync(target_IP=None,
                  oid=None,
                  community='public',
                  walk_timeout=10,
                  mode='ipv4'):
    """Script to run in the remote device for snmp mib walk.

       This script can be copied to the remote device eg:wan
       and can be executed directly using python for snmp mib walk
       The walk can done for both ipv6 and ipv4

    :param target_IP: device IP for mib query
    :type target_IP: string
    :param oid: mib query OID
    :type oid: string
    :param community: community string for mib query, defaults to public
    :type community: string, optional
    :param walk_timeout: snmp walk timeout, defaults to 10
    :type walk_timeout: integer, optional
    :param mode: mib query mode, defaults to ipv4
    :type mode: string, optional
    :return: mib query output
    :rtype: string
    """
    # SNMP table header
    headVars = [v2c.ObjectIdentifier((oid))]

    # Build PDU
    reqPDU = v2c.GetBulkRequestPDU()
    v2c.apiBulkPDU.setDefaults(reqPDU)
    v2c.apiBulkPDU.setNonRepeaters(reqPDU, 0)
    v2c.apiBulkPDU.setMaxRepetitions(reqPDU, 25)
    v2c.apiBulkPDU.setVarBinds(reqPDU, [(x, v2c.null) for x in headVars])

    # Build message
    reqMsg = v2c.Message()
    v2c.apiMessage.setDefaults(reqMsg)
    v2c.apiMessage.setCommunity(reqMsg, community)
    v2c.apiMessage.setPDU(reqMsg, reqPDU)

    startedAt = time.time()
    output_list = []

    def cbTimerFun(timeNow):
        # Duration
        if timeNow - startedAt > walk_timeout:
            if walk_timeout != 0:
                raise Exception("Request timed out")
            else:
                if timeNow - startedAt > 30:
                    transportDispatcher.jobFinished(1)

    # noinspection PyUnusedLocal
    def cbRecvFun(transportDispatcher,
                  transportDomain,
                  transportAddress,
                  wholeMsg,
                  reqPDU=reqPDU,
                  headVars=headVars):
        while wholeMsg:
            rspMsg, wholeMsg = decoder.decode(wholeMsg, asn1Spec=v2c.Message())
            rspPDU = v2c.apiMessage.getPDU(rspMsg)

            # Match response to request
            if v2c.apiBulkPDU.getRequestID(
                    reqPDU) == v2c.apiBulkPDU.getRequestID(rspPDU):
                # Format var-binds table
                varBindTable = v2c.apiBulkPDU.getVarBindTable(reqPDU, rspPDU)

                # Check for SNMP errors reported
                errorStatus = v2c.apiBulkPDU.getErrorStatus(rspPDU)
                if errorStatus and errorStatus != 2:
                    errorIndex = v2c.apiBulkPDU.getErrorIndex(rspPDU)
                    print('%s at %s' %
                          (errorStatus.prettyPrint(), errorIndex
                           and varBindTable[int(errorIndex) - 1] or '?'))
                    transportDispatcher.jobFinished(1)
                    break

                # Report SNMP table
                for tableRow in varBindTable:
                    for name, val in tableRow:
                        # print mib data
                        print('from: %s, %s = %s' %
                              (transportAddress, name.prettyPrint(),
                               val.prettyPrint()))
                        output_list.append(
                            'from: %s, %s = %s\n' %
                            (transportAddress, name.prettyPrint(),
                             val.prettyPrint()))

                # Stop on EOM
                for oid, val in varBindTable[-1]:
                    if not isinstance(val, v2c.Null):
                        break
                    else:
                        transportDispatcher.jobFinished(1)

                # Generate request for next row
                v2c.apiBulkPDU.setVarBinds(reqPDU,
                                           [(x, v2c.null)
                                            for x, y in varBindTable[-1]])
                v2c.apiBulkPDU.setRequestID(reqPDU, v2c.getNextRequestID())
                transportDispatcher.sendMessage(encoder.encode(reqMsg),
                                                transportDomain,
                                                transportAddress)
        return wholeMsg

    transportDispatcher = AsyncoreDispatcher()
    transportDispatcher.registerRecvCbFun(cbRecvFun)
    transportDispatcher.registerTimerCbFun(cbTimerFun)
    if mode == 'ipv4':
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (target_IP, 161))
    else:
        transportDispatcher.registerTransport(
            udp6.domainName,
            udp6.Udp6SocketTransport().openClientMode())
        transportDispatcher.sendMessage(encoder.encode(reqMsg),
                                        udp6.domainName, (target_IP, 161))
    transportDispatcher.jobStarted(1)
    # Dispatcher will finish as job#1 counter reaches zero
    transportDispatcher.runDispatcher()
    transportDispatcher.closeDispatcher()

    if output_list != []:
        return output_list
    else:
        return
Esempio n. 19
0
    def GETcurrent(self, IP=None):
        if IP == None:
            IP = self.ip
        pMod = api.protoModules[api.protoVersion1]

        # Build PDU
        reqPDU = pMod.GetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)
        pMod.apiPDU.setVarBinds(reqPDU,
                                ((self.command['current'], pMod.Null('')), ))

        # Build message
        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        startedAt = time()

        def cbTimerFun(timeNow):
            if timeNow - startedAt > 3:
                raise Exception("Request timed out")

        # noinspection PyUnusedLocal,PyUnusedLocal
        def cbRecvFun(transportDispatcher,
                      transportDomain,
                      transportAddress,
                      wholeMsg,
                      reqPDU=reqPDU):
            while wholeMsg:
                rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                  asn1Spec=pMod.Message())
                rspPDU = pMod.apiMessage.getPDU(rspMsg)
                # Match response to request
                if pMod.apiPDU.getRequestID(
                        reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                    # Check for SNMP errors reported
                    errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
                    if errorStatus:
                        print(errorStatus.prettyPrint())
                    else:
                        for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                            oid_str = oid.prettyPrint()
                            if oid_str == '1.3.6.1.4.1.318.1.1.12.2.3.1.1.2.1':
                                print('%s' % (val.prettyPrint()))
                    transportDispatcher.jobFinished(1)
            return wholeMsg

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(cbRecvFun)
        transportDispatcher.registerTimerCbFun(cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())

        # Pass message to dispatcher
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (IP, 161))
        transportDispatcher.jobStarted(1)

        transportDispatcher.runDispatcher()

        transportDispatcher.closeDispatcher()
Esempio n. 20
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
Esempio n. 21
0
class TrapEngine:
    """
    This trap engine core class implements all the required behaviour for SNMP traps.

    Constructor Positional Arguments:
    - snmp_host -- destination IP address for SNMP traps
    - snmp_port -- destination UDP port address for SNMP traps
    - snmp_config -- SNMP configuration details for accessing device
    """
    def __init__(self, snmp_host, snmp_host_port, session_parameters):
        self.snmp_host = snmp_host
        self.snmp_host_port = snmp_host_port
        self.session_parameters = session_parameters

        self.udp_domain_name = udp.domainName
        self.udp_socket_transport = udp.UdpSocketTransport
        self.trap_model_parameters = dict()

    def _receive_and_save(self, transportDispatcher, transportDomain,
                          transportAddress, wholeMsg):

        while wholeMsg:

            msgVer = int(api.decodeMessageVersion(wholeMsg))
            if msgVer in api.protoModules:
                pMod = api.protoModules[msgVer]

            else:
                logging.warning('Unsupported SNMP version %s' % msgVer)
                return

            reqMsg, wholeMsg = decoder.decode(
                wholeMsg,
                asn1Spec=pMod.Message(),
            )

            logging.warning('########## RECEIVED NEW TRAP ########## ')
            logging.warning(
                f'Notification message from {transportDomain}:{transportAddress}'
            )

            reqPDU = pMod.apiMessage.getPDU(reqMsg)

            if reqPDU.isSameTypeWith(pMod.TrapPDU()):
                trap_date = datetime.now()
                trap_date = trap_date.replace(hour=datetime.now().hour + 1)
                trap_date = trap_date.strftime("%m/%d/%Y, %H:%M:%S")

                trap_domain = transportDomain
                trap_address = transportAddress[0]
                trap_port = transportAddress[1]

                logging.warning(f'Datetime: {trap_date}')
                logging.warning(f'Trap Domain: {trap_domain}')
                logging.warning(f'Agent Address: {trap_address}:{trap_port}')

                full_system_name = self._get_system_name(trap_address)
                device_model = DeviceModel.objects.get(
                    full_system_name=full_system_name)

                self.trap_model_parameters = dict(device_model=device_model,
                                                  trap_domain=trap_domain,
                                                  trap_address=trap_address,
                                                  trap_port=trap_port,
                                                  trap_date=trap_date)
                varBinds = pMod.apiTrapPDU.getVarBinds(reqPDU)

                if not self._database_validator():
                    trap_model = DeviceTrapModel(**self.trap_model_parameters)
                    trap_model.save()

                    for trap_oid, trap_data in varBinds:
                        var_bids_parameters = {
                            'trap_model': trap_model,
                            'trap_oid': trap_oid,
                            'trap_data': trap_data
                        }

                        var_bids_model = VarBindModel(**var_bids_parameters)
                        var_bids_model.save()

            else:
                varBinds = pMod.apiPDU.getVarBinds(reqPDU)

            logging.warning('Var-binds:')
            for oid, val in varBinds:
                logging.warning('%s = %s' % (oid, val))

        return wholeMsg

    def _database_validator(self):
        return DeviceTrapModel.objects.filter(
            device_model=self.trap_model_parameters['device_model'],
            trap_domain=self.trap_model_parameters['trap_domain'],
            trap_address=self.trap_model_parameters['trap_address'],
            trap_port=self.trap_model_parameters['trap_port'],
            trap_date=self.trap_model_parameters['trap_date']).exists()

    def _get_system_name(self, trap_address):

        self.session_parameters['hostname'] = trap_address

        session = Session(**self.session_parameters)
        full_system_name = session.walk('sysName')[0].value

        return full_system_name

    def _initialize_engine(self):
        self.transport_dispatcher = AsyncoreDispatcher()
        self.transport_dispatcher.registerRecvCbFun(self._receive_and_save)
        self.transport_dispatcher.registerTransport(
            self.udp_domain_name,
            self.udp_socket_transport().openServerMode(
                (self.snmp_host, self.snmp_host_port)))

        self.transport_dispatcher.jobStarted(1)

    def run_engine(self):
        self._initialize_engine()
        self.transport_dispatcher.runDispatcher()

    def close_engine(self):
        self.transport_dispatcher.closeDispatcher()
Esempio n. 22
0
            # Check for SNMP errors reported
            errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
            if errorStatus:
                print(errorStatus.prettyPrint())
            else:
                for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                    print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
            transportDispatcher.jobFinished(1)
    return wholeMsg


transportDispatcher = AsyncoreDispatcher()

transportDispatcher.registerRecvCbFun(cbRecvFun)
transportDispatcher.registerTimerCbFun(cbTimerFun)

# UDP/IPv4
transportDispatcher.registerTransport(
    udp.domainName,
    udp.UdpSocketTransport().openClientMode())

# Pass message to dispatcher
transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                ('192.168.1.88', 161))
transportDispatcher.jobStarted(1)

# Dispatcher will finish as job#1 counter reaches zero
transportDispatcher.runDispatcher()

transportDispatcher.closeDispatcher()
Esempio n. 23
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
Esempio n. 24
0
                    "TRAP\tERROR | Failed to resolve symbol ({}={})".format(
                        key, value))
                continue
            key, value = parsed.prettyPrint().split(" = ")
            logger.info("TRAP\t{} | {}".format(key, value))

            if key == "PowerNet-MIB::mtrapargsString.0":
                message = value
                for contact in contacts['contacts']:
                    phoneNumber = contact['phoneNumber']
                    _redis.publish(
                        'sms',
                        json.dumps(
                            dict(phoneNumber=phoneNumber, message=message)))

    return msg


dispatcher = AsyncoreDispatcher()
dispatcher.registerRecvCbFun(snmpRecvCallback)
dispatcher.registerTransport(
    udp.domainName,
    udp.UdpSocketTransport().openServerMode((TRAP_IP_ADDRESS, TRAP_PORT)))
dispatcher.jobStarted(1)
print("Starting...")
try:
    dispatcher.runDispatcher()
except:
    dispatcher.closeDispatcher()
    raise
Esempio n. 25
0
                    print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))

            transportDispatcher.jobFinished(1)

    return wholeMsg


transportDispatcher = AsyncoreDispatcher()

transportDispatcher.registerRecvCbFun(cbRecvFun)
transportDispatcher.registerTimerCbFun(cbTimerFun)

# UDP/IPv4
udpSocketTransport = udp.UdpSocketTransport().openClientMode().enableBroadcast(
)
transportDispatcher.registerTransport(udp.DOMAIN_NAME, udpSocketTransport)

# Pass message to dispatcher
transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.DOMAIN_NAME,
                                ('255.255.255.255', 161))

# wait for a maximum of 10 responses or time out
transportDispatcher.jobStarted(1, maxNumberResponses)

# Dispatcher will finish as all jobs counter reaches zero
try:
    transportDispatcher.runDispatcher()

finally:
    transportDispatcher.closeDispatcher()
Esempio n. 26
0
    def _write(self, keys, values, IP=None):
        '''Write keys and values to PDU.
        keys and values are lists of the same length. Example:
        keys = ['1.3.6.1.4.1.318.1.1.4.5.2.1.3.1',]
        values = [1,]
        '''
        if len(keys) != len(values):
            print 'Error: the keys and values are not matched.'
            exit()
        if IP == None:
            IP = self.ip

        # Protocol version to use
        pMod = api.protoModules[api.protoVersion1]
        # Build PDU
        reqPDU = pMod.SetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)
        pMod.apiPDU.setVarBinds(reqPDU, zip(keys, map(pMod.Integer, values)))
        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        startedAt = time()

        def cbTimerFun(timeNow):
            if timeNow - startedAt > 3:
                raise Exception('Request timed out')

        def cbRecvFun(transportDispatcher,
                      transportDomain,
                      transportAddress,
                      wholeMsg,
                      reqPDU=reqPDU):
            while wholeMsg:
                rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                  asn1Spec=pMod.Message())
                rspPDU = pMod.apiMessage.getPDU(rspMsg)
                # Match response to request
                if pMod.apiPDU.getRequestID(
                        reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                    # Check for SNMP errors reported
                    errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
                    if errorStatus:
                        print(errorStatus.prettyPrint())
                    else:
                        for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                            #print '-----OK-----'
                            pass

                    transportDispatcher.jobFinished(1)
            return wholeMsg

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(cbRecvFun)
        transportDispatcher.registerTimerCbFun(cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())

        # Pass message to dispatcher
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (IP, 161))
        transportDispatcher.jobStarted(1)
        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
Esempio n. 27
0
    def _read(self, keys, IP=None):
        '''read results for keys.
        keys is a list.
        '''
        if IP == None:
            IP = self.ip
        values = []

        pMod = api.protoModules[api.protoVersion1]
        # pMod = api.protoModules[api.protoVersion2c]
        # Build PDU
        reqPDU = pMod.GetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)
        ###

        pMod.apiPDU.setVarBinds(reqPDU, zip(keys, [pMod.Null('')] * len(keys)))

        # Build message
        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        startedAt = time()

        def cbTimerFun(timeNow):
            if timeNow - startedAt > 3:
                raise Exception('Request timed out')

        def cbRecvFun(transportDispatcher,
                      transportDomain,
                      transportAddress,
                      wholeMsg,
                      reqPDU=reqPDU):
            while wholeMsg:
                rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                  asn1Spec=pMod.Message())
                rspPDU = pMod.apiMessage.getPDU(rspMsg)
                # Match response to request

                if pMod.apiPDU.getRequestID(
                        reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                    # Check for SNMP errors reported
                    errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)
                    if errorStatus:
                        print(errorStatus.prettyPrint())
                    else:
                        for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                            values.append(val.prettyPrint())

                    transportDispatcher.jobFinished(1)
            return wholeMsg

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(cbRecvFun)
        transportDispatcher.registerTimerCbFun(cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())
        # Pass message to dispatcher
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (IP, 161))
        transportDispatcher.jobStarted(1)
        transportDispatcher.runDispatcher()
        transportDispatcher.closeDispatcher()
        return values
Esempio n. 28
0
                    print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))

            transportDispatcher.jobFinished(1)

    return wholeMsg


transportDispatcher = AsyncoreDispatcher()

transportDispatcher.registerRecvCbFun(cbRecvFun)
transportDispatcher.registerTimerCbFun(cbTimerFun)

# UDP/IPv4
udpSocketTransport = udp.UdpSocketTransport().openClientMode().enableBroadcast()
transportDispatcher.registerTransport(udp.DOMAIN_NAME, udpSocketTransport)

# Pass message to dispatcher
transportDispatcher.sendMessage(
    encoder.encode(reqMsg), udp.DOMAIN_NAME, ('255.255.255.255', 161)
)

# wait for a maximum of 10 responses or time out
transportDispatcher.jobStarted(1, maxNumberResponses)

# Dispatcher will finish as all jobs counter reaches zero
try:
    transportDispatcher.runDispatcher()

finally:
    transportDispatcher.closeDispatcher()
Esempio n. 29
0
 def __init__(self, usage=False):
     # abort if pysnmp is not installed
     if not snmp_modules_found:
         output().warning_(
             "Please install the 'pysnmp' module for SNMP support.")
         if usage: print("")
         return
     # skip when running 'discover' in interactive mode
     if usage: print("No target given, discovering local printers")
     oid = (
         ('1.3.6.1.2.1.25.3.2.1.2.1',
          None),  # HOST-RESOURCES-MIB → hrDeviceType
         ('1.3.6.1.2.1.25.3.2.1.3.1',
          None),  # HOST-RESOURCES-MIB → hrDeviceDescr
         ('1.3.6.1.2.1.25.3.2.1.5.1',
          None),  # HOST-RESOURCES-MIB → hrDeviceStatus
         ('1.3.6.1.2.1.43.16.5.1.2.1.1',
          None),  # Printer-MIB        → Printer status
         ('1.3.6.1.2.1.1.3.0', None))  # SNMPv2-MIBv        → sysUpTime
     try:
         # build protocol data unit (pdu)
         pmod.apiPDU.setDefaults(pdu_send)
         pmod.apiPDU.setVarBinds(pdu_send, oid)
         # build message
         msg_send = pmod.Message()
         pmod.apiMessage.setDefaults(msg_send)
         pmod.apiMessage.setCommunity(msg_send, 'public')
         pmod.apiMessage.setPDU(msg_send, pdu_send)
         # ...
         dispatcher = AsyncoreDispatcher()
         dispatcher.registerRecvCbFun(recv)
         dispatcher.registerTimerCbFun(timer)
         # use ipv4 udp broadcast
         udpSocketTransport = udp.UdpSocketTransport().openClientMode(
         ).enableBroadcast()
         dispatcher.registerTransport(udp.domainName, udpSocketTransport)
         # pass message to dispatcher
         target = ('255.255.255.255', 161)
         dispatcher.sendMessage(encoder.encode(msg_send), udp.domainName,
                                target)
         # wait for timeout or max hosts
         dispatcher.jobStarted(1, maxhost)
         # dispatcher will finish as all jobs counter reaches zero
         try:
             dispatcher.runDispatcher()
         except stop_waiting:
             dispatcher.closeDispatcher()
         # list found network printers
         if results:
             print("")
             output().discover_(
                 ('address', ('device', 'uptime', 'status', None)))
             output().hline_(79)
             for printer in sorted(
                     results.items(),
                     key=lambda item: socket.inet_aton(item[0])):
                 output().discover_(printer)
         else:
             output().info_("No printers found via SNMP broadcast")
         if usage or results: print("")
     except Exception as e:
         output().errmsg_("SNMP Error", e)
         if usage: print("")
Esempio n. 30
0
    # SNMPv3/USM setup

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

    # Allow full MIB access for this user / securityModels at VACM
    config.addVacmUser(snmpEngine, 3, 'usr-md5-des', 'authPriv', (1, 3, 6), (1, 3, 6, 1, 2, 1))

    # Get default SNMP context this SNMP engine serves
    snmpContext = context.SnmpContext(snmpEngine)

    # Register SNMP Applications at the SNMP engine for particular SNMP context
    cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
    cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
    cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
    cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

# Register an imaginary never-ending job to keep I/O dispatcher running forever
transportDispatcher.jobStarted(1)

# Run I/O dispatcher which would receive queries and send responses
try:
    transportDispatcher.runDispatcher()
except:
    transportDispatcher.closeDispatcher()
    raise
Esempio n. 31
0
    def GEToutlet(self, outlet=None, IP=None):
        if IP == None:
            IP = self.ip
        pMod = api.protoModules[api.protoVersion1]
        # pMod = api.protoModules[api.protoVersion2c]
        # Build PDU
        reqPDU = pMod.GetRequestPDU()
        pMod.apiPDU.setDefaults(reqPDU)
        pMod.apiPDU.setVarBinds(reqPDU, (
            (self.command['name'], pMod.Null('')),
            (self.command['port'], pMod.Null('')),
            (self.command['name_1'], pMod.Null('')),
            (self.command['name_2'], pMod.Null('')),
            (self.command['name_3'], pMod.Null('')),
            (self.command['name_4'], pMod.Null('')),
            (self.command['name_5'], pMod.Null('')),
            (self.command['name_6'], pMod.Null('')),
            (self.command['name_7'], pMod.Null('')),
            (self.command['name_8'], pMod.Null('')),
        ))

        # Build message
        reqMsg = pMod.Message()
        pMod.apiMessage.setDefaults(reqMsg)
        pMod.apiMessage.setCommunity(reqMsg, self.community)
        pMod.apiMessage.setPDU(reqMsg, reqPDU)

        startedAt = time()

        def cbTimerFun(timeNow):
            if timeNow - startedAt > 3:
                raise Exception("Request timed out")

        # noinspection PyUnusedLocal,PyUnusedLocal
        def cbRecvFun(transportDispatcher=None,
                      transportDomain=None,
                      transportAddress=None,
                      wholeMsg=None,
                      reqPDU=reqPDU):
            while wholeMsg:

                rspMsg, wholeMsg = decoder.decode(wholeMsg,
                                                  asn1Spec=pMod.Message())
                rspPDU = pMod.apiMessage.getPDU(rspMsg)
                # Match response to request
                if pMod.apiPDU.getRequestID(
                        reqPDU) == pMod.apiPDU.getRequestID(rspPDU):
                    # Check for SNMP errors reported
                    errorStatus = pMod.apiPDU.getErrorStatus(rspPDU)

                    if errorStatus:
                        print(errorStatus.prettyPrint())
                    else:
                        for oid, val in pMod.apiPDU.getVarBinds(rspPDU):
                            oid_str = oid.prettyPrint()

                            if oid_str == '1.3.6.1.4.1.318.1.1.4.2.2.0':
                                self.result_str = val.prettyPrint()

                            elif oid_str == self.command['name_1']:
                                self.nothing = []
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_2']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_3']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_4']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_5']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_6']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_7']:
                                self.nothing.append(val.prettyPrint())
                            elif oid_str == self.command['name_8']:
                                self.nothing.append(val.prettyPrint())

                transportDispatcher.jobFinished(1)
            return wholeMsg

        transportDispatcher = AsyncoreDispatcher()
        transportDispatcher.registerRecvCbFun(cbRecvFun)
        transportDispatcher.registerTimerCbFun(cbTimerFun)

        # UDP/IPv4
        transportDispatcher.registerTransport(
            udp.domainName,
            udp.UdpSocketTransport().openClientMode())

        # Pass message to dispatcher
        transportDispatcher.sendMessage(encoder.encode(reqMsg), udp.domainName,
                                        (IP, 161))
        transportDispatcher.jobStarted(1)

        # Dispatcher will finish as job#1 counter reaches zero
        transportDispatcher.runDispatcher()
        self.nothing = self.nothing + [
            '...',
            '...',
            '...',
            '...',
            '...',
            '...',
            '...',
            '...',
        ]
        #print self.nothing
        result_str = self.result_str.split()
        for i, element in enumerate(result_str):
            result_str[i] = '%d--%s--%s' % (i + 1, self.nothing[i],
                                            result_str[i])
        if outlet == None:
            for i in range(len(result_str)):
                print result_str[i]
        else:
            try:
                for j in outlet:
                    print result_str[int(j) - 1]
            except:
                print 'One outlet dosen\'t exist. Please check your input.'
        transportDispatcher.closeDispatcher()