Search documentation of snmpkit

# MIB Guide - SnmpKit

This guide covers working with Management Information Bases (MIBs) in SnmpKit, including OID resolution, MIB compilation, and custom MIB integration.

## Table of Contents

- Overview
- Basic MIB Operations
- OID Resolution
- MIB Compilation
- Standard MIBs
- Custom MIBs
- Tree Navigation
- Advanced Features
- Troubleshooting

## Overview

Management Information Bases (MIBs) define the structure of manageable objects in SNMP. SnmpKit provides comprehensive MIB support through the `SnmpKit.MIB` module, allowing you to:

- Resolve OID names to numeric identifiers
- Perform reverse lookups from OIDs to names
- Compile and load custom MIBs
- Navigate the MIB tree structure
- Query object definitions and metadata

## Basic MIB Operations

### OID Name Resolution

Convert human-readable names to numeric OIDs:

    # Simple name resolution
    {:ok, oid} = SnmpKit.MIB.resolve("sysDescr.0")
    # Returns: [1, 3, 6, 1, 2, 1, 1, 1, 0]

    # Multiple resolutions (resolve each individually)
    names = ["sysDescr.0", "sysUpTime.0", "sysName.0"]
    oids = Enum.map(names, &SnmpKit.MIB.resolve/1)

    # Partial name resolution
    {:ok, oid} = SnmpKit.MIB.resolve("system.sysDescr.0")
    {:ok, oid} = SnmpKit.MIB.resolve("1.3.6.1.2.1.1.1.0")

### Reverse OID Lookup

Convert numeric OIDs back to readable names:

    # Basic reverse lookup
    {:ok, name} = SnmpKit.MIB.reverse_lookup([1, 3, 6, 1, 2, 1, 1, 1, 0])
    # Returns: "sysDescr.0"

    # Multiple reverse lookups (lookup each individually)
    oids = [[1, 3, 6, 1, 2, 1, 1, 1, 0], [1, 3, 6, 1, 2, 1, 1, 3, 0]]
    names = Enum.map(oids, &SnmpKit.MIB.reverse_lookup/1)

    # Get the longest matching name
    {:ok, partial_name} = SnmpKit.MIB.reverse_lookup([1, 3, 6, 1, 2, 1, 1, 1, 5])
    # Returns closest match even if exact OID doesn't exist

## OID Resolution

### Working with Different OID Formats

SnmpKit supports multiple OID input formats:

    # String format
    {:ok, oid} = SnmpKit.MIB.resolve("sysDescr.0")

    # Dotted decimal string
    {:ok, oid} = SnmpKit.MIB.resolve("1.3.6.1.2.1.1.1.0")

    # Mixed format
    {:ok, oid} = SnmpKit.MIB.resolve("iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0")

    # List format (already resolved)
    {:ok, oid} = SnmpKit.MIB.resolve([1, 3, 6, 1, 2, 1, 1, 1, 0])

### Common System OIDs

    # System group OIDs
    system_oids = %{
      "sysDescr.0" => [1, 3, 6, 1, 2, 1, 1, 1, 0],
      "sysObjectID.0" => [1, 3, 6, 1, 2, 1, 1, 2, 0],
      "sysUpTime.0" => [1, 3, 6, 1, 2, 1, 1, 3, 0],
      "sysContact.0" => [1, 3, 6, 1, 2, 1, 1, 4, 0],
      "sysName.0" => [1, 3, 6, 1, 2, 1, 1, 5, 0],
      "sysLocation.0" => [1, 3, 6, 1, 2, 1, 1, 6, 0],
      "sysServices.0" => [1, 3, 6, 1, 2, 1, 1, 7, 0]
    }

    # Verify all resolve correctly
    for {name, expected_oid} <- system_oids do
      {:ok, ^expected_oid} = SnmpKit.MIB.resolve(name)
    end

## MIB Compilation

### Loading Standard MIBs

SnmpKit comes with standard MIBs pre-compiled:

    # Standard MIBs are loaded automatically
    {:ok, oid} = SnmpKit.MIB.resolve("sysDescr.0")  # Works immediately

    # Load standard MIBs explicitly if needed
    :ok = SnmpKit.MIB.load_standard_mibs()

### Compiling Custom MIBs

#### High-Level Compilation

For most use cases, use the high-level compilation API:

    # Compile a single MIB file
    {:ok, compiled} = SnmpKit.MIB.compile("path/to/MY-CUSTOM-MIB.mib")
    {:ok, _} = SnmpKit.MIB.load(compiled)

    # Compile multiple MIBs with dependencies
    mib_files = [
      "CISCO-SMI.mib",
      "CISCO-TC.mib",
      "CISCO-CABLE-MODEM-MIB.mib"
    ]

    # Use compile_all for batch compilation
    {:ok, compiled_mibs} = SnmpKit.MIB.compile_all(mib_files)
    # Load each compiled MIB
    Enum.each(compiled_mibs, fn {_file, {:ok, path}} -> SnmpKit.MIB.load(path) end)

#### Low-Level Compilation

For advanced control over the compilation process:

    # Use the low-level compiler directly
    alias SnmpKit.MibCompiler

    # Configure compilation options
    options = [
      output_dir: "priv/compiled_mibs",
      include_dirs: ["priv/mibs", "/usr/share/snmp/mibs"],
      warnings_as_errors: false,
      verbose: true
    ]

    # Compile with options
    {:ok, result} = MibCompiler.compile_file("MY-MIB.mib", options)

    # Handle compilation errors
    case MibCompiler.compile_file("BROKEN-MIB.mib", options) do
      {:ok, result} ->
        IO.puts("Compilation successful")
      {:error, {:compilation_failed, errors}} ->
        IO.puts("Compilation failed:")
        for error <- errors, do: IO.puts("  #{error}")
    end

## Standard MIBs

### Commonly Used Standard MIBs

    # RFC1213-MIB (MIB-II) - Basic system information
    {:ok, _} = SnmpKit.MIB.resolve("sysDescr.0")
    {:ok, _} = SnmpKit.MIB.resolve("ifTable")
    {:ok, _} = SnmpKit.MIB.resolve("ipAddrTable")

    # IF-MIB - Interface information
    {:ok, _} = SnmpKit.MIB.resolve("ifXTable")
    {:ok, _} = SnmpKit.MIB.resolve("ifHCInOctets.1")

    # HOST-RESOURCES-MIB - System resources
    {:ok, _} = SnmpKit.MIB.resolve("hrSystemUptime.0")
    {:ok, _} = SnmpKit.MIB.resolve("hrMemorySize.0")

    # SNMPv2-MIB - SNMP statistics
    {:ok, _} = SnmpKit.MIB.resolve("snmpInPkts.0")
    {:ok, _} = SnmpKit.MIB.resolve("snmpOutPkts.0")

### Loading Additional Standard MIBs

    # Load standard MIBs that are built into the library
    :ok = SnmpKit.MIB.load_standard_mibs()

    # For additional MIBs, compile and load them individually
    {:ok, compiled} = SnmpKit.MIB.compile("path/to/BRIDGE-MIB.mib")
    {:ok, _} = SnmpKit.MIB.load(compiled)

## Custom MIBs

### Enterprise MIBs

Many vendors provide their own MIBs for device-specific objects:

    # Cisco MIBs
    cisco_mibs = [
      "CISCO-SMI.mib",
      "CISCO-TC.mib",
      "CISCO-CABLE-MODEM-MIB.mib",
      "CISCO-DOCS-EXT-MIB.mib"
    ]

    # Compile and load Cisco MIBs in dependency order
    for mib <- cisco_mibs do
      {:ok, compiled} = SnmpKit.MIB.compile(mib)
      {:ok, _} = SnmpKit.MIB.load(compiled)
    end

    # Now Cisco-specific OIDs work
    {:ok, oid} = SnmpKit.MIB.resolve("cdxCmtsCmStatusValue")

### DOCSIS MIBs

For cable modem and CMTS management:

    # DOCSIS MIBs
    docsis_mibs = [
      "DOCS-CABLE-DEVICE-MIB.mib",
      "DOCS-IF-MIB.mib",
      "DOCS-QOS-MIB.mib",
      "DOCS-SUBMGT-MIB.mib"
    ]

    # Compile and load each MIB in order
    for mib <- docsis_mibs do
      {:ok, compiled} = SnmpKit.MIB.compile(mib)
      {:ok, _} = SnmpKit.MIB.load(compiled)
    end

    # DOCSIS-specific operations
    {:ok, status} = SnmpKit.SNMP.get("10.1.1.100", "docsIfCmStatusValue.1")
    {:ok, signal} = SnmpKit.SNMP.get("10.1.1.100", "docsIfSigQSignalNoise.1")

### Loading Custom MIB Data

Custom MIB definitions can be loaded by compiling and integrating MIB files:

    # Compile and integrate a custom MIB file
    {:ok, _} = SnmpKit.MIB.load_and_integrate_mib("path/to/MY-CUSTOM-MIB.mib")

    # Now the custom objects can be resolved
    {:ok, oid} = SnmpKit.MIB.resolve("myCustomObject.0")

## Tree Navigation

### Exploring the MIB Tree

    # Get children of a node
    {:ok, children} = SnmpKit.MIB.children([1, 3, 6, 1, 2, 1, 1])
    # Returns list of child OIDs under system group

    # Get parent of a node
    {:ok, parent} = SnmpKit.MIB.parent([1, 3, 6, 1, 2, 1, 1, 1, 0])
    # Returns: [1, 3, 6, 1, 2, 1, 1, 1]

    # Walk the tree from a starting point
    {:ok, tree} = SnmpKit.MIB.walk_tree([1, 3, 6, 1, 2, 1, 1])

### Querying Object Information

    # Get detailed object information using object_info
    # Available via SnmpKit.SnmpMgr.MIB.object_info/1
    {:ok, info} = SnmpKit.SnmpMgr.MIB.object_info("sysDescr.0")
    # Returns: %{name: "sysDescr", oid: [...], syntax: %{base: :octet_string, ...}, ...}

    # Check if an OID can be resolved
    case SnmpKit.MIB.resolve("sysDescr.0") do
      {:ok, _oid} -> IO.puts("OID exists")
      {:error, :not_found} -> IO.puts("OID not found")
    end

## Advanced Features

### MIB Parsing and Analysis

    # Parse a MIB file to extract object definitions
    {:ok, parsed} = SnmpKit.MIB.parse_mib_file("MY-MIB.mib")
    IO.inspect(parsed.parsed_objects)

    # Parse MIB content from a string
    {:ok, parsed} = SnmpKit.MIB.parse_mib_content(mib_content_string)

### Enhanced Resolution

    # Use enhanced resolution that includes loaded MIB data
    {:ok, oid} = SnmpKit.MIB.resolve_enhanced("customObject.0")

### Bulk OID Operations

    # Resolve many OIDs using Enum.map
    oids_to_resolve = [
      "sysDescr.0", "sysUpTime.0", "sysName.0",
      "ifInOctets.1", "ifOutOctets.1", "ifOperStatus.1"
    ]

    resolved = Enum.map(oids_to_resolve, &SnmpKit.MIB.resolve/1)

    # Reverse lookup many OIDs
    numeric_oids = [
      [1, 3, 6, 1, 2, 1, 1, 1, 0],
      [1, 3, 6, 1, 2, 1, 1, 3, 0],
      [1, 3, 6, 1, 2, 1, 1, 5, 0]
    ]

    names = Enum.map(numeric_oids, &SnmpKit.MIB.reverse_lookup/1)

## Troubleshooting

### Common Issues

#### MIB Compilation Failures

    # Debug compilation issues
    case SnmpKit.MIB.compile("problematic.mib", debug: true) do
      {:error, {:compilation_failed, errors}} ->
        IO.puts("Compilation errors:")
        for {line, message} <- errors do
          IO.puts("Line #{line}: #{message}")
        end
      {:error, {:missing_dependencies, deps}} ->
        IO.puts("Missing dependencies: #{Enum.join(deps, ", ")}")
        IO.puts("Load these MIBs first")
    end

#### OID Resolution Problems

    # Debug OID resolution
    case SnmpKit.MIB.resolve("unknownOid.0") do
      {:ok, oid} ->
        IO.puts("Resolved to: #{inspect(oid)}")
      {:error, :not_found} ->
        IO.puts("OID not found - check MIB is loaded")
      {:error, :invalid_name} ->
        IO.puts("Invalid OID name format")
    end

#### Performance Issues

    # Profile MIB operations
    {time, {:ok, result}} = :timer.tc(fn ->
      SnmpKit.MIB.resolve("complexOid.withManyParts.0")
    end)

    IO.puts("Resolution took #{time}μs")

    # Enable verbose logging for debugging
    Logger.configure(level: :debug)
    SnmpKit.MIB.resolve("sysDescr.0")  # Will show detailed logs

### Best Practices

1. Load MIBs in dependency order - Load base MIBs before dependent ones
2. Handle errors gracefully - Always pattern match on MIB operation results
3. Use bulk operations - Resolve multiple OIDs at once using Enum.map when possible
4. Integrate MIBs properly - Use load_and_integrate_mib for full MIB support

### Getting Help

    # Get help on available MIB functions
    h SnmpKit.MIB

    # Load standard MIBs
    :ok = SnmpKit.MIB.load_standard_mibs()

    # Test resolution
    {:ok, oid} = SnmpKit.MIB.resolve("sysDescr.0")
    IO.inspect(oid)

For more examples and advanced usage, see the API documentation.

← Previous Page LICENSE
Next Page → Testing Guide - SnmpKit