lextudio/pysnmp

Unable to Load MIB file and Walk

Closed this issue · 7 comments

Hi everyone.

I am trying to walk through our HSM device using MIB file but I am unable to do that.

import asyncio
from pysnmp.hlapi.v3arch.asyncio import *

async def snmp_walk(ip, mib_oid, username, auth_protocol, auth_password, priv_protocol, priv_password):
    snmp_engine = SnmpEngine()
    auth_data = UsmUserData(username, auth_password, priv_password,
                            authProtocol=auth_protocol,
                            privProtocol=priv_protocol)
    transport_target = await UdpTransportTarget.create((ip, 16161))
    context_data = ContextData()

    async for errorIndication, errorStatus, errorIndex, varBinds in walk_cmd(
        snmp_engine,
        auth_data,
        transport_target,
        context_data,
        ObjectType(ObjectIdentity(mib_oid))
    ):
        if errorIndication:
            print(f"Error: {errorIndication}")
            break
        elif errorStatus:
            print(f"Error: {errorStatus.prettyPrint()} at {errorIndex and varBinds[int(errorIndex) - 1][0] or '?'}")
            break
        else:
            for varBind in varBinds:
                print(' = '.join([x.prettyPrint() for x in varBind]))


ip_address = '<device-ip>'
username = '<username>'
auth_password = '<auth-pass>'
priv_password = '<priv-pass>'

auth_protocol = usmHMACSHAAuthProtocol
priv_protocol = usmDESPrivProtocol

asyncio.run(snmp_walk(ip_address, '.1.3.6.1.2.1.1.1.0', username, auth_protocol, auth_password, priv_protocol, priv_password))

I got MIB file that I can read (it's not compiled) in the same directory as this script. When I run the script, this is the output:

SNMPv2-SMI::mib-2.1.2.0 = 1.3.6.1.4.1.36787.1
SNMPv2-SMI::mib-2.1.3.0 = 26118900
SNMPv2-SMI::mib-2.1.4.0 = support@futurex.com
SNMPv2-SMI::mib-2.1.5.0 = FX1829835512
SNMPv2-SMI::mib-2.1.6.0 = 
SNMPv2-SMI::mib-2.1.7.0 = 64
SNMPv2-SMI::enterprises.36787.1.3.1.1 = 1829835512
SNMPv2-SMI::enterprises.36787.1.3.1.2 = 7.6.1.7-29E9
SNMPv2-SMI::enterprises.36787.1.3.1.3 = 6.1.15-5039
SNMPv2-SMI::enterprises.36787.1.3.2.1 = online
SNMPv2-SMI::enterprises.36787.1.3.2.2 = 2500
SNMPv2-SMI::enterprises.36787.1.3.2.3 = 5
SNMPv2-SMI::enterprises.36787.1.3.2.4 = 2
SNMPv2-SMI::enterprises.36787.1.3.2.5 = 1
SNMPv2-SMI::enterprises.36787.1.3.2.6 = 2
SNMPv2-SMI::enterprises.36787.1.3.2.7 = 5
SNMPv2-SMI::enterprises.36787.1.3.2.8 = 4
SNMPv2-SMI::enterprises.36787.1.3.2.9 = 4
SNMPv2-SMI::enterprises.36787.1.3.2.10 = 0
SNMPv2-SMI::enterprises.36787.1.3.2.11 = 0
SNMPv2-SMI::enterprises.36787.1.3.3.1 = 41
SNMPv2-SMI::enterprises.36787.1.3.3.2 = 5.86
SNMPv2-SMI::enterprises.36787.1.3.3.3 = 13.2675
SNMPv2-SMI::enterprises.36787.1.3.3.4 = 1070028
SNMPv2-SMI::enterprises.36787.1.3.3.5 = 6995004
SNMPv2-SMI::enterprises.36787.1.3.3.6 = 0.0.0.0
SNMPv2-SMI::enterprises.36787.1.3.3.7 = 0.0.0.0
SNMPv2-SMI::enterprises.36787.1.3.3.8 = 
SNMPv2-SMI::enterprises.36787.1.3.3.9 = 
SNMPv2-SMI::enterprises.36787.1.3.3.10 = 
SNMPv2-SMI::enterprises.36787.1.3.3.11 = 2024-11-18T17:13:23Z
SNMPv2-SMI::enterprises.36787.1.3.3.12 = Good
SNMPv2-SMI::enterprises.36787.1.3.3.13 = Good
SNMPv2-SMI::enterprises.36787.1.3.4.1.3.1 = 10.77.22.154
SNMPv2-SMI::enterprises.36787.1.3.4.1.4.0 = 255.255.252.0
SNMPv2-SMI::enterprises.36787.1.3.4.1.4.1 = 255.255.252.0
SNMPv2-SMI::enterprises.36787.1.3.4.1.5.0 = 10.77.48.1
SNMPv2-SMI::enterprises.36787.1.3.4.1.5.1 = 10.77.20.1
SNMPv2-SMI::enterprises.36787.1.3.4.1.6.0 = MANAGEMENT,PRODUCTION
SNMPv2-SMI::enterprises.36787.1.3.4.1.6.1 = MANAGEMENT,PRODUCTION
SNMPv2-SMI::enterprises.36787.1.3.4.1.7.0 = 1
SNMPv2-SMI::enterprises.36787.1.3.4.1.7.1 = 1

I've tried using add_asn1_mib_source and add_mib_source but I think I was doing something wrong as it didn't work. Sometimes with an error that mib cannot be found and sometimes without any error, it just returned the same output as you see above.

The problem is that I don't understand the way those functions should be used and the docs are not very helpful (the docs are even missing any info about walk or next commands).

Is there anyone who would be able to tell me how to pass the MIB the file and walk properly please? Also different solutions would be very much appreciated, I'll try them all.

Thank you!

Update on what I have tried today:

Adding compiler via snmp like so:

mib_builder = builder.MibBuilder()
mib_builder.add_mib_sources(builder.DirMibSource(os.getcwd())) 
compiler.add_mib_compiler(mib_builder, sources=['file://' + os.getcwd()])
mib_builder.load_modules('FX-HSM-MIB')
mib_view_controller = view.MibViewController(mib_builder)

it seems the compiler cannot find the file even though my directory is set correctly (see hsm-connect one)

pysnmp.smi.error.MibNotFoundError: FX-HSM-MIB compilation error(s): missing; missing; missing; missing; no module "SNMPv2-SMI" in symbolTable at MIB FX-HSM-MIB caused by <class 'pysnmp.smi.error.MibNotFoundError'>: MIB file "FX-HSM-MIB.py[co]" not found in search path (DirMibSource('C:\\Users\\fab5a4z\\AppData\\Roaming\\Python\\Python311\\site-packages\\pysnmp\\smi\\mibs'), DirMibSource('C:\\Users\\fab5a4z\\AppData\\Roaming\\Python\\Python311\\site-packages\\pysnmp\\smi\\mibs\\instances'), DirMibSource('pysnmp_mibs'), DirMibSource('C:\\Users\\fab5a4z\\gitrepos\\hsm-connect'), DirMibSource('C:\\Users\\fab5a4z\\PySNMP Configuration\\mibs'))

Pre-Compiling Attempt

So after that I tried to pre-compile the MIB instead by using the mibdump tool by running:

 mibdump --destination-directory=compiled_mibs --mib-source=. FX-HSM-MIB

This returns:

Source MIB repositories: .
Borrow missing/failed MIBs from: https://mibs.pysnmp.com:443/mibs/notexts/@mib@
Existing/compiled MIB locations: pysnmp.smi.mibs, pysnmp_mibs
Compiled MIBs destination directory: compiled_mibs
MIBs excluded from code generation: INET-ADDRESS-MIB, PYSNMP-USM-MIB, RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI, RFC1158-MIB, RFC1213-MIB, SNMP-FRAMEWORK-MIB, SNMP-TARGET-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM, TRANSPORT-ADDRESS-MIB
MIBs to compile: FX-HSM-MIB
Destination format: pysnmp
Custom destination template: None
Parser grammar cache directory: not used
Also compile all relevant MIBs: yes
Rebuild MIBs regardless of age: no
Dry run mode: no
Create/update MIBs: yes
Byte-compile Python modules: yes (optimization level no)
Ignore compilation errors: no
Generate OID->MIB index: no
Generate texts in MIBs: no
Keep original texts layout: no
Try various file names while searching for MIB module: yes
Created/updated MIBs: 
Pre-compiled MIBs borrowed:
Up to date MIBs:
Missing source MIBs: RFC1155-SMI
 SNMPv2-CONF
 SNMPv2-SMI
 SNMPv2-TC
Ignored MIBs:
Failed MIBs: FX-HSM-MIB (no module "SNMPv2-SMI" in symbolTable at MIB FX-HSM-MIB)

Which means it didn't work. I've tried different variations of the command but no luck. Also, I tried adding --debug=all which gave me an error saying AttributeError: 'Debug' object has no attribute 'getCurrentLogger'. Did you mean: 'get_current_logger'? which means that the debugger's API changed but it is not reflected in the tool.

I'd be very thankful for any kind of help. Thank you!

Hello! Just a quick note:

Missing source MIBs: RFC1155-SMI
SNMPv2-CONF
SNMPv2-SMI
SNMPv2-TC

Your MIB includes those other MIBs, and therefore, the MIB compiler needs access to those included MIBs as well. Both your attempts are failing on the fact that the included MIBs cannot be found.

Seeing as the MIB borrowing system is currently non-functional, you will need to download those four MIBs yourself and put them in a directory that is being searched (e.g., the same directory as FX-HSM-MIB). You can get the missing MIBs yourself from here, for example.

Hey! Yeah, I just did that 20 minutes ago from https://github.com/haad/net-snmp/tree/master/mibs and it seems to be working. The compilation happens. Let me try if the output of the SNMP call is correct and I'll write here the result right after.

So I compiled the MIB file I need (the FX-HSM-MIB one) and I got the compiled file saved under /compiled_mibs. The other ones were not compiled but used for compiling the FX-HSM-MIB I think.

The issue is that I am still getting the same response without the proper property names.

import asyncio, os
from pysnmp.hlapi.v3arch.asyncio import *
from pysnmp.smi import builder, view

mib_builder = builder.MibBuilder()
mib_builder.add_mib_sources(builder.DirMibSource(os.getcwd() + '/compiled_mibs'))
mib_builder.load_modules('FX-HSM-MIB')
mib_view_controller = view.MibViewController(mib_builder)

async def snmp_walk(ip, mib_oid, username, auth_protocol, auth_password, priv_protocol, priv_password):
    snmp_engine = SnmpEngine()
    auth_data = UsmUserData(username, auth_password, priv_password,
                            authProtocol=auth_protocol,
                            privProtocol=priv_protocol)
    transport_target = await UdpTransportTarget.create((ip, 16161))
    context_data = ContextData()

    async for errorIndication, errorStatus, errorIndex, varBinds in walk_cmd(
        snmp_engine,
        auth_data,
        transport_target,
        context_data,
        ObjectType(ObjectIdentity(mib_oid).resolve_with_mib(mib_view_controller))
    ):
        if errorIndication:
            print(f"Error: {errorIndication}")
            break
        elif errorStatus:
            print(f"Error: {errorStatus.prettyPrint()} at {errorIndex and varBinds[int(errorIndex) - 1][0] or '?'}")
            break
        else:
            for varBind in varBinds:
                print(' = '.join([x.prettyPrint() for x in varBind]))


ip_address = ''
username = ''
auth_password = ''
priv_password = ''

auth_protocol = usmHMACSHAAuthProtocol
priv_protocol = usmDESPrivProtocol

asyncio.run(snmp_walk(ip_address, '.1.3.6.1.2.1.1.1.0', username, auth_protocol, auth_password, priv_protocol, priv_password))

The terminal print:

SNMPv2-SMI::mib-2.1.2.0 = 1.3.6.1.4.1.36787.1
SNMPv2-SMI::mib-2.1.3.0 = 625100
SNMPv2-SMI::mib-2.1.4.0 = support@futurex.com
SNMPv2-SMI::mib-2.1.5.0 = FX1829835512
SNMPv2-SMI::mib-2.1.6.0 = 
SNMPv2-SMI::mib-2.1.7.0 = 64
SNMPv2-SMI::enterprises.36787.1.3.1.1 = 1829835512
SNMPv2-SMI::enterprises.36787.1.3.1.2 = 7.6.1.7-29E9
SNMPv2-SMI::enterprises.36787.1.3.1.3 = 6.1.15-5039
SNMPv2-SMI::enterprises.36787.1.3.2.1 = online
SNMPv2-SMI::enterprises.36787.1.3.2.2 = 2500
SNMPv2-SMI::enterprises.36787.1.3.2.3 = 4
SNMPv2-SMI::enterprises.36787.1.3.2.4 = 2
SNMPv2-SMI::enterprises.36787.1.3.2.5 = 0
SNMPv2-SMI::enterprises.36787.1.3.2.6 = 2
SNMPv2-SMI::enterprises.36787.1.3.2.11 = 0
SNMPv2-SMI::enterprises.36787.1.3.3.1 = 42
SNMPv2-SMI::enterprises.36787.1.3.3.2 = 3.91
SNMPv2-SMI::enterprises.36787.1.3.3.3 = 6.23095
SNMPv2-SMI::enterprises.36787.1.3.3.4 = 502528
SNMPv2-SMI::enterprises.36787.1.3.3.5 = 7562496
SNMPv2-SMI::enterprises.36787.1.3.3.6 = 0.0.0.0
SNMPv2-SMI::enterprises.36787.1.3.3.7 = 0.0.0.0
SNMPv2-SMI::enterprises.36787.1.3.3.8 = 
SNMPv2-SMI::enterprises.36787.1.3.3.9 = 
SNMPv2-SMI::enterprises.36787.1.3.3.10 = 
SNMPv2-SMI::enterprises.36787.1.3.3.11 = 2024-11-19T15:37:36Z
SNMPv2-SMI::enterprises.36787.1.3.3.12 = Good
SNMPv2-SMI::enterprises.36787.1.3.3.13 = Good
SNMPv2-SMI::enterprises.36787.1.3.4.1.2.0 = Ethernet 1
SNMPv2-SMI::enterprises.36787.1.3.4.1.2.0 = Ethernet 1
SNMPv2-SMI::enterprises.36787.1.3.4.1.2.1 = Ethernet 2
SNMPv2-SMI::enterprises.36787.1.3.4.1.2.1 = Ethernet 2
SNMPv2-SMI::enterprises.36787.1.3.4.1.2.1 = Ethernet 2
SNMPv2-SMI::enterprises.36787.1.3.4.1.3.0 = 10.77.48.98
SNMPv2-SMI::enterprises.36787.1.3.4.1.3.1 = 10.77.22.154
SNMPv2-SMI::enterprises.36787.1.3.4.1.4.0 = 255.255.252.0
SNMPv2-SMI::enterprises.36787.1.3.4.1.4.1 = 255.255.252.0
SNMPv2-SMI::enterprises.36787.1.3.4.1.5.0 = 10.77.48.1
SNMPv2-SMI::enterprises.36787.1.3.4.1.5.1 = 10.77.20.1
SNMPv2-SMI::enterprises.36787.1.3.4.1.6.0 = MANAGEMENT,PRODUCTION
SNMPv2-SMI::enterprises.36787.1.3.4.1.6.1 = MANAGEMENT,PRODUCTION
SNMPv2-SMI::enterprises.36787.1.3.4.1.7.0 = 1
SNMPv2-SMI::enterprises.36787.1.3.4.1.7.1 = 1

EDIT: I am attaching the command for compiling the MIB too:

mibdump --destination-directory=compiled_mibs --mib-source=./mibs --destination-format=pysnmp FX-HSM-MIB.txt

@dcvmoole do you have any idea what could be wrong please?

The other ones were not compiled but used for compiling the FX-HSM-MIB I think.

The others are all part of the pysnmp base MIBs, which means that their compiled versions are included with pysnmp itself. As such, that is indeed expected behavior in this case.

@dcvmoole do you have any idea what could be wrong please?

I'm afraid I do not, sorry. This is a part of pysnmp with which I am not (yet) familiar.

For what it is worth: your issue sounds similar to #89.

Wow, thanks @dcvmoole, that worked!!

instead of using resolve_with_mib I just added snmp_engine.cache["mibViewController"] = mib_view_controller as Lex suggested.

so the full code now is:

import asyncio, os
from pysnmp.hlapi.v3arch.asyncio import *
from pysnmp.smi import builder, view

mib_builder = builder.MibBuilder()
mib_builder.add_mib_sources(builder.DirMibSource(os.getcwd() + '/compiled_mibs'))
mib_builder.load_modules('FX-HSM-MIB')
mib_view_controller = view.MibViewController(mib_builder)

async def snmp_walk(ip, mib_oid, username, auth_protocol, auth_password, priv_protocol, priv_password):
    snmp_engine = SnmpEngine()
    snmp_engine.cache["mibViewController"] = mib_view_controller

    auth_data = UsmUserData(username, auth_password, priv_password,
                            authProtocol=auth_protocol,
                            privProtocol=priv_protocol)
    transport_target = await UdpTransportTarget.create((ip, 16161))
    context_data = ContextData()

    async for errorIndication, errorStatus, errorIndex, varBinds in walk_cmd(
        snmp_engine,
        auth_data,
        transport_target,
        context_data,
        ObjectType(ObjectIdentity(mib_oid))
    ):
        if errorIndication:
            print(f"Error: {errorIndication}")
            break
        elif errorStatus:
            print(f"Error: {errorStatus.prettyPrint()} at {errorIndex and varBinds[int(errorIndex) - 1][0] or '?'}")
            break
        else:
            for varBind in varBinds:
                print(' = '.join([x.prettyPrint() for x in varBind]))


ip_address = '.com'
username = ''
auth_password = ''
priv_password = ''

auth_protocol = usmHMACSHAAuthProtocol 
priv_protocol = usmDESPrivProtocol

asyncio.run(snmp_walk(ip_address, '.1.3.6.1.2.1.1.1.0', username, auth_protocol, auth_password, priv_protocol, priv_password))

I tried with the compiler as originally planned but that seems to be broken. So pre-compiling is the way I'll go with for now. Thank you again.

Glad to hear!