Esempio n. 1
0
def checkSNMP(community, host, port, oid):
    mibBuilder = builder.MibBuilder()
    mibViewController = view.MibViewController(mibBuilder)
    compiler.addMibCompiler(mibBuilder,
                            sources=['http://mibs.snmplabs.com/asn1/@mib@'])
    mibBuilder.loadModules('RFC1213-MIB', 'IF-MIB')
    objectIdentity = rfc1902.ObjectIdentity(oid).resolveWithMib(
        mibViewController)

    errorIndication, errorStatus, errorIndex, varBinds = next(
        getCmd(SnmpEngine(), CommunityData(community),
               UdpTransportTarget((host, port), timeout=1.5, retries=0),
               ContextData(), ObjectType(objectIdentity)))

    if errorIndication:
        print(errorIndication, " : ", host)
    elif errorStatus:
        print('%s at %s' %
              (errorStatus.prettyPrint(),
               errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
    else:
        for varBind in varBinds:
            varB = (' = '.join([x.prettyPrint() for x in varBind]))
            resultado = " ".join(varB.split()[2:])
            return resultado
    return -1
Esempio n. 2
0
    def __init__(self, args):
        configDict = loadConfig(args.config)

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

        self.moduleLogger.debug('configDict:{}'.format(configDict))

        mibBuilder = builder.MibBuilder()
        self._mibViewController = view.MibViewController(mibBuilder)

        compiler.addMibCompiler(
            mibBuilder, sources=configDict['snmp'].get('mibs', ()))

        # this dict holds all OID items indexed by MIB symbols
        self._mibObjects = collections.defaultdict(dict)

        # this dict holds only recently updated OIDs (indexed by
        # MIB name and object)
        self._candidateMibObjects = collections.defaultdict(dict)

        # this dict holds all OID items populated from `mibObjects`
        self._oids = {}

        self._expireBy = time.time() + self.EXPIRE_PERIOD

        self._dirty = True  # OIDs need sorting
Esempio n. 3
0
def generator(cbCtx, ast):
    snmpEngine, ctx = cbCtx

    if 'mibViewProxy' not in ctx:
        ctx['mibViewProxy'] = MibViewProxy(ctx['mibViewController'])

    #    compiler.addMibCompiler(snmpEngine.getMibBuilder())

    snmpEngine, ctx = _MibViewGenerator().preorder((snmpEngine, ctx), ast)

    if 'MibDir' not in ctx:
        ctx['MibDir'] = [DEFAULT_MIB_SOURCE_URL]

    if 'MibBorrowers' not in ctx:
        ctx['MibBorrowers'] = [DEFAULT_MIB_BORROWER_URL]

    compiler.addMibCompiler(snmpEngine.getMibBuilder(),
                            sources=ctx['MibDir'],
                            borrowers=ctx['MibBorrowers'])

    if 'MibFiles' in ctx:
        mibBuilder = snmpEngine.getMibBuilder()

        for mibFile in ctx['MibFiles']:
            if mibFile.lower() == 'all':
                mibBuilder.loadModules()

            else:
                mibBuilder.loadModules(mibFile)

    return snmpEngine, ctx
Esempio n. 4
0
def consultaSNMP(comunidad,host,oid):
		mibBuilder = builder.MibBuilder()
		mibViewController = view.MibViewController(mibBuilder)
		compiler.addMibCompiler(mibBuilder, sources=['file:///usr/local/lib/python2.7/dist-packages/pysnmp/smi/mibs',
																						 'http://mibs.snmplabs.com/asn1/@mib@'])
		mibBuilder.loadModules('RFC1213-MIB','IF-MIB')
		objectIdentity = rfc1902.ObjectIdentity(oid).resolveWithMib(mibViewController)

		errorIndication, errorStatus, errorIndex, varBinds = next(
				getCmd(SnmpEngine(),
							 CommunityData(comunidad),
							 UdpTransportTarget((host, 161)),
							 ContextData(),
							 #ObjectType(ObjectIdentity(oid))))
							 ObjectType( objectIdentity )))

		if errorIndication:
				print(errorIndication)
		elif errorStatus:
				print('%s at %s' % (errorStatus.prettyPrint(),errorIndex and varBinds[int(errorIndex) - 1][0] or '?'))
		else:

				for varBind in varBinds:
						varB=(' = '.join([x.prettyPrint() for x in varBind]))
						resultado= " ".join(varB.split()[2:])
		return resultado
Esempio n. 5
0
def listen(
    address=DEFAULT_ADDRESSS,
    port=DEFAULT_PORT,
    community=DEFAULT_COMMUNITY,
    mibs=DEFAULT_MIBS,
):
    """Listen to and SNMP trap and print events."""
    # Based on pySNMP example code.
    mib_builder = builder.MibBuilder()
    compiler.addMibCompiler(mib_builder)
    mib_builder.loadModules(*mibs)
    global _view_controller
    _view_controller = view.MibViewController(mib_builder)
    loop = asyncio.get_event_loop()
    snmp_engine = engine.SnmpEngine()
    print(f"Agent is listening SNMP Trap on {address}, Port: {port}")
    if port < 1024:
        print(
            "WARNING: Port < 1024. Root priviledges or authbind required on *nix systems."
        )
    print("-" * 79)
    config.addTransport(
        snmp_engine,
        udp.domainName + (1, ),
        udp.UdpTransport().openServerMode((address, port)),
    )
    config.addV1System(snmp_engine, community, community)
    ntfrcv.NotificationReceiver(snmp_engine, _listen_callback)
    print("Press CTRL-C to quit.")
    loop.run_forever()
Esempio n. 6
0
def translate_mib(custom_mib_paths, load_mib_modules, name, val):
    """
    Translate OID to MIB
    custom_mib_paths: comma separated mib paths as a string
    load_mib_modules: MIB Module to load e.g. "MIB-FILE-1,MIB-FILE-2"
    Return: Translated OID string and value
    """
    if custom_mib_paths and load_mib_modules:
        try:
            mibBuilder = builder.MibBuilder()
            compiler.addMibCompiler(mibBuilder, sources=custom_mib_paths)
            mibViewController = view.MibViewController(mibBuilder)
            temp_load_mib_modules = load_mib_modules.split(',')
            mibBuilder.loadModules(*temp_load_mib_modules)
        except error.MibNotFoundError as excep:
            testcase_Utils.pNote(" {} Mib Not Found!".format(excep), "Error")
    temp_type = val.__class__.__name__
    if custom_mib_paths and load_mib_modules:
        output = rfc1902.ObjectType(rfc1902.ObjectIdentity(name),
                                    val).resolveWithMib(mibViewController).prettyPrint()
        op_list = output.split(" = ")
        name = op_list[0].strip()
        t_val = op_list[1].strip()
        if temp_type == "Integer":
            testcase_Utils.pNote('%s = %s(%s): %s' %
                                 (name, temp_type, val.prettyPrint(), t_val))
        else:
            if t_val == '': #For empty String
                testcase_Utils.pNote('%s = %s: ""' % (name, temp_type))
            else:
                testcase_Utils.pNote('%s = %s: %s' % (name, temp_type, t_val))
        return name, t_val
    else:
        testcase_Utils.pNote('%s = %s: %s' % (name.prettyPrint(), temp_type, val.prettyPrint()))
        return name.prettyPrint(), val.prettyPrint()
Esempio n. 7
0
    def __init__(self, **kwargs):
        self.standard_mibs = []
        self.mongo_client = pymongo.MongoClient(MONGO_URI)

        if kwargs.get("no_mongo"):
            self.session = Session()
        else:
            self.session = CachedLimiterSession(
                per_second=120,
                cache_name="cache_http",
                backend=MongoCache(connection=self.mongo_client,
                                   db_name=MONGO_DB),
                expire_after=1800,
                match_headers=False,
                stale_if_error=True,
                allowable_codes=[200],
            )

        self.profiles = load_profiles()
        self.last_modified = time.time()
        self.snmpEngine = SnmpEngine()
        self.builder = self.snmpEngine.getMibBuilder()
        self.mib_view_controller = view.MibViewController(self.builder)
        compiler.addMibCompiler(self.builder, sources=[MIB_SOURCES])

        # mib_standard_response = self.session.get(f"{MIB_STANDARD}", stream=True)
        # if mib_standard_response.status_code == 200:
        #     for line in mib_standard_response.iter_lines():
        #         if line:
        #             mib = line.decode("utf-8")
        #             logger.info(f"MIB: {mib}")
        #             try:
        #                 self.builder.loadModules(mib)
        #                 self.standard_mibs.append(mib)
        #             except Exception as e:
        #                 logger.warning(f"An error occurred during loading MIB module: {mib}: {e}")
        # else:
        for mib in DEFAULT_STANDARD_MIBS:
            self.standard_mibs.append(mib)
            self.builder.loadModules(mib)

        mib_response = self.session.get(f"{MIB_INDEX}")
        self.mib_map = {}
        if mib_response.status_code == 200:
            with StringIO(mib_response.text) as index_csv:
                reader = csv.reader(index_csv)
                for each_row in reader:
                    if len(each_row) == 2:
                        self.mib_map[each_row[1]] = each_row[0]
            logger.debug(f"Loaded {len(self.mib_map.keys())} mib map entries")
        else:
            logger.error(
                f"Unable to load mib map from index http error {self.mib_response.status_code}"
            )
Esempio n. 8
0
def mib_builder(custom_mib_path, LOAD_MIB_MODULE):
    mibBuilder = builder.MibBuilder()
    try:
        if custom_mib_path:
            compiler.addMibCompiler(mibBuilder, sources=custom_mib_path.split(
              ","))
        global mibViewController
        mibViewController = view.MibViewController(mibBuilder)
        if LOAD_MIB_MODULE:
            _mibs=LOAD_MIB_MODULE.split(",")
            mibBuilder.loadModules(*_mibs)
    except error.MibNotFoundError as excep:
        print(" {} Mib Not Found!".format(excep))
 def get_first_node_name(mib_filepath, mib_filename):
     """
     Get the node name from the given mib file path and file name
     :param mib_filepath: Mib file path of the git url or abs file path
     :param mib_filename: MIB file name
     :return: oid, lable, suffix, mibView, mibBuilder
     """
     mibBuilder = builder.MibBuilder()
     compiler.addMibCompiler(mibBuilder, sources=mib_filepath.split(","))
     for mib in mib_filename.split(","):
         mibBuilder.loadModules(mib)
     mibView = view.MibViewController(mibBuilder)
     oid, label, suffix = mibView.getFirstNodeName()
     return oid, label, suffix, mibView, mibBuilder
Esempio n. 10
0
def generator(cbCtx, ast):
    snmpEngine, ctx = cbCtx
    if 'mibViewProxy' not in ctx:
        ctx['mibViewProxy'] = MibViewProxy(ctx['mibViewController'])

    compiler.addMibCompiler(snmpEngine.getMibBuilder())

    snmpEngine, ctx = __MibViewGenerator().preorder((snmpEngine, ctx), ast)

    if 'MibDir' not in ctx:
        ctx['MibDir'] = [defaultMibSourceUrl]
    if 'MibBorrowers' not in ctx:
        ctx['MibBorrowers'] = [defaultMibBorrowerUrl]

    compiler.addMibCompiler(snmpEngine.getMibBuilder(),
                            sources=ctx['MibDir'],
                            borrowers=ctx['MibBorrowers'])
    return snmpEngine, ctx
Esempio n. 11
0
def generator(cbCtx, ast):
    snmpEngine, ctx = cbCtx
    if 'mibViewProxy' not in ctx:
        ctx['mibViewProxy'] = MibViewProxy(ctx['mibViewController'])

    compiler.addMibCompiler(snmpEngine.getMibBuilder())

    snmpEngine, ctx = __MibViewGenerator().preorder((snmpEngine, ctx), ast)

    if 'MibDir' not in ctx:
        ctx['MibDir'] = [ defaultMibSourceUrl ]
    if 'MibBorrowers' not in ctx:
        ctx['MibBorrowers'] = [ defaultMibBorrowerUrl ]

    compiler.addMibCompiler(snmpEngine.getMibBuilder(),
                            sources=ctx['MibDir'],
                            borrowers=ctx['MibBorrowers'])
    return snmpEngine, ctx
Esempio n. 12
0
    def __init__(self,
                 additional_mib_search_paths=[],
                 additional_mib_load_modules=[],
                 debug=False,
                 load_texts=True):
        if debug:  # Enable Debugging
            pysnmp_debug.setLogger(pysnmp_debug.Debug('all'))

        # The pysnmp libraries will compile MIB files into python files, and
        #   store them on the system in a cache directory under ~/.pysnmp/mibs
        #   It only needs to do this once as it encounters new MIBs, and not
        #   every time you run this program.  Order of the loading matters.
        mib_modules = additional_mib_load_modules + DEFAULT_MIB_LOAD_MODULES
        mib_sources = additional_mib_search_paths + DEFAULT_MIB_SEARCH_PATHS
        self.mibBuilder = builder.MibBuilder()
        self.mibBuilder.loadTexts = load_texts  # Loads mib text descriptions
        compiler.addMibCompiler(self.mibBuilder, sources=mib_sources)
        self.mibBuilder.loadModules(*mib_modules)
        self.mibView = view.MibViewController(self.mibBuilder)
 def create_trap_listner_job(cls, port="162"):
     """
     Create Trap listner job
     :param port:
     :return:None
     """
     mibBuilder = builder.MibBuilder()
     custom_mib_path = cls.data_repo.get("custom_mib_path")
     load_mib_module = cls.data_repo.get("load_mib_module")
     temp_custom_mib_paths = []
     if custom_mib_path and load_mib_module:
         custom_mib_paths = custom_mib_path.split(',')
         for paths in custom_mib_paths:
             paths = paths.strip()
             if 'http' in paths and '@mib@' not in paths:
                 if paths[-1] == '/':
                     paths = paths + '/@mib@'
                 else:
                     paths = paths + '@mib@'
             if 'http' in paths and 'browse' in paths:
                 paths = paths.replace('browse', 'raw')
             if 'http' in paths and 'browse' in paths:
                 paths = paths.replace('browse', 'raw')
             temp_custom_mib_paths.append(paths)
         if os.name == 'posix' and '/usr/share/snmp/' not in custom_mib_path:
             temp_custom_mib_paths.append('/usr/share/snmp/')
         try:
             compiler.addMibCompiler(mibBuilder,
                                     sources=temp_custom_mib_paths)
             cls.mibViewController = view.MibViewController(mibBuilder)
             mibs = load_mib_module.split(",")
             mibBuilder.loadModules(*mibs)
         except error.MibNotFoundError as excep:
             testcase_Utils.pNote("{} Mib Not Found!".format(excep),
                                  "Error")
     snmpEngine = cls.get_asyncoredispatcher(port)
     udptransport = udp.UdpTransport()
     cls.udptransport.update({"udptransport{}".format(port): udptransport})
     config.addTransport(
         snmpEngine, udp.domainName,
         udptransport.openServerMode(('0.0.0.0', int(port))))
     snmpEngine.transportDispatcher.jobStarted(1)
Esempio n. 14
0
    def _configureMibObjects(self, configDict):

        mibBuilder = builder.MibBuilder()
        mibViewController = view.MibViewController(mibBuilder)

        compiler.addMibCompiler(
            mibBuilder, sources=configDict['snmp'].get('mibs', ()))

        self._sysUpTime = rfc1902.ObjectIdentity(
            'SNMPv2-MIB', 'sysUpTime', 0).resolveWithMib(mibViewController)

        self._snmpTrapOID = rfc1902.ObjectIdentity(
            'SNMPv2-MIB', 'snmpTrapOID', 0).resolveWithMib(mibViewController)

        self._rtbrickSyslogTrap = rfc1902.ObjectIdentity(
            'RTBRICK-SYSLOG-MIB', 'rtbrickSyslogTrap', 1).resolveWithMib(mibViewController)

        self._syslogMsgNumber = rfc1902.ObjectIdentity(
            'RTBRICK-SYSLOG-MIB', 'syslogMsgNumber', 0).resolveWithMib(mibViewController)

        self._syslogMsgFacility = rfc1902.ObjectIdentity(
            'RTBRICK-SYSLOG-MIB', 'syslogMsgFacility', 0).resolveWithMib(mibViewController)

        self._syslogMsgSeverity = rfc1902.ObjectIdentity(
            'RTBRICK-SYSLOG-MIB', 'syslogMsgSeverity', 0).resolveWithMib(mibViewController)

        self._syslogMsgText = rfc1902.ObjectIdentity(
            'RTBRICK-SYSLOG-MIB', 'syslogMsgText', 0).resolveWithMib(mibViewController)

        self.moduleLogger.info(
            f'Notifications will include these SNMP objects: '
            f'{self._sysUpTime}=TimeTicks, '
            f'{self._snmpTrapOID}={self._rtbrickSyslogTrap} '
            f'{self._syslogMsgNumber}=Unsigned32 '
            f'{self._syslogMsgFacility}=OctetString '
            f'{self._syslogMsgSeverity}=Integer32 '
            f'{self._syslogMsgText}=OctetString')
Esempio n. 15
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=debug.flagMap,
        action='append', type=str, default=[],
        help='Enable one or more categories of SNMP debugging.')

    parser.add_argument(
        '--row-hint', dest='row_hint', action='store_true',
        help='Hint for MIBs Type')

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

    parser.add_argument(
        '--mib-module', dest='mib_modules', action='append',
        type=str, required=True,
        help='MIB module to generate simulation data from')

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

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

    parser.add_argument(
        '--manual-values', action='store_true',
        help='Fill all managed objects values interactively')

    parser.add_argument(
        '--automatic-values', type=int, default=5000,
        help='Probe for suitable managed object value this many times '
             'prior to failing over to manual value specification')

    parser.add_argument(
        '--table-size', type=int, default=10,
        help='Generate SNMP conceptual tables with this many rows')

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

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

    parser.add_argument(
        '--string-pool', metavar='<words>', action='append',
        help='Words to use for simulated string values')

    parser.add_argument(
        '--string-pool-file', metavar='<FILE>', type=str,
        help='File containing the words for simulating SNMP string values')

    parser.add_argument(
        '--integer32-range', metavar='<min,max>',
        type=_parse_range, default=(0, 32),
        help='Range of values used to populate simulated Integer32 values')

    parser.add_argument(
        '--unsigned-range', metavar='<min,max>',
        type=_parse_range, default=(0, 65535),
        help='Range of values used to populate simulated Unsigned values')

    parser.add_argument(
        '--counter-range', metavar='<min,max>',
        type=_parse_range, default=(0, 0xffffffff),
        help='Range of values used to populate simulated Counter values')

    parser.add_argument(
        '--counter64-range', metavar='<min,max>',
        type=_parse_range, default=(0, 0xffffffffffffffff),
        help='Range of values used to populate simulated Counter64 values')

    parser.add_argument(
        '--gauge-range', metavar='<min,max>',
        type=_parse_range, default=(0, 0xffffffff),
        help='Range of values used to populate simulated Gauge values')

    parser.add_argument(
        '--timeticks-range', metavar='<min,max>',
        type=_parse_range, default=(0, 0xffffffff),
        help='Range of values used to populate simulated Timeticks values')

    args = parser.parse_args()

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

    if args.manual_values:
        args.automatic_values = 0

    if args.string_pool_file:
        with open(args.string_pool_file) as fl:
            args.string_pool = fl.read().split()

    elif args.string_pool:
        args.string_pool = ['Jaded', 'zombies', 'acted', 'quaintly', 'but',
                            'kept', 'driving', 'their', 'oxen', 'forward']

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

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

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

    else:
        args.output_file = sys.stdout

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

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

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

    def get_value(syntax, hint='', automatic_values=args.automatic_values):

        make_guess = args.automatic_values

        val = None

        while True:
            if make_guess:
                if isinstance(syntax, rfc1902.IpAddress):
                    val = '.'.join([str(random.randrange(1, 256)) for x in range(4)])

                elif isinstance(syntax, rfc1902.TimeTicks):
                    val = random.randrange(args.timeticks_range[0], args.timeticks_range[1])

                elif isinstance(syntax, rfc1902.Gauge32):
                    val = random.randrange(args.gauge_range[0], args.gauge_range[1])

                elif isinstance(syntax, rfc1902.Counter32):
                    val = random.randrange(args.counter_range[0], args.counter_range[1])

                elif isinstance(syntax, rfc1902.Integer32):
                    val = random.randrange(args.integer32_range[0], args.integer32_range[1])

                elif isinstance(syntax, rfc1902.Unsigned32):
                    val = random.randrange(args.unsigned_range[0], args.unsigned_range[1])

                elif isinstance(syntax, rfc1902.Counter64):
                    val = random.randrange(args.counter64_range[0], args.counter64_range[1])

                elif isinstance(syntax, univ.OctetString):
                    maxWords = 10
                    val = ' '.join([args.string_pool[random.randrange(0, len(args.string_pool))]
                                    for i in range(random.randrange(1, maxWords))])

                elif isinstance(syntax, univ.ObjectIdentifier):
                    val = '.'.join(['1', '3', '6', '1', '3'] + [
                        '%d' % random.randrange(0, 255)
                        for x in range(random.randrange(0, 10))])

                elif isinstance(syntax, rfc1902.Bits):
                    val = [random.randrange(0, 256)
                           for x in range(random.randrange(0, 9))]

                else:
                    val = '?'

            # remove value enumeration

            try:
                if syntax.tagSet == rfc1902.Integer32.tagSet:
                    return rfc1902.Integer32(syntax.clone(val))

                if syntax.tagSet == rfc1902.Unsigned32.tagSet:
                    return rfc1902.Unsigned32(syntax.clone(val))

                if syntax.tagSet == rfc1902.Bits.tagSet:
                    return rfc1902.OctetString(syntax.clone(val))

                return syntax.clone(val)

            except PyAsn1Error as exc:
                if make_guess == 1:
                    sys.stderr.write(
                        '*** Inconsistent value: %s\r\n*** See constraints and '
                        'suggest a better one for:\r\n' % exc)

                if make_guess:
                    make_guess -= 1
                    continue

            sys.stderr.write('%s# Value [\'%s\'] ? ' % (
                hint, (val is None and '<none>' or val),))
            sys.stderr.flush()

            line = sys.stdin.readline().strip()

            if line:
                if line[:2] == '0x':
                    if line[:4] == '0x0x':
                        line = line[2:]

                    elif isinstance(syntax, univ.OctetString):
                        val = syntax.clone(hexValue=line[2:])

                    else:
                        val = int(line[2:], 16)

                else:
                    val = line

    data_file_handler = snmprec.SnmprecRecord()

    mib_builder = builder.MibBuilder()

    # Load MIB tree foundation classes
    (MibScalar,
     MibTable,
     MibTableRow,
     MibTableColumn) = mib_builder.importSymbols(
        'SNMPv2-SMI',
        'MibScalar',
        'MibTable',
        'MibTableRow',
        'MibTableColumn'
    )

    mib_view_controller = view.MibViewController(mib_builder)

    compiler.addMibCompiler(mib_builder, sources=args.mib_sources)

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

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

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

    output = []

    # MIBs walk
    for modName in args.mib_modules:
        if not args.quiet:
            sys.stderr.write(
                '# MIB module: %s, from %s till '
                '%s\r\n' % (modName, args.start_object or 'the beginning',
                            args.stop_object or 'the end'))

        try:
            oid = ObjectIdentity(modName).resolveWithMib(mib_view_controller)

        except error.PySnmpError as exc:
            sys.stderr.write('ERROR: failed on MIB %s: '
                             '%s\r\n' % (modName, exc))
            return 1

        hint = row_hint = ''
        row_oid = None
        suffix = ()
        this_table_size = 0

        while True:
            try:
                oid, label, _ = mib_view_controller.getNextNodeName(oid)

            except error.NoSuchObjectError:
                break

            if row_oid and not row_oid.isPrefixOf(oid):
                this_table_size += 1

                if args.automatic_values:
                    if this_table_size < args.table_size:
                        oid = tuple(row_oid)
                        if not args.quiet:
                            sys.stderr.write(
                                '# Synthesizing row #%d of table %s\r\n' % (
                                    this_table_size, row_oid))

                    else:
                        if not args.quiet:
                            sys.stderr.write(
                                '# Finished table %s (%d rows)\r\n' % (
                                    row_oid, this_table_size))

                        row_oid = None

                else:
                    while True:
                        sys.stderr.write(
                            '# Synthesize row #%d for table %s (y/n)? ' % (
                                this_table_size, row_oid))
                        sys.stderr.flush()

                        line = sys.stdin.readline().strip()
                        if line:
                            if line[0] in ('y', 'Y'):
                                oid = tuple(row_oid)
                                break

                            elif line[0] in ('n', 'N'):
                                if not args.quiet:
                                    sys.stderr.write(
                                        '# Finished table %s (%d rows)\r\n' % (
                                            row_oid, this_table_size))
                                row_oid = None
                                break

            if args.start_object and oid < args.start_object:
                continue  # skip on premature OID

            if args.stop_object and oid > args.stop_object:
                break  # stop on out of range condition

            mib_name, sym_name, _ = mib_view_controller.getNodeLocation(oid)
            node, = mib_builder.importSymbols(mib_name, sym_name)

            if isinstance(node, MibTable):
                hint = '# Table %s::%s\r\n' % (mib_name, sym_name)
                if not args.quiet:
                    sys.stderr.write(
                        '# Starting table %s::%s (%s)\r\n' % (
                            mib_name, sym_name, univ.ObjectIdentifier(oid)))
                continue

            elif isinstance(node, MibTableRow):
                row_indices = {}
                suffix = ()
                row_hint = hint + '# Row %s::%s\r\n' % (mib_name, sym_name)

                for (implied_flag,
                     idx_mod_name, idx_sym_name) in node.getIndexNames():
                    idxNode, = mib_builder.importSymbols(
                        idx_mod_name, idx_sym_name)

                    row_hint += '# Index %s::%s (type %s)\r\n' % (
                        idx_mod_name, idx_sym_name,
                        idxNode.syntax.__class__.__name__)

                    row_indices[idxNode.name] = get_value(
                        idxNode.syntax, not args.quiet and row_hint or '')

                    suffix = suffix + node.getAsName(
                        row_indices[idxNode.name], implied_flag)

                if not row_indices:
                    if not args.quiet:
                        sys.stderr.write(
                            '# WARNING: %s::%s table has no index!\r\n' % (
                                mib_name, sym_name))

                if row_oid is None:
                    this_table_size = 0

                row_oid = univ.ObjectIdentifier(oid)
                continue

            elif isinstance(node, MibTableColumn):
                oid = node.name
                if oid in row_indices:
                    val = row_indices[oid]

                else:
                    hint = ''
                    if not args.quiet:
                        hint += row_hint
                        hint += ('# Column %s::%s (type'
                                 ' %s)\r\n' % (mib_name, sym_name,
                                               node.syntax.__class__.__name__))

                    val = get_value(node.syntax, hint)

            elif isinstance(node, MibScalar):
                hint = ''
                if not args.row_hint:
                    hint += ('# Scalar %s::%s (type %s)'
                             '\r\n' % (mib_name, sym_name,
                                       node.syntax.__class__.__name__))
                oid = node.name
                suffix = (0,)
                val = get_value(node.syntax, hint)

            else:
                hint = ''
                continue

            output.append((oid + suffix, val))

        output.sort(key=lambda x: univ.ObjectIdentifier(x[0]))

        unique = set()

        for oid, val in output:
            if oid in unique:
                if not args.quiet:
                    sys.stderr.write(
                        '# Dropping duplicate OID %s\r\n' % (
                            univ.ObjectIdentifier(oid),))
            else:
                try:
                    args.output_file.write(data_file_handler.format(oid, val))

                except SnmpsimError as exc:
                    sys.stderr.write('ERROR: %s\r\n' % (exc,))

                else:
                    unique.add(oid)

        if not args.quiet:
            sys.stderr.write(
                '# End of %s, %s OID(s) dumped\r\n' % (modName, len(unique)))

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

    return 0
Esempio n. 16
0
# Load MIB tree foundation classes
(MibScalar,
 MibTable,
 MibTableRow,
 MibTableColumn) = mibBuilder.importSymbols(
    'SNMPv2-SMI',
    'MibScalar',
    'MibTable',
    'MibTableRow',
    'MibTableColumn'
)

mibViewController = view.MibViewController(mibBuilder)

compiler.addMibCompiler(
    mibBuilder, sources=mibSources or defaultMibSources
)

try:
    if isinstance(startOID, ObjectIdentity):
        startOID.resolveWithMib(mibViewController)

    if isinstance(stopOID, ObjectIdentity):
        stopOID.resolveWithMib(mibViewController)

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

output = []
"""
PDU var-binds to MIB objects
++++++++++++++++++++++++++++

This script explains how Python application could turn SNMP PDU
variable-bindings into MIB objects or the other way around.

The code that configures MIB compiler is similar to what
happens inside the pysnmp.hlapi API.
"""#
from pysnmp.smi import builder, view, compiler, rfc1902

# Assemble MIB browser
mibBuilder = builder.MibBuilder()
mibViewController = view.MibViewController(mibBuilder)
compiler.addMibCompiler(mibBuilder, sources=['file:///usr/share/snmp/mibs',
                                             'http://mibs.snmplabs.com/asn1/@mib@'])

# Pre-load MIB modules we expect to work with
mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB')

# This is what we can get in TRAP PDU
varBinds = [
    ('1.3.6.1.2.1.1.3.0', 12345),
    ('1.3.6.1.6.3.1.1.4.1.0', '1.3.6.1.6.3.1.1.5.2'),
    ('1.3.6.1.6.3.18.1.3.0', '0.0.0.0'),
    ('1.3.6.1.6.3.18.1.4.0', ''),
    ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'),
    ('1.3.6.1.2.1.1.1.0', 'my system')
]

# Run var-binds through MIB resolver
Esempio n. 18
0
    def __init__(self, host, port, raw_mibs, compiled_mibs):

        self.oid_mapping = {}
        self.databus_mediator = DatabusMediator(self.oid_mapping)
        # mapping between OID and databus keys

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

        # Configure SNMP compiler
        mib_builder = self.snmpEngine.getMibBuilder()
        addMibCompiler(mib_builder, destination=compiled_mibs)
        mib_builder.getMibCompiler().addSources(FileReader(raw_mibs))
        mib_builder.getMibCompiler().addSources(
            FtpReader("ftp.cisco.com", "/pub/mibs/v2/@mib@", 80))

        # Transport setup
        udp_sock = gevent.socket.socket(gevent.socket.AF_INET,
                                        gevent.socket.SOCK_DGRAM)
        udp_sock.setsockopt(gevent.socket.SOL_SOCKET,
                            gevent.socket.SO_BROADCAST, 1)
        udp_sock.bind((host, port))
        self.server_port = udp_sock.getsockname()[1]
        # UDP over IPv4
        self.addSocketTransport(self.snmpEngine, udp.domainName, udp_sock)

        # SNMPv1
        config.addV1System(self.snmpEngine, "public-read", "public")

        # SNMPv3/USM setup
        # user: usr-md5-des, auth: MD5, priv DES
        config.addV3User(
            self.snmpEngine,
            "usr-md5-des",
            config.usmHMACMD5AuthProtocol,
            "authkey1",
            config.usmDESPrivProtocol,
            "privkey1",
        )
        # user: usr-sha-none, auth: SHA, priv NONE
        config.addV3User(self.snmpEngine, "usr-sha-none",
                         config.usmHMACSHAAuthProtocol, "authkey1")
        # user: usr-sha-aes128, auth: SHA, priv AES/128
        config.addV3User(
            self.snmpEngine,
            "usr-sha-aes128",
            config.usmHMACSHAAuthProtocol,
            "authkey1",
            config.usmAesCfb128Protocol,
            "privkey1",
        )

        # Allow full MIB access for each user at VACM
        config.addVacmUser(
            self.snmpEngine,
            1,
            "public-read",
            "noAuthNoPriv",
            readSubTree=(1, 3, 6, 1, 2, 1),
            writeSubTree=(1, 3, 6, 1, 2, 1),
        )
        config.addVacmUser(
            self.snmpEngine,
            2,
            "public-read",
            "noAuthNoPriv",
            readSubTree=(1, 3, 6, 1, 2, 1),
            writeSubTree=(1, 3, 6, 1, 2, 1),
        )
        config.addVacmUser(
            self.snmpEngine,
            3,
            "usr-md5-des",
            "authPriv",
            readSubTree=(1, 3, 6, 1, 2, 1),
            writeSubTree=(1, 3, 6, 1, 2, 1),
        )
        config.addVacmUser(
            self.snmpEngine,
            3,
            "usr-sha-none",
            "authNoPriv",
            readSubTree=(1, 3, 6, 1, 2, 1),
            writeSubTree=(1, 3, 6, 1, 2, 1),
        )
        config.addVacmUser(
            self.snmpEngine,
            3,
            "usr-sha-aes128",
            "authPriv",
            readSubTree=(1, 3, 6, 1, 2, 1),
            writeSubTree=(1, 3, 6, 1, 2, 1),
        )

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

        # Register SNMP Applications at the SNMP engine for particular SNMP context
        self.resp_app_get = conpot_cmdrsp.c_GetCommandResponder(
            self.snmpEngine, snmpContext, self.databus_mediator, host, port)
        self.resp_app_set = conpot_cmdrsp.c_SetCommandResponder(
            self.snmpEngine, snmpContext, self.databus_mediator, host, port)
        self.resp_app_next = conpot_cmdrsp.c_NextCommandResponder(
            self.snmpEngine, snmpContext, self.databus_mediator, host, port)
        self.resp_app_bulk = conpot_cmdrsp.c_BulkCommandResponder(
            self.snmpEngine, snmpContext, self.databus_mediator, host, port)
Esempio n. 19
0
                         'pms', timeout, retryCount)
    log.info('Querying UNIX named pipe agent at %s' % agentUNIXEndpoint)

elif agentUDPv4Endpoint:
    config.addSocketTransport(snmpEngine, udp.domainName,
                              udp.UdpSocketTransport().openClientMode())
    config.addTargetAddr(snmpEngine, 'tgt', udp.domainName, agentUDPv4Endpoint,
                         'pms', timeout, retryCount)
    log.info('Querying UDP/IPv4 agent at %s:%s' % agentUDPv4Endpoint)

log.info('Agent response timeout: %.2f secs, retries: %s' %
         (timeout / 100, retryCount))

if (isinstance(startOID, ObjectIdentity)
        or isinstance(stopOID, ObjectIdentity)):
    compiler.addMibCompiler(snmpEngine.getMibBuilder(),
                            sources=mibSources or defaultMibSources)
    mibViewController = view.MibViewController(snmpEngine.getMibBuilder())
    if isinstance(startOID, ObjectIdentity):
        startOID.resolveWithMib(mibViewController)
    if isinstance(stopOID, ObjectIdentity):
        stopOID.resolveWithMib(mibViewController)

# Variation module initialization

if variationModule:
    log.info('Initializing variation module...')
    for x in ('init', 'record', 'shutdown'):
        if x not in variationModule:
            log.error('missing "%s" handler at variation module "%s"' %
                      (x, variationModuleName))
            sys.exit(-1)
Esempio n. 20
0
        udp.UdpSocketTransport().openClientMode())

    config.addTargetAddr(
        snmpEngine, 'tgt', udp.domainName, agentUDPv4Endpoint, 'pms',
        timeout, retryCount)

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

log.info('Agent response timeout: %.2f secs, retries: '
         '%s' % (timeout / 100, retryCount))

if (isinstance(startOID, ObjectIdentity) or
        isinstance(stopOID, ObjectIdentity)):

    compiler.addMibCompiler(
        snmpEngine.getMibBuilder(),
        sources=mibSources or defaultMibSources)

    mibViewController = view.MibViewController(snmpEngine.getMibBuilder())

    try:
        if isinstance(startOID, ObjectIdentity):
            startOID.resolveWithMib(mibViewController)

        if isinstance(stopOID, ObjectIdentity):
            stopOID.resolveWithMib(mibViewController)

    except PySnmpError:
        sys.stderr.write('ERROR: %s\r\n' % sys.exc_info()[1])
        sys.exit(-1)
Esempio n. 21
0
from app import app, db
from controllers import *
from pysnmp.hlapi import *
from pysnmp.smi import builder, view, compiler
from multiprocessing import Process

mibBuilder = builder.MibBuilder()
mibViewController = view.MibViewController(mibBuilder)
compiler.addMibCompiler(mibBuilder, sources=['file:///usr/share/snmp/mibs'])
mibBuilder.loadModules('SNMPv2-MIB', 'RFC1213-MIB', 'IF-MIB')


class DispositivoSNMP:
    def __init__(self, dispositivo):
        self.dispositivo = dispositivo
        self._ip = dispositivo.ip
        self.deltaTime = 600
        dispController = DispositivoController()
        self.interfaces = [
            InterfazSNMP(interfaz) for interfaz in
            dispController.getInterfacesDispositivo(dispositivo)
        ]


class InterfazSNMP:
    def __init__(self, iface):
        self.number = iface.puerto
        self.name = iface.nombre
        self.deltaTime = 600
        self._ifIn = 0
        self._ifOut = 0
++++++++++++++++++++++++++++

This script explains how Python application could turn SNMP PDU
variable-bindings into MIB objects or the other way around.

The code that configures MIB compiler is similar to what
happens inside the pysnmp.hlapi API.
"""#
from pysnmp.smi import builder, view, compiler, rfc1902

# Assemble MIB browser
mibBuilder = builder.MibBuilder()
mibViewController = view.MibViewController(mibBuilder)
compiler.addMibCompiler(mibBuilder,
                        sources=[
                            'file:///usr/share/snmp/mibs',
                            'http://mibs.snmplabs.com/asn1/@mib@'
                        ])

# Pre-load MIB modules we expect to work with
mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB')

# This is what we can get in TRAP PDU
varBinds = [('1.3.6.1.2.1.1.3.0', 12345),
            ('1.3.6.1.6.3.1.1.4.1.0', '1.3.6.1.6.3.1.1.5.2'),
            ('1.3.6.1.6.3.18.1.3.0', '0.0.0.0'), ('1.3.6.1.6.3.18.1.4.0', ''),
            ('1.3.6.1.6.3.1.1.4.3.0', '1.3.6.1.4.1.20408.4.1.1.2'),
            ('1.3.6.1.2.1.1.1.0', 'my system')]

# Run var-binds through MIB resolver
# You may want to catch and ignore resolution errors here
Esempio n. 23
0
This script performs similar to the following Net-SNMP command:

| $ snmpwalk -v1 -c public -ObentU 104.236.166.95 1.3.6.1.2.1.1 1.3.6.1.4.1.1

"""#
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import cmdgen
from pysnmp.smi import compiler, view, rfc1902

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

# Attach MIB compiler to SNMP Engine (MIB Builder)
# This call will fail if PySMI is not present on the system
compiler.addMibCompiler(snmpEngine.getMibBuilder())
# ... alternatively, this call will not complain on missing PySMI
# compiler.addMibCompiler(snmpEngine.getMibBuilder(), ifAvailable=True)

# Used for MIB objects resolution
mibViewController = view.MibViewController(snmpEngine.getMibBuilder())

#
#
# SNMPv1/2c setup
#

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

# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
Esempio n. 24
0
def main():

    lost_comments = False
    written_count = skipped_count = duplicate_count = 0
    broken_count = variation_count = 0

    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('--sort-records',
                        action='store_true',
                        help='Order simulation data records by OID')

    parser.add_argument(
        '--ignore-broken-records',
        action='store_true',
        help='Drop malformed simulation data records rather than bailing out')

    parser.add_argument('--deduplicate-records',
                        action='store_true',
                        help='Drop duplicate simulation data records')

    parser.add_argument(
        '--escaped-strings',
        action='store_true',
        help='Produce Python-style escaped strings (e.g. "\x00") in '
        'simulation data values rather than hexify such non-ASCII '
        'values')

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

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

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

    parser.add_argument(
        '--source-record-type',
        choices=RECORD_TYPES,
        default='snmprec',
        help='Treat input as simulation data of this record type')

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

    parser.add_argument('--input-file',
                        dest='input_files',
                        metavar='<FILE>',
                        action='append',
                        type=str,
                        required=True,
                        help='SNMP simulation data file to read records from')

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

    args = parser.parse_args()

    if not args.mib_source:
        args.mib_source = ['http://mibs.snmplabs.com/asn1/@mib@']

    args.input_files = [
        RECORD_TYPES[args.source_record_type].open(x) for x in args.input_files
    ]

    if args.output_file and args.output_file != '-':
        ext = os.path.extsep + RECORD_TYPES[args.destination_record_type].ext

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

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

    else:
        args.output_file = sys.stdout

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

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

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

    if not args.input_files:
        args.input_files.append(sys.stdin)

    if (isinstance(args.start_oid, rfc1902.ObjectIdentity)
            or isinstance(args.stop_oid, rfc1902.ObjectIdentity)):

        mib_builder = builder.MibBuilder()

        mib_view_controller = view.MibViewController(mib_builder)

        compiler.addMibCompiler(mib_builder, sources=args.mib_sources)

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

            if isinstance(args.stop_oid, rfc1902.ObjectIdentity):
                args.stop_oid.resolveWithMib(mib_view_controller)

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

    records_list = []

    for input_file in args.input_files:

        if not args.quiet:
            sys.stderr.write(
                '# Input file #%s, processing records from %s till '
                '%s\r\n' % (args.input_files.index(input_file), args.start_oid
                            or 'the beginning', args.stop_oid or 'the end'))

        line_no = 0

        while True:
            line, rec_line_no, _ = get_record(input_file, line_no)

            if not line:
                break

            if rec_line_no != line_no + 1:
                if not args.quiet:
                    sys.stderr.write(
                        '# Losing comment at lines %s..%s (input file #'
                        '%s)\r\n' % (line_no + 1, rec_line_no - 1,
                                     args.input_files.index(input_file)))

                line_no = rec_line_no

                lost_comments += 1

            backdoor = {}

            try:
                oid, value = RECORD_TYPES[args.source_record_type].evaluate(
                    line, backdoor=backdoor)

            except error.SnmpsimError as exc:
                if args.ignore_broken_records:
                    if not args.quiet:
                        sys.stderr.write('# Skipping broken record <%s>: '
                                         '%s\r\n' % (line, exc))
                    broken_count += 1
                    continue

                else:
                    if not args.quiet:
                        sys.stderr.write('ERROR: broken record <%s>: '
                                         '%s\r\n' % (line, exc))

                    return 1

            if (args.start_oid and args.start_oid > oid
                    or args.stop_oid and args.stop_oid < oid):
                skipped_count += 1
                continue

            records_list.append((oid, value, backdoor))

    if args.sort_records:
        records_list.sort(key=lambda x: x[0])

    unique_indices = set()

    for record in records_list:
        if args.deduplicate_records:
            if record[0] in unique_indices:
                if not args.quiet:
                    sys.stderr.write('# Skipping duplicate record '
                                     '<%s>\r\n' % record[0])

                duplicate_count += 1

                continue

            else:
                unique_indices.add(record[0])

        try:
            args.output_file.write(
                RECORD_TYPES[args.destination_record_type].format(
                    record[0],
                    record[1],
                    backdoor=record[2],
                    nohex=args.escaped_strings))

        except Exception as exc:
            sys.stderr.write('ERROR: record not written: %s\r\n' % exc)
            break

        written_count += 1

        if record[2]:
            variation_count += 1

    if not args.quiet:
        sys.stderr.write(
            '# Records: written %s, filtered out %s, de-duplicated %s, ignored '
            '%s, broken %s, variated %s\r\n' %
            (written_count, skipped_count, duplicate_count, lost_comments,
             broken_count, variation_count))

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

    return 0
Esempio n. 25
0
if len(sys.argv) > 2:
    snmpip = sys.argv[2]
if len(sys.argv) > 3:
    szOutputfile = sys.argv[3]
if len(sys.argv) > 4:
    szSnmpLogfile = sys.argv[4]

# Create output files
outputFile = open(szOutputfile, "w+")
logFile = open(szSnmpLogfile, "a+")

# Assemble MIB viewer
mibBuilder = builder.MibBuilder()
compiler.addMibCompiler(mibBuilder,
                        sources=[
                            'file:///usr/share/snmp/mibs',
                            'file:///var/lib/snmp/mibs',
                            '/usr/local/share/snmp/mibs/'
                        ])
mibViewController = view.MibViewController(mibBuilder)
# Pre-load MIB modules we expect to work with
try:
    mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB',
                           'SYSLOG-MSG-MIB')
except Exception:
    print("Failed loading MIBs")

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

# Transport setup
# UDP over IPv4, add listening interface/port
Esempio n. 26
0
from pysnmp.smi import builder, view, compiler, error
from pysnmp import debug

debug.setLogger(debug.Debug('dsp'))

# Create MIB loader/builder
mibBuilder = builder.MibBuilder()

# Optionally attach PySMI MIB compiler (if installed)
print('Attaching MIB compiler...'),
compiler.addMibCompiler(
    mibBuilder,
    sources=['/usr/share/snmp/mibs/', 'http://mibs.snmplabs.com/asn1/'])
print('done')

# Optionally set an alternative path to compiled MIBs
print('Setting MIB sources...')
mibBuilder.addMibSources(builder.DirMibSource('/usr/share/snmp/mibs/'))
print(mibBuilder.getMibSources())
print('done')

print('Loading MIB modules...'),
mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-FRAMEWORK-MIB',
                       'SNMP-COMMUNITY-MIB', 'IP-MIB', 'SNMPHANDLER-MIB')
print('done')

print('Indexing MIB objects...'),
mibView = view.MibViewController(mibBuilder)
print('done')

print('MIB symbol name lookup by OID: '),
Esempio n. 27
0
    def resolveWithMib(self, mibViewController):
        """Perform MIB variable ID conversion.

        Parameters
        ----------
        mibViewController : :py:class:`~pysnmp.smi.view.MibViewController`
            class instance representing MIB browsing functionality.

        Returns
        -------
        : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity`
            reference to itself

        Raises
        ------
        SmiError
           In case of fatal MIB hanling errora

        Notes
        -----
        Calling this method might cause the following sequence of
        events (exact details depends on many factors):

        * ASN.1 MIB file downloaded and handed over to
          :py:class:`~pysmi.compiler.MibCompiler` for conversion into
          Python MIB module (based on pysnmp classes)
        * Python MIB module is imported by SNMP engine, internal indices
          created
        * :py:class:`~pysnmp.smi.view.MibViewController` looks up the
          rest of MIB identification information based on whatever information
          is already available, :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity`
          class instance
          gets updated and ready for further use.

        Examples
        --------
        >>> objectIdentity = ObjectIdentity('SNMPv2-MIB', 'sysDescr')
        >>> objectIdentity.resolveWithMib(mibViewController)
        ObjectIdentity('SNMPv2-MIB', 'sysDescr')
        >>>

        """
        if self.__mibSourcesToAdd is not None:
            debug.logger & debug.flagMIB and debug.logger("adding MIB sources %s" % ", ".join(self.__mibSourcesToAdd))
            mibViewController.mibBuilder.addMibSources(*[ZipMibSource(x) for x in self.__mibSourcesToAdd])
            self.__mibSourcesToAdd = None

        if self.__asn1SourcesToAdd is None:
            addMibCompiler(mibViewController.mibBuilder, ifAvailable=True, ifNotAdded=True)
        else:
            debug.logger & debug.flagMIB and debug.logger(
                "adding MIB compiler with source paths %s" % ", ".join(self.__asn1SourcesToAdd)
            )
            addMibCompiler(
                mibViewController.mibBuilder,
                sources=self.__asn1SourcesToAdd,
                searchers=self.__asn1SourcesOptions.get("searchers"),
                borrowers=self.__asn1SourcesOptions.get("borrowers"),
                destination=self.__asn1SourcesOptions.get("destination"),
                ifAvailable=self.__asn1SourcesOptions.get("ifAvailable"),
                ifNotAdded=self.__asn1SourcesOptions.get("ifNotAdded"),
            )
            self.__asn1SourcesToAdd = self.__asn1SourcesOptions = None

        if self.__modNamesToLoad is not None:
            debug.logger & debug.flagMIB and debug.logger("loading MIB modules %s" % ", ".join(self.__modNamesToLoad))
            mibViewController.mibBuilder.loadModules(*self.__modNamesToLoad)
            self.__modNamesToLoad = None

        if self.__state & self.stClean:
            return self

        MibScalar, MibTableColumn = mibViewController.mibBuilder.importSymbols(
            "SNMPv2-SMI", "MibScalar", "MibTableColumn"
        )

        self.__indices = ()

        if isinstance(self.__args[0], ObjectIdentity):
            self.__args[0].resolveWithMib(mibViewController)

        if len(self.__args) == 1:  # OID or label or MIB module
            debug.logger & debug.flagMIB and debug.logger("resolving %s as OID or label" % self.__args)
            try:
                # pyasn1 ObjectIdentifier or sequence of ints or string OID
                self.__oid = rfc1902.ObjectName(self.__args[0])  # OID
            except PyAsn1Error:
                # sequence of sub-OIDs and labels
                if isinstance(self.__args[0], (list, tuple)):
                    prefix, label, suffix = mibViewController.getNodeName(self.__args[0])
                # string label
                elif "." in self.__args[0]:
                    prefix, label, suffix = mibViewController.getNodeNameByOid(tuple(self.__args[0].split(".")))
                # MIB module name
                else:
                    modName = self.__args[0]
                    mibViewController.mibBuilder.loadModules(modName)
                    if self.__kwargs.get("last"):
                        prefix, label, suffix = mibViewController.getLastNodeName(modName)
                    else:
                        prefix, label, suffix = mibViewController.getFirstNodeName(modName)

                if suffix:
                    try:
                        suffix = tuple([int(x) for x in suffix])
                    except ValueError:
                        raise SmiError("Unknown object name component %r" % (suffix,))
                self.__oid = rfc1902.ObjectName(prefix + suffix)
            else:
                prefix, label, suffix = mibViewController.getNodeNameByOid(self.__oid)

            debug.logger & debug.flagMIB and debug.logger(
                "resolved %r into prefix %r and suffix %r" % (self.__args, prefix, suffix)
            )

            modName, symName, _ = mibViewController.getNodeLocation(prefix)

            self.__modName = modName
            self.__symName = symName

            self.__label = label

            mibNode, = mibViewController.mibBuilder.importSymbols(modName, symName)

            self.__mibNode = mibNode

            debug.logger & debug.flagMIB and debug.logger("resolved prefix %r into MIB node %r" % (prefix, mibNode))

            if isinstance(mibNode, MibTableColumn):  # table column
                if suffix:
                    rowModName, rowSymName, _ = mibViewController.getNodeLocation(mibNode.name[:-1])
                    rowNode, = mibViewController.mibBuilder.importSymbols(rowModName, rowSymName)
                    self.__indices = rowNode.getIndicesFromInstId(suffix)
            elif isinstance(mibNode, MibScalar):  # scalar
                if suffix:
                    self.__indices = (rfc1902.ObjectName(suffix),)
            else:
                if suffix:
                    self.__indices = (rfc1902.ObjectName(suffix),)
            self.__state |= self.stClean

            debug.logger & debug.flagMIB and debug.logger("resolved indices are %r" % (self.__indices,))

            return self
        elif len(self.__args) > 1:  # MIB, symbol[, index, index ...]
            # MIB, symbol, index, index
            if self.__args[0] and self.__args[1]:
                self.__modName = self.__args[0]
                self.__symName = self.__args[1]
            # MIB, ''
            elif self.__args[0]:
                mibViewController.mibBuilder.loadModules(self.__args[0])
                if self.__kwargs.get("last"):
                    prefix, label, suffix = mibViewController.getLastNodeName(self.__args[0])
                else:
                    prefix, label, suffix = mibViewController.getFirstNodeName(self.__args[0])
                self.__modName, self.__symName, _ = mibViewController.getNodeLocation(prefix)
            # '', symbol, index, index
            else:
                prefix, label, suffix = mibViewController.getNodeName(self.__args[1:])
                self.__modName, self.__symName, _ = mibViewController.getNodeLocation(prefix)

            mibNode, = mibViewController.mibBuilder.importSymbols(self.__modName, self.__symName)

            self.__mibNode = mibNode

            self.__oid = rfc1902.ObjectName(mibNode.getName())

            prefix, label, suffix = mibViewController.getNodeNameByOid(self.__oid)
            self.__label = label

            debug.logger & debug.flagMIB and debug.logger(
                "resolved %r into prefix %r and suffix %r" % (self.__args, prefix, suffix)
            )

            if isinstance(mibNode, MibTableColumn):  # table
                rowModName, rowSymName, _ = mibViewController.getNodeLocation(mibNode.name[:-1])
                rowNode, = mibViewController.mibBuilder.importSymbols(rowModName, rowSymName)
                if self.__args[2:]:
                    try:
                        instIds = rowNode.getInstIdFromIndices(*self.__args[2:])
                        self.__oid += instIds
                        self.__indices = rowNode.getIndicesFromInstId(instIds)
                    except PyAsn1Error:
                        raise SmiError(
                            "Instance index %r to OID convertion failure at object %r: %s"
                            % (self.__args[2:], mibNode.getLabel(), sys.exc_info()[1])
                        )
            elif self.__args[2:]:  # any other kind of MIB node with indices
                if self.__args[2:]:
                    instId = rfc1902.ObjectName(".".join([str(x) for x in self.__args[2:]]))
                    self.__oid += instId
                    self.__indices = (instId,)
            self.__state |= self.stClean

            debug.logger & debug.flagMIB and debug.logger("resolved indices are %r" % (self.__indices,))

            return self
        else:
            raise SmiError("Non-OID, label or MIB symbol")
Esempio n. 28
0
if __name__ == "__main__":
    args = parse_input()

    # Specify the absolute path of the MIB files
    lib_path = join(dirname(dirname(abspath(__file__))), 'labSNMP')
    ansi_mib_path = 'file:///' + join(lib_path, 'MIB')
    py_mib_path = join(lib_path, 'compiled')

    # FIXME: Use environmental variables to enable pysnmp to load compiled mibs
    # I've tried to use addMibSources, and it can load the file in advance, but
    # it just refuses to use it.
    environ['PYSNMP_MIB_PKGS'] = py_mib_path

    mibBuilder = builder.MibBuilder()
    compiler.addMibCompiler(
        mibBuilder,
        sources=[ansi_mib_path, 'http://mibs.snmplabs.com/asn1/@mib@'])

    # FIXME: If non-precompiled MIB is needed, it must be loaded first
    # mibBuilder.loadModules('WIENER-CRATE-MIB')

    if args.var is not None:
        oidtype = ObjectType(ObjectIdentity(*args.oids), args.var)
    else:
        oidtype = ObjectType(ObjectIdentity(*args.oids))

    queryCmd = findCmd(args.mode)(SnmpEngine(), CommunityData(args.community),
                                  UdpTransportTarget((args.host[0], 161)),
                                  ContextData(), oidtype)

    try:
This script performs similar to the following Net-SNMP command:

| $ snmpwalk -v1 -c public -ObentU 104.236.166.95 1.3.6.1.2.1.1 1.3.6.1.4.1.1

"""#
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import cmdgen
from pysnmp.smi import compiler, view, rfc1902

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

# Attach MIB compiler to SNMP Engine (MIB Builder)
# This call will fail if PySMI is not present on the system
compiler.addMibCompiler(snmpEngine.getMibBuilder())
# ... alternatively, this call will not complain on missing PySMI
# compiler.addMibCompiler(snmpEngine.getMibBuilder(), ifAvailable=True)

# Used for MIB objects resolution
mibViewController = view.MibViewController(snmpEngine.getMibBuilder())

# 
#
# SNMPv1/2c setup
#

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

# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
Esempio n. 30
0
def main():
    variation_module = None

    parser = argparse.ArgumentParser(description=DESCRIPTION)

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

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

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

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

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

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

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

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

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

    v3arch_group = parser.add_argument_group('SNMPv3 parameters')

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

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

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

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

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

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

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

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

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

    endpoint_group = parser.add_mutually_exclusive_group(required=True)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    args = parser.parse_args()

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

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

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

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

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

    else:
        args.output_file = sys.stdout

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

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

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

    # Catch missing params

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

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

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

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

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

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

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

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

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

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

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

    # Load variation module

    if args.variation_module:

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

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

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

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

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

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

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

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

    # SNMP configuration

    snmp_engine = engine.SnmpEngine()

    if args.protocol_version == '3':

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

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

        else:
            secLevel = 'authPriv'

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

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

    else:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    # Variation module initialization

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

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

        try:
            handler = variation_module['init']

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

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

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

    data_file_handler = variation.RECORD_TYPES[args.destination_record_type]


    # SNMP worker

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

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

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

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

                except IndexError:
                    next_oid = cb_ctx['lastOID']

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

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

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

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

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

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

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

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

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

            cb_ctx['errors'] += 1

            return

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

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

        stop_flag = False

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

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

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

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

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

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

                # Build .snmprec record

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

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

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

                    more_data_notification = exc

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

                        time.sleep(more_data_notification['period'])

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

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

                    stop_flag = True  # stop current iteration

                except error.NoDataNotification:
                    pass

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

                else:
                    args.output_file.write(line)

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

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

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

        # Continue walking
        return not stop_flag

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

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

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

    else:
        cmd_gen = cmdgen.NextCommandGenerator()

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

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

    started = time.time()

    try:
        snmp_engine.transportDispatcher.runDispatcher()

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

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

            try:
                handler = variation_module['shutdown']

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

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

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

        snmp_engine.transportDispatcher.closeDispatcher()

        started = time.time() - started

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

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

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

        return cb_ctx.get('errors', 0) and 1 or 0
Esempio n. 31
0
    def resolveWithMib(self, mibViewController):
        """Perform MIB variable ID conversion.

        Parameters
        ----------
        mibViewController : :py:class:`~pysnmp.smi.view.MibViewController`
            class instance representing MIB browsing functionality.

        Returns
        -------
        : :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity`
            reference to itself

        Raises
        ------
        SmiError
           In case of fatal MIB hanling errora

        Notes
        -----
        Calling this method might cause the following sequence of
        events (exact details depends on many factors):

        * ASN.1 MIB file downloaded and handed over to
          :py:class:`~pysmi.compiler.MibCompiler` for conversion into
          Python MIB module (based on pysnmp classes)
        * Python MIB module is imported by SNMP engine, internal indices
          created
        * :py:class:`~pysnmp.smi.view.MibViewController` looks up the
          rest of MIB identification information based on whatever information
          is already available, :py:class:`~pysnmp.smi.rfc1902.ObjectIdentity`
          class instance
          gets updated and ready for further use.

        Examples
        --------
        >>> objectIdentity = ObjectIdentity('SNMPv2-MIB', 'sysDescr')
        >>> objectIdentity.resolveWithMib(mibViewController)
        ObjectIdentity('SNMPv2-MIB', 'sysDescr')
        >>>

        """
        if self.__mibSourcesToAdd is not None:
            debug.logger & debug.flagMIB and debug.logger('adding MIB sources %s' % ', '.join(self.__mibSourcesToAdd))
            mibViewController.mibBuilder.addMibSources(
                *[ZipMibSource(x) for x in self.__mibSourcesToAdd]
            )
            self.__mibSourcesToAdd = None

        if self.__asn1SourcesToAdd is None:
            addMibCompiler(mibViewController.mibBuilder,
                           ifAvailable=True, ifNotAdded=True)
        else:
            debug.logger & debug.flagMIB and debug.logger(
                'adding MIB compiler with source paths %s' % ', '.join(self.__asn1SourcesToAdd))
            addMibCompiler(
                mibViewController.mibBuilder,
                sources=self.__asn1SourcesToAdd,
                searchers=self.__asn1SourcesOptions.get('searchers'),
                borrowers=self.__asn1SourcesOptions.get('borrowers'),
                destination=self.__asn1SourcesOptions.get('destination'),
                ifAvailable=self.__asn1SourcesOptions.get('ifAvailable'),
                ifNotAdded=self.__asn1SourcesOptions.get('ifNotAdded')
            )
            self.__asn1SourcesToAdd = self.__asn1SourcesOptions = None

        if self.__modNamesToLoad is not None:
            debug.logger & debug.flagMIB and debug.logger('loading MIB modules %s' % ', '.join(self.__modNamesToLoad))
            mibViewController.mibBuilder.loadModules(*self.__modNamesToLoad)
            self.__modNamesToLoad = None

        if self.__state & self.stClean:
            return self

        MibScalar, MibTableColumn = mibViewController.mibBuilder.importSymbols('SNMPv2-SMI', 'MibScalar',
                                                                               'MibTableColumn')

        self.__indices = ()

        if isinstance(self.__args[0], ObjectIdentity):
            self.__args[0].resolveWithMib(mibViewController)

        if len(self.__args) == 1:  # OID or label or MIB module
            debug.logger & debug.flagMIB and debug.logger('resolving %s as OID or label' % self.__args)
            try:
                # pyasn1 ObjectIdentifier or sequence of ints or string OID
                self.__oid = rfc1902.ObjectName(self.__args[0])  # OID
            except PyAsn1Error:
                # sequence of sub-OIDs and labels
                if isinstance(self.__args[0], (list, tuple)):
                    prefix, label, suffix = mibViewController.getNodeName(
                        self.__args[0]
                    )
                # string label
                elif '.' in self.__args[0]:
                    prefix, label, suffix = mibViewController.getNodeNameByOid(
                        tuple(self.__args[0].split('.'))
                    )
                # MIB module name
                else:
                    modName = self.__args[0]
                    mibViewController.mibBuilder.loadModules(modName)
                    if self.__kwargs.get('last'):
                        prefix, label, suffix = mibViewController.getLastNodeName(modName)
                    else:
                        prefix, label, suffix = mibViewController.getFirstNodeName(modName)

                if suffix:
                    try:
                        suffix = tuple([int(x) for x in suffix])
                    except ValueError:
                        raise SmiError('Unknown object name component %r' % (suffix,))
                self.__oid = rfc1902.ObjectName(prefix + suffix)
            else:
                prefix, label, suffix = mibViewController.getNodeNameByOid(
                    self.__oid
                )

            debug.logger & debug.flagMIB and debug.logger(
                'resolved %r into prefix %r and suffix %r' % (self.__args, prefix, suffix))

            modName, symName, _ = mibViewController.getNodeLocation(prefix)

            self.__modName = modName
            self.__symName = symName

            self.__label = label

            mibNode, = mibViewController.mibBuilder.importSymbols(
                modName, symName
            )

            self.__mibNode = mibNode

            debug.logger & debug.flagMIB and debug.logger('resolved prefix %r into MIB node %r' % (prefix, mibNode))

            if isinstance(mibNode, MibTableColumn):  # table column
                if suffix:
                    rowModName, rowSymName, _ = mibViewController.getNodeLocation(
                        mibNode.name[:-1]
                    )
                    rowNode, = mibViewController.mibBuilder.importSymbols(
                        rowModName, rowSymName
                    )
                    self.__indices = rowNode.getIndicesFromInstId(suffix)
            elif isinstance(mibNode, MibScalar):  # scalar
                if suffix:
                    self.__indices = (rfc1902.ObjectName(suffix),)
            else:
                if suffix:
                    self.__indices = (rfc1902.ObjectName(suffix),)
            self.__state |= self.stClean

            debug.logger & debug.flagMIB and debug.logger('resolved indices are %r' % (self.__indices,))

            return self
        elif len(self.__args) > 1:  # MIB, symbol[, index, index ...]
            # MIB, symbol, index, index
            if self.__args[0] and self.__args[1]:
                self.__modName = self.__args[0]
                self.__symName = self.__args[1]
            # MIB, ''
            elif self.__args[0]:
                mibViewController.mibBuilder.loadModules(self.__args[0])
                if self.__kwargs.get('last'):
                    prefix, label, suffix = mibViewController.getLastNodeName(self.__args[0])
                else:
                    prefix, label, suffix = mibViewController.getFirstNodeName(self.__args[0])
                self.__modName, self.__symName, _ = mibViewController.getNodeLocation(prefix)
            # '', symbol, index, index
            else:
                prefix, label, suffix = mibViewController.getNodeName(self.__args[1:])
                self.__modName, self.__symName, _ = mibViewController.getNodeLocation(prefix)

            mibNode, = mibViewController.mibBuilder.importSymbols(
                self.__modName, self.__symName
            )

            self.__mibNode = mibNode

            self.__oid = rfc1902.ObjectName(mibNode.getName())

            prefix, label, suffix = mibViewController.getNodeNameByOid(
                self.__oid
            )
            self.__label = label

            debug.logger & debug.flagMIB and debug.logger(
                'resolved %r into prefix %r and suffix %r' % (self.__args, prefix, suffix))

            if isinstance(mibNode, MibTableColumn):  # table
                rowModName, rowSymName, _ = mibViewController.getNodeLocation(
                    mibNode.name[:-1]
                )
                rowNode, = mibViewController.mibBuilder.importSymbols(
                    rowModName, rowSymName
                )
                if self.__args[2:]:
                    try:
                        instIds = rowNode.getInstIdFromIndices(*self.__args[2:])
                        self.__oid += instIds
                        self.__indices = rowNode.getIndicesFromInstId(instIds)
                    except PyAsn1Error:
                        raise SmiError('Instance index %r to OID convertion failure at object %r: %s' % (
                            self.__args[2:], mibNode.getLabel(), sys.exc_info()[1]))
            elif self.__args[2:]:  # any other kind of MIB node with indices
                if self.__args[2:]:
                    instId = rfc1902.ObjectName(
                        '.'.join([str(x) for x in self.__args[2:]])
                    )
                    self.__oid += instId
                    self.__indices = (instId,)
            self.__state |= self.stClean

            debug.logger & debug.flagMIB and debug.logger('resolved indices are %r' % (self.__indices,))

            return self
        else:
            raise SmiError('Non-OID, label or MIB symbol')
Esempio n. 32
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. 33
0
    log.setLogger(PROGRAM_NAME, *loggingMethod, force=True)

    if loggingLevel:
        log.setLevel(loggingLevel)

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

if isinstance(startOID, rfc1902.ObjectIdentity) or \
        isinstance(stopOID, rfc1902.ObjectIdentity):
    mibBuilder = builder.MibBuilder()

    mibViewController = view.MibViewController(mibBuilder)

    compiler.addMibCompiler(mibBuilder,
                            sources=mibSources or defaultMibSources)
    if isinstance(startOID, rfc1902.ObjectIdentity):
        startOID.resolveWithMib(mibViewController)
    if isinstance(stopOID, rfc1902.ObjectIdentity):
        stopOID.resolveWithMib(mibViewController)

# Load variation module

if variationModuleName:
    for variationModulesDir in confdir.variation:
        log.info('Scanning "%s" directory for variation modules...' %
                 variationModulesDir)
        if not os.path.exists(variationModulesDir):
            log.info('Directory "%s" does not exist' % variationModulesDir)
            continue
Esempio n. 34
0
def main():
    variation_module = None
    endpoints = {}
    contexts = {}

    stats = {
        'UDP packets': 0,
        'IP packets': 0,
        'bad packets': 0,
        'empty packets': 0,
        'unknown L2 protocol': 0,
        'SNMP errors': 0,
        'SNMP exceptions': 0,
        'agents seen': 0,
        'contexts seen': 0,
        'snapshots taken': 0,
        'Response PDUs seen': 0,
        'OIDs seen': 0
    }

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

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

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

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

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

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

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

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

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

    parser.add_argument(
        '--output-dir',
        metavar='<FILE>',
        type=str,
        default='.',
        help='SNMP simulation data directory to place captured traffic in '
        'form of simulation records. File names reflect traffic sources '
        'on the network.')

    variation_group.add_argument(
        '--transport-id-offset',
        type=int,
        default=0,
        help='When arranging simulation data files, start enumerating '
        'receiving transport endpoints from this number.')

    traffic_group = parser.add_argument_group('Traffic capturing options')

    traffic_group.add_argument(
        '--packet-filter',
        type=str,
        default='udp and src port 161',
        help='Traffic filter (in tcpdump syntax) to use for picking SNMP '
        'packets out of the rest of the traffic.')

    variation_group.add_argument('--listen-interface',
                                 type=str,
                                 help='Listen on this network interface.')

    parser.add_argument(
        '--promiscuous-mode',
        action='store_true',
        help='Attempt to switch NIC to promiscuous mode. Depending on the '
        'network, this may make traffic of surrounding machines visible. '
        'Might require superuser privileges.')

    parser.add_argument(
        '--capture-file',
        metavar='<FILE>',
        type=str,
        help='PCAP file with SNMP simulation data file to read from '
        'instead of listening on a NIC.')

    args = parser.parse_args()

    if not pcap:
        sys.stderr.write(
            'ERROR: pylibpcap package is missing!\r\nGet it by running '
            '`pip install '
            'https://downloads.sourceforge.net/project/pylibpcap/pylibpcap'
            '/0.6.4/pylibpcap-0.6.4.tar.gz`'
            '\r\n')
        parser.print_usage(sys.stderr)
        return 1

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

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

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

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

    if (isinstance(args.start_object, rfc1902.ObjectIdentity)
            or isinstance(args.stop_object, rfc1902.ObjectIdentity)):
        mib_builder = builder.MibBuilder()

        mib_view_controller = view.MibViewController(mib_builder)

        compiler.addMibCompiler(mib_builder, sources=args.mib_sources)

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

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

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

    # Load variation module

    if args.variation_module:

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

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

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

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

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

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

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

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

    # Variation module initialization

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

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

        handler = variation_module['init']

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

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

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

    pcap_obj = pcap.pcapObject()

    if args.listen_interface:
        if not args.quiet:
            log.info('Listening on interface %s in %spromiscuous '
                     'mode' % (args.listen_interface,
                               '' if args.promiscuous_mode else 'non-'))

        try:
            pcap_obj.open_live(args.listen_interface, 65536,
                               args.promiscuous_mode, 1000)

        except Exception as exc:
            log.error('Error opening interface %s for snooping: '
                      '%s' % (args.listen_interface, exc))
            return 1

    elif args.capture_file:
        if not args.quiet:
            log.info('Opening capture file %s' % args.capture_file)

        try:
            pcap_obj.open_offline(args.capture_file)

        except Exception as exc:
            log.error('Error opening capture file %s for reading: '
                      '%s' % (args.capture_file, exc))
            return 1

    else:
        sys.stderr.write(
            'ERROR: no capture file or live interface specified\r\n')
        parser.print_usage(sys.stderr)
        return 1

    if args.packet_filter:
        if not args.quiet:
            log.info('Applying packet filter \"%s\"' % args.packet_filter)

        pcap_obj.setfilter(args.packet_filter, 0, 0)

    if not args.quiet:
        log.info('Processing records from %still '
                 '%s' %
                 ('the beginning ' if args.start_object else args.start_object,
                  args.stop_object if args.stop_object else 'the end'))

    def parse_packet(raw):
        pkt = {}

        # http://www.tcpdump.org/linktypes.html
        ll_headers = {0: 4, 1: 14, 108: 4, 228: 0}

        if pcap_obj.datalink() in ll_headers:
            raw = raw[ll_headers[pcap_obj.datalink()]:]

        else:
            stats['unknown L2 protocol'] += 1

        pkt['version'] = (ord(raw[0]) & 0xf0) >> 4
        pkt['header_len'] = ord(raw[0]) & 0x0f
        pkt['tos'] = ord(raw[1])
        pkt['total_len'] = socket.ntohs(struct.unpack('H', raw[2:4])[0])
        pkt['id'] = socket.ntohs(struct.unpack('H', raw[4:6])[0])
        pkt['flags'] = (ord(raw[6]) & 0xe0) >> 5
        pkt['fragment_offset'] = socket.ntohs(
            struct.unpack('H', raw[6:8])[0] & 0x1f)
        pkt['ttl'] = ord(raw[8])
        pkt['protocol'] = ord(raw[9])
        pkt['checksum'] = socket.ntohs(struct.unpack('H', raw[10:12])[0])
        pkt['source_address'] = pcap.ntoa(struct.unpack('i', raw[12:16])[0])
        pkt['destination_address'] = pcap.ntoa(
            struct.unpack('i', raw[16:20])[0])

        if pkt['header_len'] > 5:
            pkt['options'] = raw[20:4 * (pkt['header_len'] - 5)]

        else:
            pkt['options'] = None

        raw = raw[4 * pkt['header_len']:]

        if pkt['protocol'] == 17:
            pkt['source_port'] = socket.ntohs(struct.unpack('H', raw[0:2])[0])
            pkt['destination_port'] = socket.ntohs(
                struct.unpack('H', raw[2:4])[0])
            raw = raw[8:]
            stats['UDP packets'] += 1

        pkt['data'] = raw
        stats['IP packets'] += 1

        return pkt

    def handle_snmp_message(d, t, private={}):
        msg_ver = api.decodeMessageVersion(d['data'])

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

        else:
            stats['bad packets'] += 1
            return

        try:
            rsp_msg, whole_msg = decoder.decode(d['data'],
                                                asn1Spec=p_mod.Message())

        except PyAsn1Error:
            stats['bad packets'] += 1
            return

        if rsp_msg['data'].getName() == 'response':
            rsp_pdu = p_mod.apiMessage.getPDU(rsp_msg)
            error_status = p_mod.apiPDU.getErrorStatus(rsp_pdu)

            if error_status:
                stats['SNMP errors'] += 1

            else:
                endpoint = d['source_address'], d['source_port']

                if endpoint not in endpoints:
                    endpoints[endpoint] = udp.domainName + (
                        args.transport_id_offset + len(endpoints), )
                    stats['agents seen'] += 1

                context = '%s/%s' % (p_mod.ObjectIdentifier(
                    endpoints[endpoint]),
                                     p_mod.apiMessage.getCommunity(rsp_msg))

                if context not in contexts:
                    contexts[context] = {}
                    stats['contexts seen'] += 1

                context = '%s/%s' % (p_mod.ObjectIdentifier(
                    endpoints[endpoint]),
                                     p_mod.apiMessage.getCommunity(rsp_msg))

                stats['Response PDUs seen'] += 1

                if 'basetime' not in private:
                    private['basetime'] = t

                for oid, value in p_mod.apiPDU.getVarBinds(rsp_pdu):
                    if oid < args.start_object:
                        continue

                    if args.stop_object and oid >= args.stop_object:
                        continue

                    if oid in contexts[context]:
                        if value != contexts[context][oid]:
                            stats['snapshots taken'] += 1

                    else:
                        contexts[context][oid] = [], []

                    contexts[context][oid][0].append(t - private['basetime'])
                    contexts[context][oid][1].append(value)

                    stats['OIDs seen'] += 1

    def handle_packet(pktlen, data, timestamp):
        if not data:
            stats['empty packets'] += 1
            return

        handle_snmp_message(parse_packet(data), timestamp)

    try:
        if args.listen_interface:
            log.info('Listening on interface "%s", kill me when you '
                     'are done.' % args.listen_interface)

            while True:
                pcap_obj.dispatch(1, handle_packet)

        elif args.capture_file:
            log.info('Processing capture file "%s"....' % args.capture_file)

            args = pcap_obj.next()

            while args:
                handle_packet(*args)
                args = pcap_obj.next()

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

    finally:
        data_file_handler = SnmprecRecord()

        for context in contexts:
            ext = os.path.extsep
            ext += RECORD_TYPES[args.destination_record_type].ext

            filename = os.path.join(args.output_dir, context + ext)

            if not args.quiet:
                log.info('Creating simulation context %s at '
                         '%s' % (context, filename))

            try:
                os.mkdir(os.path.dirname(filename))

            except OSError:
                pass

            record = RECORD_TYPES[args.destination_record_type]

            try:
                output_file = record.open(filename, 'wb')

            except IOError as exc:
                log.error('writing %s: %s' % (filename, exc))
                return 1

            count = total = iteration = 0
            time_offset = 0
            req_time = time.time()

            oids = sorted(contexts[context])
            oids.append(oids[-1])  # duplicate last OID to trigger stopFlag

            while True:
                for oid in oids:

                    timeline, values = contexts[context][oid]

                    value = values[min(
                        len(values) - 1,
                        bisect.bisect_left(timeline, time_offset))]

                    if value.tagSet in (rfc1905.NoSuchObject.tagSet,
                                        rfc1905.NoSuchInstance.tagSet,
                                        rfc1905.EndOfMibView.tagSet):
                        stats['SNMP exceptions'] += 1
                        continue

                    # remove value enumeration

                    if value.tagSet == Integer32.tagSet:
                        value = Integer32(value)

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

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

                    # Build .snmprec record

                    ctx = {
                        'origOid': oid,
                        'origValue': value,
                        'count': count,
                        'total': total,
                        'iteration': iteration,
                        'reqTime': req_time,
                        'startOID': args.start_object,
                        'stopOID': args.stop_object,
                        'stopFlag': oids.index(oid) == len(oids) - 1,
                        'variationModule': variation_module
                    }

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

                    except error.MoreDataNotification as exc:
                        count = 0
                        iteration += 1

                        moreDataNotification = exc
                        if 'period' in moreDataNotification:
                            time_offset += moreDataNotification['period']
                            log.info(
                                '%s OIDs dumped, advancing time window to '
                                '%.2f sec(s)...' % (total, time_offset))
                        break

                    except error.NoDataNotification:
                        pass

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

                    else:
                        output_file.write(line)

                        count += 1
                        total += 1

                else:
                    break

            output_file.flush()
            output_file.close()

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

            handler = variation_module['shutdown']

            try:
                handler(options=args.variation_module_options,
                        mode='recording')

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

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

        log.info("""\
PCap statistics:
    packets snooped: %s
    packets dropped: %s
    packets dropped: by interface %s\
    """ % pcap_obj.stats())

        log.info("""\
SNMP statistics:
    %s\
    """ % '    '.join(['%s: %s\r\n' % kv for kv in stats.items()]))

    return 0