1use std::{
15 net::Ipv4Addr,
16 time::{Duration, Instant},
17};
18
19use icmp_socket::packet::WithEchoRequest;
20use icmp_socket::socket::IcmpSocket;
21use icmp_socket::*;
22
23pub fn main() {
24 let address = std::env::args().nth(1).unwrap_or("127.0.0.1".to_owned());
25 let parsed_addr = address.parse::<Ipv4Addr>().unwrap();
26 let packet_handler = |pkt: Icmpv4Packet, send_time: Instant, addr: Ipv4Addr| -> Option<()> {
27 let now = Instant::now();
28 let elapsed = now - send_time;
29 if addr == parsed_addr {
30 if let Icmpv4Message::EchoReply {
32 identifier: _,
33 sequence,
34 payload,
35 } = pkt.message
36 {
37 println!(
38 "Ping {} seq={} time={}ms size={}",
39 addr,
40 sequence,
41 (elapsed.as_micros() as f64) / 1000.0,
42 payload.len()
43 );
44 } else {
45 return None;
47 }
48 Some(())
49 } else {
50 eprintln!("Discarding packet from {}", addr);
51 None
52 }
53 };
54 let mut socket4 = IcmpSocket4::new().unwrap();
55 socket4
56 .bind("0.0.0.0".parse::<Ipv4Addr>().unwrap())
57 .unwrap();
58 let mut sequence = 0 as u16;
61 loop {
62 let packet = Icmpv4Packet::with_echo_request(
63 42,
64 sequence,
65 vec![
66 0x20, 0x20, 0x75, 0x73, 0x74, 0x20, 0x61, 0x20, 0x66, 0x6c, 0x65, 0x73, 0x68, 0x20,
67 0x77, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x20, 0x74, 0x69, 0x73, 0x20, 0x62, 0x75, 0x74,
68 0x20, 0x61, 0x20, 0x73, 0x63, 0x72, 0x61, 0x74, 0x63, 0x68, 0x20, 0x20, 0x6b, 0x6e,
69 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x6e, 0x69, 0x20, 0x20, 0x20,
70 ],
71 )
72 .unwrap();
73 let send_time = Instant::now();
74 socket4
75 .send_to(address.parse::<Ipv4Addr>().unwrap(), packet)
76 .unwrap();
77 socket4.set_timeout(Some(Duration::from_secs(1)));
78 loop {
79 let (resp, sock_addr) = match socket4.rcv_from() {
80 Ok(tpl) => tpl,
81 Err(e) => {
82 eprintln!("{:?}", e);
83 break;
84 }
85 };
86 if packet_handler(resp, send_time, *sock_addr.as_socket_ipv4().unwrap().ip()).is_some()
87 {
88 std::thread::sleep(Duration::from_secs(1));
89 break;
90 }
91 }
92 sequence = sequence.wrapping_add(1);
93 }
94}