Questions & Answers — Java API Usage

Q1: How do I load a MIB file?

MIB files are loaded by the MibLoader class. This class allows loading MIB files in various ways – by file name, MIB name or from within zip files. Mibble comes bundled with the standard IANA and IETF MIB files to avoid separate downloads, etc.

Below is a simplified example for loading a single MIB file:

import net.percederberg.mibble.*;

public Mib loadMib(File file)
    throws FileNotFoundException, MibLoaderException {

    // In real code, a single MibLoader instance should be reused
    MibLoader loader = new MibLoader();

    // The MIB file may import other MIBs (often in same dir)
    loader.addDir(file.getParentFile());

    // Once initialized, MIB loading is straight-forward
    return loader.load(file);
}

Q2: How does the MibLoader search for MIB files?

The MibLoader class searches for MIB files in the following order:

  1. File names in the search path — The search path is a list of directories where the MibLoader looks for files having the same name as the MIB module to be loaded. The comparison is made on case-insensitive file name, ignoring file extensions.
  2. Files in the resource path — The resource path is a list of directories for Java ClassLoader resources. The MibLoader looks for a resource with the exact MIB module name in each of these directories.
  3. File content in the search path — As a final measure all files in the search path are opened and the first few lines are read to identify their MIB module names. This search is generally slow and should be avoided.

Q3: How do I get the OID from a MibSymbol?

The OID is represented by an ObjectIdentifierValue instance. These can be found as the value of a MibValueSymbol, but note that all values are not OIDs.

Below is a simple example for retrieving the OID using the instanceof operator:

import net.percederberg.mibble.*;
import net.percederberg.mibble.value.*;

public ObjectIdentifierValue extractOid(MibSymbol symbol) {
    if (symbol instanceof MibValueSymbol) {
        MibValue value = ((MibValueSymbol) symbol).getValue();
        if (value instanceof ObjectIdentifierValue) {
            return (ObjectIdentifierValue) value;
        }
    }
    return null;
}

Q4: How do I find a symbol from an OID?

There are two main options. If you already know the MIB from which the OID belongs, use the Mib.getSymbolByOid() method. Otherwise, use MibLoader.getRootOid() to retrieve the iso instance and call ObjectIdentifierValue.find() to locate the closest matching instance (among the currently loaded MIBs).

The example below shows the general method (as of Mibble 2.10):

import net.percederberg.mibble.*;
import net.percederberg.mibble.value.*;

public MibValueSymbol locateSymbolByOid(MibLoader loader, String oid) {
    ObjectIdentifierValue iso = loader.getRootOid();
    ObjectIdentifierValue match = iso.find(oid);
    return (match == null) ? null : match.getSymbol();
}

Q5: How do I walk the OID tree?

The ObjectIdentifierValue class represents the OID tree structure. It also provides methods for for retrieving the parent and child OIDs, making it possible to traverse the whole OID tree (across MIBs).

If you only wish to traverse the OID tree for a certain MIB, use Mib.getRootSymbol() and traverse downward in the OID tree from there. See the example code below for the details:

import net.percederberg.mibble.*;
import net.percederberg.mibble.value.*;

public void walkOidTree(Mib mib) {
    MibValueSymbol symbol = mib.getRootSymbol();
    MibValue value = (symbol == null) ? null : symbol.getValue();
    if (value instanceof ObjectIdentifierValue) {
        walkOidTree(mib, (ObjectIdentifierValue) value);
    }
}

private void walkOidTree(Mib mib, ObjectIdentifierValue oid) {
    MibValueSymbol symbol = oid.getSymbol();
    if (symbol != null && symbol.getMib() != mib) {
        return; // External MIB attached here
    }
    // <-- Process OID here
    for (int i = 0; i < oid.getChildCount(); i++) {
        walkOid(mib, oid.getChild(i));
    }
}

Q6: How do I know the type of a MibSymbol?

First use the instanceof operator to check for either a MibTypeSymbol or a MibValueSymbol instance. Then call getType() to get the MibType instance. The exact subtype can then be established in one of the following ways:

If you wish to find the SNMP macro type of a symbol, use the instanceof method. SNMP macro types generally have no type tags.

To determine the exact SYNTAX of an OBJECT-TYPE, use the type tag method. This makes is possible to distinguish between different INTEGER types like TimeTick, Counter32 and Gauge32. See Q7 below for details.

Q7: How do I recognize an IpAddress or TimeTick type?

The MibTypeTag allows distinguishing between the base INTEGER or OCTET STRING types and their specializations. The former are only tagged UNIVERSAL, whereas the latter have unique APPLICATION type tags.

Lookup the appropriate APPLICATION type tag in either RFC1155-SMI or SNMPv2-SMI. Then use the MibType.hasTag() method in your code. See the code below for some simple examples:

import net.percederberg.mibble.*;

public boolean isIpAddress(MibType type) {
    // IpAddress ::= [APPLICATION 0]
    return type.hasTag(MibTypeTag.APPLICATION_CATEGORY, 0);
}

public boolean isTimeTicks(MibType type) {
    // TimeTicks ::= [APPLICATION 3]
    return type.hasTag(MibTypeTag.APPLICATION_CATEGORY, 3);
}

Q8: How do I distinguish between Gauge32 and Unsigned32?

Normally it is not necessary to distinguish between the Gauge32 and Unsigned32 types as they have the same definition and are therefore identical when sent over the wire. In some cases, it may be useful to distinguish between them in an SNMP manager for semantical reasons.

Both types share the [APPLICATION 2] type tag, so the only option is to use the MibType.hasReferenceTo() method which tracks the reference chain of a type. See the code below for an example:

import net.percederberg.mibble.*;

public boolean isGauge32(MibType type) {
    // Gauge32 ::= [APPLICATION 2]
    return type.hasTag(MibTypeTag.APPLICATION_CATEGORY, 2) &&
           type.hasReferenceTo("Gauge32");
}

public boolean isUnsigned32(MibType type) {
    // Unsigned32 ::= [APPLICATION 2]
    return type.hasTag(MibTypeTag.APPLICATION_CATEGORY, 2) &&
           type.hasReferenceTo("Unsigned32");
}

Q9: How do I get the fields from an OBJECT-TYPE symbol?

Use the instanceof operator to verify that the symbol is a MibValueSymbol with an SnmpObjectType type. The latter class provides accessor methods to all the relevant fields. See the example code below:

import net.percederberg.mibble.*;
import net.percederberg.mibble.snmp.*;

public SnmpObjectType getSnmpObjectType(MibSymbol symbol) {
    if (symbol instanceof MibValueSymbol) {
        MibType type = ((MibValueSymbol) symbol).getType();
        if (type instanceof SnmpObjectType) {
            return (SnmpObjectType) type;
        }
    }
    return null;
}

Q10: How do I get the value definitions for a bitset or an enumeration?

The BitSetType and IntegerType can both be constrained to an enumerated set of values. The values are retrieved by calling the getAllSymbols() method, which returns an unordered array of enumeration symbols. See the code below for an example:

import net.percederberg.mibble.*;
import net.percederberg.mibble.type.*;

public HashMap<Number,String> getEnumerationValues(IntegerType type) {
    MibValueSymbol[] symbols = type.getAllSymbols();
    HashMap<Number,String> res = new HashMap<>(symbols.length);
    for (int i = 0; i < symbols.length; i++) {
        String name = symbols[i].getName();
        Object value = symbols[i].getValue().toObject();
        if (value instanceof Number) {
            res.put((Number) value, name);
        }
    }
    return res;
}