]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Stop using getaddrinfo() to convert numeric address strings to on-wire
authorDave Hart <hart@ntp.org>
Sat, 6 Feb 2010 05:22:44 +0000 (05:22 +0000)
committerDave Hart <hart@ntp.org>
Sat, 6 Feb 2010 05:22:44 +0000 (05:22 +0000)
  addresses in favor of is_ip_address() alone.

bk: 4b6cfca4XtXrE9lm5sZ9fEvnMGAUeg

ChangeLog
include/ntp_rfc2553.h
include/ntpd.h
libntp/ntp_rfc2553.c
ntpd/ntp_config.c
ntpd/ntp_intres.c

index 350dfe39a365582cc7bcad02da1c0e17ca87121e..2beeb49bbc2e7fa1246159150af9a1fb8a0dfb02 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 * Include (4.2.6p1-RC5) - [Bug 1480] snprintf() cleanup caused 
   unterminated refclock IDs.
+* Stop using getaddrinfo() to convert numeric address strings to on-wire
+  addresses in favor of is_ip_address() alone.
 (4.2.7p17) 2010/02/05 Released by Harlan Stenn <stenn@ntp.org>
 * Include (4.2.6p1-RC5) - [Bug 1477] First non-gmake make in clone
   w/VPATH can't make COPYRIGHT.
index 703e972a9f49fb55db2c95c5b22f5e5277a7d0f3..b064658a83e2e8e1558e9ca60ffa025d0949c732 100644 (file)
 #include "ntp_types.h"
 
 
- /*
+#if !defined(_MSC_VER) || !defined(_DEBUG)
+struct addrinfo *copy_addrinfo_list(const struct addrinfo *);
+#else
+#define copy_addrinfo_list(ai) \
+       debug_copy_addrinfo_list((ai), __FILE__, __LINE__)
+struct addrinfo *debug_copy_addrinfo_list(const struct addrinfo *,
+                                         const char *, int);
+#endif
+
+/*
  * If various macros are not defined we need to define them
  */
 
index 3c5e4a6175c930e444958af0453a2a3e34c0d7e0..a83d8e76b91bf86f4583453aa9fbf9a792421fb1 100644 (file)
@@ -62,23 +62,32 @@ extern      void    set_sys_var (const char *, u_long, u_short);
 
 /* ntp_intres.c */
 #ifdef WORKER
-typedef void   (*gai_sometime_callback)
-                   (int, int, void *, const char *, const char *,
-                    const struct addrinfo *, const struct addrinfo *);
 /*
  * you call getaddrinfo_sometime(name, service, &hints, callback_func, context);
  * later (*callback_func)(rescode, gai_errno, context, name, service, hints, ai_result) is called.
  */
+typedef void   (*gai_sometime_callback)
+                   (int, int, void *, const char *, const char *,
+                    const struct addrinfo *, const struct addrinfo *);
 extern int     getaddrinfo_sometime(const char *, const char *,
                                     const struct addrinfo *,
                                     gai_sometime_callback, void *);
-typedef void   (*gni_sometime_callback)
-                   (int, int, sockaddr_u *, int, const char *,
-                    const char *, void *);
+/*
+ * In gai_sometime_callback routines, the resulting addrinfo list is
+ * only available until the callback returns.  To hold on to the list
+ * of addresses after the callback returns, use copy_addrinfo_list():
+ *
+ * struct addrinfo *copy_addrinfo_list(const struct addrinfo *);
+ */
+
+
 /*
  * you call getnameinfo_sometime(sockaddr, namelen, servlen, flags, callback_func, context);
  * later (*callback_func)(rescode, gni_errno, sockaddr, flags, name, service, context) is called.
  */
+typedef void   (*gni_sometime_callback)
+                   (int, int, sockaddr_u *, int, const char *,
+                    const char *, void *);
 extern int getnameinfo_sometime(sockaddr_u *, size_t, size_t, int,
                                gni_sometime_callback, void *);
 #endif /* WORKER */
index 03af593cf71e02afc4f9ca37de0f324f88f242b6..95269502b674a9499c8cbc19fa2fe6e4024ced7b 100644 (file)
 #include "ntp_malloc.h"
 #include "ntp_stdlib.h"
 #include "ntp_string.h"
+#include "ntp_debug.h"
+
+
+/*
+ * copy_addrinfo_list - copy an addrinfo list
+ *
+ * Copies an addrinfo list and its associated data to a contiguous block
+ * of storage from emalloc().  Callback routines invoked via
+ * getaddrinfo_sometime() have access to the resulting addrinfo list
+ * only until they return.  This routine provides an easy way to make a
+ * persistent copy.  Although the list provided to gai_sometime_callback
+ * routines is similarly contiguous, to keep this code usable in any
+ * context where we might want to duplicate an addrinfo list, it does
+ * not require the input list be contiguous.
+ *
+ * The returned list head pointer is passed to free() to release the
+ * entire list.
+ *
+ * In keeping with the rest of the NTP distribution, sockaddr_u is used
+ * in preference to struct sockaddr_storage, which is a member of the
+ * former union and so compatible.
+ *
+ * The rest of ntp_rfc2553.c is conditioned on ISC_PLATFORM_HAVEIPV6
+ * not being defined, copy_addrinfo_list() is an exception.
+ */
+#if !defined(_MSC_VER) || !defined(_DEBUG)
+struct addrinfo *
+copy_addrinfo_list(
+       const struct addrinfo *src
+       )
+#else
+struct addrinfo *
+debug_copy_addrinfo_list(
+       const struct addrinfo * src,
+       const char *            caller_file,
+       int                     caller_line
+       )
+#endif
+{
+       const struct addrinfo * ai_src;
+       struct addrinfo *       ai_cpy;
+       struct addrinfo *       dst;
+       sockaddr_u *            psau;
+       char *                  pcanon;
+       u_int                   elements;
+       size_t                  octets;
+       size_t                  canons_octets;
+       size_t                  str_octets;
+
+       elements = 0;
+       canons_octets = 0;
+
+       for (ai_src = src; NULL != ai_src; ai_src = ai_src->ai_next) {
+               ++elements;
+               if (NULL != ai_src->ai_canonname)
+                       canons_octets += 1 + strlen(ai_src->ai_canonname);
+       }
+
+       octets = elements * (sizeof(*ai_cpy) + sizeof(*psau));
+       octets += canons_octets;
+
+#if !defined(_MSC_VER) || !defined(_DEBUG)
+       dst = emalloc(octets);
+#else
+       dst = debug_erealloc(NULL, octets, caller_file, caller_line);
+#endif
+       memset(dst, 0, octets);
+       ai_cpy = dst;
+       psau = (void *)(ai_cpy + elements);
+       pcanon = (void *)(psau + elements);
+
+       for (ai_src = src; NULL != ai_src; ai_src = ai_src->ai_next) {
+               *ai_cpy = *ai_src;
+               NTP_REQUIRE(ai_src->ai_addrlen <= sizeof(sockaddr_u));
+               memcpy(psau, ai_src->ai_addr, ai_src->ai_addrlen);
+               ai_cpy->ai_addr = &psau->sa;
+               ++psau;
+               if (NULL != ai_cpy->ai_canonname) {
+                       ai_cpy->ai_canonname = pcanon;
+                       str_octets = 1 + strlen(ai_src->ai_canonname);
+                       memcpy(pcanon, ai_src->ai_canonname, str_octets);
+                       pcanon += str_octets;
+               }
+               if (NULL != ai_cpy->ai_next)
+                       ai_cpy->ai_next = ai_cpy + 1;
+               ++ai_cpy;
+       }
+       NTP_ENSURE(pcanon == ((char *)dst + octets));
+
+       return dst;
+}
+
 
 #ifndef ISC_PLATFORM_HAVEIPV6
 
index ef9dbf7415908dad4a88c4934376151a689194a4..45ae1b6d5f322308c415b89dee28d6b5e3ed16ca 100644 (file)
@@ -286,14 +286,11 @@ do {                                      \
 } while (0)
 
 void ntpd_set_tod_using(const char *);
-static unsigned long get_pfxmatch(char **s,struct masks *m);
-static unsigned long get_match(char *s,struct masks *m);
+static unsigned long get_pfxmatch(char **s, struct masks *m);
+static unsigned long get_match(char *s, struct masks *m);
 static unsigned long get_logmask(char *s);
-static int getnetnum(const char *num,sockaddr_u *addr, int complain,
+static int getnetnum(const char *num, sockaddr_u *addr, int complain,
                     enum gnn_type a_type);
-static int get_multiple_netnums(const char *num, sockaddr_u *addr,
-                               struct addrinfo **res, int complain,
-                               enum gnn_type a_type);
 
 
 
@@ -4294,122 +4291,27 @@ getnetnum(
        enum gnn_type a_type
        )
 {
-       int retval;
-       struct addrinfo *res;
-
-       /* Get all the addresses that resolve to this name */
-       retval = get_multiple_netnums(num, addr, &res, complain, a_type);
-
-       if (retval != 1) {
-               /* Name resolution failed */
-               return retval;
-       }
-
-       memcpy(addr, res->ai_addr, res->ai_addrlen);
-
-       DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
-
-       freeaddrinfo(res);
-       return 1;
-}
-
-
-/*
- * get_multiple_netnums
- *
- * returns 1 for success, and mysteriously, 0 or -1 for failure
- */
-static int
-get_multiple_netnums(
-       const char *nameornum,
-       sockaddr_u *addr,
-       struct addrinfo **res,
-       int complain,
-       enum gnn_type a_type
-       )
-{
-       char lookbuf[1024];
-       const char *lookup;
-       char *pch;
-       struct addrinfo hints;
-       struct addrinfo *ptr;
-       int retval;
        isc_netaddr_t ipaddr;
 
-       memset(&hints, 0, sizeof(hints));
-
-       if (strlen(nameornum) >= sizeof(lookbuf)) {
-               NTP_INSIST(strlen(nameornum) < sizeof(lookbuf));
+       if (!is_ip_address(num, AF_UNSPEC, &ipaddr))
                return 0;
-       }
-
-       lookup = nameornum;
-       if (is_ip_address(nameornum, AF_UNSPEC, &ipaddr)) {
-               hints.ai_flags = AI_NUMERICHOST;
-               hints.ai_family = ipaddr.family;
-               if ('[' == nameornum[0]) {
-                       lookup = lookbuf;
-                       strncpy(lookbuf, &nameornum[1],
-                               sizeof(lookbuf));
-                       pch = strchr(lookbuf, ']');
-                       if (pch != NULL)
-                               *pch = '\0';
-               }
-               pch = strchr(lookup, '%');
-               if (pch != NULL) {
-                       if (lookup != lookbuf) {
-                               lookup = lookbuf;
-                               strncpy(lookbuf, nameornum,
-                                       sizeof(lookbuf));
-                               pch = strchr(lookup, '%');
-                       }
-                       *pch = '\0';
-               }
-       }
-
-       if (AF_INET6 == hints.ai_family && !ipv6_works)
-               return 0;
-
-       if (AF_UNSPEC == hints.ai_family) {
-               if (!ipv6_works)
-                       hints.ai_family = AF_INET;
-               else if (!ipv4_works)
-                       hints.ai_family = AF_INET6;
-               else if (IS_IPV4(addr) || IS_IPV6(addr))
-                       hints.ai_family = AF(addr);
-       }
-
-       /* Get host address. Looking for UDP datagram connection */
-       hints.ai_socktype = SOCK_DGRAM;
 
-       DPRINTF(4, ("getaddrinfo %s%s\n", 
-                   (AF_UNSPEC == hints.ai_family)
-                       ? ""
-                       : (AF_INET == hints.ai_family)
-                               ? "v4 "
-                               : "v6 ",
-                   lookup));
+       if (AF_INET6 == ipaddr.family && !ipv6_works)
+               return -1;
 
-       retval = getaddrinfo(lookup, "ntp", &hints, &ptr);
+       memset(addr, 0, sizeof(*addr));
+       AF(addr) = (u_short)ipaddr.family;
+#ifdef ISC_PLATFORM_HAVESALEN
+       addr->sas.ss_len = SIZEOF_SOCKADDR(AF(addr));
+#endif
+       if (IS_IPV4(addr))
+               memcpy(&addr->sa4.sin_addr, &ipaddr.type.in,
+                      sizeof(addr->sa4.sin_addr));
+       else
+               memcpy(&addr->sa6.sin6_addr, &ipaddr.type.in6,
+                      sizeof(addr->sa6.sin6_addr));
 
-       if (retval || (AF_INET6 == ptr->ai_family && !ipv6_works)) {
-               if (complain)
-                       msyslog(LOG_ERR,
-                               "getaddrinfo: \"%s\" invalid host address, ignored",
-                               lookup);
-               else
-                       DPRINTF(1, ("getaddrinfo: \"%s\" invalid host address.\n",
-                                   lookup));
-
-               if (!retval) {
-                       freeaddrinfo(ptr);
-                       return -1;
-               } else 
-                       return 0;
-       }
-       *res = ptr;
+       DPRINTF(2, ("getnetnum given %s, got %s\n", num, stoa(addr)));
 
        return 1;
 }
-
-
index 5a52bd1b4cbf113a9201b31f3a6dd6679fcbf142..5353c27f53e085c80719804face3e1ba2addae38 100644 (file)
@@ -356,7 +356,7 @@ blocking_getaddrinfo(
                            + canons_octets;
 
        resp_octets = sizeof(*resp) + gai_resp->octets;
-       resp =  erealloc(resp, resp_octets);
+       resp = erealloc(resp, resp_octets);
        gai_resp = (void *)(resp + 1);
 
        /* cp serves as our current pointer while serializing */
@@ -516,11 +516,20 @@ getaddrinfo_sometime_complete(
 
        if (!gai_resp->ai_count)
                ai = NULL;
+#ifdef DEBUG
+       else    /* exercise copy_addrinfo_list() */
+               ai = copy_addrinfo_list(ai);
+#endif
        
        (*gai_req->callback)(gai_resp->retcode, gai_resp->gai_errno,
                             gai_req->context, node, service, 
                             &gai_req->hints, ai);
 
+#ifdef DEBUG
+       /* exercise copy_addrinfo_list() */
+       if (NULL != ai)
+               free(ai);
+#endif
        free(gai_req);
        /* gai_resp is part of block freed by process_blocking_response() */
 }