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