#!/bin/sh # Copyright 2006 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # dnsmasq-resolv.conf updater # Written by Roy Marples (uberlord@gentoo.org) # This is very important! # We assume that we are a local dns cache - after all, why would a server # use resolvconf? # Now that we have assumed this, we also assume that generic DHCP clients # will enter their domains and search domains ONLY in the "search" field # in their resolv.confs and VPN clients will put the domain they are for # into the domain field only. # This allows dnsmasq to forward domains for a specific VPN domain to the # VPN nameserver and everything else to the standard name servers. # A sample dnsmasq config that works as above is like so #domain-needed #interface=lo #resolv-file=/etc/dnsmasq-resolv.conf #conf-file=/etc/dnsmasq-resolvconf.conf # The last step is to configure dns configuration for /etc/resolv.conf # for the lo interface. In Gentoo we set it up like so in /etc/conf.d/net #dns_servers_lo="127.0.0.1" # Load our variables from resolvconf VARS="$(resolvconf -v)" eval "${VARS}" DNSMASQRESOLV="/etc/dnsmasq-resolv.conf" DNSMASQCONF="/etc/dnsmasq-resolvconf.conf" NEWCONF="# Generated by resolvconf\n" NEWRESOLV="${NEWCONF}" # Using DBUS means that we never have to restart the daemon # This is important as it means we should not drop DNS queries # whilst changing DNS options around. However, DBUS support is optional # so we need to validate a few things first. # Check for DBus support in the binary DBUS=no if dnsmasq --version 2>/dev/null | \ grep -q "^Compile time options.*[[:space:]]DBus[[:space:]]" \ ; then # Sanity - check that dnsmasq and dbus are running if [ -x /etc/init.d/dbus -a -x /etc/init.d/dnsmasq ] ; then if /etc/init.d/dbus --quiet status && /etc/init.d/dnsmasq --quiet status ; then DBUS=yes NEWCONF="${NEWCONF}\n# Domain specific servers will be sent over dbus\n\nenable-dbus\n" fi fi fi uniqify() { local result= while [ -n "$1" ] ; do case " ${result} " in *" $1 "*) ;; *) result="${result} $1" ;; esac shift done echo "${result# *}" } # If we only have domain information then put it in search too [ -z "${NEWSEARCH}" -a -z "${NEWNS}" ] && NEWSEARCH="${NEWDOMAIN}" for N in ${NEWSEARCH} ; do case " ${NEWSL} " in *" ${N%,*} "*) ;; *) NEWSL="${NEWSL} ${N%,*}" ;; esac case "\n${NEWRESOLV}\n" in *"\nnameserver ${N#*,}\n"*) ;; *) NEWRESOLV="${NEWRESOLV}nameserver ${N#*,}\n" ;; esac done for N in ${NEWNS} ; do case "\n${NEWRESOLV}\n" in *"\nnameserver ${N}\n") ;; *) NEWRESOLV="${NEWRESOLV}nameserver ${N}\n" ;; esac done [ -n "${NEWSL}" ] && NEWRESOLV="${NEWRESOLV}search${NEWSL}\n" DBUSDEST= for DN in $(uniqify ${NEWDOMAIN}) ; do if [ "${DBUS}" = "yes" ] ; then IP=${DN#*,} SIFS=${IFS-y} OIFS=$IFS IFS=. set -- ${IP} NUM="0x$(printf "%02x" $1 $2 $3 $4)" if [ "${SIFS}" = "y" ] ; then IFS=$OIFS else unset IFS fi DBUSDEST="${DBUSDEST} uint32:$(printf "%d" ${NUM}) string:${DN%,*}" else NEWCONF="${NEWCONF}server=/${DN%,*}/${DN#*,}\n" fi done RELOAD="no" if [ -e "${DNSMASQCONF}" ] ; then if [ "$(cat "${DNSMASQCONF}")" != "$(printf "${NEWCONF}")" ] ; then RELOAD="yes" printf "${NEWCONF}" > "${DNSMASQCONF}" fi else RELOAD="yes" printf "${NEWCONF}" > "${DNSMASQCONF}" fi if [ -e "${DNSMASQRESOLV}" ] ; then if [ "$(cat "${DNSMASQRESOLV}")" != "$(printf "${NEWRESOLV}")" ] ; then RELOAD="yes" printf "${NEWRESOLV}" > "${DNSMASQRESOLV}" fi else # dnsmasq polls this file so no need to set RELOAD="yes" printf "${NEWRESOLV}" > "${DNSMASQRESOLV}" fi if [ "${RELOAD}" = "yes" -a -x /etc/init.d/dnsmasq ] ; then /etc/init.d/dnsmasq --quiet --nodeps conditionalrestart fi if [ "${DBUS}" = "yes" ] ; then if [ "${RELOAD}" != "yes" -a -x /etc/init.d/dnsmasq ] ; then /etc/init.d/dnsmasq --quiet reload fi # Send even if emtpy so old servers are cleared dbus-send --system --dest=uk.org.thekelleys.dnsmasq \ /uk/org/thekelleys/dnsmasq uk.org.thekelleys.SetServers \ ${DBUSDEST} fi # vim: ts=4 :