1#!/bin/sh 2# Copyright 2007 Roy Marples 3# All rights reserved 4 5# libc 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 29PREFIX= 30RESOLVCONF="${PREFIX}"/etc/resolvconf 31RESOLVCONFS="$(resolvconf -l)" 32BASE="${RESOLVCONF}/resolv.conf.d/base" 33 34uniqify() { 35 local result= 36 while [ -n "$1" ]; do 37 case " ${result} " in 38 *" $1 "*);; 39 *) result="${result} $1";; 40 esac 41 shift 42 done 43 echo "${result# *}" 44} 45 46OUR_NS= 47if [ -e "${BASE}" ]; then 48 OUR_NS="$(sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p' "${BASE}")" 49fi 50OUR_NS="$(uniqify \ 51 ${OUR_NS} \ 52 $(echo "${RESOLVCONFS}" \ 53 | sed -n -e 's/^[[:space:]]*nameserver[[:space:]]*//p') \ 54)" 55 56# libc only allows for 3 nameservers 57# truncate after 127 as well 58i=0 59NS= 60LOCALH=false 61for N in ${OUR_NS}; do 62 i=$((${i} + 1)) 63 NS="${NS} ${N}" 64 [ "${i}" = "3" ] && break 65 case "${N}" in 66 127.*) LOCALH=true; break;; 67 esac 68done 69 70# This is nasty! 71# If we have a local nameserver then assume they are intelligent enough 72# to be forwarding domain requests to the correct nameserver and not search 73# ones. This means we prefer search then domain, otherwise, we use them in 74# the order given to us. 75OUR_SEARCH= 76if ${LOCALH}; then 77 if [ -e "${BASE}" ]; then 78 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' "${BASE}")" 79 fi 80 OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \ 81 | sed -n 's/^[[:space:]]*search[[:space:]]*//p')" 82 if [ -e "${BASE}" ]; then 83 OUR_SEARCH="${OUR_SEARCH} $(sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")" 84 fi 85 OUR_SEARCH="${OUR_SEARCH} $( echo "${RESOLVCONFS}" \ 86 | sed -n -e 's/^[[:space:]]*domain[[:space:]]*//p')" 87else 88 if [ -e "${BASE}" ]; then 89 OUR_SEARCH="$(sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \ 90 -e 's/^[[:space:]]*domain[[:space:]]*//p' "${BASE}")" 91 fi 92 OUR_SEARCH="${OUR_SEARCH} $(echo "${RESOLVCONFS}" \ 93 | sed -n -e 's/^[[:space:]]*search[[:space:]]*//p' \ 94 -e 's/^[[:space:]]*domain[[:space:]]*//p')" 95fi 96 97# libc only allows for 6 search domains 98i=0 99SEARCH= 100for S in $(uniqify ${OUR_SEARCH}); do 101 i=$((${i} + 1)) 102 SEARCH="${SEARCH} ${S}" 103 [ "${i}" = "6" ] && break 104done 105[ -n "${SEARCH}" ] && SEARCH="search${SEARCH}" 106 107# Hold our new resolv.conf in a variable to save on temporary files 108NEWCONF="# Generated by resolvconf\n" 109[ -e "${RESOLVCONF}"/resolv.conf.d/head ] \ 110 && NEWCONF="${NEWCONF}$(cat "${RESOLVCONF}"/resolv.conf.d/head)\n" 111[ -n "${SEARCH}" ] && NEWCONF="${NEWCONF}${SEARCH}\n" 112for N in ${NS}; do 113 NEWCONF="${NEWCONF}nameserver ${N}\n" 114done 115 116# Now dump everything else from our resolvs 117if [ -e "${BASE}" ]; then 118 NEWCONF="${NEWCONF}$(sed -e '/^[[:space:]]*$/d' \ 119 -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \ 120 -e '/^[[:space:]]*search[[:space:]]*.*/d' \ 121 -e '/^[[:space:]]*domain[[:space:]]*.*/d' \ 122 "${BASE}")" 123fi 124 125# We don't know we're using GNU sed, so we do it like this 126NEWCONF="${NEWCONF}$(echo "${RESOLVCONFS}" | sed -e '/^[[:space:]]*$/d' \ 127 -e '/^[[:space:]]*#/d' \ 128 -e '/^[[:space:]]*nameserver[[:space:]]*.*/d' \ 129 -e '/^[[:space:]]*search[[:space:]]*.*/d' \ 130 -e '/^[[:space:]]*domain[[:space:]]*.*/d' \ 131 )" 132[ -e "${RESOLVCONF}"/resolv.conf.d/tail ] \ 133 && NEWCONF="${NEWCONF}$(cat "${RESOLVCONF}"/resolv.conf.d/tail)" 134 135# Check if the file has actually changed or not 136if [ -e "${RESOLVCONF}"/run/resolv.conf ]; then 137 [ "$(cat "${RESOLVCONF}"/run/resolv.conf)" = "$(printf "${NEWCONF}")" ] && exit 0 138fi 139 140# Create our resolv.conf now 141(umask 022; printf "${NEWCONF}" > "${RESOLVCONF}"/run/resolv.conf) 142 143resolvconf -s nscd restart 144 145# Notify users of the resolver 146for x in "${REVOLVCONF}"/update-libc.d/*; do 147 [ -e "${x}" ] && "${x}" "$@" 148done 149 150# vim: ts=4 : 151