use std::{
net::Ipv6Addr,
time::{Duration, Instant},
};
use icmp_socket::packet::WithEchoRequest;
use icmp_socket::socket::IcmpSocket;
use icmp_socket::*;
pub fn main() {
let address = std::env::args().nth(1).unwrap_or("::1".to_owned());
let parsed_addr = address.parse::<Ipv6Addr>().unwrap();
let packet_handler = |pkt: Icmpv6Packet, send_time: Instant, addr: Ipv6Addr| -> Option<()> {
let now = Instant::now();
let elapsed = now - send_time;
if addr == parsed_addr {
if let Icmpv6Message::EchoReply {
identifier: _,
sequence,
payload,
} = pkt.message
{
println!(
"Ping {} seq={} time={}ms size={}",
addr,
sequence,
(elapsed.as_micros() as f64) / 1000.0,
payload.len()
);
} else {
return None;
}
Some(())
} else {
eprintln!("Discarding packet from {}", addr);
None
}
};
let mut socket6 = IcmpSocket6::new().unwrap();
socket6.bind("::0".parse::<Ipv6Addr>().unwrap()).unwrap();
let mut sequence = 0 as u16;
loop {
let packet = Icmpv6Packet::with_echo_request(
42,
sequence,
vec![
0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20,
0x77, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, 0x20, 0x62, 0x75, 0x74,
0x20, 0x61, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, 0x6b, 0x6e,
0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20,
],
)
.unwrap();
let send_time = Instant::now();
socket6
.send_to(address.parse::<Ipv6Addr>().unwrap(), packet)
.unwrap();
socket6.set_timeout(Some(Duration::from_secs(1)));
loop {
let (resp, sock_addr) = match socket6.rcv_from() {
Ok(tpl) => tpl,
Err(e) => {
eprintln!("{:?}", e);
break;
}
};
if packet_handler(resp, send_time, *sock_addr.as_socket_ipv6().unwrap().ip()).is_some()
{
std::thread::sleep(Duration::from_millis(1000));
break;
}
}
sequence = sequence.wrapping_add(1);
}
}