aboutsummaryrefslogtreecommitdiffstats
path: root/c/ping.c
blob: c98f106bcb6f16f61c16774d56feaa090e656897 (plain) (blame)
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
#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();
        }
    }
    puts("-- "); putu(got); puts("/4 received"); nl();
    net_close(s);
}