/[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 414 - (hide annotations) (download)
Wed Aug 16 08:23:44 2006 UTC (7 years, 10 months ago) by hollow
File size: 30045 byte(s)
merge r2190
1 phreak 137 #!/sbin/runscript
2 phreak 183 # Copyright (c) 2004-2006 Gentoo Foundation
3 phreak 137 # 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 phreak 372 after bootmisc hostname
16 phreak 234 use isapnp isdn pcmcia usb wlan
17 phreak 137
18     # Load any custom depend functions for the given interface
19     # For example, br0 may need eth0 and eth1
20 phreak 276 local iface="${SVCNAME#*.}"
21 phreak 137 [[ $(type -t "depend_${iface}") == "function" ]] && depend_${iface}
22 phreak 341 [[ ${iface} != "lo" && ${iface} != "lo0" ]] && after net.lo net.lo0
23 phreak 137
24     return 0
25     }
26    
27     # Define where our modules are
28 phreak 341 MODULES_DIR="${svclib}/net"
29 phreak 137
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 phreak 313 is_loopback() {
57 phreak 341 [[ $1 == "lo" || $1 == "lo0" ]]
58 phreak 313 }
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 phreak 315 # int calculate_metric(char *interface, int base)
80 phreak 313 #
81     # Calculates the best metric for the interface
82 phreak 315 # We use this when we add routes so we can prefer interfaces over each other
83 phreak 313 calculate_metric() {
84 phreak 315 local iface="$1" metric="$2"
85 phreak 313
86     # Have we already got a metric?
87 hollow 384 local m=$(awk '$1=="'${iface}'" && $2=="00000000" { print $7 }' \
88     /proc/net/route)
89 phreak 313 if [[ -n ${m} ]] ; then
90     echo "${m}"
91     return 0
92     fi
93    
94 phreak 315 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 phreak 313
103 phreak 315 # Now, sort our metrics
104 hollow 384 metrics=$(echo -e "${metrics}" | sort -n)
105 phreak 313
106 phreak 315 # 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 phreak 313 done
113 phreak 315
114     echo "${metric}"
115 phreak 313 }
116    
117     # int netmask2cidr(char *netmask)
118     #
119     # Returns the CIDR of a given netmask
120     netmask2cidr() {
121 hollow 384 local binary= i= bin=
122 phreak 313
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 hollow 384 local i=
150 phreak 313
151     is_function "${2}_depend" && return
152    
153 hollow 384 for i in $(typeset -f | grep -o '^'"${1}"'_[^ ]*'); do
154 phreak 313 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 hollow 384 local x=$(eval echo ${@// /_})
174 phreak 313 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 hollow 384 local mod= func= x= i=
189     local -a ivars=() ovars1=() ovars2=()
190     local ifvar=$(bash_variable "${iface}")
191 phreak 313
192     for mod in ${MODULES[@]}; do
193     is_function ${mod}_variables || continue
194     for v in $(${mod}_variables) ; do
195 hollow 384 x=
196 phreak 313 [[ -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 phreak 137 # bool module_load_minimum(char *module)
205     #
206     # Does the minimum checking on a module - even when forcing
207     module_load_minimum() {
208 phreak 313 local f="$1.sh" MODULE="${1##*/}"
209 phreak 137
210 phreak 234 if [[ ! -f ${f} ]] ; then
211 phreak 137 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 phreak 313 eerror "${MODULE}.sh does not support the required function ${f}"
223 phreak 137 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 phreak 313 MODULES=( $( cd "${MODULES_DIR}" ; ls *.sh ) )
239 phreak 137 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 phreak 313 MODULES[i]="${MODULES[i]%.sh*}"
254 phreak 234 if [[ ${MODULES[i]##*/} == "interface" ]] ; then
255 phreak 137 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 phreak 234 if [[ ${u} == 0 ]] ; then
263 phreak 137 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 phreak 234 if [[ $? == 0 ]] ; then
272 phreak 313 source "${MODULES[i]}.sh"
273 phreak 137 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 hollow 384 local iface="$1" ifvar=$(bash_variable "${IFACE}")
315     local i= j= k= l= nmods="${#MODULES[@]}"
316     local -a umods=()
317 phreak 137
318     # Has the interface got any specific modules?
319 phreak 210 umods="modules_${ifvar}[@]"
320 phreak 137 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 phreak 234 if [[ ${umods[i]} == "!"* ]] ; then
340 phreak 137 for (( j=0; j<nmods; j++ )); do
341     [[ -z ${MODULES[j]} ]] && continue
342     if [[ ${umods[i]:1} == "${MODULES[j]}" \
343 phreak 234 || ${umods[i]:1} == "${PROVIDES[j]}" ]] ; then
344 phreak 137 # 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 phreak 313 if [[ -e "${MODULES_DIR}/${umods[i]}.sh" ]] ; then
369     source "${MODULES_DIR}/${umods[i]}.sh"
370 phreak 137 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 hollow 384 mod=$(${umods[i]}_provide)
380 phreak 137 else
381     mod="${umods[i]}"
382     fi
383     for (( j=0; j<nmods; j++ )); do
384     [[ -z ${MODULES[j]} ]] && continue
385 phreak 234 if [[ ${PROVIDES[j]} == "${mod}" && ${umods[i]} != "${MODULES[j]}" ]] ; then
386 phreak 137 # 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 phreak 234 if [[ ${PROVIDES[l]} == "${mod}" ]] ; then
391 phreak 137 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 hollow 384 local i= j= nmods=${#MODULES[@]} m=
423 phreak 137 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 phreak 234 if [[ ${provide[j]} == "${PROVIDES[i]}" ]] ; then
432 phreak 137 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 phreak 234 if [[ ${PROVIDES[j]} == "${m}" ]] ; then
453 phreak 137 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 phreak 234 if [[ -n ${after[i]} ]] ; then
464 phreak 137 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 hollow 384 local name="$1" i= x=
473 phreak 137
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 hollow 384 local showprovides="${1:-false}" nmods="${#MODULES[@]}" i= j= needmod=
500     local missingdeps= p= interface=false
501 phreak 137
502     for (( i=0; i<nmods; i++ )); do
503     if is_function "${MODULES[i]}_need" ; then
504 hollow 384 for needmod in $(${MODULES[i]}_need); do
505 phreak 137 missingdeps=true
506     for (( j=0; j<nmods; j++ )); do
507     if [[ ${needmod} == "${MODULES[j]}" \
508 phreak 234 || ${needmod} == "${PROVIDES[j]}" ]] ; then
509 phreak 137 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 hollow 384 for f in $(${MODULES[i]}_functions); do
522 phreak 137 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 hollow 384 local iface="$1" starting="${2:-true}" MODULE= p=false i= j= k=
551     local -a x=()
552 phreak 137 local RC_INDENTATION="${RC_INDENTATION}"
553 hollow 384 local -a PROVIDES=() WRAP_MODULES=()
554 phreak 137
555 phreak 313 if ! is_loopback "${iface}" ; then
556 phreak 137 x="modules_force_${iface}[@]"
557     [[ -n ${!x} ]] && modules_force=( "${!x}" )
558 phreak 234 if [[ -n ${modules_force} ]] ; then
559 phreak 137 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 phreak 234 if [[ -z ${modules_force} ]] ; then
569 phreak 137 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 phreak 278 # 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 phreak 137 # If no provide is given, assume module name
594     if is_function "${MODULES[i]}_provide" ; then
595 hollow 384 PROVIDES[i]=$(${MODULES[i]}_provide)
596 phreak 137 else
597     PROVIDES[i]="${MODULES[i]}"
598     fi
599     done
600    
601 phreak 234 if [[ -n ${modules_force[@]} ]] ; then
602 phreak 137 # 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 phreak 234 if [[ ${PROVIDES[i]} == ${PROVIDES[k]} ]] ; then
608 phreak 137 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 phreak 210 modules_check_user "${iface}" || return 1
618 phreak 137 else
619     # Always prefer iproute2 for taking down interfaces
620     if is_function iproute2_provide ; then
621 phreak 234 function_wrap iproute2 "$(iproute2_provide)"
622 phreak 137 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 phreak 234 if [[ -z ${modules_force[@]} ]] ; then
637 phreak 137 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 hollow 384 local -a config=() fallback=() fallback_route=() conf=() a=() b=()
659     local ifvar=$(bash_variable "$1") i= j= metric=0
660 phreak 137
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 phreak 315 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 phreak 137 # 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 phreak 234 eval b=( $(expand_parameters "${a[i]}") )
683 phreak 137 config=( "${config[@]}" "${b[@]}" )
684     done
685    
686     a="fallback_${ifvar}[@]"
687     a=( "${!a}" )
688     for (( i=0; i<${#a[@]}; i++ )); do
689 phreak 234 eval b=( $(expand_parameters "${a[i]}") )
690 phreak 137 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 phreak 234 if [[ -z ${config} ]] ; then
699 phreak 137 interface_get_old_config "${iface}" || return 1
700 phreak 234 if [[ -n ${config} ]] ; then
701 hollow 414 ewarn "You are using a deprecated configuration syntax for ${iface}"
702 phreak 137 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 phreak 234 if [[ ${config[0]} == "noop" ]] ; then
708 phreak 137 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 phreak 234 if [[ -z ${config} ]] ; then
721 phreak 313 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 phreak 137 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 phreak 234 || ${config[config_counter]} == "noop" ]] ; then
736 phreak 137 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 phreak 234 elif [[ ${conf[0]:0:1} == [[:digit:]] || ${conf[0]} == *:* ]] ; then
755 phreak 137 x="0"
756 phreak 313 if ! is_loopback "${iface}" ; then
757 hollow 414 if [[ " ${MODULES[@]} " == *" arping "* ]] ; then
758 phreak 313 if arping_address_exists "${iface}" "${conf[0]}" ; then
759     eerror "${conf[0]%%/*} already taken on ${iface}"
760     x="1"
761     fi
762 phreak 137 fi
763     fi
764     [[ ${x} == "0" ]] && interface_add_address "${iface}" ${conf[@]}; x="$?"
765     eend "${x}" && config_worked=true && continue
766     else
767 phreak 211 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 phreak 137 fi
773    
774 phreak 234 if [[ -n ${fallback[config_counter]} ]] ; then
775 phreak 137 einfo "Trying fallback configuration"
776     config[config_counter]="${fallback[config_counter]}"
777     fallback[config_counter]=""
778    
779     # Do we have a fallback route?
780 phreak 234 if [[ -n ${fallback_route[config_counter]} ]] ; then
781 phreak 137 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 hollow 384 local iface="$1" i= aliases= need_begin=false mod=
813 phreak 137 local RC_INDENTATION="${RC_INDENTATION}"
814    
815     # pre Stop any modules
816     for mod in ${MODULES[@]}; do
817 phreak 313 if is_function "${mod}_pre_stop" ; then
818     ${mod}_pre_stop "${iface}" || return 1
819     fi
820 phreak 137 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 hollow 384 aliases=$(interface_get_aliases_rev "${iface}")
829 phreak 137 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 phreak 313 if is_function "${mod}_stop" ; then
839     ${mod}_stop "${i}" || return 1
840     fi
841 phreak 137 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 phreak 175 if [[ ${IN_BACKGROUND} != "true" \
854 phreak 234 && ${RC_DOWN_INTERFACE} == "yes" ]] ; then
855 phreak 137 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 hollow 384 local iface="$1" IFVAR=$(bash_variable "$1")
879 phreak 137
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 phreak 234 if [[ ${iface} == "lo" ]] ; then
884 phreak 137 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 phreak 313 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 phreak 137 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 hollow 384 local config=
918 phreak 137 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 phreak 183 if [[ ${RC_INTERFACE_KEEP_CONFIG} != "yes" \
930 phreak 234 && ${IN_BACKGROUND} != "true" ]] ; then
931 phreak 183 interface_del_addresses "${iface}"
932     fi
933 phreak 137
934     # Start the interface
935     if ! iface_start "${iface}" ; then
936 phreak 234 if [[ ${IN_BACKGROUND} != "true" ]] ; then
937 phreak 175 interface_exists "${iface}" && interface_down "${iface}"
938     fi
939 phreak 137 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 phreak 206 # 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 phreak 290 end_service "net.${iface}" 0
950 phreak 137 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 hollow 384 local iface="$1" IFVAR=$(bash_variable "$1") x
966 phreak 137
967     # Load our ESSID variable so users can use it in predown() instead
968     # of having to write code.
969 hollow 384 local ESSID=$(get_options ESSID) ESSIDVAR=
970     [[ -n ${ESSID} ]] && ESSIDVAR=$(bash_variable "${ESSID}")
971 phreak 137
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 phreak 365 elif is_net_fs / ; then
980 phreak 137 eerror "root filesystem is network mounted -- can't stop ${iface}"
981     return 1
982 phreak 365 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 phreak 137 fi
991    
992     iface_stop "${iface}" || return 1 # always succeeds, btw
993    
994 phreak 313 # Release resolv.conf information.
995     [[ -x /sbin/resolvconf ]] && resolvconf -d "${iface}"
996    
997 phreak 206 # Mark us as inactive if called from the background
998     [[ ${IN_BACKGROUND} == "true" ]] && mark_service_inactive "net.${iface}"
999    
1000 phreak 137 # Call user-defined postdown function if it exists
1001     if is_function postdown ; then
1002 phreak 206 # 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 phreak 290 end_service "net.${iface}" 0
1006 phreak 137 einfo "Running postdown function"
1007     eindent
1008     ( postdown "${iface}" )
1009     eoutdent
1010     fi
1011    
1012 phreak 313
1013 phreak 137 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 hollow 384 local -a MODULES=() mods=()
1025 phreak 137 local IN_BACKGROUND="${IN_BACKGROUND}"
1026    
1027 phreak 234 if [[ ${IN_BACKGROUND} == "true" || ${IN_BACKGROUND} == "1" ]] ; then
1028 phreak 137 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 phreak 313 if is_loopback "${iface}" ; then
1042     modules_force=( "iproute2" "ifconfig" "system" )
1043     fi
1044 phreak 137
1045     if modules_load "${iface}" "${starting}" ; then
1046 phreak 234 if [[ ${cmd} == "stop" ]] ; then
1047 phreak 137 # 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 phreak 211 # 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 phreak 137 run_start "${iface}" && r=0
1064     fi
1065     fi
1066    
1067 phreak 313 if [[ ${r} != "0" ]] ; then
1068 phreak 234 if [[ ${cmd} == "start" ]] ; then
1069 phreak 137 # 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 phreak 175 [[ ${IN_BACKGROUND} == "true" ]] \
1086     && mark_service_inactive "net.${iface}"
1087 phreak 137 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 phreak 276 declare -r IFACE="${SVCNAME#*.}"
1098 phreak 137 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 phreak 276 declare -r IFACE="${SVCNAME#*.}"
1108 phreak 137 einfo "Stopping ${IFACE}"
1109     run "${IFACE}" stop
1110     }
1111    
1112     # vim:ts=4

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.20