non-blocking ICMPv4 library for network diagnostic tools on POSIX systems.
Find a file
2026-04-23 12:59:58 +02:00
examples Initial commit - libcimp 2026-01-24 16:04:09 +01:00
includes feat: icmp_create_block() 2026-04-22 23:58:41 +02:00
src feat: icmp_create_block() 2026-04-22 23:58:41 +02:00
tests feat: add icmp_set_dont_fragment and next_mtu extraction 2026-03-13 03:21:35 +01:00
.gitignore fix(makefile)!: improve flags and type casts for stricter build and correctness 2026-02-07 20:16:06 +01:00
LICENSE chore: update LICENSE 2026-04-23 12:59:58 +02:00
Makefile feat: add -Wshadow to compile commands 2026-04-20 13:42:55 +02:00
README.md feat: icmp_create_block() 2026-04-22 23:58:41 +02:00
sources.mk feat: add icmp_set_dont_fragment and next_mtu extraction 2026-03-13 03:21:35 +01:00

libicmp

ICMPv4 library for building ping, traceroute, and network diagnostic tools. Supports both non-blocking (default) and blocking socket modes.

Dependencies

  • libc
  • GNU make
  • clang
  • POSIX-compliant OS

For tests only:

  • criterion

Build

make # Build static and shared libraries
make BUILD_STATIC=yes BUILD_SHARED=no
make install PREFIX=/usr/local
make test

API

Handle lifecycle

icmp_handle_t *icmp_create(void);
icmp_handle_t *icmp_create_block(void);
void           icmp_destroy(icmp_handle_t *h);
int            icmp_get_fd(const icmp_handle_t *h);

icmp_create() opens a raw ICMP socket in non-blocking mode and returns an opaque handle. icmp_create_block() does the same but leaves the socket in blocking modeicmp_get_fd() exposes the underlying file descriptor for use with select() or poll(). Errors are retrieved via icmp_strerror().

Send

int icmp_send_echo(icmp_handle_t *h, struct in_addr dest, uint16_t id,
                   uint16_t seq, uint8_t ttl,
                   const void *payload, size_t payload_len);

int icmp_send_raw(icmp_handle_t *h, uint8_t type, uint8_t code,
                  uint32_t header_rest,
                  const void *payload, size_t len, struct in_addr dest,
                  uint8_t ttl);

icmp_send_echo() builds and sends an ICMP ECHO_REQUEST with the given id, seq, and payload. icmp_send_raw() sends an arbitrary ICMP packet by type and code.

Receive

typedef void (*icmp_callback_t)(const icmp_reply_t *reply, void *userdata);

int icmp_process(icmp_handle_t *h, icmp_callback_t cb, void *userdata,
                 size_t max_packets);

icmp_process() drains up to max_packets from the socket in a non-blocking loop, invoking cb for each one. The icmp_reply_t passed to the callback contains the ICMP type/code, source address, TTL, timestamp, and payload. Returns the number of packets processed, or -1 on error.

Modules

handle/

Handle lifecycle: icmp_create(), icmp_create_block(), icmp_destroy(), icmp_get_fd(). Owns the opaque icmp_handle_t struct and the error state attached to it.

socket/

Raw socket creation, optional non-blocking configuration (O_NONBLOCK), and the DF (Don't Fragment) flag via IP_MTU_DISCOVER.

send/

Packet building and transmission. Assembles the ICMP header and payload, computes the checksum, and writes to the socket.

recv/

Non-blocking receive loop. Reads datagrams, timestamps each one on arrival, and dispatches them through the caller-supplied callback.

packet/

ICMP and IP packet parsing and building. Extracts fields from raw datagrams, including nested packets inside ICMP error messages (icmp_offending_packet_t).

error/

Error state storage and formatting. Wraps errno and library-specific error codes into a single slot on the handle, exposed via icmp_strerror() and icmp_should_retry().

utils/

RFC 1071 one's-complement checksum and nanosecond time helpers (icmp_get_time(), icmp_time_diff_ns()).

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

Authors

  • lohhiiccc - Git

See Also