Skip to content
HenkPoley edited this page Jun 16, 2020 · 10 revisions

This page will show you how to write your own MIBs using the System MIB and the Interface MIB as an example. Ensure you have reviewed the Using MIBs page first.

Note that 'writing MIBs' does not mean getting textual output in the ASN.1 format.

MIB Names and Locations

Generic MIBs defining standard functionality can be placed in OSS_SNMP/MIBs. Vendor specific MIBs should be placed in their own directories (such as OSS_SNMP/MIBs/Cisco/VTP).

MIB File Structure

All MIB files should define a license, a namespace and an appropriate class:

<?php

/*
    Copyright (c) 2012, Open Source Solutions Limited, Dublin, Ireland
    All rights reserved.

    Contact: Barry O'Donovan - barry (at) opensolutions (dot) ie
             http://www.opensolutions.ie/

    This file is part of the OSS_SNMP package.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

        * Redistributions of source code must retain the above copyright
          notice, this list of conditions and the following disclaimer.
        * Redistributions in binary form must reproduce the above copyright
          notice, this list of conditions and the following disclaimer in the
          documentation and/or other materials provided with the distribution.
        * Neither the name of Open Source Solutions Limited nor the
          names of its contributors may be used to endorse or promote products
          derived from this software without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

namespace OSS_SNMP\MIBS;

/**
 * A class for performing SNMP V2 queries on generic devices
 *
 * @copyright Copyright (c) 2012, Open Source Solutions Limited, Dublin, Ireland
 * @author Barry O'Donovan <barry@opensolutions.ie>
 */
class System extends \OSS_SNMP\MIB
{
    // ....
}

Unless there are genuine reasons otherwise, all contributions of MIBs should be licensed as per the above New BSD License, or an equivalent BSD or MIT license. MIBs are small pieces of code and the GNU GPL or similar copyleft licenses. (NB - we are not anti-GPL, in fact one of our projects is licensed as GPL - see ViMbAdmin).

Creating Simple Scalar 'get' Functionality

MIB files are really quite simply. Typically they define OID constants and functions to use these to query an SNMP host.

So, let's take the SNMP system contact as an example. Most / all SNMP implementations allow one to define the system contact such as the following in net-snmpd:

syscontact Open Solutions NOC <noc@example.ie>

We would typically query this via snmpget as follows with the result:

$ snmpget -On -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.1.4.0
.1.3.6.1.2.1.1.4.0 = STRING: "Open Solutions NOC <noc@example.ie>"

So, to build this functionality into our MIB we first define the OID:

    const OID_SYSTEM_UPTIME      = '.1.3.6.1.2.1.1.3.0';

and then create a properly documented function to query it:

/**
 * Returns the system contact of the device
 *
 * @return string The system contact of the device
 */
public function contact()
{
    return $this->getSNMP()->get( self::OID_SYSTEM_CONTACT );
}

And that's it! We can now use this system MIB in our PHP applications via:

echo $snmpHost->useSystem()->contact();

Creating Array / SNMP 'walk' Functionality

In most cases, we generally walk an OID to get multiple values - such as the number of octets all network interfaces have received. For this, we'll look at such an example in the Interface MIB.

The relevant OID is:

    const OID_IF_IN_OCTETS               = '.1.3.6.1.2.1.2.2.1.10';

If we walked this on the command line, we'd get:

$ snmpwalk -On -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.2.2.1.10
.1.3.6.1.2.1.2.2.1.10.1 = Counter32: 200805632
.1.3.6.1.2.1.2.2.1.10.2 = Counter32: 292181999
.1.3.6.1.2.1.2.2.1.10.3 = Counter32: 2185395302

A function for this would be:

/**
 * Get an array of device interface in octets
 *
 * "The total number of octets received on the
 * interface, including framing characters."
 *
 * @return array The total number of octets received on interfaces
 */
public function inOctets()
{
    return $this->getSNMP()->walk1d( self::OID_IF_IN_OCTETS );
}

which returns an array indexed by port ID (the last element in the OID as shown in the above snmpwalk output) containing the integer values:

Array
(
    [1] => 200805632
    [2] => 292181999
    [3] => 2185395302
)

The nice thing about PHP 5.4 is that we can dereference the returned array as follows:

$inoctets = $snmpHost->useIface()->inOctets()[2]; // $inoctets = 292181999

Creating Functionality with Translations for Types / States / etc

A common SNMP response is an integer representing a type or state of something. Once example is the administrative state of an interface. It is either up (enabled), down (disabled) or testing. The OID for interface admin states is:

    const OID_IF_ADMIN_STATUS            = '.1.3.6.1.2.1.2.2.1.7';

Walking this yields:

$ snmpwalk -On -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.2.2.1.7
.1.3.6.1.2.1.2.2.1.7.1 = INTEGER: 1
.1.3.6.1.2.1.2.2.1.7.2 = INTEGER: 1
...
.1.3.6.1.2.1.2.2.1.7.7 = INTEGER: 2

With the right MIBs installed, this might be translated as:

$ snmpwalk -m all -v 2c -c public 127.0.0.1 .1.3.6.1.2.1.2.2.1.7
RFC1213-MIB::ifAdminStatus.1 = INTEGER: up(1)
RFC1213-MIB::ifAdminStatus.2 = INTEGER: up(1)
RFC1213-MIB::ifAdminStatus.3 = INTEGER: down(2)

So, in OSS_SNMP we'd first define the OID as above and then we'd define the possible return values:

/**
 * Constant for possible value of interface admin status.
 * @see adminStates()
 */
const IF_ADMIN_STATUS_UP = 1;

/**
 * Constant for possible value of interface admin status.
 * @see adminStates()
 */
const IF_ADMIN_STATUS_DOWN = 2;

/**
 * Constant for possible value of interface admin status.
 * @see adminStates()
 */
const IF_ADMIN_STATUS_TESTING = 3;

We'd also define an array to translate these values:

/**
 * Text representation of interface admin status.
 *
 * @see adminStates()
 * @var array Text representations of interface admin status.
 */
public static $IF_ADMIN_STATES = array(
    self::IF_ADMIN_STATUS_UP      => 'up',
    self::IF_ADMIN_STATUS_DOWN    => 'down',
    self::IF_ADMIN_STATUS_TESTING => 'testing'
);

Lastly, we'd define a translation capable function:

/**
 * Get an array of device interface admin status (up / down)
 *
 * @see IF_ADMIN_STATES
 * @param boolean $translate If true, return the string representation
 * @return array An array of interface admin states
 */
public function adminStates( $translate = false )
{
    $states = $this->getSNMP()->walk1d( self::OID_IF_ADMIN_STATUS );

    if( !$translate )
        return $states;

    return $this->getSNMP()->translate( $states, self::$IF_ADMIN_STATES );
}

The function translate() is just a utility function in SNMP that can take an array of values to translate or a scalar value to translate.

Contributing MIBs

We'd love to build up a huge library of MIBs. The easiest way is to just open a pull request and we'll check the code and license and then pull it over.

When contributing, please:

  • ensure you are using a BSD / MIT / similar license;
  • that you code is clean and tidy and properly documented (with phpDoc);
  • while we haven't done it (yet) it might be an idea if the class comment included a reference to the SNMP OID/MIB documentation / specification that the file covers;
  • ensure you have a proper copyright line for your file.

If in doubt, email us or open a ticket.