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);
}
}
}
} 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 {
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 {
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 {
(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 {
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;
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;
}
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 {
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);
}
} 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;
}
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;
#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;
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;
}
/* 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);
#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;
{
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)
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");
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);
}
#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
/* ================================================== */
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;
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;
#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, addrs, MAX_ADDRESSES);
+
+ for (i = 0; status == DNS_Success && i < MAX_ADDRESSES &&
+ addrs[i].family != IPADDR_UNSPEC; i++)
+ ;
- status = DNS_Name2IPAddress(name, &addr);
- (handler)(status, &addr, anything);
+ (handler)(status, i, addrs, anything);
}
#endif /* !FEAT_ASYNCDNS */
}
DNS_Status
-DNS_Name2IPAddress(const char *name, IPAddr *addr)
+DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs)
{
return DNS_Failure;
}