RawPing.Packet (raw_ping v0.3.1)

Copy Markdown View Source

ICMP packet construction and parsing.

Handles building ICMP echo request packets and parsing echo reply packets.

ICMP Echo Request/Reply Format

0                   1                   2                   3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Type      |     Code      |          Checksum             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Identifier          |        Sequence Number        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Data ...
+-+-+-+-+-+-+-+-
  • Type 8, Code 0: Echo Request
  • Type 0, Code 0: Echo Reply

Summary

Functions

Build an ICMP echo request packet.

Calculate the ICMP checksum (one's complement of one's complement sum).

Parse an ICMP echo reply packet.

Functions

build_echo_request(id, seq, payload_size \\ 56)

@spec build_echo_request(non_neg_integer(), non_neg_integer(), non_neg_integer()) ::
  binary()

Build an ICMP echo request packet.

Parameters

  • id - Identifier (16-bit)
  • seq - Sequence number (16-bit)
  • payload_size - Size of payload data in bytes

Returns a binary packet ready to send.

calculate_checksum(data)

@spec calculate_checksum(binary()) :: non_neg_integer()

Calculate the ICMP checksum (one's complement of one's complement sum).

parse_echo_reply(data, mode \\ :raw)

@spec parse_echo_reply(binary(), RawPing.Socket.mode()) ::
  {:ok, non_neg_integer(), non_neg_integer(), non_neg_integer() | nil}
  | {:error, term()}

Parse an ICMP echo reply packet.

Accepts input with or without a leading IP header, detecting which it got. Whether the kernel includes the IP header is a property of the host, not of the socket type: on Linux a datagram ICMP socket strips it, while on macOS/BSD the same socket delivers it intact. Assuming either one breaks on the other platform, so this inspects the data instead.

When an IP header is present, TTL comes from it. When it is absent, TTL is returned as nil — recovering it would need IP_RECVTTL ancillary data.

The mode argument is accepted for symmetry with RawPing.Socket.open/1 and does not affect parsing.

Note that Linux substitutes its own value for the identifier on datagram sockets, so the returned id may not be the one passed to build_echo_request/3. Match on sequence when reading from a datagram socket.

Returns {:ok, id, seq, ttl} or {:error, reason}.