One of the most useful tools for exploring the structure of an SNMP MIB is the snmptranslate utility provided in the net-analyzer/net-snmp package. As you can see from the example below the snmptranslate utility can be used to produce a "tree" describing the structure of an SNMP MIB, in this case the structure of the SMARTCTL-MIB used to represent harddisk SMART data.
+--smartCtl(1) | +--smartCtlMIB(1) | +--smartCtlTable(2) | +--smartCtlEntry(1) | Index: smartCtlDeviceIndex | +-- -R-- Integer32 smartCtlDeviceIndex(1) | Range: 0..65535 +-- -R-- String smartCtlDeviceDev(2) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- String smartCtlDeviceModelFamily(3) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- String smartCtlDeviceDeviceModel(4) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- String smartCtlDeviceSerialNumber(5) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- String smartCtlDeviceUserCapacity(6) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- String smartCtlDeviceATAVersion(7) | Textual Convention: DisplayString | Size: 0..255 +-- -R-- EnumVal smartCtlDeviceHealthOK(8) | Textual Convention: TruthValue | Values: true(1), false(2) +-- -R-- Gauge smartCtlDeviceTemperatureCelsius(9) +-- -R-- Gauge smartCtlDeviceReallocatedSectorCt(10) +-- -R-- Gauge smartCtlDeviceCurrentPendingSector(11) +-- -R-- Gauge smartCtlDeviceOfflineUncorrectable(12) +-- -R-- Gauge smartCtlDeviceUDMACRCErrorCount(13) +-- -R-- Gauge smartCtlDeviceReadErrorRate(14) +-- -R-- Gauge smartCtlDeviceSeekErrorRate(15) +-- -R-- Gauge smartCtlDeviceHardwareECCRecovered(16)
The snmptranslate utility may also be used to resolve the numeric OID when passed a MIB name and MIB entry, as shown below.
.1.3.6.1.4.1.38696.2.1
You can see from the above example that the SMARTCTL-MIB root element (named smartCtl) is located nine levels down (there are nine groups of numbers) in the complete MIB tree.
.1.3.6.1.4.1.38696.2.1.2
As the above command demonstrates each additional level in the above tree adds another dotted decimal number to the end of the numeric OID.
The net-analyzer/net-snmp package also provides another useful utility, the snmpwalk application, which may be used to "walk" the MIB tree from a specified starting location. As you can see from the output below the "walk" ends when there are no more entries below the starting address.
.1.3.6.1.4.1.38696.2.1.2.1.1.1 = INTEGER: 1 .1.3.6.1.4.1.38696.2.1.2.1.1.2 = INTEGER: 2 .1.3.6.1.4.1.38696.2.1.2.1.1.3 = INTEGER: 3 .1.3.6.1.4.1.38696.2.1.2.1.1.4 = INTEGER: 4 .1.3.6.1.4.1.38696.2.1.2.1.2.1 = STRING: /dev/sda .1.3.6.1.4.1.38696.2.1.2.1.2.2 = STRING: /dev/sdb .1.3.6.1.4.1.38696.2.1.2.1.2.3 = STRING: /dev/sdc .1.3.6.1.4.1.38696.2.1.2.1.2.4 = STRING: /dev/sdd .1.3.6.1.4.1.38696.2.1.2.1.3.1 = STRING: Seagate Barracuda 7200.7 and 7200.7 Plus family .1.3.6.1.4.1.38696.2.1.2.1.3.2 = STRING: Seagate Barracuda 7200.7 and 7200.7 Plus family .1.3.6.1.4.1.38696.2.1.2.1.3.3 = STRING: Seagate Barracuda 7200.7 and 7200.7 Plus family .1.3.6.1.4.1.38696.2.1.2.1.3.4 = STRING: Seagate Barracuda 7200.7 and 7200.7 Plus family .1.3.6.1.4.1.38696.2.1.2.1.4.1 = STRING: ST3160827AS .1.3.6.1.4.1.38696.2.1.2.1.4.2 = STRING: ST3160827AS .1.3.6.1.4.1.38696.2.1.2.1.4.3 = STRING: ST3160827AS .1.3.6.1.4.1.38696.2.1.2.1.4.4 = STRING: ST3160827AS .1.3.6.1.4.1.38696.2.1.2.1.5.1 = STRING: 4MT00KR4 .1.3.6.1.4.1.38696.2.1.2.1.5.2 = STRING: 5MT0CG5Q .1.3.6.1.4.1.38696.2.1.2.1.5.3 = STRING: 5MT0CG9Y .1.3.6.1.4.1.38696.2.1.2.1.5.4 = STRING: 5MT0CG7J .1.3.6.1.4.1.38696.2.1.2.1.6.1 = STRING: 160,041,885,696 bytes .1.3.6.1.4.1.38696.2.1.2.1.6.2 = STRING: 160,041,885,696 bytes .1.3.6.1.4.1.38696.2.1.2.1.6.3 = STRING: 160,041,885,696 bytes .1.3.6.1.4.1.38696.2.1.2.1.6.4 = STRING: 160,041,885,696 bytes .1.3.6.1.4.1.38696.2.1.2.1.7.1 = STRING: 6 .1.3.6.1.4.1.38696.2.1.2.1.7.2 = STRING: 6 .1.3.6.1.4.1.38696.2.1.2.1.7.3 = STRING: 6 .1.3.6.1.4.1.38696.2.1.2.1.7.4 = STRING: 6 .1.3.6.1.4.1.38696.2.1.2.1.8.1 = INTEGER: true(1) .1.3.6.1.4.1.38696.2.1.2.1.8.2 = INTEGER: true(1) .1.3.6.1.4.1.38696.2.1.2.1.8.3 = INTEGER: true(1) .1.3.6.1.4.1.38696.2.1.2.1.8.4 = INTEGER: true(1) .1.3.6.1.4.1.38696.2.1.2.1.9.1 = Gauge32: 39 .1.3.6.1.4.1.38696.2.1.2.1.9.2 = Gauge32: 38 .1.3.6.1.4.1.38696.2.1.2.1.9.3 = Gauge32: 40 .1.3.6.1.4.1.38696.2.1.2.1.9.4 = Gauge32: 39 .1.3.6.1.4.1.38696.2.1.2.1.10.1 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.10.2 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.10.3 = Gauge32: 1 .1.3.6.1.4.1.38696.2.1.2.1.10.4 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.11.1 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.11.2 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.11.3 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.11.4 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.12.1 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.12.2 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.12.3 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.12.4 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.13.1 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.13.2 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.13.3 = Gauge32: 15 .1.3.6.1.4.1.38696.2.1.2.1.13.4 = Gauge32: 0 .1.3.6.1.4.1.38696.2.1.2.1.14.1 = Gauge32: 44 .1.3.6.1.4.1.38696.2.1.2.1.14.2 = Gauge32: 55 .1.3.6.1.4.1.38696.2.1.2.1.14.3 = Gauge32: 46 .1.3.6.1.4.1.38696.2.1.2.1.14.4 = Gauge32: 47 .1.3.6.1.4.1.38696.2.1.2.1.15.1 = Gauge32: 54 .1.3.6.1.4.1.38696.2.1.2.1.15.2 = Gauge32: 54 .1.3.6.1.4.1.38696.2.1.2.1.15.3 = Gauge32: 54 .1.3.6.1.4.1.38696.2.1.2.1.15.4 = Gauge32: 54 .1.3.6.1.4.1.38696.2.1.2.1.16.1 = Gauge32: 50 .1.3.6.1.4.1.38696.2.1.2.1.16.2 = Gauge32: 61 .1.3.6.1.4.1.38696.2.1.2.1.16.3 = Gauge32: 52 .1.3.6.1.4.1.38696.2.1.2.1.16.4 = Gauge32: 53
Examining the above output we can see that tabular data is represented using four additional dotted-decimal numbers. The first of these identifies the table in question, as you can see in the table below the smartCtlTable has a numeric identifier of two. The next dotted-decimal number identifies the entry in the table. As you can see below the smartCtlTable table has only a single type of entry which has been assigned the numeric identifier one. The next two numbers represent the column identifier and the index respectively.
| BASE-OID | TABLE | ENTRY | COLUMN | INDEX | TYPE | VALUE
| | | | | | |
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .1 | .1 | INTEGER | 1
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .2 | .1 | STRING | /dev/sda
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .3 | .1 | STRING | Seagate Barracuda 7200.7 and 7200.7 Plus family
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .4 | .1 | STRING | ST3160827AS
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .5 | .1 | STRING | 4MT00KR4
| | | | | | |
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .14 | .1 | Gauge32 | 44
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .15 | .1 | Gauge32 | 54
| .1.3.6.1.4.1.38696.2.1 | .2 | .1 | .16 | .1 | Gauge32 | 50
In the next section we shall demonstrate how the above MIB structure may be simply encoded using Bash arrays so that the snmpd-connector-lib library can take care of all the difficult work of generating and decoding numeric OIDs. We shall also examine how the index values are provided and how MIB specific functions can be created to enable the data to be correctly retrieved and returned to the SNMP daemon.