aboutsummaryrefslogtreecommitdiffstats
path: root/c/ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/ping.c')
-rw-r--r--c/ping.c85
1 files changed, 19 insertions, 66 deletions
diff --git a/c/ping.c b/c/ping.c
index 12dabd9..c98f106 100644
--- a/c/ping.c
+++ b/c/ping.c
@@ -1,17 +1,14 @@
-#include "netlib.h"
-/* ping - originate ICMP echo requests from the Game Boy (10.0.0.2) and print
- the replies. Target defaults to 10.0.0.1 (the SLIP peer / host); with NAT on
- the bridge it can reach real internet hosts too. Usage: ping [A.B.C.D] */
+#include "sock.h"
+/* ping - originate ICMP echo requests via the kernel socket layer. No SLIP,
+ no IP, no checksums here: the kernel owns all of that. Usage: ping [A.B.C.D]
+ (default 10.0.0.1, the SLIP peer/host; reaches real hosts through NAT). */
-static unsigned char pkt[128];
+/* rbuf is declared first (and large) so the parse target dst[] lands well past
+ the argument string the shell leaves at 0xA000 - writing dst must not clobber
+ the arg while we're still reading it. */
+static unsigned char rbuf[96];
static unsigned char dst[4];
-
-static unsigned int sum16(unsigned char *d, unsigned int len, unsigned int sum) {
- unsigned int w, i = 0;
- while (i + 1 < len) { w = ((unsigned int)d[i] << 8) | d[i + 1]; sum += w; if (sum < w) sum++; i += 2; }
- if (len & 1) { w = (unsigned int)d[len - 1] << 8; sum += w; if (sum < w) sum++; }
- return sum;
-}
+static unsigned char payload[4];
static unsigned char parse_ip(char *s, unsigned char *out) {
unsigned char i, v;
@@ -24,77 +21,33 @@ static unsigned char parse_ip(char *s, unsigned char *out) {
}
return 1;
}
-
static void put_ip(unsigned char *ip) {
unsigned char i;
for (i = 0; i < 4; i++) { putu(ip[i]); if (i < 3) putc('.'); }
}
-static void send_echo(unsigned char seq) {
- unsigned int c;
- pkt[0] = 0x45; pkt[1] = 0; pkt[2] = 0; pkt[3] = 28; /* 20 IP + 8 ICMP */
- pkt[4] = 0; pkt[5] = 0; pkt[6] = 0; pkt[7] = 0;
- pkt[8] = 64; pkt[9] = 1; pkt[10] = 0; pkt[11] = 0; /* TTL, proto ICMP */
- pkt[12] = 10; pkt[13] = 0; pkt[14] = 0; pkt[15] = 2; /* src 10.0.0.2 */
- pkt[16] = dst[0]; pkt[17] = dst[1]; pkt[18] = dst[2]; pkt[19] = dst[3];
- c = ~sum16(pkt, 20, 0); pkt[10] = (unsigned char)(c >> 8); pkt[11] = (unsigned char)c;
- pkt[20] = 8; pkt[21] = 0; pkt[22] = 0; pkt[23] = 0; /* echo request */
- pkt[24] = 0x12; pkt[25] = 0x34; pkt[26] = 0; pkt[27] = seq;
- c = ~sum16(pkt + 20, 8, 0); pkt[22] = (unsigned char)(c >> 8); pkt[23] = (unsigned char)c;
- slip_send((char *)pkt, 28);
-}
-
-/* wait for the ICMP echo reply for 'seq', skipping unrelated frames (the shared
- 10.0.0.0/24 carries IGMP/mDNS/SSDP noise). Returns 1 on match, 0 on timeout.
- The emulator runs uncapped, so the spin budget is generous to span the
- wall-clock round trip through the host bridge. */
-static unsigned char ping_wait(unsigned char seq) {
- unsigned int o, i;
- unsigned char len = 0, c, ihl;
- int b;
- for (o = 0; o < 20; o++) {
- for (i = 0; i < 60000; i++) {
- b = srecv_nb();
- if (b < 0) continue;
- c = (unsigned char)b;
- if (c == SLIP_END) {
- if (len) {
- ihl = (unsigned char)((pkt[0] & 0x0f) << 2);
- if (len >= (unsigned char)(ihl + 8) && pkt[9] == 1
- && pkt[ihl] == 0 && pkt[ihl + 7] == seq) return 1;
- len = 0; /* not ours - keep waiting */
- }
- continue;
- }
- if (c == SLIP_ESC) {
- c = srecv();
- if (c == SLIP_ESC_END) c = SLIP_END;
- else if (c == SLIP_ESC_ESC) c = SLIP_ESC;
- }
- if (len < 128) pkt[len++] = c; else len = 0;
- }
- }
- return 0;
-}
-
void main(void) {
char *arg;
- unsigned char seq, got = 0;
+ unsigned char s, seq, got = 0;
arg = getargs();
if (!arg || !*arg) { dst[0] = 10; dst[1] = 0; dst[2] = 0; dst[3] = 1; }
else if (!parse_ip(arg, dst)) { puts("ping: bad address"); nl(); sexit(1); }
+ payload[0] = 'g'; payload[1] = 'b'; payload[2] = 'o'; payload[3] = 's';
+ s = net_socket(SOCK_ICMP);
+ if (s == 0xFF) { puts("ping: no socket"); nl(); sexit(1); }
+ net_connect(s, dst, 0);
+
puts("PING "); put_ip(dst); nl();
for (seq = 1; seq <= 4; seq++) {
- send_echo(seq);
- if (ping_wait(seq)) {
+ net_send(s, payload, 4);
+ if (net_recv(s, rbuf, sizeof(rbuf)) != 0xFF) {
got++;
- puts(" reply from "); put_ip(pkt + 12);
- puts(" seq="); putu(seq);
- puts(" ttl="); putu(pkt[8]); nl();
+ puts(" reply from "); put_ip(dst); puts(" seq="); putu(seq); nl();
} else {
puts(" seq="); putu(seq); puts(" timeout"); nl();
}
}
puts("-- "); putu(got); puts("/4 received"); nl();
+ net_close(s);
}