Commit 2da4552a authored by Dave Hart's avatar Dave Hart

Stop using getaddrinfo() to convert numeric address strings...

...to on-wire  addresses in favor of is_ip_address() alone.
parent 58724f3a
* 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.
......
......@@ -74,7 +74,16 @@
#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
*/
......
......@@ -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 */
......
......@@ -82,6 +82,98 @@
#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
......
......@@ -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;
}
......@@ -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() */
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment