/[baselayout]/trunk/sh/net.sh
Gentoo

Contents of /trunk/sh/net.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2712 - (show annotations) (download) (as text)
Fri May 18 20:09:10 2007 UTC (7 years, 7 months ago) by uberlord
File MIME type: text/x-sh
File size: 12936 byte(s)
Be more resilient when the nettree is invalid
1 #!/sbin/runscript
2 # Copyright 1999-2007 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 MODULESDIR="${RC_LIBDIR}/net"
6 MODULESLIST="${RC_SVCDIR}/nettree"
7 _config_vars="config routes"
8
9 [ -z "${IN_BACKGROUND}" ] && IN_BACKGROUND=false
10
11 depend() {
12 local IFACE=${SVCNAME#*.}
13 local IFVAR=$(echo -n "${IFACE}" | sed -e 's/[^[:alnum:]]/_/g')
14
15 need localmount
16 after bootmisc
17 provide net
18 case "${IFACE}" in
19 lo|lo0) ;;
20 *)
21 after net.lo net.lo0
22 local prov=
23 eval prov=\$RC_NEED_${IFVAR}
24 [ -n "${prov}" ] && need ${prov}
25 eval prov=\$RC_USE_${IFVAR}
26 [ -n "${prov}" ] && use ${prov}
27 eval prov=\$RC_BEFORE_${IFVAR}
28 [ -n "${prov}" ] && before ${prov}
29 eval prov=\$RC_AFTER_${IFVAR}
30 [ -n "${prov}" ] && after ${prov}
31 eval prov=\$RC_PROVIDE_${IFVAR}
32 [ -n "${prov}" ] && provide ${prov}
33 ;;
34 esac
35 }
36
37 _shell_var() {
38 echo -n "$1" | sed -e 's/[^[:alnum:]]/_/g'
39 }
40
41 # Credit to David Leverton for this function which handily maps a bash array
42 # structure to positional parameters so existing configs work :)
43 # We'll deprecate arrays at some point though.
44 _get_array() {
45 if [ -n "${BASH}" ] ; then
46 case "$(declare -p "$1" 2>/dev/null)" in
47 "declare -a "*)
48 echo "set -- \"\${$1[@]}\""
49 return
50 ;;
51 esac
52 fi
53
54 echo "eval set -- \"\$$1\""
55 }
56
57 _wait_for_carrier() {
58 local timeout= efunc=einfon
59
60 _has_carrier && return 0
61
62 eval timeout=\$carrier_timeout_${IFVAR}
63 timeout=${timeout:-${carrier_timeout:-5}}
64
65 # Incase users don't want this nice feature ...
66 [ ${timeout} -le 0 ] && return 0
67
68 [ -n "${RC_EBUFFER}" -o "${RC_PREFIX}" = "yes" ] && efunc=einfo
69 ${efunc} "Waiting for carrier (${timeout} seconds) "
70 while [ ${timeout} -gt 0 ] ; do
71 sleep 1
72 if _has_carrier ; then
73 [ -z "${RC_EBUFFER}" ] && echo
74 eend 0
75 return 0
76 fi
77 timeout=$((${timeout} - 1))
78 [ -z "${RC_EBUFFER}" -a "${RC_PREFIX}" != "yes" ] && printf "."
79 done
80
81 [ -z "${RC_EBUFFER}" -a "${RC_PREFIX}" != "yes" ] && echo
82 eend 1
83 return 1
84 }
85
86 _netmask2cidr() {
87 local i= len=0
88
89 local IFS=.
90 for i in $1; do
91 while [ ${i} != "0" ] ; do
92 len=$((${len} + ${i} % 2))
93 i=$((${i} >> 1))
94 done
95 done
96
97 echo "${len}"
98 }
99
100 _configure_variables() {
101 local var= v= t=
102
103 for var in ${_config_vars} ; do
104 local v=
105 for t in "$@" ; do
106 eval v=\$${var}_${t}
107 if [ -n "${v}" ] ; then
108 eval ${var}_${IFVAR}=\$${var}_${t}
109 continue 2
110 fi
111 done
112 done
113 }
114
115 _show_address() {
116 einfo "received address $(_get_inet_address "${IFACE}")"
117 }
118
119 # Basically sorts our modules into order and saves the list
120 _gen_module_list() {
121 local x= f= force=$1
122 if ! ${force} && [ -s "${MODULESLIST}" -a "${MODULESLIST}" -nt "${MODULESDIR}" ] ; then
123 local update=false
124 for x in "${MODULESDIR}"/* ; do
125 [ -e "${x}" ] || continue
126 if [ "${x}" -nt "${MODULESLIST}" ] ; then
127 update=true
128 break
129 fi
130 done
131 ${update} || return 0
132 fi
133
134 einfo "Caching network module dependencies"
135 # Run in a subshell to protect the main script
136 (
137 after() {
138 eval ${MODULE}_after="\"\${${MODULE}_after}\${${MODULE}_after:+ }$*\""
139 }
140
141 before() {
142 local mod=${MODULE}
143 local MODULE=
144 for MODULE in "$@" ; do
145 after "${mod}"
146 done
147 }
148
149 program() {
150 if [ "$1" = "start" -o "$1" = "stop" ] ; then
151 local s="$1"
152 shift
153 eval ${MODULE}_program_${s}="\"\${${MODULE}_program_${s}}\${${MODULE}_program_${s}:+ }$*\""
154 else
155 eval ${MODULE}_program="\"\${${MODULE}_program}\${${MODULE}_program:+ }$*\""
156 fi
157 }
158
159 provide() {
160 eval ${MODULE}_provide="\"\${${MODULE}_provide}\${${MODULE}_provide:+ }$*\""
161 local x
162 for x in $* ; do
163 eval ${x}_providedby="\"\${${MODULE}_providedby}\${${MODULE}_providedby:+ }${MODULE}\""
164 done
165 }
166
167 for MODULE in "${MODULESDIR}"/* ; do
168 sh -n "${MODULE}" || continue
169 . "${MODULE}" || continue
170 MODULE=${MODULE#${MODULESDIR}/}
171 MODULE=${MODULE%.sh}
172 eval ${MODULE}_depend
173 MODULES="${MODULES} ${MODULE}"
174 done
175
176 VISITED=
177 SORTED=
178 visit() {
179 case " ${VISITED} " in
180 *" $1 "*) return ;;
181 esac
182 VISITED="${VISITED} $1"
183
184 eval AFTER=\$${1}_after
185 for MODULE in ${AFTER} ; do
186 eval PROVIDEDBY=\$${MODULE}_providedby
187 if [ -n "${PROVIDEDBY}" ] ; then
188 for MODULE in ${PROVIDEDBY} ; do
189 visit "${MODULE}"
190 done
191 else
192 visit "${MODULE}"
193 fi
194 done
195
196 eval PROVIDE=\$${1}_provide
197 for MODULE in ${PROVIDE} ; do
198 visit "${MODULE}"
199 done
200
201 eval PROVIDEDBY=\$${1}_providedby
202 [ -z "${PROVIDEDBY}" ] && SORTED="${SORTED} $1"
203 }
204
205 for MODULE in ${MODULES} ; do
206 visit "${MODULE}"
207 done
208
209 > "${MODULESLIST}"
210 i=0
211 for MODULE in ${SORTED} ; do
212 eval PROGRAM=\$${MODULE}_program
213 eval PROGRAM_START=\$${MODULE}_program_start
214 eval PROGRAM_STOP=\$${MODULE}_program_stop
215 #for x in ${PROGRAM} ; do
216 # [ -x "${x}" ] || continue 2
217 #done
218 eval PROVIDE=\$${MODULE}_provide
219 echo "module_${i}='${MODULE}'" >> "${MODULESLIST}"
220 echo "module_${i}_program='${PROGRAM}'" >> "${MODULESLIST}"
221 echo "module_${i}_program_start='${PROGRAM_START}'" >> "${MODULESLIST}"
222 echo "module_${i}_program_stop='${PROGRAM_STOP}'" >> "${MODULESLIST}"
223 echo "module_${i}_provide='${PROVIDE}'" >> "${MODULESLIST}"
224 i=$((${i} + 1))
225 done
226 echo "module_${i}=" >> "${MODULESLIST}"
227 )
228
229 return 0
230 }
231
232 _load_modules() {
233 local starting=$1 mymods=
234
235 # Ensure our list is up to date
236 _gen_module_list false
237 if ! . "${MODULESLIST}" ; then
238 _gen_module_list true
239 . "${MODULESLIST}"
240 fi
241
242 MODULES=
243 if [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] ; then
244 eval mymods=\$modules_${IFVAR}
245 [ -z "${mymods}" ] && mymods=${modules}
246 fi
247
248 local i=-1 x= mod= f= provides=
249 while true ; do
250 i=$((${i} + 1))
251 eval mod=\$module_${i}
252 [ -z "${mod}" ] && break
253 [ -e "${MODULESDIR}/${mod}.sh" ] || continue
254
255 eval set -- \$module_${i}_program
256 if [ -n "$1" ] ; then
257 x=
258 for x in "$@" ; do
259 [ -x "${x}" ] && break
260 done
261 [ -x "${x}" ] || continue
262 fi
263 if ${starting} ; then
264 eval set -- \$module_${i}_program_start
265 else
266 eval set -- \$module_${i}_program_stop
267 fi
268 if [ -n "$1" ] ; then
269 x=
270 for x in "$@" ; do
271 [ -x "${x}" ] && break
272 done
273 [ -x "${x}" ] || continue
274 fi
275
276 eval provides=\$module_${i}_provide
277 if ${starting} ; then
278 case " ${mymods} " in
279 *" !${mod} "*) continue ;;
280 *" !${provides} "*) [ -n "${provides}" ] && continue ;;
281 esac
282 fi
283 MODULES="${MODULES}${MODULES:+ }${mod}"
284
285 # Now load and wrap our functions
286 if ! . "${MODULESDIR}/${mod}.sh" ; then
287 eend 1 "${SVCNAME}: error loading module \`${mod}'"
288 exit 1
289 fi
290
291 [ -z "${provides}" ] && continue
292
293 # Wrap our provides
294 local f=
295 for f in pre_start start post_start ; do
296 eval "${provides}_${f}() { type ${mod}_${f} >/dev/null 2>/dev/null || return 0; ${mod}_${f} \"\$@\"; }"
297 done
298
299 eval module_${mod}_provides="${provides}"
300 eval module_${provides}_providedby="${mod}"
301 done
302
303 # Wrap our preferred modules
304 for mod in ${mymods} ; do
305 case " ${MODULES} " in
306 *" ${mod} "*)
307 eval x=\$module_${mod}_provides
308 [ -z "${x}" ] && continue
309 for f in pre_start start post_start ; do
310 eval "${x}_${f}() { type ${mod}_${f} >/dev/null 2>/dev/null || return 0; ${mod}_${f} \"\$@\"; }"
311 done
312 eval module_${x}_providedby="${mod}"
313 ;;
314 esac
315 done
316
317 # Finally remove any duplicated provides from our list if we're starting
318 # Otherwise reverse the list
319 local LIST="${MODULES}" p=
320 MODULES=
321 if ${starting} ; then
322 for mod in ${LIST} ; do
323 eval x=\$module_${mod}_provides
324 if [ -n "${x}" ] ; then
325 eval p=\$module_${x}_providedby
326 [ "${mod}" != "${p}" ] && continue
327 fi
328 MODULES="${MODULES}${MODULES:+ }${mod}"
329 done
330 else
331 for mod in ${LIST} ; do
332 MODULES="${mod}${MODULES:+ }${MODULES}"
333 done
334 fi
335
336 veinfo "Loaded modules: ${MODULES}"
337 }
338
339 _load_config() {
340 eval "$(_get_array "config_${IFVAR}")"
341 if [ "${IFACE}" = "lo" -o "${IFACE}" = "lo0" ] ; then
342 set -- "127.0.0.1/8" "$@"
343 else
344 if [ $# -eq 0 ] ; then
345 ewarn "No configuration specified; defaulting to DHCP"
346 set -- "dhcp"
347 fi
348 fi
349
350 # We store our config in an array like vars
351 # so modules can influence it
352 config_index=0
353 for cmd in "$@" ; do
354 eval config_${config_index}="'${cmd}'"
355 config_index=$((${config_index} + 1))
356 done
357 # Terminate the list
358 eval config_${config_index}=
359
360 config_index=0
361 eval $(_get_array fallback_${IFVAR})
362 for cmd in "$@" ; do
363 eval fallback_${config_index}="'${cmd}'"
364 config_index=$((${config_index} + 1))
365 done
366 # Terminate the list
367 eval fallback_${config_index}=
368
369 # Don't set to zero, so any net modules don't have to do anything extra
370 config_index=-1
371 }
372
373 start() {
374 local IFACE=${SVCNAME#*.} oneworked=false module=
375 local IFVAR=$(_shell_var "${IFACE}") cmd= metric=0 our_metric=$metric
376
377 einfo "Bringing up interface ${IFACE}"
378 eindent
379
380 if [ -z "${MODULES}" ] ; then
381 local MODULES=
382 _load_modules true
383 fi
384
385 _up 2>/dev/null
386
387 if type preup >/dev/null 2>/dev/null ; then
388 ebegin "Running preup"
389 eindent
390 preup || return 1
391 eoutdent
392 fi
393
394 for module in ${MODULES} ; do
395 if type "${module}_pre_start" >/dev/null 2>/dev/null ; then
396 if ! ${module}_pre_start ; then
397 eend 1
398 exit 1
399 fi
400 fi
401 done
402
403 if ! _exists ; then
404 eerror "ERROR: interface ${IFACE} does not exist"
405 eerror "Ensure that you have loaded the correct kernel module for your hardware"
406 return 1
407 fi
408
409 if ! _wait_for_carrier ; then
410 if service_started devd ; then
411 ewarn "no carrier, but devd will start us when we have one"
412 mark_service_inactive "${SVCNAME}"
413 else
414 eerror "no carrier"
415 fi
416 return 1
417 fi
418
419 local config= config_index=
420 _load_config
421 config_index=0
422
423 if [ -n "${our_metric}" ] ; then
424 metric=${our_metric}
425 elif [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] ; then
426 metric=$((${metric} + $(_ifindex)))
427 fi
428
429 while true ; do
430 eval config=\$config_${config_index}
431 [ -z "${config}" ] && break
432
433 set -- "${config}"
434 ebegin "$1"
435 eindent
436 case "$1" in
437 noop)
438 if [ -n "$(_get_inet_address)" ] ; then
439 oneworked=true
440 break
441 fi
442 ;;
443 null) : ;;
444 [0-9]*|*:*) _add_address ${config} ;;
445 *)
446 if type "${config}_start" >/dev/null 2>/dev/null ; then
447 "${config}"_start
448 else
449 eerror "nothing provides \`${config}'"
450 fi
451 ;;
452 esac
453 if eend $? ; then
454 oneworked=true
455 else
456 eval config=\$fallback_${IFVAR}
457 if [ -n "${config}" ] ; then
458 einfo "Trying fallback configuration"
459 eval config_${config_index}=\$fallback_${IFVAR}
460 eval fallback_${config_index}=
461 config_index=$((${config_index} - 1))
462 fi
463 fi
464 eoutdent
465 config_index=$((${config_index} + 1))
466 done
467
468 if ! ${oneworked} ; then
469 if type failup >/dev/null 2>/dev/null ; then
470 ebegin "Running failup"
471 eindent
472 failup
473 eoutdent
474 fi
475 return 1
476 fi
477
478 local hidefirstroute=false first=true routes=
479 eval "$(_get_array "routes_${IFVAR}")"
480 if [ "${IFACE}" = "lo" -o "${IFACE}" = "lo0" ] ; then
481 set -- "127.0.0.0/8 via 127.0.0.1" "$@"
482 hidefirstroute=true
483 fi
484 for cmd in "$@" ; do
485 if ${first} ; then
486 first=false
487 einfo "Adding routes"
488 fi
489 eindent
490 ebegin "${cmd}"
491 # Work out if we're a host or a net if not told
492 case "${cmd}" in
493 *" -net "*|*" -host "*) ;;
494 *" netmask "*) cmd="-net ${cmd}" ;;
495 *)
496 case "${cmd%% *}" in
497 *.*.*.*/32) cmd="-host ${cmd}" ;;
498 *.*.*.*/*|0.0.0.0|default) cmd="-net ${cmd}" ;;
499 *) cmd="-host ${cmd}" ;;
500 esac
501 ;;
502 esac
503 if ${hidefirstroute} ; then
504 _add_route ${cmd} >/dev/null 2>/dev/null
505 hidefirstroute=false
506 else
507 _add_route ${cmd} >/dev/null
508 fi
509 eend $?
510 eoutdent
511 done
512
513 for module in ${MODULES} ; do
514 if type "${module}_post_start" >/dev/null 2>/dev/null ; then
515 if ! ${module}_post_start ; then
516 eend 1
517 exit 1
518 fi
519 fi
520 done
521
522 if type postup >/dev/null 2>/dev/null ; then
523 ebegin "Running postup"
524 eindent
525 postup
526 eoutdent
527 fi
528
529 return 0
530 }
531
532 stop() {
533 local IFACE=${SVCNAME#*.} module=
534 local IFVAR=$(_shell_var "${IFACE}") opts=
535
536 einfo "Bringing down interface ${IFACE}"
537 eindent
538
539 if [ -z "${MODULES}" ] ; then
540 local MODULES=
541 _load_modules false
542 fi
543
544 if type predown >/dev/null 2>/dev/null ; then
545 ebegin "Running predown"
546 eindent
547 predown || return 1
548 eoutdent
549 fi
550
551 for module in ${MODULES} ; do
552 if type "${module}_pre_stop" >/dev/null 2>/dev/null ; then
553 if ! ${module}_pre_stop ; then
554 eend 1
555 exit 1
556 fi
557 fi
558 done
559
560 for module in ${MODULES} ; do
561 if type "${module}_stop" >/dev/null 2>/dev/null ; then
562 ${module}_stop
563 fi
564 done
565
566 # Only delete addresses for non PPP interfaces
567 if ! type is_ppp >/dev/null 2>/dev/null || ! is_ppp ; then
568 _delete_addresses "${IFACE}"
569 fi
570
571 for module in ${MODULES} ; do
572 if type "${module}_post_stop" >/dev/null 2>/dev/null ; then
573 ${module}_post_stop
574 fi
575 done
576
577 [ "${IN_BACKGROUND}" != "true" ] && \
578 [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] && \
579 _down 2>/dev/null
580
581 [ -x /sbin/resolvconf ] && resolvconf -d "${IFACE}"
582
583 if type postdown >/dev/null 2>/dev/null ; then
584 ebegin "Running postdown"
585 eindent
586 postdown
587 eoutdent
588 fi
589
590 return 0
591 }
592
593 # vim: set ts=4 sw=4 :

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20