Crate async_icmp

Source
Expand description

An unprivileged async ICMP socket library for macOS and Linux using tokio.

This uses PROT_ICMP sockets, so root is not needed, though on Linux access to that socket type is limited by a sysctl (see Linux link below). Some distros set the sysctl to allow all users access out of the box, while others will need configuration.

See also:

§Getting started

§Features

§Platform differences

See platform for functions to help you understand what behavior to expect on a given platform.

The links above for Linux and macOS sockets are helpful for more detail, but here’s the short version.

§Linux

  • You can only send Echo messages. Those messages will have their id field overwritten with the local socket’s port.
  • Reading messages only provides Echo Reply messages with a matching id (aka port).
  • Calculating checksums is not required.
  • IPv6 works like IPv4.

§macOS

  • You can use any id with your Echo messages.
  • Reading messages appears to be more or less unfiltered. You’ll read the Echo you sent, as well as the Echo Reply that may eventually arrive, regardless of its id.
  • IPv4 sent messages must have the checksum set (done by this library)
  • When reading IPv4 messages, the IPv4 headers are included as a prefix (stripped off by the library)
  • IPv6 appears to be less reliable than IPv4 – higher packet rates tend to cause packet loss as of macOS 15.2. See exampes/packet_loss.rs to try it on your system.

§Examples

These show the simplest possible usage. See the rest of the docs for more.

§Sending a single Echo

use std::{error, net};
use async_icmp::{Icmpv4,
    message::echo::{IcmpEchoRequest, EchoId, EchoSeq},
    socket::{IcmpSocket, SocketConfig}};

async fn send_ping() -> Result<(), Box<dyn error::Error>> {
    let socket = IcmpSocket::<Icmpv4>::new(SocketConfig::default())?;
    let mut echo = IcmpEchoRequest::from_fields(EchoId::from_be(100), EchoSeq::from_be(200), b"data");
    socket.send_to( &mut echo, net::Ipv4Addr::LOCALHOST).await?;

    Ok(())
}

§Receiving an ICMP message

use async_icmp::{Icmpv4,
    message::{decode::DecodedIcmpMsg, IcmpV4MsgType},
    socket::{IcmpSocket, SocketConfig}};
use std::error;

async fn receive_and_decode() -> Result<(), Box<dyn error::Error>> {
    let s = IcmpSocket::<Icmpv4>::new(SocketConfig::default())?;
    let mut buf = vec![0; 10_000];
    let (msg, _range) = s.recv(&mut buf).await?;
    // decode basic ICMP structure, or use raw bytes in `msg` as needed
    let decoded = DecodedIcmpMsg::decode(msg)?;
    if decoded.msg_type() == IcmpV4MsgType::SourceQuench as u8 {
        // decode body as source quench, if that's the msg type you want
    }
    // ... handle other msg types
    Ok(())
}

Modules§

message
ICMP message encoding and decoding.
ping
High level “ping” (ICMP Echo / Echo Reply) API, built on top of the rest of this library.
platform
Helper functions to query pertinent platform-dependent behaviors.
socket
ICMP socket support.

Structs§

Icmpv4
ICMPv4 marker impl of IcmpVersion.
Icmpv6
ICMPv6 marker impl of IcmpVersion.

Enums§

IpVersion
The IP version used by a socket or IP address.

Traits§

IcmpVersion
Trait abstracting over ICMPv4 and ICMPv6 behavior