dnsmasq.in revision 1.1.1.10
1#!/bin/sh
2# Copyright (c) 2007-2012 Roy Marples
3# All rights reserved
4
5# dnsmasq subscriber for resolvconf
6
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#     * Redistributions of source code must retain the above copyright
11#       notice, this list of conditions and the following disclaimer.
12#     * Redistributions in binary form must reproduce the above
13#       copyright notice, this list of conditions and the following
14#       disclaimer in the documentation and/or other materials provided
15#       with the distribution.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0
30. "@SYSCONFDIR@/resolvconf.conf" || exit 1
31[ -z "$dnsmasq_conf" -a -z "$dnsmasq_resolv" ] && exit 0
32[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
33NL="
34"
35
36: ${dnsmasq_pid:=/var/run/dnsmasq.pid}
37[ -s "$dnsmasq_pid" ] || dnsmasq_pid=/var/run/dnsmasq/dnsmasq.pid
38[ -s "$dnsmasq_pid" ] || unset dnsmasq_pid
39: ${dnsmasq_service:=dnsmasq}
40: ${dnsmasq_restart:=@RESTARTCMD ${dnsmasq_service}@}
41newconf="# Generated by resolvconf$NL"
42newresolv="$newconf"
43
44# Using dbus means that we never have to restart the daemon
45# This is important as it means we should not drop DNS queries
46# whilst changing DNS options around. However, dbus support is optional
47# so we need to validate a few things first.
48# Check for DBus support in the binary
49dbus=false
50dbus_ex=false
51dbus_introspect=$(dbus-send --print-reply --system \
52	--dest=uk.org.thekelleys.dnsmasq \
53	/uk/org/thekelleys/dnsmasq \
54	org.freedesktop.DBus.Introspectable.Introspect \
55	2>/dev/null)
56if [ $? = 0 ]; then
57	dbus=true
58	if printf %s "$dbus_introspect" | \
59	    grep -q '<method name="SetDomainServers">'
60	then
61		dbus_ex=true
62	fi
63fi
64
65for n in $NAMESERVERS; do
66	newresolv="${newresolv}nameserver $n$NL"
67done
68
69dbusdest=
70dbusdest_ex=
71conf=
72for d in $DOMAINS; do
73	dn="${d%%:*}"
74	ns="${d#*:}"
75	while [ -n "$ns" ]; do
76		n="${ns%%,*}"
77		if $dbus && ! $dbus_ex; then
78			case "$n" in
79			*.*.*.*)
80				SIFS=${IFS-y} OIFS=$IFS
81				IFS=.
82				set -- $n
83				num="0x$(printf %02x $1 $2 $3 $4)"
84				if [ "$SIFS" = y ]; then
85					unset IFS
86				else
87					IFS=$OIFS
88				fi
89				dbusdest="$dbusdest uint32:$(printf %u $num)"
90				dbusdest="$dbusdest string:$dn"
91				;;
92			*:*%*)
93				# This version of dnsmasq won't accept
94				# scoped IPv6 addresses
95				dbus=false
96				;;
97			*:*)
98				SIFS=${IFS-y} OIFS=$IFS bytes= front= back=
99				empty=false i=0
100				IFS=:
101				set -- $n
102				while [ -n "$1" -o -n "$2" ]; do
103					addr="$1"
104					shift
105					if [ -z "$addr" ]; then
106						empty=true
107						continue
108					fi
109					i=$(($i + 1))
110					while [ ${#addr} -lt 4 ]; do
111						addr="0${addr}"
112					done
113					byte1="$(printf %d 0x${addr%??})"
114					byte2="$(printf %d 0x${addr#??})"
115					if $empty; then
116						back="$back byte:$byte1 byte:$byte2"
117					else
118						front="$front byte:$byte1 byte:$byte2"
119					fi
120				done
121				while [ $i != 8 ]; do
122				i=$(($i + 1))
123					front="$front byte:0 byte:0"
124				done
125				front="${front}$back"
126				if [ "$SIFS" = y ]; then
127					unset IFS
128				else
129					IFS=$OIFS
130				fi
131				dbusdest="${dbusdest}$front string:$dn"
132				;;
133			*)
134				if ! $dbus_ex; then
135					dbus=false
136				fi
137				;;
138			esac
139		fi
140		dbusdest_ex="$dbusdest_ex${dbusdest_ex:+,}/$dn/$n"
141		conf="${conf}server=/$dn/$n$NL"
142		[ "$ns" = "${ns#*,}" ] && break
143		ns="${ns#*,}"
144	done
145done
146
147if $dbus; then
148	newconf="$newconf$NL# Domain specific servers will"
149	newconf="$newconf be sent over dbus${NL}"
150else
151	newconf="$newconf$conf"
152fi
153
154# Try to ensure that config dirs exist
155if type config_mkdirs >/dev/null 2>&1; then
156	config_mkdirs "$dnsmasq_conf" "$dnsmasq_resolv"
157else
158	@SBINDIR@/resolvconf -D "$dnsmasq_conf" "$dnsmasq_resolv"
159fi
160
161changed=false
162if [ -n "$dnsmasq_conf" ]; then
163	if [ ! -f "$dnsmasq_conf" ] || \
164		[ "$(cat "$dnsmasq_conf")" != "$(printf %s "$newconf")" ]
165	then
166		changed=true
167		printf %s "$newconf" >"$dnsmasq_conf"
168	fi
169fi
170if [ -n "$dnsmasq_resolv" ]; then
171	# dnsmasq polls this file so no need to set changed=true
172	if [ -f "$dnsmasq_resolv" ]; then
173		if [ "$(cat "$dnsmasq_resolv")" != "$(printf %s "$newresolv")" ]
174		then
175			printf %s "$newresolv" >"$dnsmasq_resolv"
176		fi
177	else
178		printf %s "$newresolv" >"$dnsmasq_resolv"
179	fi
180fi
181
182if $changed; then
183	eval $dnsmasq_restart
184fi
185if $dbus; then
186	if [ -s "$dnsmasq_pid" ]; then
187        	$changed || kill -HUP $(cat "$dnsmasq_pid")
188	fi
189	# Send even if empty so old servers are cleared
190	if $dbus_ex; then
191		method=SetDomainServers
192		if [ -n "$dbusdest_ex" ]; then
193			dbusdest_ex="array:string:$dbusdest_ex"
194		fi
195		dbusdest="$dbusdest_ex"
196	else
197		method=SetServers
198	fi
199	dbus-send --system --dest=uk.org.thekelleys.dnsmasq \
200 		/uk/org/thekelleys/dnsmasq uk.org.thekelleys.$method \
201  		$dbusdest
202fi
203