summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Wear <twear@quicinc.com>2020-11-11 09:20:58 -0800
committerMaciej Żenczykowski <maze@google.com>2021-01-05 18:38:43 +0000
commit8898837825af095f6bb9923d0ea5211fdeb9f3b7 (patch)
treec38b60ecb5325a4306af8886368c90655ed22a39
parent9a192e894b5906efb6e23d8a7d27ffc57a99366d (diff)
downloaddnsmasq-8898837825af095f6bb9923d0ea5211fdeb9f3b7.tar.gz
dnsmasq: Remove DAD Retry
DAD is disabled in TetherController, which sets accept_dad and dad_transmits to zero, so the the retry here doesn't help wrt DAD. The loop will lock dnsmasq for up to 20 seconds in error scenario's though, which is undesirable. Since IFA_F_NODAD is not set on address loop will be reduced to 1 second for now. When bind fails die() should not be called since dnsmasq is never restarted as long as tethering is enabled. Cleaning up and returning should suffice while not impacting on going tethering. Bug: 171409363 Change-Id: Id0c065c75c869d7bd241390682b7e5d932a74a22
-rw-r--r--src/config.h2
-rw-r--r--src/network.c15
2 files changed, 13 insertions, 4 deletions
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/network.c b/src/network.c
index d542c94..1bc3c21 100644
--- a/src/network.c
+++ b/src/network.c
@@ -360,7 +360,6 @@ void create_bound_listener(struct listener** listeners, struct irec* iface) {
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 @@ void create_bound_listener(struct listener** listeners, struct irec* iface) {
}
#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 @@ void create_bound_listener(struct listener** listeners, struct irec* iface) {
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 @@ void create_bound_listener(struct listener** listeners, struct irec* iface) {
if (listen(new->tcpfd, 5) == -1) die(_("failed to listen on socket: %s"), NULL, EC_BADNET);
}
+ *listeners = new;
}
/**