/[vps]/baselayout-vserver/branches/baselayout-1_12/net-scripts/init.d/net.lo
Gentoo

Contents of /baselayout-vserver/branches/baselayout-1_12/net-scripts/init.d/net.lo

Parent Directory Parent Directory | Revision Log Revision Log


Revision 206 - (show annotations) (download)
Sun Jan 15 10:27:03 2006 UTC (8 years, 9 months ago) by phreak
File size: 27226 byte(s)
Merging r1822 for branches/baselayout-1_12
1 #!/sbin/runscript
2 # Copyright (c) 2004-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 # Contributed by Roy Marples (uberlord@gentoo.org)
6 # Many thanks to Aron Griffis (agriffis@gentoo.org)
7 # for help, ideas and patches
8
9 #NB: Config is in /etc/conf.d/net
10
11 # For pcmcia users. note that pcmcia must be added to the same
12 # runlevel as the net.* script that needs it.
13 depend() {
14 need localmount
15 use pcmcia usb isdn wlan
16
17 # Load any custom depend functions for the given interface
18 # For example, br0 may need eth0 and eth1
19 local iface="${myservice##*.}"
20 [[ $(type -t "depend_${iface}") == "function" ]] && depend_${iface}
21
22 return 0
23 }
24
25 # Define where our modules are
26 MODULES_DIR="${svclib}/net.modules.d"
27
28 # Some defaults
29 background="${background:-no}"
30
31 # Load some functions shared between ourselves and our dhcp helpers
32 source "${MODULES_DIR}/helpers.d/functions"
33
34 # Make some wrappers to fudge after/before/need/use depend flags.
35 # These are callbacks so MODULE will be set.
36 after() {
37 eval "${MODULE}_after() { echo \"$*\"; }"
38 }
39 before() {
40 eval "${MODULE}_before() { echo \"$*\"; }"
41 }
42 need() {
43 eval "${MODULE}_need() { echo \"$*\"; }"
44 }
45 installed() {
46 # We deliberately misspell this as _installed will probably be used
47 # at some point
48 eval "${MODULE}_instlled() { echo \"$*\"; }"
49 }
50 provide() {
51 eval "${MODULE}_provide() { echo \"$*\"; }"
52 }
53 functions() {
54 eval "${MODULE}_functions() { echo \"$*\"; }"
55 }
56 variables() {
57 eval "${MODULE}_variables() { echo \"$*\"; }"
58 }
59
60 # bool module_load_minimum(char *module)
61 #
62 # Does the minimum checking on a module - even when forcing
63 module_load_minimum() {
64 local f="$1" MODULE="${1##*/}"
65
66 if [[ ! -f ${f} ]]; then
67 eerror "${f} does not exist"
68 return 1
69 fi
70
71 if ! source "${f}" ; then
72 eerror "${MODULE} failed a sanity check"
73 return 1
74 fi
75
76 for f in depend; do
77 is_function "${MODULE}_${f}" && continue
78 eerror "${MODULE} does not support the required function ${f}"
79 return 1
80 done
81
82 return 0
83 }
84
85 # bool modules_load_auto()
86 #
87 # Load and check each module for sanity
88 # If the module is not installed, the functions are to be removed
89 modules_load_auto() {
90 local i j inst
91
92 # Populate the MODULES array
93 # Basically we treat evey file in ${MODULES_DIR} as a module
94 MODULES=( $( cd "${MODULES_DIR}" ; ls ) )
95 j="${#MODULES[@]}"
96 for (( i=0; i<j; i++ )); do
97 MODULES[i]="${MODULES_DIR}/${MODULES[i]}"
98 [[ ! -f ${MODULES[i]} ]] && unset MODULES[i]
99 done
100 MODULES=( "${MODULES[@]}" )
101
102 # Each of these sources into the global namespace, so it's
103 # important that module functions and variables are prefixed with
104 # the module name, for example iproute2_
105
106 j="${#MODULES[@]}"
107 loaded_interface=false
108 for (( i=0; i<j; i++ )); do
109 if [[ ${MODULES[i]##*/} == "interface" ]]; then
110 eerror "interface is a reserved name - cannot load a module called interface"
111 return 1
112 fi
113
114 (
115 u=0;
116 module_load_minimum "${MODULES[i]}" || u=1;
117 if [[ ${u} == 0 ]]; then
118 inst="${MODULES[i]##*/}_check_installed";
119 if is_function "${inst}" ; then
120 ${inst} false || u=1;
121 fi
122 fi
123 exit "${u}";
124 )
125
126 if [[ $? == 0 ]]; then
127 source "${MODULES[i]}"
128 MODULES[i]="${MODULES[i]##*/}"
129 else
130 unset MODULES[i]
131 fi
132 done
133
134 MODULES=( "${MODULES[@]}" )
135 return 0
136 }
137
138 # bool modules_check_installed(void)
139 #
140 # Ensure that all modules have the required modules loaded
141 # This enables us to remove modules from the MODULES array
142 # Whilst other modules can still explicitly call them
143 # One example of this is essidnet which configures network
144 # settings for the specific ESSID connected to as the user
145 # may be using a daemon to configure wireless instead of our
146 # iwconfig module
147 modules_check_installed() {
148 local i j missingdeps nmods="${#MODULES[@]}"
149
150 for (( i=0; i<nmods; i++ )); do
151 is_function "${MODULES[i]}_instlled" || continue
152 for j in $( ${MODULES[i]}_instlled ); do
153 missingdeps=true
154 if is_function "${j}_check_installed" ; then
155 ${j}_check_installed && missingdeps=false
156 elif is_function "${j}_depend" ; then
157 missingdeps=false
158 fi
159 ${missingdeps} && unset MODULES[i] && unset PROVIDES[i] && break
160 done
161 done
162
163 MODULES=( "${MODULES[@]}" )
164 PROVIDES=( "${PROVIDES[@]}" )
165 }
166
167 # bool modules_check_user(void)
168 modules_check_user() {
169 local -a umods
170 local i j k l nmods="${#MODULES[@]}"
171
172 # Has the interface got any specific modules?
173 umods="modules_${iface}[@]"
174 umods=( "${!umods}" )
175
176 # Global setting follows interface-specific setting
177 umods=( "${umods[@]}" "${modules[@]}" )
178
179 # Add our preferred modules
180 local -a pmods=( "iproute2" "dhcpcd" "iwconfig" "netplugd" )
181 umods=( "${umods[@]}" "${pmods[@]}" )
182
183 # First we strip any modules that conflict from user settings
184 # So if the user specifies pump then we don't use dhcpcd
185 for (( i=0; i<${#umods[@]}; i++ )); do
186 # Some users will inevitably put "dhcp" in their modules
187 # list. To keep users from screwing up their system this
188 # way, ignore this setting so that the default dhcp
189 # module will be used.
190 [[ ${umods[i]} == "dhcp" ]] && continue
191
192 # We remove any modules we explicitly don't want
193 if [[ ${umods[i]} == !* ]]; then
194 for (( j=0; j<nmods; j++ )); do
195 [[ -z ${MODULES[j]} ]] && continue
196 if [[ ${umods[i]:1} == "${MODULES[j]}" \
197 || ${umods[i]:1} == "${PROVIDES[j]}" ]]; then
198 # We may need to setup a class wrapper for it even though
199 # we don't use it directly
200 # However, we put it into an array and wrap later as
201 # another module may provide the same thing
202 ${MODULES[j]}_check_installed \
203 && WRAP_MODULES=(
204 "${WRAP_MODULES[@]}"
205 "${MODULES[j]} ${PROVIDES[j]}"
206 )
207 unset MODULES[j]
208 unset PROVIDES[j]
209 fi
210 done
211 continue
212 fi
213
214 if ! is_function "${umods[i]}_depend" ; then
215 # If the module is one of our preferred modules, then
216 # ignore this error; whatever is available will be
217 # used instead.
218 (( i < ${#umods[@]} - ${#pmods[@]} )) || continue
219
220 # The function may not exist because the modules software is
221 # not installed. Load the module and report its error
222 if [[ -e "${MODULES_DIR}/${umods[i]}" ]]; then
223 source "${MODULES_DIR}/${umods[i]}"
224 is_function "${umods[i]}_check_installed" \
225 && ${umods[i]}_check_installed true
226 else
227 eerror "The module \"${umods[i]}\" does not exist"
228 fi
229 return 1
230 fi
231
232 if is_function "${umods[i]}_provide" ; then
233 mod=$( ${umods[i]}_provide )
234 else
235 mod="${umods[i]}"
236 fi
237 for (( j=0; j<nmods; j++ )); do
238 [[ -z ${MODULES[j]} ]] && continue
239 if [[ ${PROVIDES[j]} == "${mod}" && ${umods[i]} != "${MODULES[j]}" ]]; then
240 # We don't have a match - now ensure that we still provide an
241 # alternative. This is to handle our preferred modules.
242 for (( l=0; l<nmods; l++ )); do
243 [[ ${l} == "${j}" || -z ${MODULES[l]} ]] && continue
244 if [[ ${PROVIDES[l]} == "${mod}" ]]; then
245 unset MODULES[j]
246 unset PROVIDES[j]
247 break
248 fi
249 done
250 fi
251 done
252 done
253
254 # Then we strip conflicting modules.
255 # We only need to do this for 3rd party modules that conflict with
256 # our own modules and the preferred list AND the user modules
257 # list doesn't specify a preference.
258 for (( i=0; i<nmods-1; i++ )); do
259 [[ -z ${MODULES[i]} ]] && continue
260 for (( j=i+1; j<nmods; j++)); do
261 [[ -z ${MODULES[j]} ]] && continue
262 [[ ${PROVIDES[i]} == "${PROVIDES[j]}" ]] \
263 && unset MODULES[j] && unset PROVIDES[j]
264 done
265 done
266
267 MODULES=( "${MODULES[@]}" )
268 PROVIDES=( "${PROVIDES[@]}" )
269 return 0
270 }
271
272 # void modules_sort(void)
273 #
274 # Sort our modules
275 modules_sort() {
276 local i j nmods=${#MODULES[@]} m
277 local -a provide=() provide_list=() after=() dead=() sorted=() sortedp=()
278
279 # Make our provide list
280 for ((i=0; i<nmods; i++)); do
281 dead[i]="false"
282 if [[ ${MODULES[i]} != "${PROVIDES[i]}" ]] ; then
283 local provided=false
284 for ((j=0; j<${#provide[@]}; j++)); do
285 if [[ ${provide[j]} == "${PROVIDES[i]}" ]]; then
286 provide_list[j]="${provide_list[j]} ${MODULES[i]}"
287 provided=true
288 fi
289 done
290 if ! ${provided}; then
291 provide[j]="${PROVIDES[i]}"
292 provide_list[j]="${MODULES[i]}"
293 fi
294 fi
295 done
296
297 # Create an after array, which holds which modules the module at
298 # index i must be after
299 for ((i=0; i<nmods; i++)); do
300 if is_function "${MODULES[i]}_after" ; then
301 after[i]=" ${after[i]} $(${MODULES[i]}_after) "
302 fi
303 if is_function "${MODULES[i]}_before" ; then
304 for m in $(${MODULES[i]}_before); do
305 for ((j=0; j<nmods; j++)) ; do
306 if [[ ${PROVIDES[j]} == "${m}" ]]; then
307 after[j]=" ${after[j]} ${MODULES[i]} "
308 break
309 fi
310 done
311 done
312 fi
313 done
314
315 # Replace the after list modules with real modules
316 for ((i=0; i<nmods; i++)); do
317 if [[ -n ${after[i]} ]]; then
318 for ((j=0; j<${#provide[@]}; j++)); do
319 after[i]="${after[i]// ${provide[j]} / ${provide_list[j]} }"
320 done
321 fi
322 done
323
324 # We then use the below code to provide a topologial sort
325 module_after_visit() {
326 local name=$1 i x
327
328 for ((i=0; i<nmods; i++)); do
329 [[ ${MODULES[i]} == "$1" ]] && break
330 done
331
332 ${dead[i]} && return
333 dead[i]="true"
334
335 for x in ${after[i]} ; do
336 module_after_visit "${x}"
337 done
338
339 sorted=( "${sorted[@]}" "${MODULES[i]}" )
340 sortedp=( "${sortedp[@]}" "${PROVIDES[i]}" )
341 }
342
343 for x in ${MODULES[@]}; do
344 module_after_visit "${x}"
345 done
346
347 MODULES=( "${sorted[@]}" )
348 PROVIDES=( "${sortedp[@]}" )
349 }
350
351 # bool modules_check_depends(bool showprovides)
352 modules_check_depends() {
353 local showprovides="${1:-false}" nmods="${#MODULES[@]}" i j needmod
354 local missingdeps p interface=false
355
356 for (( i=0; i<nmods; i++ )); do
357 if is_function "${MODULES[i]}_need" ; then
358 for needmod in $( ${MODULES[i]}_need ); do
359 missingdeps=true
360 for (( j=0; j<nmods; j++ )); do
361 if [[ ${needmod} == "${MODULES[j]}" \
362 || ${needmod} == "${PROVIDES[j]}" ]]; then
363 missingdeps=false
364 break
365 fi
366 done
367 if ${missingdeps} ; then
368 eerror "${MODULES[i]} needs ${needmod} (dependency failure)"
369 return 1
370 fi
371 done
372 fi
373
374 if is_function "${MODULES[i]}_functions" ; then
375 for f in $( ${MODULES[i]}_functions ); do
376 if ! is_function "${f}" ; then
377 eerror "${MODULES[i]}: missing required function \"${f}\""
378 return 1
379 fi
380 done
381 fi
382
383 [[ ${PROVIDES[i]} == "interface" ]] && interface=true
384
385 if ${showprovides} ; then
386 [[ ${PROVIDES[i]} != "${MODULES[i]}" ]] \
387 && veinfo "${MODULES[i]} provides ${PROVIDES[i]}"
388 fi
389 done
390
391 if ! ${interface} ; then
392 eerror "no interface module has been loaded"
393 return 1
394 fi
395
396 return 0
397 }
398
399 # bool modules_load(char *iface, bool starting)
400 #
401 # Loads the defined handler and modules for the interface
402 # Returns 0 on success, otherwise 1
403 modules_load() {
404 local iface="$1" starting="${2:-true}" MODULE p=false i j k
405 local -a x
406 local RC_INDENTATION="${RC_INDENTATION}"
407 local -a PROVIDES WRAP_MODULES
408
409 if [[ ${iface} != "lo" ]]; then
410 x="modules_force_${iface}[@]"
411 [[ -n ${!x} ]] && modules_force=( "${!x}" )
412 if [[ -n ${modules_force} ]]; then
413 ewarn "WARNING: You are forcing modules!"
414 ewarn "Do not complain or file bugs if things start breaking"
415 report=true
416 fi
417 fi
418
419 veinfo "Loading networking modules for ${iface}"
420 eindent
421
422 if [[ -z ${modules_force} ]]; then
423 modules_load_auto || return 1
424 else
425 j="${#modules_force[@]}"
426 for (( i=0; i<j; i++ )); do
427 module_load_minimum "${MODULES_DIR}/${modules_force[i]}" || return 1
428 if is_function "${modules_force[i]}_check_installed" ; then
429 ${modules_force[i]}_check_installed || unset modules_force[i]
430 fi
431 done
432 MODULES=( "${modules_force[@]}" )
433 fi
434
435 j="${#MODULES[@]}"
436 for (( i=0; i<j; i++ )); do
437 # Now load our dependencies - we need to use the MODULE variable
438 # here as the after/before/need functions use it
439 MODULE="${MODULES[i]}"
440 ${MODULE}_depend
441
442 # If no provide is given, assume module name
443 if is_function "${MODULES[i]}_provide" ; then
444 PROVIDES[i]=$( ${MODULES[i]}_provide )
445 else
446 PROVIDES[i]="${MODULES[i]}"
447 fi
448 done
449
450 if [[ -n ${modules_force[@]} ]]; then
451 # Strip any duplicate modules providing the same thing
452 j="${#MODULES[@]}"
453 for (( i=0; i<j-1; i++ )); do
454 [[ -z ${MODULES[i]} ]] && continue
455 for (( k=i+1; k<j; k++ )); do
456 if [[ ${PROVIDES[i]} == ${PROVIDES[k]} ]]; then
457 unset MODULES[k]
458 unset PROVIDES[k]
459 fi
460 done
461 done
462 MODULES=( "${MODULES[@]}" )
463 PROVIDES=( "${PROVIDES[@]}" )
464 else
465 if ${starting}; then
466 modules_check_user || return 1
467 else
468 # Always prefer iproute2 for taking down interfaces
469 if is_function iproute2_provide ; then
470 function_wrap iproute2 $(iproute2_provide)
471 fi
472 fi
473 fi
474
475 # Wrap our modules
476 j="${#MODULES[@]}"
477 for (( i=0; i<j; i++ )); do
478 function_wrap "${MODULES[i]}" "${PROVIDES[i]}"
479 done
480 j="${#WRAP_MODULES[@]}"
481 for (( i=0; i<j; i++ )); do
482 function_wrap ${WRAP_MODULES[i]}
483 done
484
485 if [[ -z ${modules_force[@]} ]]; then
486 modules_check_installed || return 1
487 modules_sort || return 1
488 fi
489
490 veinfo "modules: ${MODULES[@]}"
491 eindent
492
493 ${starting} && p=true
494 modules_check_depends "${p}" || return 1
495 return 0
496 }
497
498 # bool iface_start(char *interface)
499 #
500 # iface_start is called from start. It's expected to start the base
501 # interface (for example "eth0"), aliases (for example "eth0:1") and to start
502 # VLAN interfaces (for example eth0.0, eth0.1). VLAN setup is accomplished by
503 # calling itself recursively.
504 iface_start() {
505 local iface="$1" mod config_counter="-1" x config_worked=false
506 local RC_INDENTATION="${RC_INDENTATION}"
507 local -a config fallback fallback_route conf a b
508 local ifvar=$( bash_variable "$1" ) i j
509
510 # Try and work out a metric for the interface if we're on auto
511 x="metric_${ifvar}"
512 if [[ -z ${!x} ]]; then
513 if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then
514 eval "metric_${ifvar}=\""$( calculate_metric ${iface} )"\""
515 else
516 eval "metric_${ifvar}=0"
517 fi
518 fi
519
520 # pre Start any modules with
521 for mod in ${MODULES[@]}; do
522 if is_function "${mod}_pre_start" ; then
523 ${mod}_pre_start "${iface}" || { eend 1; return 1; }
524 fi
525 done
526
527 # We now expand the configuration parameters and pray that the
528 # fallbacks expand to the same number as config or there will be
529 # trouble!
530 a="config_${ifvar}[@]"
531 a=( "${!a}" )
532 for (( i=0; i<${#a[@]}; i++ )); do
533 eval b=( $( expand_parameters "${a[i]}" ) )
534 config=( "${config[@]}" "${b[@]}" )
535 done
536
537 a="fallback_${ifvar}[@]"
538 a=( "${!a}" )
539 for (( i=0; i<${#a[@]}; i++ )); do
540 eval b=( $( expand_parameters "${a[i]}" ) )
541 fallback=( "${fallback[@]}" "${b[@]}" )
542 done
543
544 # We don't expand routes
545 fallback_route="fallback_route_${ifvar}[@]"
546 fallback_route=( "${!fallback_route}" )
547
548 # We must support old configs
549 if [[ -z ${config} ]]; then
550 interface_get_old_config "${iface}" || return 1
551 if [[ -n ${config} ]]; then
552 ewarn "You are using a depreciated configuration syntax for ${iface}"
553 ewarn "You are advised to read /etc/conf.d/net.example and upgrade it accordingly"
554 fi
555 fi
556
557 # Handle "noop" correctly
558 if [[ ${config[0]} == "noop" ]]; then
559 if interface_is_up "${iface}" true ; then
560 einfo "Keeping current configuration for ${iface}"
561 eend 0
562 return 0
563 fi
564
565 # Remove noop from the config var
566 config=( "${config[@]:1}" )
567 fi
568
569 # Provide a default of DHCP if no configuration is set and we're auto
570 # Otherwise a default of NULL
571 if [[ -z ${config} ]]; then
572 # if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then
573 if is_function "dhcp_start" ; then
574 config=( "dhcp" )
575 ewarn "Configuration not set for ${iface} - assuming dhcp"
576 else
577 eerror "Cannot default to dhcp as there is no dhcp module loaded"
578 eerror "No configuration for ${iface}"
579 return 1
580 fi
581 # else
582 # config=( "null" )
583 # ewarn "Configuration not set for ${iface} - assuming null"
584 # fi
585 fi
586
587 einfo "Bringing up ${iface}"
588 eindent
589 for (( config_counter=0; config_counter<${#config[@]}; config_counter++ )); do
590 # Handle null and noop correctly
591 if [[ ${config[config_counter]} == "null" \
592 || ${config[config_counter]} == "noop" ]]; then
593 eend 0
594 config_worked=true
595 continue
596 fi
597
598 # We convert it to an array - this has the added
599 # bonus of trimming spaces!
600 conf=( ${config[config_counter]} )
601 einfo "${conf[0]}"
602
603 # Do we have a function for our config?
604 if is_function "${conf[0]}_start" ; then
605 eindent
606 ${conf[0]}_start "${iface}" ; x=$?
607 eoutdent
608 [[ ${x} == 0 ]] && config_worked=true && continue
609 # We need to test to see if it's an IP address or a function
610 # We do this by testing if the 1st character is a digit
611 elif [[ ${conf[0]:0:1} == [[:digit:]] || ${conf[0]} == *:* ]]; then
612 x="0"
613 if [[ ${RC_AUTO_INTERFACE} == "yes" ]] \
614 && is_function arping_address_exists ; then
615 if arping_address_exists "${iface}" "${conf[0]}" ; then
616 eerror "${conf[0]%%/*} already taken on ${iface}"
617 x="1"
618 fi
619 fi
620 [[ ${x} == "0" ]] && interface_add_address "${iface}" ${conf[@]}; x="$?"
621 eend "${x}" && config_worked=true && continue
622 else
623 eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
624 fi
625
626 if [[ -n ${fallback[config_counter]} ]]; then
627 einfo "Trying fallback configuration"
628 config[config_counter]="${fallback[config_counter]}"
629 fallback[config_counter]=""
630
631 # Do we have a fallback route?
632 if [[ -n ${fallback_route[config_counter]} ]]; then
633 x="fallback_route[config_counter]"
634 eval "routes_${ifvar}=( \"\${!x}\" )"
635 fallback_route[config_counter]=""
636 fi
637
638 (( config_counter-- )) # since the loop will increment it
639 continue
640 fi
641 done
642 eoutdent
643
644 # We return failure if no configuration parameters worked
645 ${config_worked} || return 1
646
647 # Start any modules with _post_start
648 for mod in ${MODULES[@]}; do
649 if is_function "${mod}_post_start" ; then
650 ${mod}_post_start "${iface}" || return 1
651 fi
652 done
653
654 return 0
655 }
656
657 # bool iface_stop(char *interface)
658 #
659 # iface_stop: bring down an interface. Don't trust information in
660 # /etc/conf.d/net since the configuration might have changed since
661 # iface_start ran. Instead query for current configuration and bring
662 # down the interface.
663 iface_stop() {
664 local iface="$1" i aliases need_begin=false mod
665 local RC_INDENTATION="${RC_INDENTATION}"
666
667 # pre Stop any modules
668 for mod in ${MODULES[@]}; do
669 is_function "${mod}_pre_stop" && ${mod}_pre_stop "${iface}"
670 done
671
672 einfo "Bringing down ${iface}"
673 eindent
674
675 # Collect list of aliases for this interface.
676 # List will be in reverse order.
677 if interface_exists "${iface}" ; then
678 aliases=$( interface_get_aliases_rev "${iface}" )
679 fi
680
681 # Stop aliases before primary interface.
682 # Note this must be done in reverse order, since ifconfig eth0:1
683 # will remove eth0:2, etc. It might be sufficient to simply remove
684 # the base interface but we're being safe here.
685 for i in ${aliases} ${iface}; do
686 # Stop all our modules
687 for mod in ${MODULES[@]}; do
688 is_function "${mod}_stop" && ${mod}_stop "${i}"
689 done
690
691 # A module may have removed the interface
692 if ! interface_exists "${iface}" ; then
693 eend 0
694 continue
695 fi
696
697 # Delete all the addresses for this alias
698 interface_del_addresses "${i}"
699
700 # Do final shut down of this alias
701 if [[ ${IN_BACKGROUND} != "true" \
702 && ${RC_DOWN_INTERFACE} == "yes" ]]; then
703 ebegin "Shutting down ${i}"
704 interface_iface_stop "${i}"
705 eend "$?"
706 fi
707 done
708
709 # post Stop any modules
710 for mod in ${MODULES[@]}; do
711 # We have already taken down the interface, so no need to error
712 is_function "${mod}_post_stop" && ${mod}_post_stop "${iface}"
713 done
714
715 return 0
716 }
717
718 # bool run_start(char *iface)
719 #
720 # Brings up ${IFACE}. Calls preup, iface_start, then postup.
721 # Returns 0 (success) unless preup or iface_start returns 1 (failure).
722 # Ignores the return value from postup.
723 # We cannot check that the device exists ourselves as modules like
724 # tuntap make create it.
725 run_start() {
726 local iface="$1" IFVAR=$( bash_variable "$1" )
727
728 # We do this so users can specify additional addresses for lo if they
729 # need too - additional routes too
730 # However, no extra modules are loaded as they are just not needed
731 if [[ ${iface} == "lo" ]]; then
732 metric_lo="0"
733 config_lo=( "127.0.0.1/8 brd 127.255.255.255" "${config_lo[@]}" )
734 routes_lo=( "127.0.0.0/8" "${routes_lo[@]}" )
735 fi
736
737 # We may not have a loaded module for ${iface}
738 # Some users may have "alias natsemi eth0" in /etc/modules.d/foo
739 # so we can work with this
740 # However, if they do the same with eth1 and try to start it
741 # but eth0 has not been loaded then the module gets loaded as
742 # eth0.
743 # Not much we can do about this :(
744 # Also, we cannot error here as some modules - such as bridge
745 # create interfaces
746 if ! interface_exists "${iface}" ; then
747 /sbin/modprobe "${iface}" &>/dev/null
748 fi
749
750 # Call user-defined preup function if it exists
751 if is_function preup ; then
752 einfo "Running preup function"
753 eindent
754 ( preup "${iface}" )
755 eend "$?" "preup ${iface} failed" || return 1
756 eoutdent
757 fi
758
759 # If config is set to noop and the interface is up with an address
760 # then we don't start it
761 local config
762 config="config_${IFVAR}[@]"
763 config=( "${!config}" )
764 if [[ ${config[0]} == "noop" ]] && interface_is_up "${iface}" true ; then
765 einfo "Keeping current configuration for ${iface}"
766 eend 0
767 else
768 # Remove noop from the config var
769 [[ ${config[0]} == "noop" ]] \
770 && eval "config_${IFVAR}=( "\"\$\{config\[@\]:1\}\"" )"
771
772 # There may be existing ip address info - so we strip it
773 if [[ ${RC_INTERFACE_KEEP_CONFIG} != "yes" \
774 && ${IN_BACKGROUND} != "true" ]]; then
775 interface_del_addresses "${iface}"
776 fi
777
778 # Start the interface
779 if ! iface_start "${iface}" ; then
780 if [[ ${IN_BACKGROUND} != "true" ]]; then
781 interface_exists "${iface}" && interface_down "${iface}"
782 fi
783 eend 1
784 return 1
785 fi
786 fi
787
788 # Call user-defined postup function if it exists
789 if is_function postup ; then
790 # We need to mark the service as started incase a
791 # postdown function wants to restart services that depend on us
792 mark_service_started "net.${iface}"
793 einfo "Running postup function"
794 eindent
795 ( postup "${iface}" )
796 eoutdent
797 fi
798
799 return 0
800 }
801
802 # bool run_stop(char *iface) {
803 #
804 # Brings down ${iface}. If predown call returns non-zero, then
805 # stop returns non-zero to indicate failure bringing down device.
806 # In all other cases stop returns 0 to indicate success.
807 run_stop() {
808 local iface="$1" IFVAR=$( bash_variable "$1" ) x
809
810 # Load our ESSID variable so users can use it in predown() instead
811 # of having to write code.
812 local ESSID=$( get_options "ESSID" ) ESSIDVAR
813 [[ -n ${ESSID} ]] && ESSIDVAR=$( bash_variable "${ESSID}" )
814
815 # Call user-defined predown function if it exists
816 if is_function predown ; then
817 einfo "Running predown function"
818 eindent
819 ( predown "${iface}" )
820 eend $? "predown ${iface} failed" || return 1
821 eoutdent
822 elif is_net_fs /; then
823 eerror "root filesystem is network mounted -- can't stop ${iface}"
824 return 1
825 fi
826
827 iface_stop "${iface}" || return 1 # always succeeds, btw
828
829 # Mark us as inactive if called from the background
830 [[ ${IN_BACKGROUND} == "true" ]] && mark_service_inactive "net.${iface}"
831
832 # Call user-defined postdown function if it exists
833 if is_function postdown ; then
834 # We need to mark the service as stopped incase a
835 # postdown function wants to restart services that depend on us
836 [[ ${IN_BACKGROUND} != "true" ]] && mark_service_stopped "net.${iface}"
837 einfo "Running postdown function"
838 eindent
839 ( postdown "${iface}" )
840 eoutdent
841 fi
842
843 return 0
844 }
845
846 # bool run(char *iface, char *cmd)
847 #
848 # Main start/stop entry point
849 # We load modules here and remove any functions that they
850 # added as we may be called inside the same shell scope for another interface
851 run() {
852 local iface="$1" cmd="$2" r=1 RC_INDENTATION="${RC_INDENTATION}"
853 local starting=true
854 local -a MODULES mods
855 local IN_BACKGROUND="${IN_BACKGROUND}"
856
857 # No point in backgrounding if we're already there ...
858 # This is also required so we can select the "best" interface
859 if [[ ${IN_BACKGROUND} == "true" || ${IN_BACKGROUND} == "1" ]]; then
860 IN_BACKGROUND=true
861 background=false
862 else
863 IN_BACKGROUND=false
864 fi
865
866 # We need to override the exit function as runscript.sh now checks
867 # for it. We need it so we can mark the service as inactive ourselves.
868 unset -f exit
869
870 eindent
871 [[ ${cmd} == "stop" ]] && starting=false
872
873 # We force lo to only use these modules for a major speed boost
874 [[ ${iface} == "lo" ]] && modules_force=( "iproute2" "ifconfig" "system" )
875
876 if modules_load "${iface}" "${starting}" ; then
877 if [[ ${cmd} == "stop" ]]; then
878 # Reverse the module list for stopping
879 mods=( "${MODULES[@]}" )
880 for ((i = 0; i < ${#mods[@]}; i++)); do
881 MODULES[i]=${mods[((${#mods[@]} - i - 1))]}
882 done
883
884 run_stop "${iface}" && r=0
885 remove_state "${iface}"
886 else
887 run_start "${iface}" && r=0
888 fi
889 fi
890
891 # Only apply best state if we're on auto
892 if [[ ${r} == "0" ]]; then
893 local siface=""
894 if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then
895 siface=$( select_best_interface )
896 if [[ -n ${siface} ]]; then
897 einfo "Selecting best interface: ${siface}"
898 fi
899 elif [[ ${cmd} == "start" ]]; then
900 siface="${iface}"
901 fi
902 [[ -n ${siface} ]] && apply_state "${siface}"
903 else
904 if [[ ${cmd} == "start" ]]; then
905 # Call user-defined failup if it exists
906 if is_function failup ; then
907 einfo "Running failup function"
908 eindent
909 ( failup "${iface}" )
910 eoutdent
911 fi
912 else
913 # Call user-defined faildown if it exists
914 if is_function faildown ; then
915 einfo "Running faildown function"
916 eindent
917 ( faildown "${iface}" )
918 eoutdent
919 fi
920 fi
921 [[ ${IN_BACKGROUND} == "true" ]] \
922 && mark_service_inactive "net.${iface}"
923 fi
924
925 return "${r}"
926 }
927
928 # void link_file(char *file)
929 #
930 # Move a config file from /etc to ${netdir} and creates a link if needed.
931 # This enables net-scripts to control the config file for interface management
932 # and allow /etc to become read only.
933 link_file() {
934 local file="$1"
935 local link=$( readlink "/etc/${file}" 2>/dev/null )
936 if [[ ${link} != "${netdir}/${file}" ]]; then
937 if [[ -f "/etc/${file}" ]]; then
938 vewarn "Moving /etc/${file} to ${netdir}/${file} and creating link"
939 mv "/etc/${file}" "${netdir}"
940 ln -snf "${netdir}/${file}" "/etc/${file}"
941 fi
942 fi
943 }
944
945 # bool start(void)
946 #
947 # Start entry point so that we only have one function
948 # which localises variables and unsets functions
949 start() {
950 if [[ ${IN_HOTPLUG} == "1" ]]; then
951 # If we've been called by hotplug, check if we have
952 # a policy for the interface for not starting
953 local x ifvar=$( bash_variable "${IFACE}" )
954 x="hotplug_${ifvar}"
955 if [[ ${!x} == "no" || ${!x} == "false" ]]; then
956 eerror "Not starting interface ${IFACE} due to hotplug policy"
957 unset -f exit
958 mark_service_stopped "net.${IFACE}"
959 exit 1
960 fi
961 fi
962
963 if [[ ! -d "${statedir}/${IFACE}" ]]; then
964 if ! mkdir -m 0755 -p "${statedir}/${IFACE}" ; then
965 eerror "Unable to create state directory!"
966 return 1
967 fi
968 fi
969
970 if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then
971 link_file "resolv.conf"
972 link_file "ntp.conf"
973 link_file "yp.conf"
974 fi
975
976 einfo "Starting ${IFACE}"
977 run "${IFACE}" start
978 }
979
980 # bool stop(void)
981 #
982 # Stop entry point so that we only have one function
983 # which localises variables and unsets functions
984 stop() {
985 einfo "Stopping ${IFACE}"
986 run "${IFACE}" stop
987 }
988
989 # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20