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

Contents of /trunk/sh/net.sh

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20