1793621c9Sroy#!/bin/sh 2*59c22029Sroy# Copyright (c) 2007-2023 Roy Marples 3793621c9Sroy# All rights reserved 4793621c9Sroy 5793621c9Sroy# libc subscriber for resolvconf 6793621c9Sroy 7793621c9Sroy# Redistribution and use in source and binary forms, with or without 8793621c9Sroy# modification, are permitted provided that the following conditions 9793621c9Sroy# are met: 10793621c9Sroy# * Redistributions of source code must retain the above copyright 11793621c9Sroy# notice, this list of conditions and the following disclaimer. 12793621c9Sroy# * Redistributions in binary form must reproduce the above 13793621c9Sroy# copyright notice, this list of conditions and the following 14793621c9Sroy# disclaimer in the documentation and/or other materials provided 15793621c9Sroy# with the distribution. 16793621c9Sroy# 17793621c9Sroy# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18793621c9Sroy# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19793621c9Sroy# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20793621c9Sroy# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21793621c9Sroy# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22793621c9Sroy# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23793621c9Sroy# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24793621c9Sroy# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25793621c9Sroy# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26793621c9Sroy# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27793621c9Sroy# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28793621c9Sroy 29793621c9SroySYSCONFDIR=@SYSCONFDIR@ 30793621c9SroyLIBEXECDIR=@LIBEXECDIR@ 31793621c9SroyVARDIR=@VARDIR@ 32793621c9SroyIFACEDIR="$VARDIR/interfaces" 33d8775c93SroyNL=" 34d8775c93Sroy" 35793621c9Sroy 36793621c9Sroy# sed may not be available, and this is faster on small files 37793621c9Sroykey_get_value() 38793621c9Sroy{ 39e37204c6Sroy key="$1" 40793621c9Sroy shift 41e37204c6Sroy 42793621c9Sroy if [ $# -eq 0 ]; then 4302c18234Sroy while read -r line; do 44793621c9Sroy case "$line" in 45793621c9Sroy "$key"*) echo "${line##$key}";; 46793621c9Sroy esac 47793621c9Sroy done 48793621c9Sroy else 4902c18234Sroy for x do 5002c18234Sroy while read -r line; do 51793621c9Sroy case "$line" in 52793621c9Sroy "$key"*) echo "${line##$key}";; 53793621c9Sroy esac 54793621c9Sroy done < "$x" 55793621c9Sroy done 56793621c9Sroy fi 57793621c9Sroy} 58793621c9Sroy 5902c18234Sroykeys_remove() 6002c18234Sroy{ 6102c18234Sroy while read -r line; do 6202c18234Sroy found=false 6302c18234Sroy for key do 6402c18234Sroy case "$line" in 6502c18234Sroy "$key"*|"#"*|" "*|" "*|"") found=true;; 6602c18234Sroy esac 6702c18234Sroy $found && break 6802c18234Sroy done 6902c18234Sroy $found || echo "$line" 7002c18234Sroy done 7102c18234Sroy} 7202c18234Sroy 73075ee3c1Sroylocal_nameservers="127.* 0.0.0.0 255.255.255.255 ::1" 74075ee3c1Sroy 75793621c9Sroy# Support original resolvconf configuration layout 76793621c9Sroy# as well as the openresolv config file 77793621c9Sroyif [ -f "$SYSCONFDIR"/resolvconf.conf ]; then 78793621c9Sroy . "$SYSCONFDIR"/resolvconf.conf 79793621c9Sroyelif [ -d "$SYSCONFDIR"/resolvconf ]; then 80e37204c6Sroy SYSCONFDIR="$SYSCONFDIR/resolvconf" 81793621c9Sroy base="$SYSCONFDIR/resolv.conf.d/base" 82793621c9Sroy if [ -f "$base" ]; then 83e9917e6eSroy prepend_nameservers="$(key_get_value "nameserver " "$base")" 8402c18234Sroy domain="$(key_get_value "domain " "$base")" 85e9917e6eSroy prepend_search="$(key_get_value "search " "$base")" 86793621c9Sroy resolv_conf_options="$(key_get_value "options " "$base")" 8702c18234Sroy resolv_conf_sortlist="$(key_get_value "sortlist " "$base")" 88793621c9Sroy fi 89793621c9Sroy if [ -f "$SYSCONFDIR"/resolv.conf.d/head ]; then 90793621c9Sroy resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.d/head)" 91793621c9Sroy fi 92793621c9Sroy if [ -f "$SYSCONFDIR"/resolv.conf.d/tail ]; then 93793621c9Sroy resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.d/tail)" 94793621c9Sroy fi 95793621c9Sroyfi 96793621c9Sroy: ${resolv_conf:=/etc/resolv.conf} 97*59c22029Sroy: ${resolv_conf_tmp:="$resolv_conf.$$.openresolv"} 98d8775c93Sroy: ${libc_service:=nscd} 99e9917e6eSroy: ${list_resolv:=@SBINDIR@/resolvconf -l} 100d7a1218eSkreif [ "${resolv_conf_head-x}" = x ] && [ -f "$SYSCONFDIR"/resolv.conf.head ] 101d7a1218eSkrethen 102793621c9Sroy resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.head)" 103793621c9Sroyfi 104d7a1218eSkreif [ "${resolv_conf_tail-x}" = x ] && [ -f "$SYSCONFDIR"/resolv.conf.tail ] 105d7a1218eSkrethen 106793621c9Sroy resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.tail)" 107793621c9Sroyfi 108793621c9Sroy 109548d7cc4Sroybackup=true 110548d7cc4Sroysignature="# Generated by resolvconf" 111548d7cc4Sroy 112793621c9Sroyuniqify() 113793621c9Sroy{ 114e37204c6Sroy result= 115793621c9Sroy while [ -n "$1" ]; do 116793621c9Sroy case " $result " in 117793621c9Sroy *" $1 "*);; 118793621c9Sroy *) result="$result $1";; 119793621c9Sroy esac 120793621c9Sroy shift 121793621c9Sroy done 122793621c9Sroy echo "${result# *}" 123793621c9Sroy} 124793621c9Sroy 125793621c9Sroycase "${resolv_conf_passthrough:-NO}" in 126793621c9Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 127548d7cc4Sroy backup=false 128793621c9Sroy newest= 129793621c9Sroy for conf in "$IFACEDIR"/*; do 130d7a1218eSkre if [ -z "$newest" ] || [ "$conf" -nt "$newest" ]; then 131793621c9Sroy newest="$conf" 132793621c9Sroy fi 133793621c9Sroy done 134793621c9Sroy [ -z "$newest" ] && exit 0 135d8775c93Sroy newconf="$(cat "$newest")$NL" 136793621c9Sroy ;; 137075ee3c1Sroy/dev/null|[Nn][Uu][Ll][Ll]) 138075ee3c1Sroy : ${resolv_conf_local_only:=NO} 139075ee3c1Sroy if [ "$local_nameservers" = "127.* 0.0.0.0 255.255.255.255 ::1" ]; then 140075ee3c1Sroy local_nameservers= 141075ee3c1Sroy fi 142075ee3c1Sroy # Need to overwrite our variables. 143075ee3c1Sroy eval "$(@SBINDIR@/resolvconf -V)" 144075ee3c1Sroy ;; 145075ee3c1Sroy 146793621c9Sroy*) 147e9917e6eSroy [ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)" 148075ee3c1Sroy ;; 149075ee3c1Sroyesac 150075ee3c1Sroycase "${resolv_conf_passthrough:-NO}" in 151075ee3c1Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;; 152075ee3c1Sroy*) 153075ee3c1Sroy : ${domain:=$DOMAIN} 154548d7cc4Sroy newsearch="$(uniqify $prepend_search $SEARCH $append_search)" 155cf0cc01bSroy NS="$LOCALNAMESERVERS $NAMESERVERS" 156cf0cc01bSroy newns= 157cf0cc01bSroy gotlocal=false 158548d7cc4Sroy for n in $(uniqify $prepend_nameservers $NS $append_nameservers); do 159cf0cc01bSroy add=true 160075ee3c1Sroy islocal=false 161075ee3c1Sroy for l in $local_nameservers; do 162cf0cc01bSroy case "$n" in 163075ee3c1Sroy $l) islocal=true; gotlocal=true; break;; 164075ee3c1Sroy esac 165075ee3c1Sroy done 166075ee3c1Sroy if ! $islocal; then 167cf0cc01bSroy case "${resolv_conf_local_only:-YES}" in 168cf0cc01bSroy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 169cf0cc01bSroy $gotlocal && add=false;; 170333b3001Sroy esac 171075ee3c1Sroy fi 172cf0cc01bSroy $add && newns="$newns $n" 173cf0cc01bSroy done 174793621c9Sroy 175793621c9Sroy # Hold our new resolv.conf in a variable to save on temporary files 176548d7cc4Sroy newconf="$signature$NL" 177793621c9Sroy if [ -n "$resolv_conf_head" ]; then 178d8775c93Sroy newconf="$newconf$resolv_conf_head$NL" 179793621c9Sroy fi 18002c18234Sroy 18102c18234Sroy [ -n "$domain" ] && newconf="${newconf}domain $domain$NL" 182d7a1218eSkre if [ -n "$newsearch" ] && [ "$newsearch" != "$domain" ]; then 18302c18234Sroy newconf="${newconf}search $newsearch$NL" 18402c18234Sroy fi 185793621c9Sroy for n in $newns; do 186d8775c93Sroy newconf="${newconf}nameserver $n$NL" 187793621c9Sroy done 188793621c9Sroy 18902c18234Sroy # Now add anything we don't care about such as sortlist and options 19002c18234Sroy stuff="$($list_resolv | keys_remove nameserver domain search)" 19102c18234Sroy if [ -n "$stuff" ]; then 19202c18234Sroy newconf="$newconf$stuff$NL" 19302c18234Sroy fi 19402c18234Sroy 19502c18234Sroy # Append any user defined ones 19602c18234Sroy if [ -n "$resolv_conf_options" ]; then 19702c18234Sroy newconf="${newconf}options $resolv_conf_options$NL" 19802c18234Sroy fi 19902c18234Sroy if [ -n "$resolv_conf_sortlist" ]; then 20002c18234Sroy newconf="${newconf}sortlist $resolv_conf_sortlist$NL" 201793621c9Sroy fi 202793621c9Sroy 203793621c9Sroy if [ -n "$resolv_conf_tail" ]; then 204d8775c93Sroy newconf="$newconf$resolv_conf_tail$NL" 205793621c9Sroy fi 206793621c9Sroy ;; 207793621c9Sroyesac 208793621c9Sroy 209793621c9Sroy# Check if the file has actually changed or not 210793621c9Sroyif [ -e "$resolv_conf" ]; then 211d8775c93Sroy [ "$(cat "$resolv_conf")" = "$(printf %s "$newconf")" ] && exit 0 212793621c9Sroyfi 213793621c9Sroy 214548d7cc4Sroy# Change is good. 215548d7cc4Sroy# If the old file does not have our signature, back it up. 216548d7cc4Sroy# If the new file just has our signature, restore the backup. 217548d7cc4Sroyif $backup; then 218548d7cc4Sroy if [ "$newconf" = "$signature$NL" ]; then 219548d7cc4Sroy if [ -e "$resolv_conf.bak" ]; then 220292189d7Sroy newconf="$(cat "$resolv_conf.bak")$NL" 221548d7cc4Sroy fi 222548d7cc4Sroy elif [ -e "$resolv_conf" ]; then 223548d7cc4Sroy read line <"$resolv_conf" 224548d7cc4Sroy if [ "$line" != "$signature" ]; then 225548d7cc4Sroy cp "$resolv_conf" "$resolv_conf.bak" 226548d7cc4Sroy fi 227548d7cc4Sroy fi 228548d7cc4Sroyfi 229548d7cc4Sroy 230*59c22029Sroy# There are pros and cons for writing directly to resolv.conf 231*59c22029Sroy# instead of a temporary file and then moving it over. 232*59c22029Sroy# The default is to write to resolv.conf as it has the least 233*59c22029Sroy# issues and has been the long standing default behaviour. 234*59c22029Sroycase "${resolv_conf_mv:-NO}" in 235*59c22029Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 236*59c22029Sroy # Protect against symlink attack, ensure new file does not exist 237*59c22029Sroy rm -f "$resolv_conf_tmp" 238*59c22029Sroy # Keep original file owner, group and mode 239*59c22029Sroy [ -r "$resolv_conf" ] && cp -p "$resolv_conf" "$resolv_conf_tmp" 240793621c9Sroy # Create our resolv.conf now 241*59c22029Sroy if (umask 022; printf %s "$newconf" >"$resolv_conf_tmp"); then 242*59c22029Sroy mv "$resolv_conf_tmp" "$resolv_conf" 243*59c22029Sroy fi 244*59c22029Sroy ;; 245*59c22029Sroy*) 24602c18234Sroy (umask 022; printf %s "$newconf" >"$resolv_conf") 247*59c22029Sroy ;; 248*59c22029Sroyesac 249*59c22029Sroy 2509d6c0475Sroyif [ -n "$libc_restart" ]; then 251793621c9Sroy eval $libc_restart 2529d6c0475Sroyelif [ -n "$RESTARTCMD" ]; then 2539d6c0475Sroy set -- ${libc_service} 2544fa65b6bSkre eval "$RESTARTCMD" 2559d6c0475Sroyelse 2569d6c0475Sroy @SBINDIR@/resolvconf -r ${libc_service} 2579d6c0475Sroyfi 258793621c9Sroy 259793621c9Sroyretval=0 260793621c9Sroy# Notify users of the resolver 261793621c9Sroyfor script in "$LIBEXECDIR"/libc.d/*; do 2625bcbb70cSroy if [ -f "$script" ]; then 2635bcbb70cSroy if [ -x "$script" ]; then 264793621c9Sroy "$script" "$@" 2655bcbb70cSroy else 266d8775c93Sroy (. "$script") 2675bcbb70cSroy fi 268793621c9Sroy retval=$(($retval + $?)) 269793621c9Sroy fi 270793621c9Sroydone 271793621c9Sroyexit $retval 272