SnmpKit.SnmpLib.Transport (snmpkit v0.6.6)

UDP transport layer for SNMP communications.

Provides socket management, connection utilities, and network operations for both SNMP managers and agents/simulators.

Features

  • UDP socket creation and management
  • Address resolution and validation
  • Connection pooling and reuse
  • Timeout handling
  • Error recovery
  • Performance optimizations

Examples

# Create and use a socket
{:ok, socket} = SnmpKit.SnmpLib.Transport.create_socket("0.0.0.0", 161)
{:ok, data} = SnmpKit.SnmpLib.Transport.receive_packet(socket, 5000)
:ok = SnmpKit.SnmpLib.Transport.send_packet(socket, "192.168.1.100", 161, packet_data)
:ok = SnmpKit.SnmpLib.Transport.close_socket(socket)

# Address utilities
{:ok, {192, 168, 1, 100}} = SnmpKit.SnmpLib.Transport.resolve_address("192.168.1.100")
true = SnmpKit.SnmpLib.Transport.validate_port(161)

Summary

Functions

Closes a UDP socket.

Creates a client socket for outgoing SNMP requests.

Creates a server socket for incoming SNMP requests.

Creates a UDP socket bound to the specified address and port.

Formats an endpoint (address and port) as a string.

Gets the local address and port of a socket.

Gets socket statistics and information.

Checks if a port number is a standard SNMP port.

Calculates network MTU considerations for SNMP packets.

Resolves an address to an IP tuple.

Receives a packet from the socket with optional timeout.

Sends a packet to the specified destination.

Sends a request packet and waits for a response.

Returns standard SNMP port numbers.

Tests connectivity to a destination by sending a test packet.

Validates if a packet size is suitable for SNMP transmission.

Validates a port number.

Types

address()

@type address() :: :inet.socket_address() | :inet.hostname() | binary()

packet_data()

@type packet_data() :: binary()

port_number()

@type port_number() :: :inet.port_number()

socket()

@type socket() :: :gen_udp.socket()

socket_options()

@type socket_options() :: [:gen_udp.option()]

Functions

close_socket(socket)

@spec close_socket(socket()) :: :ok

Closes a UDP socket.

Examples

:ok = SnmpKit.SnmpLib.Transport.close_socket(socket)

create_client_socket(options \\ [])

@spec create_client_socket(socket_options()) :: {:ok, socket()} | {:error, atom()}

Creates a client socket for outgoing SNMP requests.

Uses an ephemeral port and optimizes settings for client use.

Examples

{:ok, socket} = SnmpKit.SnmpLib.Transport.create_client_socket()
{:ok, socket} = SnmpKit.SnmpLib.Transport.create_client_socket([{:recbuf, 65536}])

create_server_socket(port, bind_address \\ "0.0.0.0")

@spec create_server_socket(port_number(), binary()) ::
  {:ok, socket()} | {:error, atom()}

Creates a server socket for incoming SNMP requests.

Optimizes settings for server use with proper buffer sizes.

Examples

{:ok, socket} = SnmpKit.SnmpLib.Transport.create_server_socket(161)
{:ok, socket} = SnmpKit.SnmpLib.Transport.create_server_socket(161, "192.168.1.10")

create_socket(bind_address, port, options \\ [])

@spec create_socket(
  binary() | :inet.socket_address(),
  port_number(),
  socket_options()
) ::
  {:ok, socket()} | {:error, atom()}

Creates a UDP socket bound to the specified address and port.

Parameters

  • bind_address: Address to bind to (use "0.0.0.0" for all interfaces)
  • port: Port number to bind to
  • options: Additional socket options (optional)

Returns

  • {:ok, socket} on success
  • {:error, reason} on failure

Examples

{:ok, socket} = SnmpKit.SnmpLib.Transport.create_socket("0.0.0.0", 161)
{:ok, client_socket} = SnmpKit.SnmpLib.Transport.create_socket("0.0.0.0", 0, [{:active, true}])

format_endpoint(address, port)

@spec format_endpoint(address(), port_number()) :: binary()

Formats an endpoint (address and port) as a string.

Examples

"192.168.1.100:161" = SnmpKit.SnmpLib.Transport.format_endpoint({192, 168, 1, 100}, 161)
"localhost:162" = SnmpKit.SnmpLib.Transport.format_endpoint("localhost", 162)

get_socket_address(socket)

@spec get_socket_address(socket()) ::
  {:ok, {:inet.socket_address(), port_number()}} | {:error, atom()}

Gets the local address and port of a socket.

Examples

{:ok, {{127, 0, 0, 1}, 12345}} = SnmpKit.SnmpLib.Transport.get_socket_address(socket)

get_socket_stats(socket)

@spec get_socket_stats(socket()) :: {:ok, map()} | {:error, atom()}

Gets socket statistics and information.

Examples

{:ok, stats} = SnmpKit.SnmpLib.Transport.get_socket_stats(socket)
# stats contains buffer sizes, packet counts, etc.

is_snmp_port?(port)

@spec is_snmp_port?(port_number()) :: boolean()

Checks if a port number is a standard SNMP port.

Examples

true = SnmpKit.SnmpLib.Transport.is_snmp_port?(161)
true = SnmpKit.SnmpLib.Transport.is_snmp_port?(162)
false = SnmpKit.SnmpLib.Transport.is_snmp_port?(80)

max_snmp_payload_size()

@spec max_snmp_payload_size() :: non_neg_integer()

Calculates network MTU considerations for SNMP packets.

Returns recommended maximum payload size to avoid fragmentation.

Examples

1472 = SnmpKit.SnmpLib.Transport.max_snmp_payload_size()  # Ethernet MTU - headers

receive_packet(socket, timeout \\ 5000)

@spec receive_packet(socket(), non_neg_integer()) ::
  {:ok, {packet_data(), :inet.socket_address(), port_number()}}
  | {:error, atom()}

receive_packet_filtered(socket, filter_fn, timeout, per_recv_timeout \\ 1000)

@spec receive_packet_filtered(
  socket(),
  function(),
  non_neg_integer(),
  non_neg_integer()
) ::
  {:ok, {packet_data(), :inet.socket_address(), port_number()}}
  | {:error, atom()}

Receives a packet with a custom filter function.

Continues receiving until a packet matches the filter or timeout occurs.

Parameters

  • socket: UDP socket to receive from
  • filter_fn: Function that returns true for desired packets
  • timeout: Total timeout in milliseconds
  • per_recv_timeout: Timeout per receive attempt (default: 1000ms)

Examples

# Wait for packet from specific address
filter_fn = fn {_data, from_addr, _from_port} -> from_addr == {192, 168, 1, 100} end
{:ok, {data, addr, port}} = SnmpKit.SnmpLib.Transport.receive_packet_filtered(socket, filter_fn, 5000)

resolve_address(address)

@spec resolve_address(address()) :: {:ok, :inet.socket_address()} | {:error, atom()}

Resolves an address to an IP tuple.

Accepts:

  • IP address strings (e.g., "192.168.1.1")
  • Hostnames (e.g., "localhost")
  • IP tuples (e.g., {192, 168, 1, 1})

Examples

iex> SnmpKit.SnmpLib.Transport.resolve_address("192.168.1.1")
{:ok, {192, 168, 1, 1}}

iex> SnmpKit.SnmpLib.Transport.resolve_address({192, 168, 1, 1})
{:ok, {192, 168, 1, 1}}

send_and_receive_packet(dest_address, dest_port, data, timeout \\ 5000)

@spec send_and_receive_packet(
  :inet.socket_address(),
  port_number(),
  packet_data(),
  non_neg_integer()
) ::
  {:ok, {packet_data(), :inet.socket_address(), port_number()}}
  | {:error, atom()}

Receives a packet from the socket with optional timeout.

Parameters

  • socket: UDP socket to receive from
  • timeout: Timeout in milliseconds (default: 5000)

Returns

  • {:ok, {data, from_address, from_port}} on success
  • {:error, reason} on failure or timeout

Examples

{:ok, {data, from_ip, from_port}} = SnmpKit.SnmpLib.Transport.receive_packet(socket)
{:ok, {data, from_ip, from_port}} = SnmpKit.SnmpLib.Transport.receive_packet(socket, 10000)

send_packet(socket, dest_address, dest_port, data)

@spec send_packet(socket(), address(), port_number(), packet_data()) ::
  :ok | {:error, atom()}

Sends a packet to the specified destination.

Parameters

  • socket: UDP socket to send from
  • dest_address: Destination IP address or hostname
  • dest_port: Destination port number
  • data: Binary data to send

Returns

  • :ok on success
  • {:error, reason} on failure

Examples

:ok = SnmpKit.SnmpLib.Transport.send_packet(socket, "192.168.1.100", 161, packet_data)
:ok = SnmpKit.SnmpLib.Transport.send_packet(socket, {192, 168, 1, 100}, 161, packet_data)

send_request(dest_address, dest_port, request_data, timeout \\ 5000)

@spec send_request(address(), port_number(), packet_data(), non_neg_integer()) ::
  {:ok, packet_data()} | {:error, atom()}

Sends a request packet and waits for a response.

This creates a temporary socket, sends a packet, waits for the response, and returns the response data. Useful for SNMPv3 discovery and security operations.

Parameters

  • dest_address: Destination IP address or hostname
  • dest_port: Destination port number
  • request_data: Binary request data to send
  • timeout: Timeout in milliseconds (default: 5000)

Returns

  • {:ok, response_data} if request succeeds and response received
  • {:error, reason} if request fails or times out

Examples

{:ok, response} = SnmpKit.SnmpLib.Transport.send_request("192.168.1.100", 161, request_packet, 5000)
{:error, :timeout} = SnmpKit.SnmpLib.Transport.send_request("10.0.0.1", 161, request_packet, 1000)

snmp_agent_port()

@spec snmp_agent_port() :: port_number()

Returns standard SNMP port numbers.

snmp_trap_port()

@spec snmp_trap_port() :: port_number()

test_connectivity(dest_address, dest_port, timeout \\ 3000)

@spec test_connectivity(address(), port_number(), non_neg_integer()) ::
  :ok | {:error, atom()}

Tests connectivity to a destination by sending a test packet.

This creates a temporary socket, sends a small packet, and waits for any response to verify network connectivity.

Parameters

  • dest_address: Destination IP address or hostname
  • dest_port: Destination port number
  • timeout: Timeout in milliseconds (default: 3000)

Returns

  • :ok if connectivity is confirmed
  • {:error, reason} if connectivity fails

Examples

:ok = SnmpKit.SnmpLib.Transport.test_connectivity("192.168.1.100", 161)
{:error, :timeout} = SnmpKit.SnmpLib.Transport.test_connectivity("10.0.0.1", 161, 1000)

valid_packet_size?(size)

@spec valid_packet_size?(non_neg_integer()) :: boolean()

Validates if a packet size is suitable for SNMP transmission.

Examples

true = SnmpKit.SnmpLib.Transport.valid_packet_size?(500)
false = SnmpKit.SnmpLib.Transport.valid_packet_size?(2000)

validate_port(port)

@spec validate_port(term()) :: boolean()

Validates a port number.

Examples

true = SnmpKit.SnmpLib.Transport.validate_port(161)
true = SnmpKit.SnmpLib.Transport.validate_port(65535)
true = SnmpKit.SnmpLib.Transport.validate_port(0)
false = SnmpKit.SnmpLib.Transport.validate_port(65536)