Using PySNMP as Trap Receiver with own/vendor MIB - python

I try to use PySNMP to receive SNMPv3 Traps. I found this example code:
#!/usr/bin/env /usr/bin/python3
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity.rfc3413 import ntfrcv
from pysnmp.proto.api import v2c
from pysnmp.smi.rfc1902 import ObjectIdentity
snmpEngine = engine.SnmpEngine()
# Transport setup
# UDP over IPv4
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode(('0.0.0.0', 162)),
)
# SNMPv3/USM setup
config.addV3User(
snmpEngine, '<username>',
config.usmHMACMD5AuthProtocol, '<password>',
config.usmAesCfb128Protocol, '<password>',
securityEngineId=v2c.OctetString(hexValue='<engineid>')
)
def cbFun(snmpEngine, stateReference, contextEngineId, contextName,
varBinds, cbCtx):
print('Notification from ContextEngineId "%s", ContextName "%s"' (contextEngineId.prettyPrint(), contextName.prettyPrint()))
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
# Register SNMP Application at the SNMP engine
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
# Run I/O dispatcher which would receive queries and send confirmations
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
This code works for me, but i get the raw Traps. I have an vendor specific MIB File I want to use. But I can't find any documentation how to bind the mib to the snmpEngine. The examples using MIBs from the PySNMP documentation show only the usage for SNMP GET operations and are not applicable here.
Has someone tried this before and can help me?
Thanks!

If your goal is to resolve raw variable-bindings you receive into human-friendly form, then you need to process those variable-bindings through the MIB browser object.
You are right, that's exactly the same operation that command generator frequently performs in the examples.
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 that define objects we receive in TRAPs
mibBuilder.loadModules('SNMPv2-MIB', 'SNMP-COMMUNITY-MIB')
# This is what we would get in a 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')
]
# Pass raw var-binds through MIB browser
varBinds = [
rfc1902.ObjectType(rfc1902.ObjectIdentity(x[0]), x[1]).resolveWithMib(mibViewController)
for x in varBinds
]
for varBind in varBinds:
print(varBind.prettyPrint())

Related

How to get SNMP OID Values in Cisco Router with Authentication

Am writing a Sample code below for fetching Cisco Switch Information through SNMP for the python pysnmp module.
after executing below code am getting 'No SNMP response received before timeout'.
from pysnmp.entity.rfc3413.oneliner import cmdgen
import time
#SNMP agent address
SNMP_AGENT_HOST = 'IPADDRESS' # IP adderess
#SNMP default port
SNMP_PORT = 161
#Add SNMP agent community here
SNMP_COMMUNITY = 'public'
cmdGen = cmdgen.CommandGenerator()
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(SNMP_COMMUNITY),
cmdgen.UdpTransportTarget((SNMP_AGENT_HOST, SNMP_PORT)),
'1.3.6.1.4.1.9.2.1.56.0', # Cisco Switch OID
'1.3.6.1.4.1.9.2.1.57.0' #
)
# Check for errors and print out results
if errorIndication:
print(errorIndication)
else:
if errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1] or '?'
)
)
else:
for name, val in varBinds:
print('%s = %s' % (name.prettyPrint(), val.prettyPrint()))
I getting the result
No SNMP response received before timeout
I want to be fetch all OID related Information through the GET call.
Your quickest way of diagnosing this is to use an EXISTING utility that you know works, and try it against that IPADDRESS with the authentication that you think should work.
If that utility, eg. NET-SNMP snmpwalk or snmpgetnext, does not work, then your problem is likely not in your code, but your understanding of how to access the SNMP agent. Eg. are you certain the community string "public" works?
It is ALWAYS better to work from success, than to interpolate from failure.

Pysnmp can't resolve OID's from snmp trap

I'm trying to resolve the OIDs that are received on an SNMP Trap from an HP switch stack but they only resolve down to a certain level and stop. It's like the HP MIBs are not being loaded. It's unclear from all the documentation I can find on pysnmp if this is the appropriate way to add custom MIBs and resolve OIDs from a trap.
MIBs can be downloaded here.
from pysnmp.entity import engine, config
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.smi import view, builder, rfc1902
from pysnmp.entity.rfc3413 import ntfrcv, mibvar
# Create SNMP engine with autogenernated engineID and pre-bound
# to socket transport dispatcher
snmpEngine = engine.SnmpEngine()
build = snmpEngine.getMibBuilder()
build.addMibSources(builder.DirMibSource("C:/Users/t/Documents/mibs"))
viewer = view.MibViewController(build)
# Transport setup
# UDP over IPv4, first listening interface/port
config.addTransport(
snmpEngine,
udp.domainName + (1,),
udp.UdpTransport().openServerMode(('0.0.0.0', 162))
)
# SNMPv1/2c setup
# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, '????', 'public')
# Callback function for receiving notifications
# noinspection PyUnusedLocal,PyUnusedLocal,PyUnusedLocal
def cbFun(snmpEngine, stateReference, contextEngineId, contextName, varBinds, cbCtx):
print('Notification from ContextEngineId "%s", ContextName "%s"' % (contextEngineId.prettyPrint(),
contextName.prettyPrint()))
for name, val in varBinds:
print(name)
symbol = rfc1902.ObjectIdentity(name).resolveWithMib(viewer).getMibSymbol()
print(symbol[1])
# Register SNMP Application at the SNMP engine
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish
# Run I/O dispatcher which would receive queries and send confirmations
try:
snmpEngine.transportDispatcher.runDispatcher()
except:
snmpEngine.transportDispatcher.closeDispatcher()
raise
Output upon receiving a trap:
Notification from ContextEngineId "0x80004fb8056ed891e8", ContextName ""
1.3.6.1.2.1.1.3.0
sysUpTime
1.3.6.1.6.3.1.1.4.1.0
snmpTrapOID
1.3.6.1.6.3.18.1.3.0
snmpTrapAddress
1.3.6.1.6.3.18.1.4.0
snmpTrapCommunity
1.3.6.1.6.3.1.1.4.3.0
snmpTrapEnterprise
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.9
enterprises
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.0.1
enterprises
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.0.2
enterprises
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.0.3
enterprises
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.0.4
enterprises
1.3.6.1.4.1.11.2.14.11.5.1.7.1.29.1.0.5
enterprises
As you can see many distinct OIDs just resolve to "enterprises". I am using pysnmp 4.4.4.
Yes, it seems that only the core MIBs are loaded.
If you want to follow this quite low-level path, then you need to pre-compile all your ASN.1 MIBs (those you pulled from HPE site) with the mibdump tool into pysnmp format. Then put those *.py files into some directory and point pysnmp to it through build.addMibSources(builder.DirMibSource()) call.
Also, make sure to pre-load up all those MIBs at once on startup by invoking build.loadModules() (w/o arguments).

Get printer status with SNMP using Pysnmp

I try to get status from my printer using SNMP protocol
The problem is, I've never used the SNMP and I have trouble understanding how can I get my status like ( PAPER OUT, RIBBON OUT, etc... ).
I configured my printer to enable the SNMP protocol using the community name "public"
I presume SNMP messages are sent on the port 161
I'm using Pysnmp because I want to integrate the python script in my program to listen to my printer and display status if there is a problem with the printer.
For now I've tried this code :
import socket
import random
from struct import pack, unpack
from datetime import datetime as dt
from pysnmp.entity.rfc3413.oneliner import cmdgen
from pysnmp.proto.rfc1902 import Integer, IpAddress, OctetString
ip = '172.20.0.229'
community = 'public'
value = (1,3,6,1,2,1,25,3,5,1,2)
generator = cmdgen.CommandGenerator()
comm_data = cmdgen.CommunityData('server', community, 1) # 1 means version SNMP v2c
transport = cmdgen.UdpTransportTarget((ip, 161))
real_fun = getattr(generator, 'getCmd')
res = (errorIndication, errorStatus, errorIndex, varBinds) \
= real_fun(comm_data, transport, value)
if not errorIndication is None or errorStatus is True:
print "Error: %s %s %s %s" % res
else:
print "%s" % varBinds
The IP address is the IP of my printer
The problem is the OID: I don't know what to put in the OID field because I have trouble understanding how does OID work.
I found this page but I'm not sure it fits with all printers ==> click here
You need your printer specific MIB file in common case. E.g., printer in my office seems to be not support both oids by your link. Also you can use snmpwalk to get available oids and values on your printer and if you somehow understand which values you need, you can use it for specific instance of your printer.

pysnmp send timeout when called from django view

Im reitryng to get some kids from some network switch and for that im using a purepyton library called pysnmp. its installed w/o problems.
Used a sample code that works.
from pysnmp.entity.rfc3413.oneliner import cmdgen
cmdGen = cmdgen.CommandGenerator()
datos = []
ip = 'theipaddress'
comunidad_snmp = 'thecomunityv2c'
errorIndication, errorStatus, errorIndex, varBinds = cmdGen.getCmd(
cmdgen.CommunityData(comunidad_snmp),
cmdgen.UdpTransportTarget((ip, 161)),
'.1.3.6.1.2.1.1.1.0', # sysDescr.0
lookupNames=True, lookupValues=True
)
if errorIndication:
print(errorIndication)
elif errorStatus:
print(errorStatus)
else:
for name, val in varBinds:
datos.append({'nombre': name.prettyPrint(), 'valor': val.prettyPrint()})
print datos
our problem is that if I copy this code(as is) inside any view the result its always
"No SNMP response received before timeout"
is there something we need to add for this to work as expected?.
the environment is cents 6
Could it be that your SNMP/UDP queries from Django host get filtered while your command-line tests do not?
Digging deeper: your code invokes pysnmp with default, asyncore-based transport. If Django (or some of its components) somehow uses asyncore in a non-cooperative way, pysnmp/django systems may somehow interfere... A way to avoid such interference would be use your own map of pysnmp I/O socket objects like this:
...
from pysnmp.carrier.asynsock.dispatch import AsynsockDispatcher
cmdGen.snmpEngine.registerTransportDispatcher(AsynsockDispatcher())
mySockMap = {}
cmdGen.snmpEngine.transportDispatcher.setSocketMap(mySockMap)
...
Another idea is to enable pysnmp debugging to see what's going on there:
import sys
from pysnmp import debug
debug.setLogger(debug.Debug('all', printer=sys.stderr.write))
There are other, less verbose pysnmp debugging flags (see pysnmp.debug).

What is 'my-creds', 'my-area', and 'my-router' in these Python PySNMP codes?

I am new in using PySNMP module in Python. According to this user manual and this manual, the following python scripts perform similar things like the net-snmp command:
net-snmp v1 command:
snmpget -v1 -c public -ObentU 195.218.195.228 1.3.6.1.2.1.1.1.0
Python v1 script:
from twisted.internet import reactor, defer
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413.twisted import cmdgen
from pysnmp.carrier.twisted import dispatch
from pysnmp.carrier.twisted.dgram import udp
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()
# Instantiate and register Twisted dispatcher at SNMP engine
snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
#
# SNMPv1 setup
#
# SecurityName <-> CommunityName mapping
config.addV1System(snmpEngine, 'my-area', 'public')
# Specify security settings per SecurityName (SNMPv1 - 0, SNMPv2c - 1)
config.addTargetParams(snmpEngine, 'my-creds', 'my-area', 'noAuthNoPriv', 0)
#
# Setup transport endpoint and bind it with security settings yielding
# a target name
#
# UDP/IPv4
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpTwistedTransport().openClientMode()
)
config.addTargetAddr(
snmpEngine, 'my-router',
udp.domainName, ('195.218.195.228', 161),
'my-creds'
)
# Error/response receiver
def cbFun(cbCtx):
(errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
if errorIndication:
print(errorIndication)
# SNMPv1 response may contain noSuchName error *and* SNMPv2c exception,
# so we ignore noSuchName error here
elif errorStatus and errorStatus != 2:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
)
)
else:
for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
reactor.stop()
# Prepare request to be sent yielding Twisted deferred object
df = cmdgen.GetCommandGenerator().sendReq(
snmpEngine,
'my-router',
( ('1.3.6.1.2.1.1.1.0', None), ('1.3.6.1.2.1.1.2.0', None) ),
)
# Register error/response receiver function at deferred
df.addCallback(cbFun)
# Run Twisted main loop
reactor.run()
net-snmp v3 command:
snmpget -v3 -l authPriv -u usr-sha-aes -a SHA -A authkey1 -x AES -X privkey1 -ObentU 195.218.195.228:161 1.3.6.1.2.1.1.1.0
Python v3 script:
from twisted.internet import reactor, defer
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413.twisted import cmdgen
from pysnmp.carrier.twisted import dispatch
from pysnmp.carrier.twisted.dgram import udp
# Create SNMP engine instance
snmpEngine = engine.SnmpEngine()
# Instantiate and register Twisted dispatcher at SNMP engine
snmpEngine.registerTransportDispatcher(dispatch.TwistedDispatcher())
#
# SNMPv3/USM setup
#
# user: usr-sha-aes, auth: SHA, priv AES
config.addV3User(
snmpEngine, 'usr-sha-aes',
config.usmHMACSHAAuthProtocol, 'authkey1',
config.usmAesCfb128Protocol, 'privkey1'
)
config.addTargetParams(snmpEngine, 'my-creds', 'usr-sha-aes', 'authPriv')
#
# Setup transport endpoint and bind it with security settings yielding
# a target name
#
# UDP/IPv4
config.addSocketTransport(
snmpEngine,
udp.domainName,
udp.UdpTwistedTransport().openClientMode()
)
config.addTargetAddr(
snmpEngine, 'my-router',
udp.domainName, ('195.218.195.228', 161),
'my-creds'
)
# Error/response receiver
def cbFun(cbCtx):
(errorIndication, errorStatus, errorIndex, varBinds) = cbCtx
if errorIndication:
print(errorIndication)
elif errorStatus:
print('%s at %s' % (
errorStatus.prettyPrint(),
errorIndex and varBinds[int(errorIndex)-1][0] or '?'
)
)
else:
for oid, val in varBinds:
print('%s = %s' % (oid.prettyPrint(), val.prettyPrint()))
reactor.stop()
# Prepare request to be sent yielding Twisted deferred object
df = cmdgen.GetCommandGenerator().sendReq(
snmpEngine,
'my-router',
( ('1.3.6.1.2.1.1.1.0', None), ),
)
# Register error/response receiver function at deferred
df.addCallback(cbFun)
# Run Twisted main loop
reactor.run()
In the above net-snmp commands, you can see that there is no 'my-creds', 'my-area', and 'my-router' parameters. However, these parameters are used in the Python scripts.
May I know what is 'my-creds', 'my-area', and 'my-router' in these Python PySNMP scripts?
In SNMP (not just pysnmp), system configuration is scattered across several 'SNMP tables'. They are defined in their respective MIBs and their rows can be logically linked one with the other by columnar names.
In the end you can refer to all SNMP configuration details for a particular SNMP peer via a single ID. Also, you can re-use common parts of SNMP configuration for multiple distinct peers.
In most pysnmp scripts you can spot the following tables and their relations:
securityName + securityLevel + snmpMessageProcessingModel (3) -> snmpTargetParameters (see SNMP-TARGET-MIB::snmpTargetParams)
securityName + communityName + snmpMessageVersion (1|2c) -> snmpTargetParameters (see SNMP-COMMUNITY-MIB::snmpCommunity)
snmpTargetParameters + targetAddress + timeout + retries -> snmpTarget (see SNMP-TARGET-MIB::snmpTargetAddr)
So snmpTarget (e.g. 'my-router') is the top-level ID that can be referred to when requesting SNMP application (like Command Generator) to send SNMP request to specific peer via specific SNMP version and with specific credentials.
One of the features of this configuration model (for at least for SNMP Agent situation) is that it can be managed remotely through SNMP.

Categories

Resources