1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
| #![no_std]
#![no_main]
#[macro_use]
#[path = "../../../rbrt/ulib.rs"]
mod ulib;
const PAYLOAD: usize = 56;
fn main() -> i64 {
let mut count = 4u16;
let mut interval_ms = 1000;
let mut host = None;
let mut i = 1;
while let Some(a) = ulib::arg(i) {
match a {
"-c" => { i += 1; count = ulib::arg(i).and_then(|v| v.parse().ok()).unwrap_or(4); }
"-i" => { i += 1; interval_ms = ulib::arg(i).and_then(|v| v.parse().ok()).unwrap_or(1000); }
_ => host = Some(a),
}
i += 1;
}
let Some(host) = host else {
eprintln!("usage: ping [-c count] [-i interval_ms] host");
return 2;
};
let ip = match ulib::resolve(host) {
Ok(ip) => ip,
Err(e) => {
eprintln!("ping: {}: {}", host, ulib::strerror(e));
return 2;
}
};
let fd = ulib::socket(ulib::SOCK_DGRAM, ulib::IPPROTO_ICMP);
if fd < 0 {
eprintln!("ping: socket: {}", ulib::strerror(fd));
return 2;
}
ulib::set_recv_timeout(fd, 1000); println!("PING {} ({}): {} data bytes", host, ip, PAYLOAD);
let (mut received, mut min, mut max, mut total) = (0u64, u64::MAX, 0u64, 0u64);
for seq in 1..=count {
let mut packet = [0u8; 8 + PAYLOAD];
packet[0] = 8;
packet[6..8].copy_from_slice(&seq.to_be_bytes());
for (j, b) in packet[8..].iter_mut().enumerate() {
*b = j as u8; }
let sent_at = ulib::now_us();
let n = ulib::sendto(fd, &packet, ip, 0);
if n < 0 {
eprintln!("ping: sendto: {}", ulib::strerror(n));
return 2;
}
let mut reply = [0u8; 8 + PAYLOAD + 64];
loop {
let (n, from) = ulib::recvfrom(fd, &mut reply);
if n < 0 {
println!("Request timeout for icmp_seq={}", seq);
break;
}
let n = n as usize;
if n >= 8 && reply[0] == 0 && reply[6..8] == seq.to_be_bytes() {
let us = ulib::now_us() - sent_at;
let ok = reply[8..n] == packet[8..];
println!(
"{} bytes from {}: icmp_seq={} time={}.{:02} ms{}",
n, from.ip(), seq, us / 1000, us % 1000 / 10,
if ok { "" } else { " (payload differs!)" }
);
received += 1;
(min, max, total) = (min.min(us), max.max(us), total + us);
break;
}
}
if seq < count {
ulib::sleep_ms(interval_ms);
}
}
ulib::close(fd);
let loss = (count as u64 - received) * 100 / count.max(1) as u64;
println!("--- {} ping statistics ---", host);
println!("{} packets transmitted, {} received, {}% packet loss", count, received, loss);
if received > 0 {
let avg = total / received;
println!(
"rtt min/avg/max = {}.{:02}/{}.{:02}/{}.{:02} ms",
min / 1000, min % 1000 / 10, avg / 1000, avg % 1000 / 10, max / 1000, max % 1000 / 10
);
}
if received > 0 { 0 } else { 1 }
}
|