From: Dave Hart Date: Tue, 9 Feb 2010 18:19:12 +0000 (+0000) Subject: [Bug 1483] hostname in ntp.conf "restrict" parameter rejected. X-Git-Tag: NTP_4_2_7P20~1^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8b0855993ddaccb3d2a72d383715f987dc52430;p=thirdparty%2Fntp.git [Bug 1483] hostname in ntp.conf "restrict" parameter rejected. Use all addresses for each restrict by hostname. Use async DNS to resolve trap directive hostnames. bk: 4b71a720C2RskVESWsb7TTBU3D5Gag --- diff --git a/ChangeLog b/ChangeLog index 92e8a7828..c34deb26f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +* [Bug 1483] hostname in ntp.conf "restrict" parameter rejected. +* Use all addresses for each restrict by hostname. +* Use async DNS to resolve trap directive hostnames. (4.2.7p18) 2010/02/07 Released by Harlan Stenn * Include (4.2.6p1-RC5) - [Bug 1480] snprintf() cleanup caused unterminated refclock IDs. diff --git a/include/ntp_config.h b/include/ntp_config.h index bb002415b..af21cdd40 100644 --- a/include/ntp_config.h +++ b/include/ntp_config.h @@ -76,8 +76,8 @@ struct attr_val { /* Structure for nodes on the syntax tree */ struct address_node { - char *address; - int type; + char *address; + short type; /* family, AF_UNSPEC (0), AF_INET, AF_INET6 */ }; struct restrict_node { @@ -198,6 +198,17 @@ struct REMOTE_CONFIG_INFO { int no_errors; }; + +/* + * context for trap_name_resolved() to call ctlsettrap() once the + * name->address resolution completes. + */ +typedef struct settrap_parms_tag { + sockaddr_u ifaddr; + int ifaddr_nonnull; +} settrap_parms; + + /* get text from T_ tokens */ const char * token_name(int token); diff --git a/include/ntp_stdlib.h b/include/ntp_stdlib.h index f88965eb0..2340bac1d 100644 --- a/include/ntp_stdlib.h +++ b/include/ntp_stdlib.h @@ -102,6 +102,10 @@ extern sockaddr_u * netof (sockaddr_u *); extern char * numtoa (u_int32); extern char * numtohost (u_int32); extern char * socktoa (sockaddr_u *); +#define localaddrtoa(pif) ((NULL == (pif)) \ + ? "" \ + : socktoa(&((pif)->sin))) +#define latoa(pif) localaddrtoa(pif) extern char * socktohost (sockaddr_u *); extern int octtoint (const char *, u_long *); extern u_long ranp2 (int); diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index 45ae1b6d5..da3b7e31c 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -269,6 +269,9 @@ void peer_name_resolved(int, int, void *, const char *, const char *, void unpeer_name_resolved(int, int, void *, const char *, const char *, const struct addrinfo *, const struct addrinfo *); +void trap_name_resolved(int, int, void *, const char *, const char *, + const struct addrinfo *, + const struct addrinfo *); #endif enum gnn_type { @@ -1195,11 +1198,13 @@ create_address_node( struct address_node *my_node; NTP_REQUIRE(NULL != addr); + NTP_REQUIRE(AF_INET == type || + AF_INET6 == type || AF_UNSPEC == type); my_node = get_node(sizeof *my_node); my_node->address = addr; - my_node->type = type; + my_node->type = (short)type; return my_node; } @@ -2062,6 +2067,10 @@ config_access( int * curr_flag; sockaddr_u addr_sock; sockaddr_u addr_mask; + struct addrinfo hints; + struct addrinfo * ai_list; + struct addrinfo * pai; + int rc; int flags; int mflags; int restrict_default; @@ -2105,6 +2114,8 @@ config_access( my_node = next_node(my_node)) { ZERO_SOCK(&addr_sock); + ai_list = NULL; + pai = NULL; if (NULL == my_node->addr) { /* @@ -2120,11 +2131,41 @@ config_access( if (getnetnum(my_node->addr->address, &addr_sock, 1, t_UNK) != 1) { - - msyslog(LOG_ERR, - "restrict: error in address '%s' on line %d. Ignoring...", - my_node->addr->address, my_node->line_no); - continue; + /* + * Attempt a blocking lookup. This + * is in violation of the nonblocking + * design of ntpd's mainline code. The + * alternative of running without the + * restriction until the name resolved + * seems worse. + * Ideally some scheme could be used for + * restrict directives in the startup + * ntp.conf to delay starting up the + * protocol machinery until after all + * restrict hosts have been resolved. + */ + ai_list = NULL; + memset(&hints, 0, sizeof(hints)); + hints.ai_protocol = IPPROTO_UDP; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_family = my_node->addr->type; + rc = getaddrinfo(my_node->addr->address, + "ntp", &hints, + &ai_list); + if (rc) { + msyslog(LOG_ERR, + "restrict: ignoring line %d, address/host '%s' unusable.", + my_node->line_no, + my_node->addr->address); + continue; + } + NTP_INSIST(ai_list != NULL); + pai = ai_list; + NTP_INSIST(pai->ai_addr != NULL); + NTP_INSIST(sizeof(addr_sock) >= pai->ai_addrlen); + memcpy(&addr_sock, pai->ai_addr, pai->ai_addrlen); + NTP_INSIST(AF_INET == AF(&addr_sock) || + AF_INET6 == AF(&addr_sock)); } SET_HOSTMASK(&addr_mask, AF(&addr_sock)); @@ -2133,11 +2174,12 @@ config_access( if (my_node->mask) { ZERO_SOCK(&addr_mask); AF(&addr_mask) = (u_short)my_node->mask->type; - if (getnetnum(my_node->mask->address, &addr_mask, 1, t_MSK) != 1) { - + if (getnetnum(my_node->mask->address, + &addr_mask, 1, t_MSK) != 1) { msyslog(LOG_ERR, - "restrict: error in mask '%s' on line %d. Ignoring...", - my_node->mask->address, my_node->line_no); + "restrict: ignoring line %d, mask '%s' unusable.", + my_node->line_no, + my_node->mask->address); continue; } } @@ -2217,14 +2259,30 @@ config_access( /* Set the flags */ if (restrict_default) { AF(&addr_sock) = AF_INET; - hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask, - mflags, flags); - + AF(&addr_mask) = AF_INET; + hack_restrict(RESTRICT_FLAGS, &addr_sock, + &addr_mask, mflags, flags); AF(&addr_sock) = AF_INET6; + AF(&addr_mask) = AF_INET6; } - hack_restrict(RESTRICT_FLAGS, &addr_sock, &addr_mask, - mflags, flags); + do { + hack_restrict(RESTRICT_FLAGS, &addr_sock, + &addr_mask, mflags, flags); + if (pai != NULL && + NULL != (pai = pai->ai_next)) { + NTP_INSIST(pai->ai_addr != NULL); + NTP_INSIST(sizeof(addr_sock) >= pai->ai_addrlen); + ZERO_SOCK(&addr_sock); + memcpy(&addr_sock, pai->ai_addr, pai->ai_addrlen); + NTP_INSIST(AF_INET == AF(&addr_sock) || + AF_INET6 == AF(&addr_sock)); + SET_HOSTMASK(&addr_mask, AF(&addr_sock)); + } + } while (pai != NULL); + + if (ai_list != NULL) + freeaddrinfo(ai_list); if ((RES_MSSNTP & flags) && !warned_signd) { warned_signd = 1; @@ -2819,8 +2877,12 @@ config_trap( sockaddr_u peeraddr; struct address_node *addr_node; struct interface *localaddr; - u_short port_no; + struct addrinfo hints; + char port_text[8]; + settrap_parms *pstp; + u_short port; int err_flag; + int rc; /* silence warning about addr_sock potentially uninitialized */ AF(&addr_sock) = AF_UNSPEC; @@ -2830,7 +2892,7 @@ config_trap( curr_trap = next_node(curr_trap)) { err_flag = 0; - port_no = 0; + port = 0; localaddr = NULL; curr_opt = queue_head(curr_trap->options); @@ -2844,7 +2906,7 @@ config_trap( curr_opt->value.i); err_flag = 1; } - port_no = (u_short)curr_opt->value.i; + port = (u_short)curr_opt->value.i; } else if (T_Interface == curr_opt->attr) { addr_node = curr_opt->value.p; @@ -2875,13 +2937,52 @@ config_trap( * and port number */ if (!err_flag) { + if (!port) + port = TRAPPORT; ZERO_SOCK(&peeraddr); - if (1 != getnetnum(curr_trap->addr->address, - &peeraddr, 1, t_UNK)) + rc = getnetnum(curr_trap->addr->address, + &peeraddr, 1, t_UNK); + if (1 != rc) { +#ifndef WORKER + msyslog(LOG_ERR, + "trap: unable to use IP address %s.", + curr_trap->addr->address); +#else /* WORKER follows */ + /* + * save context and hand it off + * for name resolution. + */ + memset(&hints, 0, sizeof(hints)); + hints.ai_protocol = IPPROTO_UDP; + hints.ai_socktype = SOCK_DGRAM; + snprintf(port_text, sizeof(port_text), + "%u", port); + hints.ai_flags = AI_NUMERICSERV; + pstp = emalloc(sizeof(*pstp)); + memset(pstp, 0, sizeof(*pstp)); + if (localaddr != NULL) { + hints.ai_family = localaddr->family; + pstp->ifaddr_nonnull = 1; + memcpy(&pstp->ifaddr, + &localaddr->sin, + sizeof(pstp->ifaddr)); + } + rc = getaddrinfo_sometime( + curr_trap->addr->address, + port_text, + &hints, + &trap_name_resolved, + pstp); + if (!rc) + msyslog(LOG_ERR, + "config_trap: getaddrinfo_sometime(%s,%s): %m", + curr_trap->addr->address, + port_text); +#endif /* WORKER */ continue; - + } /* port is at same location for v4 and v6 */ - SET_PORT(&peeraddr, port_no ? port_no : TRAPPORT); + SET_PORT(&peeraddr, port); if (NULL == localaddr) localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); @@ -2891,13 +2992,59 @@ config_trap( if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) msyslog(LOG_ERR, - "can't set trap for %s", + "set trap %s -> %s failed.", + latoa(localaddr), stoa(&peeraddr)); } } } +/* + * trap_name_resolved() + * + * Callback invoked when config_trap()'s DNS lookup completes. + */ +#ifdef WORKER +void +trap_name_resolved( + int rescode, + int gai_errno, + void * context, + const char * name, + const char * service, + const struct addrinfo * hints, + const struct addrinfo * res + ) +{ + settrap_parms *pstp; + struct interface *localaddr; + sockaddr_u peeraddr; + + pstp = context; + if (rescode) { + msyslog(LOG_ERR, + "giving up resolving trap host %s: %s (%d)", + name, gai_strerror(rescode), rescode); + free(pstp); + return; + } + NTP_INSIST(sizeof(peeraddr) >= res->ai_addrlen); + memset(&peeraddr, 0, sizeof(peeraddr)); + memcpy(&peeraddr, res->ai_addr, res->ai_addrlen); + localaddr = NULL; + if (pstp->ifaddr_nonnull) + localaddr = findinterface(&pstp->ifaddr); + if (NULL == localaddr) + localaddr = ANY_INTERFACE_CHOOSE(&peeraddr); + if (!ctlsettrap(&peeraddr, localaddr, 0, NTP_VERSION)) + msyslog(LOG_ERR, "set trap %s -> %s failed.", + latoa(localaddr), stoa(&peeraddr)); + free(pstp); +} +#endif /* WORKER */ + + #ifdef FREE_CFG_T static void free_config_trap( @@ -4281,7 +4428,8 @@ gettokens_netinfo ( /* * getnetnum - return a net number (this is crude, but careful) * - * returns 1 for success, and mysteriously, 0 or -1 for failure + * returns 1 for success, and mysteriously, 0 for most failures, and + * -1 if the address found is IPv6 and we believe IPv6 isn't working. */ static int getnetnum( @@ -4293,7 +4441,11 @@ getnetnum( { isc_netaddr_t ipaddr; - if (!is_ip_address(num, AF_UNSPEC, &ipaddr)) + NTP_REQUIRE(AF_UNSPEC == AF(addr) || + AF_INET == AF(addr) || + AF_INET6 == AF(addr)); + + if (!is_ip_address(num, AF(addr), &ipaddr)) return 0; if (AF_INET6 == ipaddr.family && !ipv6_works) diff --git a/ntpd/ntp_peer.c b/ntpd/ntp_peer.c index 8530089f4..9c36194e7 100644 --- a/ntpd/ntp_peer.c +++ b/ntpd/ntp_peer.c @@ -561,8 +561,7 @@ peer_refresh_interface( { printf( "peer_refresh_interface: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x: new interface: ", - peer->dstadr == NULL ? "" : - stoa(&peer->dstadr->sin), stoa(&peer->srcadr), + latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode, peer->version, peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags, peer->ttl, peer->keyid); @@ -892,10 +891,9 @@ newpeer( snprintf(tbuf, sizeof(tbuf), "assoc %d", peer->associd); report_event(PEVNT_MOBIL, peer, tbuf); DPRINTF(1, ("newpeer: %s->%s mode %d vers %d poll %d %d flags 0x%x 0x%x ttl %d key %08x\n", - peer->dstadr == NULL ? "" : stoa(&peer->dstadr->sin), - stoa(&peer->srcadr), peer->hmode, peer->version, - peer->minpoll, peer->maxpoll, peer->flags, peer->cast_flags, - peer->ttl, peer->keyid)); + latoa(peer->dstadr), stoa(&peer->srcadr), peer->hmode, + peer->version, peer->minpoll, peer->maxpoll, peer->flags, + peer->cast_flags, peer->ttl, peer->keyid)); return (peer); } diff --git a/ntpd/ntp_restrict.c b/ntpd/ntp_restrict.c index 2ea4f35aa..d3080aad4 100644 --- a/ntpd/ntp_restrict.c +++ b/ntpd/ntp_restrict.c @@ -272,14 +272,14 @@ hack_restrict( register struct restrictlist6 *rl6 = NULL; register struct restrictlist6 *rlprev6 = NULL; int i, addr_cmp, mask_cmp; - memset(&addr6, 0, sizeof(struct in6_addr)); - memset(&mask6, 0, sizeof(struct in6_addr)); - if (IS_IPV4(resaddr)) { + DPRINTF(1, ("restrict: addr %s mask %s mflags %08x flags %08x\n", + stoa(resaddr), stoa(resmask), mflags, flags)); - DPRINTF(1, ("restrict: addr %08x mask %08x mflags %08x flags %08x\n", - SRCADR(resaddr), SRCADR(resmask), mflags, flags)); + memset(&addr6, 0, sizeof(addr6)); + memset(&mask6, 0, sizeof(mask6)); + if (IS_IPV4(resaddr)) { /* * Get address and mask in host byte order */