/[baselayout]/trunk/net-scripts/init.d/net.lo
Gentoo

Contents of /trunk/net-scripts/init.d/net.lo

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2050 - (show annotations) (download)
Fri Jun 2 20:02:40 2006 UTC (8 years, 1 month ago) by uberlord
File size: 30003 byte(s)
    Allow LC_* and LANG vars through to runscript.sh by default.

    net.lo now comes after bootmisc, #135118 thanks to Oldrich Jedlicka.

    arping.sh now has MAC address support, #134253 thanks to Oldrich Jedlicka.

    pppd.sh now updates secret files with a blank password, #134337

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