From 2c0d96f3909543af0988811fd503fcb24a97185f Mon Sep 17 00:00:00 2001 From: reyk <> Date: Thu, 12 Feb 2015 01:54:57 +0000 Subject: [PATCH] Use ntpd's deferred DNS resolving for constraints as well. This allows to get constraint addresses even if network/DNS is not available at startup (or system boot). thumbs up & OK henning@ --- src/usr.sbin/ntpd/client.c | 4 +- src/usr.sbin/ntpd/constraint.c | 142 +++++++++++++++++++++++++++------ src/usr.sbin/ntpd/ntp.c | 13 ++- src/usr.sbin/ntpd/ntp_dns.c | 14 +++- src/usr.sbin/ntpd/ntpd.h | 6 +- src/usr.sbin/ntpd/parse.y | 19 +---- 6 files changed, 147 insertions(+), 51 deletions(-) diff --git a/src/usr.sbin/ntpd/client.c b/src/usr.sbin/ntpd/client.c index 06c5e924..bf7cdd0e 100644 --- a/src/usr.sbin/ntpd/client.c +++ b/src/usr.sbin/ntpd/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.99 2015/02/10 06:40:08 reyk Exp $ */ +/* $OpenBSD: client.c,v 1.100 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -107,7 +107,7 @@ client_nextaddr(struct ntp_peer *p) return (-1); if (p->addr_head.a == NULL) { - priv_host_dns(p->addr_head.name, p->id); + priv_dns(IMSG_HOST_DNS, p->addr_head.name, p->id); p->state = STATE_DNS_INPROGRESS; return (-1); } diff --git a/src/usr.sbin/ntpd/constraint.c b/src/usr.sbin/ntpd/constraint.c index 5272cdf1..8e0b2974 100644 --- a/src/usr.sbin/ntpd/constraint.c +++ b/src/usr.sbin/ntpd/constraint.c @@ -1,4 +1,4 @@ -/* $OpenBSD: constraint.c,v 1.3 2015/02/10 23:52:41 reyk Exp $ */ +/* $OpenBSD: constraint.c,v 1.4 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2015 Reyk Floeter @@ -43,6 +43,8 @@ #include "ntpd.h" int constraint_addr_init(struct constraint *); +struct constraint * + constraint_byid(u_int32_t); struct constraint * constraint_byfd(int); struct constraint * @@ -51,6 +53,8 @@ int constraint_close(int); void constraint_update(void); void constraint_reset(void); int constraint_cmp(const void *, const void *); +void constraint_add(struct constraint *); +void constraint_remove(struct constraint *); struct httpsdate * httpsdate_init(const char *, const char *, const char *, @@ -63,6 +67,8 @@ void *httpsdate_query(const char *, const char *, const char *, char *tls_readline(struct tls *, size_t *, size_t *, struct timeval *); +extern u_int constraint_cnt; + struct httpsdate { char *tls_host; char *tls_port; @@ -91,31 +97,37 @@ constraint_addr_init(struct constraint *cstr) struct sockaddr_in *sa_in; struct sockaddr_in6 *sa_in6; struct ntp_addr *h; - int cnt = 0; - - for (h = cstr->addr; h != NULL; h = h->next) { - switch (h->ss.ss_family) { - case AF_INET: - sa_in = (struct sockaddr_in *)&h->ss; - if (ntohs(sa_in->sin_port) == 0) - sa_in->sin_port = htons(443); - 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); - cstr->state = STATE_DNS_DONE; - break; - default: - /* XXX king bula sez it? */ - fatalx("wrong AF in constraint_addr_init"); - /* NOTREACHED */ - } - cnt++; + + if (cstr->state == STATE_DNS_INPROGRESS) + return (0); + + if (cstr->addr_head.a == NULL) { + priv_dns(IMSG_CONSTRAINT_DNS, cstr->addr_head.name, cstr->id); + cstr->state = STATE_DNS_INPROGRESS; + return (0); + } + + h = cstr->addr; + switch (h->ss.ss_family) { + case AF_INET: + sa_in = (struct sockaddr_in *)&h->ss; + if (ntohs(sa_in->sin_port) == 0) + sa_in->sin_port = htons(443); + 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); + cstr->state = STATE_DNS_DONE; + break; + default: + /* XXX king bula sez it? */ + fatalx("wrong AF in constraint_addr_init"); + /* NOTREACHED */ } - return (cnt); + return (1); } int @@ -134,6 +146,10 @@ constraint_query(struct constraint *cstr) case STATE_DNS_DONE: /* Proceed and query the time */ break; + case STATE_DNS_TEMPFAIL: + /* Retry resolving the address */ + constraint_init(cstr); + return (-1); case STATE_QUERY_SENT: if (cstr->last + CONSTRAINT_SCAN_TIMEOUT > now) { /* The caller should expect a reply */ @@ -277,6 +293,19 @@ constraint_check_child(void) } while (pid > 0 || (pid == -1 && errno == EINTR)); } +struct constraint * +constraint_byid(u_int32_t id) +{ + struct constraint *cstr; + + TAILQ_FOREACH(cstr, &conf->constraints, entry) { + if (cstr->id == id) + return (cstr); + } + + return (NULL); +} + struct constraint * constraint_byfd(int fd) { @@ -326,6 +355,23 @@ constraint_close(int fd) return (1); } +void +constraint_add(struct constraint *cstr) +{ + TAILQ_INSERT_TAIL(&conf->constraints, cstr, entry); + constraint_cnt += constraint_init(cstr); +} + +void +constraint_remove(struct constraint *cstr) +{ + TAILQ_REMOVE(&conf->constraints, cstr, entry); + free(cstr->addr_head.name); + free(cstr->addr_head.path); + free(cstr); + constraint_cnt--; +} + int constraint_dispatch_msg(struct pollfd *pfd) { @@ -383,6 +429,54 @@ constraint_dispatch_msg(struct pollfd *pfd) return (0); } +void +constraint_dns(u_int32_t id, u_int8_t *data, size_t len) +{ + struct constraint *cstr, *ncstr; + u_int8_t *p; + struct ntp_addr *h; + + if ((cstr = constraint_byid(id)) == NULL) { + log_warnx("IMSG_CONSTRAINT_DNS with invalid constraint id"); + return; + } + if (cstr->addr != NULL) { + log_warnx("IMSG_CONSTRAINT_DNS but addr != NULL!"); + return; + } + if (len == 0) { + log_debug("%s FAILED", __func__); + cstr->state = STATE_DNS_TEMPFAIL; + return; + } + + if ((len % sizeof(struct sockaddr_storage)) != 0) + fatalx("IMSG_CONSTRAINT_DNS len"); + + p = data; + do { + if ((h = calloc(1, sizeof(*h))) == NULL) + fatal("calloc ntp_addr"); + memcpy(&h->ss, p, sizeof(h->ss)); + p += sizeof(h->ss); + len -= sizeof(h->ss); + + ncstr = new_constraint(); + ncstr->addr = h; + ncstr->addr_head.a = h; + ncstr->addr_head.name = strdup(cstr->addr_head.name); + ncstr->addr_head.path = strdup(cstr->addr_head.path); + if (ncstr->addr_head.name == NULL || + ncstr->addr_head.path == NULL) + fatal("calloc name"); + ncstr->addr_head.pool = cstr->addr_head.pool; + + constraint_add(ncstr); + } while (len && cstr->addr_head.pool); + + constraint_remove(cstr); +} + int constraint_cmp(const void *a, const void *b) { diff --git a/src/usr.sbin/ntpd/ntp.c b/src/usr.sbin/ntpd/ntp.c index 76629af5..a836f4ca 100644 --- a/src/usr.sbin/ntpd/ntp.c +++ b/src/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.128 2015/02/10 06:40:08 reyk Exp $ */ +/* $OpenBSD: ntp.c,v 1.129 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -49,6 +49,7 @@ struct ntpd_conf *conf; struct ctl_conns ctl_conns; u_int peer_cnt; u_int sensors_cnt; +u_int constraint_cnt; time_t lastreport; void ntp_sighdlr(int); @@ -84,7 +85,7 @@ ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, int ctls, boundaries; u_int pfd_elms = 0, idx2peer_elms = 0; u_int listener_cnt, new_cnt, sent_cnt, trial_cnt; - u_int ctl_cnt, constraint_cnt; + u_int ctl_cnt; pid_t pid; struct pollfd *pfd = NULL; struct servent *se; @@ -582,6 +583,10 @@ ntp_dispatch_imsg_dns(void) else client_addr_init(peer); break; + case IMSG_CONSTRAINT_DNS: + constraint_dns(imsg.hdr.peerid, + imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE); + break; default: break; } @@ -762,12 +767,12 @@ priv_settime(double offset) } void -priv_host_dns(char *name, u_int32_t peerid) +priv_dns(int cmd, char *name, u_int32_t peerid) { u_int16_t dlen; dlen = strlen(name) + 1; - imsg_compose(ibuf_dns, IMSG_HOST_DNS, peerid, 0, -1, name, dlen); + imsg_compose(ibuf_dns, cmd, peerid, 0, -1, name, dlen); } void diff --git a/src/usr.sbin/ntpd/ntp_dns.c b/src/usr.sbin/ntpd/ntp_dns.c index 37dea75b..08cdb13f 100644 --- a/src/usr.sbin/ntpd/ntp_dns.c +++ b/src/usr.sbin/ntpd/ntp_dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp_dns.c,v 1.8 2015/01/21 03:14:10 bcook Exp $ */ +/* $OpenBSD: ntp_dns.c,v 1.9 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2003-2008 Henning Brauer @@ -129,6 +129,7 @@ dns_dispatch_imsg(void) char *name; struct ntp_addr *h, *hn; struct ibuf *buf; + const char *str; if ((n = imsg_read(ibuf_dns)) == -1) return (-1); @@ -147,16 +148,21 @@ dns_dispatch_imsg(void) switch (imsg.hdr.type) { case IMSG_HOST_DNS: + case IMSG_CONSTRAINT_DNS: + if (imsg.hdr.type == IMSG_HOST_DNS) + str = "IMSG_HOST_DNS"; + else + str = "IMSG_CONSTRAINT_DNS"; name = imsg.data; if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) - fatalx("invalid IMSG_HOST_DNS received"); + fatalx("invalid %s received", str); imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; if (name[imsg.hdr.len] != '\0' || strlen(name) != imsg.hdr.len) - fatalx("invalid IMSG_HOST_DNS received"); + fatalx("invalid %s received", str); if ((cnt = host_dns(name, &hn)) == -1) break; - buf = imsg_create(ibuf_dns, IMSG_HOST_DNS, + buf = imsg_create(ibuf_dns, imsg.hdr.type, imsg.hdr.peerid, 0, cnt * sizeof(struct sockaddr_storage)); if (cnt > 0) { diff --git a/src/usr.sbin/ntpd/ntpd.h b/src/usr.sbin/ntpd/ntpd.h index 9c65ee2d..1ffd46a2 100644 --- a/src/usr.sbin/ntpd/ntpd.h +++ b/src/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.118 2015/02/10 06:40:08 reyk Exp $ */ +/* $OpenBSD: ntpd.h,v 1.119 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -280,6 +280,7 @@ enum imsg_type { IMSG_SETTIME, IMSG_HOST_DNS, IMSG_CONSTRAINT, + IMSG_CONSTRAINT_DNS, IMSG_CTL_SHOW_STATUS, IMSG_CTL_SHOW_PEERS, IMSG_CTL_SHOW_PEERS_END, @@ -302,7 +303,7 @@ enum ctl_actions { pid_t ntp_main(int[2], int, struct ntpd_conf *, struct passwd *); int priv_adjtime(void); void priv_settime(double); -void priv_host_dns(char *, u_int32_t); +void priv_dns(int, char *, u_int32_t); int offset_compare(const void *, const void *); void update_scale(double); time_t scale_interval(time_t); @@ -345,6 +346,7 @@ int constraint_query(struct constraint *); int constraint_dispatch_msg(struct pollfd *); void constraint_check_child(void); int constraint_check(double); +void constraint_dns(u_int32_t, u_int8_t *, size_t); /* util.c */ double gettime_corrected(void); diff --git a/src/usr.sbin/ntpd/parse.y b/src/usr.sbin/ntpd/parse.y index 01c35234..e5b403b4 100644 --- a/src/usr.sbin/ntpd/parse.y +++ b/src/usr.sbin/ntpd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.59 2015/02/10 11:46:39 reyk Exp $ */ +/* $OpenBSD: parse.y,v 1.60 2015/02/12 01:54:57 reyk Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer @@ -251,11 +251,10 @@ main : LISTEN ON address listen_opts { } | CONSTRAINT FROM url { struct constraint *p; - struct ntp_addr *h, *next; + struct ntp_addr *h; p = new_constraint(); - for (h = $3->a; h != NULL; h = next) { - next = h->next; + if ((h = $3->a) != NULL) { if (h->ss.ss_family != AF_INET && h->ss.ss_family != AF_INET6) { yyerror("IPv4 or IPv6 address " @@ -267,8 +266,8 @@ main : LISTEN ON address listen_opts { free($3); YYERROR; } - h->next = p->addr; p->addr = h; + host_dns_free(h->next); } p->addr_head.a = p->addr; @@ -332,16 +331,6 @@ url : STRING { if (($$->name = strdup(hname)) == NULL) fatal("strdup"); } - - if ($$->a == NULL && - (host_dns($$->name, &$$->a) == -1 || - $$->a == NULL)) { - yyerror("could not resolve \"%s\"", $$->name); - free($$->name); - free($$->path); - free($$); - YYERROR; - } } ;