Simplify and always retry DNS64 prefix discovery.

  - Only request AAAAs for the IPv4-only hostname, since that's
    all the information being used.  Perhaps at some point in the
    future when _validation_ of the IPv4 address(es)'s presence
    within the IPv6 address(es) is being done this should be
    revisited.

  - Only use the first AAAA returned to find the DNS64 prefix.
    It's not clear how to properly resolve any potential DNS64
    prefix conflicts anyway.

  - Re-try DNS64 prefix discovery on any type of error.
    If clatd was started (presumably an IPv6-only network), retry
    DNS64 prefix discovery with exponential backoff.  Some
    "permanent" errors can be indistinguishable from transient
    errors (e.g. receiving an erroneous SERVFAIL from a DNS
    resolver, ...).

  - Fix-up back-off logic to not sleep 128 then 120, 120, ...
    :-)

Bug: 17569702
Change-Id: I226ea7772cd7c88d2b60153ef76e5435400e11aa
diff --git a/config.c b/config.c
index d8bec80..13889a0 100644
--- a/config.c
+++ b/config.c
@@ -165,16 +165,11 @@
       memcpy(&Global_Clatd_Config.plat_subnet, &tmp_ptr, sizeof(struct in6_addr));
       return;
     }
-    if(status < 0) {
-      logmsg(ANDROID_LOG_FATAL, "dns64_detection/no dns64, giving up\n");
-      exit(1);
-    }
-    logmsg(ANDROID_LOG_WARN, "dns64_detection failed, sleeping for %d seconds", backoff_sleep);
+    logmsg(ANDROID_LOG_WARN, "dns64_detection -- error, sleeping for %d seconds", backoff_sleep);
     sleep(backoff_sleep);
+    backoff_sleep *= 2;
     if(backoff_sleep >= 120) {
       backoff_sleep = 120;
-    } else {
-      backoff_sleep *= 2;
     }
   }
 }
diff --git a/dns64.c b/dns64.c
index ce8539d..4e9252d 100644
--- a/dns64.c
+++ b/dns64.c
@@ -30,69 +30,44 @@
 #include "resolv_netid.h"
 
 /* function: plat_prefix
- * looks up an ipv4-only hostname and looks for a nat64 /96 prefix, returns 1 on success, 0 on temporary failure, -1 on permanent failure
+ * looks up an ipv4-only hostname and looks for a nat64 /96 prefix, returns 1 on success, 0 on failure
  * ipv4_name  - name to lookup
  * net_id     - (optional) netId to use, NETID_UNSET indicates use of default network
  * prefix     - the plat /96 prefix
  */
 int plat_prefix(const char *ipv4_name, unsigned net_id, struct in6_addr *prefix) {
-  struct addrinfo hints, *result, *p;
-  int status, plat_addr_set, ipv4_records, ipv6_records;
-  struct in6_addr plat_addr, this_plat_addr;
-  struct sockaddr_in6 *this_addr;
+  const struct addrinfo hints = {
+    .ai_family = AF_INET6,
+  };
+  int status;
+  struct addrinfo *result = NULL;
+  struct in6_addr plat_addr;
   char plat_addr_str[INET6_ADDRSTRLEN];
 
   logmsg(ANDROID_LOG_INFO, "Detecting NAT64 prefix from DNS...");
 
-  result = NULL;
-  plat_addr_set = 0;
-  ipv4_records = ipv6_records = 0;
-
-  bzero(&hints, sizeof(hints));
-  hints.ai_family = AF_UNSPEC;
   status = android_getaddrinfofornet(ipv4_name, NULL, &hints, net_id, MARK_UNSET, &result);
-  if(status != 0) {
-    logmsg(ANDROID_LOG_ERROR,"plat_prefix/dns(%s) status = %d/%s\n", ipv4_name, status, gai_strerror(status));
+  if (status != 0 || result == NULL) {
+    logmsg(ANDROID_LOG_ERROR, "plat_prefix/dns(%s) status = %d/%s",
+           ipv4_name, status, gai_strerror(status));
     return 0;
   }
 
-  for(p = result; p; p = p->ai_next) {
-    if(p->ai_family == AF_INET) {
-      ipv4_records++;
-      continue;
-    }
-    if(p->ai_family != AF_INET6) {
-      logmsg(ANDROID_LOG_WARN,"plat_prefix/unexpected address family: %d\n", p->ai_family);
-      continue;
-    }
-    ipv6_records++;
-    this_addr = (struct sockaddr_in6 *)p->ai_addr;
-    this_plat_addr = this_addr->sin6_addr;
-    this_plat_addr.s6_addr32[3] = 0;
+  // Use only the first result.  If other records are present, possibly with
+  // differing DNS64 prefixes they are ignored (there is very little sensible
+  // that could be done with them at this time anyway).
 
-    if(!plat_addr_set) {
-      plat_addr = this_plat_addr;
-      plat_addr_set = 1;
-      continue;
-    }
+  if (result->ai_family != AF_INET6) {
+    logmsg(ANDROID_LOG_WARN, "plat_prefix/unexpected address family: %d", result->ai_family);
+    return 0;
+  }
+  plat_addr = ((struct sockaddr_in6 *)result->ai_addr)->sin6_addr;
+  // Only /96 DNS64 prefixes are supported at this time.
+  plat_addr.s6_addr32[3] = 0;
+  freeaddrinfo(result);
 
-    inet_ntop(AF_INET6, &plat_addr, plat_addr_str, sizeof(plat_addr_str));
-    if(!IN6_ARE_ADDR_EQUAL(&plat_addr, &this_plat_addr)) {
-      char this_plat_addr_str[INET6_ADDRSTRLEN];
-      inet_ntop(AF_INET6, &this_plat_addr, this_plat_addr_str, sizeof(this_plat_addr_str));
-      logmsg(ANDROID_LOG_ERROR,"plat_prefix/two different plat addrs = %s,%s",
-             plat_addr_str,this_plat_addr_str);
-    }
-  }
-  if(result != NULL) {
-    freeaddrinfo(result);
-  }
-  if(ipv4_records > 0 && ipv6_records == 0) {
-    logmsg(ANDROID_LOG_WARN,"plat_prefix/no dns64 detected\n");
-    return -1;
-  }
-
-  logmsg(ANDROID_LOG_INFO, "Detected NAT64 prefix %s/96", plat_addr_str);
+  logmsg(ANDROID_LOG_INFO, "Detected NAT64 prefix %s/96",
+         inet_ntop(AF_INET6, &plat_addr, plat_addr_str, sizeof(plat_addr_str)));
   *prefix = plat_addr;
   return 1;
 }