aboutsummaryrefslogtreecommitdiffstats
path: root/c/ping.c
diff options
context:
space:
mode:
authoruser <user@clank>2026-07-17 19:45:13 +0200
committeruser <user@clank>2026-07-17 19:45:13 +0200
commit4f038ecad87777bc1d74f8f93f267da8cd396446 (patch)
tree28332e362bb8c1c75e97483af21c51cc13cffdac /c/ping.c
parentdocs: investigation notes for the idle link-socket drop (open bug) (diff)
downloadgbos-4f038ecad87777bc1d74f8f93f267da8cd396446.tar.gz
gbos-4f038ecad87777bc1d74f8f93f267da8cd396446.tar.xz
gbos-4f038ecad87777bc1d74f8f93f267da8cd396446.zip
net: unbreak ping against hosts that intermittently drop ICMP
Pinging sl0p.foo through gbhub looked hung: DNS resolved, then nothing. Packet-tracing showed the echo request leaving the hub's TUN and eth0 correctly NATed every time - but 80.78.19.56 blackholes ICMP for all ids in windows of tens of seconds (provider rate limiting). One lost reply wedged ping for minutes because net_recv's pump-counted timeout is effectively unbounded at native emulation speed. Two fixes: - NET_RECVNB (op 8): non-blocking recv - one RX pump, $FE if nothing buffered, same delivery/EOF semantics as NET_RECV otherwise. ping now waits <=~2s per seq (net_recv_nb + msleep loop), prints 'seq=N timeout' and moves on, like real ping. - ICMP echo id was hardcoded $1234 for every GB, every boot, so all sessions produced byte-identical flows - hostile to NAT conntrack (keyed on icmp id). wNetEchoId is now our host octet + rDIV timing noise sampled at DHCP lease, distinct per GB and per boot. Verified: 8 back-to-back native-speed gbhub runs, zero hangs; a run that hit a blackhole window printed seq=1 timeout then recovered to 3/4 received. GB<->GB ping and DNS/DHCP unaffected.
Diffstat (limited to '')
-rw-r--r--c/ping.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/c/ping.c b/c/ping.c
index f8d5bf7..8671318 100644
--- a/c/ping.c
+++ b/c/ping.c
@@ -14,6 +14,19 @@ static void put_ip(unsigned char *ip) {
for (i = 0; i < 4; i++) { putu(ip[i]); if (i < 3) putc('.'); }
}
+/* wait up to ~2s for an echo reply without blocking in the kernel: a lost
+ reply (some hosts rate-limit ICMP) must cost one "timeout" line, not
+ minutes wedged inside net_recv's pump-counted wait. */
+static unsigned char wait_reply(unsigned char s) {
+ unsigned char t, r;
+ for (t = 0; t < 40; t++) {
+ r = net_recv_nb(s, rbuf, (unsigned char)sizeof(rbuf));
+ if (r != 0xFE) return r; /* reply (or error) */
+ msleep(50);
+ }
+ return 0xFF; /* ~2s with no reply */
+}
+
void main(void) {
char *arg;
unsigned char s, seq, got = 0, i;
@@ -35,7 +48,7 @@ void main(void) {
puts("PING "); put_ip(dst); nl();
for (seq = 1; seq <= 4; seq++) {
net_send(s, payload, 4);
- if (net_recv(s, rbuf, (unsigned char)sizeof(rbuf)) != 0xFF) {
+ if (wait_reply(s) != 0xFF) {
got++;
puts(" reply from "); put_ip(dst); puts(" seq="); putu(seq); nl();
} else {