addresses in favor of is_ip_address() alone.
bk: 4b6cfca4XtXrE9lm5sZ9fEvnMGAUeg
* 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.
#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
*/
/* 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 */
#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
} 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);
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;
}
-
-
+ 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 */
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() */
}