nameserv: add support for returning multiple addresses

This commit is contained in:
Miroslav Lichvar 2014-10-21 15:37:16 +02:00
parent 699680807d
commit 4d1a754ec6
8 changed files with 65 additions and 36 deletions

View file

@ -119,7 +119,7 @@ open_io(const char *hostname, int port)
int on_off = 1;
/* Note, this call could block for a while */
if (DNS_Name2IPAddress(hostname, &ip) != DNS_Success) {
if (DNS_Name2IPAddress(hostname, &ip, 1) != DNS_Success) {
fprintf(stderr, "Could not get IP address for %s\n", hostname);
exit(1);
}
@ -233,7 +233,7 @@ read_mask_address(char *line, IPAddr *mask, IPAddr *address)
}
}
} else {
if (DNS_Name2IPAddress(p, address) == DNS_Success) {
if (DNS_Name2IPAddress(p, address, 1) == DNS_Success) {
bits_to_mask(-1, address->family, mask);
return 1;
} else {
@ -305,7 +305,7 @@ read_address_integer(char *line, IPAddr *address, int *value)
fprintf(stderr, "Invalid syntax for address value\n");
ok = 0;
} else {
if (DNS_Name2IPAddress(hostname, address) != DNS_Success) {
if (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
@ -333,7 +333,7 @@ read_address_double(char *line, IPAddr *address, double *value)
fprintf(stderr, "Invalid syntax for address value\n");
ok = 0;
} else {
if (DNS_Name2IPAddress(hostname, address) != DNS_Success) {
if (DNS_Name2IPAddress(hostname, address, 1) != DNS_Success) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {
@ -660,7 +660,7 @@ parse_allow_deny(CMD_Request *msg, char *line)
(n = sscanf(p, "%lu.%lu.%lu.%lu", &a, &b, &c, &d)) == 0) {
/* Try to parse as the name of a machine */
if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) {
fprintf(stderr, "Could not read address\n");
return 0;
} else {
@ -828,7 +828,7 @@ accheck_getaddr(char *line, IPAddr *addr)
addr->addr.in4 = (a<<24) | (b<<16) | (c<<8) | d;
return 1;
} else {
if (DNS_Name2IPAddress(p, &ip) != DNS_Success) {
if (DNS_Name2IPAddress(p, &ip, 1) != DNS_Success) {
return 0;
} else {
*addr = ip;
@ -935,7 +935,7 @@ process_cmd_add_server_or_peer(CMD_Request *msg, char *line)
status = CPS_ParseNTPSourceAdd(line, &data);
switch (status) {
case CPS_Success:
if (DNS_Name2IPAddress(data.name, &ip_addr) != DNS_Success) {
if (DNS_Name2IPAddress(data.name, &ip_addr, 1) != DNS_Success) {
fprintf(stderr, "Invalid host/IP address\n");
break;
}
@ -1056,7 +1056,7 @@ process_cmd_delete(CMD_Request *msg, char *line)
fprintf(stderr, "Invalid syntax for address\n");
ok = 0;
} else {
if (DNS_Name2IPAddress(hostname, &address) != DNS_Success) {
if (DNS_Name2IPAddress(hostname, &address, 1) != DNS_Success) {
fprintf(stderr, "Could not get address for hostname\n");
ok = 0;
} else {

4
conf.c
View file

@ -817,7 +817,7 @@ parse_initstepslew(char *line)
hostname = p;
p = CPS_SplitWord(p);
if (*hostname) {
if (DNS_Name2IPAddress(hostname, &ip_addr) == DNS_Success) {
if (DNS_Name2IPAddress(hostname, &ip_addr, 1) == DNS_Success) {
ARR_AppendElement(init_sources, &ip_addr);
} else {
LOG(LOGS_WARN, LOGF_Configure, "Could not resolve address of initstepslew server %s", hostname);
@ -985,7 +985,7 @@ parse_allow_deny(char *line, ARR_Instance restrictions, int allow)
}
} else {
if (DNS_Name2IPAddress(p, &ip_addr) == DNS_Success) {
if (DNS_Name2IPAddress(p, &ip_addr, 1) == DNS_Success) {
new_node = (AllowDeny *)ARR_GetNewElement(restrictions);
new_node->allow = allow;
new_node->all = all;

View file

@ -44,11 +44,11 @@ DNS_SetAddressFamily(int family)
}
DNS_Status
DNS_Name2IPAddress(const char *name, IPAddr *addr)
DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs)
{
#ifdef HAVE_GETADDRINFO
struct addrinfo hints, *res, *ai;
int result;
int i, result;
memset(&hints, 0, sizeof (hints));
hints.ai_family = AF_UNSPEC;
@ -64,29 +64,37 @@ DNS_Name2IPAddress(const char *name, IPAddr *addr)
#endif
}
for (ai = res; !result && ai != NULL; ai = ai->ai_next) {
for (ai = res, i = 0; i < max_addrs && ai != NULL; ai = ai->ai_next) {
switch (ai->ai_family) {
case AF_INET:
addr->family = IPADDR_INET4;
addr->addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
result = 1;
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4)
continue;
ip_addrs[i].family = IPADDR_INET4;
ip_addrs[i].addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr);
i++;
break;
#ifdef FEAT_IPV6
case AF_INET6:
addr->family = IPADDR_INET6;
memcpy(&addr->addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, sizeof (addr->addr.in6));
result = 1;
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6)
continue;
ip_addrs[i].family = IPADDR_INET6;
memcpy(&ip_addrs[i].addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr,
sizeof (ip_addrs->addr.in6));
i++;
break;
#endif
}
if (result && address_family != IPADDR_UNSPEC && address_family != addr->family)
result = 0;
}
for (; i < max_addrs; i++)
ip_addrs[i].family = IPADDR_UNSPEC;
freeaddrinfo(res);
return result ? DNS_Success : DNS_Failure;
return !max_addrs || ip_addrs[0].family != IPADDR_UNSPEC ? DNS_Success : DNS_Failure;
#else
struct hostent *host;
int i;
if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4)
return DNS_Failure;
@ -100,8 +108,14 @@ DNS_Name2IPAddress(const char *name, IPAddr *addr)
if (host->h_addrtype != AF_INET || !host->h_addr_list[0])
return DNS_Failure;
addr->family = IPADDR_INET4;
addr->addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[0]);
for (i = 0; host->h_addr_list[i] && i < max_addrs; i++) {
ip_addrs[i].family = IPADDR_INET4;
ip_addrs[i].addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[i]);
}
for (; i < max_addrs; i++)
ip_addrs[i].family = IPADDR_UNSPEC;
return DNS_Success;
}

View file

@ -39,7 +39,7 @@ typedef enum {
/* Resolve names only to selected address family */
extern void DNS_SetAddressFamily(int family);
extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *addr);
extern DNS_Status DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs);
extern int DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len);

View file

@ -37,12 +37,14 @@
#ifdef USE_PTHREAD_ASYNCDNS
#include <pthread.h>
#define MAX_ADDRESSES 16
/* ================================================== */
struct DNS_Async_Instance {
const char *name;
DNS_Status status;
IPAddr addr;
IPAddr addresses[MAX_ADDRESSES];
DNS_NameResolveHandler handler;
void *arg;
@ -59,7 +61,7 @@ start_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
inst->status = DNS_Name2IPAddress(inst->name, &inst->addr);
inst->status = DNS_Name2IPAddress(inst->name, inst->addresses, MAX_ADDRESSES);
/* Notify the main thread that the result is ready */
if (write(inst->pipe[1], "", 1) < 0)
@ -74,6 +76,7 @@ static void
end_resolving(void *anything)
{
struct DNS_Async_Instance *inst = (struct DNS_Async_Instance *)anything;
int i;
if (pthread_join(inst->thread, NULL)) {
LOG_FATAL(LOGF_Nameserv, "pthread_join() failed");
@ -85,7 +88,11 @@ end_resolving(void *anything)
close(inst->pipe[0]);
close(inst->pipe[1]);
(inst->handler)(inst->status, &inst->addr, inst->arg);
for (i = 0; inst->status == DNS_Success && i < MAX_ADDRESSES &&
inst->addresses[i].family != IPADDR_UNSPEC; i++)
;
(inst->handler)(inst->status, i, inst->addresses, inst->arg);
Free(inst);
}

View file

@ -31,7 +31,7 @@
#include "nameserv.h"
/* Function type for callback to process the result */
typedef void (*DNS_NameResolveHandler)(DNS_Status status, IPAddr *ip_addr, void *anything);
typedef void (*DNS_NameResolveHandler)(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything);
/* Request resolving of a name to IP address. The handler will be
called when the result is available, but it may be also called

View file

@ -300,7 +300,7 @@ NSR_AddSource(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourceParam
/* ================================================== */
static void
name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything)
name_resolve_handler(DNS_Status status, int n_addrs, IPAddr *ip_addrs, void *anything)
{
struct UnresolvedSource *us, **i, *next;
NTP_Remote_Address address;
@ -313,8 +313,8 @@ name_resolve_handler(DNS_Status status, IPAddr *ip_addr, void *anything)
case DNS_TryAgain:
break;
case DNS_Success:
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(ip_addr));
address.ip_addr = *ip_addr;
DEBUG_LOG(LOGF_NtpSources, "%s resolved to %s", us->name, UTI_IPToString(&ip_addrs[0]));
address.ip_addr = ip_addrs[0];
address.port = us->port;
NSR_AddSource(&address, us->type, &us->params);
break;

16
stubs.c
View file

@ -41,16 +41,24 @@
#ifndef FEAT_ASYNCDNS
#define MAX_ADDRESSES 16
/* This is a blocking implementation used when asynchronous resolving is not available */
void
DNS_Name2IPAddressAsync(const char *name, DNS_NameResolveHandler handler, void *anything)
{
IPAddr addr;
IPAddr addrs[MAX_ADDRESSES];
DNS_Status status;
int i;
status = DNS_Name2IPAddress(name, &addr);
(handler)(status, &addr, anything);
status = DNS_Name2IPAddress(name, addrs, MAX_ADDRESSES);
for (i = 0; status == DNS_Success && i < MAX_ADDRESSES &&
addrs[i].family != IPADDR_UNSPEC; i++)
;
(handler)(status, i, addrs, anything);
}
#endif /* !FEAT_ASYNCDNS */
@ -267,7 +275,7 @@ DNS_SetAddressFamily(int family)
}
DNS_Status
DNS_Name2IPAddress(const char *name, IPAddr *addr)
DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs)
{
return DNS_Failure;
}