#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(); }