1219732Sume#!/bin/sh 2304515Spfg# Copyright (c) 2007-2016 Roy Marples 3219732Sume# All rights reserved 4219732Sume 5219732Sume# dnsmasq subscriber for resolvconf 6219732Sume 7219732Sume# Redistribution and use in source and binary forms, with or without 8219732Sume# modification, are permitted provided that the following conditions 9219732Sume# are met: 10219732Sume# * Redistributions of source code must retain the above copyright 11219732Sume# notice, this list of conditions and the following disclaimer. 12219732Sume# * Redistributions in binary form must reproduce the above 13219732Sume# copyright notice, this list of conditions and the following 14219732Sume# disclaimer in the documentation and/or other materials provided 15219732Sume# with the distribution. 16219732Sume# 17219732Sume# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18219732Sume# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19219732Sume# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20219732Sume# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21219732Sume# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22219732Sume# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23219732Sume# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24219732Sume# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25219732Sume# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26219732Sume# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27219732Sume# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28219732Sume 29219732Sume[ -f "@SYSCONFDIR@"/resolvconf.conf ] || exit 0 30219732Sume. "@SYSCONFDIR@/resolvconf.conf" || exit 1 31219732Sume[ -z "$dnsmasq_conf" -a -z "$dnsmasq_resolv" ] && exit 0 32282434Sgjb[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)" 33225524ShrsNL=" 34225524Shrs" 35219732Sume 36219732Sume: ${dnsmasq_pid:=/var/run/dnsmasq.pid} 37219732Sume[ -s "$dnsmasq_pid" ] || dnsmasq_pid=/var/run/dnsmasq/dnsmasq.pid 38282434Sgjb[ -s "$dnsmasq_pid" ] || unset dnsmasq_pid 39219732Sume: ${dnsmasq_service:=dnsmasq} 40225524Shrsnewconf="# Generated by resolvconf$NL" 41219732Sumenewresolv="$newconf" 42219732Sume 43219732Sume# Using dbus means that we never have to restart the daemon 44219732Sume# This is important as it means we should not drop DNS queries 45219732Sume# whilst changing DNS options around. However, dbus support is optional 46219732Sume# so we need to validate a few things first. 47219732Sume# Check for DBus support in the binary 48219732Sumedbus=false 49282434Sgjbdbus_ex=false 50282434Sgjbdbus_introspect=$(dbus-send --print-reply --system \ 51282434Sgjb --dest=uk.org.thekelleys.dnsmasq \ 52282434Sgjb /uk/org/thekelleys/dnsmasq \ 53282434Sgjb org.freedesktop.DBus.Introspectable.Introspect \ 54282434Sgjb 2>/dev/null) 55282434Sgjbif [ $? = 0 ]; then 56282434Sgjb dbus=true 57282434Sgjb if printf %s "$dbus_introspect" | \ 58282434Sgjb grep -q '<method name="SetDomainServers">' 59219732Sume then 60282434Sgjb dbus_ex=true 61219732Sume fi 62219732Sumefi 63219732Sume 64219732Sumefor n in $NAMESERVERS; do 65225524Shrs newresolv="${newresolv}nameserver $n$NL" 66219732Sumedone 67219732Sume 68219732Sumedbusdest= 69282434Sgjbdbusdest_ex= 70282434Sgjbconf= 71219732Sumefor d in $DOMAINS; do 72219732Sume dn="${d%%:*}" 73219732Sume ns="${d#*:}" 74219732Sume while [ -n "$ns" ]; do 75282434Sgjb n="${ns%%,*}" 76282434Sgjb if $dbus && ! $dbus_ex; then 77282434Sgjb case "$n" in 78282434Sgjb *.*.*.*) 79282434Sgjb SIFS=${IFS-y} OIFS=$IFS 80282434Sgjb IFS=. 81282434Sgjb set -- $n 82282434Sgjb num="0x$(printf %02x $1 $2 $3 $4)" 83282434Sgjb if [ "$SIFS" = y ]; then 84282434Sgjb unset IFS 85282434Sgjb else 86282434Sgjb IFS=$OIFS 87282434Sgjb fi 88282434Sgjb dbusdest="$dbusdest uint32:$(printf %u $num)" 89282434Sgjb dbusdest="$dbusdest string:$dn" 90282434Sgjb ;; 91282434Sgjb *:*%*) 92282434Sgjb # This version of dnsmasq won't accept 93282434Sgjb # scoped IPv6 addresses 94282434Sgjb dbus=false 95282434Sgjb ;; 96282434Sgjb *:*) 97282434Sgjb SIFS=${IFS-y} OIFS=$IFS bytes= front= back= 98282434Sgjb empty=false i=0 99282434Sgjb IFS=: 100282434Sgjb set -- $n 101282434Sgjb while [ -n "$1" -o -n "$2" ]; do 102282434Sgjb addr="$1" 103282434Sgjb shift 104282434Sgjb if [ -z "$addr" ]; then 105282434Sgjb empty=true 106282434Sgjb continue 107282434Sgjb fi 108282434Sgjb i=$(($i + 1)) 109282434Sgjb while [ ${#addr} -lt 4 ]; do 110282434Sgjb addr="0${addr}" 111282434Sgjb done 112282434Sgjb byte1="$(printf %d 0x${addr%??})" 113282434Sgjb byte2="$(printf %d 0x${addr#??})" 114282434Sgjb if $empty; then 115282434Sgjb back="$back byte:$byte1 byte:$byte2" 116282434Sgjb else 117282434Sgjb front="$front byte:$byte1 byte:$byte2" 118282434Sgjb fi 119282434Sgjb done 120282434Sgjb while [ $i != 8 ]; do 121282434Sgjb i=$(($i + 1)) 122282434Sgjb front="$front byte:0 byte:0" 123282434Sgjb done 124282434Sgjb front="${front}$back" 125282434Sgjb if [ "$SIFS" = y ]; then 126282434Sgjb unset IFS 127282434Sgjb else 128282434Sgjb IFS=$OIFS 129282434Sgjb fi 130282434Sgjb dbusdest="${dbusdest}$front string:$dn" 131282434Sgjb ;; 132282434Sgjb *) 133282434Sgjb if ! $dbus_ex; then 134282434Sgjb dbus=false 135282434Sgjb fi 136282434Sgjb ;; 137282434Sgjb esac 138219732Sume fi 139282434Sgjb dbusdest_ex="$dbusdest_ex${dbusdest_ex:+,}/$dn/$n" 140282434Sgjb conf="${conf}server=/$dn/$n$NL" 141219732Sume [ "$ns" = "${ns#*,}" ] && break 142219732Sume ns="${ns#*,}" 143219732Sume done 144219732Sumedone 145219732Sume 146282434Sgjbif $dbus; then 147282434Sgjb newconf="$newconf$NL# Domain specific servers will" 148282434Sgjb newconf="$newconf be sent over dbus${NL}" 149282434Sgjbelse 150282434Sgjb newconf="$newconf$conf" 151282434Sgjbfi 152282434Sgjb 153282434Sgjb# Try to ensure that config dirs exist 154282434Sgjbif type config_mkdirs >/dev/null 2>&1; then 155282434Sgjb config_mkdirs "$dnsmasq_conf" "$dnsmasq_resolv" 156282434Sgjbelse 157282434Sgjb @SBINDIR@/resolvconf -D "$dnsmasq_conf" "$dnsmasq_resolv" 158282434Sgjbfi 159282434Sgjb 160219732Sumechanged=false 161219732Sumeif [ -n "$dnsmasq_conf" ]; then 162219732Sume if [ ! -f "$dnsmasq_conf" ] || \ 163225524Shrs [ "$(cat "$dnsmasq_conf")" != "$(printf %s "$newconf")" ] 164219732Sume then 165219732Sume changed=true 166225524Shrs printf %s "$newconf" >"$dnsmasq_conf" 167219732Sume fi 168219732Sumefi 169219732Sumeif [ -n "$dnsmasq_resolv" ]; then 170282434Sgjb # dnsmasq polls this file so no need to set changed=true 171219732Sume if [ -f "$dnsmasq_resolv" ]; then 172225524Shrs if [ "$(cat "$dnsmasq_resolv")" != "$(printf %s "$newresolv")" ] 173219732Sume then 174225524Shrs printf %s "$newresolv" >"$dnsmasq_resolv" 175219732Sume fi 176219732Sume else 177225524Shrs printf %s "$newresolv" >"$dnsmasq_resolv" 178219732Sume fi 179219732Sumefi 180219732Sume 181219732Sumeif $changed; then 182304515Spfg # dnsmasq does not re-read the configuration file on SIGHUP 183304515Spfg if [ -n "$dnsmasq_restart" ]; then 184304515Spfg eval $dnsmasq_restart 185304515Spfg elif [ -n "$RESTARTCMD" ]; then 186304515Spfg set -- ${dnsmasq_service} 187304515Spfg eval $RESTARTCMD 188304515Spfg else 189304515Spfg @SBINDIR@/resolvconf -r ${dnsmasq_service} 190304515Spfg fi 191219732Sumefi 192219732Sumeif $dbus; then 193282434Sgjb if [ -s "$dnsmasq_pid" ]; then 194282434Sgjb $changed || kill -HUP $(cat "$dnsmasq_pid") 195282434Sgjb fi 196219732Sume # Send even if empty so old servers are cleared 197282434Sgjb if $dbus_ex; then 198282434Sgjb method=SetDomainServers 199282434Sgjb if [ -n "$dbusdest_ex" ]; then 200282434Sgjb dbusdest_ex="array:string:$dbusdest_ex" 201282434Sgjb fi 202282434Sgjb dbusdest="$dbusdest_ex" 203282434Sgjb else 204282434Sgjb method=SetServers 205282434Sgjb fi 206219732Sume dbus-send --system --dest=uk.org.thekelleys.dnsmasq \ 207282434Sgjb /uk/org/thekelleys/dnsmasq uk.org.thekelleys.$method \ 208219732Sume $dbusdest 209219732Sumefi 210