resolvconf.in revision 1.11 1 1.1 roy #!/bin/sh
2 1.11 roy # Copyright (c) 2007-2025 Roy Marples
3 1.1 roy # All rights reserved
4 1.1 roy
5 1.1 roy # Redistribution and use in source and binary forms, with or without
6 1.1 roy # modification, are permitted provided that the following conditions
7 1.1 roy # are met:
8 1.1 roy # * Redistributions of source code must retain the above copyright
9 1.1 roy # notice, this list of conditions and the following disclaimer.
10 1.1 roy # * Redistributions in binary form must reproduce the above
11 1.1 roy # copyright notice, this list of conditions and the following
12 1.1 roy # disclaimer in the documentation and/or other materials provided
13 1.1 roy # with the distribution.
14 1.1 roy #
15 1.1 roy # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 1.1 roy # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 1.1 roy # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 1.1 roy # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 1.1 roy # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 1.1 roy # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 1.1 roy # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 roy # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 roy # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 roy # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 1.1 roy # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 roy
27 1.1 roy RESOLVCONF="$0"
28 1.11 roy OPENRESOLV_VERSION="3.14.0"
29 1.1 roy SYSCONFDIR=@SYSCONFDIR@
30 1.1 roy LIBEXECDIR=@LIBEXECDIR@
31 1.1 roy VARDIR=@VARDIR@
32 1.2 kre RCDIR=@RCDIR@
33 1.2 kre RESTARTCMD=@RESTARTCMD@
34 1.2 kre
35 1.2 kre if [ "$1" = "--version" ]; then
36 1.2 kre echo "openresolv $OPENRESOLV_VERSION"
37 1.11 roy echo "Copyright (c) 2007-2025 Roy Marples"
38 1.2 kre exit 0
39 1.2 kre fi
40 1.2 kre
41 1.2 kre # Disregard dhcpcd setting
42 1.2 kre unset interface_order state_dir
43 1.2 kre
44 1.2 kre # If you change this, change the test in VFLAG and libc.in as well
45 1.2 kre local_nameservers="127.* 0.0.0.0 255.255.255.255 ::1"
46 1.2 kre
47 1.7 roy dynamic_order="tap[0-9]* tun[0-9]* vpn vpn[0-9]* wg[0-9]* ppp[0-9]* ippp[0-9]*"
48 1.2 kre interface_order="lo lo[0-9]*"
49 1.2 kre name_server_blacklist="0.0.0.0"
50 1.2 kre
51 1.11 roy # Poor mans cat
52 1.11 roy # /usr might not be available
53 1.11 roy cat()
54 1.11 roy {
55 1.11 roy OIFS="$IFS"
56 1.11 roy IFS=''
57 1.11 roy if [ -n "$1" ]; then
58 1.11 roy while read -r line; do
59 1.11 roy printf "%s\n" "$line"
60 1.11 roy done < "$1"
61 1.11 roy else
62 1.11 roy while read -r line; do
63 1.11 roy printf "%s\n" "$line"
64 1.11 roy done
65 1.11 roy fi
66 1.11 roy retval=$?
67 1.11 roy IFS="$OIFS"
68 1.11 roy return $retval
69 1.11 roy }
70 1.11 roy
71 1.11 roy
72 1.1 roy # Support original resolvconf configuration layout
73 1.1 roy # as well as the openresolv config file
74 1.1 roy if [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
75 1.1 roy . "$SYSCONFDIR"/resolvconf.conf
76 1.1 roy [ -n "$state_dir" ] && VARDIR="$state_dir"
77 1.1 roy elif [ -d "$SYSCONFDIR/resolvconf" ]; then
78 1.1 roy SYSCONFDIR="$SYSCONFDIR/resolvconf"
79 1.1 roy if [ -f "$SYSCONFDIR"/interface-order ]; then
80 1.1 roy interface_order="$(cat "$SYSCONFDIR"/interface-order)"
81 1.1 roy fi
82 1.1 roy fi
83 1.7 roy
84 1.1 roy IFACEDIR="$VARDIR/interfaces"
85 1.1 roy METRICDIR="$VARDIR/metrics"
86 1.1 roy PRIVATEDIR="$VARDIR/private"
87 1.2 kre EXCLUSIVEDIR="$VARDIR/exclusive"
88 1.9 roy DEPRECATEDDIR="$VARDIR/deprecated"
89 1.2 kre LOCKDIR="$VARDIR/lock"
90 1.2 kre _PWD="$PWD"
91 1.1 roy
92 1.2 kre warn()
93 1.2 kre {
94 1.2 kre echo "$*" >&2
95 1.2 kre }
96 1.1 roy
97 1.1 roy error_exit()
98 1.1 roy {
99 1.1 roy echo "$*" >&2
100 1.1 roy exit 1
101 1.1 roy }
102 1.1 roy
103 1.1 roy usage()
104 1.1 roy {
105 1.1 roy cat <<-EOF
106 1.2 kre Usage: ${RESOLVCONF##*/} [options] command [argument]
107 1.1 roy
108 1.1 roy Inform the system about any DNS updates.
109 1.1 roy
110 1.2 kre Commands:
111 1.1 roy -a \$INTERFACE Add DNS information to the specified interface
112 1.1 roy (DNS supplied via stdin in resolv.conf format)
113 1.9 roy -C \$PATTERN Deprecate DNS information for matched interfaces
114 1.9 roy -c \$PATTERN Configure DNS information for matched interfaces
115 1.1 roy -d \$INTERFACE Delete DNS information from the specified interface
116 1.2 kre -h Show this help cruft
117 1.1 roy -i [\$PATTERN] Show interfaces that have supplied DNS information
118 1.1 roy optionally from interfaces that match the specified
119 1.1 roy pattern
120 1.2 kre -l [\$PATTERN] Show DNS information, optionally from interfaces
121 1.2 kre that match the specified pattern
122 1.11 roy -L [\$PATTERN] Same as -l, but adjusted by our config
123 1.2 kre
124 1.2 kre -u Run updates from our current DNS information
125 1.2 kre --version Echo the ${RESOLVCONF##*/} version
126 1.2 kre
127 1.2 kre Options:
128 1.2 kre -f Ignore non existent interfaces
129 1.2 kre -m metric Give the added DNS information a metric
130 1.2 kre -p Mark the interface as private
131 1.2 kre -x Mark the interface as exclusive
132 1.2 kre
133 1.2 kre Subscriber and System Init Commands:
134 1.2 kre -I Init the state dir
135 1.2 kre -r \$SERVICE Restart the system service
136 1.2 kre (restarting a non-existent or non-running service
137 1.2 kre should have no output and return 0)
138 1.2 kre -R Show the system service restart command
139 1.1 roy -v [\$PATTERN] echo NEWDOMAIN, NEWSEARCH and NEWNS variables to
140 1.1 roy the console
141 1.2 kre -V [\$PATTERN] Same as -v, but only uses configuration in
142 1.2 kre $SYSCONFDIR/resolvconf.conf
143 1.1 roy EOF
144 1.1 roy [ -z "$1" ] && exit 0
145 1.1 roy echo
146 1.1 roy error_exit "$*"
147 1.1 roy }
148 1.1 roy
149 1.2 kre # Strip any trailing dot from each name as a FQDN does not belong
150 1.2 kre # in resolv.conf(5)
151 1.2 kre # If you think otherwise, capture a DNS trace and you'll see libc
152 1.2 kre # will strip it regardless.
153 1.2 kre # This also solves setting up duplicate zones in our subscribers.
154 1.5 roy # Also strip any comments denoted by #.
155 1.5 roy resolv_strip()
156 1.2 kre {
157 1.5 roy space=
158 1.5 roy for word; do
159 1.5 roy case "$word" in
160 1.5 roy \#*) break;;
161 1.5 roy esac
162 1.5 roy printf "%s%s" "$space${word%.}"
163 1.5 roy space=" "
164 1.2 kre done
165 1.2 kre printf "\n"
166 1.2 kre }
167 1.2 kre
168 1.2 kre private_iface()
169 1.1 roy {
170 1.2 kre # Allow expansion
171 1.2 kre cd "$IFACEDIR"
172 1.2 kre
173 1.2 kre # Public interfaces override private ones.
174 1.2 kre for p in $public_interfaces; do
175 1.2 kre case "$iface" in
176 1.2 kre "$p"|"$p":*) return 1;;
177 1.2 kre esac
178 1.2 kre done
179 1.2 kre
180 1.2 kre if [ -e "$PRIVATEDIR/$iface" ]; then
181 1.2 kre return 0
182 1.2 kre fi
183 1.10 roy
184 1.2 kre for p in $private_interfaces; do
185 1.2 kre case "$iface" in
186 1.2 kre "$p"|"$p":*) return 0;;
187 1.2 kre esac
188 1.2 kre done
189 1.2 kre
190 1.2 kre # Not a private interface
191 1.2 kre return 1
192 1.1 roy }
193 1.1 roy
194 1.1 roy # Parse resolv.conf's and make variables
195 1.1 roy # for domain name servers, search name servers and global nameservers
196 1.1 roy parse_resolv()
197 1.1 roy {
198 1.5 roy domain=
199 1.5 roy new=true
200 1.2 kre newns=
201 1.5 roy ns=
202 1.5 roy private=false
203 1.5 roy search=
204 1.1 roy
205 1.2 kre while read -r line; do
206 1.5 roy stripped_line="$(resolv_strip ${line#* })"
207 1.1 roy case "$line" in
208 1.1 roy "# resolv.conf from "*)
209 1.1 roy if ${new}; then
210 1.1 roy iface="${line#\# resolv.conf from *}"
211 1.1 roy new=false
212 1.2 kre if private_iface "$iface"; then
213 1.1 roy private=true
214 1.2 kre else
215 1.2 kre private=false
216 1.2 kre fi
217 1.2 kre fi
218 1.2 kre ;;
219 1.2 kre "nameserver "*)
220 1.2 kre islocal=false
221 1.2 kre for l in $local_nameservers; do
222 1.5 roy case "$stripped_line" in
223 1.2 kre $l)
224 1.2 kre islocal=true
225 1.2 kre break
226 1.1 roy ;;
227 1.1 roy esac
228 1.2 kre done
229 1.5 roy if $islocal; then
230 1.5 roy echo "LOCALNAMESERVERS=\"\$LOCALNAMESERVERS $stripped_line\""
231 1.5 roy else
232 1.5 roy ns="$ns$stripped_line "
233 1.5 roy fi
234 1.2 kre ;;
235 1.2 kre "domain "*)
236 1.5 roy search="$stripped_line"
237 1.2 kre if [ -z "$domain" ]; then
238 1.2 kre domain="$search"
239 1.2 kre echo "DOMAIN=\"$domain\""
240 1.1 roy fi
241 1.1 roy ;;
242 1.2 kre "search "*)
243 1.5 roy search="$stripped_line"
244 1.1 roy ;;
245 1.1 roy *)
246 1.1 roy [ -n "$line" ] && continue
247 1.2 kre if [ -n "$ns" ] && [ -n "$search" ]; then
248 1.1 roy newns=
249 1.1 roy for n in $ns; do
250 1.1 roy newns="$newns${newns:+,}$n"
251 1.1 roy done
252 1.1 roy ds=
253 1.1 roy for d in $search; do
254 1.1 roy ds="$ds${ds:+ }$d:$newns"
255 1.1 roy done
256 1.1 roy echo "DOMAINS=\"\$DOMAINS $ds\""
257 1.1 roy fi
258 1.1 roy echo "SEARCH=\"\$SEARCH $search\""
259 1.1 roy if ! $private; then
260 1.1 roy echo "NAMESERVERS=\"\$NAMESERVERS $ns\""
261 1.1 roy fi
262 1.1 roy ns=
263 1.1 roy search=
264 1.1 roy new=true
265 1.1 roy ;;
266 1.1 roy esac
267 1.1 roy done
268 1.1 roy }
269 1.1 roy
270 1.1 roy uniqify()
271 1.1 roy {
272 1.5 roy result=
273 1.1 roy while [ -n "$1" ]; do
274 1.1 roy case " $result " in
275 1.1 roy *" $1 "*);;
276 1.1 roy *) result="$result $1";;
277 1.1 roy esac
278 1.1 roy shift
279 1.1 roy done
280 1.1 roy echo "${result# *}"
281 1.1 roy }
282 1.1 roy
283 1.2 kre dirname()
284 1.2 kre {
285 1.5 roy OIFS="$IFS"
286 1.5 roy IFS=/
287 1.2 kre set -- $@
288 1.2 kre IFS="$OIFS"
289 1.2 kre if [ -n "$1" ]; then
290 1.2 kre printf %s .
291 1.2 kre else
292 1.2 kre shift
293 1.2 kre fi
294 1.2 kre while [ -n "$2" ]; do
295 1.2 kre printf "/%s" "$1"
296 1.2 kre shift
297 1.2 kre done
298 1.2 kre printf "\n"
299 1.2 kre }
300 1.2 kre
301 1.2 kre config_mkdirs()
302 1.2 kre {
303 1.2 kre for f; do
304 1.2 kre [ -n "$f" ] || continue
305 1.2 kre d="$(dirname "$f")"
306 1.2 kre if [ ! -d "$d" ]; then
307 1.9 roy mkdir -p "$d" || return $?
308 1.2 kre fi
309 1.2 kre done
310 1.9 roy return 0
311 1.2 kre }
312 1.2 kre
313 1.2 kre # With the advent of alternative init systems, it's possible to have
314 1.2 kre # more than one installed. So we need to try and guess what one we're
315 1.10 roy # using unless overridden by configure.
316 1.2 kre # Note that restarting a service is a last resort - the subscribers
317 1.10 roy # should make a reasonable attempt to reconfigure the service via some
318 1.2 kre # method, normally SIGHUP.
319 1.2 kre detect_init()
320 1.2 kre {
321 1.2 kre [ -n "$RESTARTCMD" ] && return 0
322 1.2 kre
323 1.2 kre # Detect the running init system.
324 1.2 kre # As systemd and OpenRC can be installed on top of legacy init
325 1.2 kre # systems we try to detect them first.
326 1.5 roy status="@STATUSARG@"
327 1.2 kre : ${status:=status}
328 1.2 kre if [ -x /bin/systemctl ] && [ -S /run/systemd/private ]; then
329 1.2 kre RESTARTCMD='
330 1.2 kre if /bin/systemctl --quiet is-active $1.service
331 1.2 kre then
332 1.2 kre /bin/systemctl restart $1.service
333 1.2 kre fi'
334 1.2 kre elif [ -x /usr/bin/systemctl ] && [ -S /run/systemd/private ]; then
335 1.2 kre RESTARTCMD='
336 1.2 kre if /usr/bin/systemctl --quiet is-active $1.service
337 1.2 kre then
338 1.2 kre /usr/bin/systemctl restart $1.service
339 1.2 kre fi'
340 1.5 roy elif [ -x /sbin/rc-service ] &&
341 1.5 roy { [ -s /libexec/rc/init.d/softlevel ] ||
342 1.5 roy [ -s /run/openrc/softlevel ]; }
343 1.2 kre then
344 1.2 kre RESTARTCMD='/sbin/rc-service -i $1 -- -Ds restart'
345 1.2 kre elif [ -x /usr/sbin/invoke-rc.d ]; then
346 1.2 kre RCDIR=/etc/init.d
347 1.2 kre RESTARTCMD='
348 1.2 kre if /usr/sbin/invoke-rc.d --quiet $1 status >/dev/null 2>&1
349 1.2 kre then
350 1.2 kre /usr/sbin/invoke-rc.d $1 restart
351 1.2 kre fi'
352 1.10 roy elif [ -x /usr/bin/s6-rc ] && [ -x /usr/bin/s6-svc ]; then
353 1.10 roy RESTARTCMD='
354 1.11 roy if s6-rc -a list 2>/dev/null | grep -qFx $1-srv
355 1.10 roy then
356 1.10 roy s6-svc -r /run/service/$1-srv
357 1.10 roy fi'
358 1.2 kre elif [ -x /sbin/service ]; then
359 1.2 kre # Old RedHat
360 1.2 kre RCDIR=/etc/init.d
361 1.2 kre RESTARTCMD='
362 1.2 kre if /sbin/service $1; then
363 1.2 kre /sbin/service $1 restart
364 1.2 kre fi'
365 1.2 kre elif [ -x /usr/sbin/service ]; then
366 1.2 kre # Could be FreeBSD
367 1.4 kre RESTARTCMD="
368 1.4 kre if /usr/sbin/service \$1 $status >/dev/null 2>&1
369 1.2 kre then
370 1.4 kre /usr/sbin/service \$1 restart
371 1.4 kre fi"
372 1.2 kre elif [ -x /bin/sv ]; then
373 1.2 kre RESTARTCMD='/bin/sv status $1 >/dev/null 2>&1 &&
374 1.2 kre /bin/sv try-restart $1'
375 1.2 kre elif [ -x /usr/bin/sv ]; then
376 1.2 kre RESTARTCMD='/usr/bin/sv status $1 >/dev/null 2>&1 &&
377 1.2 kre /usr/bin/sv try-restart $1'
378 1.2 kre elif [ -e /etc/arch-release ] && [ -d /etc/rc.d ]; then
379 1.2 kre RCDIR=/etc/rc.d
380 1.2 kre RESTARTCMD='
381 1.2 kre if [ -e /var/run/daemons/$1 ]
382 1.2 kre then
383 1.2 kre /etc/rc.d/$1 restart
384 1.2 kre fi'
385 1.2 kre elif [ -e /etc/slackware-version ] && [ -d /etc/rc.d ]; then
386 1.2 kre RESTARTCMD='
387 1.2 kre if /etc/rc.d/rc.$1 status >/dev/null 2>&1
388 1.2 kre then
389 1.2 kre /etc/rc.d/rc.$1 restart
390 1.2 kre fi'
391 1.2 kre elif [ -e /etc/rc.d/rc.subr ] && [ -d /etc/rc.d ]; then
392 1.2 kre # OpenBSD
393 1.2 kre RESTARTCMD='
394 1.2 kre if /etc/rc.d/$1 check >/dev/null 2>&1
395 1.2 kre then
396 1.2 kre /etc/rc.d/$1 restart
397 1.2 kre fi'
398 1.10 roy elif [ -d /etc/dinit.d ] && command -v dinitctl >/dev/null 2>&1; then
399 1.10 roy RESTARTCMD='dinitctl --quiet restart --ignore-unstarted $1'
400 1.2 kre else
401 1.2 kre for x in /etc/init.d/rc.d /etc/rc.d /etc/init.d; do
402 1.2 kre [ -d $x ] || continue
403 1.2 kre RESTARTCMD="
404 1.2 kre if $x/\$1 $status >/dev/null 2>&1
405 1.2 kre then
406 1.2 kre $x/\$1 restart
407 1.2 kre fi"
408 1.2 kre break
409 1.2 kre done
410 1.2 kre fi
411 1.2 kre
412 1.2 kre if [ -z "$RESTARTCMD" ]; then
413 1.2 kre if [ "$_NOINIT_WARNED" != true ]; then
414 1.2 kre warn "could not detect a useable init system"
415 1.2 kre _NOINIT_WARNED=true
416 1.2 kre fi
417 1.2 kre return 1
418 1.2 kre fi
419 1.2 kre _NOINIT_WARNED=
420 1.2 kre return 0
421 1.2 kre }
422 1.2 kre
423 1.2 kre echo_resolv()
424 1.2 kre {
425 1.5 roy OIFS="$IFS"
426 1.2 kre
427 1.2 kre [ -n "$1" ] && [ -f "$IFACEDIR/$1" ] || return 1
428 1.2 kre echo "# resolv.conf from $1"
429 1.2 kre # Our variable maker works of the fact each resolv.conf per interface
430 1.2 kre # is separated by blank lines.
431 1.2 kre # So we remove them when echoing them.
432 1.2 kre while read -r line; do
433 1.2 kre IFS="$OIFS"
434 1.2 kre if [ -n "$line" ]; then
435 1.2 kre # We need to set IFS here to preserve any whitespace
436 1.2 kre IFS=''
437 1.2 kre printf "%s\n" "$line"
438 1.2 kre fi
439 1.2 kre done < "$IFACEDIR/$1"
440 1.2 kre IFS="$OIFS"
441 1.2 kre }
442 1.2 kre
443 1.9 roy deprecated_interface()
444 1.9 roy {
445 1.9 roy [ -d "$DEPRECATEDDIR" ] || return 1
446 1.9 roy
447 1.9 roy cd "$DEPRECATEDDIR"
448 1.9 roy for da; do
449 1.9 roy for daf in *; do
450 1.9 roy [ -f "$daf" ] || continue
451 1.9 roy case "$da" in
452 1.9 roy $daf) return 0;;
453 1.9 roy esac
454 1.9 roy done
455 1.9 roy done
456 1.9 roy return 1
457 1.9 roy }
458 1.9 roy
459 1.11 roy match()
460 1.11 roy {
461 1.11 roy match="$1"
462 1.11 roy file="$2"
463 1.11 roy retval=1
464 1.11 roy count=0
465 1.11 roy
466 1.11 roy while read -r keyword value; do
467 1.11 roy new_match=
468 1.11 roy for om in $match; do
469 1.11 roy m="$om"
470 1.11 roy keep=
471 1.11 roy while [ -n "$m" ]; do
472 1.11 roy k="${m%%/*}"
473 1.11 roy r="${m#*/}"
474 1.11 roy f="${r%%/*}"
475 1.11 roy r="${r#*/}"
476 1.11 roy # If the length of m is the same as k/f then
477 1.11 roy # we know that we are done
478 1.11 roy if [ ${#m} = $((${#k} + 1 + ${#f})) ]; then
479 1.11 roy r=
480 1.11 roy fi
481 1.11 roy m="$r"
482 1.11 roy matched=false
483 1.11 roy case "$keyword" in
484 1.11 roy $k)
485 1.11 roy case "$value" in
486 1.11 roy $f)
487 1.11 roy matched=true
488 1.11 roy ;;
489 1.11 roy esac
490 1.11 roy ;;
491 1.11 roy esac
492 1.11 roy if ! $matched; then
493 1.11 roy keep="$keep${keep:+/}$k/$f"
494 1.11 roy fi
495 1.11 roy done
496 1.11 roy if [ -n "$om" ] && [ -z "$keep" ]; then
497 1.11 roy retval=0
498 1.11 roy break 2
499 1.11 roy fi
500 1.11 roy new_match="${new_match}${new_match:+ }${keep}"
501 1.11 roy done
502 1.11 roy match="${new_match}"
503 1.11 roy done < "$file"
504 1.11 roy return $retval
505 1.11 roy }
506 1.11 roy
507 1.1 roy list_resolv()
508 1.1 roy {
509 1.1 roy [ -d "$IFACEDIR" ] || return 0
510 1.1 roy
511 1.11 roy OPTIND=
512 1.11 roy list_cmd=
513 1.11 roy while getopts iLl OPT; do
514 1.11 roy case "$OPT" in
515 1.11 roy '?') exit 1;;
516 1.11 roy *) list_cmd="$OPT";;
517 1.11 roy esac
518 1.11 roy done
519 1.11 roy shift $(($OPTIND - 1))
520 1.11 roy
521 1.10 roy pattern_specified="$1"
522 1.10 roy
523 1.5 roy excl=false
524 1.5 roy list=
525 1.5 roy report=false
526 1.5 roy retval=0
527 1.1 roy
528 1.2 kre case "$IF_EXCLUSIVE" in
529 1.2 kre [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
530 1.5 roy excl=true
531 1.2 kre if [ -d "$EXCLUSIVEDIR" ]; then
532 1.2 kre cd "$EXCLUSIVEDIR"
533 1.2 kre for i in *; do
534 1.2 kre if [ -f "$i" ]; then
535 1.2 kre list="${i#* }"
536 1.2 kre break
537 1.2 kre fi
538 1.2 kre done
539 1.2 kre fi
540 1.2 kre cd "$IFACEDIR"
541 1.2 kre for i in $inclusive_interfaces; do
542 1.2 kre if [ -f "$i" ] && [ "$list" = "$i" ]; then
543 1.2 kre list=
544 1.2 kre excl=false
545 1.2 kre break
546 1.2 kre fi
547 1.2 kre done
548 1.2 kre ;;
549 1.2 kre esac
550 1.2 kre
551 1.1 roy # If we have an interface ordering list, then use that.
552 1.1 roy # It works by just using pathname expansion in the interface directory.
553 1.10 roy if [ -n "$pattern_specified" ]; then
554 1.2 kre list="$*"
555 1.1 roy $force || report=true
556 1.2 kre elif ! $excl; then
557 1.1 roy cd "$IFACEDIR"
558 1.9 roy
559 1.1 roy for i in $interface_order; do
560 1.2 kre [ -f "$i" ] && list="$list $i"
561 1.2 kre for ii in "$i":* "$i".*; do
562 1.2 kre [ -f "$ii" ] && list="$list $ii"
563 1.2 kre done
564 1.1 roy done
565 1.9 roy
566 1.1 roy for i in $dynamic_order; do
567 1.2 kre if [ -e "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then
568 1.1 roy list="$list $i"
569 1.1 roy fi
570 1.2 kre for ii in "$i":* "$i".*; do
571 1.2 kre if [ -f "$ii" ] && ! [ -e "$METRICDIR/"*" $ii" ]
572 1.2 kre then
573 1.2 kre list="$list $ii"
574 1.2 kre fi
575 1.2 kre done
576 1.1 roy done
577 1.9 roy
578 1.5 roy # Interfaces have an implicit metric of 0 if not specified.
579 1.5 roy for i in *; do
580 1.5 roy if [ -f "$i" ] && ! [ -e "$METRICDIR/"*" $i" ]; then
581 1.5 roy list="$list $i"
582 1.5 roy fi
583 1.5 roy done
584 1.9 roy
585 1.1 roy if [ -d "$METRICDIR" ]; then
586 1.1 roy cd "$METRICDIR"
587 1.1 roy for i in *; do
588 1.2 kre [ -f "$i" ] && list="$list ${i#* }"
589 1.1 roy done
590 1.1 roy fi
591 1.9 roy
592 1.9 roy # Move deprecated interfaces to the back
593 1.9 roy active=
594 1.9 roy deprecated=
595 1.9 roy for i in $list; do
596 1.9 roy if deprecated_interface "$i"; then
597 1.9 roy deprecated="$deprecated $i"
598 1.9 roy else
599 1.9 roy active="$active $i"
600 1.9 roy fi
601 1.9 roy done
602 1.9 roy list="$active $deprecated"
603 1.1 roy fi
604 1.1 roy
605 1.1 roy cd "$IFACEDIR"
606 1.10 roy if $excl || [ -n "$pattern_specified" ]; then
607 1.10 roy retval=1
608 1.10 roy else
609 1.10 roy retval=0
610 1.10 roy fi
611 1.1 roy for i in $(uniqify $list); do
612 1.1 roy # Only list interfaces which we really have
613 1.2 kre if ! [ -f "$i" ]; then
614 1.1 roy if $report; then
615 1.1 roy echo "No resolv.conf for interface $i" >&2
616 1.2 kre retval=2
617 1.1 roy fi
618 1.1 roy continue
619 1.1 roy fi
620 1.7 roy
621 1.11 roy if [ "$list_cmd" = L ]; then
622 1.7 roy if [ -n "$allow_interfaces" ]; then
623 1.7 roy x=false
624 1.7 roy for j in $allow_interfaces; do
625 1.7 roy if [ "$i" = "$j" ]; then
626 1.7 roy x=true
627 1.7 roy fi
628 1.7 roy done
629 1.7 roy $x || continue
630 1.7 roy fi
631 1.7 roy for j in $deny_interfaces; do
632 1.7 roy if [ "$i" = "$j" ]; then
633 1.7 roy continue 2
634 1.7 roy fi
635 1.7 roy done
636 1.11 roy
637 1.11 roy if [ -n "$exclude" ] && match "$exclude" "$i"; then
638 1.11 roy continue
639 1.11 roy fi
640 1.7 roy fi
641 1.10 roy
642 1.11 roy if [ "$list_cmd" = i ]; then
643 1.2 kre printf %s "$i "
644 1.2 kre else
645 1.2 kre echo_resolv "$i" && echo
646 1.2 kre fi
647 1.2 kre [ $? = 0 ] && [ "$retval" = 1 ] && retval=0
648 1.2 kre done
649 1.11 roy [ "$list_cmd" = i ] && echo
650 1.2 kre return $retval
651 1.2 kre }
652 1.2 kre
653 1.5 roy list_remove()
654 1.5 roy {
655 1.2 kre [ -z "$2" ] && return 0
656 1.2 kre eval list=\"\$$1\"
657 1.2 kre shift
658 1.5 roy result=
659 1.5 roy retval=0
660 1.2 kre
661 1.2 kre set -f
662 1.2 kre for e; do
663 1.2 kre found=false
664 1.2 kre for l in $list; do
665 1.2 kre case "$e" in
666 1.2 kre $l) found=true;;
667 1.2 kre esac
668 1.2 kre $found && break
669 1.2 kre done
670 1.2 kre if $found; then
671 1.2 kre retval=$(($retval + 1))
672 1.1 roy else
673 1.2 kre result="$result $e"
674 1.1 roy fi
675 1.1 roy done
676 1.2 kre set +f
677 1.2 kre echo "${result# *}"
678 1.1 roy return $retval
679 1.1 roy }
680 1.1 roy
681 1.2 kre echo_prepend()
682 1.2 kre {
683 1.2 kre echo "# Generated by resolvconf"
684 1.2 kre if [ -n "$search_domains" ]; then
685 1.2 kre echo "search $search_domains"
686 1.2 kre fi
687 1.2 kre for n in $name_servers; do
688 1.2 kre echo "nameserver $n"
689 1.2 kre done
690 1.2 kre echo
691 1.2 kre }
692 1.2 kre
693 1.2 kre echo_append()
694 1.2 kre {
695 1.2 kre echo "# Generated by resolvconf"
696 1.2 kre if [ -n "$search_domains_append" ]; then
697 1.2 kre echo "search $search_domains_append"
698 1.2 kre fi
699 1.2 kre for n in $name_servers_append; do
700 1.2 kre echo "nameserver $n"
701 1.2 kre done
702 1.2 kre echo
703 1.2 kre }
704 1.2 kre
705 1.2 kre replace()
706 1.2 kre {
707 1.2 kre while read -r keyword value; do
708 1.2 kre for r in $replace; do
709 1.2 kre k="${r%%/*}"
710 1.2 kre r="${r#*/}"
711 1.2 kre f="${r%%/*}"
712 1.2 kre r="${r#*/}"
713 1.2 kre v="${r%%/*}"
714 1.2 kre case "$keyword" in
715 1.2 kre $k)
716 1.2 kre case "$value" in
717 1.2 kre $f) value="$v";;
718 1.2 kre esac
719 1.2 kre ;;
720 1.2 kre esac
721 1.2 kre done
722 1.2 kre val=
723 1.2 kre for sub in $value; do
724 1.2 kre for r in $replace_sub; do
725 1.2 kre k="${r%%/*}"
726 1.2 kre r="${r#*/}"
727 1.2 kre f="${r%%/*}"
728 1.2 kre r="${r#*/}"
729 1.2 kre v="${r%%/*}"
730 1.2 kre case "$keyword" in
731 1.2 kre $k)
732 1.2 kre case "$sub" in
733 1.2 kre $f) sub="$v";;
734 1.2 kre esac
735 1.2 kre ;;
736 1.2 kre esac
737 1.2 kre done
738 1.2 kre val="$val${val:+ }$sub"
739 1.2 kre done
740 1.2 kre printf "%s %s\n" "$keyword" "$val"
741 1.2 kre done
742 1.2 kre }
743 1.2 kre
744 1.1 roy make_vars()
745 1.1 roy {
746 1.2 kre # Clear variables
747 1.2 kre DOMAIN=
748 1.2 kre DOMAINS=
749 1.2 kre SEARCH=
750 1.2 kre NAMESERVERS=
751 1.2 kre LOCALNAMESERVERS=
752 1.7 roy
753 1.2 kre if [ -n "${name_servers}${search_domains}" ]; then
754 1.2 kre eval "$(echo_prepend | parse_resolv)"
755 1.2 kre fi
756 1.2 kre if [ -z "$VFLAG" ]; then
757 1.2 kre IF_EXCLUSIVE=1
758 1.2 kre list_resolv -i "$@" >/dev/null || IF_EXCLUSIVE=0
759 1.11 roy eval "$(list_resolv -L "$@" | replace | parse_resolv)"
760 1.2 kre fi
761 1.3 ryoon if [ -n "${name_servers_append}${search_domains_append}" ]; then
762 1.2 kre eval "$(echo_append | parse_resolv)"
763 1.2 kre fi
764 1.1 roy
765 1.1 roy # Ensure that we only list each domain once
766 1.5 roy newdomains=
767 1.1 roy for d in $DOMAINS; do
768 1.1 roy dn="${d%%:*}"
769 1.2 kre list_remove domain_blacklist "$dn" >/dev/null || continue
770 1.1 roy case " $newdomains" in
771 1.1 roy *" ${dn}:"*) continue;;
772 1.1 roy esac
773 1.1 roy newns=
774 1.1 roy for nd in $DOMAINS; do
775 1.1 roy if [ "$dn" = "${nd%%:*}" ]; then
776 1.1 roy ns="${nd#*:}"
777 1.1 roy while [ -n "$ns" ]; do
778 1.1 roy case ",$newns," in
779 1.1 roy *,${ns%%,*},*) ;;
780 1.2 kre *) list_remove name_server_blacklist \
781 1.2 kre "${ns%%,*}" >/dev/null \
782 1.2 kre && newns="$newns${newns:+,}${ns%%,*}";;
783 1.1 roy esac
784 1.1 roy [ "$ns" = "${ns#*,}" ] && break
785 1.1 roy ns="${ns#*,}"
786 1.1 roy done
787 1.1 roy fi
788 1.1 roy done
789 1.2 kre if [ -n "$newns" ]; then
790 1.2 kre newdomains="$newdomains${newdomains:+ }$dn:$newns"
791 1.2 kre fi
792 1.1 roy done
793 1.2 kre DOMAIN="$(list_remove domain_blacklist $DOMAIN)"
794 1.2 kre SEARCH="$(uniqify $SEARCH)"
795 1.2 kre SEARCH="$(list_remove domain_blacklist $SEARCH)"
796 1.2 kre NAMESERVERS="$(uniqify $NAMESERVERS)"
797 1.2 kre NAMESERVERS="$(list_remove name_server_blacklist $NAMESERVERS)"
798 1.2 kre LOCALNAMESERVERS="$(uniqify $LOCALNAMESERVERS)"
799 1.2 kre LOCALNAMESERVERS="$(list_remove name_server_blacklist $LOCALNAMESERVERS)"
800 1.2 kre echo "DOMAIN='$DOMAIN'"
801 1.2 kre echo "SEARCH='$SEARCH'"
802 1.2 kre echo "NAMESERVERS='$NAMESERVERS'"
803 1.2 kre echo "LOCALNAMESERVERS='$LOCALNAMESERVERS'"
804 1.1 roy echo "DOMAINS='$newdomains'"
805 1.1 roy }
806 1.1 roy
807 1.1 roy force=false
808 1.2 kre VFLAG=
809 1.11 roy while getopts a:C:c:Dd:fhIiLlm:pRruvVx OPT; do
810 1.1 roy case "$OPT" in
811 1.1 roy f) force=true;;
812 1.1 roy h) usage;;
813 1.1 roy m) IF_METRIC="$OPTARG";;
814 1.1 roy p) IF_PRIVATE=1;;
815 1.2 kre V)
816 1.2 kre VFLAG=1
817 1.2 kre if [ "$local_nameservers" = \
818 1.2 kre "127.* 0.0.0.0 255.255.255.255 ::1" ]
819 1.2 kre then
820 1.2 kre local_nameservers=
821 1.2 kre fi
822 1.2 kre ;;
823 1.2 kre x) IF_EXCLUSIVE=1;;
824 1.9 roy '?') exit 1;;
825 1.1 roy *) cmd="$OPT"; iface="$OPTARG";;
826 1.1 roy esac
827 1.1 roy done
828 1.1 roy shift $(($OPTIND - 1))
829 1.2 kre args="$iface${iface:+ }$*"
830 1.1 roy
831 1.1 roy # -I inits the state dir
832 1.1 roy if [ "$cmd" = I ]; then
833 1.1 roy if [ -d "$VARDIR" ]; then
834 1.1 roy rm -rf "$VARDIR"/*
835 1.1 roy fi
836 1.1 roy exit $?
837 1.1 roy fi
838 1.1 roy
839 1.2 kre # -D ensures that the listed config file base dirs exist
840 1.2 kre if [ "$cmd" = D ]; then
841 1.2 kre config_mkdirs "$@"
842 1.2 kre exit $?
843 1.2 kre fi
844 1.2 kre
845 1.1 roy # -l lists our resolv files, optionally for a specific interface
846 1.2 kre if [ "$cmd" = l ] || [ "$cmd" = i ]; then
847 1.11 roy list_resolv "-$cmd" "$args"
848 1.1 roy exit $?
849 1.1 roy fi
850 1.11 roy # -L is the same as -l, but post-processed from our config
851 1.11 roy if [ "$cmd" = L ]; then
852 1.11 roy list_resolv "-$cmd" "$args" | replace
853 1.11 roy exit $?2
854 1.11 roy fi
855 1.1 roy
856 1.2 kre # Restart a service or echo the command to restart a service
857 1.2 kre if [ "$cmd" = r ] || [ "$cmd" = R ]; then
858 1.2 kre detect_init || exit 1
859 1.2 kre if [ "$cmd" = r ]; then
860 1.2 kre set -- $args
861 1.4 kre eval "$RESTARTCMD"
862 1.2 kre else
863 1.5 roy echo "$RESTARTCMD" |
864 1.5 roy sed -e '/^$/d' -e 's/^ //g'
865 1.2 kre fi
866 1.2 kre exit $?
867 1.2 kre fi
868 1.2 kre
869 1.1 roy # Not normally needed, but subscribers should be able to run independently
870 1.2 kre if [ "$cmd" = v ] || [ -n "$VFLAG" ]; then
871 1.1 roy make_vars "$iface"
872 1.1 roy exit $?
873 1.1 roy fi
874 1.1 roy
875 1.1 roy # Test that we have valid options
876 1.9 roy case "$cmd" in
877 1.9 roy a|d|C|c)
878 1.1 roy if [ -z "$iface" ]; then
879 1.9 roy error_exit "Interface not specified"
880 1.9 roy fi
881 1.9 roy ;;
882 1.9 roy u) ;;
883 1.9 roy *)
884 1.9 roy if [ -n "$cmd" ] && [ "$cmd" != h ]; then
885 1.9 roy error_exit "Unknown option $cmd"
886 1.1 roy fi
887 1.1 roy usage
888 1.9 roy ;;
889 1.9 roy esac
890 1.2 kre
891 1.1 roy if [ "$cmd" = a ]; then
892 1.1 roy for x in '/' \\ ' ' '*'; do
893 1.1 roy case "$iface" in
894 1.1 roy *[$x]*) error_exit "$x not allowed in interface name";;
895 1.1 roy esac
896 1.1 roy done
897 1.1 roy for x in '.' '-' '~'; do
898 1.1 roy case "$iface" in
899 1.1 roy [$x]*) error_exit \
900 1.1 roy "$x not allowed at start of interface name";;
901 1.1 roy esac
902 1.1 roy done
903 1.2 kre [ "$cmd" = a ] && [ -t 0 ] && error_exit "No file given via stdin"
904 1.1 roy fi
905 1.1 roy
906 1.2 kre if [ ! -d "$VARDIR" ]; then
907 1.2 kre if [ -L "$VARDIR" ]; then
908 1.2 kre dir="$(readlink "$VARDIR")"
909 1.2 kre # link maybe relative
910 1.2 kre cd "${VARDIR%/*}"
911 1.2 kre if ! mkdir -m 0755 -p "$dir"; then
912 1.2 kre error_exit "Failed to create needed" \
913 1.2 kre "directory $dir"
914 1.2 kre fi
915 1.2 kre else
916 1.2 kre if ! mkdir -m 0755 -p "$VARDIR"; then
917 1.2 kre error_exit "Failed to create needed" \
918 1.2 kre "directory $VARDIR"
919 1.1 roy fi
920 1.1 roy fi
921 1.2 kre fi
922 1.2 kre
923 1.2 kre if [ ! -d "$IFACEDIR" ]; then
924 1.1 roy mkdir -m 0755 -p "$IFACEDIR" || \
925 1.1 roy error_exit "Failed to create needed directory $IFACEDIR"
926 1.1 roy if [ "$cmd" = d ]; then
927 1.2 kre # Provide the same error messages as below
928 1.2 kre if ! ${force}; then
929 1.2 kre cd "$IFACEDIR"
930 1.2 kre for i in $args; do
931 1.2 kre warn "No resolv.conf for interface $i"
932 1.2 kre done
933 1.2 kre fi
934 1.2 kre ${force}
935 1.2 kre exit $?
936 1.1 roy fi
937 1.1 roy fi
938 1.1 roy
939 1.2 kre # An interface was added, changed, deleted or a general update was called.
940 1.2 kre # Due to exclusivity we need to ensure that this is an atomic operation.
941 1.2 kre # Our subscribers *may* need this as well if the init system is sub par.
942 1.2 kre # As such we spinlock at this point as best we can.
943 1.2 kre # We don't use flock(1) because it's not widely available and normally resides
944 1.2 kre # in /usr which we do our very best to operate without.
945 1.2 kre [ -w "$VARDIR" ] || error_exit "Cannot write to $LOCKDIR"
946 1.2 kre : ${lock_timeout:=10}
947 1.9 roy : ${clear_nopids:=5}
948 1.9 roy have_pid=false
949 1.9 roy had_pid=false
950 1.2 kre while true; do
951 1.2 kre if mkdir "$LOCKDIR" 2>/dev/null; then
952 1.2 kre trap 'rm -rf "$LOCKDIR";' EXIT
953 1.2 kre trap 'rm -rf "$LOCKDIR"; exit 1' INT QUIT ABRT SEGV ALRM TERM
954 1.2 kre echo $$ >"$LOCKDIR/pid"
955 1.2 kre break
956 1.2 kre fi
957 1.9 roy pid=$(cat "$LOCKDIR/pid" 2>/dev/null)
958 1.9 roy if [ "$pid" -gt 0 ] 2>/dev/null; then
959 1.9 roy have_pid=true
960 1.9 roy had_pid=true
961 1.9 roy else
962 1.9 roy have_pid=false
963 1.9 roy clear_nopids=$(($clear_nopids - 1))
964 1.9 roy if [ "$clear_nopids" -le 0 ]; then
965 1.9 roy warn "not seen a pid, clearing lock directory"
966 1.9 roy rm -rf "$LOCKDIR"
967 1.9 roy else
968 1.9 roy lock_timeout=$(($lock_timeout - 1))
969 1.9 roy sleep 1
970 1.9 roy fi
971 1.9 roy continue
972 1.9 roy fi
973 1.9 roy if $have_pid && ! kill -0 "$pid"; then
974 1.2 kre warn "clearing stale lock pid $pid"
975 1.2 kre rm -rf "$LOCKDIR"
976 1.2 kre continue
977 1.2 kre fi
978 1.2 kre lock_timeout=$(($lock_timeout - 1))
979 1.2 kre if [ "$lock_timeout" -le 0 ]; then
980 1.9 roy if $have_pid; then
981 1.9 roy error_exit "timed out waiting for lock from pid $pid"
982 1.9 roy else
983 1.9 roy if $had_pid; then
984 1.9 roy error_exit "timed out waiting for lock" \
985 1.9 roy "from some pids"
986 1.9 roy else
987 1.9 roy error_exit "timed out waiting for lock"
988 1.9 roy fi
989 1.9 roy fi
990 1.2 kre fi
991 1.2 kre sleep 1
992 1.2 kre done
993 1.9 roy unset have_pid had_pid clear_nopids
994 1.2 kre
995 1.2 kre case "$cmd" in
996 1.2 kre a)
997 1.1 roy # Read resolv.conf from stdin
998 1.2 kre resolv="$(cat)"
999 1.2 kre changed=false
1000 1.2 kre changedfile=false
1001 1.1 roy # If what we are given matches what we have, then do nothing
1002 1.1 roy if [ -e "$IFACEDIR/$iface" ]; then
1003 1.2 kre if [ "$(echo "$resolv")" != \
1004 1.1 roy "$(cat "$IFACEDIR/$iface")" ]
1005 1.1 roy then
1006 1.2 kre changed=true
1007 1.2 kre changedfile=true
1008 1.1 roy fi
1009 1.2 kre else
1010 1.2 kre changed=true
1011 1.2 kre changedfile=true
1012 1.1 roy fi
1013 1.2 kre
1014 1.2 kre # Set metric and private before creating the interface resolv.conf file
1015 1.2 kre # to ensure that it will have the correct flags
1016 1.1 roy [ ! -d "$METRICDIR" ] && mkdir "$METRICDIR"
1017 1.2 kre oldmetric="$METRICDIR/"*" $iface"
1018 1.2 kre newmetric=
1019 1.1 roy if [ -n "$IF_METRIC" ]; then
1020 1.1 roy # Pad metric to 6 characters, so 5 is less than 10
1021 1.1 roy while [ ${#IF_METRIC} -le 6 ]; do
1022 1.1 roy IF_METRIC="0$IF_METRIC"
1023 1.1 roy done
1024 1.2 kre newmetric="$METRICDIR/$IF_METRIC $iface"
1025 1.1 roy fi
1026 1.2 kre rm -f "$METRICDIR/"*" $iface"
1027 1.2 kre [ "$oldmetric" != "$newmetric" ] &&
1028 1.2 kre [ "$oldmetric" != "$METRICDIR/* $iface" ] &&
1029 1.2 kre changed=true
1030 1.2 kre [ -n "$newmetric" ] && echo " " >"$newmetric"
1031 1.2 kre
1032 1.1 roy case "$IF_PRIVATE" in
1033 1.1 roy [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1034 1.1 roy if [ ! -d "$PRIVATEDIR" ]; then
1035 1.1 roy [ -e "$PRIVATEDIR" ] && rm "$PRIVATEDIR"
1036 1.1 roy mkdir "$PRIVATEDIR"
1037 1.1 roy fi
1038 1.2 kre [ -e "$PRIVATEDIR/$iface" ] || changed=true
1039 1.1 roy [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$iface"
1040 1.1 roy ;;
1041 1.1 roy *)
1042 1.1 roy if [ -e "$PRIVATEDIR/$iface" ]; then
1043 1.1 roy rm -f "$PRIVATEDIR/$iface"
1044 1.2 kre changed=true
1045 1.1 roy fi
1046 1.1 roy ;;
1047 1.1 roy esac
1048 1.2 kre
1049 1.2 kre oldexcl=
1050 1.2 kre for x in "$EXCLUSIVEDIR/"*" $iface"; do
1051 1.2 kre if [ -f "$x" ]; then
1052 1.2 kre oldexcl="$x"
1053 1.2 kre break
1054 1.2 kre fi
1055 1.2 kre done
1056 1.2 kre case "$IF_EXCLUSIVE" in
1057 1.2 kre [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
1058 1.2 kre if [ ! -d "$EXCLUSIVEDIR" ]; then
1059 1.2 kre [ -e "$EXCLUSIVEDIR" ] && rm "$EXCLUSIVEDIR"
1060 1.2 kre mkdir "$EXCLUSIVEDIR"
1061 1.2 kre fi
1062 1.2 kre cd "$EXCLUSIVEDIR"
1063 1.2 kre for x in *; do
1064 1.2 kre [ -f "$x" ] && break
1065 1.2 kre done
1066 1.2 kre if [ "${x#* }" != "$iface" ]; then
1067 1.2 kre if [ "$x" = "${x% *}" ]; then
1068 1.2 kre x=10000000
1069 1.2 kre else
1070 1.2 kre x="${x% *}"
1071 1.2 kre fi
1072 1.2 kre if [ "$x" = "0000000" ]; then
1073 1.2 kre warn "exclusive underflow"
1074 1.2 kre else
1075 1.2 kre x=$(($x - 1))
1076 1.2 kre fi
1077 1.2 kre if [ -d "$EXCLUSIVEDIR" ]; then
1078 1.2 kre echo " " >"$EXCLUSIVEDIR/$x $iface"
1079 1.2 kre fi
1080 1.2 kre changed=true
1081 1.2 kre fi
1082 1.2 kre ;;
1083 1.2 kre *)
1084 1.2 kre if [ -f "$oldexcl" ]; then
1085 1.2 kre rm -f "$oldexcl"
1086 1.2 kre changed=true
1087 1.2 kre fi
1088 1.2 kre ;;
1089 1.2 kre esac
1090 1.2 kre
1091 1.2 kre if $changedfile; then
1092 1.2 kre printf "%s\n" "$resolv" >"$IFACEDIR/$iface" || exit $?
1093 1.2 kre elif ! $changed; then
1094 1.2 kre exit 0
1095 1.2 kre fi
1096 1.2 kre unset changed changedfile oldmetric newmetric x oldexcl
1097 1.2 kre ;;
1098 1.2 kre
1099 1.2 kre d)
1100 1.2 kre # Delete any existing information about the interface
1101 1.2 kre cd "$IFACEDIR"
1102 1.2 kre changed=false
1103 1.2 kre for i in $args; do
1104 1.2 kre if [ -e "$i" ]; then
1105 1.2 kre changed=true
1106 1.2 kre elif ! ${force}; then
1107 1.2 kre warn "No resolv.conf for interface $i"
1108 1.2 kre fi
1109 1.2 kre rm -f "$i" "$METRICDIR/"*" $i" \
1110 1.2 kre "$PRIVATEDIR/$i" \
1111 1.2 kre "$EXCLUSIVEDIR/"*" $i" || exit $?
1112 1.2 kre done
1113 1.9 roy
1114 1.9 roy if ! $changed; then
1115 1.2 kre # Set the return code based on the forced flag
1116 1.9 roy $force
1117 1.2 kre exit $?
1118 1.2 kre fi
1119 1.2 kre unset changed i
1120 1.2 kre ;;
1121 1.9 roy
1122 1.9 roy C)
1123 1.9 roy # Mark interface as deprecated
1124 1.9 roy [ ! -d "$DEPRECATEDDIR" ] && mkdir "$DEPRECATEDDIR"
1125 1.9 roy cd "$DEPRECATEDDIR"
1126 1.9 roy changed=false
1127 1.9 roy for i in $args; do
1128 1.9 roy if [ ! -e "$i" ]; then
1129 1.9 roy changed=true
1130 1.9 roy echo " " >"$i" || exit $?
1131 1.9 roy fi
1132 1.9 roy done
1133 1.9 roy $changed || exit 0
1134 1.9 roy unset changed i
1135 1.9 roy ;;
1136 1.9 roy
1137 1.9 roy c)
1138 1.9 roy # Mark interface as active
1139 1.9 roy if [ -d "$DEPRECATEDDIR" ]; then
1140 1.9 roy cd "$DEPRECATEDDIR"
1141 1.9 roy changed=false
1142 1.9 roy for i in $args; do
1143 1.9 roy if [ -e "$i" ]; then
1144 1.9 roy changed=true
1145 1.9 roy rm "$i" || exit $?
1146 1.9 roy fi
1147 1.9 roy done
1148 1.9 roy $changed || exit 0
1149 1.9 roy unset changed i
1150 1.9 roy fi
1151 1.9 roy ;;
1152 1.2 kre esac
1153 1.2 kre
1154 1.2 kre case "${resolvconf:-YES}" in
1155 1.2 kre [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
1156 1.2 kre *) exit 0;;
1157 1.2 kre esac
1158 1.2 kre
1159 1.2 kre # Try and detect a suitable init system for our scripts
1160 1.2 kre detect_init
1161 1.2 kre export RESTARTCMD RCDIR _NOINIT_WARNED
1162 1.1 roy
1163 1.1 roy eval "$(make_vars)"
1164 1.2 kre export RESOLVCONF DOMAINS SEARCH NAMESERVERS LOCALNAMESERVERS
1165 1.11 roy : ${list_resolv:=list_resolv -L}
1166 1.1 roy retval=0
1167 1.2 kre
1168 1.2 kre # Run scripts in the same directory resolvconf is run from
1169 1.2 kre # in case any scripts accidentally dump files in the wrong place.
1170 1.2 kre cd "$_PWD"
1171 1.1 roy for script in "$LIBEXECDIR"/*; do
1172 1.2 kre if [ -f "$script" ]; then
1173 1.2 kre eval script_enabled="\$${script##*/}"
1174 1.2 kre case "${script_enabled:-YES}" in
1175 1.2 kre [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
1176 1.2 kre *) continue;;
1177 1.2 kre esac
1178 1.2 kre if [ -x "$script" ]; then
1179 1.2 kre "$script" "$cmd" "$iface"
1180 1.2 kre else
1181 1.2 kre (set -- "$cmd" "$iface"; . "$script")
1182 1.2 kre fi
1183 1.2 kre retval=$(($retval + $?))
1184 1.2 kre fi
1185 1.1 roy done
1186 1.1 roy exit $retval
1187