/[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 607 - (show annotations) (download)
Wed Oct 13 18:39:18 2004 UTC (14 years, 8 months ago) by agriffis
File size: 16387 byte(s)
Cosmetic fixes for starting loopback interface

1 #!/sbin/runscript
2 # net-scripts main code
3 # Version 1.0.1
4 # Copyright (c) 2004 Gentoo Foundation
5 # Distributed under the terms of the GNU General Public License V2
6 # Contributed by Roy "UberLord" Marples (uberlord@rsm.demon.co.uk)
7 # Many thanks to Aron Griffis (agriffis@gentoo.org)
8 # for help, ideas and patches
9
10 #NB: Config is in /etc/conf.d/net
11
12 if [[ -n $NET_DEBUG ]]; then
13 set -x
14 devnull=/dev/stderr
15 else
16 devnull=/dev/null
17 fi
18
19 # For pcmcia users. note that pcmcia must be added to the same
20 # runlevel as the net.* script that needs it.
21 depend() {
22 use coldplug hotplug pcmcia usb bridge
23 }
24
25 # Make some wrappers to fudge after/before/need/use depend flags.
26 # These are callbacks so mods[i] will be set.
27 after() {
28 local x="$*"
29 [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
30 eval "${mods[i]}_after() { echo \"$x\"; }"
31 }
32 before() {
33 local x="$*"
34 [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
35 eval "${mods[i]}_before() { echo \"$x\"; }"
36 }
37 need() {
38 local x="$*"
39 [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
40 eval "${mods[i]}_need() { echo \"$x\"; }"
41 }
42 use() {
43 local x="$*"
44 [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
45 eval "${mods[i]}_use() { echo \"$x\"; }"
46 }
47
48 sort() {
49 LC_ALL=C /bin/sort "$@"
50 }
51
52 # bool modules_load(char *iface, bool all)
53 #
54 # Loads the defined handler and modules for the interface
55 # Returns 0 on success, otherwise 1
56 modules_load()
57 {
58 local iface=${1} all=${2:-false} i j k p e before after diffs mod
59 local loaded_interface changed_something tmp modnums missingdeps
60 local -a mods=( $( find /lib/rcscripts/net.modules.d/ -maxdepth 1 -type f | sort ) ) umods sort_history
61 local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
62
63 [[ ${iface} != lo ]] && einfo "Loading networking modules for ${iface}"
64 eindent
65
66 # Each of these sources into the global namespace, so it's
67 # important that module functions and variables are prefixed with
68 # the module name, for example iproute2_
69 before=$( typeset -f )
70 j=${#mods[@]}
71 loaded_interface=false
72 for (( i=0; i < j; i++ )); do
73 if ! source ${mods[i]} ; then
74 eerror "${mods[i]##*/} failed a sanity check - will not load"
75 unset mods[i]
76 continue
77 fi
78
79 mods[i]=${mods[i]##*/}
80 if [[ ${mods[i]} == interface ]]; then
81 eerror "interface is a reserved name - cannot load a module called interface"
82 return 1
83 fi
84
85 e=false
86 for p in check_installed provides check_depends depend; do
87 [[ $( type -t ${mods[i]}_${p} ) == function ]] && continue
88 eerror "${mods[i]} does not support the required function ${p}"
89 e=true
90 done
91 ${e} && return 1
92
93 # Wrap our before/after/need/use functions
94 ${mods[i]}_depend
95
96 # Double check that we've only *added* to the function list, not
97 # replaced. This is as much protection for devs as for users ;-)
98 after=$( typeset -f )
99
100 # Though diffutils is in the profiles, don't depend that it will exist.
101 # Here is an example of the output we're looking through.
102 #
103 # $ diff -U0 -p <(echo "$funcs") <(echo "$funcs2")
104 # --- /dev/fd/63 2004-10-12 17:51:10.342906704 -0400
105 # +++ /dev/fd/62 2004-10-12 17:51:10.346905655 -0400
106 # @@ -69,0 +70,4 @@ addpath ()
107 # +asdf ()
108 # +{
109 # + echo
110 # +}
111 # @@ -1160,4 +1163,0 @@ xvf ()
112 # -xzf ()
113 # -{
114 # - xf "$@"
115 # -}
116 # @@ -1166 +1166,2 @@ xzvf ()
117 # - xvf "$@"
118 # + xvf "$@";
119 # + echo whoah
120 #
121 diffs=$( diff -U0 -p <(echo "${before}") <(echo "${after}") 2>/dev/null | \
122 awk 'BEGIN { ORS = " "; } # no need for xargs
123 /^@@ / { f = $(NF-1); } # collect function names reported by diff
124 /^-/ && $2 == "()" { f = substr($1, 2); } # override when functions are removed
125 /^+/ && $2 == "()" { f = ""; } # ignore when functions are added
126 /^-/ && f { print f; f = ""; } # report only once per function
127 ' )
128 if [[ -n ${diffs} ]]; then
129 eerror "${mods[i]} modified functions: ${diffs}"
130 return 1
131 fi
132 before="${after}"
133
134 if ! ${mods[i]}_check_installed; then
135 unset mods[i]
136 continue
137 fi
138
139 [[ -n ${mods[i]} && $( ${mods[i]}_provides ) == interface ]] && loaded_interface=true
140 done
141
142 if ! ${loaded_interface}; then
143 eerror "no interface module has been loaded"
144 return 1
145 fi
146
147 mods=( "${mods[@]}" )
148
149 if ! ${all}; then
150 # Has the interface got any specific modules?
151 eval umods=( \"\$\{modules_${iface}\[@\]\}\" )
152
153 # If not then has a global setting been made?
154 [[ -z ${umods} ]] && umods=( "${modules[@]}" )
155
156 # We add our preferred modules here
157 umods=( "${umods[@]}" "ifconfig" "dhcpcd" )
158
159 # First we strip any modules that conflict from user settings
160 # So if the user specifies pump then we don't use dhcpcd
161 for ((i=0; i < ${#umods[@]}; i++)); do
162 if [[ $( type -t ${umods[i]}_provides ) != function ]]; then
163 eerror "${umods[i]} is not a valid module (missing provides)"
164 return 1
165 fi
166
167 # Ensure that the user specified module has it's package installed.
168 # This is ${#umods[@]}-2 because we added two modules,
169 # ifconfig and dhcpcd, to the end of the list.
170 if [[ ${i} -lt ${#umods[@]}-2 ]]; then
171 ${umods[i]}_check_installed true || return 1
172 fi
173
174 k=${#mods[@]}
175 for (( j=0; j < k; j++ )); do
176 if [[ $( ${mods[j]}_provides ) == $( ${umods[i]}_provides ) && ${umods[i]} != ${mods[j]} ]]; then
177 # We don't have a match - now ensure that we still provide an alternative
178 # This is to handle our preferred modules
179 for (( e=0; e < k; e++ )); do
180 [[ ${e} -eq ${j} || -z ${mods[e]} ]] && continue
181 if [[ $( ${mods[e]}_provides ) == $( ${umods[i]}_provides ) ]]; then
182 unset mods[j]
183 break
184 fi
185 done
186 fi
187 done
188 mods=( "${mods[@]}" )
189 done
190
191 # Then we strip conflicting modules
192 # We only need todo this for 3rd party modules that conflict with
193 # our own modules and the preferred list AND the user modules
194 # list doesn't specify a preferrence
195 k=${#mods[@]}
196 for (( i=0; i < k-1; i++ )); do
197 [[ -z ${mods[i]} ]] && continue
198 for (( j=i+1; j < k; j++)); do
199 [[ -z ${mods[j]} ]] && continue
200 [[ $( ${mods[i]}_provides ) == $( ${mods[j]}_provides ) ]] && unset mods[j]
201 done
202 done
203 mods=( "${mods[@]}" )
204 fi
205
206 # Sort our modules
207 # We do this by assigning numbers to each module
208 modnums=()
209 for (( i=0; i < ${#mods[@]}; i++ )); do
210 modnums[i]=${i}
211 done
212
213 # Then we swap numbers based on and after/before flags
214 # until we don't swap anymore. The sort_history array prevents
215 # the possibility of an infinite loop
216 sort_history[0]="${modnums[*]}"
217 for (( k=1; 1; k++ )); do
218 changed_something=false
219 for (( i=0; i < ${#mods[@]}; i++ )); do
220 if [[ $( type -t ${mods[i]}_after ) == function ]]; then
221 for p in $( ${mods[i]}_after ); do
222 for (( j=0; j < ${#mods[@]}; j++ )); do
223 [[ ${p} != ${mods[j]} && ${p} != $( ${mods[j]}_provides ) ]] && continue
224 if [[ ${modnums[i]} -lt ${modnums[j]} ]]; then
225 tmp=${modnums[i]}
226 modnums[i]=${modnums[j]}
227 modnums[j]=${tmp}
228 changed_something=true
229 fi
230 done
231 done
232 fi
233 if [[ $( type -t ${mods[i]}_before ) == function ]]; then
234 for p in $( ${mods[i]}_before ); do
235 for (( j=0; j < ${#mods[@]}; j++ )); do
236 [[ ${p} != ${mods[j]} && ${p} != $( ${mods[j]}_provides ) ]] && continue
237 if [[ ${modnums[i]} -gt ${modnums[j]} ]]; then
238 tmp=${modnums[i]}
239 modnums[i]=${modnums[j]}
240 modnums[j]=${tmp}
241 changed_something=true
242 fi
243 done
244 done
245 fi
246 done
247 ${changed_something} || break
248
249 # Make sure we aren't repeating a previous state
250 # First time through, k=1, k/2=0
251 sort_history[k]="${modnums[*]}"
252 if [[ ${sort_history[k]} == ${sort_history[k/2]} ]]; then
253 eerror "Detected an infinite loop sorting modules; blundering ahead"
254 break
255 fi
256 done
257
258 # Finally we sort our modules in number order
259 um=""
260 for (( i=0; i < ${#mods[@]}; i++ )); do
261 um="${um}${modnums[i]} ${mods[i]}\n"
262 done
263 MODULES=( $( echo -e ${um} | sort -n | awk '{print $2}' ) )
264
265 [[ ${iface} != lo ]] && einfo "modules: ${MODULES[@]}"
266 eindent
267
268 # Setup class wrappers: interface_up -> iproute2_up, for example
269 for i in ${MODULES[@]}; do
270 p=$( ${i}_provides )
271 [[ ${p} == ${i} ]] && continue
272 for j in $( typeset -f | grep -o ^${i}_'[^ ]*' ); do
273 eval "${p}${j#${i}}() { ${j} \"\$@\"; }"
274 done
275 done
276
277 # Ensure that all modules have what they need
278 # from either other modules or the system
279 for i in ${MODULES[@]}; do
280 if [[ $( type -t ${i}_need ) == function ]]; then
281 for j in $( ${i}_need ); do
282 missingdeps=true
283 for k in ${MODULES[@]}; do
284 p=$( ${k}_provides )
285 if [[ ${j} == ${k} || ${j} == $( ${k}_provides ) ]]; then
286 missingdeps=false
287 break
288 fi
289 done
290 if ${missingdeps}; then
291 eerror "${i} needs ${j} (dependency failure)"
292 return 1
293 fi
294 done
295 fi
296 ${i}_check_depends || return 1
297 e=$( ${i}_provides )
298 if [[ ${all} != true && ${iface} != lo && ${e} != ${i} ]]; then
299 einfo "${i} provides ${e}"
300 fi
301 done
302 }
303
304 # char* get_device(char *iface)
305 #
306 # Gets the base device of the interface
307 # Can handle eth0:1 and eth0.1
308 # Which returns eth0 in this case
309 get_device() {
310 local iface=${1}
311 local dev=${iface%%.*}
312 [[ ${dev} == ${iface} ]] && dev=${iface%%:*}
313 echo ${dev}
314 }
315
316 # bool interface_exists(char *interface)
317 #
318 # Returns 0 if the interface exists, otherwise 0
319 interface_exists() {
320 grep "${1}:" /proc/net/dev &>/dev/null && return 0
321 return 1
322 }
323
324 # bool iface_start(char *interface)
325 #
326 # iface_start is called from start. It's expected to start the base
327 # interface (for example "eth0"), aliases (for example "eth0:1") and to start
328 # VLAN interfaces (for example eth0.0, eth0.1). VLAN setup is accomplished by
329 # calling itself recursively.
330 iface_start() {
331 local iface=${1} mod i label x conf warn=false
332 local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
333
334 # Localise and initialise variables
335 for mod in ${MODULES[@]}; do
336 x="${mod}_local_vars"
337 if [[ $( type -t ${x} ) == function ]]; then
338 x=$( ${x} )
339 ${x}
340 fi
341 x="${mod}_setup_vars"
342 if [[ $( type -t ${x} ) == function ]]; then
343 ${x} ${iface} || return 1
344 fi
345 done
346
347 # Provide a default of DHCP if no configuration is set
348 if [[ -z ${config_IFACE} ]]; then
349 if [[ $( type -t dhcp_start ) == function ]]; then
350 config_IFACE=( "dhcp" )
351 warn=true
352 else
353 eerror "Cannot default to dhcp as there is no dhcp module loaded"
354 eerror "No configuration for ${iface}"
355 return 1
356 fi
357 fi
358
359 einfo "Bringing up ${iface}"
360 eindent
361 for (( i=0; i < ${#config_IFACE[@]}; i++ )); do
362 # Set a label for the alias if $i > 0
363 [[ ${i} -eq 0 ]] && label=${iface} || label=${iface}:${i}
364
365 ${warn} && ewarn "Configuration not set for ${iface} - assuming dhcp"
366
367 # We convert it to an array - this has the added
368 # bonus of trimming spaces!
369 conf=( ${config_IFACE[i]} )
370 einfo "${label} ${conf[0]}"
371
372 # Do we have a function for our config?
373 if [[ $( type -t ${conf[0]}_start ) == function ]]; then
374 eindent
375 ${conf[0]}_start ${label} ; x=$?
376 eoutdent
377 [[ ${x} == 0 ]] && continue
378 # We need to test to see if it's an IP address or a function
379 # We do this by testing if the 1st character is a digit
380 elif [[ ${conf[0]:0:1} == [[:digit:]] ]]; then
381 eindent
382 interface_configure ${label} ${conf[@]} ; x=$?
383 eoutdent
384 [[ ${x} == 0 ]] && continue
385 else
386 eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
387 fi
388
389 if [[ -n ${config_fallback_IFACE[i]} ]]; then
390 einfo "Trying fallback configuration"
391 config_IFACE[i]=${config_fallback_IFACE[i]}
392 config_fallback_IFACE[i]=''
393 (( i-- )) # since the loop will increment it
394 continue
395 fi
396
397 # Only return failure if it was the first address for the interface
398 [[ ${i} -eq 0 ]] && return 1
399 done
400 eoutdent
401
402 # Enabling rp_filter causes wacky packets to be auto-dropped by
403 # the kernel. Note that we only do this if it is not set via
404 # /etc/sysctl.conf ...
405 if [[ -e /proc/sys/net/ipv4/conf/${iface}/rp_filter && \
406 -z "$(grep -s '^[^#]*rp_filter' /etc/sysctl.conf)" ]]; then
407 echo -n 1 > /proc/sys/net/ipv4/conf/${iface}/rp_filter
408 fi
409
410 # Start any modules with _post_start
411 # We do this here as the variables were localised in this function
412 for mod in ${MODULES[@]}; do
413 if [[ function == $( type -t ${mod}_post_start ) ]]; then
414 ${mod}_post_start ${iface} || return 1
415 fi
416 done
417
418 return 0
419 }
420
421 # bool iface_stop(char *interface)
422 #
423 # iface_stop: bring down an interface. Don't trust information in
424 # /etc/conf.d/net since the configuration might have changed since
425 # iface_start ran. Instead query for current configuration and bring
426 # down the interface.
427 #
428 # However, we are currently reliant on handler and modules specified
429 # in /etc/conf.d/net
430 iface_stop() {
431 local iface=${1} i aliases need_begin=false mod
432 local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
433
434 einfo "Bringing down ${iface}"
435 eindent
436
437 # Collect list of aliases for this interface.
438 # List will be in reverse order.
439 aliases=$( interface_get_aliases_rev ${iface} )
440
441 # Stop aliases before primary interface.
442 # Note this must be done in reverse order, since ifconfig eth0:1
443 # will remove eth0:2, etc. It might be sufficient to simply remove
444 # the base interface but we're being safe here.
445 for i in ${aliases} ${iface}; do
446 # Stop all our modules
447 for mod in ${MODULES[@]}; do
448 [[ $( type -t ${mod}_stop ) == function ]] && ${mod}_stop ${i}
449 done
450
451 # Delete all the addresses for this alias
452 interface_del_addresses ${i} true
453
454 # Do final shut down of this alias
455 ebegin "Shutting down ${i}"
456 interface_iface_stop ${i}
457 eend $?
458 done
459
460 return 0
461 }
462
463 # bool start(void)
464 #
465 # Brings up ${IFACE}. Calls preup, iface_start, then postup.
466 # Returns 0 (success) unless preup or iface_start returns 1 (failure).
467 # Ignores the return value from postup.
468 start() {
469 local mod RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
470 local -a MODULES
471
472 einfo "Starting ${IFACE}"
473 eindent
474
475 modules_load ${IFACE} || { eend 1; return 1; }
476
477 if [[ ${IFACE} == lo ]]; then
478 ebegin "Bringing up ${IFACE}"
479 interface_loopback_create
480 eend $?
481 return $?
482 fi
483
484 if ! interface_exists ${IFACE}; then
485 eerror "${IFACE} does not exist"
486 return 1
487 fi
488
489 # Call user-defined preup function if it exists
490 if [[ $( type -t preup ) == function ]]; then
491 einfo "Running preup function"
492 if ! preup ${IFACE} ; then
493 eerror "preup ${IFACE} failed"
494 return 1
495 fi
496 fi
497
498 # pre Start any modules with
499 for mod in ${MODULES[@]}; do
500 if [[ $( type -t ${mod}_pre_start ) == function ]]; then
501 ${mod}_pre_start ${IFACE} || return 1
502 fi
503 done
504
505 # Start the interface
506 if ! iface_start ${IFACE} ; then
507 interface_down ${IFACE}
508 return 1
509 fi
510
511 # post Start modules is called in iface_start
512 # as that's where the functions get localised
513 # and they may have to call iface_start recursively
514
515 # Call user-defined postup function if it exists
516 if [[ $( type -t postup ) == function ]]; then
517 einfo "Running postup function"
518 postup ${IFACE}
519 fi
520
521 return 0
522 }
523
524 # bool stop(void)
525 #
526 # Brings down ${IFACE}. If predown call returns non-zero, then
527 # stop returns non-zero to indicate failure bringing down device.
528 # In all other cases stop returns 0 to indicate success.
529 stop() {
530 local mod RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
531 local -a MODULES
532
533 einfo "Stopping ${IFACE}"
534 eindent
535
536 modules_load ${IFACE} true || return 1
537
538 # Call user-defined predown function if it exists
539 if [[ ${IFACE} != lo ]]; then
540 if [[ $( type -t predown ) == function ]]; then
541 einfo "Running predown function"
542 if ! predown ${IFACE} ; then
543 eerror "predown ${IFACE} failed"
544 return 1
545 fi
546 elif is_net_fs /; then
547 eerror "root filesystem is network mounted -- can't stop ${IFACE}"
548 return 1
549 fi
550 fi
551
552 # pre Stop any modules
553 for mod in ${MODULES[@]}; do
554 [[ $( type -t ${mod}_pre_stop ) == function ]] && ${mod}_pre_stop ${IFACE}
555 done
556
557 iface_stop ${IFACE} || return 1 # always succeeds, btw
558
559 # post Stop any modules
560 for mod in ${MODULES[@]}; do
561 # We have already taken down the interface, so no need to error
562 [[ $( type -t ${mod}_post_stop ) == function ]] && ${mod}_post_stop ${IFACE}
563 done
564
565 # Call user-defined postdown function if it exists
566 if [[ ${IFACE} != lo && $( type -t postdown ) == function ]]; then
567 einfo "Running postdown function"
568 postdown ${IFACE}
569 fi
570
571 return 0
572 }
573
574 # 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