Pure Erlang/OTP ICMP ping library using the modern :socket API.
No NIFs, no external dependencies. Requires Elixir 1.17+ (OTP 25+).
Usage
# Single ping
{:ok, rtt_ms} = RawPing.ping("8.8.8.8")
{:ok, rtt_ms} = RawPing.ping({8, 8, 8, 8})
# With options
{:ok, rtt_ms} = RawPing.ping("8.8.8.8", timeout: 2000)
# Multiple pings with stats
{:ok, stats} = RawPing.ping_stats("8.8.8.8", count: 5)
# => {:ok, %{min: 10.5, max: 15.2, avg: 12.3, success_rate: 1.0, ...}}
# Batch ping multiple hosts
results = RawPing.ping_batch(["8.8.8.8", "1.1.1.1", "192.168.1.1"])
# => %{"8.8.8.8" => {:ok, 12.5}, "1.1.1.1" => {:ok, 8.2}, ...}Privileges
Raw ICMP sockets typically require elevated privileges. Options:
- Run as root/sudo
- Set CAP_NET_RAW capability on the BEAM:
setcap cap_net_raw+ep /path/to/beam.smp - Use a setuid wrapper
How It Works
Uses Erlang's :socket module to open a raw ICMP socket, builds ICMP echo
request packets manually, sends them, and parses the echo replies to calculate
round-trip time.
Summary
Functions
Ping a host and return the round-trip time in milliseconds.
Ping multiple hosts concurrently.
Ping a host multiple times and return statistics.
Types
@type ip_address() :: String.t() | :inet.ip_address() | [integer()]
@type ping_stats() :: %{ min: float() | nil, max: float() | nil, avg: float() | nil, success_rate: float(), success_count: non_neg_integer(), failure_count: non_neg_integer(), rtts: [float()] }
Functions
@spec ping( ip_address(), keyword() ) :: ping_result()
Ping a host and return the round-trip time in milliseconds.
Options
:timeout- Timeout in milliseconds (default: 5000):payload_size- Size of ICMP payload in bytes (default: 56)
Examples
{:ok, rtt} = RawPing.ping("8.8.8.8")
{:ok, rtt} = RawPing.ping({8, 8, 8, 8}, timeout: 1000)
{:error, :timeout} = RawPing.ping("10.255.255.1", timeout: 100)
@spec ping_batch( [ip_address()], keyword() ) :: %{required(String.t()) => ping_result()}
Ping multiple hosts concurrently.
Returns a map of host => result.
Options
:timeout- Timeout per ping in milliseconds (default: 5000):max_concurrency- Maximum concurrent pings (default: 50)
Examples
results = RawPing.ping_batch(["8.8.8.8", "1.1.1.1"])
# %{"8.8.8.8" => {:ok, 12.5}, "1.1.1.1" => {:ok, 8.2}}
@spec ping_stats( ip_address(), keyword() ) :: {:ok, ping_stats()} | {:error, term()}
Ping a host multiple times and return statistics.
Options
:count- Number of pings to send (default: 1):timeout- Timeout per ping in milliseconds (default: 5000):payload_size- Size of ICMP payload in bytes (default: 56)
Examples
{:ok, stats} = RawPing.ping_stats("8.8.8.8", count: 5)
# %{min: 10.2, max: 15.8, avg: 12.5, success_rate: 1.0, ...}