]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1483] hostname in ntp.conf "restrict" parameter rejected.
authorDave Hart <hart@ntp.org>
Tue, 9 Feb 2010 18:19:12 +0000 (18:19 +0000)
committerDave Hart <hart@ntp.org>
Tue, 9 Feb 2010 18:19:12 +0000 (18:19 +0000)
Use all addresses for each restrict by hostname.
Use async DNS to resolve trap directive hostnames.

bk: 4b71a720C2RskVESWsb7TTBU3D5Gag

ChangeLog
include/ntp_config.h
include/ntp_stdlib.h
ntpd/ntp_config.c
ntpd/ntp_peer.c
ntpd/ntp_restrict.c

index 92e8a78280ae8b154d9e499ec3ea69dfdddbcd05..c34deb26f38da65b64d00414fe411c62f2bce2c5 100644 (file)
--- 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 <stenn@ntp.org>
 * Include (4.2.6p1-RC5) - [Bug 1480] snprintf() cleanup caused 
   unterminated refclock IDs.
index bb002415bf135a553c20b3de00896837a03ef39f..af21cdd405f5462fd5b07c7bd271c5b6bd6374da 100644 (file)
@@ -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);
 
index f88965eb0bb67607985c2fa822126362b2df7fc2..2340bac1df3180f6c84df8539ebb4fa8236fe057 100644 (file)
@@ -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))                \
+                                    ? "<null>"                 \
+                                    : 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);
index 45ae1b6d5f322308c415b89dee28d6b5e3ed16ca..da3b7e31c3aa43651d2a7eadc32210dfc5afd000 100644 (file)
@@ -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)
index 8530089f4c8d1637e0031ce0d2f4ac8602981e33..9c36194e769fae1e205b13bfa7340159681fc717 100644 (file)
@@ -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 ? "<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 ? "<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);
 }
 
index 2ea4f35aae078db57de3fba1e6d44561a0a5c233..d3080aad48588694b49a64cf612230f2eea1198f 100644 (file)
@@ -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
                 */