DO NOT MERGE - Mark RQ3A.210410.001 as merged

Bug: 190855093
Merged-In: I50e6061b99e37561600c0c2524d6be12801e6863
Change-Id: I1e6a4a5e2092e166c5d914543e02d52cea0d0a69
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..6d8601b
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: RESTRICTED
+}
diff --git a/src/Android.bp b/src/Android.bp
index c764039..052e3e6 100644
--- a/src/Android.bp
+++ b/src/Android.bp
@@ -1,3 +1,37 @@
+package {
+    default_applicable_licenses: ["external_dnsmasq_src_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "external_dnsmasq_src_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-BSD",
+        "SPDX-license-identifier-GPL",
+        "SPDX-license-identifier-GPL-2.0",
+        "SPDX-license-identifier-LGPL",
+        "SPDX-license-identifier-MIT",
+        "legacy_unencumbered",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_binary {
     name: "dnsmasq",
     srcs: [
diff --git a/src/config.h b/src/config.h
index 05d74ae..14b5c98 100644
--- a/src/config.h
+++ b/src/config.h
@@ -69,7 +69,7 @@
 #define DHCP_CLIENT_ALTPORT 1068
 #define LOG_MAX 5 /* log-queue length */
 #define RANDFILE "/dev/urandom"
-#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
+#define DAD_WAIT 1 /* retry binding IPv6 sockets for this long */
 
 /* A small collection of RR-types which are missing on some platforms */
 
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index 27ad864..46d15ee 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -350,10 +350,10 @@
 
     if (!(daemon->options & OPT_DEBUG) && getuid() == 0) {
         int bad_capabilities = 0;
-        gid_t dummy;
+        gid_t unused;
 
         /* remove all supplimentary groups */
-        if (gp && (setgroups(0, &dummy) == -1 || setgid(gp->gr_gid) == -1)) {
+        if (gp && (setgroups(0, &unused) == -1 || setgid(gp->gr_gid) == -1)) {
             send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
             _exit(0);
         }
@@ -571,7 +571,7 @@
         /* alarm is used to kill TCP children after a fixed time. */
         if (sig == SIGALRM) _exit(0);
     } else {
-        /* master process */
+        /* main process */
         const int errsave = errno;
         int event;
 
diff --git a/src/helper.c b/src/helper.c
index eb6614a..3e414b2 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -75,8 +75,8 @@
     sigaction(SIGALRM, &sigact, NULL);
 
     if (!(daemon->options & OPT_DEBUG) && uid != 0) {
-        gid_t dummy;
-        if (setgroups(0, &dummy) == -1 || setgid(gid) == -1 || setuid(uid) == -1) {
+        gid_t unused;
+        if (setgroups(0, &unused) == -1 || setgid(gid) == -1 || setuid(uid) == -1) {
             if (daemon->options & OPT_NO_FORK) /* send error to daemon process if no-fork */
                 send_event(event_fd, EVENT_HUSER_ERR, errno);
             else {
diff --git a/src/log.c b/src/log.c
index d1fcfb9..1cc4745 100644
--- a/src/log.c
+++ b/src/log.c
@@ -104,7 +104,7 @@
         return log_fd != -1;
     } else
 #if defined(__ANDROID__)
-#define _PATH_LOG "" /* dummy */
+#define _PATH_LOG "" /* unused */
         log_fd = -1;
 #else
     {
diff --git a/src/network.c b/src/network.c
index 98b4f68..1bc3c21 100644
--- a/src/network.c
+++ b/src/network.c
@@ -180,7 +180,7 @@
 #ifdef HAVE_IPV6
 static int iface_allowed_v6(struct in6_addr* local, int scope, int if_index, void* vparam) {
     union mysockaddr addr;
-    struct in_addr netmask; /* dummy */
+    struct in_addr netmask; /* unused */
 
     netmask.s_addr = 0;
 
@@ -360,7 +360,6 @@
     new->next = *listeners;
     new->tcpfd = -1;
     new->fd = -1;
-    *listeners = new;
 
     if (daemon->port != 0) {
         if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
@@ -378,12 +377,17 @@
         }
 #endif
 
+        /* Unless the IPv6 address is added with IFA_F_NODAD, bind() can fail even if DAD
+           is disabled on the interface. This is because without IFA_F_NODAD the IPv6
+           address creation call moves the IPv6 address to tentative. A timer will
+           fire to immediately remove the tentative flag, but this is not sufficient to
+           avoid a race condition (see comments in tun_interface.cpp and iproute.py). */
         while (1) {
             if ((rc = bind(new->fd, &iface->addr.sa, sa_len(&iface->addr))) != -1) break;
 
 #ifdef HAVE_IPV6
             /* An interface may have an IPv6 address which is still undergoing DAD.
-               If so, the bind will fail until the DAD completes, so we try over 20 seconds
+               If so, the bind will fail until the DAD completes, so we try again
                before failing. */
             /* TODO: What to do here? 20 seconds is way too long. We use optimistic addresses, so
                bind() will only fail if the address has already failed DAD, in which case retrying
@@ -399,7 +403,11 @@
 
         if (rc == -1 || bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1) {
             prettyprint_addr(&iface->addr, daemon->namebuff);
-            die(_("failed to bind listening socket for %s: %s"), daemon->namebuff, EC_BADNET);
+            close(new->fd);
+            close(new->tcpfd);
+            free(new);
+            syslog(LOG_ERR, _("failed to bind listening socket for %s"), daemon->namebuff);
+            return;
         }
 
         uint32_t mark = daemon->listen_mark;
@@ -409,6 +417,7 @@
 
         if (listen(new->tcpfd, 5) == -1) die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
     }
+    *listeners = new;
 }
 
 /**
diff --git a/src/util.c b/src/util.c
index 11b43a0..175b7bb 100644
--- a/src/util.c
+++ b/src/util.c
@@ -273,12 +273,12 @@
 
 time_t dnsmasq_time(void) {
 #ifdef HAVE_BROKEN_RTC
-    struct tms dummy;
+    struct tms unused;
     static long tps = 0;
 
     if (tps == 0) tps = sysconf(_SC_CLK_TCK);
 
-    return (time_t)(times(&dummy) / tps);
+    return (time_t)(times(&unused) / tps);
 #else
     return time(NULL);
 #endif