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:
examples/ping.rs
for how to use this library to build a fairly complete ping CLI tool.- Linux
PROT_ICMP
sockets: https://lwn.net/Articles/443051/ - macOS
PROT_ICMP
sockets: http://www.manpagez.com/man/4/icmp/ - ICMPv4: https://www.rfc-editor.org/rfc/rfc792
- ICMPv6: https://www.rfc-editor.org/rfc/rfc4443
§Getting started
- Open an
socket::IcmpSocket
- Create a suitable
message::echo::IcmpEchoRequest
or other impl ofmessage::EncodeIcmpMessage
and send it with the socket - Handle received ICMP messages, either as raw bytes or with
message::decode::DecodedIcmpMsg
- Or, if you just want to ping (aka ICMP Echo), see
ping
for high-level ping-specific functionality.
§Features
rand
(enabled by default): Generate randommessage::echo::EchoId
s conveniently. Adds a dependency onrand
§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§
- Icmp
Version - Trait abstracting over ICMPv4 and ICMPv6 behavior