Search documentation of snmpkit

# SnmpKit.SnmpLib.Transport (snmpkit v1.2.0)

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

## Types

address()
packet_data()
port_number()
socket()
socket_options()

## Functions

close_socket(socket)

Closes a UDP socket.

create_client_socket(options \\ [])

Creates a client socket for outgoing SNMP requests.

create_server_socket(port, bind_address \\ "0.0.0.0")

Creates a server socket for incoming SNMP requests.

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

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

format_endpoint(address, port)

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

get_socket_address(socket)

Gets the local address and port of a socket.

get_socket_stats(socket)

Gets socket statistics and information.

is_snmp_port?(port)

Checks if a port number is a standard SNMP port.

max_snmp_payload_size()

Calculates network MTU considerations for SNMP packets.

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

Receives a packet with a custom filter function.

resolve_address(address)

Resolves an address to an IP tuple.

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

Receives a packet from the socket with optional timeout.

send_packet(socket, dest_address, dest_port, data)

Sends a packet to the specified destination.

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

Sends a request packet and waits for a response.

snmp_agent_port()

Returns standard SNMP port numbers.

snmp_trap_port()
test_connectivity(dest_address, dest_port, timeout \\ 3000)

Tests connectivity to a destination by sending a test packet.

valid_packet_size?(size)

Validates if a packet size is suitable for SNMP transmission.

validate_port(port)

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)