]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
nameserv: add support for returning multiple addresses
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 21 Oct 2014 13:37:16 +0000 (15:37 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 23 Oct 2014 14:48:13 +0000 (16:48 +0200)
client.c
conf.c
nameserv.c
nameserv.h
nameserv_async.c
nameserv_async.h
ntp_sources.c
stubs.c

index 7c01435babb1435fa899bdcb12283e6424920c3a..2e1866c833f31cfd77b3e28b2e2434d493bafea5 100644 (file)
--- a/client.c
+++ b/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 {
diff --git a/conf.c b/conf.c
index d14c53e738613443ef75110ebf274a76bcb52a9c..d29118d0c14fc6fb4e90e0328dc8344fe7a0d992 100644 (file)
--- a/conf.c
+++ b/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;
index 8134342e9f9b366c87a1bddbe7c4241ac49574d4..bb9309e2e6a4b9478b66446525dbd46be68bee73 100644 (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;
   }
 
index 3980c1b46e9116731389843c81114070f3b5e287..341a609fbb4db86b51417dba2b0b9e52c432c36b 100644 (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);
 
index 82b2f7b3a5540f429cd7e1ad274b940fba3d3be9..1ceeb28b933ca0d33cdaf69630434b7f6ba4e11e 100644 (file)
 #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);
 }
index 5c1704e6322063fb862f636e531f875a5c5b3a1e..cea2d82ccabbae37e36ea6401d448d8560e6d191 100644 (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
index a638f8c7f137c082034252f0fabae056734edf1e..1e5acff23dd7b298f156b65ee1009da5b3d189ef 100644 (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;
diff --git a/stubs.c b/stubs.c
index aafd6d24eb7a47dbc07f44c1fd2c70ce444e1b33..f8e730449b3c2461bc8f1e25fe40e03b04a49e62 100644 (file)
--- a/stubs.c
+++ b/stubs.c
 
 #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 */
@@ -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;
 }