a946ed8c44b5cfa9f95dd6ad654d476dca069e7d
[openresolv] / resolvconf.in
1 #!/bin/sh
2 # Copyright (c) 2007-2015 Roy Marples
3 # All rights reserved
4
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #     * Redistributions of source code must retain the above copyright
9 #       notice, this list of conditions and the following disclaimer.
10 #     * Redistributions in binary form must reproduce the above
11 #       copyright notice, this list of conditions and the following
12 #       disclaimer in the documentation and/or other materials provided
13 #       with the distribution.
14 #
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27 RESOLVCONF="$0"
28 SYSCONFDIR=@SYSCONFDIR@
29 LIBEXECDIR=@LIBEXECDIR@
30 VARDIR=@VARDIR@
31
32 # Disregard dhcpcd setting
33 unset interface_order state_dir
34
35 # If you change this, change the test in VFLAG and libc.in as well
36 local_nameservers="127.* 0.0.0.0 255.255.255.255 ::1"
37
38 dynamic_order="tap[0-9]* tun[0-9]* vpn vpn[0-9]* ppp[0-9]* ippp[0-9]*"
39 interface_order="lo lo[0-9]*"
40 name_server_blacklist="0.0.0.0"
41
42 # Support original resolvconf configuration layout
43 # as well as the openresolv config file
44 if [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
45         . "$SYSCONFDIR"/resolvconf.conf
46         [ -n "$state_dir" ] && VARDIR="$state_dir"
47 elif [ -d "$SYSCONFDIR/resolvconf" ]; then
48         SYSCONFDIR="$SYSCONFDIR/resolvconf"
49         if [ -f "$SYSCONFDIR"/interface-order ]; then
50                 interface_order="$(cat "$SYSCONFDIR"/interface-order)"
51         fi
52 fi
53 IFACEDIR="$VARDIR/interfaces"
54 METRICDIR="$VARDIR/metrics"
55 PRIVATEDIR="$VARDIR/private"
56 EXCLUSIVEDIR="$VARDIR/exclusive"
57 LOCKDIR="$VARDIR/lock"
58
59 warn()
60 {
61         echo "$*" >&2
62 }
63
64 error_exit()
65 {
66         echo "$*" >&2
67         exit 1
68 }
69
70 usage()
71 {
72         cat <<-EOF
73         Usage: ${RESOLVCONF##*/} [options]
74
75         Inform the system about any DNS updates.
76
77         Options:
78           -a \$INTERFACE    Add DNS information to the specified interface
79                            (DNS supplied via stdin in resolv.conf format)
80           -m metric        Give the added DNS information a metric
81           -p               Mark the interface as private
82           -x               Mark the interface as exclusive
83           -d \$INTERFACE    Delete DNS information from the specified interface
84           -f               Ignore non existant interfaces
85           -I               Init the state dir
86           -u               Run updates from our current DNS information
87           -l [\$PATTERN]    Show DNS information, optionally from interfaces
88                            that match the specified pattern
89           -i [\$PATTERN]    Show interfaces that have supplied DNS information
90                    optionally from interfaces that match the specified
91                    pattern
92           -v [\$PATTERN]    echo NEWDOMAIN, NEWSEARCH and NEWNS variables to
93                            the console
94           -h               Show this help cruft
95         EOF
96         [ -z "$1" ] && exit 0
97         echo
98         error_exit "$*"
99 }
100
101 echo_resolv()
102 {
103         local line= OIFS="$IFS"
104
105         [ -n "$1" -a -f "$IFACEDIR/$1" ] || return 1
106         echo "# resolv.conf from $1"
107         # Our variable maker works of the fact each resolv.conf per interface
108         # is separated by blank lines.
109         # So we remove them when echoing them.
110         while read -r line; do
111                 IFS="$OIFS"
112                 if [ -n "$line" ]; then
113                         # We need to set IFS here to preserve any whitespace
114                         IFS=''
115                         printf "%s\n" "$line"
116                 fi
117         done < "$IFACEDIR/$1"
118         echo
119         IFS="$OIFS"
120 }
121
122 # Parse resolv.conf's and make variables
123 # for domain name servers, search name servers and global nameservers
124 parse_resolv()
125 {
126         local line= ns= ds= search= d= n= newns=
127         local new=true iface= private=false p= domain= l= islocal=
128
129         newns=
130
131         while read -r line; do
132                 case "$line" in
133                 "# resolv.conf from "*)
134                         if ${new}; then
135                                 iface="${line#\# resolv.conf from *}"
136                                 new=false
137                                 if [ -e "$PRIVATEDIR/$iface" ]; then
138                                         private=true
139                                 else
140                                         # Allow expansion
141                                         cd "$IFACEDIR"
142                                         private=false
143                                         for p in $private_interfaces; do
144                                                 case "$iface" in
145                                                 "$p"|"$p":*) private=true; break;;
146                                                 esac
147                                         done
148                                 fi
149                         fi
150                         ;;
151                 "nameserver "*)
152                         islocal=false
153                         for l in $local_nameservers; do
154                                 case "${line#* }" in
155                                 $l)
156                                         islocal=true
157                                         echo "LOCALNAMESERVERS=\"\$LOCALNAMESERVERS ${line#* }\""
158                                         break
159                                         ;;
160                                 esac
161                         done
162                         $islocal || ns="$ns${line#* } "
163                         ;;
164                 "domain "*)
165                         if [ -z "$domain" ]; then
166                                 domain="${line#* }"
167                                 echo "DOMAIN=\"$domain\""
168                         fi
169                         search="${line#* }"
170                         ;;
171                 "search "*)
172                         search="${line#* }"
173                         ;;
174                 *)
175                         [ -n "$line" ] && continue
176                         if [ -n "$ns" -a -n "$search" ]; then
177                                 newns=
178                                 for n in $ns; do
179                                         newns="$newns${newns:+,}$n"
180                                 done
181                                 ds=
182                                 for d in $search; do
183                                         ds="$ds${ds:+ }$d:$newns"
184                                 done
185                                 echo "DOMAINS=\"\$DOMAINS $ds\""
186                         fi
187                         echo "SEARCH=\"\$SEARCH $search\""
188                         if ! $private; then
189                                 echo "NAMESERVERS=\"\$NAMESERVERS $ns\""
190                         fi
191                         ns=
192                         search=
193                         new=true
194                         ;;
195                 esac
196         done
197 }
198
199 uniqify()
200 {
201         local result=
202         while [ -n "$1" ]; do
203                 case " $result " in
204                 *" $1 "*);;
205                 *) result="$result $1";;
206                 esac
207                 shift
208         done
209         echo "${result# *}"
210 }
211
212 dirname()
213 {
214         local dir= OIFS="$IFS"
215         local IFS=/
216         set -- $@
217         IFS="$OIFS"
218         if [ -n "$1" ]; then
219                 printf %s .
220         else
221                 shift
222         fi
223         while [ -n "$2" ]; do
224                 printf "/%s" "$1"
225                 shift
226         done
227         printf "\n"
228 }
229
230 config_mkdirs()
231 {
232         local e=0 f d
233         for f; do
234                 [ -n "$f" ] || continue
235                 d="$(dirname "$f")"
236                 if [ ! -d "$d" ]; then
237                         if type install >/dev/null 2>&1; then
238                                 install -d "$d" || e=$?
239                         else
240                                 mkdir "$d" || e=$?
241                         fi
242                 fi
243         done
244         return $e
245 }
246
247 list_resolv()
248 {
249         [ -d "$IFACEDIR" ] || return 0
250
251         local report=false list= retval=0 cmd="$1" excl=
252         shift
253
254         case "$IF_EXCLUSIVE" in
255         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
256                 if [ -d "$EXCLUSIVEDIR" ]; then
257                         cd "$EXCLUSIVEDIR"
258                         for i in *; do
259                                 if [ -f "$i" ]; then
260                                         list="${i#* }"
261                                         break
262                                 fi
263                         done
264                 fi
265                 excl=true
266                 ;;
267         *)
268                 excl=false
269                 ;;
270         esac
271
272         # If we have an interface ordering list, then use that.
273         # It works by just using pathname expansion in the interface directory.
274         if [ -n "$1" ]; then
275                 list="$*"
276                 $force || report=true
277         elif ! $excl; then
278                 cd "$IFACEDIR"
279                 for i in $interface_order; do
280                         [ -f "$i" ] && list="$list $i"
281                         for ii in "$i":* "$i".*; do
282                                 [ -f "$ii" ] && list="$list $ii"
283                         done
284                 done
285                 for i in $dynamic_order; do
286                         if [ -e "$i" -a ! -e "$METRICDIR/"*" $i" ]; then
287                                 list="$list $i"
288                         fi
289                         for ii in "$i":* "$i".*; do
290                                 if [ -f "$ii" -a ! -e "$METRICDIR/"*" $ii" ]; then
291                                         list="$list $ii"
292                                 fi
293                         done
294                 done
295                 if [ -d "$METRICDIR" ]; then
296                         cd "$METRICDIR"
297                         for i in *; do
298                                 [ -f "$i" ] && list="$list ${i#* }"
299                         done
300                 fi
301                 list="$list *"
302         fi
303
304         cd "$IFACEDIR"
305         retval=1
306         for i in $(uniqify $list); do
307                 # Only list interfaces which we really have
308                 if ! [ -f "$i" ]; then
309                         if $report; then
310                                 echo "No resolv.conf for interface $i" >&2
311                                 retval=2
312                         fi
313                         continue
314                 fi
315                 
316                 if [ "$cmd" = i -o "$cmd" = "-i" ]; then
317                         printf %s "$i "
318                 else
319                         echo_resolv "$i"
320                 fi
321                 [ $? = 0 -a "$retval" = 1 ] && retval=0
322         done
323         [ "$cmd" = i -o "$cmd" = "-i" ] && echo
324         return $retval
325 }
326
327 list_remove() {
328         local list= e= l= result= found= retval=0
329
330         [ -z "$2" ] && return 0
331         eval list=\"\$$1\"
332         shift
333
334         set -f
335         for e; do
336                 found=false
337                 for l in $list; do
338                         case "$e" in
339                         $l) found=true;;
340                         esac
341                         $found && break
342                 done
343                 if $found; then
344                         retval=$(($retval + 1))
345                 else
346                         result="$result $e"
347                 fi
348         done
349         set +f
350         echo "${result# *}"
351         return $retval
352 }
353
354 echo_prepend()
355 {
356         echo "# Generated by resolvconf"
357         if [ -n "$search_domains" ]; then
358                 echo "search $search_domains"
359         fi
360         for n in $name_servers; do
361                 echo "nameserver $n"
362         done
363         echo
364 }
365
366 echo_append()
367 {
368         echo "# Generated by resolvconf"
369         if [ -n "$search_domains_append" ]; then
370                 echo "search $search_domains_append"
371         fi
372         for n in $name_servers_append; do
373                 echo "nameserver $n"
374         done
375         echo
376 }
377
378 replace()
379 {
380         local r= k= f= v= val= sub=
381
382         while read -r keyword value; do
383                 for r in $replace; do
384                         k="${r%%/*}"
385                         r="${r#*/}"
386                         f="${r%%/*}"
387                         r="${r#*/}"
388                         v="${r%%/*}"
389                         case "$keyword" in
390                         $k)
391                                 case "$value" in
392                                 $f) value="$v";;
393                                 esac
394                                 ;;
395                         esac
396                 done
397                 val=
398                 for sub in $value; do
399                         for r in $replace_sub; do
400                                 k="${r%%/*}"
401                                 r="${r#*/}"
402                                 f="${r%%/*}"
403                                 r="${r#*/}"
404                                 v="${r%%/*}"
405                                 case "$keyword" in
406                                 $k)
407                                         case "$sub" in
408                                         $f) sub="$v";;
409                                         esac
410                                         ;;
411                                 esac
412                         done
413                         val="$val${val:+ }$sub"
414                 done
415                 printf "%s %s\n" "$keyword" "$val"
416         done
417 }
418
419 make_vars()
420 {
421         local newdomains= d= dn= newns= ns=
422
423         # Clear variables
424         DOMAIN=
425         DOMAINS=
426         SEARCH=
427         NAMESERVERS=
428         LOCALNAMESERVERS=
429         
430         if [ -n "$name_servers" -o -n "$search_domains" ]; then
431                 eval "$(echo_prepend | parse_resolv)"
432         fi
433         if [ -z "$VFLAG" ]; then
434                 IF_EXCLUSIVE=1
435                 list_resolv -i "$@" >/dev/null || IF_EXCLUSIVE=0
436                 eval "$(list_resolv -l "$@" | replace | parse_resolv)"
437         fi
438         if [ -n "$name_servers_append" -o -n "$search_domains_append" ]; then
439                 eval "$(echo_append | parse_resolv)"
440         fi
441
442         # Ensure that we only list each domain once
443         for d in $DOMAINS; do
444                 dn="${d%%:*}"
445                 list_remove domain_blacklist "$dn" >/dev/null || continue
446                 case " $newdomains" in
447                 *" ${dn}:"*) continue;;
448                 esac
449                 newns=
450                 for nd in $DOMAINS; do
451                         if [ "$dn" = "${nd%%:*}" ]; then
452                                 ns="${nd#*:}"
453                                 while [ -n "$ns" ]; do
454                                         case ",$newns," in
455                                         *,${ns%%,*},*) ;;
456                                         *) list_remove name_server_blacklist \
457                                                 "${ns%%,*}" >/dev/null \
458                                         && newns="$newns${newns:+,}${ns%%,*}";;
459                                         esac
460                                         [ "$ns" = "${ns#*,}" ] && break
461                                         ns="${ns#*,}"
462                                 done
463                         fi
464                 done
465                 if [ -n "$newns" ]; then
466                         newdomains="$newdomains${newdomains:+ }$dn:$newns"
467                 fi
468         done
469         DOMAIN="$(list_remove domain_blacklist $DOMAIN)"
470         SEARCH="$(uniqify $SEARCH)"
471         SEARCH="$(list_remove domain_blacklist $SEARCH)"
472         NAMESERVERS="$(uniqify $NAMESERVERS)"
473         NAMESERVERS="$(list_remove name_server_blacklist $NAMESERVERS)"
474         LOCALNAMESERVERS="$(uniqify $LOCALNAMESERVERS)"
475         LOCALNAMESERVERS="$(list_remove name_server_blacklist $LOCALNAMESERVERS)"
476         echo "DOMAIN='$DOMAIN'"
477         echo "SEARCH='$SEARCH'"
478         echo "NAMESERVERS='$NAMESERVERS'"
479         echo "LOCALNAMESERVERS='$LOCALNAMESERVERS'"
480         echo "DOMAINS='$newdomains'"
481 }
482
483 force=false
484 VFLAG=
485 while getopts a:Dd:fhIilm:puvVx OPT; do
486         case "$OPT" in
487         f) force=true;;
488         h) usage;;
489         m) IF_METRIC="$OPTARG";;
490         p) IF_PRIVATE=1;;
491         V)
492                 VFLAG=1
493                 if [ "$local_nameservers" = \
494                     "127.* 0.0.0.0 255.255.255.255 ::1" ]
495                 then
496                         local_nameservers=
497                 fi
498                 ;;
499         x) IF_EXCLUSIVE=1;;
500         '?') ;;
501         *) cmd="$OPT"; iface="$OPTARG";;
502         esac
503 done
504 shift $(($OPTIND - 1))
505 args="$iface${iface:+ }$*"
506
507 # -I inits the state dir
508 if [ "$cmd" = I ]; then
509         if [ -d "$VARDIR" ]; then
510                 rm -rf "$VARDIR"/*
511         fi
512         exit $?
513 fi
514
515 # -D ensures that the listed config file base dirs exist
516 if [ "$cmd" = D ]; then
517         config_mkdirs "$@"
518         exit $?
519 fi
520
521 # -l lists our resolv files, optionally for a specific interface
522 if [ "$cmd" = l -o "$cmd" = i ]; then
523         list_resolv "$cmd" "$args"
524         exit $?
525 fi
526
527 # Not normally needed, but subscribers should be able to run independently
528 if [ "$cmd" = v -o -n "$VFLAG" ]; then
529         make_vars "$iface"
530         exit $?
531 fi
532
533 # Test that we have valid options
534 if [ "$cmd" = a -o "$cmd" = d ]; then
535         if [ -z "$iface" ]; then
536                 usage "Interface not specified"
537         fi
538 elif [ "$cmd" != u ]; then
539         [ -n "$cmd" -a "$cmd" != h ] && usage "Unknown option $cmd"
540         usage
541 fi
542
543 if [ "$cmd" = a ]; then
544         for x in '/' \\ ' ' '*'; do
545                 case "$iface" in
546                 *[$x]*) error_exit "$x not allowed in interface name";;
547                 esac
548         done
549         for x in '.' '-' '~'; do
550                 case "$iface" in
551                 [$x]*) error_exit \
552                         "$x not allowed at start of interface name";;
553                 esac
554         done
555         [ "$cmd" = a -a -t 0 ] && error_exit "No file given via stdin"
556 fi
557
558 if [ ! -d "$VARDIR" ]; then
559         if [ -L "$VARDIR" ]; then
560                 dir="$(readlink "$VARDIR")"
561                 # link maybe relative
562                 cd "${VARDIR%/*}"
563                 if ! mkdir -m 0755 -p "$dir"; then
564                         error_exit "Failed to create needed" \
565                                 "directory $dir"
566                 fi
567         else
568                 if ! mkdir -m 0755 -p "$VARDIR"; then
569                         error_exit "Failed to create needed" \
570                                 "directory $VARDIR"
571                 fi
572         fi
573 fi
574
575 if [ ! -d "$IFACEDIR" ]; then
576         mkdir -m 0755 -p "$IFACEDIR" || \
577                 error_exit "Failed to create needed directory $IFACEDIR"
578         if [ "$cmd" = d ]; then
579                 # Provide the same error messages as below
580                 if ! ${force}; then
581                         cd "$IFACEDIR"
582                         for i in $args; do
583                                 warn "No resolv.conf for interface $i"
584                         done
585                 fi
586                 ${force}
587                 exit $?
588         fi
589 fi
590
591 # An interface was added, changed, deleted or a general update was called.
592 # Due to exclusivity we need to ensure that this is an atomic operation.
593 # Our subscribers *may* need this as well if the init system is sub par.
594 # As such we spinlock at this point as best we can.
595 # We don't use flock(1) because it's not widely available and normally resides
596 # in /usr which we do our very best to operate without.
597 [ -w "$VARDIR" ] || error_exit "Cannot write to $LOCKDIR"
598 : ${lock_timeout:=10}
599 while true; do
600         if mkdir "$LOCKDIR" 2>/dev/null; then
601                 trap 'rm -rf "$LOCKDIR";' EXIT
602                 trap 'rm -rf "$LOCKDIR"; exit 1' INT QUIT ABRT SEGV ALRM TERM
603                 echo $$ >"$LOCKDIR/pid"
604                 break
605         fi
606         pid=$(cat "$LOCKDIR/pid")
607         if ! kill -0 "$pid"; then
608                 warn "clearing stale lock pid $pid"
609                 rm -rf "$LOCKDIR"
610                 continue
611         fi
612         lock_timeout=$(($lock_timeout - 1))
613         if [ "$lock_timeout" -le 0 ]; then
614                 error_exit "timed out waiting for lock from pid $pid"
615         fi
616         sleep 1
617 done
618
619 case "$cmd" in
620 a)
621         # Read resolv.conf from stdin
622         resolv="$(cat)"
623         changed=false
624         changedfile=false
625         # If what we are given matches what we have, then do nothing
626         if [ -e "$IFACEDIR/$iface" ]; then
627                 if [ "$(echo "$resolv")" != \
628                         "$(cat "$IFACEDIR/$iface")" ]
629                 then
630                         changed=true
631                         changedfile=true
632                 fi
633         else
634                 changed=true
635                 changedfile=true
636         fi
637
638         # Set metric and private before creating the interface resolv.conf file
639         # to ensure that it will have the correct flags
640         [ ! -d "$METRICDIR" ] && mkdir "$METRICDIR"
641         oldmetric="$METRICDIR/"*" $iface"
642         newmetric=
643         if [ -n "$IF_METRIC" ]; then
644                 # Pad metric to 6 characters, so 5 is less than 10
645                 while [ ${#IF_METRIC} -le 6 ]; do
646                         IF_METRIC="0$IF_METRIC"
647                 done
648                 newmetric="$METRICDIR/$IF_METRIC $iface"
649         fi
650         rm -f "$METRICDIR/"*" $iface"
651         [ "$oldmetric" != "$newmetric" -a \
652             "$oldmetric" != "$METRICDIR/* $iface" ] &&
653                 changed=true
654         [ -n "$newmetric" ] && echo " " >"$newmetric"
655
656         case "$IF_PRIVATE" in
657         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
658                 if [ ! -d "$PRIVATEDIR" ]; then
659                         [ -e "$PRIVATEDIR" ] && rm "$PRIVATEDIR"
660                         mkdir "$PRIVATEDIR"
661                 fi
662                 [ -e "$PRIVATEDIR/$iface" ] || changed=true
663                 [ -d "$PRIVATEDIR" ] && echo " " >"$PRIVATEDIR/$iface"
664                 ;;
665         *)
666                 if [ -e "$PRIVATEDIR/$iface" ]; then
667                         rm -f "$PRIVATEDIR/$iface"
668                         changed=true
669                 fi
670                 ;;
671         esac
672
673         oldexcl=
674         for x in "$EXCLUSIVEDIR/"*" $iface"; do
675                 if [ -f "$x" ]; then
676                         oldexcl="$x"
677                         break
678                 fi
679         done
680         case "$IF_EXCLUSIVE" in
681         [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
682                 if [ ! -d "$EXCLUSIVEDIR" ]; then
683                         [ -e "$EXCLUSIVEDIR" ] && rm "$EXCLUSIVEDIR"
684                         mkdir "$EXCLUSIVEDIR"
685                 fi
686                 cd "$EXCLUSIVEDIR"
687                 for x in *; do
688                         [ -f "$x" ] && break
689                 done
690                 if [ "${x#* }" != "$iface" ]; then
691                         if [ "$x" = "${x% *}" ]; then
692                                 x=10000000
693                         else
694                                 x="${x% *}"
695                         fi
696                         if [ "$x" = "0000000" ]; then
697                                 warn "exclusive underflow"
698                         else
699                                 x=$(($x - 1))
700                         fi
701                         if [ -d "$EXCLUSIVEDIR" ]; then
702                                 echo " " >"$EXCLUSIVEDIR/$x $iface"
703                         fi
704                         changed=true
705                 fi
706                 ;;
707         *)
708                 if [ -f "$oldexcl" ]; then
709                         rm -f "$oldexcl"
710                         changed=true
711                 fi
712                 ;;
713         esac
714
715         if $changedfile; then
716                 printf "%s\n" "$resolv" >"$IFACEDIR/$iface" || exit $?
717         elif ! $changed; then
718                 exit 0
719         fi
720         unset changed changedfile oldmetric newmetric x oldexcl
721         ;;
722
723 d)
724         # Delete any existing information about the interface
725         cd "$IFACEDIR"
726         changed=false
727         for i in $args; do
728                 if [ -e "$i" ]; then
729                         changed=true
730                 elif ! ${force}; then
731                         warn "No resolv.conf for interface $i"
732                 fi
733                 rm -f "$i" "$METRICDIR/"*" $i" \
734                         "$PRIVATEDIR/$i" \
735                         "$EXCLUSIVEDIR/"*" $i" || exit $?
736         done
737         if ! ${changed}; then
738                 # Set the return code based on the forced flag
739                 ${force}
740                 exit $?
741         fi
742         unset changed i
743         ;;
744 esac
745
746 case "${resolvconf:-YES}" in
747 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
748 *) exit 0;;
749 esac
750
751 eval "$(make_vars)"
752 export RESOLVCONF DOMAINS SEARCH NAMESERVERS LOCALNAMESERVERS
753 : ${list_resolv:=list_resolv -l}
754 retval=0
755 for script in "$LIBEXECDIR"/*; do
756         if [ -f "$script" ]; then
757                 eval script_enabled="\$${script##*/}"
758                 case "${script_enabled:-YES}" in
759                 [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
760                 *) continue;;
761                 esac
762                 if [ -x "$script" ]; then
763                         "$script" "$cmd" "$iface"
764                 else
765                         (set -- "$cmd" "$iface"; . "$script")
766                 fi
767                 retval=$(($retval + $?))
768         fi
769 done
770 exit $retval