nameserv: add support for returning multiple addresses
This commit is contained in:
parent
699680807d
commit
4d1a754ec6
8 changed files with 65 additions and 36 deletions
16
client.c
16
client.c
|
@ -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
4
conf.c
|
@ -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;
|
||||
|
|
42
nameserv.c
42
nameserv.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
16
stubs.c
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue