[LEDE-DEV,v5] dnsmasq: manage resolv.conf iff when listening on 127.0.0.1#53

Message ID 20170624121154.76312-1-por@xs4all.nl
State New
Delegated to: Hans Dedecker
Headers show

Commit Message

Paul Oranje June 24, 2017, 12:11 p.m.
With this patch the dnsmasq init script manages resolv.conf if and only if
when dnsmasq will listen on 127.0.0.1#53 (is main resolver instance).
Also adds ::1 to the resolver file.

For unbound a likewise patch exists (PR#4454).
Fixes (combined with the unbound PR) FS#785

Signed-off-by: Paul Oranje <por@xs4all.nl>
---
The intended invariant is that resolv.conf is managed whenever a resolver
listens on 127.0.0.1#53. Besides dnsmasq, unbound can take that role as well 
(but only when dnsmasq is not already listens on 127.0.0.1#53).
When no instance of dnsmasq has been configured to listen on 127.0.0.1#53 then
resolv.conf is not touched by dnsmasq.

Currently unbound handles resolv.conf also, but leaves it to dnsmasq whenever
that will run, even when no dnsmasq instance will listen on localhost:53. So
for unbound PR#4454  has been submitted to make sure it always manages
resov.conf when it owns localhost:domain.


Tests performed:

- with/without unbound, dhcp linkages none and dnsmasq
- dnsmasq listens on #53, not #53 (dnsmasq takes precedence when also on #53)
- listen on localhost, not localhost
- noresolv false and true
- one/multiple dnsmasq instances (useless combinations are omitted in testing)

single dnsmasq instance
    standard setup
==> dnsmasq manages resolv.conf

two dnsmasq instances, each serving another LAN
    both dnsmasq on #53
    dnsmasq-2 notinterface loopback
==> dnsmasq-1 manages resolv.conf

two dnsmasq unstances and unbound (dhcp_link: none, one dnsmasq behind ubound)
    both dnsmasq on #53
    dnsmasq-2 on #53, notinterface loopback
        noresolv true and server 127.0.0.1#1053
    unbound on #1053
==> dnsmasq-1 manages resolv.conf

two dnsmasq instances and unbound (dhcp_link: dnsmasq)
    dnsmasq-1 on #1053, noresolv true
    dnsmasq-2 on #2053, noresolv true
    unbound on #53
        forward LAN1 to 127.0.0.1#1053, forward LAN2 to 127.0.0.1#2053
==> unbound manages resolv.conf

on stops resolv.conf is reset to the auto
   if it was written by the instance resolvfile.


History:
v2	corrected synxtax error
	increased PKG_RELEASE
v2	was reverted with commit 8180bbac7c237a31bd6e06c63e342c72342b7303
v3	rewritten and thoroughly tested
v4	corrected test on existence of resolvfile
v5	replaces cat ... case with grep in _resolv_teardown()
	rebased on master

Paul
---

 package/network/services/dnsmasq/Makefile          |  2 +-
 .../network/services/dnsmasq/files/dnsmasq.init    | 77 +++++++++++++++-------
 2 files changed, 53 insertions(+), 26 deletions(-)

Patch

diff --git a/package/network/services/dnsmasq/Makefile b/package/network/services/dnsmasq/Makefile
index 35ac6b2891..11baff37e8 100644
--- a/package/network/services/dnsmasq/Makefile
+++ b/package/network/services/dnsmasq/Makefile
@@ -9,7 +9,7 @@  include $(TOPDIR)/rules.mk
 
 PKG_NAME:=dnsmasq
 PKG_VERSION:=2.77
-PKG_RELEASE:=4
+PKG_RELEASE:=5
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
 PKG_SOURCE_URL:=http://thekelleys.org.uk/dnsmasq/
diff --git a/package/network/services/dnsmasq/files/dnsmasq.init b/package/network/services/dnsmasq/files/dnsmasq.init
index 065d1fd8c2..c16079d73a 100644
--- a/package/network/services/dnsmasq/files/dnsmasq.init
+++ b/package/network/services/dnsmasq/files/dnsmasq.init
@@ -714,9 +714,49 @@  dhcp_relay_add() {
 	fi
 }
 
+_resolv_setup()
+{
+	local cfg="$1"
+	local port notinterfaces
+
+	config_get port "$cfg" port "53"
+	[ $port = "53" ] || return
+
+	config_get notinterfaces "$cfg" notinterface ""
+	[ -n "$notinterfaces" ] && list_contains notinterfaces "loopback" && return
+
+	# dnsmasq instance is designated to listen on 127.0.0.1#53.
+	# rewrite /tmp/resolv.conf
+	rm -f /tmp/resolv.conf
+	{
+		echo "# /tmp/resolv.conf generated by dnsmasq $cfg $( date )"
+		[ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
+			echo "search $DOMAIN"
+		}
+		DNS_SERVERS="$DNS_SERVERS 127.0.0.1 ::1"
+		for DNS_SERVER in $DNS_SERVERS ; do
+			echo "nameserver $DNS_SERVER"
+		done
+	} > /tmp/resolv.conf
+
+	return
+}
+
+_resolv_teardown()
+{
+	cfg="$1"
+
+	grep -q -e "generated by dnsmasq $cfg" /tmp/resolv.conf 2>/dev/null && {
+		# resolv.conf was written by this instance,
+		# reset /tmp/resolv.conf to default.
+		[ -f /tmp/resolv.conf ] && rm -f /tmp/resolv.conf
+		ln -s /tmp/resolv.conf.auto /tmp/resolv.conf
+	}
+}
+
 dnsmasq_start()
 {
-	local cfg="$1" disabled resolvfile user_dhcpscript
+	local cfg="$1" disabled noresolv resolvfile user_dhcpscript
 
 	config_get_bool disabled "$cfg" disabled 0
 	[ "$disabled" -gt 0 ] && return 0
@@ -792,7 +832,6 @@  dnsmasq_start()
 	append_bool "$cfg" nonegcache "--no-negcache"
 	append_bool "$cfg" strictorder "--strict-order"
 	append_bool "$cfg" logqueries "--log-queries=extra"
-	append_bool "$cfg" noresolv "--no-resolv"
 	append_bool "$cfg" localise_queries "--localise-queries"
 	append_bool "$cfg" readethers "--read-ethers"
 	append_bool "$cfg" dbus "--enable-dbus"
@@ -861,14 +900,15 @@  dnsmasq_start()
 	config_get_bool cachelocal "$cfg" cachelocal 1
 
 	config_get_bool noresolv "$cfg" noresolv 0
-	if [ "$noresolv" != "1" ]; then
+	if [ "$noresolv" = "1" ]; then
+		xappend "--no-resolv"
+	else
 		config_get resolvfile "$cfg" resolvfile "/tmp/resolv.conf.auto"
+		xappend "--resolv-file=$resolvfile"
 		# So jail doesn't complain if file missing
-		[ -n "$resolvfile" -a \! -e "$resolvfile" ] && touch "$resolvfile"
+		[ ! -e "$resolvfile" ] && touch "$resolvfile"
 	fi
 
-	[ -n "$resolvfile" ] && xappend "--resolv-file=$resolvfile"
-
 	config_get hostsfile "$cfg" dhcphostsfile
 	[ -e "$hostsfile" ] && xappend "--dhcp-hostsfile=$hostsfile"
 
@@ -980,16 +1020,6 @@  dnsmasq_start()
 	echo >> $CONFIGFILE_TMP
 	mv -f $CONFIGFILE_TMP $CONFIGFILE
 
-	[ "$resolvfile" = "/tmp/resolv.conf.auto" ] && {
-		rm -f /tmp/resolv.conf
-		[ $ADD_LOCAL_DOMAIN -eq 1 ] && [ -n "$DOMAIN" ] && {
-			echo "search $DOMAIN" >> /tmp/resolv.conf
-		}
-		DNS_SERVERS="$DNS_SERVERS 127.0.0.1"
-		for DNS_SERVER in $DNS_SERVERS ; do
-			echo "nameserver $DNS_SERVER" >> /tmp/resolv.conf
-		done
-	}
 
 	procd_open_instance $cfg
 	procd_set_param command $PROG -C $CONFIGFILE -k -x /var/run/dnsmasq/dnsmasq."${cfg}".pid
@@ -1007,21 +1037,18 @@  dnsmasq_start()
 	procd_add_jail_mount_rw /var/run/dnsmasq/ $leasefile
 
 	procd_close_instance
+
+
+	# rewrite /tmp/resolv.conf only for main instance
+	_resolv_setup $cfg
 }
 
 dnsmasq_stop()
 {
 	local cfg="$1"
 
-	config_get resolvfile "$cfg" "resolvfile"
-
-	#relink /tmp/resolve.conf only for main instance
-	[ "$resolvfile" = "/tmp/resolv.conf.auto" ] && {
-		[ -f /tmp/resolv.conf ] && {
-			rm -f /tmp/resolv.conf
-			ln -s "$resolvfile" /tmp/resolv.conf
-		}
-	}
+	#relink /tmp/resolv.conf only for main instance
+	_resolv_teardown $cfg
 
 	rm -f ${BASEDHCPSTAMPFILE}.${cfg}.*.dhcp
 }