SnmpKit.SnmpLib.PDU (snmpkit v0.6.3)

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

Functions

Builds a GETNEXT request PDU.

Builds a GET request PDU.

Builds a GET request PDU with multiple varbinds.

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

Creates an error response PDU.

Alias for decode_message/1.

Decodes an SNMP message from binary format.

Legacy alias for decode/1.

Alias for encode_message/1.

Encodes an SNMP message to binary format.

Legacy alias for encode/1.

Converts an error status code to its atom representation.

Converts an error status atom to its numeric code.

Normalizes an OID to a list of integers.

Normalizes an SNMP type atom.

Validates a PDU structure.

Types

error_status()

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

message()

oid()

pdu()

snmp_type()

snmp_value()

varbind()

Functions

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

@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")