Search documentation of snmpkit

# SnmpKit.SnmpLib.PDU (snmpkit v1.3.17)

SNMP PDU (Protocol Data Unit) encoding and decoding with RFC compliance.

Provides comprehensive SNMP PDU functionality combining the best features from multiple SNMP implementations. Supports SNMPv1 and SNMPv2c protocols with high-performance encoding/decoding, robust error handling, and full RFC compliance.

## API Documentation

### PDU Structure

All PDU functions in this library use a consistent map structure with these fields:

    %{
      type: :get_request | :get_next_request | :get_response | :set_request | :get_bulk_request,
      request_id: non_neg_integer(),
      error_status: 0..5,
      error_index: non_neg_integer(),
      varbinds: [varbind()],
      # GETBULK only:
      non_repeaters: non_neg_integer(),      # Optional, GETBULK requests only
      max_repetitions: non_neg_integer()     # Optional, GETBULK requests only
    }

IMPORTANT: Always use the `:type` field (not `:pdu_type`) with atom values.

### Variable Bindings Format

Variable bindings (`varbinds`) support two formats:

- 2-tuple format: `{oid, value}` - Used for responses and simple cases
- 3-tuple format: `{oid, type, value}` - Used for requests with explicit type info

    # Request varbinds (3-tuple with type information)
    [{[1, 3, 6, 1, 2, 1, 1, 1, 0], :null, :null}]

    # Response varbinds (2-tuple format)
    [{[1, 3, 6, 1, 2, 1, 1, 1, 0], "Linux server"}]

    # Response varbinds (3-tuple format also supported)
    [{[1, 3, 6, 1, 2, 1, 1, 1, 0], :octet_string, "Linux server"}]

### Message Structure

SNMP messages have this structure:

    %{
      version: 0 | 1,           # 0 = SNMPv1, 1 = SNMPv2c
      community: binary(),      # Community string
      pdu: pdu()               # PDU map as described above
    }

## Examples

### Building PDUs

    # GET request for system description
    pdu = SnmpKit.SnmpLib.PDU.build_get_request([1, 3, 6, 1, 2, 1, 1, 1, 0], 123)

    # GETBULK request for interface table
    pdu = SnmpKit.SnmpLib.PDU.build_get_bulk_request([1, 3, 6, 1, 2, 1, 2, 2, 1], 124, 0, 10)

    # SET request
    pdu = SnmpKit.SnmpLib.PDU.build_set_request([1, 3, 6, 1, 2, 1, 1, 5, 0], {:octet_string, "New Name"}, 125)

### Building Messages

    # Complete SNMP message
    {:ok, message} = SnmpKit.SnmpLib.PDU.build_message(pdu, "public", :v2c)

    # Encode to binary
    {:ok, packet} = SnmpKit.SnmpLib.PDU.encode_message(message)

    # Decode from binary
    {:ok, decoded_message} = SnmpKit.SnmpLib.PDU.decode_message(packet)

### Error Responses

    # Create error response
    error_pdu = SnmpKit.SnmpLib.PDU.create_error_response(original_pdu, :no_such_name, 1)

# Summary

## Types

error_status()
message()
oid()
pdu()
snmp_type()
snmp_value()
varbind()

## Functions

build_get_bulk_request(oid_list, request_id, non_repeaters \\ 0, max_repetitions \\ 30)

Builds a GETBULK request PDU (SNMPv2c only).

build_get_next_request(oid_or_oids, request_id)

Builds a GETNEXT request PDU.

build_get_request(oid, request_id)

Builds a GET request PDU.

build_get_request_multi(varbinds, request_id)

Builds a GET request PDU with multiple varbinds.

build_message(pdu, community, version \\ :v1)

Builds an SNMP message with version, community, and PDU.

build_response(request_id, error_status, error_index, varbinds \\ [])

Builds a response PDU.

build_set_request(oid_list, type_value, request_id)

Builds a SET request PDU.

create_error_response(request_pdu, error_status)

Creates an error response PDU.

create_error_response(request_pdu, error_status, error_index)

Creates an error response PDU.

decode(data)

Alias for decode_message/1.

decode_message(data)

Decodes an SNMP message from binary format.

decode_snmp_packet(data)

Legacy alias for decode/1.

encode(message)

Alias for encode_message/1.

encode_message(message)

Encodes an SNMP message to binary format.

encode_snmp_packet(message)

Legacy alias for encode/1.

error_status_to_atom(code)

Converts an error status code to its atom representation.

error_status_to_code(status)

Converts an error status atom to its numeric code.

normalize_oid(oid)

Normalizes an OID to a list of integers.

normalize_type(type)

Normalizes an SNMP type atom.

validate(pdu)

Validates a PDU structure.

validate_community(encoded_message, expected_community)

Validates a community string.

# Types

# error_status()

    @type error_status() :: SnmpKit.SnmpLib.PDU.Constants.error_status()

# message()

    @type message() :: SnmpKit.SnmpLib.PDU.Constants.message()

# oid()

    @type oid() :: SnmpKit.SnmpLib.PDU.Constants.oid()

# pdu()

    @type pdu() :: SnmpKit.SnmpLib.PDU.Constants.pdu()

# snmp_type()

    @type snmp_type() :: SnmpKit.SnmpLib.PDU.Constants.snmp_type()

# snmp_value()

    @type snmp_value() :: SnmpKit.SnmpLib.PDU.Constants.snmp_value()

# varbind()

    @type varbind() :: SnmpKit.SnmpLib.PDU.Constants.varbind()

# Functions

# build_get_bulk_request(oid_list, request_id, non_repeaters \\ 0, max_repetitions \\ 30)

    @spec build_get_bulk_request(
      oid(),
      non_neg_integer(),
      non_neg_integer(),
      non_neg_integer()
    ) :: pdu()

Builds a GETBULK request PDU (SNMPv2c only).

## Parameters

- `oid_list`: Single OID list or list of OID lists to request
- `request_id`: Unique request identifier
- `non_repeaters`: Number of non-repeating variables (default: 0)
- `max_repetitions`: Maximum repetitions for repeating variables (default: 10)

## Examples

    iex> pdu = SnmpKit.SnmpLib.PDU.build_get_bulk_request([1, 3, 6, 1, 2, 1, 2, 2], 123, 0, 10)
    iex> pdu.type
    :get_bulk_request

# build_get_next_request(oid_or_oids, request_id)

    @spec build_get_next_request(oid() | [oid()], non_neg_integer()) :: pdu()

Builds a GETNEXT request PDU.

## Parameters

- `oid_or_oids`: Single OID list or list of OID lists to request
- `request_id`: Unique request identifier

## Examples

    iex> pdu = SnmpKit.SnmpLib.PDU.build_get_next_request([1, 3, 6, 1, 2, 1, 1], 123)
    iex> pdu.type
    :get_next_request

# build_get_request(oid, request_id)

    @spec build_get_request(oid(), non_neg_integer()) :: pdu()

Builds a GET request PDU.

## Parameters

- `oid`: Single OID as list of integers
- `request_id`: Unique request identifier

## Examples

    iex> pdu = SnmpKit.SnmpLib.PDU.build_get_request([1, 3, 6, 1, 2, 1, 1, 1, 0], 123)
    iex> pdu.type
    :get_request

# build_get_request_multi(varbinds, request_id)

    @spec build_get_request_multi([varbind()], non_neg_integer()) :: pdu()

Builds a GET request PDU with multiple varbinds.

## Parameters

- `varbinds`: List of variable bindings in format `{oid, type, value}`
- `request_id`: Unique request identifier

## Examples

    iex> varbinds = [{[1, 3, 6, 1, 2, 1, 1, 1, 0], :null, :null}]
    iex> pdu = SnmpKit.SnmpLib.PDU.build_get_request_multi(varbinds, 123)
    iex> pdu.type
    :get_request

# build_message(pdu, community, version \\ :v1)

    @spec build_message(pdu(), binary(), SnmpKit.SnmpLib.PDU.Constants.snmp_version()) ::
      message()

Builds an SNMP message with version, community, and PDU.

## Parameters

- `pdu`: PDU structure to include in the message
- `community`: Community string for authentication
- `version`: SNMP version

## Examples

    iex> pdu = SnmpKit.SnmpLib.PDU.build_get_request([1, 3, 6, 1, 2, 1, 1, 1, 0], 123)
    iex> message = SnmpKit.SnmpLib.PDU.build_message(pdu, "public", :v2c)
    iex> message.version
    1

# build_response(request_id, error_status, error_index, varbinds \\ [])

    @spec build_response(non_neg_integer(), error_status(), non_neg_integer(), [varbind()]) ::
      pdu()

Builds a response PDU.

## Parameters

- `request_pdu`: Original request PDU to respond to
- `varbinds`: List of variable bindings for the response
- `error_status`: Error status code (default: 0 for no error)
- `error_index`: Error index (default: 0)

## Examples

    iex> varbinds = [{[1, 3, 6, 1, 2, 1, 1, 1, 0], :octet_string, "Linux server"}]
    iex> pdu = SnmpKit.SnmpLib.PDU.build_response(123, 0, 0, varbinds)
    iex> pdu.type
    :get_response

# build_set_request(oid_list, type_value, request_id)

    @spec build_set_request(oid(), {atom(), any()}, non_neg_integer()) :: pdu()

Builds a SET request PDU.

## Parameters

- `oid_list`: Single OID as list of integers
- `type_value`: Tuple of `{type, value}` for the SET operation
- `request_id`: Unique request identifier

## Examples

    iex> pdu = SnmpKit.SnmpLib.PDU.build_set_request([1, 3, 6, 1, 2, 1, 1, 5, 0], {:octet_string, "Test"}, 123)
    iex> pdu.type
    :set_request

# create_error_response(request_pdu, error_status)

    @spec create_error_response(pdu(), error_status() | atom()) :: pdu()

Creates an error response PDU.

## Parameters

- `request_pdu`: Original request PDU
- `error_status`: Error status atom or code

## Examples

    iex> request_pdu = %{type: :get_request, request_id: 123, error_status: 0, error_index: 0, varbinds: []}
    iex> error_pdu = SnmpKit.SnmpLib.PDU.create_error_response(request_pdu, :no_such_name)
    iex> error_pdu.error_status
    2

# create_error_response(request_pdu, error_status, error_index)

    @spec create_error_response(pdu(), error_status() | atom(), non_neg_integer()) ::
      pdu()

Creates an error response PDU.

## Parameters

- `request_pdu`: Original request PDU
- `error_status`: Error status atom or code
- `error_index`: Index of the variable that caused the error

## Examples

    iex> request_pdu = %{type: :get_request, request_id: 123, error_status: 0, error_index: 0, varbinds: []}
    iex> error_pdu = SnmpKit.SnmpLib.PDU.create_error_response(request_pdu, :no_such_name, 1)
    iex> error_pdu.error_status
    2

# decode(data)

    @spec decode(binary()) :: {:ok, message()} | {:error, atom()}

Alias for decode_message/1.

# decode_message(data)

    @spec decode_message(binary()) :: {:ok, message()} | {:error, atom()}

Decodes an SNMP message from binary format.

## Examples

    iex> {:ok, binary} = SnmpKit.SnmpLib.PDU.encode_message(%{version: 1, community: "public", pdu: %{type: :get_request, request_id: 123, error_status: 0, error_index: 0, varbinds: []}})
    iex> {:ok, _message} = SnmpKit.SnmpLib.PDU.decode_message(binary)

# decode_snmp_packet(data)

    @spec decode_snmp_packet(binary()) :: {:ok, message()} | {:error, atom()}

Legacy alias for decode/1.

# encode(message)

    @spec encode(message()) :: {:ok, binary()} | {:error, atom()}

Alias for encode_message/1.

# encode_message(message)

    @spec encode_message(message()) :: {:ok, binary()} | {:error, atom()}

Encodes an SNMP message to binary format.

## Examples

    iex> message = %{version: 1, community: "public", pdu: %{type: :get_request, request_id: 123, error_status: 0, error_index: 0, varbinds: []}}
    iex> {:ok, _binary} = SnmpKit.SnmpLib.PDU.encode_message(message)

# encode_snmp_packet(message)

    @spec encode_snmp_packet(message()) :: {:ok, binary()} | {:error, atom()}

Legacy alias for encode/1.

# error_status_to_atom(code)

    @spec error_status_to_atom(non_neg_integer()) :: atom()

Converts an error status code to its atom representation.

## Examples

    iex> SnmpKit.SnmpLib.PDU.error_status_to_atom(2)
    :no_such_name

# error_status_to_code(status)

    @spec error_status_to_code(atom()) :: non_neg_integer()

Converts an error status atom to its numeric code.

## Examples

    iex> SnmpKit.SnmpLib.PDU.error_status_to_code(:no_such_name)
    2

# normalize_oid(oid)

    @spec normalize_oid(oid() | binary()) :: oid()

Normalizes an OID to a list of integers.

## Examples

    iex> SnmpKit.SnmpLib.PDU.normalize_oid([1, 3, 6, 1, 2, 1, 1, 1, 0])
    [1, 3, 6, 1, 2, 1, 1, 1, 0]

# normalize_type(type)

    @spec normalize_type(atom()) :: snmp_type()

Normalizes an SNMP type atom.

## Examples

    iex> SnmpKit.SnmpLib.PDU.normalize_type(:string)
    :octet_string

# validate(pdu)

    @spec validate(pdu()) :: {:ok, pdu()} | {:error, atom()}

Validates a PDU structure.

## Examples

    iex> pdu = %{type: :get_request, request_id: 123, error_status: 0, error_index: 0, varbinds: []}
    iex> {:ok, ^pdu} = SnmpKit.SnmpLib.PDU.validate(pdu)

# validate_community(encoded_message, expected_community)

    @spec validate_community(binary(), binary()) :: :ok | {:error, atom()}

Validates a community string.

## Parameters

- `encoded_message`: Encoded SNMP message
- `expected_community`: Expected community string

## Examples

    iex> :ok = SnmpKit.SnmpLib.PDU.validate_community(encoded_msg, "public")