#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). */ /* 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 char payload[4]; static unsigned char parse_ip(char *s, unsigned char *out) { unsigned char i, v; for (i = 0; i < 4; i++) { if (*s < '0' || *s > '9') return 0; v = 0; while (*s >= '0' && *s <= '9') { v = (unsigned char)(v * 10 + (*s - '0')); s++; } out[i] = v; if (i < 3) { if (*s != '.') return 0; s++; } } 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('.'); } } void main(void) { char *arg; 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++) { net_send(s, payload, 4); if (net_recv(s, rbuf, sizeof(rbuf)) != 0xFF) { got++; puts(" reply from "); put_ip(dst); puts(" seq="); putu(seq); nl(); } else { puts(" seq="); putu(seq); puts(" timeout"); nl(); } if (seq < 4) msleep(800); /* pace like real ping */ } puts("-- "); putu(got); puts("/4 received"); nl(); net_close(s); }