1793621c9Sroy#!/bin/sh 2*59c22029Sroy# Copyright (c) 2007-2023 Roy Marples 3793621c9Sroy# All rights reserved 4793621c9Sroy 5793621c9Sroy# Redistribution and use in source and binary forms, with or without 6793621c9Sroy# modification, are permitted provided that the following conditions 7793621c9Sroy# are met: 8793621c9Sroy# * Redistributions of source code must retain the above copyright 9793621c9Sroy# notice, this list of conditions and the following disclaimer. 10793621c9Sroy# * Redistributions in binary form must reproduce the above 11793621c9Sroy# copyright notice, this list of conditions and the following 12793621c9Sroy# disclaimer in the documentation and/or other materials provided 13793621c9Sroy# with the distribution. 14793621c9Sroy# 15793621c9Sroy# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16793621c9Sroy# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17793621c9Sroy# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18793621c9Sroy# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19793621c9Sroy# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20793621c9Sroy# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21793621c9Sroy# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22793621c9Sroy# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23793621c9Sroy# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24793621c9Sroy# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25793621c9Sroy# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26793621c9Sroy 27793621c9SroyRESOLVCONF="$0" 28*59c22029SroyOPENRESOLV_VERSION="3.13.2" 29793621c9SroySYSCONFDIR=@SYSCONFDIR@ 30793621c9SroyLIBEXECDIR=@LIBEXECDIR@ 31793621c9SroyVARDIR=@VARDIR@ 329d6c0475SroyRCDIR=@RCDIR@ 339d6c0475SroyRESTARTCMD=@RESTARTCMD@ 34c3da4b2aSroy 35292189d7Sroyif [ "$1" = "--version" ]; then 36292189d7Sroy echo "openresolv $OPENRESOLV_VERSION" 379cbb0fe2Sroy echo "Copyright (c) 2007-2020 Roy Marples" 38292189d7Sroy exit 0 39292189d7Sroyfi 40292189d7Sroy 41c3da4b2aSroy# Disregard dhcpcd setting 42e9917e6eSroyunset interface_order state_dir 43c3da4b2aSroy 44075ee3c1Sroy# If you change this, change the test in VFLAG and libc.in as well 45075ee3c1Sroylocal_nameservers="127.* 0.0.0.0 255.255.255.255 ::1" 46075ee3c1Sroy 479cbb0fe2Sroydynamic_order="tap[0-9]* tun[0-9]* vpn vpn[0-9]* wg[0-9]* ppp[0-9]* ippp[0-9]*" 48075ee3c1Sroyinterface_order="lo lo[0-9]*" 49075ee3c1Sroyname_server_blacklist="0.0.0.0" 50075ee3c1Sroy 51793621c9Sroy# Support original resolvconf configuration layout 52793621c9Sroy# as well as the openresolv config file 53793621c9Sroyif [ -f "$SYSCONFDIR"/resolvconf.conf ]; then 54793621c9Sroy . "$SYSCONFDIR"/resolvconf.conf 55793621c9Sroy [ -n "$state_dir" ] && VARDIR="$state_dir" 56793621c9Sroyelif [ -d "$SYSCONFDIR/resolvconf" ]; then 57793621c9Sroy SYSCONFDIR="$SYSCONFDIR/resolvconf" 58793621c9Sroy if [ -f "$SYSCONFDIR"/interface-order ]; then 59793621c9Sroy interface_order="$(cat "$SYSCONFDIR"/interface-order)" 60793621c9Sroy fi 61793621c9Sroyfi 629cbb0fe2Sroy 63793621c9SroyIFACEDIR="$VARDIR/interfaces" 64793621c9SroyMETRICDIR="$VARDIR/metrics" 65793621c9SroyPRIVATEDIR="$VARDIR/private" 664ac8d7d2SroyEXCLUSIVEDIR="$VARDIR/exclusive" 670949b2edSroyDEPRECATEDDIR="$VARDIR/deprecated" 68075ee3c1SroyLOCKDIR="$VARDIR/lock" 692644931fSroy_PWD="$PWD" 70793621c9Sroy 71075ee3c1Sroywarn() 72075ee3c1Sroy{ 73075ee3c1Sroy echo "$*" >&2 74075ee3c1Sroy} 75793621c9Sroy 76793621c9Sroyerror_exit() 77793621c9Sroy{ 78793621c9Sroy echo "$*" >&2 79793621c9Sroy exit 1 80793621c9Sroy} 81793621c9Sroy 82793621c9Sroyusage() 83793621c9Sroy{ 84793621c9Sroy cat <<-EOF 859d6c0475Sroy Usage: ${RESOLVCONF##*/} [options] command [argument] 86793621c9Sroy 87793621c9Sroy Inform the system about any DNS updates. 88793621c9Sroy 899d6c0475Sroy Commands: 90793621c9Sroy -a \$INTERFACE Add DNS information to the specified interface 91793621c9Sroy (DNS supplied via stdin in resolv.conf format) 920949b2edSroy -C \$PATTERN Deprecate DNS information for matched interfaces 930949b2edSroy -c \$PATTERN Configure DNS information for matched interfaces 94793621c9Sroy -d \$INTERFACE Delete DNS information from the specified interface 959d6c0475Sroy -h Show this help cruft 96793621c9Sroy -i [\$PATTERN] Show interfaces that have supplied DNS information 97793621c9Sroy optionally from interfaces that match the specified 98793621c9Sroy pattern 999d6c0475Sroy -l [\$PATTERN] Show DNS information, optionally from interfaces 1009d6c0475Sroy that match the specified pattern 1019d6c0475Sroy 1029d6c0475Sroy -u Run updates from our current DNS information 103292189d7Sroy --version Echo the ${RESOLVCONF##*/} version 1049d6c0475Sroy 1059d6c0475Sroy Options: 106292189d7Sroy -f Ignore non existent interfaces 1079d6c0475Sroy -m metric Give the added DNS information a metric 1089d6c0475Sroy -p Mark the interface as private 1099d6c0475Sroy -x Mark the interface as exclusive 1109d6c0475Sroy 1119d6c0475Sroy Subscriber and System Init Commands: 1129d6c0475Sroy -I Init the state dir 1139d6c0475Sroy -r \$SERVICE Restart the system service 1149d6c0475Sroy (restarting a non-existent or non-running service 1159d6c0475Sroy should have no output and return 0) 1169d6c0475Sroy -R Show the system service restart command 117793621c9Sroy -v [\$PATTERN] echo NEWDOMAIN, NEWSEARCH and NEWNS variables to 118793621c9Sroy the console 1199d6c0475Sroy -V [\$PATTERN] Same as -v, but only uses configuration in 1209d6c0475Sroy $SYSCONFDIR/resolvconf.conf 121793621c9Sroy EOF 122793621c9Sroy [ -z "$1" ] && exit 0 123793621c9Sroy echo 124793621c9Sroy error_exit "$*" 125793621c9Sroy} 126793621c9Sroy 1272644931fSroy# Strip any trailing dot from each name as a FQDN does not belong 1282644931fSroy# in resolv.conf(5) 1292644931fSroy# If you think otherwise, capture a DNS trace and you'll see libc 1302644931fSroy# will strip it regardless. 1312644931fSroy# This also solves setting up duplicate zones in our subscribers. 132e37204c6Sroy# Also strip any comments denoted by #. 133e37204c6Sroyresolv_strip() 1342644931fSroy{ 135e37204c6Sroy space= 136e37204c6Sroy for word; do 137e37204c6Sroy case "$word" in 138e37204c6Sroy \#*) break;; 139e37204c6Sroy esac 140e37204c6Sroy printf "%s%s" "$space${word%.}" 141e37204c6Sroy space=" " 1422644931fSroy done 1432644931fSroy printf "\n" 1442644931fSroy} 1452644931fSroy 146292189d7Sroyprivate_iface() 147292189d7Sroy{ 148292189d7Sroy # Allow expansion 149292189d7Sroy cd "$IFACEDIR" 150292189d7Sroy 151292189d7Sroy # Public interfaces override private ones. 152292189d7Sroy for p in $public_interfaces; do 153292189d7Sroy case "$iface" in 154292189d7Sroy "$p"|"$p":*) return 1;; 155292189d7Sroy esac 156292189d7Sroy done 157292189d7Sroy 158292189d7Sroy if [ -e "$PRIVATEDIR/$iface" ]; then 159292189d7Sroy return 0 160292189d7Sroy fi 161292189d7Sroy 162292189d7Sroy for p in $private_interfaces; do 163292189d7Sroy case "$iface" in 164292189d7Sroy "$p"|"$p":*) return 0;; 165292189d7Sroy esac 166292189d7Sroy done 167292189d7Sroy 168292189d7Sroy # Not a private interface 169292189d7Sroy return 1 170292189d7Sroy} 171292189d7Sroy 172793621c9Sroy# Parse resolv.conf's and make variables 173793621c9Sroy# for domain name servers, search name servers and global nameservers 174793621c9Sroyparse_resolv() 175793621c9Sroy{ 176e37204c6Sroy domain= 177e37204c6Sroy new=true 178d8775c93Sroy newns= 179e37204c6Sroy ns= 180e37204c6Sroy private=false 181e37204c6Sroy search= 182793621c9Sroy 18302c18234Sroy while read -r line; do 184e37204c6Sroy stripped_line="$(resolv_strip ${line#* })" 185793621c9Sroy case "$line" in 186793621c9Sroy "# resolv.conf from "*) 187793621c9Sroy if ${new}; then 188793621c9Sroy iface="${line#\# resolv.conf from *}" 189793621c9Sroy new=false 190292189d7Sroy if private_iface "$iface"; then 191793621c9Sroy private=true 192793621c9Sroy else 193793621c9Sroy private=false 1945bcbb70cSroy fi 195793621c9Sroy fi 196793621c9Sroy ;; 197793621c9Sroy "nameserver "*) 198075ee3c1Sroy islocal=false 199075ee3c1Sroy for l in $local_nameservers; do 200e37204c6Sroy case "$stripped_line" in 201075ee3c1Sroy $l) 202075ee3c1Sroy islocal=true 203075ee3c1Sroy break 204d8775c93Sroy ;; 205793621c9Sroy esac 206075ee3c1Sroy done 207e37204c6Sroy if $islocal; then 208e37204c6Sroy echo "LOCALNAMESERVERS=\"\$LOCALNAMESERVERS $stripped_line\"" 209e37204c6Sroy else 210e37204c6Sroy ns="$ns$stripped_line " 211e37204c6Sroy fi 212793621c9Sroy ;; 21302c18234Sroy "domain "*) 214e37204c6Sroy search="$stripped_line" 21502c18234Sroy if [ -z "$domain" ]; then 2162644931fSroy domain="$search" 21702c18234Sroy echo "DOMAIN=\"$domain\"" 21802c18234Sroy fi 21902c18234Sroy ;; 22002c18234Sroy "search "*) 221e37204c6Sroy search="$stripped_line" 222793621c9Sroy ;; 223793621c9Sroy *) 224793621c9Sroy [ -n "$line" ] && continue 225d7a1218eSkre if [ -n "$ns" ] && [ -n "$search" ]; then 226793621c9Sroy newns= 227793621c9Sroy for n in $ns; do 228793621c9Sroy newns="$newns${newns:+,}$n" 229793621c9Sroy done 230793621c9Sroy ds= 231793621c9Sroy for d in $search; do 232793621c9Sroy ds="$ds${ds:+ }$d:$newns" 233793621c9Sroy done 234793621c9Sroy echo "DOMAINS=\"\$DOMAINS $ds\"" 235793621c9Sroy fi 236793621c9Sroy echo "SEARCH=\"\$SEARCH $search\"" 237793621c9Sroy if ! $private; then 238793621c9Sroy echo "NAMESERVERS=\"\$NAMESERVERS $ns\"" 239793621c9Sroy fi 240793621c9Sroy ns= 241793621c9Sroy search= 242793621c9Sroy new=true 243793621c9Sroy ;; 244793621c9Sroy esac 245793621c9Sroy done 246793621c9Sroy} 247793621c9Sroy 248793621c9Sroyuniqify() 249793621c9Sroy{ 250e37204c6Sroy result= 251793621c9Sroy while [ -n "$1" ]; do 252793621c9Sroy case " $result " in 253793621c9Sroy *" $1 "*);; 254793621c9Sroy *) result="$result $1";; 255793621c9Sroy esac 256793621c9Sroy shift 257793621c9Sroy done 258793621c9Sroy echo "${result# *}" 259793621c9Sroy} 260793621c9Sroy 26102c18234Sroydirname() 26202c18234Sroy{ 263e37204c6Sroy OIFS="$IFS" 264e37204c6Sroy IFS=/ 26502c18234Sroy set -- $@ 26602c18234Sroy IFS="$OIFS" 26702c18234Sroy if [ -n "$1" ]; then 26802c18234Sroy printf %s . 26902c18234Sroy else 27002c18234Sroy shift 27102c18234Sroy fi 27202c18234Sroy while [ -n "$2" ]; do 27302c18234Sroy printf "/%s" "$1" 27402c18234Sroy shift 27502c18234Sroy done 27602c18234Sroy printf "\n" 27702c18234Sroy} 27802c18234Sroy 27902c18234Sroyconfig_mkdirs() 28002c18234Sroy{ 28102c18234Sroy for f; do 28202c18234Sroy [ -n "$f" ] || continue 28302c18234Sroy d="$(dirname "$f")" 28402c18234Sroy if [ ! -d "$d" ]; then 2850949b2edSroy mkdir -p "$d" || return $? 28602c18234Sroy fi 28702c18234Sroy done 2880949b2edSroy return 0 28902c18234Sroy} 29002c18234Sroy 2919d6c0475Sroy# With the advent of alternative init systems, it's possible to have 2929d6c0475Sroy# more than one installed. So we need to try and guess what one we're 293*59c22029Sroy# using unless overridden by configure. 2949d6c0475Sroy# Note that restarting a service is a last resort - the subscribers 295*59c22029Sroy# should make a reasonable attempt to reconfigure the service via some 2969d6c0475Sroy# method, normally SIGHUP. 2979d6c0475Sroydetect_init() 2989d6c0475Sroy{ 2999d6c0475Sroy [ -n "$RESTARTCMD" ] && return 0 3009d6c0475Sroy 3019d6c0475Sroy # Detect the running init system. 3029d6c0475Sroy # As systemd and OpenRC can be installed on top of legacy init 3039d6c0475Sroy # systems we try to detect them first. 304e37204c6Sroy status="@STATUSARG@" 3059d6c0475Sroy : ${status:=status} 306d7a1218eSkre if [ -x /bin/systemctl ] && [ -S /run/systemd/private ]; then 307d7a1218eSkre RESTARTCMD=' 308d7a1218eSkre if /bin/systemctl --quiet is-active $1.service 3099d6c0475Sroy then 310d7a1218eSkre /bin/systemctl restart $1.service 311d7a1218eSkre fi' 312d7a1218eSkre elif [ -x /usr/bin/systemctl ] && [ -S /run/systemd/private ]; then 313d7a1218eSkre RESTARTCMD=' 314d7a1218eSkre if /usr/bin/systemctl --quiet is-active $1.service 315d7a1218eSkre then 316d7a1218eSkre /usr/bin/systemctl restart $1.service 317d7a1218eSkre fi' 318e37204c6Sroy elif [ -x /sbin/rc-service ] && 319e37204c6Sroy { [ -s /libexec/rc/init.d/softlevel ] || 320e37204c6Sroy [ -s /run/openrc/softlevel ]; } 321d7a1218eSkre then 322d7a1218eSkre RESTARTCMD='/sbin/rc-service -i $1 -- -Ds restart' 3239d6c0475Sroy elif [ -x /usr/sbin/invoke-rc.d ]; then 3249d6c0475Sroy RCDIR=/etc/init.d 325d7a1218eSkre RESTARTCMD=' 326d7a1218eSkre if /usr/sbin/invoke-rc.d --quiet $1 status >/dev/null 2>&1 327d7a1218eSkre then 328d7a1218eSkre /usr/sbin/invoke-rc.d $1 restart 329d7a1218eSkre fi' 330*59c22029Sroy elif [ -x /usr/bin/s6-rc ] && [ -x /usr/bin/s6-svc ]; then 331*59c22029Sroy RESTARTCMD=' 332*59c22029Sroy if s6-rc -a list | grep -qFx $1-srv 333*59c22029Sroy then 334*59c22029Sroy s6-svc -r /run/service/$1-srv 335*59c22029Sroy fi' 3369d6c0475Sroy elif [ -x /sbin/service ]; then 3379d6c0475Sroy # Old RedHat 3389d6c0475Sroy RCDIR=/etc/init.d 339d7a1218eSkre RESTARTCMD=' 340d7a1218eSkre if /sbin/service $1; then 341d7a1218eSkre /sbin/service $1 restart 342d7a1218eSkre fi' 3439d6c0475Sroy elif [ -x /usr/sbin/service ]; then 3449d6c0475Sroy # Could be FreeBSD 3454113b4f7Skre RESTARTCMD=" 3464113b4f7Skre if /usr/sbin/service \$1 $status >/dev/null 2>&1 347d7a1218eSkre then 3484113b4f7Skre /usr/sbin/service \$1 restart 3494113b4f7Skre fi" 3509d6c0475Sroy elif [ -x /bin/sv ]; then 351d7a1218eSkre RESTARTCMD='/bin/sv status $1 >/dev/null 2>&1 && 352d7a1218eSkre /bin/sv try-restart $1' 3539d6c0475Sroy elif [ -x /usr/bin/sv ]; then 354d7a1218eSkre RESTARTCMD='/usr/bin/sv status $1 >/dev/null 2>&1 && 355d7a1218eSkre /usr/bin/sv try-restart $1' 356d7a1218eSkre elif [ -e /etc/arch-release ] && [ -d /etc/rc.d ]; then 3579d6c0475Sroy RCDIR=/etc/rc.d 358d7a1218eSkre RESTARTCMD=' 359d7a1218eSkre if [ -e /var/run/daemons/$1 ] 360d7a1218eSkre then 361d7a1218eSkre /etc/rc.d/$1 restart 362d7a1218eSkre fi' 363d7a1218eSkre elif [ -e /etc/slackware-version ] && [ -d /etc/rc.d ]; then 364d7a1218eSkre RESTARTCMD=' 365d7a1218eSkre if /etc/rc.d/rc.$1 status >/dev/null 2>&1 366d7a1218eSkre then 367d7a1218eSkre /etc/rc.d/rc.$1 restart 368d7a1218eSkre fi' 369d7a1218eSkre elif [ -e /etc/rc.d/rc.subr ] && [ -d /etc/rc.d ]; then 3709d6c0475Sroy # OpenBSD 371d7a1218eSkre RESTARTCMD=' 372d7a1218eSkre if /etc/rc.d/$1 check >/dev/null 2>&1 373d7a1218eSkre then 374d7a1218eSkre /etc/rc.d/$1 restart 375d7a1218eSkre fi' 376*59c22029Sroy elif [ -d /etc/dinit.d ] && command -v dinitctl >/dev/null 2>&1; then 377*59c22029Sroy RESTARTCMD='dinitctl --quiet restart --ignore-unstarted $1' 3789d6c0475Sroy else 3799d6c0475Sroy for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do 3809d6c0475Sroy [ -d $x ] || continue 381d7a1218eSkre RESTARTCMD=" 382d7a1218eSkre if $x/\$1 $status >/dev/null 2>&1 383d7a1218eSkre then 384d7a1218eSkre $x/\$1 restart 3859d6c0475Sroy fi" 3869d6c0475Sroy break 3879d6c0475Sroy done 3889d6c0475Sroy fi 3899d6c0475Sroy 3909d6c0475Sroy if [ -z "$RESTARTCMD" ]; then 391d7a1218eSkre if [ "$_NOINIT_WARNED" != true ]; then 3929d6c0475Sroy warn "could not detect a useable init system" 3939d6c0475Sroy _NOINIT_WARNED=true 3949d6c0475Sroy fi 3959d6c0475Sroy return 1 3969d6c0475Sroy fi 3979d6c0475Sroy _NOINIT_WARNED= 3989d6c0475Sroy return 0 3999d6c0475Sroy} 4009d6c0475Sroy 4019d6c0475Sroyecho_resolv() 4029d6c0475Sroy{ 403e37204c6Sroy OIFS="$IFS" 4049d6c0475Sroy 405d7a1218eSkre [ -n "$1" ] && [ -f "$IFACEDIR/$1" ] || return 1 4069d6c0475Sroy echo "# resolv.conf from $1" 4079d6c0475Sroy # Our variable maker works of the fact each resolv.conf per interface 4089d6c0475Sroy # is separated by blank lines. 4099d6c0475Sroy # So we remove them when echoing them. 4109d6c0475Sroy while read -r line; do 4119d6c0475Sroy IFS="$OIFS" 4129d6c0475Sroy if [ -n "$line" ]; then 4139d6c0475Sroy # We need to set IFS here to preserve any whitespace 4149d6c0475Sroy IFS='' 4159d6c0475Sroy printf "%s\n" "$line" 4169d6c0475Sroy fi 4179d6c0475Sroy done < "$IFACEDIR/$1" 4189d6c0475Sroy IFS="$OIFS" 4199d6c0475Sroy} 4209d6c0475Sroy 4210949b2edSroydeprecated_interface() 4220949b2edSroy{ 4230949b2edSroy [ -d "$DEPRECATEDDIR" ] || return 1 4240949b2edSroy 4250949b2edSroy cd "$DEPRECATEDDIR" 4260949b2edSroy for da; do 4270949b2edSroy for daf in *; do 4280949b2edSroy [ -f "$daf" ] || continue 4290949b2edSroy case "$da" in 4300949b2edSroy $daf) return 0;; 4310949b2edSroy esac 4320949b2edSroy done 4330949b2edSroy done 4340949b2edSroy return 1 4350949b2edSroy} 4360949b2edSroy 437793621c9Sroylist_resolv() 438793621c9Sroy{ 439793621c9Sroy [ -d "$IFACEDIR" ] || return 0 440793621c9Sroy 441e37204c6Sroy cmd="$1" 442793621c9Sroy shift 443*59c22029Sroy pattern_specified="$1" 444*59c22029Sroy 445e37204c6Sroy excl=false 446e37204c6Sroy list= 447e37204c6Sroy report=false 448e37204c6Sroy retval=0 449793621c9Sroy 4504ac8d7d2Sroy case "$IF_EXCLUSIVE" in 4514ac8d7d2Sroy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 452e37204c6Sroy excl=true 4534ac8d7d2Sroy if [ -d "$EXCLUSIVEDIR" ]; then 4544ac8d7d2Sroy cd "$EXCLUSIVEDIR" 4554ac8d7d2Sroy for i in *; do 4564ac8d7d2Sroy if [ -f "$i" ]; then 4574ac8d7d2Sroy list="${i#* }" 4584ac8d7d2Sroy break 4594ac8d7d2Sroy fi 4604ac8d7d2Sroy done 4614ac8d7d2Sroy fi 462292189d7Sroy cd "$IFACEDIR" 463292189d7Sroy for i in $inclusive_interfaces; do 464d7a1218eSkre if [ -f "$i" ] && [ "$list" = "$i" ]; then 465292189d7Sroy list= 466292189d7Sroy excl=false 467292189d7Sroy break 468292189d7Sroy fi 469292189d7Sroy done 4704ac8d7d2Sroy ;; 4714ac8d7d2Sroy esac 4724ac8d7d2Sroy 473793621c9Sroy # If we have an interface ordering list, then use that. 474793621c9Sroy # It works by just using pathname expansion in the interface directory. 475*59c22029Sroy if [ -n "$pattern_specified" ]; then 476d8775c93Sroy list="$*" 477793621c9Sroy $force || report=true 4784ac8d7d2Sroy elif ! $excl; then 479793621c9Sroy cd "$IFACEDIR" 4800949b2edSroy 481793621c9Sroy for i in $interface_order; do 4824ac8d7d2Sroy [ -f "$i" ] && list="$list $i" 4834ac8d7d2Sroy for ii in "$i":* "$i".*; do 4844ac8d7d2Sroy [ -f "$ii" ] && list="$list $ii" 485327a6ebcSroy done 486793621c9Sroy done 4870949b2edSroy 488793621c9Sroy for i in $dynamic_order; do 489d7a1218eSkre if [ -e "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then 490793621c9Sroy list="$list $i" 491793621c9Sroy fi 4924ac8d7d2Sroy for ii in "$i":* "$i".*; do 493d7a1218eSkre if [ -f "$ii" ] && ! [ -e "$METRICDIR/"*" $ii" ] 494d7a1218eSkre then 495327a6ebcSroy list="$list $ii" 496327a6ebcSroy fi 497327a6ebcSroy done 498793621c9Sroy done 4990949b2edSroy 500e37204c6Sroy # Interfaces have an implicit metric of 0 if not specified. 501e37204c6Sroy for i in *; do 502e37204c6Sroy if [ -f "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then 503e37204c6Sroy list="$list $i" 504e37204c6Sroy fi 505e37204c6Sroy done 5060949b2edSroy 507793621c9Sroy if [ -d "$METRICDIR" ]; then 508793621c9Sroy cd "$METRICDIR" 509793621c9Sroy for i in *; do 5104ac8d7d2Sroy [ -f "$i" ] && list="$list ${i#* }" 511793621c9Sroy done 512793621c9Sroy fi 5130949b2edSroy 5140949b2edSroy # Move deprecated interfaces to the back 5150949b2edSroy active= 5160949b2edSroy deprecated= 5170949b2edSroy for i in $list; do 5180949b2edSroy if deprecated_interface "$i"; then 5190949b2edSroy deprecated="$deprecated $i" 5200949b2edSroy else 5210949b2edSroy active="$active $i" 5220949b2edSroy fi 5230949b2edSroy done 5240949b2edSroy list="$active $deprecated" 525793621c9Sroy fi 526793621c9Sroy 527793621c9Sroy cd "$IFACEDIR" 528*59c22029Sroy if $excl || [ -n "$pattern_specified" ]; then 5294ac8d7d2Sroy retval=1 530*59c22029Sroy else 531*59c22029Sroy retval=0 532*59c22029Sroy fi 533793621c9Sroy for i in $(uniqify $list); do 534793621c9Sroy # Only list interfaces which we really have 5354ac8d7d2Sroy if ! [ -f "$i" ]; then 536793621c9Sroy if $report; then 537793621c9Sroy echo "No resolv.conf for interface $i" >&2 5384ac8d7d2Sroy retval=2 539793621c9Sroy fi 540793621c9Sroy continue 541793621c9Sroy fi 542793621c9Sroy 5439cbb0fe2Sroy if ! $ALLIFACES; then 5449cbb0fe2Sroy if [ -n "$allow_interfaces" ]; then 5459cbb0fe2Sroy x=false 5469cbb0fe2Sroy for j in $allow_interfaces; do 5479cbb0fe2Sroy if [ "$i" = "$j" ]; then 5489cbb0fe2Sroy x=true 5499cbb0fe2Sroy fi 5509cbb0fe2Sroy done 5519cbb0fe2Sroy $x || continue 5529cbb0fe2Sroy fi 5539cbb0fe2Sroy for j in $deny_interfaces; do 5549cbb0fe2Sroy if [ "$i" = "$j" ]; then 5559cbb0fe2Sroy continue 2 5569cbb0fe2Sroy fi 5579cbb0fe2Sroy done 5589cbb0fe2Sroy fi 5599cbb0fe2Sroy 560d7a1218eSkre if [ "$cmd" = i ] || [ "$cmd" = "-i" ]; then 56102c18234Sroy printf %s "$i " 562793621c9Sroy else 563292189d7Sroy echo_resolv "$i" && echo 564793621c9Sroy fi 565d7a1218eSkre [ $? = 0 ] && [ "$retval" = 1 ] && retval=0 566793621c9Sroy done 567d7a1218eSkre [ "$cmd" = i ] || [ "$cmd" = "-i" ] && echo 568793621c9Sroy return $retval 569793621c9Sroy} 570793621c9Sroy 571e37204c6Sroylist_remove() 572e37204c6Sroy{ 573333b3001Sroy [ -z "$2" ] && return 0 574333b3001Sroy eval list=\"\$$1\" 575333b3001Sroy shift 576e37204c6Sroy result= 577e37204c6Sroy retval=0 578333b3001Sroy 579333b3001Sroy set -f 580333b3001Sroy for e; do 581333b3001Sroy found=false 582333b3001Sroy for l in $list; do 583333b3001Sroy case "$e" in 584333b3001Sroy $l) found=true;; 585333b3001Sroy esac 586333b3001Sroy $found && break 587333b3001Sroy done 588333b3001Sroy if $found; then 589333b3001Sroy retval=$(($retval + 1)) 590333b3001Sroy else 591333b3001Sroy result="$result $e" 592333b3001Sroy fi 593333b3001Sroy done 594333b3001Sroy set +f 595333b3001Sroy echo "${result# *}" 596333b3001Sroy return $retval 597333b3001Sroy} 598333b3001Sroy 599e9917e6eSroyecho_prepend() 600e9917e6eSroy{ 601e9917e6eSroy echo "# Generated by resolvconf" 602e9917e6eSroy if [ -n "$search_domains" ]; then 603e9917e6eSroy echo "search $search_domains" 604e9917e6eSroy fi 605e9917e6eSroy for n in $name_servers; do 606e9917e6eSroy echo "nameserver $n" 607e9917e6eSroy done 608e9917e6eSroy echo 609e9917e6eSroy} 610e9917e6eSroy 611e9917e6eSroyecho_append() 612e9917e6eSroy{ 613e9917e6eSroy echo "# Generated by resolvconf" 614e9917e6eSroy if [ -n "$search_domains_append" ]; then 615e9917e6eSroy echo "search $search_domains_append" 616e9917e6eSroy fi 617e9917e6eSroy for n in $name_servers_append; do 618e9917e6eSroy echo "nameserver $n" 619e9917e6eSroy done 620e9917e6eSroy echo 621e9917e6eSroy} 622e9917e6eSroy 623548d7cc4Sroyreplace() 624548d7cc4Sroy{ 625548d7cc4Sroy while read -r keyword value; do 626548d7cc4Sroy for r in $replace; do 627548d7cc4Sroy k="${r%%/*}" 628548d7cc4Sroy r="${r#*/}" 629548d7cc4Sroy f="${r%%/*}" 630548d7cc4Sroy r="${r#*/}" 631548d7cc4Sroy v="${r%%/*}" 632548d7cc4Sroy case "$keyword" in 633548d7cc4Sroy $k) 634548d7cc4Sroy case "$value" in 635548d7cc4Sroy $f) value="$v";; 636548d7cc4Sroy esac 637548d7cc4Sroy ;; 638548d7cc4Sroy esac 639548d7cc4Sroy done 640548d7cc4Sroy val= 641548d7cc4Sroy for sub in $value; do 642548d7cc4Sroy for r in $replace_sub; do 643548d7cc4Sroy k="${r%%/*}" 644548d7cc4Sroy r="${r#*/}" 645548d7cc4Sroy f="${r%%/*}" 646548d7cc4Sroy r="${r#*/}" 647548d7cc4Sroy v="${r%%/*}" 648548d7cc4Sroy case "$keyword" in 649548d7cc4Sroy $k) 650548d7cc4Sroy case "$sub" in 651548d7cc4Sroy $f) sub="$v";; 652548d7cc4Sroy esac 653548d7cc4Sroy ;; 654548d7cc4Sroy esac 655548d7cc4Sroy done 656548d7cc4Sroy val="$val${val:+ }$sub" 657548d7cc4Sroy done 658548d7cc4Sroy printf "%s %s\n" "$keyword" "$val" 659548d7cc4Sroy done 660548d7cc4Sroy} 661548d7cc4Sroy 662793621c9Sroymake_vars() 663793621c9Sroy{ 664e9917e6eSroy # Clear variables 665e9917e6eSroy DOMAIN= 666e9917e6eSroy DOMAINS= 667e9917e6eSroy SEARCH= 668e9917e6eSroy NAMESERVERS= 669e9917e6eSroy LOCALNAMESERVERS= 670e9917e6eSroy 671d7a1218eSkre if [ -n "${name_servers}${search_domains}" ]; then 672e9917e6eSroy eval "$(echo_prepend | parse_resolv)" 673e9917e6eSroy fi 674075ee3c1Sroy if [ -z "$VFLAG" ]; then 6754ac8d7d2Sroy IF_EXCLUSIVE=1 6764ac8d7d2Sroy list_resolv -i "$@" >/dev/null || IF_EXCLUSIVE=0 677548d7cc4Sroy eval "$(list_resolv -l "$@" | replace | parse_resolv)" 678075ee3c1Sroy fi 679871fbadaSryoon if [ -n "${name_servers_append}${search_domains_append}" ]; then 680e9917e6eSroy eval "$(echo_append | parse_resolv)" 681e9917e6eSroy fi 682793621c9Sroy 683793621c9Sroy # Ensure that we only list each domain once 684e37204c6Sroy newdomains= 685793621c9Sroy for d in $DOMAINS; do 686793621c9Sroy dn="${d%%:*}" 687333b3001Sroy list_remove domain_blacklist "$dn" >/dev/null || continue 688793621c9Sroy case " $newdomains" in 689793621c9Sroy *" ${dn}:"*) continue;; 690793621c9Sroy esac 691793621c9Sroy newns= 692793621c9Sroy for nd in $DOMAINS; do 693793621c9Sroy if [ "$dn" = "${nd%%:*}" ]; then 694793621c9Sroy ns="${nd#*:}" 695793621c9Sroy while [ -n "$ns" ]; do 696793621c9Sroy case ",$newns," in 697793621c9Sroy *,${ns%%,*},*) ;; 698333b3001Sroy *) list_remove name_server_blacklist \ 699075ee3c1Sroy "${ns%%,*}" >/dev/null \ 700333b3001Sroy && newns="$newns${newns:+,}${ns%%,*}";; 701793621c9Sroy esac 702793621c9Sroy [ "$ns" = "${ns#*,}" ] && break 703793621c9Sroy ns="${ns#*,}" 704793621c9Sroy done 705793621c9Sroy fi 706793621c9Sroy done 707333b3001Sroy if [ -n "$newns" ]; then 708333b3001Sroy newdomains="$newdomains${newdomains:+ }$dn:$newns" 709333b3001Sroy fi 710793621c9Sroy done 711333b3001Sroy DOMAIN="$(list_remove domain_blacklist $DOMAIN)" 712333b3001Sroy SEARCH="$(uniqify $SEARCH)" 713333b3001Sroy SEARCH="$(list_remove domain_blacklist $SEARCH)" 714333b3001Sroy NAMESERVERS="$(uniqify $NAMESERVERS)" 715333b3001Sroy NAMESERVERS="$(list_remove name_server_blacklist $NAMESERVERS)" 716333b3001Sroy LOCALNAMESERVERS="$(uniqify $LOCALNAMESERVERS)" 717333b3001Sroy LOCALNAMESERVERS="$(list_remove name_server_blacklist $LOCALNAMESERVERS)" 71802c18234Sroy echo "DOMAIN='$DOMAIN'" 719333b3001Sroy echo "SEARCH='$SEARCH'" 720333b3001Sroy echo "NAMESERVERS='$NAMESERVERS'" 721333b3001Sroy echo "LOCALNAMESERVERS='$LOCALNAMESERVERS'" 72202c18234Sroy echo "DOMAINS='$newdomains'" 723793621c9Sroy} 724793621c9Sroy 725793621c9Sroyforce=false 726075ee3c1SroyVFLAG= 7270949b2edSroywhile getopts a:C:c:Dd:fhIilm:pRruvVx OPT; do 728793621c9Sroy case "$OPT" in 729793621c9Sroy f) force=true;; 730793621c9Sroy h) usage;; 731793621c9Sroy m) IF_METRIC="$OPTARG";; 732793621c9Sroy p) IF_PRIVATE=1;; 733075ee3c1Sroy V) 734075ee3c1Sroy VFLAG=1 735075ee3c1Sroy if [ "$local_nameservers" = \ 736075ee3c1Sroy "127.* 0.0.0.0 255.255.255.255 ::1" ] 737075ee3c1Sroy then 738075ee3c1Sroy local_nameservers= 739075ee3c1Sroy fi 740075ee3c1Sroy ;; 7414ac8d7d2Sroy x) IF_EXCLUSIVE=1;; 7420949b2edSroy '?') exit 1;; 743793621c9Sroy *) cmd="$OPT"; iface="$OPTARG";; 744793621c9Sroy esac 745793621c9Sroydone 746793621c9Sroyshift $(($OPTIND - 1)) 747d8775c93Sroyargs="$iface${iface:+ }$*" 748793621c9Sroy 749793621c9Sroy# -I inits the state dir 750793621c9Sroyif [ "$cmd" = I ]; then 751793621c9Sroy if [ -d "$VARDIR" ]; then 752793621c9Sroy rm -rf "$VARDIR"/* 753793621c9Sroy fi 754793621c9Sroy exit $? 755793621c9Sroyfi 756793621c9Sroy 75702c18234Sroy# -D ensures that the listed config file base dirs exist 75802c18234Sroyif [ "$cmd" = D ]; then 75902c18234Sroy config_mkdirs "$@" 76002c18234Sroy exit $? 76102c18234Sroyfi 76202c18234Sroy 763793621c9Sroy# -l lists our resolv files, optionally for a specific interface 764d7a1218eSkreif [ "$cmd" = l ] || [ "$cmd" = i ]; then 7659cbb0fe2Sroy ALLIFACES=true 766793621c9Sroy list_resolv "$cmd" "$args" 767793621c9Sroy exit $? 768793621c9Sroyfi 7699cbb0fe2SroyALLIFACES=false 770793621c9Sroy 7719d6c0475Sroy# Restart a service or echo the command to restart a service 772d7a1218eSkreif [ "$cmd" = r ] || [ "$cmd" = R ]; then 7739d6c0475Sroy detect_init || exit 1 7749d6c0475Sroy if [ "$cmd" = r ]; then 7759d6c0475Sroy set -- $args 7764113b4f7Skre eval "$RESTARTCMD" 7779d6c0475Sroy else 778e37204c6Sroy echo "$RESTARTCMD" | 779e37204c6Sroy sed -e '/^$/d' -e 's/^ //g' 7809d6c0475Sroy fi 7819d6c0475Sroy exit $? 7829d6c0475Sroyfi 7839d6c0475Sroy 784793621c9Sroy# Not normally needed, but subscribers should be able to run independently 785d7a1218eSkreif [ "$cmd" = v ] || [ -n "$VFLAG" ]; then 786793621c9Sroy make_vars "$iface" 787793621c9Sroy exit $? 788793621c9Sroyfi 789793621c9Sroy 790793621c9Sroy# Test that we have valid options 7910949b2edSroycase "$cmd" in 7920949b2edSroya|d|C|c) 793793621c9Sroy if [ -z "$iface" ]; then 7940949b2edSroy error_exit "Interface not specified" 795793621c9Sroy fi 7960949b2edSroy ;; 7970949b2edSroyu) ;; 7980949b2edSroy*) 7990949b2edSroy if [ -n "$cmd" ] && [ "$cmd" != h ]; then 8000949b2edSroy error_exit "Unknown option $cmd" 8010949b2edSroy fi 802793621c9Sroy usage 8030949b2edSroy ;; 8040949b2edSroyesac 805075ee3c1Sroy 806793621c9Sroyif [ "$cmd" = a ]; then 807793621c9Sroy for x in '/' \\ ' ' '*'; do 808793621c9Sroy case "$iface" in 809793621c9Sroy *[$x]*) error_exit "$x not allowed in interface name";; 810793621c9Sroy esac 811793621c9Sroy done 812793621c9Sroy for x in '.' '-' '~'; do 813793621c9Sroy case "$iface" in 814793621c9Sroy [$x]*) error_exit \ 815793621c9Sroy "$x not allowed at start of interface name";; 816793621c9Sroy esac 817793621c9Sroy done 818d7a1218eSkre [ "$cmd" = a ] && [ -t 0 ] && error_exit "No file given via stdin" 819793621c9Sroyfi 820793621c9Sroy 821793621c9Sroyif [ ! -d "$VARDIR" ]; then 822793621c9Sroy if [ -L "$VARDIR" ]; then 823793621c9Sroy dir="$(readlink "$VARDIR")" 824793621c9Sroy # link maybe relative 825793621c9Sroy cd "${VARDIR%/*}" 826793621c9Sroy if ! mkdir -m 0755 -p "$dir"; then 827793621c9Sroy error_exit "Failed to create needed" \ 828793621c9Sroy "directory $dir" 829793621c9Sroy fi 830793621c9Sroy else 831793621c9Sroy if ! mkdir -m 0755 -p "$VARDIR"; then 832793621c9Sroy error_exit "Failed to create needed" \ 833793621c9Sroy "directory $VARDIR" 834793621c9Sroy fi 835793621c9Sroy fi 836793621c9Sroyfi 837075ee3c1Sroy 838075ee3c1Sroyif [ ! -d "$IFACEDIR" ]; then 839793621c9Sroy mkdir -m 0755 -p "$IFACEDIR" || \ 840793621c9Sroy error_exit "Failed to create needed directory $IFACEDIR" 841548d7cc4Sroy if [ "$cmd" = d ]; then 842548d7cc4Sroy # Provide the same error messages as below 843548d7cc4Sroy if ! ${force}; then 844548d7cc4Sroy cd "$IFACEDIR" 845548d7cc4Sroy for i in $args; do 846548d7cc4Sroy warn "No resolv.conf for interface $i" 847548d7cc4Sroy done 848548d7cc4Sroy fi 849548d7cc4Sroy ${force} 850548d7cc4Sroy exit $? 851548d7cc4Sroy fi 852793621c9Sroyfi 853793621c9Sroy 8544ac8d7d2Sroy# An interface was added, changed, deleted or a general update was called. 8554ac8d7d2Sroy# Due to exclusivity we need to ensure that this is an atomic operation. 8564ac8d7d2Sroy# Our subscribers *may* need this as well if the init system is sub par. 8574ac8d7d2Sroy# As such we spinlock at this point as best we can. 8584ac8d7d2Sroy# We don't use flock(1) because it's not widely available and normally resides 8594ac8d7d2Sroy# in /usr which we do our very best to operate without. 8604ac8d7d2Sroy[ -w "$VARDIR" ] || error_exit "Cannot write to $LOCKDIR" 8614ac8d7d2Sroy: ${lock_timeout:=10} 8620949b2edSroy: ${clear_nopids:=5} 8630949b2edSroyhave_pid=false 8640949b2edSroyhad_pid=false 8654ac8d7d2Sroywhile true; do 8664ac8d7d2Sroy if mkdir "$LOCKDIR" 2>/dev/null; then 8674ac8d7d2Sroy trap 'rm -rf "$LOCKDIR";' EXIT 8684ac8d7d2Sroy trap 'rm -rf "$LOCKDIR"; exit 1' INT QUIT ABRT SEGV ALRM TERM 8694ac8d7d2Sroy echo $$ >"$LOCKDIR/pid" 8704ac8d7d2Sroy break 8714ac8d7d2Sroy fi 8720949b2edSroy pid=$(cat "$LOCKDIR/pid" 2>/dev/null) 8730949b2edSroy if [ "$pid" -gt 0 ] 2>/dev/null; then 8740949b2edSroy have_pid=true 8750949b2edSroy had_pid=true 8760949b2edSroy else 8770949b2edSroy have_pid=false 8780949b2edSroy clear_nopids=$(($clear_nopids - 1)) 8790949b2edSroy if [ "$clear_nopids" -le 0 ]; then 8800949b2edSroy warn "not seen a pid, clearing lock directory" 8810949b2edSroy rm -rf "$LOCKDIR" 8820949b2edSroy else 8830949b2edSroy lock_timeout=$(($lock_timeout - 1)) 8840949b2edSroy sleep 1 8850949b2edSroy fi 8860949b2edSroy continue 8870949b2edSroy fi 8880949b2edSroy if $have_pid && ! kill -0 "$pid"; then 8894ac8d7d2Sroy warn "clearing stale lock pid $pid" 8904ac8d7d2Sroy rm -rf "$LOCKDIR" 8914ac8d7d2Sroy continue 8924ac8d7d2Sroy fi 8934ac8d7d2Sroy lock_timeout=$(($lock_timeout - 1)) 8944ac8d7d2Sroy if [ "$lock_timeout" -le 0 ]; then 8950949b2edSroy if $have_pid; then 8964ac8d7d2Sroy error_exit "timed out waiting for lock from pid $pid" 8970949b2edSroy else 8980949b2edSroy if $had_pid; then 8990949b2edSroy error_exit "timed out waiting for lock" \ 9000949b2edSroy "from some pids" 9010949b2edSroy else 9020949b2edSroy error_exit "timed out waiting for lock" 9030949b2edSroy fi 9040949b2edSroy fi 9054ac8d7d2Sroy fi 9064ac8d7d2Sroy sleep 1 9074ac8d7d2Sroydone 9080949b2edSroyunset have_pid had_pid clear_nopids 9094ac8d7d2Sroy 9104ac8d7d2Sroycase "$cmd" in 9114ac8d7d2Sroya) 912793621c9Sroy # Read resolv.conf from stdin 913d8775c93Sroy resolv="$(cat)" 91402c18234Sroy changed=false 915075ee3c1Sroy changedfile=false 916793621c9Sroy # If what we are given matches what we have, then do nothing 917793621c9Sroy if [ -e "$IFACEDIR/$iface" ]; then 91802c18234Sroy if [ "$(echo "$resolv")" != \ 919793621c9Sroy "$(cat "$IFACEDIR/$iface")" ] 920793621c9Sroy then 92102c18234Sroy changed=true 922075ee3c1Sroy changedfile=true 923793621c9Sroy fi 92402c18234Sroy else 92502c18234Sroy changed=true 926075ee3c1Sroy changedfile=true 92702c18234Sroy fi 9284ac8d7d2Sroy 929075ee3c1Sroy # Set metric and private before creating the interface resolv.conf file 930075ee3c1Sroy # to ensure that it will have the correct flags 931793621c9Sroy [ ! -d "$METRICDIR" ] && mkdir "$METRICDIR" 93202c18234Sroy oldmetric="$METRICDIR/"*" $iface" 93302c18234Sroy newmetric= 934793621c9Sroy if [ -n "$IF_METRIC" ]; then 935793621c9Sroy # Pad metric to 6 characters, so 5 is less than 10 936793621c9Sroy while [ ${#IF_METRIC} -le 6 ]; do 937793621c9Sroy IF_METRIC="0$IF_METRIC" 938793621c9Sroy done 93902c18234Sroy newmetric="$METRICDIR/$IF_METRIC $iface" 940793621c9Sroy fi 94102c18234Sroy rm -f "$METRICDIR/"*" $iface" 942d7a1218eSkre [ "$oldmetric" != "$newmetric" ] && 943d7a1218eSkre [ "$oldmetric" != "$METRICDIR/* $iface" ] && 94402c18234Sroy changed=true 94502c18234Sroy [ -n "$newmetric" ] && echo " " >"$newmetric" 9464ac8d7d2Sroy 947793621c9Sroy case "$IF_PRIVATE" in 948793621c9Sroy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 949793621c9Sroy if [ ! -d "$PRIVATEDIR" ]; then 950793621c9Sroy [ -e "$PRIVATEDIR" ] && rm "$PRIVATEDIR" 951793621c9Sroy mkdir "$PRIVATEDIR" 952793621c9Sroy fi 95302c18234Sroy [ -e "$PRIVATEDIR/$iface" ] || changed=true 954793621c9Sroy [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$iface" 955793621c9Sroy ;; 956793621c9Sroy *) 957793621c9Sroy if [ -e "$PRIVATEDIR/$iface" ]; then 958793621c9Sroy rm -f "$PRIVATEDIR/$iface" 95902c18234Sroy changed=true 960793621c9Sroy fi 961793621c9Sroy ;; 962793621c9Sroy esac 9634ac8d7d2Sroy 9644ac8d7d2Sroy oldexcl= 9654ac8d7d2Sroy for x in "$EXCLUSIVEDIR/"*" $iface"; do 9664ac8d7d2Sroy if [ -f "$x" ]; then 9674ac8d7d2Sroy oldexcl="$x" 9684ac8d7d2Sroy break 9694ac8d7d2Sroy fi 9704ac8d7d2Sroy done 9714ac8d7d2Sroy case "$IF_EXCLUSIVE" in 9724ac8d7d2Sroy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) 9734ac8d7d2Sroy if [ ! -d "$EXCLUSIVEDIR" ]; then 9744ac8d7d2Sroy [ -e "$EXCLUSIVEDIR" ] && rm "$EXCLUSIVEDIR" 9754ac8d7d2Sroy mkdir "$EXCLUSIVEDIR" 9764ac8d7d2Sroy fi 9774ac8d7d2Sroy cd "$EXCLUSIVEDIR" 9784ac8d7d2Sroy for x in *; do 9794ac8d7d2Sroy [ -f "$x" ] && break 9804ac8d7d2Sroy done 9814ac8d7d2Sroy if [ "${x#* }" != "$iface" ]; then 9824ac8d7d2Sroy if [ "$x" = "${x% *}" ]; then 9834ac8d7d2Sroy x=10000000 9844ac8d7d2Sroy else 9854ac8d7d2Sroy x="${x% *}" 9864ac8d7d2Sroy fi 9874ac8d7d2Sroy if [ "$x" = "0000000" ]; then 9884ac8d7d2Sroy warn "exclusive underflow" 9894ac8d7d2Sroy else 9904ac8d7d2Sroy x=$(($x - 1)) 9914ac8d7d2Sroy fi 9924ac8d7d2Sroy if [ -d "$EXCLUSIVEDIR" ]; then 9934ac8d7d2Sroy echo " " >"$EXCLUSIVEDIR/$x $iface" 9944ac8d7d2Sroy fi 9954ac8d7d2Sroy changed=true 9964ac8d7d2Sroy fi 9974ac8d7d2Sroy ;; 9984ac8d7d2Sroy *) 9994ac8d7d2Sroy if [ -f "$oldexcl" ]; then 10004ac8d7d2Sroy rm -f "$oldexcl" 10014ac8d7d2Sroy changed=true 10024ac8d7d2Sroy fi 10034ac8d7d2Sroy ;; 10044ac8d7d2Sroy esac 10054ac8d7d2Sroy 1006075ee3c1Sroy if $changedfile; then 10074ac8d7d2Sroy printf "%s\n" "$resolv" >"$IFACEDIR/$iface" || exit $? 10084ac8d7d2Sroy elif ! $changed; then 10094ac8d7d2Sroy exit 0 1010075ee3c1Sroy fi 10114ac8d7d2Sroy unset changed changedfile oldmetric newmetric x oldexcl 10124ac8d7d2Sroy ;; 10134ac8d7d2Sroy 10144ac8d7d2Sroyd) 10154ac8d7d2Sroy # Delete any existing information about the interface 10164ac8d7d2Sroy cd "$IFACEDIR" 10174ac8d7d2Sroy changed=false 10184ac8d7d2Sroy for i in $args; do 10194ac8d7d2Sroy if [ -e "$i" ]; then 10204ac8d7d2Sroy changed=true 10214ac8d7d2Sroy elif ! ${force}; then 10224ac8d7d2Sroy warn "No resolv.conf for interface $i" 1023075ee3c1Sroy fi 10244ac8d7d2Sroy rm -f "$i" "$METRICDIR/"*" $i" \ 10254ac8d7d2Sroy "$PRIVATEDIR/$i" \ 10264ac8d7d2Sroy "$EXCLUSIVEDIR/"*" $i" || exit $? 10274ac8d7d2Sroy done 10280949b2edSroy 10290949b2edSroy if ! $changed; then 10304ac8d7d2Sroy # Set the return code based on the forced flag 10310949b2edSroy $force 10324ac8d7d2Sroy exit $? 1033793621c9Sroy fi 10344ac8d7d2Sroy unset changed i 10354ac8d7d2Sroy ;; 10360949b2edSroy 10370949b2edSroyC) 10380949b2edSroy # Mark interface as deprecated 10390949b2edSroy [ ! -d "$DEPRECATEDDIR" ] && mkdir "$DEPRECATEDDIR" 10400949b2edSroy cd "$DEPRECATEDDIR" 10410949b2edSroy changed=false 10420949b2edSroy for i in $args; do 10430949b2edSroy if [ ! -e "$i" ]; then 10440949b2edSroy changed=true 10450949b2edSroy echo " " >"$i" || exit $? 10460949b2edSroy fi 10470949b2edSroy done 10480949b2edSroy $changed || exit 0 10490949b2edSroy unset changed i 10500949b2edSroy ;; 10510949b2edSroy 10520949b2edSroyc) 10530949b2edSroy # Mark interface as active 10540949b2edSroy if [ -d "$DEPRECATEDDIR" ]; then 10550949b2edSroy cd "$DEPRECATEDDIR" 10560949b2edSroy changed=false 10570949b2edSroy for i in $args; do 10580949b2edSroy if [ -e "$i" ]; then 10590949b2edSroy changed=true 10600949b2edSroy rm "$i" || exit $? 10610949b2edSroy fi 10620949b2edSroy done 10630949b2edSroy $changed || exit 0 10640949b2edSroy unset changed i 10650949b2edSroy fi 10660949b2edSroy ;; 10674ac8d7d2Sroyesac 1068793621c9Sroy 1069075ee3c1Sroycase "${resolvconf:-YES}" in 1070075ee3c1Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;; 1071075ee3c1Sroy*) exit 0;; 1072075ee3c1Sroyesac 1073075ee3c1Sroy 10749d6c0475Sroy# Try and detect a suitable init system for our scripts 10759d6c0475Sroydetect_init 10769d6c0475Sroyexport RESTARTCMD RCDIR _NOINIT_WARNED 10779d6c0475Sroy 1078793621c9Sroyeval "$(make_vars)" 1079d8775c93Sroyexport RESOLVCONF DOMAINS SEARCH NAMESERVERS LOCALNAMESERVERS 1080793621c9Sroy: ${list_resolv:=list_resolv -l} 1081793621c9Sroyretval=0 10822644931fSroy 10832644931fSroy# Run scripts in the same directory resolvconf is run from 1084292189d7Sroy# in case any scripts accidentally dump files in the wrong place. 10852644931fSroycd "$_PWD" 1086793621c9Sroyfor script in "$LIBEXECDIR"/*; do 10875bcbb70cSroy if [ -f "$script" ]; then 1088075ee3c1Sroy eval script_enabled="\$${script##*/}" 1089075ee3c1Sroy case "${script_enabled:-YES}" in 1090075ee3c1Sroy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;; 1091075ee3c1Sroy *) continue;; 1092075ee3c1Sroy esac 10935bcbb70cSroy if [ -x "$script" ]; then 10945bcbb70cSroy "$script" "$cmd" "$iface" 10955bcbb70cSroy else 1096d8775c93Sroy (set -- "$cmd" "$iface"; . "$script") 10975bcbb70cSroy fi 1098793621c9Sroy retval=$(($retval + $?)) 10995bcbb70cSroy fi 1100793621c9Sroydone 1101793621c9Sroyexit $retval 1102