SNMP Cuddletech Reference. ------------------------- Tool -> UCD-SNMP (aka NET-SNMP) URL: http://net-snmp.sourceforge.net/ Useful RFCs: Directory Server Monitoring MIB http://www.ietf.org/rfc/rfc2605.txt Concise MIB Definitions http://davinci.hio.hen.nl/cgi-bin/show-gz/rfc/snmp/rfc1212.txt.gz Management Information Base v2 http://davinci.hio.hen.nl/cgi-bin/show-gz/rfc/snmp/rfc1450.txt.gz SNMP Management Frameworks http://www.ietf.org/rfc/rfc2571.txt Useful FAQ: Net_SNMP FAQ: http://net-snmp.sourceforge.net/FAQ.html Net-SNMP provides two tools that you're interested in: snmpget and snmpwalk. Before you can use them, you should add any MIBS you'll need. You can add MIBS by downloading the approiate file and placing it in the /usr/local/share/snmp/mibs directory. All MIBS should have the extention .txt. I've inserted a NetApp Filer mib in this manner: -rw-r--r-- 1 root root 296280 Dec 12 15:56 netapp_1_5.mib lrwxrwxrwx 1 root root 14 Dec 12 15:57 NETWORK-APPLIANCE-MIB.txt -> netapp_1_5.mib The NetApp MIB is shipped (or downloaded from NOW) named netapp_1_5.mib, a link saved me from renaming the file. Definition of term MIB from RFC 2605: Managed objects are accessed via a virtual information store, termed the Management Information Base or MIB. Objects in the MIB are defined using the mechanisms defined in the SMI. Understand that to access SNMP values or variables you do not need a MIB. MIB's are little more than a naming scheme similar to DNS. You don't need hostnames or DNS to navigate the InterNet, however if you don't have DNS you'll need to know the exact IP of everywhere you want to go... the same concept applied to SNMP. Every varable supplied by an SNMP client will offer a number of OID's (Object Indentifier) in a numeric format. These numbers are "translated" into textual identifiers via information in the MIB. Using SNMP Get -------------- snmpget is a command offered with Net-SNMP. Here is an example of it's use: $export MIBS="+NETWORK-APPLIANCE-MIB" $snmpget -v 1 -Ov ralph public enterprises.netapp.netapp1.raid.diskSummary.diskFailedMessage.0 "There are no failed disks." $snmpget -v 1 -Ov ralph public enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 2 $ SYNTAX: snmpget -v 1 -Ov (host) (community) (oid) Where: "-v 1" means use SNMPv1 and "-Ov" means output values only, not OID = value Here's a look at an SNMP get without the -Ov: $snmpget -v 1 ralph public enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 = 2 Using SNMP Without MIBS ----------------------- The first thing to do is understand what you want. This can be done in a number of ways. One method is to discect the MIB and pullout the OID numbers you want and disregard the rest. Another is to use trial and error. Yet another is to simply walk the SNMP OID tree looking for what you want. $snmpget -v 1 -Of ralph public enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 .iso.org.dod.internet.private.enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 = 2 $snmpget -v 1 -Ofn ralph public enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 .1.3.6.1.4.1.789.1.6.4.8.0 = 2 $ Notice above, on the first line I've used SNMPget like before, but I've used the output option "f" to indicat that I want to see the FULL OID, not just the truncated part like before. In the second use of the command I used the output options "f" and "n" which give us the full OID and also to give us that OID in numberic format. Now that I've got the numberic representation of the OID for blah.diskSummary.diskSpareCount.0, lets try it again with the number OID: $snmpget -v 1 ralph public .1.3.6.1.4.1.789.1.6.4.8.0 enterprises.789.1.6.4.8.0 = 2 $ The above example, I didn't have my MIBS env var set, so it doesn't use the MIB at all, yet I can still check the OID. This can make the process of SNMP applications alittle more portable and easy, as they don't need the MIB. However, the MIB exsists for a reason. Portablility is one, ease is another, and currency is cheif. If NetApp updates their SNMP scheme, I should only need to update my MIB and be off and running. However if I hardcode all the OIDs, I'll have to rework the app I build just to keep monitoring. Using MIBS is the best choice. Anatomy of an OID ----------------- An OID is used in two forms, fully qualified and relevent. A fully qualified OID looks like this: .iso.org.dod.internet.private.enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 or numerically like this: .1.3.6.1.4.1.789.1.6.4.8.0 You can see from the output that the first portion of the OID is always going to be the same. Therefore, a fully qualified OID will have a ".iso.org.dod.internet.private" on it, while a relevant OID will only have the following ".enterprises.netapp.netapp1.raid.diskSummary.blah". In this case the .iso.org stuff is assumed. You'll also notice that the representation of ".netapp" is 789. Using SNMP Walk --------------- SNMP Walking is useful for looking at all the OIDs and their values below a given threshold. For instance, we've been using the blah.blah.diskSummary.diskSpareCount.0 OID for our tests. If we want to see all OIDs below the "DiskSummary", we can walk it from there. For instance: $snmpwalk -v 1 ralph public enterprises.netapp.netapp1.raid.diskSummary enterprises.netapp.netapp1.raid.diskSummary.diskTotalCount.0 = 84 enterprises.netapp.netapp1.raid.diskSummary.diskActiveCount.0 = 82 enterprises.netapp.netapp1.raid.diskSummary.diskReconstructingCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskReconstructingParityCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskVerifyingParityCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskScrubbingCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskFailedCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskSpareCount.0 = 2 enterprises.netapp.netapp1.raid.diskSummary.diskAddingSpareCount.0 = 0 enterprises.netapp.netapp1.raid.diskSummary.diskFailedMessage.0 = "There are no failed disks." $ Here's the same thing, but without the MIB: $snmpwalk -v1 ralph public .1.3.6.1.4.1.789.1.6.4 enterprises.789.1.6.4.1.0 = 84 enterprises.789.1.6.4.2.0 = 82 enterprises.789.1.6.4.3.0 = 0 enterprises.789.1.6.4.4.0 = 0 enterprises.789.1.6.4.5.0 = 0 enterprises.789.1.6.4.6.0 = 0 enterprises.789.1.6.4.7.0 = 0 enterprises.789.1.6.4.8.0 = 2 enterprises.789.1.6.4.9.0 = 0 enterprises.789.1.6.4.10.0 = "There are no failed disks." $ SNMP Walking can be used for a variety of reasons, chief among them is searching for the OID you want. As you can see from the 2 outputs above, walking without the MIB isn't nearly as productive. You can walk hosts in a default mode for standard information that is very useful. Here is an example, from a Solaris box: [benr@nexus nasparecheck]$ snmpwalk -v1 -Of solaris9 public | more .iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = Sun SNMP Agent, Sun-Blade-100 .iso.org.dod.internet.mgmt.mib-2.system.sysObjectID.0 = OID: .iso.org.dod.internet.private.enterprises.42.2.1.1 .iso.org.dod.internet.mgmt.mib-2.system.sysUpTime.0 = Timeticks: (68040820) 7 days, 21:00:08.20 .iso.org.dod.internet.mgmt.mib-2.system.sysContact.0 = System administrator .iso.org.dod.internet.mgmt.mib-2.system.sysName.0 = unknown .iso.org.dod.internet.mgmt.mib-2.system.sysLocation.0 = System administrators office .iso.org.dod.internet.mgmt.mib-2.system.sysServices.0 = 72 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifNumber.0 = 2 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.1 = 1 .iso.org.dod.internet.mgmt.mib-2.interfaces.ifTable.ifEntry.ifIndex.2 = 2 ....... etc .......... Notice that this is a diffrent OID domain, considered to be default. Almost all devices will answer to these. The mib-2 OID range is broken into these areas: ->system. ->interfaces ->at (Address Translation) ->ip ->icmp ->tcp ->udp ->snmp These implemented by RFC 1213, spec for MIB-II found here: ftp://ftp.isi.edu/in-notes/rfc1213.txt Exploring an SNMP Device ------------------------- When using a new device that you haven't used before you may have trouble determining where to start. The best option is to walk the device. By default, a walk will probe the mib-2 OIDs: [benr@nexus SNMP]$ snmpwalk -v 1 -c public 10.10.1.223 SNMPv2-MIB::sysDescr.0 = STRING: APC Web/SNMP Management Card SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.318.1.3.7 SNMPv2-MIB::sysUpTime.0 = Timeticks: (1096779) 3:02:47.79 SNMPv2-MIB::sysContact.0 = STRING: 123-123-1234 SNMPv2-MIB::sysName.0 = STRING: APC-1234 SNMPv2-MIB::sysLocation.0 = STRING: Someplace SNMPv2-MIB::sysServices.0 = INTEGER: 72 IF-MIB::ifNumber.0 = INTEGER: 1 IF-MIB::ifIndex.1 = INTEGER: 1 IF-MIB::ifDescr.1 = STRING: veya IF-MIB::ifType.1 = INTEGER: iso88023Csmacd(7) IF-MIB::ifMtu.1 = INTEGER: 0 IF-MIB::ifSpeed.1 = Gauge32: 10000000 ...... etc ..... In the previous example, we specified niether a MIB nor a OID path. We can look at the device specific information by searching the Enterprises OID, without the MIB: [benr@nexus SNMP]$ snmpwalk -v 1 -c public 10.10.1.223 .iso.org.dod.internet.private.enterprises SNMPv2-SMI::enterprises.318.1.1.1.1.1.1.0 = STRING: "Silcon DP320E" SNMPv2-SMI::enterprises.318.1.1.1.1.1.2.0 = STRING: "UPS_IDEN" ..... etc ....... SNMPv2-SMI::enterprises.318.2.4.2.3.3.0 = STRING: "apc" SNMPv2-SMI::enterprises.318.2.4.3.1.0 = INTEGER: 1 End of MIB [benr@nexus apc]$ We could have even used simply "enterprises" instead of the fully qualified ".iso.org.dod.internet.private.enterprises". If we have a MIB, we can then use it for a more full view, using the "-m" option, however when using a custom MIB we must use the fully qualified IOD. Note that the MIB is specified WITH a path!: [benr@nexus SNMP]$ snmpwalk -v 1 -c public 10.10.1.223 -m ./powernet.mib .iso.org.dod.internet.private.enterprises PowerNet-MIB::upsBasicIdentModel.0 = STRING: "Silcon DP320E" PowerNet-MIB::upsBasicIdentName.0 = STRING: "UPS_IDEN" PowerNet-MIB::upsAdvIdentFirmwareRevision.0 = STRING: "309.10.D" ... etc ... And remember that for a fully qualified OID for each object to use the "-Of" option, and for numberic output, "-Ofn". Useful for scripting is the "-Oqv" option, which outputs values numberically, rather than by name, eg: "batteryNormal(2)" vs "2". Therefore, lets look at one last example which prints the complete MIB fully qualified, and then do a simple get on the OID: [benr@nexus SNMP]$ snmpwalk -v 1 -c public 10.10.1.223 -Of -m ./powernet.mib .iso.org.dod.internet.private.enterprises.apc .iso.org.dod.internet.private.enterprises.apc.products.hardware.ups.upsIdent.upsBasicIdent.upsBasicIdentModel.0 = STRING: "Silcon DP320E" .iso.org.dod.internet.private.enterprises.apc.products.hardware.ups.upsIdent.upsBasicIdent.upsBasicIdentName.0 = STRING: "UPS_IDEN" .iso.org.dod.internet.private.enterprises.apc.products.hardware.ups.upsBattery.upsBasicBattery.upsBasicBatteryStatus.0 = INTEGER: batteryNormal(2) ............. [benr@nexus SNMP]$ snmpget -v 1 -c public 10.10.1.223 -Ofn -m ./powernet.mib .iso.org.dod.internet.private.enterprises.\ apc.products.hardware.ups.upsBattery.upsBasicBattery.upsBasicBatteryStatus.0 .1.3.6.1.4.1.318.1.1.1.2.1.1.0 = INTEGER: batteryNormal(2) [benr@nexus SNMP]$ snmpget -v 1 -c public -Oqv 10.10.1.223 .1.3.6.1.4.1.318.1.1.1.2.1.1.0 2 [benr@nexus SNMP]$ Using PERL the OLD way ---------- PERL is the ultimate tool to pair with SNMP. A simple way to get information from an SNMP OID into a useful app would be to simply to this: $ENV{'MIBS'}="+NETWORK-APPLIANCE-MIB"; my $HOST = "ralph"; my $COMMUNITY = "public"; chomp($STATUS = `snmpget -v 1 -Ov $HOST $COMMUNITY enterprises.netapp.netapp1.raid.diskSummary.diskFailedMessage.0`); print("Status of failed disks on $HOST is: $STATUS \n"); There are a number of varients you can build off of this. Another method would be to use the Net-SNMP PERL module. Here is a good link for info on the SNMP module: http://www.switch.ch/misc/leinen/snmp/perl/ Here is an example of using the SNMP_Session.pm module: use BER; require 'SNMP_Session.pm'; # Set $host to the name of the host whose SNMP agent you want # to talk to. Set $community to the community name under # which you want to talk to the agent. Set port to the UDP # port on which the agent listens (usually 161). $session = SNMP_Session->open ($host, $community, $port) || die "couldn't open SNMP session to $host"; # Set $oid1, $oid2... to the BER-encoded OIDs of the MIB # variables you want to get. if ($session->get_request_response ($oid1, $oid2, ...)) { ($bindings) = $session->decode_get_response ($session->{pdu_buffer}); while ($bindings ne '') { ($binding,$bindings) = &decode_sequence ($bindings); ($oid,$value) = &decode_by_template ($binding, "%O%@"); print &pretty_print ($oid)," => ", &pretty_print ($value), "\n"; } } else { die "No response from agent on $host"; } Using PERL the NEW Way (Net-SNMP) --------------------------------- Sample: ------------------------------ #!/usr/local/bin/perl use SNMP; $COMMUNITY = "public"; $ENV{'MIBFILES'}="extreme620.mib"; $SNMP::verbose = 1; $SNMP::use_enums=1; $SNMP::use_sprint_value=1; $SESSION = new SNMP::Session ( DestHost => $TARGET_HOST, Community => $COMMUNITY, Version => 1); $BOARD_VLIST = new SNMP::VarList(['extremeSystemID'], ['extremeSlotModuleConfiguredType'], ['extremeSlotModuleInsertedType'], ['extremeSlotModuleState']); @BOARD_LIST = $SESSION->getnext($BOARD_VLIST); ------------------------------ At this point you can start using the output varables found in @BOARD_LIST, ala: print("The system id is $BOARD_LIST[0]\n); The most try part of this all is how you load the MIB. You can use one of the following methods: 1) $ENV{'MIBFILES'}="extreme.mib"; When you use this method the file should be in the PWD and you should use the EXACT name for the file. 2) $ENV{'MIBS'}="ALL"; When you use this method you only need to put the MIB in the MIBS directory for NetSNMP which is usually /usr/local/share/snmp/mibs. The file can be named anything you want. 3) $ENV{'MIBS'}="+NETWORK-APPLIANCE-MIB"; If you use this method you must understand that you are not specifying the FILE to be used but the MIB. Meaning that all files in the MIBS directory will be scanned for the file MIB that matches the name you specify. You can find the name of the MIB in the first line of the MIB (the first non-commented, non-empty blank line, where comments are "--"), here is an example from the first line of the NetApp MIB (used in this example): NETWORK-APPLIANCE-MIB DEFINITIONS ::= BEGIN None of the other "clean" methods of loading (ie: via the module functions) have had any success. -------------------------------------------------------- NOTES: Walking: [benr@nexus extreme]$ snmpwalk -v 1 -c hs-user 10.10.0.240 -Of -m ./extreme620.mib enterprises.extremenetworks.extremeAgent.extremeSystem .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeSaveConfiguration.0 = INTEGER: saveToPrimary(1) .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeSaveStatus.0 = INTEGER: saveNotInProgress(2) .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeCurrentConfigInUse.0 = INTEGER: primary(1) .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeConfigToUseOnReboot.0 = INTEGER: primary(1) .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeOverTemperatureAlarm.0 = INTEGER: false(2) .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeCurrentTemperature.0 = INTEGER: 34 .iso.org.dod.internet.private.enterprises.extremenetworks.extremeAgent.extremeSystem.extremeSystemCommon.extremeFanStatusTable.extremeFanStatusEntry.extremeFanNumber.1 = INTEGER: 1 ------ or -------- [benr@nexus extreme]$ snmpwalk -v 1 -c hs-user 10.10.0.240 -m ./extreme620.mib enterprises.extremenetworks.extremeAgent.extremeSystem EXTREME-SYSTEM-MIB::extremeSaveConfiguration.0 = INTEGER: saveToPrimary(1) EXTREME-SYSTEM-MIB::extremeSaveStatus.0 = INTEGER: saveNotInProgress(2) EXTREME-SYSTEM-MIB::extremeCurrentConfigInUse.0 = INTEGER: primary(1) EXTREME-SYSTEM-MIB::extremeConfigToUseOnReboot.0 = INTEGER: primary(1) EXTREME-SYSTEM-MIB::extremeOverTemperatureAlarm.0 = INTEGER: false(2) EXTREME-SYSTEM-MIB::extremeCurrentTemperature.0 = INTEGER: 34 EXTREME-SYSTEM-MIB::extremeFanNumber.1 = INTEGER: 1 EXTREME-SYSTEM-MIB::extremeFanNumber.2 = INTEGER: 2 EXTREME-SYSTEM-MIB::extremeFanNumber.3 = INTEGER: 3 EXTREME-SYSTEM-MIB::extremeFanOperational.1 = INTEGER: true(1) --- ore ---- [benr@nexus scripts]$ snmpget -v1 -c hs-user 10.10.0.240 -m ./extreme620.mib EXTREME-SYSTEM-MIB::extremeSlotModuleSerialNumber.3 EXTREME-SYSTEM-MIB::extremeSlotModuleSerialNumber.3 = STRING: "7010xyz294"