diff options
author | Tyler Wear <twear@quicinc.com> | 2020-11-11 09:20:58 -0800 |
---|---|---|
committer | Maciej Żenczykowski <maze@google.com> | 2021-01-05 18:38:43 +0000 |
commit | 8898837825af095f6bb9923d0ea5211fdeb9f3b7 (patch) | |
tree | c38b60ecb5325a4306af8886368c90655ed22a39 | |
parent | 9a192e894b5906efb6e23d8a7d27ffc57a99366d (diff) | |
download | dnsmasq-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.h | 2 | ||||
-rw-r--r-- | src/network.c | 15 |
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; } /** |