From 744231d99505cdead314d13506b5ff8c44a13088 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 27 Nov 2023 23:08:31 +0000 Subject: [PATCH] Tighten up error checking in --bind-dynamic mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In bind-dynamic mode, its OK to fail to bind a socket to an address given by --listen-address if no interface with that address exists for the time being. Dnsmasq will attempt to create the socket again when the host's network configuration changes. The code used to ignore pretty much any error from bind(), which is incorrect and can lead to confusing behaviour. This change make ONLY a return of EADDRNOTAVAIL from bind() a non-error: anything else will be fatal during startup phase, or logged after startup phase. Thanks to Petr Menšík for the problem report and first-pass patch. --- src/network.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/network.c b/src/network.c index ca9fada..f37c1d1 100644 --- a/src/network.c +++ b/src/network.c @@ -920,15 +920,24 @@ static int make_sock(union mysockaddr *addr, int type, int dienow) errno = errsave; - if (dienow) + /* Failure to bind addresses given by --listen-address at this point + because there's no interface with the address is OK if we're doing bind-dynamic. + If/when an interface is created with the relevant address we'll notice + and attempt to bind it then. This is in the generic error path so we close the socket, + but EADDRNOTAVAIL is only a possible error from bind() + + When a new address is created and we call this code again (dienow == 0) there + may still be configured addresses when don't exist, (consider >1 --listen-address, + when the first is created, the second will still be missing) so we suppress + EADDRNOTAVAIL even in that case to avoid confusing log entries. + */ + if (!option_bool(OPT_CLEVERBIND) || errno != EADDRNOTAVAIL) { - /* failure to bind addresses given by --listen-address at this point - is OK if we're doing bind-dynamic */ - if (!option_bool(OPT_CLEVERBIND)) + if (dienow) die(s, daemon->addrbuff, EC_BADNET); + else + my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno)); } - else - my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno)); return -1; }