2 # Copyright 2007 Roy Marples
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
8 # * Redistributions of source code must retain the above copyright
9 # notice, this list of conditions and the following disclaimer.
10 # * Redistributions in binary form must reproduce the above
11 # copyright notice, this list of conditions and the following
12 # disclaimer in the documentation and/or other materials provided
13 # with the distribution.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 RESOLVCONF="${PREFIX}"/etc/resolvconf
31 UPDATED="${RESOLVCONF}"/update.d
32 VARDIR="${RESOLVCONF}"/run
33 IFACEDIR="${VARDIR}/interfaces"
42 Usage: ${argv0##*/} [options]
44 Inform the system about any DNS updates.
47 -a \$INTERFACE Add DNS information to the specified interface
48 (DNS supplied via stdin in resolv.conf format)
49 -d \$INTERFACE Delete DNS information from the specified interface
50 -u Run updates from our current DNS information
51 -l [\$PATTERN] Show DNS information, optionally from interfaces
52 that match the specified pattern
53 -i [\$PATTERN] Show interfaces that have supplied DNS information
54 optionally from interfaces that match the specified
56 -v [\$PATTERN] echo NEWDOMAIN, NEWSEARCH and NEWNS variables to
58 -s \$SVC \$CMD Do \$CMD for the system service \$SVC
59 -h Show this help cruft
67 [ -n "$1" -a -e "${IFACEDIR}/$1" ] || return 1
68 echo "# resolv.conf for interface $1"
78 *) result="${result} $1";;
90 # We do our service restarting here so that our subscribers don't have to know
91 # about the OS's init system.
92 if [ "x${CMD}" = "x-s" ]; then
97 [ -z "${SERVICE}" ] && usage "Service not specified"
102 [ -z "${ACTION}" ] && usage "Action not specified"
104 # If restarting check if service is running or not if we can
105 if [ "x${ACTION}" = "xrestart" ]; then
106 if [ -s /var/run/"${SERVICE}".pid ]; then
107 kill -0 $(cat /var/run/"${SERVICE}".pid)
108 elif [ -s /var/run/"${SERVICE}"/"${SERVICE}".pid ]; then
109 kill -0 $(cat /var/run/"${SERVICE}".pid)
110 elif [ -s /var/run/"${SERVICE}"/pid ]; then
111 kill -0 $(cat /var/run/"${SERVICE}"/pid)
115 # Service not running, so don't restart
116 [ $? != 0 ] && exit 1
118 if [ -x /sbin/service ]; then
119 service "${SERVICE}" "${ACTION}" "$@"
120 elif [ -x /etc/init.d/"${SERVICE}" -a -x /sbin/runscript ]; then
121 if [ "x${ACTION}" = "xrestart" ]; then
122 /etc/init.d/"${SERVICE}" --quiet --nodeps conditionalrestart "$@"
124 /etc/init.d/"${SERVICE}" --quiet --nodeps "${ACTION}" "$@"
126 elif [ -x /etc/init.d/"${SERVICE}" ]; then
127 /etc/init.d/"${SERVICE}" "${ACTION}" "$@"
128 elif [ -x /etc/rc.d/"${SERVICE}" ]; then
129 /etc/rc.d/"${SERVICE}" "${ACTION}" "$@"
130 elif [ -x /etc/rc.d/rc."${SERVICE}" ]; then
131 /etc/rc.d/rc."${SERVICE}" "${ACTION}" "$@"
133 error_exit "Don't know how to interact with services on this platform"
143 # -l lists our resolv files, optionally for a specific interface
144 if [ "x${CMD}" = "x-l" -o "x${CMD}" = "x-i" ]; then
145 [ -d "${IFACEDIR}" ] || exit 0
147 # If we have an interface ordering list, then use that.
148 # It works by just using pathname expansion in the interface directory.
149 if [ -n "${IFACE}" ]; then
151 elif [ -r "${RESOLVCONF}"/interface-order ]; then
152 LIST="$(cat "${RESOLVCONF}"/interface-order)"
155 # If we don't have a list then prefer lo, tunnels, ppp
156 # and then anything else.
157 if [ -z "${LIST}" ]; then
158 LIST="lo lo[0-9]* tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]* *"
162 for IFACE in $(uniqify ${LIST}); do
163 # Only list interfaces which we really have
164 [ -e "${IFACE}" ] || continue
166 if [ "x${CMD}" = "x-i" ]; then
169 echo_resolv "${IFACE}"
172 [ "x${CMD}" = "x-i" ] && echo
176 if [ "x${CMD}" = "x-v" ]; then
183 LINES="$("${argv0}" -l "${IFACE}" | sed -e "s/'/'\\\\''/g" -e "s/^/'/g" -e "s/$/'/g")"
191 NS="${NS}${LINE#* } "
194 [ -z "${SEARCH}" ] && DOMAIN="${LINE#* }"
201 if [ -z "${LINE}" ]; then
203 if [ -n "${DOMAIN}" ]; then
204 NEWDOMAIN="${NEWDOMAIN} ${DOMAIN},${N}"
205 elif [ -n "${SEARCH}" ]; then
206 for S in ${SEARCH}; do
207 NEWSEARCH="${NEWSEARCH} ${S},${N}"
210 NEWNS="${NEWNS} ${N}"
221 # Prefer DOMAIN nameservers over SEARCH nameservers
222 # if we are supplied both.
223 NEWDOMAIN="$(uniqify ${NEWDOMAIN})"
224 NEWSEARCH="$(uniqify ${NEWSEARCH})"
225 NEWNS="$(uniqify ${NEWNS})"
226 for S in ${NEWSEARCH}; do
227 for DN in ${NEWDOMAIN}; do
228 if [ "${S%,*}" = "${DN%,*}" ]; then
229 NEWSEARCH="$(echo "${NEWSEARCH}" | sed -e "s/${S}/${DN}/g")"
230 NEWDOMAIN="$(echo "${NEWDOMAIN}" | sed -e "s/${DN}//g")"
236 echo "NEWDOMAIN='${NEWDOMAIN}'"
237 echo "NEWSEARCH='${NEWSEARCH}'"
238 echo "NEWNS='${NEWNS}'"
242 # Test that we have valid options
243 if [ "x${CMD}" = "x-a" -o "x${CMD}" = "x-d" ]; then
244 if [ -z "${IFACE}" ]; then
245 usage "Interface not specified"
247 elif [ "x${CMD}" != "x-u" ]; then
248 [ -n "x${CMD}" -a "x${CMD}" != "x-h" ] && usage "Unknown option ${CMD}"
251 if [ "x${CMD}" = "x-a" ]; then
252 for x in '/' \\ ' ' '*'; do
254 *[${x}]*) error_exit "${x} not allowed in interface name";;
257 for x in '.' '-' '~'; do
259 [${x}]*) error_exit "${x} not allowed at start of interface name";;
262 [ "x${CMD}" = "x-a" -a -t 0 ] && error_exit "No file given via stdin"
263 IFACERESOLV="${IFACEDIR}/${IFACE}"
266 # Ensure that libdir exists
267 if [ ! -d "${IFACEDIR}" ]; then
268 if [ ! -d "${VARDIR}" ]; then
269 if [ -L "${VARDIR}" ]; then
270 DIR="$(readlink "${VARDIR}")"
271 # Change to /etc as link maybe relative
273 if ! mkdir -m 0755 -p "${DIR}"; then
274 error_exit "Failed to create needed directory ${DIR}"
277 if ! mkdir -m 0755 -p "${VARDIR}"; then
278 error_exit "Failed to create needed directory ${VARDIR}"
282 mkdir -m 0755 -p "${IFACEDIR}" || \
283 error_exit "Failed to create needed directory ${IFACEDIR}"
285 # Delete any existing information about the interface
286 if [ "x${CMD}" = "x-a" -o "x${CMD}" = "x-d" ]; then
288 for iface in ${IFACE}; do
289 rm -f "${iface}" || exit $?
294 if [ "x${CMD}" = "x-a" ]; then
295 # Create our resolv.conf file
296 cat >"${IFACEDIR}"/"${IFACE}" || exit $?
300 for x in "${UPDATED}"/*; do
301 if [ -e "${x}" ]; then
302 "${x}" "${CMD}" "${IFACE}"
303 retval=$((${retval} + $?))