aboutsummaryrefslogtreecommitdiffstats
path: root/usr/ntpdate.c
blob: bbeeb927d43cb3b0821e7291e84000da5ef35098 (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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "resolve.h"
/* ntpdate [SERVER]: set the clock from SNTP (default pool.ntp.org).
 *
 * An MBC5 cart has no RTC, so this is the only way gbos can know the real
 * time. One 48-byte UDP exchange with port 123: the reply's transmit
 * timestamp is seconds since 1900, and unix time is that minus 2208988800.
 * The kernel keeps the stamp plus the tick it arrived at (SYS_SETTIME), so
 * date(1) can add the elapsed ticks back.
 *
 * The clock does not survive a power cycle - put ntpdate in /rc. */

#define NTP_PORT      123
#define UNIX_EPOCH_HI 0x8383 /* 2208988800 = 0x83AA7E80 */

static unsigned char pkt[48];
static unsigned char namebuf[64];
static unsigned char srv[4];
static unsigned char now[4];

void main(void) {
    char args[40];
    unsigned char s, n, i;

    {
        char *a = getargs();
        for (i = 0; a[i] && i < 39; i++) args[i] = a[i];
        args[i] = 0;
    }
    if (!args[0]) {
        const char *d = "pool.ntp.org";
        for (i = 0; d[i]; i++) args[i] = d[i];
        args[i] = 0;
    }
    for (i = 0; args[i] && i < 63; i++) namebuf[i] = (unsigned char)args[i];
    namebuf[i] = 0;

    if (!resolve((char *)namebuf, srv)) {
        puts("ntpdate: cannot resolve ");
        puts((char *)namebuf);
        nl();
        sexit(1);
    }
    for (i = 0; i < 48; i++) pkt[i] = 0;
    pkt[0] = 0x1B; /* LI=0, VN=3, mode=3 (client) */

    s = net_socket(SOCK_UDP);
    if (s == 0xFF) {
        puts("ntpdate: no socket");
        nl();
        sexit(1);
    }
    net_bind(s, 40123);
    net_connect(s, srv, NTP_PORT);
    net_send(s, pkt, 48);
    n = net_recv(s, pkt, 48);
    net_close(s);
    if (n == 0xFF || n < 48) {
        puts("ntpdate: no reply");
        nl();
        sexit(1);
    }

    /* transmit timestamp: seconds since 1900 at bytes 40..43, big-endian.
       unix = ntp - 2208988800 ($83AA7E80), done bytewise - no long math. */
    {
        unsigned char b0 = pkt[43], b1 = pkt[42], b2 = pkt[41], b3 = pkt[40];
        unsigned int t;
        t = (unsigned int)b0 - 0x80;
        now[0] = (unsigned char)t;
        t = (unsigned int)b1 - 0x7E - ((t >> 8) & 1);
        now[1] = (unsigned char)t;
        t = (unsigned int)b2 - 0xAA - ((t >> 8) & 1);
        now[2] = (unsigned char)t;
        t = (unsigned int)b3 - 0x83 - ((t >> 8) & 1);
        now[3] = (unsigned char)t;
    }
    settime(now);
    puts("ntpdate: clock set from ");
    puts((char *)namebuf);
    nl();
}