diff --git a/patches/.gitattributes b/patches/.gitattributes new file mode 100644 index 0000000..da08186 --- /dev/null +++ b/patches/.gitattributes @@ -0,0 +1 @@ +*.patch linguist-language=c diff --git a/patches/1-patch_better-logs.patch b/patches/1-patch_better-logs.patch new file mode 100644 index 0000000..5cadd36 --- /dev/null +++ b/patches/1-patch_better-logs.patch @@ -0,0 +1,2248 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Provide human-readable error messages for easier process interpretation + + +--- a/src/client.c 2020-08-01 00:19:23.432392415 +0300 ++++ b/src/client.c 2020-08-02 02:02:37.850286445 +0300 +@@ -52,7 +52,7 @@ int + client_peer_init(struct ntp_peer *p) + { + if ((p->query = calloc(1, sizeof(struct ntp_query))) == NULL) +- fatal("client_peer_init calloc"); ++ fatal("NTP client: can't allocate memory for a new NTP peer connection"); + p->query->fd = -1; + p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3); + p->state = STATE_NONE; +@@ -86,9 +86,14 @@ client_addr_init(struct ntp_peer *p) + p->state = STATE_DNS_DONE; + break; + default: +- fatalx("king bula sez: wrong AF in client_addr_init"); ++ fatalx("NTP client: NTP peer %s has wrong network address family", ++ p->addr_head.name ++ ); + /* NOTREACHED */ + } ++ log_info("NTP client: DNS query found IP address %s for NTP peer %s", ++ log_sockaddr((struct sockaddr *)&h->ss), ++ p->addr_head.name); + } + + p->query->fd = -1; +@@ -129,6 +134,16 @@ int + client_query(struct ntp_peer *p) + { + int val; ++ struct ntp_addr *h; ++ h = p->addr; ++/* ++ if (h != NULL) { ++ ++ log_debug("NTP client: listening on NTP peer %s on remote UDP port %d", ++ log_sockaddr((struct sockaddr *)&h->ss), ++ p->addr_head.port); ++ } ++*/ + + if (p->addr == NULL && client_nextaddr(p) == -1) { + if (conf->settime) +@@ -156,21 +171,23 @@ client_query(struct ntp_peer *p) + p->query->fd = socket(p->addr->ss.ss_family, SOCK_DGRAM, 0); + if (p->query->fd == -1) { + if (errno == EAFNOSUPPORT) { +- log_warn("client_query socket"); ++ log_warn("NTP client: can't create UDP socket"); + client_nextaddr(p); + set_next(p, error_interval()); + return (-1); + } else +- fatal("client_query socket"); ++ fatal("NTP client: NTP peer has unknown network address family %s", ++ log_sockaddr((struct sockaddr *)&h->ss) ++ ); + } + + if (p->addr->ss.ss_family == qa4->sa_family) { + if (bind(p->query->fd, qa4, SA_LEN(qa4)) == -1) +- fatal("couldn't bind to IPv4 query address: %s", ++ fatal("NTP client: can't bind to NTP peer IPv4 query address %s", + log_sockaddr(qa4)); + } else if (p->addr->ss.ss_family == qa6->sa_family) { + if (bind(p->query->fd, qa6, SA_LEN(qa6)) == -1) +- fatal("couldn't bind to IPv6 query address: %s", ++ fatal("NTP client: can't bind to NTP peer IPv6 query address %s", + log_sockaddr(qa6)); + } + +@@ -187,17 +204,17 @@ client_query(struct ntp_peer *p) + p->senderrors++; + return (-1); + } else +- fatal("client_query connect"); ++ fatal("NTP client: can't connect to NTP peer due to socket error"); + } + val = IPTOS_LOWDELAY; + if (p->addr->ss.ss_family == AF_INET && setsockopt(p->query->fd, + IPPROTO_IP, IP_TOS, &val, sizeof(val)) == -1) +- log_warn("setsockopt IPTOS_LOWDELAY"); ++ log_warn("NTP client: can't set NTP peer IPv4 socket field IP_TOS"); + #ifdef SO_TIMESTAMP + val = 1; + if (setsockopt(p->query->fd, SOL_SOCKET, SO_TIMESTAMP, + &val, sizeof(val)) == -1) +- fatal("setsockopt SO_TIMESTAMP"); ++ fatal("NTP client: can't set NTP peer IPv4 socket control option SO_TIMESTAMP"); + #endif + } + +@@ -256,7 +273,7 @@ handle_auto(uint8_t trusted, double offs + + if (offset < AUTO_THRESHOLD) { + /* don't bother */ +- priv_settime(0, "offset is negative or close enough"); ++ priv_settime(0, "NTP client: NTP peer offset is negative or close enough"); + return; + } + /* collect some more */ +@@ -305,21 +322,21 @@ client_dispatch(struct ntp_peer *p, u_in + errno == ENETUNREACH || errno == ENETDOWN || + errno == ECONNREFUSED || errno == EADDRNOTAVAIL || + errno == ENOPROTOOPT || errno == ENOENT) { +- client_log_error(p, "recvmsg", errno); ++ client_log_error(p, "socket message reception", errno); + set_next(p, error_interval()); + return (0); + } else +- fatal("recvfrom"); ++ fatal("NTP client: can't get socket message for an unknown reason"); + } + + if (somsg.msg_flags & MSG_TRUNC) { +- client_log_error(p, "recvmsg packet", EMSGSIZE); ++ client_log_error(p, "socket packet message reception", EMSGSIZE); + set_next(p, error_interval()); + return (0); + } + + if (somsg.msg_flags & MSG_CTRUNC) { +- client_log_error(p, "recvmsg control data", E2BIG); ++ client_log_error(p, "socket control data message reception", E2BIG); + set_next(p, error_interval()); + return (0); + } +@@ -359,7 +376,7 @@ client_dispatch(struct ntp_peer *p, u_in + } + interval = error_interval(); + set_next(p, interval); +- log_info("reply from %s: not synced (%s), next query %llds", ++ log_info("NTP client: reply from %-16s is not synced (%s), next query in %llds", + log_sockaddr((struct sockaddr *)&p->addr->ss), s, + (long long)interval); + return (0); +@@ -387,7 +404,7 @@ client_dispatch(struct ntp_peer *p, u_in + /* Detect liars */ + if (!p->trusted && conf->constraint_median != 0 && + (constraint_check(T2) != 0 || constraint_check(T3) != 0)) { +- log_info("reply from %s: constraint check failed", ++ log_info("NTP client: reply from %-16s constraint check failed", + log_sockaddr((struct sockaddr *)&p->addr->ss)); + set_next(p, error_interval()); + return (0); +@@ -399,8 +416,8 @@ client_dispatch(struct ntp_peer *p, u_in + if (p->reply[p->shift].delay < 0) { + interval = error_interval(); + set_next(p, interval); +- log_info("reply from %s: negative delay %fs, " +- "next query %llds", ++ log_info("NTP client: reply from %-16s has negative delay %9fs, " ++ "next query in %llds", + log_sockaddr((struct sockaddr *)&p->addr->ss), + p->reply[p->shift].delay, (long long)interval); + return (0); +@@ -449,13 +466,13 @@ client_dispatch(struct ntp_peer *p, u_in + if (p->trustlevel < TRUSTLEVEL_MAX) { + if (p->trustlevel < TRUSTLEVEL_BADPEER && + p->trustlevel + 1 >= TRUSTLEVEL_BADPEER) +- log_info("peer %s now valid", ++ log_info("NTP client: NTP peer %s is valid now", + log_sockaddr((struct sockaddr *)&p->addr->ss)); + p->trustlevel++; + } + +- log_debug("reply from %s: offset %f delay %f, " +- "next query %llds", ++ log_debug("NTP client: reply from %-16s offset: %9fs, delay: %9fs, " ++ "next query in %llds", + log_sockaddr((struct sockaddr *)&p->addr->ss), + p->reply[p->shift].offset, p->reply[p->shift].delay, + (long long)interval); +@@ -518,9 +535,9 @@ client_log_error(struct ntp_peer *peer, + + address = log_sockaddr((struct sockaddr *)&peer->addr->ss); + if (peer->lasterror == error) { +- log_debug("%s %s: %s", operation, address, strerror(error)); ++ log_debug("NTP client: NTP peer %s, error in %s: %s", operation, address, strerror(error)); + return; + } + peer->lasterror = error; +- log_warn("%s %s", operation, address); ++ log_warn("NTP client: NTP peer %s, error in %s", operation, address); + } +--- a/src/config.c 2020-08-01 00:19:23.449059082 +0300 ++++ b/src/config.c 2020-07-31 23:11:30.429054797 +0300 +@@ -44,7 +44,7 @@ host(const char *s, struct ntp_addr **hn + + if (!strcmp(s, "*")) { + if ((h = calloc(1, sizeof(*h))) == NULL) +- fatal(NULL); ++ fatal("can't allocate memory for NTP peer address"); + } else { + if ((h = host_ip(s)) == NULL) { + non_numeric = 1; +@@ -69,7 +69,7 @@ host_ip(const char *s) + if (res->ai_family == AF_INET || + res->ai_family == AF_INET6) { + if ((h = calloc(1, sizeof(*h))) == NULL) +- fatal(NULL); ++ fatal("can't allocate memory for NTP peer IP address"); + memcpy(&h->ss, res->ai_addr, res->ai_addrlen); + } + freeaddrinfo(res); +@@ -110,7 +110,7 @@ host_dns1(const char *s, struct ntp_addr + return (0); + } + if (error) { +- log_warnx("could not parse \"%s\": %s", s, ++ log_warnx("DNS process: can't parse \"%s\": %s", s, + gai_strerror(error)); + return (-1); + } +@@ -120,7 +120,7 @@ host_dns1(const char *s, struct ntp_addr + res->ai_family != AF_INET6) + continue; + if ((h = calloc(1, sizeof(*h))) == NULL) +- fatal(NULL); ++ fatal("DNS process: can't allocate memory for NTP peer address"); + memcpy(&h->ss, res->ai_addr, res->ai_addrlen); + h->notauth = notauth; + +@@ -139,19 +139,19 @@ host_dns(const char *s, int synced, stru + { + int error; + +- log_debug("trying to resolve %s", s); ++ log_debug("DNS process: trying to resolve %s", s); + error = host_dns1(s, hn, 0); + #ifdef RES_USE_CD + if (!synced && error <= 0) { + int save_opts; +- log_debug("no luck, trying to resolve %s without checking", s); ++ log_debug("DNS process: trying to resolve %s without checking", s); + save_opts = _res.options; + _res.options |= RES_USE_CD; + error = host_dns1(s, hn, 1); + _res.options = save_opts; + } + #endif +- log_debug("resolve %s done: %d", s, error); ++ log_debug("DNS process: resolve for %s done: %d", s, error); + return error; + } + +@@ -161,7 +161,7 @@ new_peer(void) + struct ntp_peer *p; + + if ((p = calloc(1, sizeof(struct ntp_peer))) == NULL) +- fatal("new_peer calloc"); ++ fatal("NTP client: can't allocate memory for a new NTP peer"); + p->id = ++maxid; + + return (p); +@@ -173,9 +173,9 @@ new_sensor(char *device) + struct ntp_conf_sensor *s; + + if ((s = calloc(1, sizeof(struct ntp_conf_sensor))) == NULL) +- fatal("new_sensor calloc"); ++ fatal("sensor: can't allocate memory for a new sensor"); + if ((s->device = strdup(device)) == NULL) +- fatal("new_sensor strdup"); ++ fatal("sensor: can't duplicate memory address for a new sensor"); + + return (s); + } +@@ -186,12 +186,12 @@ new_constraint(void) + struct constraint *p; + + if ((p = calloc(1, sizeof(struct constraint))) == NULL) +- fatal("new_constraint calloc"); ++ fatal("constraint: can't allocate memory for a new constraint"); + p->id = ++constraint_maxid; + p->fd = -1; + + #ifndef HAVE_LIBTLS +- log_warnx("constraint configured without libtls support"); ++ log_warnx("constraint configured without LibreSSL support"); + #endif + return (p); + } +--- a/src/constraint.c 2020-08-01 00:19:23.425725748 +0300 ++++ b/src/constraint.c 2020-08-02 01:55:31.236952662 +0300 +@@ -135,8 +135,7 @@ constraint_addr_init(struct constraint * + cstr->state = STATE_DNS_DONE; + break; + default: +- /* XXX king bula sez it? */ +- fatalx("wrong AF in constraint_addr_init"); ++ fatalx("constraint id %d: wrong network address family", cstr->id); + /* NOTREACHED */ + } + +@@ -238,23 +237,23 @@ priv_constraint_msg(u_int32_t id, u_int8 + int rv; + + if ((cstr = constraint_byid(id)) != NULL) { +- log_warnx("IMSG_CONSTRAINT_QUERY repeated for id %d", id); ++ log_warnx("constraint id %d: repeated query", id); + return; + } + + if (len < sizeof(am)) { +- log_warnx("invalid IMSG_CONSTRAINT_QUERY received"); ++ log_warnx("constraint id %d: longer query expected", id); + return; + } + memcpy(&am, data, sizeof(am)); + if (len != (sizeof(am) + am.namelen + am.pathlen)) { +- log_warnx("invalid IMSG_CONSTRAINT_QUERY received"); ++ log_warnx("constraint id %d: invalid query received", id); + return; + } + /* Additional imsg data is obtained in the unpriv child */ + + if ((h = calloc(1, sizeof(*h))) == NULL) +- fatal("calloc ntp_addr"); ++ fatal("constraint id %d: can't allocate memory for network address", id); + memcpy(h, &am.a, sizeof(*h)); + h->next = NULL; + +@@ -267,19 +266,23 @@ priv_constraint_msg(u_int32_t id, u_int8 + + if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, AF_UNSPEC, + pipes) == -1) +- fatal("%s pipes", __func__); ++ fatal("constraint id %d: can't create required socket pairs (%s)", ++ id, __func__ ++ ); + + /* Prepare and send constraint data to child. */ + cstr->fd = pipes[0]; + imsg_init(&cstr->ibuf, cstr->fd); + if (imsg_compose(&cstr->ibuf, IMSG_CONSTRAINT_QUERY, id, 0, -1, + data, len) == -1) +- fatal("%s: imsg_compose", __func__); ++ fatal("constraint id %d: can't compose data from parent process (%s)", ++ id, __func__ ++ ); + do { + rv = imsg_flush(&cstr->ibuf); + } while (rv == -1 && errno == EAGAIN); + if (rv == -1) +- fatal("imsg_flush"); ++ fatal("constraint id %d: can't flush old data", id); + + /* + * Fork child handlers and make sure to do any sensitive work in the +@@ -301,11 +304,14 @@ priv_constraint_readquery(struct constra + + /* Read the message our parent left us. */ + if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0) +- fatal("%s: imsg_read", __func__); ++ fatal("constraint: can't read message from parent process (%s)", ++ __func__); + if (((n = imsg_get(&cstr->ibuf, &imsg)) == -1) || n == 0) +- fatal("%s: imsg_get", __func__); ++ fatal("constraint: can't get message from parent process (%s)", ++ __func__); + if (imsg.hdr.type != IMSG_CONSTRAINT_QUERY) +- fatalx("%s: invalid message type", __func__); ++ fatalx("constraint: invalid message type from parent process (%s)", ++ __func__); + + /* + * Copy the message contents just like our father: +@@ -313,16 +319,19 @@ priv_constraint_readquery(struct constra + */ + mlen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (mlen < sizeof(*am)) +- fatalx("%s: mlen < sizeof(*am)", __func__); ++ fatalx("constraint: expected longer message from parent process (%s)", ++ __func__ ++ ); + + memcpy(am, imsg.data, sizeof(*am)); + if (mlen != (sizeof(*am) + am->namelen + am->pathlen)) +- fatalx("%s: mlen < sizeof(*am) + am->namelen + am->pathlen", +- __func__); ++ fatalx("constraint: invalid message length received from parent process (%s)", ++ __func__ ++ ); + + if ((h = calloc(1, sizeof(*h))) == NULL || + (*data = calloc(1, mlen)) == NULL) +- fatal("%s: calloc", __func__); ++ fatal("constraint: can't allocate memory (%s)", __func__); + + memcpy(h, &am->a, sizeof(*h)); + h->next = NULL; +@@ -349,29 +358,27 @@ priv_constraint_child(const char *pw_dir + struct iovec iov[2]; + int i, rv; + +- log_procinit("constraint"); +- + if (setpriority(PRIO_PROCESS, 0, 0) == -1) +- log_warn("could not set priority"); ++ log_warn("constraint: can't set priority for subprocess"); + + #ifdef HAVE_LIBTLS + /* Init TLS and load CA certs before chroot() */ + if (tls_init() == -1) +- fatalx("tls_init"); ++ fatalx("constraint: can't initialize LibreSSL engine"); + if ((conf->ca = tls_load_file(tls_default_ca_cert_file(), + &conf->ca_len, NULL)) == NULL) +- fatalx("failed to load constraint ca"); ++ log_warnx("constraint: failed to load CA certificate bundle file"); + #endif + + if (chroot(pw_dir) == -1) +- fatal("chroot"); ++ fatal("constraint: can't set isolated working directory for subprocess"); + if (chdir("/") == -1) +- fatal("chdir(\"/\")"); ++ fatal("constraint: can't change subprocess working directory"); + + if (setgroups(1, &pw_gid) || + setresgid(pw_gid, pw_gid, pw_gid) || + setresuid(pw_uid, pw_uid, pw_uid)) +- fatal("can't drop privileges"); ++ fatal("constraint: can't drop subprocess privileges"); + + /* Reset all signal handlers */ + memset(&sa, 0, sizeof(sa)); +@@ -382,7 +389,7 @@ priv_constraint_child(const char *pw_dir + sigaction(i, &sa, NULL); + + if (pledge("stdio inet", NULL) == -1) +- fatal("pledge"); ++ fatal("constraint: can't restrict subprocess privileges"); + + cstr.fd = CONSTRAINT_PASSFD; + imsg_init(&cstr.ibuf, cstr.fd); +@@ -398,10 +405,11 @@ priv_constraint_child(const char *pw_dir + SA_LEN((struct sockaddr *)&cstr.addr->ss), + addr, sizeof(addr), NULL, 0, + NI_NUMERICHOST) != 0) +- fatalx("%s getnameinfo", __func__); ++ fatalx("constraint %s: can't get host and service name from IP address" ++ " (getnameinfo) (%s)", addr, __func__); + +- log_debug("constraint request to %s", addr); +- setproctitle("constraint from %s", addr); ++ log_debug("constraint %s: setting HTTPS request", addr); ++ setproctitle("constraint %s: new HTTPS request", addr); + (void)closefrom(CONSTRAINT_PASSFD + 1); + + /* +@@ -411,25 +419,27 @@ priv_constraint_child(const char *pw_dir + * but we keep it as a safety belt; especially for portability. + */ + if (fcntl(CONSTRAINT_PASSFD, F_SETFD, FD_CLOEXEC) == -1) +- fatal("%s fcntl F_SETFD", __func__); ++ fatal("constraint %s: unexpected file descriptor %d closure after execution (%s fcntl F_SETFD)", ++ addr, CONSTRAINT_PASSFD, __func__); + + /* Get remaining data from imsg in the unpriv child */ + if (am.namelen) { + if ((cstr.addr_head.name = + get_string(data, am.namelen)) == NULL) +- fatalx("invalid IMSG_CONSTRAINT_QUERY name"); ++ fatalx("constraint %s: invalid name", addr); + data += am.namelen; + } + if (am.pathlen) { + if ((cstr.addr_head.path = + get_string(data, am.pathlen)) == NULL) +- fatalx("invalid IMSG_CONSTRAINT_QUERY path"); ++ fatalx("constraint %s: invalid path", addr); + } + + /* Run! */ + if ((ctx = httpsdate_query(addr, + CONSTRAINT_PORT, cstr.addr_head.name, cstr.addr_head.path, + conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { ++ log_debug("constraint %s: failed to get proper time results", addr); + /* Abort with failure but without warning */ + exit(1); + } +@@ -464,7 +474,7 @@ priv_constraint_check_child(pid_t pid, i + if (WEXITSTATUS(status) != 0) + fail = 1; + } else +- fatalx("unexpected cause of SIGCHLD"); ++ fatalx("constraint: unexpected closure in check (SIGCHLD)"); + + if ((cstr = constraint_bypid(pid)) != NULL) { + if (sig) { +@@ -489,7 +499,7 @@ priv_constraint_kill(u_int32_t id) + struct constraint *cstr; + + if ((cstr = constraint_byid(id)) == NULL) { +- log_warnx("IMSG_CONSTRAINT_KILL for invalid id %d", id); ++ log_warnx("constraint id %d: kill failed: invalid id", id); + return; + } + +@@ -541,7 +551,7 @@ constraint_close(u_int32_t id) + struct constraint *cstr; + + if ((cstr = constraint_byid(id)) == NULL) { +- log_warn("%s: id %d: not found", __func__, id); ++ log_warn("constraint id %d: id not found (%s)", id, __func__); + return (0); + } + +@@ -569,7 +579,7 @@ priv_constraint_close(int fd, int fail) + u_int32_t id; + + if ((cstr = constraint_byfd(fd)) == NULL) { +- log_warn("%s: fd %d: not found", __func__, fd); ++ log_warn("constraint id %d: constraint file descriptor %d not found (%s)", cstr->id, fd, __func__); + return; + } + +@@ -643,7 +653,9 @@ priv_constraint_dispatch(struct pollfd * + switch (imsg.hdr.type) { + case IMSG_CONSTRAINT_RESULT: + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(tv)) +- fatalx("invalid IMSG_CONSTRAINT received"); ++ fatalx("constraint id %d: invalid header length received in dispatch", ++ cstr->id ++ ); + + /* state is maintained by child, but we want to + remember we've seen the result */ +@@ -669,12 +681,12 @@ constraint_msg_result(u_int32_t id, u_in + double offset; + + if ((cstr = constraint_byid(id)) == NULL) { +- log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); ++ log_warnx("constraint id %d: invalid constraint id in result", id); + return; + } + + if (len != sizeof(tv)) { +- log_warnx("invalid IMSG_CONSTRAINT received"); ++ log_warnx("constraint id %d: invalid header length %zu received in result", id, len); + return; + } + +@@ -683,7 +695,7 @@ constraint_msg_result(u_int32_t id, u_in + offset = gettime_from_timeval(&tv[0]) - + gettime_from_timeval(&tv[1]); + +- log_info("constraint reply from %s: offset %f", ++ log_info("constraint %s: reply received: offset %fs", + log_sockaddr((struct sockaddr *)&cstr->addr->ss), + offset); + +@@ -702,20 +714,22 @@ constraint_msg_close(u_int32_t id, u_int + static int total_fails; + + if ((cstr = constraint_byid(id)) == NULL) { +- log_warnx("IMSG_CONSTRAINT_CLOSE with invalid constraint id"); ++ log_warnx("constraint id %d: closure failed: invalid constraint id", id); + return; + } + + if (len != sizeof(int)) { +- log_warnx("invalid IMSG_CONSTRAINT_CLOSE received"); ++ log_warnx("constraint id %d: closure failed: invalid header length %zu received", ++ id, ++ len); + return; + } + + memcpy(&fail, data, len); + + if (fail) { +- log_debug("no constraint reply from %s" +- " received in time, next query %ds", ++ log_debug("constraint %s: no reply" ++ " received in time, next query in %ds", + log_sockaddr((struct sockaddr *) + &cstr->addr->ss), CONSTRAINT_SCAN_INTERVAL); + +@@ -724,7 +738,7 @@ constraint_msg_close(u_int32_t id, u_int + cnt++; + if (cnt > 0 && ++total_fails >= cnt && + conf->constraint_median == 0) { +- log_warnx("constraints configured but none available"); ++ log_warnx("constraint: constraints configured but none available"); + total_fails = 0; + } + } +@@ -743,21 +757,21 @@ constraint_msg_dns(u_int32_t id, u_int8_ + struct ntp_addr *h; + + if ((cstr = constraint_byid(id)) == NULL) { +- log_debug("IMSG_CONSTRAINT_DNS with invalid constraint id"); ++ log_warnx("constraint id %d: DNS dispatching failed: invalid constraint id", id); + return; + } + if (cstr->addr != NULL) { +- log_warnx("IMSG_CONSTRAINT_DNS but addr != NULL!"); ++ log_warnx("constraint id %d: DNS dispatching failed: address is not empty", id); + return; + } + if (len == 0) { +- log_debug("%s FAILED", __func__); ++ log_debug("constraint id %d: DNS dispatching failed: invalid header length %zu (%s FAILED)", id, len, __func__); + cstr->state = STATE_DNS_TEMPFAIL; + return; + } + + if (len % (sizeof(struct sockaddr_storage) + sizeof(int)) != 0) +- fatalx("IMSG_CONSTRAINT_DNS len"); ++ fatalx("constraint id %d: DNS dispatching failed: invalid header length", id); + + if (cstr->addr_head.pool) { + struct constraint *n, *tmp; +@@ -772,7 +786,7 @@ constraint_msg_dns(u_int32_t id, u_int8_ + p = data; + do { + if ((h = calloc(1, sizeof(*h))) == NULL) +- fatal("calloc ntp_addr"); ++ fatal("constraint id %d: DNS dispatching failed: can't allocate memory", id); + memcpy(&h->ss, p, sizeof(h->ss)); + p += sizeof(h->ss); + len -= sizeof(h->ss); +@@ -788,7 +802,7 @@ constraint_msg_dns(u_int32_t id, u_int8_ + ncstr->addr_head.path = strdup(cstr->addr_head.path); + if (ncstr->addr_head.name == NULL || + ncstr->addr_head.path == NULL) +- fatal("calloc name"); ++ fatal("constraint id %d: DNS dispatching failed: invalid data", id); + ncstr->addr_head.pool = cstr->addr_head.pool; + ncstr->state = STATE_DNS_DONE; + constraint_add(ncstr); +@@ -831,7 +845,7 @@ constraint_update(void) + return; + + if ((values = calloc(cnt, sizeof(time_t))) == NULL) +- fatal("calloc"); ++ fatal("constraint: can't allocate memory for constraint time"); + + i = 0; + TAILQ_FOREACH(cstr, &conf->constraints, entry) { +@@ -979,11 +993,14 @@ httpsdate_request(struct httpsdate *http + * does not trigger any DNS operation and is safe to be called + * without the dns pledge. + */ ++ log_debug("constraint %s: establishing connection", httpsdate->tls_addr); + if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr, + httpsdate->tls_port, httpsdate->tls_hostname) == -1) { +- log_debug("tls connect failed: %s (%s): %s", +- httpsdate->tls_addr, httpsdate->tls_hostname, +- tls_error(httpsdate->tls_ctx)); ++ log_debug("constraint %s: TLS connection failed (%s): %s", ++ httpsdate->tls_addr, ++ httpsdate->tls_hostname, ++ tls_error(httpsdate->tls_ctx) ++ ); + goto fail; + } + +@@ -994,9 +1011,11 @@ httpsdate_request(struct httpsdate *http + if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) + continue; + if (ret == -1) { +- log_warnx("tls write failed: %s (%s): %s", +- httpsdate->tls_addr, httpsdate->tls_hostname, +- tls_error(httpsdate->tls_ctx)); ++ log_warnx("constraint %s: TLS write operation failed (%s): %s", ++ httpsdate->tls_addr, ++ httpsdate->tls_hostname, ++ tls_error(httpsdate->tls_ctx) ++ ); + goto fail; + } + buf += ret; +@@ -1022,7 +1041,9 @@ httpsdate_request(struct httpsdate *http + */ + if (strptime(p, IMF_FIXDATE, + &httpsdate->tls_tm) == NULL) { +- log_warnx("unsupported date format"); ++ log_warnx("constraint %s: unsupported date format", ++ httpsdate->tls_addr ++ ); + free(line); + return (-1); + } +@@ -1050,8 +1071,8 @@ httpsdate_request(struct httpsdate *http + if (strftime(timebuf2, sizeof(timebuf2), X509_DATE, + &httpsdate->tls_tm) == 0) + goto fail; +- log_warnx("tls certificate not yet valid: %s (%s): " +- "not before %s, now %s", httpsdate->tls_addr, ++ log_warnx("constraint %s: TLS certificate not yet valid (%s): " ++ "not before %s, now is %s", httpsdate->tls_addr, + httpsdate->tls_hostname, timebuf1, timebuf2); + goto fail; + } +@@ -1063,8 +1084,8 @@ httpsdate_request(struct httpsdate *http + if (strftime(timebuf2, sizeof(timebuf2), X509_DATE, + &httpsdate->tls_tm) == 0) + goto fail; +- log_warnx("tls certificate expired: %s (%s): " +- "not after %s, now %s", httpsdate->tls_addr, ++ log_warnx("constraint %s: TLS certificate has been expired (%s): " ++ "not after %s, now is %s", httpsdate->tls_addr, + httpsdate->tls_hostname, timebuf1, timebuf2); + goto fail; + } +@@ -1117,11 +1138,11 @@ tls_readline(struct tls *tls, size_t *le + + len = 128; + if ((buf = malloc(len)) == NULL) +- fatal("Can't allocate memory for transfer buffer"); ++ fatal("constraint: can't allocate memory for TLS transfer buffer"); + for (i = 0; ; i++) { + if (i >= len - 1) { + if ((q = reallocarray(buf, len, 2)) == NULL) +- fatal("Can't expand transfer buffer"); ++ fatal("constraint: can't expand TLS transfer buffer"); + buf = q; + len *= 2; + } +@@ -1136,7 +1157,7 @@ tls_readline(struct tls *tls, size_t *le + } + + if (maxlength != NULL && (*maxlength)-- == 0) { +- log_warnx("maximum length exceeded"); ++ log_warnx("constraint: maximum HTTP header length exceeded"); + free(buf); + return (NULL); + } +@@ -1147,7 +1168,7 @@ tls_readline(struct tls *tls, size_t *le + } + *lenp = i; + if (gettimeofday(when, NULL) == -1) +- fatal("gettimeofday"); ++ fatal("constraint: can't get a valid time stamp"); + return (buf); + } + +--- a/src/control.c 2020-08-01 00:19:21.849059080 +0300 ++++ b/src/control.c 2020-07-31 23:23:56.959055574 +0300 +@@ -47,12 +47,12 @@ control_check(char *path) + strlcpy(sun.sun_path, path, sizeof(sun.sun_path)); + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { +- log_debug("control_check: socket check"); ++ log_debug("control socket: socket error in check"); + return (-1); + } + + if (connect(fd, (struct sockaddr *)&sun, sizeof(sun)) == 0) { +- log_debug("control_check: socket in use"); ++ log_debug("control socket: socket is in use"); + close(fd); + return (-1); + } +@@ -70,7 +70,7 @@ control_init(char *path) + mode_t old_umask; + + if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { +- log_warn("control_init: socket"); ++ log_warn("control socket: can't create UDP socket"); + return (-1); + } + +@@ -78,18 +78,18 @@ control_init(char *path) + sa.sun_family = AF_UNIX; + if (strlcpy(sa.sun_path, path, sizeof(sa.sun_path)) >= + sizeof(sa.sun_path)) +- errx(1, "ctl socket name too long"); ++ errx(1, "control socket: name is too long"); + + if (unlink(path) == -1) + if (errno != ENOENT) { +- log_warn("control_init: unlink %s", path); ++ log_warn("control socket: can't unlink %s", path); + close(fd); + return (-1); + } + + old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); + if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { +- log_warn("control_init: bind: %s", path); ++ log_warn("control socket: can't bind %s", path); + close(fd); + umask(old_umask); + return (-1); +@@ -97,7 +97,7 @@ control_init(char *path) + umask(old_umask); + + if (chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) { +- log_warn("control_init: chmod"); ++ log_warn("control socket: can't set owner permission bits for %s", path); + close(fd); + (void)unlink(path); + return (-1); +@@ -112,7 +112,7 @@ int + control_listen(int fd) + { + if (fd != -1 && listen(fd, CONTROL_BACKLOG) == -1) { +- log_warn("control_listen: listen"); ++ log_warn("control socket: can't initialize listening interface"); + return (-1); + } + +@@ -137,14 +137,14 @@ control_accept(int listenfd) + if ((connfd = accept(listenfd, + (struct sockaddr *)&sa, &len)) == -1) { + if (errno != EWOULDBLOCK && errno != EINTR) +- log_warn("control_accept: accept"); ++ log_warn("control socket: unable to accept connections"); + return (0); + } + + session_socket_nonblockmode(connfd); + + if ((ctl_conn = calloc(1, sizeof(struct ctl_conn))) == NULL) { +- log_warn("control_accept"); ++ log_warn("control socket: can't allocate memory for NTP server"); + close(connfd); + return (0); + } +@@ -175,7 +175,7 @@ control_close(int fd) + struct ctl_conn *c; + + if ((c = control_connbyfd(fd)) == NULL) { +- log_warn("control_close: fd %d: not found", fd); ++ log_warn("control socket: file descriptor %d not found while closing", fd); + return (0); + } + +@@ -202,7 +202,7 @@ control_dispatch_msg(struct pollfd *pfd, + ssize_t n; + + if ((c = control_connbyfd(pfd->fd)) == NULL) { +- log_warn("control_dispatch_msg: fd %d: not found", pfd->fd); ++ log_warn("control socket: file descriptor %d not found while preparing NTP server subprocess", pfd->fd); + return (0); + } + +@@ -298,12 +298,12 @@ session_socket_nonblockmode(int fd) + int flags; + + if ((flags = fcntl(fd, F_GETFL)) == -1) +- fatal("fcntl F_GETFL"); ++ fatal("control socket: unable to get file descriptor %d status flags", fd); + + flags |= O_NONBLOCK; + + if ((flags = fcntl(fd, F_SETFL, flags)) == -1) +- fatal("fcntl F_SETFL"); ++ fatal("control socket: unable to set file descriptor %d status flags", fd); + } + + void +@@ -349,7 +349,7 @@ build_show_peer(struct ctl_show_peer *cp + if (p->addr) { + a = log_sockaddr((struct sockaddr *)&p->addr->ss); + if (p->addr->notauth) +- auth = " (non-dnssec lookup)"; ++ auth = " (non-DNSSEC lookup)"; + } + if (p->addr_head.pool) + pool = "from pool "; +--- a/src/ntp.c 2020-08-01 00:19:21.849059080 +0300 ++++ b/src/ntp.c 2020-07-31 23:34:32.462389577 +0300 +@@ -93,38 +93,38 @@ ntp_main(struct ntpd_conf *nconf, struct + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, + pipe_dns) == -1) +- fatal("socketpair"); ++ fatal("main process: can't set socket pair for DNS"); + + start_child(NTPDNS_PROC_NAME, pipe_dns[1], argc, argv); + + log_init(nconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG, nconf->verbose, + LOG_DAEMON); + if (!nconf->debug && setsid() == -1) +- fatal("setsid"); +- log_procinit("ntp"); ++ fatal("main process: can't create a new session"); ++ log_procinit("NTP"); + + if ((se = getservbyname("ntp", "udp")) == NULL) +- fatal("getservbyname"); ++ fatal("main process: can't find default system information for NTP protocol (getservbyname)"); + + /* Start control socket. */ + if ((fd_ctl = control_init(CTLSOCKET)) == -1) +- fatalx("control socket init failed"); ++ fatalx("control socket: unable to initialize"); + if (control_listen(fd_ctl) == -1) +- fatalx("control socket listen failed"); ++ fatalx("control socket: unable to listen"); + if ((nullfd = open("/dev/null", O_RDWR, 0)) == -1) +- fatal(NULL); ++ fatal("control socket: can't read /dev/null"); + + if (stat(pw->pw_dir, &stb) == -1) { +- fatal("privsep dir %s could not be opened", pw->pw_dir); ++ fatal("main process: can't open working directory %s", pw->pw_dir); + } + if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { +- fatalx("bad privsep dir %s permissions: %o", ++ fatalx("main process: working directory %s has bad permissions (%o)", + pw->pw_dir, stb.st_mode); + } + if (chroot(pw->pw_dir) == -1) +- fatal("chroot"); ++ fatal("main process: can't set isolated working directory"); + if (chdir("/") == -1) +- fatal("chdir(\"/\")"); ++ fatal("main process: can't change subprocess working directory"); + + if (!nconf->debug) { + dup2(nullfd, STDIN_FILENO); +@@ -133,21 +133,22 @@ ntp_main(struct ntpd_conf *nconf, struct + } + close(nullfd); + +- setproctitle("ntp engine"); ++ setproctitle("NTP engine"); + + conf = nconf; + setup_listeners(se, conf, &listener_cnt); ++ log_debug("main process: setting up listeners"); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) +- fatal("can't drop privileges"); ++ fatal("main process: can't drop privileges"); + + endservent(); + + /* The ntp process will want to open NTP client sockets -> "inet" */ + if (pledge("stdio inet", NULL) == -1) +- err(1, "pledge"); ++ err(1, "main process: can't restrict NTP process privileges"); + + signal(SIGTERM, ntp_sighdlr); + signal(SIGINT, ntp_sighdlr); +@@ -156,10 +157,10 @@ ntp_main(struct ntpd_conf *nconf, struct + signal(SIGCHLD, SIG_DFL); + + if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) +- fatal(NULL); ++ fatal("main process: can't allocate memory for main data buffer"); + imsg_init(ibuf_main, PARENT_SOCK_FILENO); + if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) +- fatal(NULL); ++ fatal("main process: can't allocate memory for DNS data buffer"); + imsg_init(ibuf_dns, pipe_dns[0]); + + constraint_cnt = 0; +@@ -192,7 +193,7 @@ ntp_main(struct ntpd_conf *nconf, struct + TAILQ_INIT(&ctl_conns); + sensor_init(); + +- log_info("ntp engine ready"); ++ log_info("NTP engine ready"); + + ctl_cnt = 0; + peer_cnt = 0; +@@ -204,7 +205,7 @@ ntp_main(struct ntpd_conf *nconf, struct + if ((newp = reallocarray(idx2peer, peer_cnt, + sizeof(*idx2peer))) == NULL) { + /* panic for now */ +- log_warn("could not resize idx2peer from %u -> " ++ log_warn("main process: could not resize server pool from %u -> " + "%u entries", idx2peer_elms, peer_cnt); + fatalx("exiting"); + } +@@ -218,7 +219,7 @@ ntp_main(struct ntpd_conf *nconf, struct + if ((newp = reallocarray(pfd, new_cnt, + sizeof(*pfd))) == NULL) { + /* panic for now */ +- log_warn("could not resize pfd from %u -> " ++ log_warn("main process: could not resize process file descriptor pool from %u -> " + "%u entries", pfd_elms, new_cnt); + fatalx("exiting"); + } +@@ -258,12 +259,12 @@ ntp_main(struct ntpd_conf *nconf, struct + } + if (p->deadline > 0 && p->deadline <= getmonotime()) { + timeout = 300; +- log_debug("no reply from %s received in time, " +- "next query %ds", log_sockaddr( ++ log_debug("NTP client: NTP peer %s - no reply received in time, " ++ "next query in %ds", log_sockaddr( + (struct sockaddr *)&p->addr->ss), timeout); + if (p->trustlevel >= TRUSTLEVEL_BADPEER && + (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER) +- log_info("peer %s now invalid", ++ log_info("NTP client: NTP peer %s is invalid now", + log_sockaddr( + (struct sockaddr *)&p->addr->ss)); + if (client_nextaddr(p) == 1) { +@@ -273,8 +274,8 @@ ntp_main(struct ntpd_conf *nconf, struct + set_next(p, timeout); + } + if (p->senderrors > MAX_SEND_ERRORS) { +- log_debug("failed to send query to %s, " +- "next query %ds", log_sockaddr( ++ log_debug("NTP client: NTP peer %s - failed to send query, " ++ "next query in %ds", log_sockaddr( + (struct sockaddr *)&p->addr->ss), + INTERVAL_QUERY_PATHETIC); + p->senderrors = 0; +@@ -323,7 +324,7 @@ ntp_main(struct ntpd_conf *nconf, struct + if (conf->settime && + ((trial_cnt > 0 && sent_cnt == 0) || + (peer_cnt == 0 && sensors_cnt == 0))) +- priv_settime(0, "no valid peers configured"); ++ priv_settime(0, "NTP client: no valid peers configured"); + + TAILQ_FOREACH(cstr, &conf->constraints, entry) { + if (constraint_query(cstr) == -1) +@@ -351,21 +352,21 @@ ntp_main(struct ntpd_conf *nconf, struct + + if ((nfds = poll(pfd, i, timeout ? timeout * 1000 : 1)) == -1) + if (errno != EINTR) { +- log_warn("poll error"); ++ log_warn("file descriptor: poll error"); + ntp_quit = 1; + } + + if (nfds > 0 && (pfd[PFD_PIPE_MAIN].revents & POLLOUT)) + if (msgbuf_write(&ibuf_main->w) <= 0 && + errno != EAGAIN) { +- log_warn("pipe write error (to parent)"); ++ log_warn("file descriptor: pipe write error (to parent)"); + ntp_quit = 1; + } + + if (nfds > 0 && pfd[PFD_PIPE_MAIN].revents & (POLLIN|POLLERR)) { + nfds--; + if (ntp_dispatch_imsg() == -1) { +- log_debug("pipe read error (from main)"); ++ log_warn("file descriptor: pipe write error (from main)"); + ntp_quit = 1; + } + } +@@ -373,14 +374,14 @@ ntp_main(struct ntpd_conf *nconf, struct + if (nfds > 0 && (pfd[PFD_PIPE_DNS].revents & POLLOUT)) + if (msgbuf_write(&ibuf_dns->w) <= 0 && + errno != EAGAIN) { +- log_warn("pipe write error (to dns engine)"); ++ log_warn("file descriptor: pipe write error (to DNS engine)"); + ntp_quit = 1; + } + + if (nfds > 0 && pfd[PFD_PIPE_DNS].revents & (POLLIN|POLLERR)) { + nfds--; + if (ntp_dispatch_imsg_dns() == -1) { +- log_warn("pipe read error (from dns engine)"); ++ log_warn("file descriptor: pipe write error (from DNS engine)"); + ntp_quit = 1; + } + } +@@ -394,7 +395,7 @@ ntp_main(struct ntpd_conf *nconf, struct + if (pfd[j].revents & (POLLIN|POLLERR)) { + nfds--; + if (server_dispatch(pfd[j].fd, conf) == -1) { +- log_warn("pipe write error (conf)"); ++ log_warn("file descriptor: pipe write error (in configuration)"); + ntp_quit = 1; + } + } +@@ -404,7 +405,7 @@ ntp_main(struct ntpd_conf *nconf, struct + nfds--; + if (client_dispatch(idx2peer[j - idx_peers], + conf->settime, conf->automatic) == -1) { +- log_warn("pipe write error (settime)"); ++ log_warn("file descriptor: pipe write error (in settime)"); + ntp_quit = 1; + } + } +@@ -429,7 +430,7 @@ ntp_main(struct ntpd_conf *nconf, struct + msgbuf_clear(&ibuf_dns->w); + free(ibuf_dns); + +- log_info("ntp engine exiting"); ++ log_info("NTP engine exiting"); + exit(0); + } + +@@ -453,12 +454,12 @@ ntp_dispatch_imsg(void) + case IMSG_ADJTIME: + memcpy(&n, imsg.data, sizeof(n)); + if (n == 1 && !conf->status.synced) { +- log_info("clock is now synced"); ++ log_info("main process: clock is synced now"); + conf->status.synced = 1; + priv_dns(IMSG_SYNCED, NULL, 0); + constraint_reset(); + } else if (n == 0 && conf->status.synced) { +- log_info("clock is now unsynced"); ++ log_info("main process: clock is unsynced now"); + conf->status.synced = 0; + priv_dns(IMSG_UNSYNCED, NULL, 0); + } +@@ -529,11 +530,11 @@ ntp_dispatch_imsg_dns(void) + if (peer->id == imsg.hdr.peerid) + break; + if (peer == NULL) { +- log_warnx("IMSG_HOST_DNS with invalid peerID"); ++ log_warnx("NTP client: invalid NTP peer ID retrieved in DNS dispatch initialization"); + break; + } + if (peer->addr != NULL) { +- log_warnx("IMSG_HOST_DNS but addr != NULL!"); ++ log_warnx("NTP client: invalid NTP peer ID retrieved in DNS dispatch initialization"); + break; + } + +@@ -556,10 +557,10 @@ ntp_dispatch_imsg_dns(void) + + dlen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (dlen == 0) { /* no data -> temp error */ +- log_warnx("DNS lookup tempfail"); ++ log_warnx("DNS lookup temporary failed"); + peer->state = STATE_DNS_TEMPFAIL; + if (conf->tmpfail++ == TRIES_AUTO_DNSFAIL) +- priv_settime(0, "of dns failures"); ++ priv_settime(0, "of DNS failures"); + break; + } + +@@ -571,7 +572,7 @@ ntp_dispatch_imsg_dns(void) + sizeof(int)) { + if ((h = calloc(1, sizeof(struct ntp_addr))) == + NULL) +- fatal(NULL); ++ fatal("NTP client: can't allocate memory for NTP peer address"); + memcpy(&h->ss, p, sizeof(h->ss)); + p += sizeof(h->ss); + dlen -= sizeof(h->ss); +@@ -588,7 +589,7 @@ ntp_dispatch_imsg_dns(void) + free(h); + continue; + } +- log_debug("Adding address %s to %s", ++ log_debug("NTP client: adding address %s to %s", + log_sockaddr((struct sockaddr *) + &h->ss), peer->addr_head.name); + npeer = new_peer(); +@@ -614,7 +615,7 @@ ntp_dispatch_imsg_dns(void) + } + } + if (dlen != 0) +- fatalx("IMSG_HOST_DNS: dlen != 0"); ++ fatalx("NTP client: didn't expect data for stored NTP peer network address in DNS dispatch initialization"); + if (peer->addr_head.pool) + peer_remove(peer); + else +@@ -627,10 +628,10 @@ ntp_dispatch_imsg_dns(void) + case IMSG_PROBE_ROOT: + dlen = imsg.hdr.len - IMSG_HEADER_SIZE; + if (dlen != sizeof(int)) +- fatalx("IMSG_PROBE_ROOT"); ++ fatalx("NTP client: invalid header length in data buffer for DNS probe"); + memcpy(&n, imsg.data, sizeof(int)); + if (n < 0) +- priv_settime(0, "dns probe failed"); ++ priv_settime(0, "NTP client: DNS probe failed"); + break; + default: + break; +@@ -738,7 +739,7 @@ priv_adjtime(void) + return (1); + + if ((offsets = calloc(offset_cnt, sizeof(struct ntp_offset *))) == NULL) +- fatal("calloc priv_adjtime"); ++ fatal("main process: can't allocate memory for time adjustment"); + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { + if (p->trustlevel < TRUSTLEVEL_BADPEER) +@@ -815,7 +816,7 @@ void + priv_settime(double offset, char *msg) + { + if (offset == 0) +- log_info("cancel settime because %s", msg); ++ log_info("NTP client: setting time was cancelled because %s", msg); + imsg_compose(ibuf_main, IMSG_SETTIME, 0, 0, -1, + &offset, sizeof(offset)); + conf->settime = 0; +--- a/src/ntpd.c 2020-08-01 00:19:23.455725749 +0300 ++++ b/src/ntpd.c 2020-08-01 13:33:10.798104786 +0300 +@@ -102,7 +102,7 @@ writepid(struct ntpd_conf *lconf) + if (lconf->pid_file != NULL) { + FILE *f = fopen(lconf->pid_file, "w"); + if (f == NULL) +- fatal("couldn't open pid file"); ++ fatal("main process: couldn't open pid file"); + fprintf(f, "%ld\n", (long) getpid()); + fclose(f); + } +@@ -131,7 +131,7 @@ auto_preconditions(const struct ntpd_con + int mib[2] = { CTL_KERN, KERN_SECURELVL }; + size_t sz = sizeof(int); + if (sysctl(mib, 2, &securelevel, &sz, NULL, 0) == -1) +- err(1, "sysctl"); ++ err(1, "error while processing kernel security level"); + #endif + constraints = !TAILQ_EMPTY(&cnf->constraints); + return !cnf->settime && (constraints || cnf->trusted_peers || +@@ -244,15 +244,15 @@ main(int argc, char *argv[]) + exit(1); + + if (lconf.noaction) { +- fprintf(stderr, "configuration OK\n"); ++ fprintf(stderr, "main process: configuration OK\n"); + exit(0); + } + + if (geteuid()) +- errx(1, "need root privileges"); ++ errx(1, "main process: need root privileges"); + + if ((pw = getpwnam(NTPD_USER)) == NULL) +- errx(1, "unknown user %s", NTPD_USER); ++ errx(1, "main process: unknown user %s", NTPD_USER); + + lconf.automatic = auto_preconditions(&lconf); + if (lconf.automatic) +@@ -261,7 +261,7 @@ main(int argc, char *argv[]) + if (pname != NULL) { + /* Remove our proc arguments, so child doesn't need to. */ + if (sanitize_argv(&argc0, &argv0) == -1) +- fatalx("sanitize_argv"); ++ fatalx("main process: can't sanitize environment for subprocesses"); + + if (strcmp(NTP_PROC_NAME, pname) == 0) + ntp_main(&lconf, pw, argc0, argv0); +@@ -271,17 +271,16 @@ main(int argc, char *argv[]) + priv_constraint_child(pw->pw_dir, pw->pw_uid, + pw->pw_gid); + else +- fatalx("%s: invalid process name '%s'", __func__, +- pname); ++ fatalx("main process: invalid process name '%s' (%s)", pname, __func__); + +- fatalx("%s: process '%s' failed", __func__, pname); ++ fatalx("main process: process '%s' failed (%s)", pname, __func__); + } else { + if ((control_check(CTLSOCKET)) == -1) +- fatalx("ntpd already running"); ++ fatalx("OpenNTPD is already running"); + } + + if (setpriority(PRIO_PROCESS, 0, -20) == -1) +- warn("can't set priority"); ++ warn("main process: can't set priority"); + reset_adjtime(); + + logdest = lconf.debug ? LOG_TO_STDERR : LOG_TO_SYSLOG; +@@ -289,7 +288,7 @@ main(int argc, char *argv[]) + log_init(logdest, lconf.verbose, LOG_DAEMON); + if (!lconf.debug) { + if (daemon(1, 0)) +- fatal("daemon"); ++ fatal("main process: can't daemonize process"); + writepid(&lconf); + } + } else { +@@ -299,10 +298,10 @@ main(int argc, char *argv[]) + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, + pipe_chld) == -1) +- fatal("socketpair"); ++ fatal("main process: can't set socket pair for child processes"); + + if (chdir("/") == -1) +- fatal("chdir(\"/\")"); ++ fatal("main process: can't change working directory"); + + signal(SIGCHLD, sighdlr); + +@@ -319,7 +318,7 @@ main(int argc, char *argv[]) + constraint_purge(); + + if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) +- fatal(NULL); ++ fatal("main process: can't allocate memory for data buffer"); + imsg_init(ibuf, pipe_chld[0]); + + constraint_cnt = 0; +@@ -329,11 +328,11 @@ main(int argc, char *argv[]) + * then privdrop into chroot before speaking to the outside world. + */ + if (unveil(tls_default_ca_cert_file(), "r") == -1) +- err(1, "unveil"); ++ err(1, "main process: can't unveil certificate file for reading"); + if (unveil("/usr/sbin/ntpd", "x") == -1) +- err(1, "unveil"); ++ err(1, "main process: can't unveil ntpd executable for execute operations"); + if (pledge("stdio rpath inet settime proc exec id", NULL) == -1) +- err(1, "pledge"); ++ err(1, "main process: can't restrict privileges for constraints"); + + while (quit == 0) { + new_cnt = PFD_MAX + constraint_cnt; +@@ -341,7 +340,7 @@ main(int argc, char *argv[]) + if ((newp = reallocarray(pfd, new_cnt, + sizeof(*pfd))) == NULL) { + /* panic for now */ +- log_warn("could not resize pfd from %u -> " ++ log_warn("main process: could not resize pfd from %u -> " + "%u entries", pfd_elms, new_cnt); + fatalx("exiting"); + } +@@ -364,7 +363,7 @@ main(int argc, char *argv[]) + + if ((nfds = poll(pfd, i, timeout)) == -1) + if (errno != EINTR) { +- log_warn("poll error"); ++ log_warn("file descriptor: poll error"); + quit = 1; + } + +@@ -373,18 +372,18 @@ main(int argc, char *argv[]) + lconf.settime = 0; + timeout = INFTIM; + log_init(logdest, lconf.verbose, LOG_DAEMON); +- log_warnx("no reply received in time, skipping initial " +- "time setting"); ++ log_warnx("main process: no reply received in time, skipping initial " ++ "time setting for constraint"); + if (!lconf.debug) { + if (daemon(1, 0)) +- fatal("daemon"); ++ fatal("main process: can't daemonize process"); + writepid(&lconf); + } + } + + if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT)) + if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) { +- log_warn("pipe write error (to child)"); ++ log_warn("file descriptor: pipe write error (to child)"); + quit = 1; + } + +@@ -412,7 +411,7 @@ main(int argc, char *argv[]) + do { + if ((pid = wait(NULL)) == -1 && + errno != EINTR && errno != ECHILD) +- fatal("wait"); ++ fatal("main process: can't get child process ID"); + } while (pid != -1 || (pid == -1 && errno == EINTR)); + + msgbuf_clear(&ibuf->w); +@@ -458,7 +457,7 @@ dispatch_imsg(struct ntpd_conf *lconf, i + switch (imsg.hdr.type) { + case IMSG_ADJTIME: + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) +- fatalx("invalid IMSG_ADJTIME received"); ++ fatalx("main process: invalid stored data for time adjustment"); + memcpy(&d, imsg.data, sizeof(d)); + n = ntpd_adjtime(d); + imsg_compose(ibuf, IMSG_ADJTIME, 0, 0, -1, +@@ -466,13 +465,13 @@ dispatch_imsg(struct ntpd_conf *lconf, i + break; + case IMSG_ADJFREQ: + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) +- fatalx("invalid IMSG_ADJFREQ received"); ++ fatalx("main process: invalid stored data for frequency adjustment"); + memcpy(&d, imsg.data, sizeof(d)); + ntpd_adjfreq(d, 1); + break; + case IMSG_SETTIME: + if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(d)) +- fatalx("invalid IMSG_SETTIME received"); ++ fatalx("main process: invalid stored data for setting time"); + if (!lconf->settime) + break; + log_init(lconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG, +@@ -482,7 +481,7 @@ dispatch_imsg(struct ntpd_conf *lconf, i + /* daemonize now */ + if (!lconf->debug) { + if (daemon(1, 0)) +- fatal("daemon"); ++ fatal("main process: can't daemonize process"); + writepid(lconf); + } + lconf->settime = 0; +@@ -511,7 +510,7 @@ reset_adjtime(void) + + timerclear(&tv); + if (adjtime(&tv, NULL) == -1) +- log_warn("reset adjtime failed"); ++ log_warn("main process: time adjustment reset failed"); + } + + int +@@ -523,9 +522,9 @@ ntpd_adjtime(double d) + + d += getoffset(); + if (d >= threshold || d <= -1 * threshold) +- log_info("adjusting local clock by %fs", d); ++ log_info("main process: adjusting local clock by %fs", d); + else +- log_debug("adjusting local clock by %fs", d); ++ log_debug("main process: adjusting local clock by %fs", d); + + #ifdef HAVE_ADJTIMEX + int rc; +@@ -541,9 +540,9 @@ ntpd_adjtime(double d) + + if (rc == TIME_ERROR) { + if ((tx.status & ~STA_UNSYNC)) +- log_warn("adjtimex returned TIME_ERROR"); ++ log_warn("main process: time adjustment failed due to time error"); + } else if (rc < 0) { +- log_warn("adjtimex failed"); ++ log_warn("main process: time adjustment failed"); + } else if (!firstadj && tx.offset == offset) { + synced = 1; + } +@@ -551,7 +550,7 @@ ntpd_adjtime(double d) + struct timeval tv, olddelta; + d_to_tv(d, &tv); + if (adjtime(&tv, &olddelta) == -1) +- log_warn("adjtime failed"); ++ log_warn("main process: time adjustment failed"); + else if (!firstadj && olddelta.tv_sec == 0 && olddelta.tv_usec == 0) + synced = 1; + #endif +@@ -568,7 +567,7 @@ ntpd_adjfreq(double relfreq, int wrlog) + int r; + + if (adjfreq(NULL, &curfreq) == -1) { +- log_warn("adjfreq failed"); ++ log_warn("main process: frequency adjustment failed"); + return; + } + +@@ -582,17 +581,17 @@ ntpd_adjfreq(double relfreq, int wrlog) + if (wrlog) { + if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ || + ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ) +- log_info("adjusting clock frequency by %f to %fppm%s", ++ log_info("main process: adjusting clock frequency by %f to %f ppm%s", + ppmfreq, curfreq / 1e3 / (1LL << 32), + r ? "" : " (no drift file)"); + else +- log_debug("adjusting clock frequency by %f to %fppm%s", ++ log_debug("main process: adjusting clock frequency by %f to %f ppm%s", + ppmfreq, curfreq / 1e3 / (1LL << 32), + r ? "" : " (no drift file)"); + } + + if (adjfreq(&curfreq, NULL) == -1) +- log_warn("adjfreq failed"); ++ log_warn("main process: frequency adjustment failed"); + } + + void +@@ -606,7 +605,7 @@ ntpd_settime(double d) + return; + + if (gettimeofday(&curtime, NULL) == -1) { +- log_warn("gettimeofday"); ++ log_warn("main process: can't get current time"); + return; + } + d_to_tv(d, &tv); +@@ -615,13 +614,13 @@ ntpd_settime(double d) + curtime.tv_usec %= 1000000; + + if (settimeofday(&curtime, NULL) == -1) { +- log_warn("settimeofday"); ++ log_warn("main process: can't set time"); + return; + } + tval = curtime.tv_sec; + strftime(buf, sizeof(buf), "%a %b %e %H:%M:%S %Z %Y", + localtime(&tval)); +- log_info("set local clock to %s (offset %fs)", buf, d); ++ log_info("main process: set local clock to %s (offset %fs)", buf, d); + } + + static FILE *freqfp; +@@ -635,10 +634,10 @@ readfreq(void) + + fd = open(DRIFTFILE, O_RDWR); + if (fd == -1) { +- log_warnx("creating new %s", DRIFTFILE); ++ log_warnx("main process: creating new drift file %s", DRIFTFILE); + current = 0; + if (adjfreq(¤t, NULL) == -1) +- log_warn("adjfreq reset failed"); ++ log_warn("main process: frequency reset failed"); + freqfp = fopen(DRIFTFILE, "w"); + return; + } +@@ -647,13 +646,13 @@ readfreq(void) + + /* if we're adjusting frequency already, don't override */ + if (adjfreq(NULL, ¤t) == -1) +- log_warn("adjfreq failed"); ++ log_warn("main process: frequency adjustment failed"); + else if (current == 0 && freqfp) { + if (fscanf(freqfp, "%lf", &d) == 1) { + d /= 1e6; /* scale from ppm */ + ntpd_adjfreq(d, 0); + } else +- log_warnx("%s is empty", DRIFTFILE); ++ log_warnx("main process: drift file %s is empty", DRIFTFILE); + } + } + +@@ -670,7 +669,7 @@ writefreq(double d) + r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */ + if (r < 0 || fflush(freqfp) != 0) { + if (warnonce) { +- log_warnx("can't write %s", DRIFTFILE); ++ log_warnx("main process: can't write drift file %s", DRIFTFILE); + warnonce = 0; + } + clearerr(freqfp); +@@ -678,7 +677,7 @@ writefreq(double d) + } + off = ftello(freqfp); + if (off == -1 || ftruncate(fileno(freqfp), off) == -1) +- log_warnx("can't truncate %s", DRIFTFILE); ++ log_warnx("main process: can't truncate drift file %s", DRIFTFILE); + fsync(fileno(freqfp)); + return 1; + } +@@ -704,7 +703,7 @@ ctl_main(int argc, char *argv[]) + case 's': + showopt = ctl_lookup_option(optarg, ctl_showopt_list); + if (showopt == NULL) { +- warnx("Unknown show modifier '%s'", optarg); ++ warnx("control socket: unknown show modifier '%s'", optarg); + usage(); + } + break; +@@ -736,18 +735,18 @@ ctl_main(int argc, char *argv[]) + /* NOTREACHED */ + + if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) +- err(1, "ntpctl: socket"); ++ err(1, "ntpctl: socket error"); + + memset(&sa, 0, sizeof(sa)); + sa.sun_family = AF_UNIX; + if (strlcpy(sa.sun_path, sockname, sizeof(sa.sun_path)) >= + sizeof(sa.sun_path)) +- errx(1, "ctl socket name too long"); ++ errx(1, "ntpctl: control socket name is too long"); + if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) +- err(1, "connect: %s", sockname); ++ err(1, "ntpctl: failed to connect to socket %s", sockname); + + if (pledge("stdio", NULL) == -1) +- err(1, "pledge"); ++ err(1, "ntpctl: can't restrict privileges"); + + if ((ibuf_ctl = malloc(sizeof(struct imsgbuf))) == NULL) + err(1, NULL); +@@ -771,24 +770,24 @@ ctl_main(int argc, char *argv[]) + 0, 0, -1, NULL, 0); + break; + default: +- errx(1, "invalid action"); ++ errx(1, "ntpctl: invalid action"); + break; /* NOTREACHED */ + } + + while (ibuf_ctl->w.queued) + if (msgbuf_write(&ibuf_ctl->w) <= 0 && errno != EAGAIN) +- err(1, "ibuf_ctl: msgbuf_write error"); ++ err(1, "ntpctl: stored control message buffer data: write error"); + + done = 0; + while (!done) { + if ((n = imsg_read(ibuf_ctl)) == -1 && errno != EAGAIN) +- err(1, "ibuf_ctl: imsg_read error"); ++ err(1, "ntpctl: stored control message buffer data: read error"); + if (n == 0) + errx(1, "ntpctl: pipe closed"); + + while (!done) { + if ((n = imsg_get(ibuf_ctl, &imsg)) == -1) +- err(1, "ibuf_ctl: imsg_get error"); ++ err(1, "ntpctl: stored control message buffer data: get error"); + if (n == 0) + break; + +@@ -853,7 +852,7 @@ ctl_lookup_option(char *cmd, const char + if (item == NULL) + item = *list; + else +- errx(1, "%s is ambiguous", cmd); ++ errx(1, "ntpctl: optional argument %s is ambiguous", cmd); + } + return (item); + } +@@ -866,16 +865,17 @@ show_status_msg(struct imsg *imsg) + struct timeval tv; + + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_status)) +- fatalx("invalid IMSG_CTL_SHOW_STATUS received"); ++ fatalx("ntpctl: invalid control socket data size for status check"); + + cstatus = (struct ctl_show_status *)imsg->data; + ++ printf("ntpctl: "); + if (cstatus->peercnt > 0) +- printf("%d/%d peers valid, ", ++ printf("%d/%d peers are valid, ", + cstatus->valid_peers, cstatus->peercnt); + + if (cstatus->sensorcnt > 0) +- printf("%d/%d sensors valid, ", ++ printf("%d/%d sensors are valid, ", + cstatus->valid_sensors, cstatus->sensorcnt); + + if (cstatus->constraint_median) { +@@ -895,9 +895,9 @@ show_status_msg(struct imsg *imsg) + printf("no peers and no sensors configured\n"); + + if (cstatus->synced == 1) +- printf("clock synced, stratum %u\n", cstatus->stratum); ++ printf("clock is synced, stratum %u\n", cstatus->stratum); + else { +- printf("clock unsynced"); ++ printf("clock is unsynced"); + clock_offset = cstatus->clock_offset < 0 ? + -1.0 * cstatus->clock_offset : cstatus->clock_offset; + if (clock_offset > 5e-7) +@@ -918,20 +918,20 @@ show_peer_msg(struct imsg *imsg, int cal + + if (imsg->hdr.type == IMSG_CTL_SHOW_PEERS_END) { + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt)) +- fatalx("invalid IMSG_CTL_SHOW_PEERS_END received"); ++ fatalx("ntpctl: invalid control socket data size for a NTP peer end check"); + memcpy(&cnt, imsg->data, sizeof(cnt)); + if (cnt == 0) +- printf("no peers configured\n"); ++ printf("ntpctl: no peers configured\n"); + return; + } + + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_peer)) +- fatalx("invalid IMSG_CTL_SHOW_PEERS received"); ++ fatalx("ntpctl: invalid control socket data size for NTP peer check"); + + cpeer = (struct ctl_show_peer *)imsg->data; + + if (strlen(cpeer->peer_desc) > MAX_DISPLAY_WIDTH - 1) +- fatalx("peer_desc is too long"); ++ fatalx("ntpctl: NTP peer description is too long"); + + if (firsttime) { + firsttime = 0; +@@ -968,20 +968,20 @@ show_sensor_msg(struct imsg *imsg, int c + + if (imsg->hdr.type == IMSG_CTL_SHOW_SENSORS_END) { + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(cnt)) +- fatalx("invalid IMSG_CTL_SHOW_SENSORS_END received"); ++ fatalx("ntpctl: invalid control socket data size for sensor end check"); + memcpy(&cnt, imsg->data, sizeof(cnt)); + if (cnt == 0) +- printf("no sensors configured\n"); ++ printf("ntpctl: no sensors configured\n"); + return; + } + + if (imsg->hdr.len != IMSG_HEADER_SIZE + sizeof(struct ctl_show_sensor)) +- fatalx("invalid IMSG_CTL_SHOW_SENSORS received"); ++ fatalx("ntpctl: invalid control socket data size for a sensor end check"); + + csensor = (struct ctl_show_sensor *)imsg->data; + + if (strlen(csensor->sensor_desc) > MAX_DISPLAY_WIDTH - 1) +- fatalx("sensor_desc is too long"); ++ fatalx("ntpctl: sensor description is too long"); + + if (firsttime) { + firsttime = 0; +--- a/src/ntp_dns.c 2020-08-01 00:19:23.449059082 +0300 ++++ b/src/ntp_dns.c 2020-07-31 23:26:26.505722398 +0300 +@@ -66,16 +66,16 @@ ntp_dns(struct ntpd_conf *nconf, struct + + res_init(); + if (setpriority(PRIO_PROCESS, 0, 0) == -1) +- log_warn("could not set priority"); ++ log_warn("DNS process: can't set priority"); + + log_init(nconf->debug ? LOG_TO_STDERR : LOG_TO_SYSLOG, nconf->verbose, + LOG_DAEMON); + if (!nconf->debug && setsid() == -1) +- fatal("setsid"); +- log_procinit("dns"); ++ fatal("DNS process: can't create a new session"); ++ log_procinit("DNS"); + + if ((nullfd = open("/dev/null", O_RDWR, 0)) == -1) +- fatal(NULL); ++ fatal("DNS process: can't read /dev/null"); + + if (!nconf->debug) { + dup2(nullfd, STDIN_FILENO); +@@ -84,28 +84,28 @@ ntp_dns(struct ntpd_conf *nconf, struct + } + close(nullfd); + +- setproctitle("dns engine"); ++ setproctitle("DNS engine"); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) +- fatal("can't drop privileges"); ++ fatal("DNS process: can't drop privileges"); + + signal(SIGTERM, sighdlr_dns); + signal(SIGINT, sighdlr_dns); + signal(SIGHUP, SIG_IGN); + + if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) +- fatal(NULL); ++ fatal("DNS process: can't allocate memory for data buffer"); + imsg_init(ibuf_dns, PARENT_SOCK_FILENO); + + if (pledge("stdio dns", NULL) == -1) +- err(1, "pledge"); ++ err(1, "DNS process: can't restrict privileges"); + + if (non_numeric) + probe_root(); + else +- log_debug("all addresses numeric, no dns probe"); ++ log_debug("DNS process: all addresses numeric, no DNS probe"); + + while (quit_dns == 0) { + pfd[0].fd = ibuf_dns->fd; +@@ -115,14 +115,14 @@ ntp_dns(struct ntpd_conf *nconf, struct + + if ((nfds = poll(pfd, 1, INFTIM)) == -1) + if (errno != EINTR) { +- log_warn("poll error"); ++ log_warn("file descriptor: poll error"); + quit_dns = 1; + } + + if (nfds > 0 && (pfd[0].revents & POLLOUT)) + if (msgbuf_write(&ibuf_dns->w) <= 0 && + errno != EAGAIN) { +- log_warn("pipe write error (to ntp engine)"); ++ log_warn("file descriptor: pipe write error (to NTP engine)"); + quit_dns = 1; + } + +@@ -168,11 +168,11 @@ dns_dispatch_imsg(struct ntpd_conf *ncon + str = "IMSG_CONSTRAINT_DNS"; + name = imsg.data; + if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) +- fatalx("invalid %s received", str); ++ fatalx("DNS process: invalid header size received (%s)", str); + len = imsg.hdr.len - 1 - IMSG_HEADER_SIZE; + if (name[len] != '\0' || + strlen(name) != len) +- fatalx("invalid %s received", str); ++ fatalx("DNS process: invalid name received (%s)", str); + if ((cnt = host_dns(name, nconf->status.synced, + &hn)) == -1) + break; +@@ -252,5 +252,5 @@ probe_root(void) + } + if (imsg_compose(ibuf_dns, IMSG_PROBE_ROOT, 0, 0, -1, &n, + sizeof(int)) == -1) +- fatalx("probe_root"); ++ fatalx("DNS process: can't compose data buffer for probe"); + } +--- a/src/ntp_msg.c 2020-08-01 00:19:21.849059080 +0300 ++++ b/src/ntp_msg.c 2020-07-31 23:27:44.465722482 +0300 +@@ -29,7 +29,7 @@ int + ntp_getmsg(struct sockaddr *sa, char *p, ssize_t len, struct ntp_msg *msg) + { + if (len != NTP_MSGSIZE_NOAUTH && len != NTP_MSGSIZE) { +- log_debug("malformed packet received from %s", ++ log_debug("NTP message: malformed packet received from %s", + log_sockaddr(sa)); + return (-1); + } +@@ -57,12 +57,12 @@ ntp_sendmsg(int fd, struct sockaddr *sa, + /* logging is futile */ + return (-1); + } +- log_warn("sendto"); ++ log_warn("NTP message: can't send data to destination socket"); + return (-1); + } + + if (n != sizeof(*msg)) { +- log_warnx("ntp_sendmsg: only %zd of %zu bytes sent", n, ++ log_warnx("NTP message: only %zd of %zu bytes sent", n, + sizeof(*msg)); + return (-1); + } +--- a/src/parse.y 2020-08-01 00:19:23.405725749 +0300 ++++ b/src/parse.y 2020-07-31 23:57:08.642391006 +0300 +@@ -122,7 +122,7 @@ main : LISTEN ON address listen_opts { + next = h->next; + la = calloc(1, sizeof(struct listen_addr)); + if (la == NULL) +- fatal("listen on calloc"); ++ fatal("can't allocate memory for listening address"); + la->fd = -1; + la->rtable = $4.rtable; + memcpy(&la->sa, &h->ss, +@@ -348,7 +348,7 @@ urllist : urllist address { + + if (inet_pton(AF_INET, $2->name, &ina) != 1 && + inet_pton(AF_INET6, $2->name, &in6a) != 1) { +- yyerror("url can only be followed by IP " ++ yyerror("URL can only be followed by IP " + "addresses"); + free($2->name); + free($2); +@@ -376,7 +376,7 @@ url : STRING { + + if (($$ = calloc(1, sizeof(struct ntp_addr_wrap))) == + NULL) +- fatal("calloc"); ++ fatal("can't allocate memory for URL"); + + if (strncmp("https://", $1, + strlen("https://")) != 0) { +@@ -388,16 +388,16 @@ url : STRING { + path = hname + strcspn(hname, "/\\"); + if (*path != '\0') { + if (($$->path = strdup(path)) == NULL) +- fatal("strdup"); ++ fatal("can't allocate memory for %s", path); + *path = '\0'; + } + host(hname, &$$->a); + if (($$->name = strdup(hname)) == NULL) +- fatal("strdup"); ++ fatal("can't allocate memory for %s", hname); + } + if ($$->path == NULL && + ($$->path = strdup("/")) == NULL) +- fatal("strdup"); ++ fatal("can't allocate memory space for new URL"); + } + ; + +@@ -453,7 +453,7 @@ refid : REFID STRING { + size_t l = strlen($2); + + if (l < 1 || l > 4) { +- yyerror("refid must be 1 to 4 characters"); ++ yyerror("refid length must be from 1 to 4 characters"); + free($2); + YYERROR; + } +@@ -482,7 +482,7 @@ rtable : RTABLE NUMBER { + #ifdef RT_TABLEID_MAX + if ($2 < 0 || $2 > RT_TABLEID_MAX) { + yyerror("rtable must be between 1" +- " and RT_TABLEID_MAX"); ++ " and %d", RT_TABLEID_MAX); + YYERROR; + } + #endif +@@ -518,7 +518,7 @@ yyerror(const char *fmt, ...) + file->errors++; + va_start(ap, fmt); + if (vasprintf(&msg, fmt, ap) == -1) +- fatalx("yyerror vasprintf"); ++ fatalx("can't create error string"); + va_end(ap); + log_warnx("%s:%d: %s", file->name, yylval.lineno, msg); + free(msg); +@@ -710,7 +710,7 @@ yylex(void) + } + yylval.v.string = strdup(buf); + if (yylval.v.string == NULL) +- fatal("yylex: strdup"); ++ fatal("can't allocate memory for buffered quote string"); + return (STRING); + } + +@@ -721,7 +721,7 @@ yylex(void) + do { + *p++ = c; + if ((size_t)(p-buf) >= sizeof(buf)) { +- yyerror("string too long"); ++ yyerror("string is too long"); + return (findeol()); + } + } while ((c = lgetc(0)) != EOF && isdigit(c)); +@@ -760,7 +760,7 @@ nodigits: + do { + *p++ = c; + if ((size_t)(p-buf) >= sizeof(buf)) { +- yyerror("string too long"); ++ yyerror("string is too long"); + return (findeol()); + } + } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); +@@ -768,7 +768,7 @@ nodigits: + *p = '\0'; + if ((token = lookup(buf)) == STRING) + if ((yylval.v.string = strdup(buf)) == NULL) +- fatal("yylex: strdup"); ++ fatal("can't allocate memory for buffered string"); + return (token); + } + if (c == '\n') { +@@ -786,16 +786,16 @@ pushfile(const char *name) + struct file *nfile; + + if ((nfile = calloc(1, sizeof(struct file))) == NULL) { +- log_warn("%s", __func__); ++ log_warn("can't allocate space for file"); + return (NULL); + } + if ((nfile->name = strdup(name)) == NULL) { +- log_warn("%s", __func__); ++ log_warn("can't allocate memory for file name"); + free(nfile); + return (NULL); + } + if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { +- log_warn("%s: %s", __func__, nfile->name); ++ log_warn("can't open file %s", nfile->name); + free(nfile->name); + free(nfile); + return (NULL); +--- a/src/sensors.c 2020-08-01 00:19:21.849059080 +0300 ++++ b/src/sensors.c 2020-07-31 23:58:46.572391110 +0300 +@@ -90,7 +90,7 @@ sensor_probe(int devid, char *dxname, st + return (0); + if (errno == ENOENT) + return (-1); +- log_warn("sensor_probe sysctl"); ++ log_warn("sensor: can't set probe device from kernel data"); + } + + if (sensordev.maxnumt[SENSOR_TIMEDELTA] == 0) +@@ -101,7 +101,9 @@ sensor_probe(int devid, char *dxname, st + slen = sizeof(*sensor); + if (sysctl(mib, 5, sensor, &slen, NULL, 0) == -1) { + if (errno != ENOENT) +- log_warn("sensor_probe sysctl"); ++ log_warn("sensor %s: can't set probe device from kernel data", ++ sensor->device); ++ ); + return (0); + } + +@@ -128,7 +130,9 @@ sensor_add(int sensordev, char *dxname) + return; + + if ((s = calloc(1, sizeof(*s))) == NULL) +- fatal("sensor_add calloc"); ++ fatal("sensor %s: can't allocate memory for the device", ++ s->device ++ ); + + s->next = getmonotime(); + s->weight = cs->weight; +@@ -136,7 +140,8 @@ sensor_add(int sensordev, char *dxname) + s->stratum = cs->stratum - 1; + s->trusted = cs->trusted; + if ((s->device = strdup(dxname)) == NULL) +- fatal("sensor_add strdup"); ++ fatal("sensor %s: can't allocate memory for the device", ++ s->device); + s->sensordevid = sensordev; + + if (cs->refstr == NULL) +@@ -148,7 +153,7 @@ sensor_add(int sensordev, char *dxname) + + TAILQ_INSERT_TAIL(&conf->ntp_sensors, s, entry); + +- log_debug("sensor %s added (weight %d, correction %.6f, refstr %.4u, " ++ log_debug("sensor %s: added (weight %d, correction %.6f, refstr %.4u, " + "stratum %d)", s->device, s->weight, s->correction / 1e6, + s->refid, s->stratum); + } +@@ -244,7 +249,7 @@ sensor_update(struct ntp_sensor *s) + + if ((offsets = calloc(SENSOR_OFFSETS, sizeof(struct ntp_offset *))) == + NULL) +- fatal("calloc sensor_update"); ++ fatal("sensor %s: can't allocate memory for data update", s->device); + + for (i = 0; i < SENSOR_OFFSETS; i++) + offsets[i] = &s->offsets[i]; +@@ -260,6 +265,6 @@ sensor_update(struct ntp_sensor *s) + } + free(offsets); + +- log_debug("sensor update %s: offset %f", s->device, s->update.offset); ++ log_debug("sensor %s: update: offset %fs", s->device, s->update.offset); + priv_adjtime(); + } +--- a/src/server.c 2020-08-01 00:19:23.439059082 +0300 ++++ b/src/server.c 2020-08-01 00:04:05.369058112 +0300 +@@ -53,7 +53,7 @@ setup_listeners(struct servent *se, stru + switch (lap->sa.ss_family) { + case AF_UNSPEC: + if (getifaddrs(&ifa) == -1) +- fatal("getifaddrs"); ++ fatal("NTP server: can't get network interfaces"); + + for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { + sa = ifap->ifa_addr; +@@ -87,7 +87,7 @@ setup_listeners(struct servent *se, stru + + if ((la = calloc(1, sizeof(struct listen_addr))) == + NULL) +- fatal("setup_listeners calloc"); ++ fatal("NTP server: can't allocate memory for listening address"); + + memcpy(&la->sa, sa, SA_LEN(sa)); + #ifdef SO_RTABLE +@@ -123,36 +123,37 @@ setup_listeners(struct servent *se, stru + la = nla; + continue; + default: +- fatalx("king bula sez: af borked"); ++ fatalx("NTP server: wrong network address family"); + } + +- log_info("listening on %s %s", ++ log_info("NTP server: listening on %s %s (UDP port %d)", + log_sockaddr((struct sockaddr *)&la->sa), +- print_rtable(la->rtable)); ++ print_rtable(la->rtable), ++ ntohs((((struct sockaddr_in *)&la->sa)->sin_port))); + + if ((la->fd = socket(la->sa.ss_family, SOCK_DGRAM, 0)) == -1) +- fatal("socket"); ++ fatal("NTP server: socket error"); + + if (la->sa.ss_family == AF_INET && setsockopt(la->fd, + IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) +- log_warn("setsockopt IPTOS_LOWDELAY"); ++ log_warn("NTP server: can't set IPv4 socket field IP_TOS"); + + #ifdef IPV6_V6ONLY + if (la->sa.ss_family == AF_INET6 && setsockopt(la->fd, + IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) +- log_warn("setsockopt IPV6_V6ONLY"); ++ log_warn("NTP server: can't set IPv6 socket field IPV6_V6ONLY"); + #endif + + #ifdef SO_RTABLE + if (la->rtable != -1 && + setsockopt(la->fd, SOL_SOCKET, SO_RTABLE, &la->rtable, + sizeof(la->rtable)) == -1) +- fatal("setup_listeners setsockopt SO_RTABLE"); ++ log_warn("NTP server: can't set socket field SO_RTABLE"); + #endif + + if (bind(la->fd, (struct sockaddr *)&la->sa, + SA_LEN((struct sockaddr *)&la->sa)) == -1) { +- log_warn("bind on %s failed, skipping", ++ log_warn("NTP server %s: bind failed, skipping", + log_sockaddr((struct sockaddr *)&la->sa)); + close(la->fd); + nla = TAILQ_NEXT(la, entry); +@@ -185,11 +186,12 @@ server_dispatch(int fd, struct ntpd_conf + (struct sockaddr *)&fsa, &fsa_len)) == -1) { + if (errno == EHOSTUNREACH || errno == EHOSTDOWN || + errno == ENETUNREACH || errno == ENETDOWN) { +- log_warn("recvfrom %s", ++ log_warn("NTP server %s: can't receive socket message: " ++ "network is down or host is unreachable", + log_sockaddr((struct sockaddr *)&fsa)); + return (0); + } else +- fatal("recvfrom"); ++ fatal("NTP server: can't receive socket message"); + } + + rectime = gettime_corrected(); +--- a/src/util.c 2020-08-01 00:19:23.449059082 +0300 ++++ b/src/util.c 2020-08-01 01:35:02.868060038 +0300 +@@ -46,7 +46,7 @@ gettime(void) + struct timeval tv; + + if (gettimeofday(&tv, NULL) == -1) +- fatal("gettimeofday"); ++ fatal("can't get time value"); + + return (gettime_from_timeval(&tv)); + } +@@ -66,7 +66,7 @@ getmonotime(void) + struct timespec ts; + + if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) +- fatal("clock_gettime"); ++ fatal("can't get elapsed clock time"); + + return (ts.tv_sec); + } +@@ -172,7 +172,7 @@ start_child(char *pname, int cfd, int ar + /* Prepare the child process new argv. */ + nargv = calloc(argc + 3, sizeof(char *)); + if (nargv == NULL) +- fatal("%s: calloc", __func__); ++ fatal("main process: can't allocate enough memory for child (%s)", __func__); + + /* Copy the program name first. */ + nargc = 0; +@@ -188,18 +188,18 @@ start_child(char *pname, int cfd, int ar + + switch (pid = fork()) { + case -1: +- fatal("%s: fork", __func__); ++ fatal("main process: can't fork (%s)", __func__); + break; + case 0: + /* Prepare the parent socket and execute. */ + if (cfd != PARENT_SOCK_FILENO) { + if (dup2(cfd, PARENT_SOCK_FILENO) == -1) +- fatal("dup2"); ++ fatal("parent socket: can't duplicate file descriptor %d", cfd); + } else if (fcntl(cfd, F_SETFD, 0) == -1) +- fatal("fcntl"); ++ fatal("child file descriptor %d: can't reset flags", cfd); + + execvp(argv[0], nargv); +- fatal("%s: execvp", __func__); ++ fatal("child process: duplication of actions (%s: execvp)", __func__); + break; + + default: +--- a/compat/adjfreq_freebsd.c 2020-08-01 00:19:08.772392399 +0300 ++++ b/compat/adjfreq_freebsd.c 2020-08-01 00:14:17.172392093 +0300 +@@ -38,19 +38,19 @@ adjfreq(const int64_t *freq, int64_t *ol + txc.freq = *freq / 1e3 / (1LL << 16); + + if ((ntp_adjtime(&txc)) == -1) +- log_warn("ntp_adjtime (2) failed"); ++ log_warn("clock: adjustment failed"); + +- log_debug("ntp_adjtime adjusted frequency by %fppm", ++ log_debug("clock: frequency adjusted by %fppm", + ((txc.freq * 1e3) * (1LL<<16) / 1e3 / (1LL << 32))); + } + if (oldfreq != NULL) { + txc.modes = 0; + if ((ntp_adjtime(&txc)) == -1) { +- log_warn("ntp_adjtime (1) failed"); ++ log_warn("clock: adjustment failed"); + return -1; + } + newfreq = (txc.freq * 1e3) * (1LL<<16); +- log_debug("ntp_adjtime returns frequency of %fppm", ++ log_debug("clock: adjustment returns frequency of %fppm", + newfreq / 1e3 / (1LL << 32)); + *oldfreq = newfreq; + } +@@ -74,6 +74,6 @@ update_time_sync_status(int synced) + } else + txc.status = STA_UNSYNC; + if (ntp_adjtime(&txc) == -1) +- log_warn("ntp_adjtime (3) failed"); ++ log_warn("clock: adjustment failed"); + return; + } +--- a/compat/adjfreq_linux.c 2020-08-01 00:19:08.772392399 +0300 ++++ b/compat/adjfreq_linux.c 2020-08-01 00:13:49.995725398 +0300 +@@ -38,19 +38,19 @@ adjfreq(const int64_t *freq, int64_t *ol + txc.freq = *freq / 1e3 / (1LL << 16); + + if ((adjtimex(&txc)) == -1) +- log_warn("adjtimex failed"); ++ log_warn("clock: adjustment failed"); + +- log_debug("adjtimex adjusted frequency by %fppm", ++ log_debug("clock: frequency adjusted by %fppm", + ((txc.freq * 1e3) * (1LL<<16) / 1e3 / (1LL << 32))); + } + if (oldfreq != NULL) { + txc.modes = 0; + if ((adjtimex(&txc)) == -1) { +- log_warn("adjtimex failed"); ++ log_warn("clock: adjustment failed"); + return -1; + } + newfreq = (txc.freq * 1e3) * (1LL<<16); +- log_debug("adjtimex returns frequency of %fppm", ++ log_debug("clock: adjustment returns frequency of %fppm", + newfreq / 1e3 / (1LL << 32)); + *oldfreq = newfreq; + } +@@ -74,6 +74,6 @@ update_time_sync_status(int synced) + } else + txc.status = STA_UNSYNC; + if (adjtimex(&txc) == -1) +- log_warn("ntp_adjtime (3) failed"); ++ log_warn("clock: adjustment failed"); + return; + } +--- a/compat/adjfreq_netbsd.c 2020-08-01 00:19:08.772392399 +0300 ++++ b/compat/adjfreq_netbsd.c 2020-08-01 00:15:45.465725518 +0300 +@@ -39,19 +39,19 @@ adjfreq(const int64_t *freq, int64_t *ol + txc.freq = *freq / 1e3 / (1LL << 16); + + if ((ntp_adjtime(&txc)) == -1) +- log_warn("ntp_adjtime (2) failed"); ++ log_warn("clock: adjustment failed"); + +- log_debug("ntp_adjtime adjusted frequency by %fppm", ++ log_debug("clock: frequency adjusted by %fppm", + ((txc.freq * 1e3) * (1LL<<16) / 1e3 / (1LL << 32))); + } + if (oldfreq != NULL) { + txc.modes = 0; + if ((ntp_adjtime(&txc)) == -1) { +- log_warn("ntp_adjtime (1) failed"); ++ log_warn("clock: adjustment failed"); + return -1; + } + newfreq = (txc.freq * 1e3) * (1LL<<16); +- log_debug("ntp_adjtime returns frequency of %fppm", ++ log_debug("clock: adjustment returns frequency of %fppm", + newfreq / 1e3 / (1LL << 32)); + *oldfreq = newfreq; + } +@@ -75,6 +75,6 @@ update_time_sync_status(int synced) + } else + txc.status = STA_UNSYNC; + if (ntp_adjtime(&txc) == -1) +- log_warn("ntp_adjtime (3) failed"); ++ log_warn("clock: adjustment failed"); + return; + } diff --git a/patches/2-patch_ntpctl-sensors-tolowercase.patch b/patches/2-patch_ntpctl-sensors-tolowercase.patch new file mode 100644 index 0000000..c862cce --- /dev/null +++ b/patches/2-patch_ntpctl-sensors-tolowercase.patch @@ -0,0 +1,54 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Set 'Sensors' to lowercase in ntpctl settings + + +--- a/src/ntpd.c 2020-08-01 13:33:10.798104786 +0300 ++++ b/src/ntpd.c 2020-08-01 13:33:27.848104803 +0300 +@@ -76,7 +76,7 @@ extern u_int constraint_cnt; + const char *showopt; + + static const char *ctl_showopt_list[] = { +- "peers", "Sensors", "status", "all", NULL ++ "peers", "sensors", "status", "all", NULL + }; + + void +@@ -115,7 +115,7 @@ usage(void) + + if (strcmp(__progname, "ntpctl") == 0) + fprintf(stderr, +- "usage: ntpctl -s all | peers | Sensors | status\n"); ++ "usage: ntpctl -s all | peers | sensors | status\n"); + else + fprintf(stderr, "usage: %s [-dnv] [-f file] [-p file]\n", + __progname); +--- a/src/ntpctl.8 2020-07-31 23:00:50.329054281 +0300 ++++ b/src/ntpctl.8 2020-08-01 00:35:22.158056263 +0300 +@@ -22,7 +22,7 @@ + .Nd control the Network Time Protocol daemon + .Sh SYNOPSIS + .Nm ntpctl +-.Fl s Cm all | peers | Sensors | status ++.Fl s Cm all | peers | sensors | status + .Sh DESCRIPTION + The + .Nm +@@ -32,7 +32,7 @@ daemon. + .Pp + The options are as follows: + .Bl -tag -width "-s modifierX" +-.It Fl s Cm all | peers | Sensors | status ++.It Fl s Cm all | peers | sensors | status + Used to display information about the running daemon. + Keywords may be abbreviated. + .Pp +@@ -46,7 +46,7 @@ in seconds, and offset, network delay an + When the system clock is synced to a peer, an asterisk + is displayed to the left of the weight column for that peer. + .Pp +-.Cm Sensors ++.Cm sensors + shows the following information about each sensor: weight, sensor "good" + status, stratum, and offset and the configured correction in + milliseconds. diff --git a/patches/3-patch_unhardcode-ports.patch b/patches/3-patch_unhardcode-ports.patch new file mode 100644 index 0000000..d041514 --- /dev/null +++ b/patches/3-patch_unhardcode-ports.patch @@ -0,0 +1,678 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Unhardcode NTP server, client and constraint UDP & TCP port numbers + + +--- a/src/client.c 2020-08-02 02:03:13.840286484 +0300 ++++ b/src/client.c 2020-08-02 02:04:23.993619892 +0300 +@@ -76,13 +76,13 @@ client_addr_init(struct ntp_peer *p) + case AF_INET: + sa_in = (struct sockaddr_in *)&h->ss; + if (ntohs(sa_in->sin_port) == 0) +- sa_in->sin_port = htons(123); ++ sa_in->sin_port = htons(p->addr_head.port); + p->state = STATE_DNS_DONE; + break; + case AF_INET6: + sa_in6 = (struct sockaddr_in6 *)&h->ss; + if (ntohs(sa_in6->sin6_port) == 0) +- sa_in6->sin6_port = htons(123); ++ sa_in6->sin6_port = htons(p->addr_head.port); + p->state = STATE_DNS_DONE; + break; + default: +@@ -122,9 +122,10 @@ client_nextaddr(struct ntp_peer *p) + p->shift = 0; + p->trustlevel = TRUSTLEVEL_PATHETIC; + +- if (p->addr == NULL) ++ if (p->addr == NULL) { + p->addr = p->addr_head.a; +- else if ((p->addr = p->addr->next) == NULL) ++ p->port = p->addr_head.port; ++ } else if ((p->addr = p->addr->next) == NULL) + return (1); + + return (0); +--- a/src/ntp.c 2020-07-31 23:34:32.000000000 +0300 ++++ b/src/ntp.c 2020-08-01 00:56:09.608057581 +0300 +@@ -603,6 +603,8 @@ ntp_dispatch_imsg_dns(void) + peer->addr_head.name; + npeer->addr_head.pool = + peer->addr_head.pool; ++ npeer->addr_head.port = ++ peer->addr_head.port; + client_peer_init(npeer); + npeer->state = STATE_DNS_DONE; + peer_add(npeer); +@@ -611,6 +613,7 @@ ntp_dispatch_imsg_dns(void) + h->next = peer->addr; + peer->addr = h; + peer->addr_head.a = peer->addr; ++ peer->addr_head.port = peer->port; + peer->state = STATE_DNS_DONE; + } + } +--- a/src/config.c 2020-07-31 23:11:30.000000000 +0300 ++++ b/src/config.c 2020-08-01 01:02:14.468057965 +0300 +@@ -196,3 +196,10 @@ new_constraint(void) + return (p); + } + ++int ++intdup(int in) ++{ ++ int *out; ++ out = ∈ ++ return *out; ++} +--- a/src/ntpd.h 2020-07-31 23:00:51.000000000 +0300 ++++ b/src/ntpd.h 2020-08-01 01:27:06.418059534 +0300 +@@ -95,7 +95,7 @@ + #define CONSTRAINT_SCAN_INTERVAL (15*60) + #define CONSTRAINT_SCAN_TIMEOUT (10) + #define CONSTRAINT_MARGIN (2.0*60) +-#define CONSTRAINT_PORT "443" /* HTTPS port */ ++ + #define CONSTRAINT_MAXHEADERLENGTH 8192 + #define CONSTRAINT_PASSFD (STDERR_FILENO + 1) + +@@ -121,6 +121,7 @@ struct listen_addr { + struct sockaddr_storage sa; + int fd; + int rtable; ++ int port; + }; + + struct ntp_addr { +@@ -132,14 +133,17 @@ struct ntp_addr { + struct ntp_addr_wrap { + char *name; + char *path; ++ int port; + struct ntp_addr *a; + u_int8_t pool; + }; + + struct ntp_addr_msg { + struct ntp_addr a; ++ int port; + size_t namelen; + size_t pathlen; ++ size_t portlen; + }; + + struct ntp_status { +@@ -184,6 +188,7 @@ struct ntp_peer { + u_int8_t trusted; + int lasterror; + int senderrors; ++ int port; + }; + + struct ntp_sensor { +@@ -206,6 +211,7 @@ struct constraint { + TAILQ_ENTRY(constraint) entry; + struct ntp_addr_wrap addr_head; + struct ntp_addr *addr; ++ int port; + int senderrors; + enum client_state state; + u_int32_t id; +@@ -365,6 +371,7 @@ void host_dns_free(struct ntp_addr *) + struct ntp_peer *new_peer(void); + struct ntp_conf_sensor *new_sensor(char *); + struct constraint *new_constraint(void); ++int intdup(int); + + /* ntp_msg.c */ + int ntp_getmsg(struct sockaddr *, char *, ssize_t, struct ntp_msg *); +@@ -401,6 +408,7 @@ void priv_constraint_kill(u_int32_t); + int priv_constraint_dispatch(struct pollfd *); + void priv_constraint_check_child(pid_t, int); + char *get_string(u_int8_t *, size_t); ++int intlen(int); + + /* util.c */ + double gettime_corrected(void); +--- a/src/constraint.c 2020-08-02 01:56:09.060286035 +0300 ++++ b/src/constraint.c 2020-08-02 01:56:47.110286075 +0300 +@@ -66,11 +66,11 @@ void priv_constraint_readquery(struct c + uint8_t **); + + struct httpsdate * +- httpsdate_init(const char *, const char *, const char *, ++ httpsdate_init(const char *, const int *, const char *, + const char *, const u_int8_t *, size_t); + void httpsdate_free(void *); + int httpsdate_request(struct httpsdate *, struct timeval *); +-void *httpsdate_query(const char *, const char *, const char *, ++void *httpsdate_query(const char *, const int *, const char *, + const char *, const u_int8_t *, size_t, + struct timeval *, struct timeval *); + +@@ -125,13 +125,13 @@ constraint_addr_init(struct constraint * + case AF_INET: + sa_in = (struct sockaddr_in *)&h->ss; + if (ntohs(sa_in->sin_port) == 0) +- sa_in->sin_port = htons(443); ++ sa_in->sin_port = htons(cstr->addr_head.port); + cstr->state = STATE_DNS_DONE; + break; + case AF_INET6: + sa_in6 = (struct sockaddr_in6 *)&h->ss; + if (ntohs(sa_in6->sin6_port) == 0) +- sa_in6->sin6_port = htons(443); ++ sa_in6->sin6_port = htons(cstr->addr_head.port); + cstr->state = STATE_DNS_DONE; + break; + default: +@@ -206,6 +206,7 @@ constraint_query(struct constraint *cstr + + memset(&am, 0, sizeof(am)); + memcpy(&am.a, cstr->addr, sizeof(am.a)); ++ memcpy(&am.port, &cstr->addr_head.port, sizeof(am.port)); + + iov[iov_cnt].iov_base = &am; + iov[iov_cnt++].iov_len = sizeof(am); +@@ -219,6 +220,11 @@ constraint_query(struct constraint *cstr + iov[iov_cnt].iov_base = cstr->addr_head.path; + iov[iov_cnt++].iov_len = am.pathlen; + } ++ if (cstr->addr_head.port) { ++ am.portlen = intlen(cstr->addr_head.port) + 1; ++ iov[iov_cnt].iov_base = &cstr->addr_head.port; ++ iov[iov_cnt++].iov_len = am.portlen; ++ } + + imsg_composev(ibuf_main, IMSG_CONSTRAINT_QUERY, + cstr->id, 0, -1, iov, iov_cnt); +@@ -246,7 +252,7 @@ priv_constraint_msg(u_int32_t id, u_int8 + return; + } + memcpy(&am, data, sizeof(am)); +- if (len != (sizeof(am) + am.namelen + am.pathlen)) { ++ if (len != (sizeof(am) + am.namelen + am.pathlen + am.portlen)) { + log_warnx("constraint id %d: invalid query received", id); + return; + } +@@ -301,6 +307,7 @@ priv_constraint_readquery(struct constra + int n; + struct imsg imsg; + size_t mlen; ++ int port; + + /* Read the message our parent left us. */ + if (((n = imsg_read(&cstr->ibuf)) == -1 && errno != EAGAIN) || n == 0) +@@ -324,7 +331,7 @@ priv_constraint_readquery(struct constra + ); + + memcpy(am, imsg.data, sizeof(*am)); +- if (mlen != (sizeof(*am) + am->namelen + am->pathlen)) ++ if (mlen != (sizeof(*am) + am->namelen + am->pathlen + am->portlen)) + fatalx("constraint: invalid message length received from parent process (%s)", + __func__ + ); +@@ -334,12 +341,15 @@ priv_constraint_readquery(struct constra + fatal("constraint: can't allocate memory (%s)", __func__); + + memcpy(h, &am->a, sizeof(*h)); ++ memcpy(&port, &am->port, sizeof(port)); + h->next = NULL; +- ++ + cstr->id = imsg.hdr.peerid; + cstr->addr = h; + cstr->addr_head.a = h; +- ++ cstr->port = port; ++ cstr->addr_head.port = port; ++ + dptr = imsg.data; + memcpy(*data, dptr + sizeof(*am), mlen - sizeof(*am)); + imsg_free(&imsg); +@@ -434,10 +444,14 @@ priv_constraint_child(const char *pw_dir + get_string(data, am.pathlen)) == NULL) + fatalx("constraint %s: invalid path", addr); + } ++ if (am.portlen) { ++ if (cstr.addr_head.port == 0) ++ fatalx("constraint %s: invalid port", addr); ++ } + + /* Run! */ + if ((ctx = httpsdate_query(addr, +- CONSTRAINT_PORT, cstr.addr_head.name, cstr.addr_head.path, ++ &cstr.addr_head.port, cstr.addr_head.name, cstr.addr_head.path, + conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { + log_debug("constraint %s: failed to get proper time results", addr); + /* Abort with failure but without warning */ +@@ -800,8 +814,14 @@ constraint_msg_dns(u_int32_t id, u_int8_ + ncstr->addr_head.a = h; + ncstr->addr_head.name = strdup(cstr->addr_head.name); + ncstr->addr_head.path = strdup(cstr->addr_head.path); ++ ncstr->addr_head.port = intdup(cstr->addr_head.port); ++ ++ // Unless we do this, we have value 0 in ncstr->port ++ ncstr->port = intdup(cstr->port); ++ + if (ncstr->addr_head.name == NULL || +- ncstr->addr_head.path == NULL) ++ ncstr->addr_head.path == NULL || ++ ncstr->addr_head.port == 0 || ncstr->port == 0) + fatal("constraint id %d: DNS dispatching failed: invalid data", id); + ncstr->addr_head.pool = cstr->addr_head.pool; + ncstr->state = STATE_DNS_DONE; +@@ -811,6 +831,7 @@ constraint_msg_dns(u_int32_t id, u_int8_ + h->next = ncstr->addr; + ncstr->addr = h; + ncstr->addr_head.a = h; ++ // TODO missing port? + } + } while (len); + +@@ -912,10 +933,11 @@ constraint_check(double val) + } + + struct httpsdate * +-httpsdate_init(const char *addr, const char *port, const char *hostname, ++httpsdate_init(const char *addr, const int *port, const char *hostname, + const char *path, const u_int8_t *ca, size_t ca_len) + { + struct httpsdate *httpsdate = NULL; ++ char port_s[sizeof(port)]; + + if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL) + goto fail; +@@ -923,8 +945,10 @@ httpsdate_init(const char *addr, const c + if (hostname == NULL) + hostname = addr; + ++ sprintf(port_s, "%d", *port); ++ + if ((httpsdate->tls_addr = strdup(addr)) == NULL || +- (httpsdate->tls_port = strdup(port)) == NULL || ++ (httpsdate->tls_port = strdup(port_s)) == NULL || + (httpsdate->tls_hostname = strdup(hostname)) == NULL || + (httpsdate->tls_path = strdup(path)) == NULL) + goto fail; +@@ -1098,7 +1122,7 @@ httpsdate_request(struct httpsdate *http + } + + void * +-httpsdate_query(const char *addr, const char *port, const char *hostname, ++httpsdate_query(const char *addr, const int *port, const char *hostname, + const char *path, const u_int8_t *ca, size_t ca_len, + struct timeval *rectv, struct timeval *xmttv) + { +@@ -1183,3 +1207,17 @@ get_string(u_int8_t *ptr, size_t len) + + return strndup(ptr, i); + } ++ ++int ++intlen(int val) ++{ ++ int n = 1; ++ if (val < 0) ++ return 0; ++ while(val > 9) { ++ n++; ++ val /= 10; ++ } ++ ++ return val; ++} +--- a/src/parse.y 2020-07-31 23:57:08.000000000 +0300 ++++ b/src/parse.y 2020-08-01 01:51:28.041394057 +0300 +@@ -60,6 +60,7 @@ int findeol(void); + struct sockaddr_in query_addr4; + struct sockaddr_in6 query_addr6; + int poolseqnum; ++struct servent *se; + + struct opts { + int weight; +@@ -68,6 +69,7 @@ struct opts { + int rtable; + int trusted; + char *refstr; ++ int port; + } opts; + void opts_default(void); + +@@ -86,18 +88,21 @@ typedef struct { + %token LISTEN ON CONSTRAINT CONSTRAINTS FROM QUERY TRUSTED + %token SERVER SERVERS SENSOR CORRECTION RTABLE REFID STRATUM WEIGHT + %token ERROR ++%token PORT + %token STRING + %token NUMBER + %type address url urllist + %type listen_opts listen_opts_l listen_opt + %type server_opts server_opts_l server_opt + %type sensor_opts sensor_opts_l sensor_opt ++%type constraint_opts constraint_opts_l constraint_opt + %type correction + %type rtable + %type refid + %type stratum + %type weight + %type trusted ++%type port + %% + + grammar : /* empty */ +@@ -125,6 +130,10 @@ main : LISTEN ON address listen_opts { + fatal("can't allocate memory for listening address"); + la->fd = -1; + la->rtable = $4.rtable; ++ ++ if ($4.port != 0) ++ la->port = $4.port; ++ + memcpy(&la->sa, &h->ss, + sizeof(struct sockaddr_storage)); + TAILQ_INSERT_TAIL(&conf->listen_addrs, la, +@@ -186,10 +195,22 @@ main : LISTEN ON address listen_opts { + p->trusted = $3.trusted; + conf->trusted_peers = conf->trusted_peers || + $3.trusted; ++ ++ if ($3.port == 0) { ++ if ((se = getservbyname("ntp", "udp")) == NULL) { ++ fatal("new server: can't find default system information for NTP protocol (getservbyname)"); ++ } else { ++ $3.port = ntohs(se->s_port); ++ } ++ } ++ p->port = $3.port; ++ $2->port = p->port; ++ + p->query_addr4 = query_addr4; + p->query_addr6 = query_addr6; + p->addr = h; + p->addr_head.a = h; ++ p->addr_head.port = intdup($2->port); + p->addr_head.pool = ++poolseqnum; + p->addr_head.name = strdup($2->name); + if (p->addr_head.name == NULL) +@@ -228,9 +249,21 @@ main : LISTEN ON address listen_opts { + p->trusted = $3.trusted; + conf->trusted_peers = conf->trusted_peers || + $3.trusted; ++ ++ if ($3.port == 0) { ++ if ((se = getservbyname("ntp", "udp")) == NULL) { ++ fatal("new server: can't find default system information for NTP protocol (getservbyname)"); ++ } else { ++ $3.port = ntohs(se->s_port); ++ } ++ } ++ p->port = $3.port; ++ $2->port = p->port; ++ + p->query_addr4 = query_addr4; + p->query_addr6 = query_addr6; + p->addr_head.a = p->addr; ++ p->addr_head.port = intdup($2->port); + p->addr_head.pool = 0; + p->addr_head.name = strdup($2->name); + if (p->addr_head.name == NULL) +@@ -241,7 +274,7 @@ main : LISTEN ON address listen_opts { + free($2->name); + free($2); + } +- | CONSTRAINTS FROM url { ++ | CONSTRAINTS FROM url constraint_opts { + struct constraint *p; + struct ntp_addr *h, *next; + +@@ -266,6 +299,17 @@ main : LISTEN ON address listen_opts { + p = new_constraint(); + p->addr = h; + p->addr_head.a = h; ++ ++ if ($4.port == 0) { ++ if ((se = getservbyname("https", "tcp")) == NULL) { ++ fatal("new constraint: can't find default system information for HTTPS protocol (getservbyname)"); ++ } else { ++ $4.port = ntohs(se->s_port); ++ } ++ } ++ p->port = $4.port; ++ p->addr_head.port = intdup($4.port); ++ + p->addr_head.pool = ++poolseqnum; + p->addr_head.name = strdup($3->name); + p->addr_head.path = strdup($3->path); +@@ -281,7 +325,7 @@ main : LISTEN ON address listen_opts { + free($3->name); + free($3); + } +- | CONSTRAINT FROM urllist { ++ | CONSTRAINT FROM urllist constraint_opts { + struct constraint *p; + struct ntp_addr *h, *next; + +@@ -304,6 +348,17 @@ main : LISTEN ON address listen_opts { + } + + p->addr_head.a = p->addr; ++ ++ if ($4.port == 0) { ++ if ((se = getservbyname("https", "tcp")) == NULL) { ++ fatal("new constraint: can't find default system information for HTTPS protocol (getservbyname)"); ++ } else { ++ $4.port = ntohs(se->s_port); ++ } ++ } ++ p->port = $4.port; ++ p->addr_head.port = intdup($4.port); ++ + p->addr_head.pool = 0; + p->addr_head.name = strdup($3->name); + p->addr_head.path = strdup($3->path); +@@ -410,6 +465,7 @@ listen_opts_l : listen_opts_l listen_opt + | listen_opt + ; + listen_opt : rtable ++ | port + ; + + server_opts : { opts_default(); } +@@ -422,6 +478,18 @@ server_opts_l : server_opts_l server_opt + ; + server_opt : weight + | trusted ++ | port ++ ; ++ ++constraint_opts : { opts_default(); } ++ constraint_opts_l ++ { $$ = opts; } ++ | { opts_default(); $$ = opts; } ++ ; ++constraint_opts_l : constraint_opts_l constraint_opt ++ | constraint_opt ++ ; ++constraint_opt : port + ; + + sensor_opts : { opts_default(); } +@@ -478,6 +546,17 @@ weight : WEIGHT NUMBER { + } + opts.weight = $2; + } ++ ; ++ ++port : PORT NUMBER { ++ if ($2 < 1 || $2 > 65535) { ++ yyerror("port must be between 1 and 65535"); ++ YYERROR; ++ } ++ opts.port = $2; ++ } ++ ; ++ + rtable : RTABLE NUMBER { + #ifdef RT_TABLEID_MAX + if ($2 < 0 || $2 > RT_TABLEID_MAX) { +@@ -502,6 +581,7 @@ opts_default(void) + memset(&opts, 0, sizeof opts); + opts.weight = 1; + opts.stratum = 1; ++ opts.port = 0; + } + + struct keywords { +@@ -542,6 +622,7 @@ lookup(char *s) + { "from", FROM}, + { "listen", LISTEN}, + { "on", ON}, ++ { "port", PORT}, + { "query", QUERY}, + { "refid", REFID}, + { "rtable", RTABLE}, +--- a/src/server.c 2020-08-01 00:04:05.000000000 +0300 ++++ b/src/server.c 2020-08-01 01:14:42.328058753 +0300 +@@ -107,14 +107,18 @@ setup_listeners(struct servent *se, stru + for (la = TAILQ_FIRST(&lconf->listen_addrs); la; ) { + switch (la->sa.ss_family) { + case AF_INET: +- if (((struct sockaddr_in *)&la->sa)->sin_port == 0) +- ((struct sockaddr_in *)&la->sa)->sin_port = +- se->s_port; ++ if ((la->port == 0) && \ ++ (((struct sockaddr_in *)&la->sa)->sin_port == 0)) ++ ((struct sockaddr_in *)&la->sa)->sin_port = se->s_port; ++ else ++ ((struct sockaddr_in *)&la->sa)->sin_port = ntohs(la->port); + break; + case AF_INET6: +- if (((struct sockaddr_in6 *)&la->sa)->sin6_port == 0) +- ((struct sockaddr_in6 *)&la->sa)->sin6_port = +- se->s_port; ++ if ((la->port == 0) && \ ++ (((struct sockaddr_in6 *)&la->sa)->sin6_port == 0)) ++ ((struct sockaddr_in6 *)&la->sa)->sin6_port = se->s_port; ++ else ++ ((struct sockaddr_in6 *)&la->sa)->sin6_port = ntohs(la->port); + break; + case AF_UNSPEC: + nla = TAILQ_NEXT(la, entry); +--- a/src/ntpd.conf.5 2020-07-31 23:00:51.000000000 +0300 ++++ b/src/ntpd.conf.5 2020-08-01 01:22:25.424725907 +0300 +@@ -14,7 +14,7 @@ + .\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + .\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + .\" +-.Dd $Mdocdate: May 16 2020 $ ++.Dd $Mdocdate: August 01 2020 $ + .Dt NTPD.CONF 5 + .Os + .Sh NAME +@@ -37,6 +37,7 @@ The basic configuration options are as f + .Bl -tag -width Ds + .It Xo Ic listen on Ar address + .Op Ic rtable Ar table-id ++.Op Ic port Ar port-number + .Xc + .Xr ntpd 8 + has the ability to sync the local clock to remote NTP servers and, if +@@ -62,6 +63,12 @@ keyword will specify which routing table + By default + .Xr ntpd 8 + will listen using the current routing table. ++The optional ++.Ic port ++keyword will specify which local UDP port the NTP server process should use for inbound connections. ++By default ++.Xr ntpd 8 ++will listen to UDP port 123 for new client connections. + For example: + .Bd -literal -offset indent + listen on * +@@ -72,6 +79,7 @@ or + listen on 127.0.0.1 + listen on ::1 + listen on 127.0.0.1 rtable 4 ++listen on 127.0.0.1 port 1230 + .Ed + .It Ic query from Ar sourceaddr + Specify a local IP address the +@@ -165,6 +173,7 @@ than a server with a weight of 1. + .It Xo Ic server Ar address + .Op Ic trusted + .Op Ic weight Ar weight-value ++.Op Ic port Ar port-number + .Xc + Specify the IP address or the hostname of an NTP + server to synchronize to. +@@ -182,6 +191,7 @@ For example: + .Bd -literal -offset indent + server 10.0.0.2 weight 5 + server ntp.example.org weight 1 ++server ntp.foo.org port 123 + .Ed + .Pp + To provide redundancy, it is good practice to configure multiple servers. +@@ -190,6 +200,7 @@ network latency. + .It Xo Ic servers Ar address + .Op Ic trusted + .Op Ic weight Ar weight-value ++.Op Ic port Ar port-number + .Xc + As with + .Cm server , +@@ -204,6 +215,7 @@ For example: + .Bd -literal -offset indent + servers pool.ntp.org + servers pool.ntp.org weight 5 ++servers pool.ntp.org weight 6 port 123 + .Ed + .El + .Sh CONSTRAINTS +@@ -227,8 +239,13 @@ without libtls causes + to log a warning message on startup. + .Bl -tag -width Ds + .It Ic constraint from Ar url [ip...] ++.Op Ic port Ar port-number + Specify the URL, IP address or the hostname of an HTTPS server to +-provide a constraint. ++provide a constraint. The optional ++.Ic port ++number is an HTTPS server port to connect to. By default ++.Xr ntpd 8 ++will connect to remote TCP port 443. + If the url is followed by one or more addresses the url and addresses will be + tried until a working one is found. + The url path and expected certificate name is always taken from the +@@ -242,8 +259,10 @@ will calculate a median constraint from + server ntp.example.org + constraint from www.example.com + constraint from "https://9.9.9.9" "2620:fe::9" ++constraint from www.google.com port 443 + .Ed + .It Ic constraints from Ar url ++.Op Ic port Ar port-number + As with + .Ic constraint from , + specify the URL, IP address or the hostname of an HTTPS server to +@@ -251,10 +270,16 @@ provide a constraint. + Should the hostname resolve to multiple IP addresses, + .Xr ntpd 8 + will calculate a median constraint from all of them. ++The optional ++.Ic port ++number is an HTTPS server port to connect to. By default ++.Xr ntpd 8 ++will connect to remote TCP port 443. + For example: + .Bd -literal -offset indent + servers pool.ntp.org + constraints from "https://www.google.com/" ++constraints from "https://duckduckgo.com/" port 443 + .Ed + .El + .Sh FILES diff --git a/patches/4-patch_peercount-init.patch b/patches/4-patch_peercount-init.patch new file mode 100644 index 0000000..7127bbe --- /dev/null +++ b/patches/4-patch_peercount-init.patch @@ -0,0 +1,24 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Fix C compiler warning about uninitialized variable peercount + + +--- a/src/ntp.c 2020-08-01 00:56:09.608057581 +0300 ++++ b/src/ntp.c 2020-08-01 15:22:42.981445052 +0300 +@@ -511,7 +511,7 @@ ntp_dispatch_imsg_dns(void) + u_int16_t dlen; + u_char *p; + struct ntp_addr *h; +- size_t addrcount, peercount; ++ size_t addrcount, peercount = 0; + int n; + + if (((n = imsg_read(ibuf_dns)) == -1 && errno != EAGAIN) || n == 0) +@@ -540,7 +540,6 @@ ntp_dispatch_imsg_dns(void) + + if (peer->addr_head.pool) { + n = 0; +- peercount = 0; + + TAILQ_FOREACH_SAFE(npeer, &conf->ntp_peers, + entry, tmp) { diff --git a/patches/5-patch_debugmode-fix.patch b/patches/5-patch_debugmode-fix.patch new file mode 100644 index 0000000..68bae15 --- /dev/null +++ b/patches/5-patch_debugmode-fix.patch @@ -0,0 +1,22 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Fix debug mode not showing output in command line + + +--- a/src/ntpd.c 2020-08-01 13:33:42.000000000 +0300 ++++ b/src/ntpd.c 2020-08-01 16:07:32.660248971 +0300 +@@ -195,12 +195,14 @@ main(int argc, char *argv[]) + switch (ch) { + case 'd': + lconf.debug = 1; ++ lconf.verbose = 2; + break; + case 'f': + conffile = optarg; + break; + case 'n': + lconf.debug = 1; ++ lconf.verbose = 2; + lconf.noaction = 1; + break; + case 'P': diff --git a/patches/6-patch_unhardcode-conf.patch b/patches/6-patch_unhardcode-conf.patch new file mode 100644 index 0000000..9586e52 --- /dev/null +++ b/patches/6-patch_unhardcode-conf.patch @@ -0,0 +1,1906 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Unhardcode majority of configuration settings, update manual + + +--- a/src/sensors.c 2020-07-31 23:58:46.000000000 +0300 ++++ b/src/sensors.c 2020-08-01 12:22:05.214766958 +0300 +@@ -145,7 +145,7 @@ sensor_add(int sensordev, char *dxname) + s->sensordevid = sensordev; + + if (cs->refstr == NULL) +- memcpy(&s->refid, SENSOR_DEFAULT_REFID, sizeof(s->refid)); ++ memcpy(&s->refid, conf->sensor_default_refid, sizeof(s->refid)); + else { + s->refid = 0; + strncpy((char *)&s->refid, cs->refstr, sizeof(s->refid)); +@@ -174,12 +174,12 @@ sensor_query(struct ntp_sensor *s) + double sens_time; + + if (conf->settime) +- s->next = getmonotime() + SENSOR_QUERY_INTERVAL_SETTIME; ++ s->next = getmonotime() + conf->sensor_query_interval_settime; + else +- s->next = getmonotime() + SENSOR_QUERY_INTERVAL; ++ s->next = getmonotime() + conf->sensor_query_interval; + + /* rcvd is walltime here, monotime in client.c. not used elsewhere */ +- if (s->update.rcvd < time(NULL) - SENSOR_DATA_MAXAGE) ++ if (s->update.rcvd < time(NULL) - conf->sensor_data_maxage) + s->update.good = 0; + + if (!sensor_probe(s->sensordevid, dxname, &sensor)) { +@@ -234,7 +234,7 @@ sensor_query(struct ntp_sensor *s) + log_debug("sensor %s: offset %f", s->device, + s->offsets[s->shift].offset); + +- if (++s->shift >= SENSOR_OFFSETS) { ++ if (++s->shift >= conf->sensor_offsets) { + s->shift = 0; + sensor_update(s); + } +@@ -247,19 +247,19 @@ sensor_update(struct ntp_sensor *s) + struct ntp_offset **offsets; + int i; + +- if ((offsets = calloc(SENSOR_OFFSETS, sizeof(struct ntp_offset *))) == ++ if ((offsets = calloc(conf->sensor_offsets, sizeof(struct ntp_offset *))) == + NULL) + fatal("sensor %s: can't allocate memory for data update", s->device); + +- for (i = 0; i < SENSOR_OFFSETS; i++) ++ for (i = 0; i < conf->sensor_offsets; i++) + offsets[i] = &s->offsets[i]; + +- qsort(offsets, SENSOR_OFFSETS, sizeof(struct ntp_offset *), ++ qsort(offsets, conf->sensor_offsets, sizeof(struct ntp_offset *), + offset_compare); + +- i = SENSOR_OFFSETS / 2; ++ i = conf->sensor_offsets / 2; + memcpy(&s->update, offsets[i], sizeof(s->update)); +- if (SENSOR_OFFSETS % 2 == 0) { ++ if (conf->sensor_offsets % 2 == 0) { + s->update.offset = + (offsets[i - 1]->offset + offsets[i]->offset) / 2; + } +--- a/src/ntpd.c 2020-08-01 16:07:32.660248971 +0300 ++++ b/src/ntpd.c 2020-08-01 17:13:23.406919806 +0300 +@@ -135,7 +135,7 @@ auto_preconditions(const struct ntpd_con + #endif + constraints = !TAILQ_EMPTY(&cnf->constraints); + return !cnf->settime && (constraints || cnf->trusted_peers || +- conf->trusted_sensors) && securelevel == 0; ++ cnf->trusted_sensors) && securelevel == 0; + } + + #define POLL_MAX 8 +@@ -195,14 +195,14 @@ main(int argc, char *argv[]) + switch (ch) { + case 'd': + lconf.debug = 1; +- lconf.verbose = 2; ++ lconf.verbose = 2; + break; + case 'f': + conffile = optarg; + break; + case 'n': + lconf.debug = 1; +- lconf.verbose = 2; ++ lconf.verbose = 2; + lconf.noaction = 1; + break; + case 'P': +@@ -253,8 +253,8 @@ main(int argc, char *argv[]) + if (geteuid()) + errx(1, "main process: need root privileges"); + +- if ((pw = getpwnam(NTPD_USER)) == NULL) +- errx(1, "main process: unknown user %s", NTPD_USER); ++ if ((pw = getpwnam(conf->ntpd_user)) == NULL) ++ errx(1, "main process: unknown user %s", conf->ntpd_user); + + lconf.automatic = auto_preconditions(&lconf); + if (lconf.automatic) +@@ -277,7 +277,7 @@ main(int argc, char *argv[]) + + fatalx("main process: process '%s' failed (%s)", pname, __func__); + } else { +- if ((control_check(CTLSOCKET)) == -1) ++ if ((control_check(conf->ctlsocket)) == -1) + fatalx("OpenNTPD is already running"); + } + +@@ -295,7 +295,7 @@ main(int argc, char *argv[]) + } + } else { + settime_deadline = getmonotime(); +- timeout = 100; ++ timeout = conf->settime_timeout; + } + + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, +@@ -311,6 +311,10 @@ main(int argc, char *argv[]) + start_child(NTP_PROC_NAME, pipe_chld[1], argc0, argv0); + + log_procinit("[priv]"); ++ ++ if (lconf.debug) ++ print_conf(&lconf); ++ + readfreq(); + + signal(SIGTERM, sighdlr); +@@ -370,7 +374,7 @@ main(int argc, char *argv[]) + } + + if (nfds == 0 && lconf.settime && +- getmonotime() > settime_deadline + SETTIME_TIMEOUT) { ++ getmonotime() > settime_deadline + conf->settime_timeout) { + lconf.settime = 0; + timeout = INFTIM; + log_init(logdest, lconf.verbose, LOG_DAEMON); +@@ -520,7 +524,7 @@ ntpd_adjtime(double d) + { + int synced = 0; + static int firstadj = 1; +- double threshold = (double)LOG_NEGLIGIBLE_ADJTIME / 1000; ++ double threshold = (double)conf->log_negligible_adjtime / 1000; + + d += getoffset(); + if (d >= threshold || d <= -1 * threshold) +@@ -581,8 +585,8 @@ ntpd_adjfreq(double relfreq, int wrlog) + r = writefreq(curfreq / 1e9 / (1LL << 32)); + ppmfreq = relfreq * 1e6; + if (wrlog) { +- if (ppmfreq >= LOG_NEGLIGIBLE_ADJFREQ || +- ppmfreq <= -LOG_NEGLIGIBLE_ADJFREQ) ++ if (ppmfreq >= conf->log_negligible_adjfreq || ++ ppmfreq <= -(conf->log_negligible_adjfreq)) + log_info("main process: adjusting clock frequency by %f to %f ppm%s", + ppmfreq, curfreq / 1e3 / (1LL << 32), + r ? "" : " (no drift file)"); +@@ -634,13 +638,13 @@ readfreq(void) + int fd; + double d; + +- fd = open(DRIFTFILE, O_RDWR); ++ fd = open(conf->driftfile, O_RDWR); + if (fd == -1) { +- log_warnx("main process: creating new drift file %s", DRIFTFILE); ++ log_warnx("main process: creating new drift file %s", conf->driftfile); + current = 0; + if (adjfreq(¤t, NULL) == -1) + log_warn("main process: frequency reset failed"); +- freqfp = fopen(DRIFTFILE, "w"); ++ freqfp = fopen(conf->driftfile, "w"); + return; + } + +@@ -654,7 +658,7 @@ readfreq(void) + d /= 1e6; /* scale from ppm */ + ntpd_adjfreq(d, 0); + } else +- log_warnx("main process: drift file %s is empty", DRIFTFILE); ++ log_warnx("main process: drift file %s is empty", conf->driftfile); + } + } + +@@ -671,7 +675,7 @@ writefreq(double d) + r = fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */ + if (r < 0 || fflush(freqfp) != 0) { + if (warnonce) { +- log_warnx("main process: can't write drift file %s", DRIFTFILE); ++ log_warnx("main process: can't write drift file %s", conf->driftfile); + warnonce = 0; + } + clearerr(freqfp); +@@ -679,7 +683,7 @@ writefreq(double d) + } + off = ftello(freqfp); + if (off == -1 || ftruncate(fileno(freqfp), off) == -1) +- log_warnx("main process: can't truncate drift file %s", DRIFTFILE); ++ log_warnx("main process: can't truncate drift file %s", conf->driftfile); + fsync(fileno(freqfp)); + return 1; + } +@@ -693,7 +697,7 @@ ctl_main(int argc, char *argv[]) + int fd, n, done, ch, action; + char *sockname; + +- sockname = CTLSOCKET; ++ sockname = conf->ctlsocket; + + if (argc < 2) { + usage(); +@@ -932,7 +936,7 @@ show_peer_msg(struct imsg *imsg, int cal + + cpeer = (struct ctl_show_peer *)imsg->data; + +- if (strlen(cpeer->peer_desc) > MAX_DISPLAY_WIDTH - 1) ++ if (strlen(cpeer->peer_desc) > conf->max_display_width - 1) + fatalx("ntpctl: NTP peer description is too long"); + + if (firsttime) { +@@ -953,7 +957,7 @@ show_peer_msg(struct imsg *imsg, int cal + cpeer->weight, cpeer->trustlevel, stratum, + (long long)cpeer->next, (long long)cpeer->poll); + +- if (cpeer->trustlevel >= TRUSTLEVEL_BADPEER) ++ if (cpeer->trustlevel >= conf->trustlevel_badpeer) + printf(" %12.3fms %9.3fms %8.3fms\n", cpeer->offset, + cpeer->delay, cpeer->jitter); + else +@@ -982,7 +986,7 @@ show_sensor_msg(struct imsg *imsg, int c + + csensor = (struct ctl_show_sensor *)imsg->data; + +- if (strlen(csensor->sensor_desc) > MAX_DISPLAY_WIDTH - 1) ++ if (strlen(csensor->sensor_desc) > conf->max_display_width - 1) + fatalx("ntpctl: sensor description is too long"); + + if (firsttime) { +--- a/src/ntp.c 2020-08-01 15:22:42.000000000 +0300 ++++ b/src/ntp.c 2020-08-01 18:38:24.803591850 +0300 +@@ -55,7 +55,7 @@ int ntp_dispatch_imsg_dns(void); + void peer_add(struct ntp_peer *); + void peer_remove(struct ntp_peer *); + int inpool(struct sockaddr_storage *, +- struct sockaddr_storage[MAX_SERVERS_DNS], size_t); ++ struct sockaddr_storage[conf->max_servers_dns], size_t); + + void + ntp_sighdlr(int sig) +@@ -258,12 +258,12 @@ ntp_main(struct ntpd_conf *nconf, struct + sent_cnt++; + } + if (p->deadline > 0 && p->deadline <= getmonotime()) { +- timeout = 300; ++ timeout = conf->interval_query_timeout; + log_debug("NTP client: NTP peer %s - no reply received in time, " + "next query in %ds", log_sockaddr( + (struct sockaddr *)&p->addr->ss), timeout); +- if (p->trustlevel >= TRUSTLEVEL_BADPEER && +- (p->trustlevel /= 2) < TRUSTLEVEL_BADPEER) ++ if (p->trustlevel >= conf->trustlevel_badpeer && ++ (p->trustlevel /= 2) < conf->trustlevel_badpeer) + log_info("NTP client: NTP peer %s is invalid now", + log_sockaddr( + (struct sockaddr *)&p->addr->ss)); +@@ -273,17 +273,17 @@ ntp_main(struct ntpd_conf *nconf, struct + } + set_next(p, timeout); + } +- if (p->senderrors > MAX_SEND_ERRORS) { ++ if (p->senderrors > conf->max_send_errors) { + log_debug("NTP client: NTP peer %s - failed to send query, " + "next query in %ds", log_sockaddr( + (struct sockaddr *)&p->addr->ss), +- INTERVAL_QUERY_PATHETIC); ++ conf->interval_query_pathetic); + p->senderrors = 0; + if (client_nextaddr(p) == 1) { + peer_addr_head_clear(p); + client_nextaddr(p); + } +- set_next(p, INTERVAL_QUERY_PATHETIC); ++ set_next(p, conf->interval_query_pathetic); + } + if (p->next > 0 && p->next < nextaction) + nextaction = p->next; +@@ -304,13 +304,13 @@ ntp_main(struct ntpd_conf *nconf, struct + (conf->trusted_sensors || constraint_cnt == 0 || + conf->constraint_median != 0)) { + if (last_sensor_scan == 0 || +- last_sensor_scan + SENSOR_SCAN_INTERVAL <= getmonotime()) { ++ last_sensor_scan + conf->sensor_scan_interval <= getmonotime()) { + sensors_cnt = sensor_scan(); + last_sensor_scan = getmonotime(); + } + if (sensors_cnt == 0 && +- nextaction > last_sensor_scan + SENSOR_SCAN_INTERVAL) +- nextaction = last_sensor_scan + SENSOR_SCAN_INTERVAL; ++ nextaction > last_sensor_scan + conf->sensor_scan_interval) ++ nextaction = last_sensor_scan + conf->sensor_scan_interval; + sensors_cnt = 0; + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { + if (conf->settime && s->offsets[0].offset) +@@ -482,7 +482,7 @@ ntp_dispatch_imsg(void) + + int + inpool(struct sockaddr_storage *a, +- struct sockaddr_storage old[MAX_SERVERS_DNS], size_t n) ++ struct sockaddr_storage old[conf->max_servers_dns], size_t n) + { + size_t i; + +@@ -506,7 +506,7 @@ int + ntp_dispatch_imsg_dns(void) + { + struct imsg imsg; +- struct sockaddr_storage existing[MAX_SERVERS_DNS]; ++ struct sockaddr_storage existing[conf->max_servers_dns]; + struct ntp_peer *peer, *npeer, *tmp; + u_int16_t dlen; + u_char *p; +@@ -558,7 +558,7 @@ ntp_dispatch_imsg_dns(void) + if (dlen == 0) { /* no data -> temp error */ + log_warnx("DNS lookup temporary failed"); + peer->state = STATE_DNS_TEMPFAIL; +- if (conf->tmpfail++ == TRIES_AUTO_DNSFAIL) ++ if (conf->tmpfail++ == conf->tries_auto_dnsfail) + priv_settime(0, "of DNS failures"); + break; + } +@@ -690,7 +690,7 @@ priv_adjfreq(double offset) + conf->freq.y += offset; + conf->freq.xx += curtime * curtime; + +- if (conf->freq.samples % FREQUENCY_SAMPLES != 0) ++ if (conf->freq.samples % conf->frequency_samples != 0) + return; + + freq = +@@ -698,10 +698,10 @@ priv_adjfreq(double offset) + / + (conf->freq.xx - conf->freq.x * conf->freq.x / conf->freq.samples); + +- if (freq > MAX_FREQUENCY_ADJUST) +- freq = MAX_FREQUENCY_ADJUST; +- else if (freq < -MAX_FREQUENCY_ADJUST) +- freq = -MAX_FREQUENCY_ADJUST; ++ if (freq > conf->max_frequency_adjust) ++ freq = conf->max_frequency_adjust; ++ else if (freq < -(conf->max_frequency_adjust)) ++ freq = -(conf->max_frequency_adjust); + + imsg_compose(ibuf_main, IMSG_ADJFREQ, 0, 0, -1, &freq, sizeof(freq)); + conf->filters |= FILTER_ADJFREQ; +@@ -724,7 +724,7 @@ priv_adjtime(void) + double offset_median; + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { +- if (p->trustlevel < TRUSTLEVEL_BADPEER) ++ if (p->trustlevel < conf->trustlevel_badpeer) + continue; + if (!p->update.good) + return (1); +@@ -744,7 +744,7 @@ priv_adjtime(void) + fatal("main process: can't allocate memory for time adjustment"); + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { +- if (p->trustlevel < TRUSTLEVEL_BADPEER) ++ if (p->trustlevel < conf->trustlevel_badpeer) + continue; + for (j = 0; j < p->weight; j++) + offsets[i++] = &p->update; +@@ -784,12 +784,12 @@ priv_adjtime(void) + free(offsets); + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { +- for (i = 0; i < OFFSET_ARRAY_SIZE; i++) ++ for (i = 0; i < conf->offset_array_size; i++) + p->reply[i].offset -= offset_median; + p->update.good = 0; + } + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { +- for (i = 0; i < SENSOR_OFFSETS; i++) ++ for (i = 0; i < conf->sensor_offsets; i++) + s->offsets[i].offset -= offset_median; + s->update.offset -= offset_median; + } +@@ -841,13 +841,13 @@ update_scale(double offset) + if (offset < 0) + offset = -offset; + +- if (offset > QSCALE_OFF_MAX || !conf->status.synced || ++ if (offset > conf->qscale_off_max || !conf->status.synced || + conf->freq.num < 3) + conf->scale = 1; +- else if (offset < QSCALE_OFF_MIN) +- conf->scale = QSCALE_OFF_MAX / QSCALE_OFF_MIN; ++ else if (offset < conf->qscale_off_min) ++ conf->scale = conf->qscale_off_max / conf->qscale_off_min; + else +- conf->scale = QSCALE_OFF_MAX / offset; ++ conf->scale = conf->qscale_off_max / offset; + } + + time_t +@@ -865,7 +865,7 @@ error_interval(void) + { + time_t interval, r; + +- interval = INTERVAL_QUERY_PATHETIC * QSCALE_OFF_MAX / QSCALE_OFF_MIN; ++ interval = conf->interval_query_pathetic * conf->qscale_off_max / conf->qscale_off_min; + r = arc4random_uniform(interval / 10); + return (interval + r); + } +--- a/src/control.c 2020-07-31 23:23:56.000000000 +0300 ++++ b/src/control.c 2020-08-01 11:49:36.991431574 +0300 +@@ -317,7 +317,7 @@ build_show_status(struct ctl_show_status + + TAILQ_FOREACH(p, &conf->ntp_peers, entry) { + cs->peercnt++; +- if (p->trustlevel >= TRUSTLEVEL_BADPEER) ++ if (p->trustlevel >= conf->trustlevel_badpeer) + cs->valid_peers++; + } + TAILQ_FOREACH(s, &conf->ntp_sensors, entry) { +@@ -362,7 +362,7 @@ build_show_peer(struct ctl_show_peer *cp + + validdelaycnt = best = 0; + cp->offset = cp->delay = 0.0; +- for (shift = 0; shift < OFFSET_ARRAY_SIZE; shift++) { ++ for (shift = 0; shift < conf->offset_array_size; shift++) { + if (p->reply[shift].delay > 0.0) { + cp->offset += p->reply[shift].offset; + cp->delay += p->reply[shift].delay; +@@ -381,7 +381,7 @@ build_show_peer(struct ctl_show_peer *cp + + jittercnt = 0; + cp->jitter = 0.0; +- for (shift = 0; shift < OFFSET_ARRAY_SIZE; shift++) { ++ for (shift = 0; shift < conf->offset_array_size; shift++) { + if (p->reply[shift].delay > 0.0 && shift != best) { + cp->jitter += square(p->reply[shift].delay - + p->reply[best].delay); +@@ -393,7 +393,7 @@ build_show_peer(struct ctl_show_peer *cp + cp->jitter = sqrt(cp->jitter); + + if (p->shift == 0) +- shift = OFFSET_ARRAY_SIZE - 1; ++ shift = conf->offset_array_size - 1; + else + shift = p->shift - 1; + +@@ -424,14 +424,14 @@ build_show_sensor(struct ctl_show_sensor + + now = getmonotime(); + +- memcpy(&refid, SENSOR_DEFAULT_REFID, sizeof(refid)); ++ memcpy(&refid, conf->sensor_default_refid, sizeof(refid)); + refid = refid == s->refid ? 0 : s->refid; + + snprintf(cs->sensor_desc, sizeof(cs->sensor_desc), + "%s %.4s", s->device, (char *)&refid); + + if (s->shift == 0) +- shift = SENSOR_OFFSETS - 1; ++ shift = conf->sensor_offsets - 1; + else + shift = s->shift - 1; + +@@ -445,7 +445,7 @@ build_show_sensor(struct ctl_show_sensor + cs->good = s->update.good; + cs->stratum = s->offsets[shift].status.stratum; + cs->next = s->next - now < 0 ? 0 : s->next - now; +- cs->poll = SENSOR_QUERY_INTERVAL; ++ cs->poll = conf->sensor_query_interval; + cs->offset = s->offsets[shift].offset * 1000.0; + cs->correction = (double)s->correction / 1000.0; + } +--- a/src/constraint.c 2020-08-02 01:57:36.430286127 +0300 ++++ b/src/constraint.c 2020-08-02 01:57:57.020286149 +0300 +@@ -165,8 +165,8 @@ constraint_query(struct constraint *cstr + /* Proceed and query the time */ + break; + case STATE_DNS_TEMPFAIL: +- if (now > cstr->last + (cstr->dnstries >= TRIES_AUTO_DNSFAIL ? +- CONSTRAINT_RETRY_INTERVAL : INTERVAL_AUIO_DNSFAIL)) { ++ if (now > cstr->last + (cstr->dnstries >= conf->tries_auto_dnsfail ? ++ conf->constraint_retry_interval : conf->interval_auto_dnsfail)) { + cstr->dnstries++; + /* Retry resolving the address */ + constraint_init(cstr); +@@ -174,7 +174,7 @@ constraint_query(struct constraint *cstr + } + return (-1); + case STATE_QUERY_SENT: +- if (cstr->last + CONSTRAINT_SCAN_TIMEOUT > now) { ++ if (cstr->last + conf->constraint_scan_timeout > now) { + /* The caller should expect a reply */ + return (0); + } +@@ -186,7 +186,7 @@ constraint_query(struct constraint *cstr + cstr->state = STATE_TIMEOUT; + return (-1); + case STATE_INVALID: +- if (cstr->last + CONSTRAINT_SCAN_INTERVAL > now) { ++ if (cstr->last + conf->constraint_scan_interval > now) { + /* Nothing to do */ + return (-1); + } +@@ -745,7 +745,7 @@ constraint_msg_close(u_int32_t id, u_int + log_debug("constraint %s: no reply" + " received in time, next query in %ds", + log_sockaddr((struct sockaddr *) +- &cstr->addr->ss), CONSTRAINT_SCAN_INTERVAL); ++ &cstr->addr->ss), conf->constraint_scan_interval); + + cnt = 0; + TAILQ_FOREACH(tmp, &conf->constraints, entry) +@@ -920,9 +920,9 @@ constraint_check(double val) + tv.tv_usec = 0; + diff = fabs(val - gettime_from_timeval(&tv)); + +- if (diff > CONSTRAINT_MARGIN) { ++ if (diff > conf->constraint_margin) { + if (conf->constraint_errors++ > +- (CONSTRAINT_ERROR_MARGIN * peer_cnt)) { ++ (conf->constraint_error_margin * peer_cnt)) { + constraint_reset(); + } + +@@ -999,7 +999,7 @@ int + httpsdate_request(struct httpsdate *httpsdate, struct timeval *when) + { + char timebuf1[32], timebuf2[32]; +- size_t outlen = 0, maxlength = CONSTRAINT_MAXHEADERLENGTH, len; ++ size_t outlen = 0, maxlength = conf->constraint_maxheaderlength, len; + char *line, *p, *buf; + time_t httptime, notbefore, notafter; + struct tm *tm; +--- a/src/config.c 2020-08-01 01:02:14.000000000 +0300 ++++ b/src/config.c 2020-08-01 11:35:05.758097319 +0300 +@@ -115,7 +115,7 @@ host_dns1(const char *s, struct ntp_addr + return (-1); + } + +- for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) { ++ for (res = res0; res && cnt < conf->max_servers_dns; res = res->ai_next) { + if (res->ai_family != AF_INET && + res->ai_family != AF_INET6) + continue; +--- a/src/client.c 2020-08-02 02:04:55.666953258 +0300 ++++ b/src/client.c 2020-08-02 02:05:18.690286616 +0300 +@@ -57,7 +57,7 @@ client_peer_init(struct ntp_peer *p) + p->query->msg.status = MODE_CLIENT | (NTP_VERSION << 3); + p->state = STATE_NONE; + p->shift = 0; +- p->trustlevel = TRUSTLEVEL_PATHETIC; ++ p->trustlevel = conf->trustlevel_pathetic; + p->lasterror = 0; + p->senderrors = 0; + +@@ -120,7 +120,7 @@ client_nextaddr(struct ntp_peer *p) + } + + p->shift = 0; +- p->trustlevel = TRUSTLEVEL_PATHETIC; ++ p->trustlevel = conf->trustlevel_pathetic; + + if (p->addr == NULL) { + p->addr = p->addr_head.a; +@@ -148,10 +148,10 @@ client_query(struct ntp_peer *p) + + if (p->addr == NULL && client_nextaddr(p) == -1) { + if (conf->settime) +- set_next(p, INTERVAL_AUIO_DNSFAIL); ++ set_next(p, conf->interval_auto_dnsfail); + else +- set_next(p, MAXIMUM(SETTIME_TIMEOUT, +- scale_interval(INTERVAL_QUERY_AGGRESSIVE))); ++ set_next(p, MAXIMUM(conf->settime_timeout, ++ scale_interval(conf->interval_query_aggressive))); + return (0); + } + +@@ -200,8 +200,8 @@ client_query(struct ntp_peer *p) + client_nextaddr(p); + if (p->addr == NULL) + p->addr = p->addr_head.a; +- set_next(p, MAXIMUM(SETTIME_TIMEOUT, +- scale_interval(INTERVAL_QUERY_AGGRESSIVE))); ++ set_next(p, MAXIMUM(conf->settime_timeout, ++ scale_interval(conf->interval_query_aggressive))); + p->senderrors++; + return (-1); + } else +@@ -239,14 +239,14 @@ client_query(struct ntp_peer *p) + + if (ntp_sendmsg(p->query->fd, NULL, &p->query->msg) == -1) { + p->senderrors++; +- set_next(p, INTERVAL_QUERY_PATHETIC); +- p->trustlevel = TRUSTLEVEL_PATHETIC; ++ set_next(p, conf->interval_query_pathetic); ++ p->trustlevel = conf->trustlevel_pathetic; + return (-1); + } + + p->senderrors = 0; + p->state = STATE_QUERY_SENT; +- set_deadline(p, QUERYTIME_MAX); ++ set_deadline(p, conf->querytime_max); + + return (0); + } +@@ -263,7 +263,7 @@ void + handle_auto(uint8_t trusted, double offset) + { + static int count; +- static double v[AUTO_REPLIES]; ++ double v[conf->auto_replies]; + + /* + * It happens the (constraint) resolves initially fail, don't give up +@@ -272,7 +272,7 @@ handle_auto(uint8_t trusted, double offs + if (!trusted && conf->constraint_median == 0) + return; + +- if (offset < AUTO_THRESHOLD) { ++ if (offset < conf->auto_threshold) { + /* don't bother */ + priv_settime(0, "NTP client: NTP peer offset is negative or close enough"); + return; +@@ -281,13 +281,13 @@ handle_auto(uint8_t trusted, double offs + v[count++] = offset; + if (count < AUTO_REPLIES) + return; +- ++ + /* we have enough */ + qsort(v, count, sizeof(double), auto_cmp); +- if (AUTO_REPLIES % 2 == 0) +- offset = (v[AUTO_REPLIES / 2 - 1] + v[AUTO_REPLIES / 2]) / 2; ++ if (conf->auto_replies % 2 == 0) ++ offset = (v[conf->auto_replies / 2 - 1] + v[conf->auto_replies / 2]) / 2; + else +- offset = v[AUTO_REPLIES / 2]; ++ offset = v[conf->auto_replies / 2]; + priv_settime(offset, ""); + } + +@@ -451,22 +451,22 @@ client_dispatch(struct ntp_peer *p, u_in + } else + p->reply[p->shift].status.send_refid = msg.xmttime.fractionl; + +- if (p->trustlevel < TRUSTLEVEL_PATHETIC) +- interval = scale_interval(INTERVAL_QUERY_PATHETIC); +- else if (p->trustlevel < TRUSTLEVEL_AGGRESSIVE) ++ if (p->trustlevel < conf->trustlevel_pathetic) ++ interval = scale_interval(conf->interval_query_pathetic); ++ else if (p->trustlevel < conf->trustlevel_aggressive) + interval = (conf->settime && conf->automatic) ? +- INTERVAL_QUERY_ULTRA_VIOLENCE : +- scale_interval(INTERVAL_QUERY_AGGRESSIVE); ++ conf->interval_query_ultra_violence : ++ scale_interval(conf->interval_query_aggressive); + else +- interval = scale_interval(INTERVAL_QUERY_NORMAL); ++ interval = scale_interval(conf->interval_query_normal); + + set_next(p, interval); + p->state = STATE_REPLY_RECEIVED; + + /* every received reply which we do not discard increases trust */ +- if (p->trustlevel < TRUSTLEVEL_MAX) { +- if (p->trustlevel < TRUSTLEVEL_BADPEER && +- p->trustlevel + 1 >= TRUSTLEVEL_BADPEER) ++ if (p->trustlevel < conf->trustlevel_max) { ++ if (p->trustlevel < conf->trustlevel_badpeer && ++ p->trustlevel + 1 >= conf->trustlevel_badpeer) + log_info("NTP client: NTP peer %s is valid now", + log_sockaddr((struct sockaddr *)&p->addr->ss)); + p->trustlevel++; +@@ -486,7 +486,7 @@ client_dispatch(struct ntp_peer *p, u_in + priv_settime(p->reply[p->shift].offset, ""); + } + +- if (++p->shift >= OFFSET_ARRAY_SIZE) ++ if (++p->shift >= conf->offset_array_size) + p->shift = 0; + + return (0); +@@ -504,13 +504,13 @@ client_update(struct ntp_peer *p) + * invalidate it and all older ones + */ + +- for (i = 0; good == 0 && i < OFFSET_ARRAY_SIZE; i++) ++ for (i = 0; good == 0 && i < conf->offset_array_size; i++) + if (p->reply[i].good) { + good++; + best = i; + } + +- for (; i < OFFSET_ARRAY_SIZE; i++) ++ for (; i < conf->offset_array_size; i++) + if (p->reply[i].good) { + good++; + if (p->reply[i].delay < p->reply[best].delay) +@@ -522,7 +522,7 @@ client_update(struct ntp_peer *p) + + memcpy(&p->update, &p->reply[best], sizeof(p->update)); + if (priv_adjtime() == 0) { +- for (i = 0; i < OFFSET_ARRAY_SIZE; i++) ++ for (i = 0; i < conf->offset_array_size; i++) + if (p->reply[i].rcvd <= p->reply[best].rcvd) + p->reply[i].good = 0; + } +--- a/src/ntpd.h 2020-08-01 01:27:06.000000000 +0300 ++++ b/src/ntpd.h 2020-08-01 17:13:17.616919800 +0300 +@@ -56,6 +56,8 @@ + #define INTERVAL_QUERY_AGGRESSIVE 5 + #define INTERVAL_QUERY_ULTRA_VIOLENCE 1 /* used at startup for auto */ + ++#define INTERVAL_QUERY_TIMEOUT 300 ++ + #define TRUSTLEVEL_BADPEER 6 + #define TRUSTLEVEL_PATHETIC 2 + #define TRUSTLEVEL_AGGRESSIVE 8 +@@ -69,7 +71,7 @@ + #define QUERYTIME_MAX 15 /* single query might take n secs max */ + #define OFFSET_ARRAY_SIZE 8 + #define SENSOR_OFFSETS 6 +-#define SETTIME_TIMEOUT 15 /* max seconds to wait with -s */ ++#define SETTIME_TIMEOUT 100 /* max seconds to wait when settime == 1 */ + #define LOG_NEGLIGIBLE_ADJTIME 32 /* negligible drift to not log (ms) */ + #define LOG_NEGLIGIBLE_ADJFREQ 0.05 /* negligible rate to not log (ppm) */ + #define FREQUENCY_SAMPLES 8 /* samples for est. of permanent drift */ +@@ -80,7 +82,7 @@ + #define FILTER_ADJFREQ 0x01 /* set after doing adjfreq */ + #define AUTO_REPLIES 4 /* # of ntp replies we want for auto */ + #define AUTO_THRESHOLD 60 /* dont bother auto setting < this */ +-#define INTERVAL_AUIO_DNSFAIL 1 /* DNS tmpfail interval for auto */ ++#define INTERVAL_AUTO_DNSFAIL 1 /* DNS tmpfail interval for auto */ + #define TRIES_AUTO_DNSFAIL 4 /* DNS tmpfail quick retries */ + + +@@ -268,6 +270,63 @@ struct ntpd_conf { + size_t ca_len; + int tmpfail; + char *pid_file; ++ ++ char *ntpd_user; ++ char *driftfile; ++ char *ctlsocket; ++ ++ int interval_query_normal; ++ int interval_query_pathetic; ++ int interval_query_aggressive; ++ int interval_query_ultra_violence; ++ ++ int interval_query_timeout; ++ ++ int trustlevel_badpeer; ++ int trustlevel_pathetic; ++ int trustlevel_aggressive; ++ int trustlevel_max; ++ ++ int max_servers_dns; ++ ++ double qscale_off_min; ++ double qscale_off_max; ++ ++ int querytime_max; ++ int offset_array_size; ++ int sensor_offsets; ++ int settime_timeout; ++ ++ int log_negligible_adjtime; ++ double log_negligible_adjfreq; ++ ++ int frequency_samples; ++ double max_frequency_adjust; ++ ++ int max_send_errors; ++ ++ int max_display_width; ++ ++ u_int8_t filter_adjfreq; ++ ++ int auto_replies; ++ int auto_threshold; ++ int interval_auto_dnsfail; ++ int tries_auto_dnsfail; ++ ++ int sensor_query_interval_settime; ++ int sensor_data_maxage; ++ int sensor_query_interval; ++ int sensor_scan_interval; ++ char *sensor_default_refid; ++ ++ double constraint_error_margin; ++ int constraint_retry_interval; ++ int constraint_scan_interval; ++ int constraint_scan_timeout; ++ double constraint_margin; ++ ++ int constraint_maxheaderlength; + }; + + struct ctl_show_status { +@@ -363,6 +422,7 @@ extern struct ctl_conns ctl_conns; + + /* parse.y */ + int parse_config(const char *, struct ntpd_conf *); ++void print_conf(struct ntpd_conf *); + + /* config.c */ + void host(const char *, struct ntp_addr **); +--- a/src/parse.y 2020-08-01 01:51:28.000000000 +0300 ++++ b/src/parse.y 2020-08-01 21:17:48.293601924 +0300 +@@ -52,7 +52,6 @@ int yyerror(const char *, ...) + __attribute__((__format__ (printf, 1, 2))) + __attribute__((__nonnull__ (1))); + int kw_cmp(const void *, const void *); +-int lookup(char *); + int lgetc(int); + int lungetc(int); + int findeol(void); +@@ -70,12 +69,15 @@ struct opts { + int trusted; + char *refstr; + int port; ++ int pos_num; ++ double pos_decimal; + } opts; + void opts_default(void); + + typedef struct { + union { + int64_t number; ++ double decimal; + char *string; + struct ntp_addr_wrap *addr; + struct opts opts; +@@ -89,8 +91,68 @@ typedef struct { + %token SERVER SERVERS SENSOR CORRECTION RTABLE REFID STRATUM WEIGHT + %token ERROR + %token PORT ++ ++%token _NTPD_USER ++%token _DRIFTFILE ++%token _CTLSOCKET ++ ++%token _INTERVAL_QUERY_NORMAL ++%token _INTERVAL_QUERY_PATHETIC ++%token _INTERVAL_QUERY_AGGRESSIVE ++%token _INTERVAL_QUERY_ULTRA_VIOLENCE ++ ++%token _INTERVAL_QUERY_TIMEOUT ++ ++%token _TRUSTLEVEL_BADPEER ++%token _TRUSTLEVEL_PATHETIC ++%token _TRUSTLEVEL_AGGRESSIVE ++%token _TRUSTLEVEL_MAX ++ ++%token _MAX_SERVERS_DNS ++ ++%token _QSCALE_OFF_MIN ++%token _QSCALE_OFF_MAX ++ ++%token _QUERYTIME_MAX ++%token _OFFSET_ARRAY_SIZE ++%token _SENSOR_OFFSETS ++%token _SETTIME_TIMEOUT ++ ++%token _LOG_NEGLIGIBLE_ADJTIME ++%token _LOG_NEGLIGIBLE_ADJFREQ ++ ++%token _FREQUENCY_SAMPLES ++%token _MAX_FREQUENCY_ADJUST ++ ++%token _MAX_SEND_ERRORS ++ ++%token _MAX_DISPLAY_WIDTH ++ ++%token _FILTER_ADJFREQ ++ ++%token _AUTO_REPLIES ++%token _AUTO_THRESHOLD ++ ++%token _INTERVAL_AUTO_DNSFAIL ++%token _TRIES_AUTO_DNSFAIL ++ ++%token _SENSOR_DATA_MAXAGE ++%token _SENSOR_QUERY_INTERVAL ++%token _SENSOR_SCAN_INTERVAL ++ ++%token _SENSOR_DEFAULT_REFID ++ ++%token _CONSTRAINT_ERROR_MARGIN ++%token _CONSTRAINT_RETRY_INTERVAL ++%token _CONSTRAINT_SCAN_INTERVAL ++%token _CONSTRAINT_SCAN_TIMEOUT ++%token _CONSTRAINT_MARGIN ++ ++%token _CONSTRAINT_MAXHEADERLENGTH ++ + %token STRING + %token NUMBER ++%token NUMBER_DOUBLE + %type address url urllist + %type listen_opts listen_opts_l listen_opt + %type server_opts server_opts_l server_opt +@@ -103,6 +165,9 @@ typedef struct { + %type weight + %type trusted + %type port ++ ++%type pos_num ++%type pos_decimal + %% + + grammar : /* empty */ +@@ -385,6 +450,171 @@ main : LISTEN ON address listen_opts { + free($2); + TAILQ_INSERT_TAIL(&conf->ntp_conf_sensors, s, entry); + } ++ ++ | _NTPD_USER STRING { ++ conf->ntpd_user = $2; ++ } ++ | _DRIFTFILE STRING { ++ conf->driftfile = $2; ++ } ++ | _CTLSOCKET STRING { ++ conf->ctlsocket = $2; ++ } ++ ++ | _INTERVAL_QUERY_NORMAL pos_num { ++ conf->interval_query_normal = $2.pos_num; ++ } ++ | _INTERVAL_QUERY_PATHETIC pos_num { ++ conf->interval_query_pathetic = $2.pos_num; ++ } ++ | _INTERVAL_QUERY_AGGRESSIVE pos_num { ++ conf->interval_query_aggressive = $2.pos_num; ++ } ++ | _INTERVAL_QUERY_ULTRA_VIOLENCE pos_num { ++ conf->interval_query_ultra_violence = $2.pos_num; ++ } ++ ++ | _INTERVAL_QUERY_TIMEOUT pos_num { ++ conf->interval_query_timeout = $2.pos_num; ++ } ++ ++ | _TRUSTLEVEL_BADPEER pos_num { ++ conf->trustlevel_badpeer = $2.pos_num; ++ } ++ | _TRUSTLEVEL_PATHETIC pos_num { ++ conf->trustlevel_pathetic = $2.pos_num; ++ } ++ | _TRUSTLEVEL_AGGRESSIVE pos_num { ++ conf->trustlevel_aggressive = $2.pos_num; ++ } ++ | _TRUSTLEVEL_MAX pos_num { ++ conf->trustlevel_max = $2.pos_num; ++ } ++ ++ | _MAX_SERVERS_DNS pos_num { ++ conf->max_servers_dns = $2.pos_num; ++ } ++ ++ | _QSCALE_OFF_MIN pos_decimal { ++ conf->qscale_off_min = $2.pos_decimal; ++ } ++ | _QSCALE_OFF_MAX pos_decimal { ++ conf->qscale_off_max = $2.pos_decimal; ++ } ++ ++ | _QUERYTIME_MAX pos_num { ++ conf->querytime_max = $2.pos_num; ++ } ++ | _OFFSET_ARRAY_SIZE pos_num { ++ conf->offset_array_size = $2.pos_num; ++ } ++ | _SENSOR_OFFSETS pos_num { ++ conf->sensor_offsets = $2.pos_num; ++ } ++ | _SETTIME_TIMEOUT pos_num { ++ conf->settime_timeout = $2.pos_num; ++ } ++ ++ | _LOG_NEGLIGIBLE_ADJTIME pos_num { ++ conf->log_negligible_adjtime = $2.pos_num; ++ } ++ | _LOG_NEGLIGIBLE_ADJFREQ pos_decimal { ++ conf->log_negligible_adjfreq = $2.pos_decimal; ++ } ++ ++ | _FREQUENCY_SAMPLES pos_num { ++ conf->frequency_samples = $2.pos_num; ++ } ++ | _MAX_FREQUENCY_ADJUST pos_decimal { ++ conf->max_frequency_adjust = $2.pos_decimal; ++ } ++ ++ | _MAX_SEND_ERRORS pos_num { ++ conf->max_send_errors = $2.pos_num; ++ } ++ ++ | _MAX_DISPLAY_WIDTH pos_num { ++ conf->max_display_width = $2.pos_num; ++ } ++ ++ | _AUTO_REPLIES pos_num { ++ conf->auto_replies = $2.pos_num; ++ } ++ | _AUTO_THRESHOLD pos_num { ++ conf->auto_threshold = $2.pos_num; ++ } ++ | _INTERVAL_AUTO_DNSFAIL pos_num { ++ conf->interval_auto_dnsfail = $2.pos_num; ++ } ++ | _TRIES_AUTO_DNSFAIL pos_num { ++ conf->tries_auto_dnsfail = $2.pos_num; ++ } ++ ++ | _FILTER_ADJFREQ STRING { ++ u_int8_t val; ++ ++ if (strcmp("true", $2) == 0) { ++ val = 0x01; ++ } else if (strcmp("false", $2) == 0) { ++ val = 0x00; ++ } else { ++ yyerror("option filter_adjfreq expects either 'true' or 'false'"); ++ YYERROR; ++ } ++ ++ conf->filter_adjfreq = val; ++ } ++ ++ | _SENSOR_DATA_MAXAGE pos_num { ++ conf->sensor_data_maxage = $2.pos_num; ++ } ++ | _SENSOR_QUERY_INTERVAL pos_num { ++ conf->sensor_query_interval = $2.pos_num; ++ } ++ | _SENSOR_SCAN_INTERVAL pos_num { ++ conf->sensor_scan_interval = $2.pos_num; ++ } ++ ++ | _SENSOR_DEFAULT_REFID STRING { ++ conf->sensor_default_refid = $2; ++ } ++ ++ | _CONSTRAINT_ERROR_MARGIN pos_num { ++ conf->constraint_error_margin = $2.pos_num; ++ } ++ | _CONSTRAINT_RETRY_INTERVAL pos_num { ++ conf->constraint_retry_interval = $2.pos_num; ++ } ++ | _CONSTRAINT_SCAN_INTERVAL pos_num { ++ conf->constraint_scan_interval = $2.pos_num; ++ } ++ | _CONSTRAINT_SCAN_TIMEOUT pos_num { ++ conf->constraint_scan_timeout = $2.pos_num; ++ } ++ | _CONSTRAINT_MARGIN pos_num { ++ conf->constraint_margin = (double)$2.pos_num; ++ } ++ | _CONSTRAINT_MAXHEADERLENGTH pos_num { ++ conf->constraint_maxheaderlength = $2.pos_num; ++ } ++ ; ++ ++pos_num : NUMBER { ++ if ($1 < 0) { ++ yyerror("must be a positive number"); ++ YYERROR; ++ } ++ $$.pos_num = $1; ++ } ++ ; ++ ++pos_decimal : NUMBER_DOUBLE { ++ if ($1 < 0) { ++ yyerror("must be a positive decimal number"); ++ YYERROR; ++ } ++ $$.pos_decimal = $1; ++ } + ; + + address : STRING { +@@ -587,8 +817,12 @@ opts_default(void) + struct keywords { + const char *k_name; + int k_val; ++ const char *k_times; ++ int k_seen; + }; + ++struct keywords *lookup(char *); ++ + int + yyerror(const char *fmt, ...) + { +@@ -611,37 +845,82 @@ kw_cmp(const void *k, const void *e) + return (strcmp(k, ((const struct keywords *)e)->k_name)); + } + +-int ++struct keywords * + lookup(char *s) + { +- /* this has to be sorted always */ +- static const struct keywords keywords[] = { +- { "constraint", CONSTRAINT}, +- { "constraints", CONSTRAINTS}, +- { "correction", CORRECTION}, +- { "from", FROM}, +- { "listen", LISTEN}, +- { "on", ON}, +- { "port", PORT}, +- { "query", QUERY}, +- { "refid", REFID}, +- { "rtable", RTABLE}, +- { "sensor", SENSOR}, +- { "server", SERVER}, +- { "servers", SERVERS}, +- { "stratum", STRATUM}, +- { "trusted", TRUSTED}, +- { "weight", WEIGHT} ++ /* NOTE: this has to be sorted always! */ ++ // NOTE: Because dynamic k_seen has been added, const definition is removed ++ // from this data structure. If you want to keep const, already set k_seen ++ // value can't be changed from its initial value. ++ static struct keywords keywords[] = { ++ { "auto_replies", _AUTO_REPLIES, "single" }, ++ { "auto_threshold", _AUTO_THRESHOLD, "single" }, ++ { "constraint", CONSTRAINT, "multiple" }, ++ { "constraint_error_margin", _CONSTRAINT_ERROR_MARGIN, "single" }, ++ { "constraint_margin", _CONSTRAINT_MARGIN, "single" }, ++ { "constraint_maxheaderlength", _CONSTRAINT_MAXHEADERLENGTH, "single" }, ++ { "constraint_retry_interval", _CONSTRAINT_RETRY_INTERVAL, "single" }, ++ { "constraint_scan_interval", _CONSTRAINT_SCAN_INTERVAL, "single" }, ++ { "constraint_scan_timeout", _CONSTRAINT_SCAN_TIMEOUT, "single" }, ++ { "constraints", CONSTRAINTS, "multiple" }, ++ { "correction", CORRECTION, "multiple" }, ++ { "ctlsocket", _CTLSOCKET, "single" }, ++ { "driftfile", _DRIFTFILE, "single" }, ++ { "filter_adjfreq", _FILTER_ADJFREQ, "single" }, ++ { "frequency_samples", _FREQUENCY_SAMPLES, "single" }, ++ { "from", FROM, "multiple" }, ++ { "interval_auto_dnsfail", _INTERVAL_AUTO_DNSFAIL, "single" }, ++ { "interval_query_aggressive", _INTERVAL_QUERY_AGGRESSIVE, "single" }, ++ { "interval_query_normal", _INTERVAL_QUERY_NORMAL, "single" }, ++ { "interval_query_pathetic", _INTERVAL_QUERY_PATHETIC, "single" }, ++ { "interval_query_timeout", _INTERVAL_QUERY_TIMEOUT, "single" }, ++ { "interval_query_ultra_violence", _INTERVAL_QUERY_ULTRA_VIOLENCE, "single" }, ++ { "listen", LISTEN, "multiple" }, ++ { "log_negligible_adjfreq", _LOG_NEGLIGIBLE_ADJFREQ, "single" }, ++ { "log_negligible_adjtime", _LOG_NEGLIGIBLE_ADJTIME, "single" }, ++ { "max_display_width", _MAX_DISPLAY_WIDTH, "single" }, ++ { "max_frequency_adjust", _MAX_FREQUENCY_ADJUST, "single" }, ++ { "max_send_errors", _MAX_SEND_ERRORS, "single" }, ++ { "max_servers_dns", _MAX_SERVERS_DNS, "single" }, ++ { "ntpd_user", _NTPD_USER, "single" }, ++ { "on", ON, "multiple" }, ++ { "port", PORT, "multiple" }, ++ { "qscale_off_min", _QSCALE_OFF_MIN, "single" }, ++ { "qscale_off_max", _QSCALE_OFF_MAX, "single" }, ++ { "query", QUERY, "multiple" }, ++ { "querytime_max", _QUERYTIME_MAX, "single" }, ++ { "refid", REFID, "multiple" }, ++ { "rtable", RTABLE, "multiple" }, ++ { "sensor", SENSOR, "multiple" }, ++ { "sensor_data_maxage", _SENSOR_DATA_MAXAGE, "single" }, ++ { "sensor_default_refid", _SENSOR_DEFAULT_REFID, "single" }, ++ { "sensor_offsets", _SENSOR_OFFSETS, "single" }, ++ { "sensor_query_interval", _SENSOR_QUERY_INTERVAL, "single" }, ++ { "sensor_scan_interval", _SENSOR_SCAN_INTERVAL, "single" }, ++ { "server", SERVER, "multiple" }, ++ { "servers", SERVERS, "multiple" }, ++ { "settime_timeout", _SETTIME_TIMEOUT, "single" }, ++ { "stratum", STRATUM, "multiple" }, ++ { "tries_auto_dnsfail", _TRIES_AUTO_DNSFAIL, "single" }, ++ { "trusted", TRUSTED, "multiple" }, ++ { "trustlevel_aggressive", _TRUSTLEVEL_AGGRESSIVE, "single" }, ++ { "trustlevel_badpeer", _TRUSTLEVEL_BADPEER, "single" }, ++ { "trustlevel_max", _TRUSTLEVEL_MAX, "single" }, ++ { "trustlevel_pathetic", _TRUSTLEVEL_PATHETIC, "single" }, ++ { "weight", WEIGHT, "multiple" }, + }; +- const struct keywords *p; ++ struct keywords *p; + ++ // Compare supplied character buffer and keywords[0] + p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), + sizeof(keywords[0]), kw_cmp); + +- if (p) +- return (p->k_val); +- else +- return (STRING); ++ /* ++ * When having non-keyword (i.e. invalid keyword) value, ++ * we return NULL. Therefore, return value must separately ++ * be checked if it is used anywhere. ++ */ ++ return (p); + } + + #define MAXPUSHBACK 128 +@@ -743,8 +1022,9 @@ yylex(void) + { + u_char buf[8096]; + u_char *p; ++ char *derr; + int quotec, next, c; +- int token; ++ struct keywords *token; + + p = buf; + while ((c = lgetc(0)) == ' ' || c == '\t') +@@ -805,7 +1085,7 @@ yylex(void) + yyerror("string is too long"); + return (findeol()); + } +- } while ((c = lgetc(0)) != EOF && isdigit(c)); ++ } while ((c = lgetc(0)) != EOF && (isdigit(c) || c == '.')); + lungetc(c); + if (p == buf + 1 && buf[0] == '-') + goto nodigits; +@@ -816,10 +1096,23 @@ yylex(void) + yylval.v.number = strtonum(buf, LLONG_MIN, + LLONG_MAX, &errstr); + if (errstr) { ++ ++ // Fall back. Check if it is actually a decimal number ++ yylval.v.decimal = strtod(buf, &derr); ++ if (*derr != 0) { ++ // Fall back. Assume it is actually a string (e.g. IP address) ++ yylval.v.string = strdup(buf); ++ return (STRING); ++ // If not a string, syntax error is returned in further checks ++ } ++ return (NUMBER_DOUBLE); ++ /* + yyerror("\"%s\" invalid number: %s", + buf, errstr); + return (findeol()); ++ */ + } ++ + return (NUMBER); + } else { + nodigits: +@@ -847,11 +1140,47 @@ nodigits: + } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); + lungetc(c); + *p = '\0'; +- if ((token = lookup(buf)) == STRING) +- if ((yylval.v.string = strdup(buf)) == NULL) +- fatal("can't allocate memory for buffered string"); +- return (token); ++ ++ /* ++ * When having *non-null* value for token, we have a validated ++ * keyword argument (integer) in place. In other cases, ++ * we assume integer value of STRING, generated dynamically ++ * by Bison yyParser. This STRING integer value is used for ++ * further argument checks where ever STRING keyworded ++ * arguments are used. ++ * Furthermore, we limit count of arguments which are meant ++ * to be defined only once by a user. This is defined by ++ * values of token->k_seen and token->k_times individually ++ * for each supplied argument. ++ */ ++ if ((token = lookup(buf)) != NULL) { ++ ++ if (!token->k_seen) ++ token->k_seen = 0; ++ ++ if (strcmp("multiple", token->k_times) == 0) { ++ return (token->k_val); ++ ++ } else if ((strcmp("single", token->k_times) == 0) && ++ token->k_seen == 0) { ++ token->k_seen = 1; ++ return (token->k_val); ++ ++ } else { ++ yyerror("option %s is already set", token->k_name); ++ return (c); ++ } ++ ++ } else { ++ if ((yylval.v.string = strdup(buf)) == NULL) { ++ fatal("can't duplicate memory for buffered string"); ++ } else { ++ return STRING; ++ } ++ } ++ + } ++ + if (c == '\n') { + yylval.lineno = file->lineno; + file->lineno++; +@@ -902,12 +1231,205 @@ popfile(void) + return (file ? 0 : EOF); + } + ++void ++checkvalues(const double a, char *aa, const double b, char *bb) ++{ ++ if (a <= b) ++ fatalx("error in configuration values: %s can't be greater or equal than %s", bb, aa); ++} ++ ++// NTP Configuration defaults ++void ++init_conf(struct ntpd_conf *conf) ++{ ++ conf->ntpd_user = NTPD_USER; // _ntp; ++ ++ conf->driftfile = DRIFTFILE; // /var/db/ntpd.drift; ++ conf->ctlsocket = CTLSOCKET; // /var/run/ntpd.sock; ++ ++ conf->interval_query_normal = INTERVAL_QUERY_NORMAL; // 30; ++ conf->interval_query_pathetic = INTERVAL_QUERY_PATHETIC; // 60; ++ conf->interval_query_aggressive = INTERVAL_QUERY_AGGRESSIVE; // 5; ++ conf->interval_query_ultra_violence = INTERVAL_QUERY_ULTRA_VIOLENCE; // 1; ++ ++ conf->interval_query_timeout = INTERVAL_QUERY_TIMEOUT; // 300; ++ ++ conf->trustlevel_badpeer = TRUSTLEVEL_BADPEER; // 6; ++ conf->trustlevel_pathetic = TRUSTLEVEL_PATHETIC; // 2; ++ conf->trustlevel_aggressive = TRUSTLEVEL_AGGRESSIVE; // 8; ++ conf->trustlevel_max = TRUSTLEVEL_MAX; // 10; ++ ++ /* maximum number of servers from DNS query */ ++ conf->max_servers_dns = MAX_SERVERS_DNS; // 8; ++ ++ conf->qscale_off_min = QSCALE_OFF_MIN; // 0.001; ++ conf->qscale_off_max = QSCALE_OFF_MAX; // 0.050; ++ ++ /* single query might take n secs max */ ++ conf->querytime_max = QUERYTIME_MAX; // 15; ++ /*Maximum number of allowed sensor offsets*/ ++ conf->offset_array_size = OFFSET_ARRAY_SIZE; // 8; ++ /*Number of sensor offset values allowed for median offset value calculation*/ ++ conf->sensor_offsets = SENSOR_OFFSETS; // 6; ++ /* max seconds to wait with -s */ ++ conf->settime_timeout = SETTIME_TIMEOUT; // 100; ++ ++ /* negligible drift to not log (ms) */ ++ conf->log_negligible_adjtime = LOG_NEGLIGIBLE_ADJTIME; // 32; ++ ++ /* negligible rate to not log (ppm) */ ++ conf->log_negligible_adjfreq = LOG_NEGLIGIBLE_ADJFREQ; // 0.05; ++ ++ /* samples for est. of permanent drift */ ++ conf->frequency_samples = FREQUENCY_SAMPLES; // 8; ++ ++ /* max correction per iteration */ ++ conf->max_frequency_adjust = MAX_FREQUENCY_ADJUST; // 128e-5; ++ ++ /* max send errors before reconnect */ ++ conf->max_send_errors = MAX_SEND_ERRORS; // 3; ++ ++ /* max chars in ctl_show report line */ ++ conf->max_display_width = MAX_DISPLAY_WIDTH; // 80; ++ ++ /* set after doing adjfreq */ ++ conf->filter_adjfreq = FILTER_ADJFREQ; // 0x01; ++ ++ /* # of ntp replies we want for auto */ ++ conf->auto_replies = AUTO_REPLIES; // 4; ++ ++ /* dont bother auto setting < this */ ++ conf->auto_threshold = AUTO_THRESHOLD; // 60; ++ ++ /* DNS tmpfail interval for auto */ ++ conf->interval_auto_dnsfail = INTERVAL_AUTO_DNSFAIL; // 1; ++ ++ /* DNS tmpfail quick retries */ ++ conf->tries_auto_dnsfail = TRIES_AUTO_DNSFAIL; // 4; ++ ++ conf->sensor_data_maxage = SENSOR_DATA_MAXAGE; // 15*60; ++ conf->sensor_query_interval = SENSOR_QUERY_INTERVAL; // 15; ++ conf->sensor_scan_interval = SENSOR_SCAN_INTERVAL; // 1*60; ++ ++ conf->sensor_default_refid = SENSOR_DEFAULT_REFID; // "HARD"; ++ ++ conf->constraint_error_margin = CONSTRAINT_ERROR_MARGIN; // 4; ++ conf->constraint_retry_interval = CONSTRAINT_RETRY_INTERVAL; // 15; ++ conf->constraint_scan_interval = CONSTRAINT_SCAN_INTERVAL; // 15*60; ++ conf->constraint_scan_timeout = CONSTRAINT_SCAN_TIMEOUT; // 10; ++ conf->constraint_margin = CONSTRAINT_MARGIN; // 2.0*60; ++ ++ conf->constraint_maxheaderlength = CONSTRAINT_MAXHEADERLENGTH; // 8192; ++} ++ ++void ++print_conf(struct ntpd_conf *lconf) ++{ ++ char* boolean[5]; ++ struct constraint *cstr; ++ struct ntp_conf_sensor *sens; ++ struct ntp_peer *peer; ++ ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Current configuration:\n\n"); ++ fprintf(stdout, "NTPd user: %s\n", conf->ntpd_user); ++ fprintf(stdout, "Drift file: %s\n", conf->driftfile); ++ fprintf(stdout, "CTL socket file: %s\n", conf->ctlsocket); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Query interval (normal): %d seconds\n", conf->interval_query_normal); ++ fprintf(stdout, "Query interval (pathetic): %d seconds\n", conf->interval_query_pathetic); ++ fprintf(stdout, "Query interval (aggressive): %d seconds\n", conf->interval_query_aggressive); ++ fprintf(stdout, "Query interval (ultra violent): %d seconds\n", conf->interval_query_ultra_violence); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Query interval after reply timeout: %d seconds\n", conf->interval_query_timeout); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Trust level (bad peer): %d\n", conf->trustlevel_badpeer); ++ fprintf(stdout, "Trust level (pathetic): %d\n", conf->trustlevel_pathetic); ++ fprintf(stdout, "Trust level (aggressive): %d\n", conf->trustlevel_aggressive); ++ fprintf(stdout, "Trust level (maximum): %d\n", conf->trustlevel_max); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Maximum number of allowed sensor offsets: %d\n", conf->offset_array_size); ++ fprintf(stdout, "Number of sensor offset values considered for median offset value calculation: %d\n", conf->sensor_offsets); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Query time (maximum): %d seconds\n", conf->querytime_max); ++ fprintf(stdout, "Start up timeout in auto mode: %d seconds\n", conf->settime_timeout); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Maximum number of retrievable servers from a DNS query: %d\n", conf->max_servers_dns); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Time adjustment minimum scale: %.4f seconds\n", conf->qscale_off_min); ++ fprintf(stdout, "Time adjustment maximum scale: %.4f seconds\n", conf->qscale_off_max); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Neglible drift time to not log: %d milliseconds\n", conf->log_negligible_adjtime); ++ fprintf(stdout, "Neglible frequency rate to not log: %f ppm\n", conf->log_negligible_adjfreq); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Frequency samples for estimation of permanent drift: %d\n", conf->frequency_samples); ++ fprintf(stdout, "Maximum frequency correction per iteration: %f\n", conf->max_frequency_adjust); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Maximum send errors before reconnection: %d\n", conf->max_send_errors); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Maximum number of characters per output line: %d\n", conf->max_display_width); ++ fprintf(stdout, "\n"); ++ ++ if ((conf->filter_adjfreq) == 0x01) ++ *boolean = "true"; ++ else if ((conf->filter_adjfreq) == 0x00) ++ *boolean = "false"; ++ ++ fprintf(stdout, "Filter frequency adjustment after maximum frequency correction: %s\n", *boolean); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "NTP replies for auto mode: %d seconds\n", conf->auto_replies); ++ fprintf(stdout, "Threshold count for auto mode: %d\n", conf->auto_threshold); ++ fprintf(stdout, "DNS failure interval for auto mode: %d\n", conf->interval_auto_dnsfail); ++ fprintf(stdout, "DNS retries on failure in auto mode: %d\n", conf->tries_auto_dnsfail); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Sensor query interval: %d seconds\n", conf->sensor_query_interval); ++ fprintf(stdout, "Sensor data maximum age: %d seconds\n", conf->sensor_data_maxage); ++ fprintf(stdout, "Sensor scan interval: %d seconds\n", conf->sensor_scan_interval); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Sensor default reference ID string: %s\n", conf->sensor_default_refid); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Constraint error margin: %.2f seconds\n", conf->constraint_error_margin); ++ fprintf(stdout, "Constraint default margin: %.2f seconds\n", conf->constraint_margin); ++ fprintf(stdout, "\n"); ++ fprintf(stdout, "Constraint retry interval: %d seconds\n", conf->constraint_retry_interval); ++ fprintf(stdout, "Constraint scan interval: %d seconds\n", conf->constraint_scan_interval); ++ fprintf(stdout, "Constraint scan timeout: %d seconds\n", conf->constraint_scan_timeout); ++ fprintf(stdout, "Constraint maximum HTTP header length: %d bytes\n", conf->constraint_maxheaderlength); ++ fprintf(stdout, "\n"); ++ ++ TAILQ_FOREACH(sens, &conf->ntp_conf_sensors, entry) { ++ fprintf(stdout, "Configuration: sensor %s, refid %s stratum %d weight %d\n", ++ sens->device, ++ sens->refstr, ++ sens->stratum, ++ sens->weight ++ ); ++ } ++ ++ TAILQ_FOREACH(peer, &conf->ntp_peers, entry) { ++ fprintf(stdout, "Configuration: NTP server %s on remote UDP port %d\n", ++ peer->addr_head.name, ++ peer->addr_head.port ++ ); ++ } ++ ++ TAILQ_FOREACH(cstr, &conf->constraints, entry) { ++ fprintf(stdout, "Configuration: HTTPS constraint server %s on remote TCP port %d\n", ++ cstr->addr_head.name, ++ cstr->addr_head.port ++ ); ++ } ++ fprintf(stdout, "\n"); ++} ++ + int + parse_config(const char *filename, struct ntpd_conf *xconf) + { + int errors = 0; + + conf = xconf; ++ init_conf(conf); ++ + TAILQ_INIT(&conf->listen_addrs); + TAILQ_INIT(&conf->ntp_peers); + TAILQ_INIT(&conf->ntp_conf_sensors); +@@ -922,5 +1444,18 @@ parse_config(const char *filename, struc + errors = file->errors; + popfile(); + ++ // Rough checks for conflicting values ++ checkvalues(conf->qscale_off_max, "qscale_off_max", ++ conf->qscale_off_min, "qscale_off_min"); ++ ++ checkvalues(conf->trustlevel_max, "trustlevel_max", ++ conf->trustlevel_aggressive, "trustlevel_aggressive"); ++ ++ checkvalues(conf->trustlevel_aggressive, "trustlevel_aggressive", ++ conf->trustlevel_badpeer, "trustlevel_badpeer"); ++ ++ checkvalues(conf->trustlevel_badpeer, "trustlevel_badpeer", ++ conf->trustlevel_pathetic, "trustlevel_pathetic"); ++ + return (errors ? -1 : 0); + } +--- a/src/ntpd.conf.5 2020-08-01 01:22:25.000000000 +0300 ++++ b/src/ntpd.conf.5 2020-08-02 02:31:01.526954911 +0300 +@@ -14,7 +14,7 @@ + .\" AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + .\" OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + .\" +-.Dd $Mdocdate: August 01 2020 $ ++.Dd $Mdocdate: August 02 2020 $ + .Dt NTPD.CONF 5 + .Os + .Sh NAME +@@ -31,8 +31,10 @@ has the following format: + Empty lines and lines beginning with the + .Sq # + character are ignored. +-.Pp +-Keywords may be specified multiple times within the configuration file. ++.Ed ++.El ++.Sh BASIC KEYWORDS ++Basic keywords may be specified multiple times within the configuration file. + The basic configuration options are as follows: + .Bl -tag -width Ds + .It Xo Ic listen on Ar address +@@ -282,12 +284,523 @@ constraints from "https://www.google.com + constraints from "https://duckduckgo.com/" port 443 + .Ed + .El ++.Sh ADVANCED KEYWORDS ++Some ++.Xr ntpd 8 ++default configuration values can be overridden, thus offering better ++adaption to system policy and flexibility for system administrators. Advanced ++keywords may be specified only once within the configuration file. The ++following values can be changed from the highlighted defaults: ++.Bl -tag -width Ds ++ ++.It Ic auto_replies Ar number ++During OpenNTPD initialization, all NTP peers get automatic time offset value, ++if pre-conditions for automatic interval adjustment are being met. The ++conditions are as follows: OpenNTPD configuration has constraints, ++.Ic trusted ++NTP peers or ++.Ic trusted ++sensors and current internally defined ++process security level is 0. In this case, initial time offset value ++is set to 1 which, in return, triggers automatic offset calculation. ++.Pp ++In the automatic offset calculation, a ++.Ic trusted ++NTP peer offset values are being counted for each peer. For each peer an independent ++pool size is determined by ++.Ic auto_replies ++value, ignoring the last value. For instance, with ++.Ic auto_replies ++value 4, first 3 NTP peer offset values are considered for a single NTP peer, ++and a median offset value of these collected 3 offset values is calculated ++and used for time adjustment. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++4 ++.El ++.Ed ++.It Ic auto_threshold Ar number ++In OpenNTPD initial automatic time offset calculation, three conditions ++are being considered for NTP peers: is a NTP peer ++.Ic trusted ++and current overall constraint-based median offset not 0, and whether an initial NTP ++peer time offset exceeds value of ++.Ic auto_threshold ++\&. If these conditions are met, then ++.Ic auto_threshold ++value may be considered. If NTP peer current time offset value is less than ++.Ic auto_threshold ++, then the system time offset value is considered to be already OK, and ++OpenNTPD stops calculating automatic offset value from further NTP ++peer queries. In this case, median offset value is not calculated. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++60 ++.El ++.Ed ++.It Ic interval_auto_dnsfail Ar seconds ++In automatic NTP peer offset calculation mode (during OpenNTPD initialization), ++if NTP peer IP address is still unresolved (unknown), the next query is ++attempted in ++.Ic interval_auto_dnsfail ++seconds. Applies to unresolved constraint IP addresses, as well. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++1 ++.El ++.Ed ++.It Ic tries_auto_dnsfail Ar number ++Maximum number of attempts to resolve a constraint IP address(es) with a ++DNS query before falling back from ++.Ic constraint_retry_interval ++to ++.Ic interval_auto_dnsfail ++\& in constraint initialization. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++4 ++.El ++.Ed ++.It Ic constraint_error_margin Ar number ++Accepted number of errors during constraint process. If error count exceeds ++this value multiplied by calculated peer count, constraint connection will ++be reseted and a new constraint is retrieved. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++4 ++.El ++.Ed ++.It Ic constraint_margin Ar seconds ++Acceptable time difference between retrieved HTTP header time value and ++calculated time value in seconds. HTTP header time values exceeding this ++margin value will be ignored. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++120 ++.El ++.Ed ++.It Ic constraint_maxheaderlength Ar length ++Maximum allowed HTTP header length of constraint HTTPS server reply to ++be fetched in bytes. If the value is exceeded during processing, ++nothing is returned and constraint check fails. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++8192 ++.El ++.Ed ++.It Ic constraint_scan_interval Ar seconds ++Constraint HTTPS servers scan interval in seconds. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++900 ++.El ++.Ed ++.It Ic constraint_scan_timeout Ar seconds ++Maximum connection establishment time to a constraint HTTPS server in seconds. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++10 ++.El ++.Ed ++.It Ic ctlsocket Ar path-to-file ++.Xr ntpd 8 ++socket file path. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++/var/run/ntpd.sock ++.El ++.Ed ++.It Ic driftfile Ar path-to-file ++.Xr ntpd 8 ++drift file path. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++/var/db/ntpd.drift ++.El ++.Ed ++.It Ic filter_adjfreq Ar true | false ++Whether to reset frequency filters after frequency adjustment. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++true ++.El ++.Ed ++.It Ic frequency_samples Ar number ++Number of frequency samples for estimating permanent drift value. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++8 ++.El ++.Ed ++.It Ic trustlevel_pathetic Ar number ++Initial trust level for a new, timed out or erroneous remote NTP ++server. Every received and non-discarded reply increases trust ++for the server. The trust level is used for setting used ++.Ic interval_query_* ++value for the server and keeping track of valid remote NTP servers. ++.Pp ++A server having this trust level uses remote NTP query interval ++value ++.Ic interval_query_aggressive ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++2 ++.El ++.Ed ++.It Ic trustlevel_badpeer Ar number ++If a replying remote NTP server has trust level one number ++less than this value, the server gets trusted. In this case, ++the server can achieve maximum trust level ++.Ic trustlevel_max ++\&. This trust level is preceded by trust level ++.Ic trustlevel_pathetic ++and followed by trust level ++.Ic trustlevel_aggressive ++\&. ++.Pp ++A NTP server having trust level value ++.Ic trustlevel_badpeer ++, or value greater than ++.Ic trustlevel_pathetic ++but less than ++.Ic trustlevel_aggressive ++uses remote NTP query interval value ++.Ic interval_query_aggressive ++\&. ++.Pp ++In a case of NTP server reply time out, if the server has at ++least trust level value ++.Ic trustlevel_badpeer ++and the trust level value divided by 2 is less than the ++.Ic trustlevel_badpeer ++value, the server will be invalidated and falls back to ++initial trust level ++.Ic trustlevel_pathetic ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++6 ++.El ++.Ed ++.It Ic trustlevel_aggressive Ar number ++Aggressive trust level is preceded by trust level ++.Ic trustlevel_badpeer ++and followed by trust level ++.Ic trustlevel_max ++\&. If a remote NTP server current trust level is at least value ++.Ic trustlevel_pathetic ++but less than this value, used remote NTP query interval is ++determined by value ++.Ic interval_query_aggressive ++\&. A server with exact trust level ++.Ic trustlevel_aggressive ++uses query interval ++.Ic interval_query_normal ++(see ++.Ic trustlevel_max ++below). ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++8 ++.El ++.Ed ++.It Ic trustlevel_max Ar number ++Maximum trust level follows trust level ++.Ic trustlevel_aggressive ++\&. This is the maximum trust level which a remote ++NTP server can achieve. A server having at least trust level of ++.Ic trustlevel_aggressive ++uses remote NTP query interval value ++.Ic interval_query_normal ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++10 ++.El ++.Ed ++.It Ic interval_query_pathetic Ar seconds ++Remote NTP server query interval in seconds for servers with ++a trust level value less than ++.Ic trustlevel_pathetic ++\&. Practically never used. ++This value is not the final query interval value but used ++in a combination with a dynamic offset scale value, determined by ++.Ic qscale_off_min ++and ++.Ic qscale_off_max ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++60 ++.El ++.Ed ++.It Ic interval_query_ultra_violence Ar seconds ++Remote NTP server query interval in seconds for servers ++with a trust level value greater than ++.Ic trustlevel_pathetic ++but less than ++.Ic trustlevel_aggressive ++in a case where a NTP peer does not still have large enough ++pool of already queried offset time values for its offset ++time median calculation (checked against value ++.Ic auto replies ++) or is not ++.Ic trusted ++, interval value ++.Ic interval_query_ultra_violence ++may be triggered. Applies only to NTP offset calculation ++automatic mode. ++.Pp ++In most cases, ++.Ic interval_query_aggressive ++is used instead. Dynamic offset scale value factors ++.Ic qscale_off_min ++and ++.Ic qscale_off_max ++are ignored. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++1 ++.El ++.Ed ++.It Ic interval_query_aggressive Ar seconds ++Remote NTP server query interval in seconds for servers ++with a trust level value greater than ++.Ic trustlevel_pathetic ++but less than ++.Ic trustlevel_aggressive ++\&. Applies only, if automatic NTP peer query state is finished. ++This value is not the final query interval value but used ++in a combination with a dynamic offset scale value, determined by ++.Ic qscale_off_min ++and ++.Ic qscale_off_max ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++5 ++.El ++.Ed ++.It Ic interval_query_normal Ar seconds ++Remote NTP server query interval in seconds for servers with ++a trust level value between ++.Ic trustlevel_aggressive ++and ++.Ic trustlevel_max ++\&. This value is not the final query interval value but used ++in a combination with a dynamic offset scale value, determined by ++.Ic qscale_off_min ++and ++.Ic qscale_off_max ++\&. ++.Bd -literal -offset indent ++.Bl -tag -width "Default:" -compact ++.It Default: ++30 ++.El ++.Ed ++.It Ic interval_query_timeout Ar seconds ++Retry time in seconds after failed connection attempt to a remote NTP server. ++.Bd -li \ No newline at end of file diff --git a/patches/7-patch_implement-openssl.patch b/patches/7-patch_implement-openssl.patch new file mode 100644 index 0000000..7ef4916 --- /dev/null +++ b/patches/7-patch_implement-openssl.patch @@ -0,0 +1,706 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Implement OpenSSL support, update manual, update ChangeLog + + +--- a/configure.ac 2020-07-31 23:00:40.000000000 +0300 ++++ b/configure.ac 2020-08-02 01:23:30.696950640 +0300 +@@ -59,35 +59,100 @@ AM_CONDITIONAL([HAVE_ADJFREQ], [test "x$ + AM_CONDITIONAL([HAVE_CLOCK_GETRES], [test "x$ac_cv_func_clock_getres" = xyes]) + AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test "x$ac_cv_func_clock_gettime" = xyes]) + +-# check for libtls +-AC_SEARCH_LIBS([tls_config_set_ca_mem],[tls], +- [LIBS="$LIBS -ltls -lssl -lcrypto"],,[-lssl -lcrypto]) +-AC_CHECK_FUNCS([tls_config_set_ca_mem]) +- +-# check if libtls uses 3-argument tls_write +-AC_CACHE_CHECK([if tls_write takes 3 arguments], ac_cv_have_tls_write_3_arg, [ +- AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +-#include +-size_t outlen; +- ]], [[ tls_write(NULL, NULL, 0); ]])], +- [ ac_cv_have_tls_write_3_arg="yes" ], +- [ ac_cv_have_tls_write_3_arg="no" ++# NOTE: hard-set AC_CHECK_HEADER or friends can't really be checked since ++# libressl/openssl include header files must be determined by OS basis ++# during compilation. Use the following approach instead. ++ ++AM_CONDITIONAL(HAVE_SSL, false) ++AM_CONDITIONAL([HAVE_LIBRESSL], false) ++AM_CONDITIONAL([HAVE_OPENSSL], false) ++ ++# check for libressl ++AC_ARG_WITH([libressl], ++ AS_HELP_STRING([--without-libressl], ++ [Disable LibreSSL support for constraints])) ++ ++AS_IF([test "x$with_libressl" != "xno" ], ++ [ have_libressl="yes" ], ++ [ have_libressl="no" ] ++) ++ ++if test "x$have_libressl" == "xyes"; then ++ ++ AC_SEARCH_LIBS([tls_config_set_ca_mem],[tls], ++ [LIBS="$LIBS -ltls -lssl -lcrypto"],,[-lssl -lcrypto]) ++ ++ AC_CHECK_FUNCS([tls_config_set_ca_mem]) ++ ++ # check if libressl uses 3-argument tls_write ++ AC_CACHE_CHECK( ++ [if LibreSSL tls_write takes 3 arguments], ++ ac_cv_have_libressl_write_3_arg, ++ [AC_LINK_IFELSE([AC_LANG_PROGRAM( ++ [[ #include ]], ++ [[ size_t outlen; ]], ++ [[ tls_write(NULL, NULL, 0); ]] ++ )], ++ [ ac_cv_have_libressl_write_3_arg="yes" ], ++ [ ac_cv_have_libressl_write_3_arg="no" ] ++ ) ++ ]) ++fi ++ ++# check for openssl ++AC_ARG_WITH([openssl], ++ AS_HELP_STRING([--without-openssl], ++ [Disable OpenSSL support for constraints])) ++ ++AS_IF([test "x$with_openssl" != "xno" ], ++ [ have_openssl="yes" ], ++ [ have_openssl="no" ] ++) ++ ++if test "x$have_openssl" == "xyes"; then ++ ++ AC_SEARCH_LIBS([X509_STORE_load_locations],[ssl], ++ [LIBS="$LIBS -lssl -lcrypto"],,[-lssl -lcrypto]) ++ ++ AC_CHECK_FUNCS([X509_STORE_load_locations]) ++ ++ # check if openssl uses 3-argument SSL_write ++ AC_CACHE_CHECK( ++ [if OpenSSL SSL_write takes 3 arguments], ++ ac_cv_have_openssl_write_3_arg, ++ [AC_LINK_IFELSE([AC_LANG_PROGRAM( ++ [[ #include ]], ++ [[ SSL *a; SSL_CTX *ff; ]], ++ [[ ff = SSL_CTX_new(TLS_method()); ]], ++ [[ a = SSL_new(ff); ]], ++ [[ SSL_write(a, NULL, 0); ]] ++ )], ++ [ ac_cv_have_openssl_write_3_arg="yes" ], ++ [ ac_cv_have_openssl_write_3_arg="no" ] ++ ) + ]) +-]) ++fi + +-AC_ARG_ENABLE([https-constraint], +- AS_HELP_STRING([--disable-https-constraint], +- [Disable HTTPS Constraint Functionality])) +- +-AM_CONDITIONAL([HAVE_LIBTLS], +- [test "x$ac_cv_func_tls_config_set_ca_mem" = xyes \ +- -a "x$ac_cv_have_tls_write_3_arg" = xyes \ +- -a "x$enable_https_constraint" != xno]) +- +-if test "x$ac_cv_func_tls_config_set_ca_mem" = xyes \ +- -a "x$ac_cv_have_tls_write_3_arg" = xyes \ +- -a "x$enable_https_constraint" != xno; then +- AC_DEFINE([HAVE_LIBTLS], [yes]) ++if test "x$with_libressl" != xno \ ++ -a "x$ac_cv_func_tls_config_set_ca_mem" = xyes \ ++ -a "x$ac_cv_have_libressl_write_3_arg" = xyes; then ++ AM_CONDITIONAL([HAVE_LIBRESSL], true) ++ AM_CONDITIONAL([HAVE_SSL], true) ++ AC_DEFINE([HAVE_LIBRESSL], [yes]) ++ AC_DEFINE([HAVE_SSL], [yes]) ++else ++ AC_MSG_WARN([LibreSSL support disabled]) ++fi ++ ++if test "x$with_openssl" != xno \ ++ -a "x$ac_cv_func_X509_STORE_load_locations" = xyes \ ++ -a "x$ac_cv_have_openssl_write_3_arg" = xyes; then ++ AM_CONDITIONAL([HAVE_OPENSSL], true) ++ AM_CONDITIONAL([HAVE_SSL], true) ++ AC_DEFINE([HAVE_OPENSSL], [yes]) ++ AC_DEFINE([HAVE_SSL], [yes]) ++else ++ AC_MSG_WARN([OpenSSL support disabled]) + fi + + # Share test results with automake +@@ -144,14 +209,6 @@ AC_ARG_WITH([privsep-path], + ) + AC_SUBST(PRIVSEP_PATH) + +-AC_ARG_WITH([cacert], +- AS_HELP_STRING([--with-cacert=path], +- [CA certificate location for HTTPS constraint validation]), +- CONSTRAINT_CA="$withval", +- CONSTRAINT_CA="/etc/ssl/cert.pem" +-) +-AC_DEFINE_UNQUOTED(CONSTRAINT_CA, "$CONSTRAINT_CA", [CA certificate path]) +- + AC_CONFIG_FILES([ + Makefile + include/Makefile +--- a/include/tls.h 2020-07-31 23:00:40.000000000 +0300 ++++ b/include/tls.h 2020-08-01 19:24:29.153594762 +0300 +@@ -1,8 +1,22 @@ + /* + * Public domain + * tls.h compatibility shim ++ * ++ * __linux__ ++ * __sun ++ * __FreeBSD__ ++ * __NetBSD__ ++ * __OpenBSD__ ++ * __APPLE__ + */ + +-#ifdef HAVE_LIBTLS ++#if defined(HAVE_LIBRESSL) && __linux__ ++#include_next ++#elif HAVE_LIBRESSL + #include_next + #endif ++ ++#ifdef HAVE_OPENSSL ++#include ++#include ++#endif +--- a/src/constraint.c 2020-08-02 01:57:57.020286149 +0300 ++++ b/src/constraint.c 2020-08-02 01:58:28.366952848 +0300 +@@ -39,7 +39,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -65,33 +64,11 @@ void priv_constraint_close(int, int); + void priv_constraint_readquery(struct constraint *, struct ntp_addr_msg *, + uint8_t **); + +-struct httpsdate * +- httpsdate_init(const char *, const int *, const char *, +- const char *, const u_int8_t *, size_t); +-void httpsdate_free(void *); +-int httpsdate_request(struct httpsdate *, struct timeval *); +-void *httpsdate_query(const char *, const int *, const char *, +- const char *, const u_int8_t *, size_t, +- struct timeval *, struct timeval *); +- +-char *tls_readline(struct tls *, size_t *, size_t *, struct timeval *); +- + u_int constraint_cnt; + extern u_int peer_cnt; + extern struct imsgbuf *ibuf; /* priv */ + extern struct imsgbuf *ibuf_main; /* chld */ + +-struct httpsdate { +- char *tls_addr; +- char *tls_port; +- char *tls_hostname; +- char *tls_path; +- char *tls_request; +- struct tls_config *tls_config; +- struct tls *tls_ctx; +- struct tm tls_tm; +-}; +- + int + constraint_init(struct constraint *cstr) + { +@@ -155,7 +132,7 @@ constraint_query(struct constraint *cstr + { + time_t now; + struct ntp_addr_msg am; +- struct iovec iov[3]; ++ struct iovec iov[4]; + int iov_cnt = 0; + + now = getmonotime(); +@@ -252,7 +229,7 @@ priv_constraint_msg(u_int32_t id, u_int8 + return; + } + memcpy(&am, data, sizeof(am)); +- if (len != (sizeof(am) + am.namelen + am.pathlen + am.portlen)) { ++ if (len != (sizeof(am) + am.namelen + am.pathlen + am.portlen)) { + log_warnx("constraint id %d: invalid query received", id); + return; + } +@@ -343,13 +320,13 @@ priv_constraint_readquery(struct constra + memcpy(h, &am->a, sizeof(*h)); + memcpy(&port, &am->port, sizeof(port)); + h->next = NULL; +- ++ + cstr->id = imsg.hdr.peerid; + cstr->addr = h; + cstr->addr_head.a = h; + cstr->port = port; + cstr->addr_head.port = port; +- ++ + dptr = imsg.data; + memcpy(*data, dptr + sizeof(*am), mlen - sizeof(*am)); + imsg_free(&imsg); +@@ -364,20 +341,46 @@ priv_constraint_child(const char *pw_dir + static char addr[NI_MAXHOST]; + struct timeval rectv, xmttv; + struct sigaction sa; +- void *ctx; ++ void *ctx = NULL; + struct iovec iov[2]; + int i, rv; ++#ifdef HAVE_OPENSSL ++ X509_STORE *o_store = NULL; ++#endif + + if (setpriority(PRIO_PROCESS, 0, 0) == -1) + log_warn("constraint: can't set priority for subprocess"); + +-#ifdef HAVE_LIBTLS +- /* Init TLS and load CA certs before chroot() */ +- if (tls_init() == -1) +- fatalx("constraint: can't initialize LibreSSL engine"); +- if ((conf->ca = tls_load_file(tls_default_ca_cert_file(), +- &conf->ca_len, NULL)) == NULL) +- log_warnx("constraint: failed to load CA certificate bundle file"); ++/* Init TLS and load CA certs before chroot() */ ++#ifdef HAVE_LIBRESSL ++ if (strcmp("libressl", conf->constraint_engine) == 0) { ++ if (tls_init() == -1) ++ fatalx("constraint: can't initialize LibreSSL engine"); ++ if (conf->constraint_ca_validation == 1) { ++ if ((conf->ca = tls_load_file(conf->constraint_ca, ++ &conf->ca_len, NULL)) == NULL) ++ log_warnx("constraint: failed to load CA certificate bundle file"); ++ } ++ } ++#endif ++ ++#ifdef HAVE_OPENSSL ++ if (strcmp("openssl", conf->constraint_engine) == 0) { ++ if (OPENSSL_init_ssl(0, NULL) == 0) ++ fatalx("constraint: can't initialize OpenSSL engine"); ++ //SSL_library_init(); ++ OpenSSL_add_all_algorithms(); ++ OpenSSL_add_all_digests(); ++ SSL_load_error_strings(); ++ o_store = X509_STORE_new(); ++ ++ if (conf->constraint_ca_validation == 1) { ++ if ((conf->o_ca = X509_STORE_load_locations(o_store, conf->constraint_ca, NULL)) != 1) { ++ log_warnx("constraint: failed to load CA certificate bundle file"); ++ openssl_lasterr(); ++ } ++ } ++ } + #endif + + if (chroot(pw_dir) == -1) +@@ -420,7 +423,13 @@ priv_constraint_child(const char *pw_dir + + log_debug("constraint %s: setting HTTPS request", addr); + setproctitle("constraint %s: new HTTPS request", addr); +- (void)closefrom(CONSTRAINT_PASSFD + 1); ++ ++ /* ++ * OpenSSL requires new file descriptors which must not be deleted. ++ * This restriction does not apply to LibreSSL implementation. ++ */ ++ if (strcmp("libressl", conf->constraint_engine) == 0) ++ (void)closefrom(CONSTRAINT_PASSFD + 1); + + /* + * Set the close-on-exec flag to prevent leaking the communication +@@ -449,14 +458,32 @@ priv_constraint_child(const char *pw_dir + fatalx("constraint %s: invalid port", addr); + } + +- /* Run! */ +- if ((ctx = httpsdate_query(addr, +- &cstr.addr_head.port, cstr.addr_head.name, cstr.addr_head.path, +- conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { +- log_debug("constraint %s: failed to get proper time results", addr); +- /* Abort with failure but without warning */ +- exit(1); ++#ifdef HAVE_LIBRESSL ++ if (strcmp("libressl", conf->constraint_engine) == 0) { ++ /* Run! */ ++ log_debug("constraint %s: initializing HTTPS request", addr); ++ if ((ctx = httpsdate_query(addr, ++ &cstr.addr_head.port, cstr.addr_head.name, cstr.addr_head.path, ++ conf->ca, conf->ca_len, &rectv, &xmttv)) == NULL) { ++ log_debug("constraint %s: failed to get proper time results", addr); ++ /* Abort with failure but without warning */ ++ exit(1); ++ } + } ++#endif ++ ++#ifdef HAVE_OPENSSL ++ if (strcmp("openssl", conf->constraint_engine) == 0) { ++ /* Run! */ ++ log_debug("constraint %s: initializing HTTPS request", addr); ++ if ((ctx = o_httpsdate_query(&cstr, ++ &conf->o_ca, &rectv, &xmttv)) == NULL) { ++ log_debug("constraint %s: failed to get proper time results", addr); ++ /* Abort with failure but without warning */ ++ exit(1); ++ } ++ } ++#endif + + iov[0].iov_base = &rectv; + iov[0].iov_len = sizeof(rectv); +@@ -468,8 +495,18 @@ priv_constraint_child(const char *pw_dir + rv = imsg_flush(&cstr.ibuf); + } while (rv == -1 && errno == EAGAIN); + +- /* Tear down the TLS connection after sending the result */ +- httpsdate_free(ctx); ++/* Tear down the TLS connection after sending the result */ ++#ifdef HAVE_LIBRESSL ++ if (strcmp("libressl", conf->constraint_engine) == 0) { ++ httpsdate_free(ctx); ++ } ++#endif ++ ++#ifdef HAVE_OPENSSL ++ if (strcmp("openssl", conf->constraint_engine) == 0) { ++ o_httpsdate_free(ctx); ++ } ++#endif + + exit(0); + } +@@ -932,270 +969,6 @@ constraint_check(double val) + return (0); + } + +-struct httpsdate * +-httpsdate_init(const char *addr, const int *port, const char *hostname, +- const char *path, const u_int8_t *ca, size_t ca_len) +-{ +- struct httpsdate *httpsdate = NULL; +- char port_s[sizeof(port)]; +- +- if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL) +- goto fail; +- +- if (hostname == NULL) +- hostname = addr; +- +- sprintf(port_s, "%d", *port); +- +- if ((httpsdate->tls_addr = strdup(addr)) == NULL || +- (httpsdate->tls_port = strdup(port_s)) == NULL || +- (httpsdate->tls_hostname = strdup(hostname)) == NULL || +- (httpsdate->tls_path = strdup(path)) == NULL) +- goto fail; +- +- if (asprintf(&httpsdate->tls_request, +- "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", +- httpsdate->tls_path, httpsdate->tls_hostname) == -1) +- goto fail; +- +- if ((httpsdate->tls_config = tls_config_new()) == NULL) +- goto fail; +- if (tls_config_set_ca_mem(httpsdate->tls_config, ca, ca_len) == -1) +- goto fail; +- +- /* +- * Due to the fact that we're trying to determine a constraint for time +- * we do our own certificate validity checking, since the automatic +- * version is based on our wallclock, which may well be inaccurate... +- */ +- tls_config_insecure_noverifytime(httpsdate->tls_config); +- +- return (httpsdate); +- +- fail: +- httpsdate_free(httpsdate); +- return (NULL); +-} +- +-void +-httpsdate_free(void *arg) +-{ +- struct httpsdate *httpsdate = arg; +- if (httpsdate == NULL) +- return; +- if (httpsdate->tls_ctx) +- tls_close(httpsdate->tls_ctx); +- tls_free(httpsdate->tls_ctx); +- tls_config_free(httpsdate->tls_config); +- free(httpsdate->tls_addr); +- free(httpsdate->tls_port); +- free(httpsdate->tls_hostname); +- free(httpsdate->tls_path); +- free(httpsdate->tls_request); +- free(httpsdate); +-} +- +-int +-httpsdate_request(struct httpsdate *httpsdate, struct timeval *when) +-{ +- char timebuf1[32], timebuf2[32]; +- size_t outlen = 0, maxlength = conf->constraint_maxheaderlength, len; +- char *line, *p, *buf; +- time_t httptime, notbefore, notafter; +- struct tm *tm; +- ssize_t ret; +- +- if ((httpsdate->tls_ctx = tls_client()) == NULL) +- goto fail; +- +- if (tls_configure(httpsdate->tls_ctx, httpsdate->tls_config) == -1) +- goto fail; +- +- /* +- * libtls expects an address string, which can also be a DNS name, +- * but we pass a pre-resolved IP address string in tls_addr so it +- * does not trigger any DNS operation and is safe to be called +- * without the dns pledge. +- */ +- log_debug("constraint %s: establishing connection", httpsdate->tls_addr); +- if (tls_connect_servername(httpsdate->tls_ctx, httpsdate->tls_addr, +- httpsdate->tls_port, httpsdate->tls_hostname) == -1) { +- log_debug("constraint %s: TLS connection failed (%s): %s", +- httpsdate->tls_addr, +- httpsdate->tls_hostname, +- tls_error(httpsdate->tls_ctx) +- ); +- goto fail; +- } +- +- buf = httpsdate->tls_request; +- len = strlen(httpsdate->tls_request); +- while (len > 0) { +- ret = tls_write(httpsdate->tls_ctx, buf, len); +- if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) +- continue; +- if (ret == -1) { +- log_warnx("constraint %s: TLS write operation failed (%s): %s", +- httpsdate->tls_addr, +- httpsdate->tls_hostname, +- tls_error(httpsdate->tls_ctx) +- ); +- goto fail; +- } +- buf += ret; +- len -= ret; +- } +- +- while ((line = tls_readline(httpsdate->tls_ctx, &outlen, +- &maxlength, when)) != NULL) { +- line[strcspn(line, "\r\n")] = '\0'; +- +- if ((p = strchr(line, ' ')) == NULL || *p == '\0') +- goto next; +- *p++ = '\0'; +- if (strcasecmp("Date:", line) != 0) +- goto next; +- +- /* +- * Expect the date/time format as IMF-fixdate which is +- * mandated by HTTP/1.1 in the new RFC 7231 and was +- * preferred by RFC 2616. Other formats would be RFC 850 +- * or ANSI C's asctime() - the latter doesn't include +- * the timezone which is required here. +- */ +- if (strptime(p, IMF_FIXDATE, +- &httpsdate->tls_tm) == NULL) { +- log_warnx("constraint %s: unsupported date format", +- httpsdate->tls_addr +- ); +- free(line); +- return (-1); +- } +- +- free(line); +- break; +- next: +- free(line); +- } +- +- /* +- * Now manually check the validity of the certificate presented in the +- * TLS handshake, based on the time specified by the server's HTTP Date: +- * header. +- */ +- notbefore = tls_peer_cert_notbefore(httpsdate->tls_ctx); +- notafter = tls_peer_cert_notafter(httpsdate->tls_ctx); +- if ((httptime = timegm(&httpsdate->tls_tm)) == -1) +- goto fail; +- if (httptime <= notbefore) { +- if ((tm = gmtime(¬before)) == NULL) +- goto fail; +- if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0) +- goto fail; +- if (strftime(timebuf2, sizeof(timebuf2), X509_DATE, +- &httpsdate->tls_tm) == 0) +- goto fail; +- log_warnx("constraint %s: TLS certificate not yet valid (%s): " +- "not before %s, now is %s", httpsdate->tls_addr, +- httpsdate->tls_hostname, timebuf1, timebuf2); +- goto fail; +- } +- if (httptime >= notafter) { +- if ((tm = gmtime(¬after)) == NULL) +- goto fail; +- if (strftime(timebuf1, sizeof(timebuf1), X509_DATE, tm) == 0) +- goto fail; +- if (strftime(timebuf2, sizeof(timebuf2), X509_DATE, +- &httpsdate->tls_tm) == 0) +- goto fail; +- log_warnx("constraint %s: TLS certificate has been expired (%s): " +- "not after %s, now is %s", httpsdate->tls_addr, +- httpsdate->tls_hostname, timebuf1, timebuf2); +- goto fail; +- } +- +- return (0); +- +- fail: +- httpsdate_free(httpsdate); +- return (-1); +-} +- +-void * +-httpsdate_query(const char *addr, const int *port, const char *hostname, +- const char *path, const u_int8_t *ca, size_t ca_len, +- struct timeval *rectv, struct timeval *xmttv) +-{ +- struct httpsdate *httpsdate; +- struct timeval when; +- time_t t; +- +- if ((httpsdate = httpsdate_init(addr, port, hostname, path, +- ca, ca_len)) == NULL) +- return (NULL); +- +- if (httpsdate_request(httpsdate, &when) == -1) +- return (NULL); +- +- /* Return parsed date as local time */ +- t = timegm(&httpsdate->tls_tm); +- +- /* Report parsed Date: as "received time" */ +- rectv->tv_sec = t; +- rectv->tv_usec = 0; +- +- /* And add delay as "transmit time" */ +- xmttv->tv_sec = when.tv_sec; +- xmttv->tv_usec = when.tv_usec; +- +- return (httpsdate); +-} +- +-/* Based on SSL_readline in ftp/fetch.c */ +-char * +-tls_readline(struct tls *tls, size_t *lenp, size_t *maxlength, +- struct timeval *when) +-{ +- size_t i, len; +- char *buf, *q, c; +- ssize_t ret; +- +- len = 128; +- if ((buf = malloc(len)) == NULL) +- fatal("constraint: can't allocate memory for TLS transfer buffer"); +- for (i = 0; ; i++) { +- if (i >= len - 1) { +- if ((q = reallocarray(buf, len, 2)) == NULL) +- fatal("constraint: can't expand TLS transfer buffer"); +- buf = q; +- len *= 2; +- } +- again: +- ret = tls_read(tls, &c, 1); +- if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) +- goto again; +- if (ret == -1) { +- /* SSL read error, ignore */ +- free(buf); +- return (NULL); +- } +- +- if (maxlength != NULL && (*maxlength)-- == 0) { +- log_warnx("constraint: maximum HTTP header length exceeded"); +- free(buf); +- return (NULL); +- } +- +- buf[i] = c; +- if (c == '\n') +- break; +- } +- *lenp = i; +- if (gettimeofday(when, NULL) == -1) +- fatal("constraint: can't get a valid time stamp"); +- return (buf); +-} +- + char * + get_string(u_int8_t *ptr, size_t len) + { +--- /dev/null 2020-07-26 15:23:52.401078754 +0300 ++++ b/src/constraint-openssl.c 2020-08-01 19:56:30.010263450 +0300 +@@ -0,0 +1,329 @@ ++/* ++ * Copyright (c) 2015 Reyk Floeter ++ * Copyright (c) 2020 Pekka Helenius ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "ntpd.h" ++ ++struct o_httpsdate * ++o_httpsdate_init(struct constraint *cstr, const int *ca) ++{ ++ struct o_httpsdate *httpsdate = NULL; ++ ++ if ((httpsdate = calloc(1, sizeof(*httpsdate))) == NULL) ++ goto fail; ++ ++ if ((httpsdate->cstr = cstr) == NULL) ++ goto fail; ++ ++ if (asprintf(&httpsdate->tls_request, ++ "HEAD %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", ++ httpsdate->cstr->addr_head.path, ++ httpsdate->cstr->addr_head.name) == -1) ++ goto fail; ++ ++ if ((httpsdate->tls_method = TLS_method()) == NULL) ++ goto fai \ No newline at end of file diff --git a/patches/8-patch_update-conf.patch b/patches/8-patch_update-conf.patch new file mode 100644 index 0000000..f90885b --- /dev/null +++ b/patches/8-patch_update-conf.patch @@ -0,0 +1,344 @@ +From: Pekka Helenius +Date: Sun, 02 Aug 2020 14:12:40 +0300 +Subject: Update default configuration file + + +--- a/ntpd.conf 2020-07-31 23:00:50.000000000 +0300 ++++ b/ntpd.conf 2020-08-02 02:30:41.706954890 +0300 +@@ -1,11 +1,330 @@ +-# $OpenBSD: ntpd.conf,v 1.16 2019/11/06 19:04:12 deraadt Exp $ +-# + # See ntpd.conf(5) and /etc/examples/ntpd.conf + ++# BASIC KEYWORDS ++ ++# listen on 127.0.0.1 port 123 ++ + servers pool.ntp.org +-server time.cloudflare.com +-sensor * ++server time.cloudflare.com ++sensor * + +-constraint from "9.9.9.9" # quad9 v4 without DNS +-constraint from "2620:fe::fe" # quad9 v6 without DNS ++constraint from "9.9.9.9" # quad9 v4 without DNS ++constraint from "2620:fe::fe" # quad9 v6 without DNS + constraints from "www.google.com" # intentionally not 8.8.8.8 ++ ++constraints from "https://www.duckduckgo.com" port 443 ++ ++# ADVANCED KEYWORDS ++ ++# During OpenNTPD initialization, all NTP peers get ++# automatic time offset value, if pre-conditions for ++# automatic interval adjustment are being met. ++# The conditions are as follows: OpenNTPD configuration ++# has constraints, trusted NTP peers or trusted sensors ++# and current internally defined process security level ++# is 0. In this case, initial time offset value is set ++# to 1 which, in return, triggers automatic offset calculation. ++# ++# In the automatic offset calculation, a trusted NTP ++# peer offset values are being counted for each peer. ++# For each peer an independent pool size is determined ++# by auto_replies value, ignoring the last value. ++# For instance, with auto_replies value 4, first ++# 3 NTP peer offset values are considered for a single ++# NTP peer, and a median offset value of these collected ++# 3 offset values is calculated and used for time adjustment. ++# ++# auto_replies 4 ++ ++# In OpenNTPD initial automatic time offset calculation, ++# three conditions are being considered for NTP peers: ++# is a NTP peer trusted and current overall constraint-based ++# median offset not 0, and whether an initial NTP peer ++# time offset exceeds value of auto_threshold . If these ++# conditions are met, then auto_threshold value may be ++# considered. If NTP peer current time offset value is ++# less than auto_threshold , then the system time offset ++# value is considered to be already OK, and OpenNTPD stops ++# calculating automatic offset value from further NTP peer ++# queries. In this case, median offset value is not calculated. ++# ++# auto_threshold 60 ++ ++# In automatic NTP peer offset calculation mode (during OpenNTPD ++# initialization), if NTP peer IP address is still unresolved ++# (unknown), the next query is attempted in interval_auto_dnsfail ++# seconds. Applies to unresolved constraint IP addresses, as well. ++# ++# interval_auto_dnsfail 1 ++ ++# Maximum number of attempts to resolve a constraint IP address(es) ++# with a DNS query before falling back from constraint_retry_interval ++# to interval_auto_dnsfail in constraint initialization. ++# ++# tries_auto_dnsfail 4 ++ ++# PEM-formatted certificate bundle file ++# for constraint HTTPS connections. ++# ++# constraint_ca /etc/ssl/cert.pem ++ ++# Whether to validate constraint HTTPS ++# server certificate. ++# ++# constraint_ca_validation true ++ ++# Use either LibreSSL (libressl) or OpenSSL (openssl) ++# for constraint HTTPS server connections. To ++# support chosen TLS engine, ntpd(8) must be ++# compiled and run with proper libraries installed ++# on the system. Only LibreSSL and OpenSSL are ++# supported. ++# ++# constraint_engine libressl ++ ++# Accepted number of errors during constraint ++# process. If error count exceeds this value ++# multiplied by calculated peer count, ++# constraint connection will be reseted and ++# a new constraint is retrieved. ++# ++# constraint_error_margin 4 ++ ++# Acceptable time difference between retrieved ++# HTTP header time value and calculated time ++# value in seconds. HTTP header time values ++# exceeding this margin value will be ignored. ++# ++# constraint_margin 120 ++ ++# Maximum allowed HTTP header length of constraint ++# HTTPS server reply to be fetched in bytes. If ++# the value is exceeded during processing, nothing ++# is returned and constraint check fails. ++# ++# constraint_max_headerlength 8192 ++ ++# Constraint HTTPS servers scan interval in seconds. ++# ++# constraint_scan_interval 900 ++ ++# Maximum connection establishment time to a ++# constraint HTTPS server in seconds. ++# ++# constraint_scan_timeout 10 ++ ++# ntpd(8) socket file path. ++# ++# ctlsocket /var/run/ntpd.sock ++ ++# ntpd(8) drift file path. ++# ++# driftfile /var/db/ntpd.drift ++ ++# Whether to reset frequency filters after ++# frequency adjustment. ++# ++# filter_adjfreq true ++ ++# Number of frequency samples for estimating ++# permanent drift value. ++# ++# frequency_samples 8 ++ ++# Initial trust level for a new, timed out or ++# erroneous remote NTP server. Every received ++# and non-discarded reply increases trust for ++# the server. The trust level is used for ++# setting used interval_query_* value for the ++# server and keeping track of valid remote NTP ++# servers. ++# ++# A server having this trust level uses remote ++# NTP query interval value interval_query_aggressive . ++# ++# trustlevel_pathetic 2 ++ ++# If a replying remote NTP server has trust level ++# one number less than this value, the server gets ++# trusted. In this case, the server can achieve ++# maximum trust level trustlevel_max . This trust ++# level is preceded by trust level trustlevel_pathetic ++# and followed by trust level trustlevel_aggressive . ++# ++# A NTP server having trust level value trustlevel_badpeer , ++# or value greater than trustlevel_pathetic but less than ++# trustlevel_aggressive uses remote NTP query interval ++# value interval_query_aggressive . ++# ++# In a case of NTP server reply time out, if the server ++# has at least trust level value trustlevel_badpeer ++# and the trust level value divided by 2 is less than ++# the trustlevel_badpeer value, the server will be ++# invalidated and falls back to initial trust level ++# trustlevel_pathetic . ++# ++# trustlevel_badpeer 6 ++ ++# Aggressive trust level is preceded by trust level ++# trustlevel_badpeer and followed by trust level ++# trustlevel_max . If a remote NTP server current trust ++# level is at least value of trustlevel_pathetic but ++# less than this value, used remote NTP query interval ++# is determined by value interval_query_aggressive . ++# A server with exact trust level trustlevel_aggressive ++# uses query interval interval_query_normal ++# (see trustlevel_max below). ++# ++# trustlevel_aggressive 8 ++ ++# Maximum trust level follows trust level trustlevel_aggressive . ++# This is the maximum trust level which a remote NTP ++# server can achieve. A server having at least trust ++# level trustlevel_aggressive uses remote NTP query ++# interval value interval_query_normal . ++# ++# trustlevel_max 10 ++ ++# Remote NTP server query interval in seconds for servers with ++# a trust level value greater than trustlevel_pathetic but less ++# than trustlevel_aggressive in a case where a NTP peer does not ++# still have large enough pool of already queried offset time values ++# for its offset time median calculation (checked against value ++# auto replies ) or is not trusted , interval value ++# interval_query_ultra_violence may be triggered. ++# Applies only to NTP offset calculation automatic mode. ++# ++# In most cases, interval_query_aggressive is used instead. ++# Dynamic offset scale value factors qscale_off_min and qscale_off_max ++# are ignored. ++# ++# interval_query_ultra_violence 1 ++ ++# Remote NTP server query interval in seconds for ++# servers with a trust level value less than trustlevel_pathetic . ++# Practically never used. ++# ++# This value is not the final query interval value but ++# used in a combination with a dynamic offset scale value, ++# determined by qscale_off_min and qscale_off_max . ++# ++# trustlevel_query_pathetic 60 ++ ++# Remote NTP server query interval in seconds for servers ++# with a trust level value greater than trustlevel_pathetic ++# but less than trustlevel_aggressive . Since all servers ++# start with a value trustlevel_pathetic , it means that ++# this is the initial value used for all new, timed out ++# or erroneous NTP servers. ++# ++# This value is not the final query interval value but ++# used in a combination with a dynamic offset scale value, ++# determined by qscale_off_min and qscale_off_max . ++# ++# trustlevel_query_aggressive 5 ++ ++# Remote NTP server query interval in seconds for servers ++# with a trust level value between trustlevel_aggressive ++# and trustlevel_max . ++# ++# This value is not the final query interval value but ++# used in a combination with a dynamic offset scale value, ++# determined by qscale_off_min and qscale_off_max . ++# ++# trustlevel_query_normal 30 ++ ++# Retry time in seconds after failed connection attempt ++# to a remote NTP server. ++# ++# interval_query_timeout 300 ++ ++# Negligible frequency rate to not log in PPM. ++# ++# log_negligible_adjfreq 0.05 ++ ++# Negligible drift time to not log in milliseconds. ++# ++# log_negligible_adjtime 32 ++ ++# Maximum number of characters in a ntpctl(8) ++# report line (peers, status, sensors and all). ++# ++# max_display_width 80 ++ ++# Maximum allowed frequency correction per iteration. ++# ++# max_frequency_adjust 0.0128 ++ ++# Maximum number of errors tolerated before reconnecting ++# to a remote NTP server. ++# ++# max_send_errors 3 ++ ++# Maximum number of remote NTP server IP addresses ++# fetched per DNS query. ++# ++# max_servers_dns 8 ++ ++# ntpd(8) process user name. Group name and working ++# directory are internally fetched by getpwnam(3) . ++# ++# ntpd_user ntp ++ ++# Minimum scale value used for dynamically adjusting ++# NTP server query interval time. If median NTP server ++# & sensor offset value is lower than this value, then ++# this value is used for scale calculation as minimum value. ++# Otherwise, the offset value is used as minimum value. ++# The offset value is a combined median value, based on ++# all NTP server & sensor offset values. ++# ++# The determined frequency scale is ++# qscale_off_max / { qscale_off_min OR median offset } . ++# ++# In the end, the calculated scale value is multiplied ++# one of interval_query_* values (pathetic, aggressive, normal) ++# on a client side, and ultimately used for dynamic ++# adjustment of client-side NTP server query interval time ++# for ntpd(8) process. ++# ++# qscale_off_min 0.001 ++ ++# Maximum scale value used for dynamically adjusting ++# NTP server query interval time. This value is used ++# either with a median NTP server & sensor offset value, ++# described in qscale_off_min section, or directly with ++# the value of qscale_off_min . The more detailed description ++# about further use of this value is above and ++# in interval_query_* sections. ++# ++# qscale_off_max 0.050 ++ ++# Maximum time reserved for a single NTP server query ++# in seconds. ++# ++# querytime_max 15 ++ ++# Sensor data maximum valid age in seconds. ++# ++# sensor_data_maxage 900 ++ ++# Sensor default reference ID string. ++# ++# sensor_default_refid "HARD" ++ ++# Maximum allowed sensor time offset in seconds. ++# ++# sensor_offsets 6 ++ ++# Sensor query interval in seconds. ++# ++# sensor_query_interval 15 ++ ++# Scan interval for new sensors in seconds. ++# ++# sensor_scan_interval 60 ++ ++# Maximum time to wait for a constraint to reply ++# during OpenNTPD initial automatic mode. ++# ++# settime_timeout 100