#include #include #include #include #include #include #include #include #include #include // TODO put that in the libc somewhere #include "netstack/util.h" enum { PacketSize = 12 * 4, /* 12 words */ ClientMode = 3, NtpV4 = 4 << 3, TxTimestamp = 40, }; uint64_t offset = 0; uint64_t getntptime(const char *addr) { char packet[PacketSize] = {0}; packet[0] |= ClientMode; packet[0] |= NtpV4; hid_t h = camellia_open(addr, OPEN_READ | OPEN_WRITE); if (h < 0) { warn("open %s", addr); return 0; } if (write(h, packet, PacketSize) != PacketSize) { warnx("partial write"); close(h); return 0; } ssize_t ret = read(h, packet, PacketSize); if (ret != PacketSize) { warnx("partial read"); close(h); return 0; } return nget64(packet + TxTimestamp); } /* Converts an NTP timestamp to the amount of nanoseconds (10^-9) since the * Unix epoch. */ uint64_t ntp2unix(uint64_t ntp) { uint64_t seconds = (ntp >> 32) - 2208988800; uint64_t frac = ntp & 0xFFFFFFFF; uint64_t prec = 1000000000; return seconds * prec + ((frac * prec) >> 32); } int main(int argc, const char *argv[]) { if (argc != 2) { errx(1, "bad usage"); } // TODO: error checking, once i actually implement timeouts uint64_t ntpt = getntptime(argv[1]); uint64_t unixt = ntp2unix(ntpt); offset = unixt - _sys_time(0); char buf[256]; int len; struct ufs_request req; hid_t reqh; while ((reqh = ufs_wait(buf, sizeof(buf), &req))) { switch (req.op) { case VFSOP_OPEN: if (req.len == 0 && !OPEN_WRITEABLE(req.flags)) { _sys_fs_respond(reqh, NULL, 0, 0); } else { _sys_fs_respond(reqh, NULL, -EGENERIC, 0); } break; case VFSOP_READ: len = snprintf(buf, sizeof(buf), "%lu\n", _sys_time(0) + offset); if (0 <= len && len < (int)sizeof(buf)) { fs_normslice(&req.offset, &req.len, len, false); _sys_fs_respond(reqh, buf + req.offset, req.len, 0); } else { _sys_fs_respond(reqh, NULL, -EGENERIC, 0); } break; default: _sys_fs_respond(reqh, NULL, -ENOSYS, 0); break; } } }