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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20