diff options
| author | user <user@clank> | 2026-07-17 02:05:26 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-17 02:05:26 +0200 |
| commit | ed752bba5a5d06275531182245737600bf1f72e9 (patch) | |
| tree | ba250a89b079403c55119cd33ce56ec6d2d562ed /tools | |
| parent | net: real IP stack, milestone A - ICMP echo (you can ping a Game Boy) (diff) | |
| download | gbos-ed752bba5a5d06275531182245737600bf1f72e9.tar.gz gbos-ed752bba5a5d06275531182245737600bf1f72e9.tar.xz gbos-ed752bba5a5d06275531182245737600bf1f72e9.zip | |
net: IP stack milestone B - UDP echo (pseudo-header checksum)
Refactor netd into a protocol dispatcher (IP -> ICMP/UDP) and add UDP echo:
swap addresses + ports and recompute the UDP checksum over the pseudo-header
(src/dst IP + proto + length) plus the datagram. This is the same pseudo-
header TCP uses, so it de-risks the next milestone.
tools/gateway.py --mode udp sends a datagram and verifies the echo.
Verified: 'hello udp gbos' echoes back with cksum=ok.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/gateway.py | 28 |
1 files changed, 27 insertions, 1 deletions
diff --git a/tools/gateway.py b/tools/gateway.py index 590526e..f5fc701 100644 --- a/tools/gateway.py +++ b/tools/gateway.py @@ -126,9 +126,19 @@ def icmp_echo(seq, payload=b"gbos-ping-0123456789"): ip = ip[:10] + struct.pack("!H", inet_cksum(ip)) + ip[12:] return ip + icmp +def udp_packet(sport, dport, payload): + ulen = 8 + len(payload) + udp = struct.pack("!HHHH", sport, dport, ulen, 0) + payload + pseudo = GW_IP + GB_IP + bytes([0, 17]) + struct.pack("!H", ulen) + ck = inet_cksum(pseudo + udp) or 0xffff + udp = udp[:6] + struct.pack("!H", ck) + udp[8:] + ip = struct.pack("!BBHHHBBH", 0x45, 0, 20+ulen, 7, 0, 64, 17, 0) + GW_IP + GB_IP + ip = ip[:10] + struct.pack("!H", inet_cksum(ip)) + ip[12:] + return ip + udp + def main(): ap = argparse.ArgumentParser() - ap.add_argument("--mode", default="echo", choices=["echo", "http", "chat", "irc", "ping"]) + ap.add_argument("--mode", default="echo", choices=["echo", "http", "chat", "irc", "ping", "udp"]) ap.add_argument("--cmd", default="necho") ap.add_argument("--nick", default="gameboy") ap.add_argument("--channel", default="#sl0p") @@ -159,6 +169,17 @@ def main(): m = bytes(payload).decode("latin1", "replace") sys.stderr.write("\n[gw] GB says: %s\n" % m) return [("<bot> " + m).encode()] + elif a.mode == "udp": + def on_frame(payload): + p = bytes(payload) + if len(p) >= 28 and p[9] == 17: + ihl = (p[0] & 0x0f) * 4 + sport, dport, ulen = struct.unpack("!HHH", p[ihl:ihl+6]) + data = p[ihl+8:ihl+8+ulen-8] + ck_ok = inet_cksum(GB_IP + GW_IP + bytes([0,17]) + p[ihl+4:ihl+6] + p[ihl:]) == 0 + sys.stderr.write("\n[gw] UDP echo %d->%d: %r cksum=%s\n" + % (sport, dport, data, "ok" if ck_ok else "BAD")) + return [] elif a.mode == "ping": def on_frame(payload): p = bytes(payload) @@ -183,6 +204,11 @@ def main(): except Exception: pass irc_holder[0] = IRC(a.host, a.port, a.nick, a.channel, to_gb) threading.Thread(target=irc_holder[0].loop, daemon=True).start() + if a.mode == "udp": + time.sleep(1.0) + p.stdin.write(slip_encode(udp_packet(5000, 7, b"hello udp gbos"))); p.stdin.flush() + sys.stderr.write("[gw] sent UDP :5000->:7 'hello udp gbos'\n") + time.sleep(2.0) if a.mode == "ping": time.sleep(1.0) for seq in range(1, 5): |
