diff options
Diffstat (limited to 'net-scripts/init.d/net.lo')
-rwxr-xr-x | net-scripts/init.d/net.lo | 307 |
1 files changed, 163 insertions, 144 deletions
diff --git a/net-scripts/init.d/net.lo b/net-scripts/init.d/net.lo index 523dd65..f1dbfdc 100755 --- a/net-scripts/init.d/net.lo +++ b/net-scripts/init.d/net.lo @@ -17,7 +17,7 @@ depend() { # Load any custom depend functions for the given interface # For example, br0 may need eth0 and eth1 local iface="${myservice##*.}" - [[ $( type -t depend_${iface} ) == "function" ]] && depend_${iface} + [[ $(type -t "depend_${iface}") == "function" ]] && depend_${iface} return 0 } @@ -34,30 +34,27 @@ source "${MODULES_DIR}/helpers.d/functions" # Make some wrappers to fudge after/before/need/use depend flags. # These are callbacks so MODULE will be set. after() { - local x="$*" - [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs ) - eval "${MODULE}_after() { echo \"$x\"; }" + eval "${MODULE}_after() { echo \"$*\"; }" } before() { - local x="$*" - [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs ) - eval "${MODULE}_before() { echo \"$x\"; }" + eval "${MODULE}_before() { echo \"$*\"; }" } need() { - local x="$*" - [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs ) - eval "${MODULE}_need() { echo \"$x\"; }" + eval "${MODULE}_need() { echo \"$*\"; }" } installed() { - local x="$*" - [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs ) # We deliberately misspell this as _installed will probably be used # at some point - eval "${MODULE}_instlled() { echo \"$x\"; }" + eval "${MODULE}_instlled() { echo \"$*\"; }" } - -sort() { - LC_ALL=C /bin/sort "$@" +provide() { + eval "${MODULE}_provide() { echo \"$*\"; }" +} +functions() { + eval "${MODULE}_functions() { echo \"$*\"; }" +} +variables() { + eval "${MODULE}_variables() { echo \"$*\"; }" } # void go_background(void) @@ -85,8 +82,8 @@ module_load_minimum() { return 1 fi - for f in check_installed provides check_depends depend; do - [[ $( type -t "${MODULE}_${f}" ) == "function" ]] && continue + for f in depend; do + is_function "${MODULE}_${f}" && continue eerror "${MODULE} does not support the required function ${f}" return 1 done @@ -99,7 +96,7 @@ module_load_minimum() { # Load and check each module for sanity # If the module is not installed, the functions are to be removed modules_load_auto() { - local i j + local i j inst # Populate the MODULES array # Basically we treat evey file in ${MODULES_DIR} as a module @@ -122,10 +119,16 @@ modules_load_auto() { eerror "interface is a reserved name - cannot load a module called interface" return 1 fi + ( u=0; module_load_minimum "${MODULES[i]}" || u=1; - [[ ${u} == 0 ]] && ${MODULES[i]##*/}_check_installed false || u=1; + if [[ ${u} == 0 ]]; then + inst="${MODULES[i]##*/}_check_installed"; + if is_function "${inst}" ; then + ${inst} false || u=1; + fi + fi exit "${u}"; ) @@ -154,11 +157,13 @@ modules_check_installed() { local i j missingdeps nmods="${#MODULES[@]}" for (( i=0; i<nmods; i++ )); do - [[ $( type -t "${MODULES[i]}_instlled" ) != "function" ]] && continue + is_function "${MODULES[i]}_instlled" || continue for j in $( ${MODULES[i]}_instlled ); do missingdeps=true - if [[ $( type -t "${j}_check_installed" ) == "function" ]]; then + if is_function "${j}_check_installed" ; then ${j}_check_installed && missingdeps=false + elif is_function "${j}_depend" ; then + missingdeps=false fi ${missingdeps} && unset MODULES[i] && unset PROVIDES[i] && break done @@ -209,13 +214,12 @@ modules_check_user() { ) unset MODULES[j] unset PROVIDES[j] - break fi done continue fi - if [[ $( type -t "${umods[i]}_provides" ) != "function" ]]; then + if ! is_function "${umods[i]}_depend" ; then # If the module is one of our preferred modules, then # ignore this error; whatever is available will be # used instead. @@ -225,14 +229,19 @@ modules_check_user() { # not installed. Load the module and report its error if [[ -e "${MODULES_DIR}/${umods[i]}" ]]; then source "${MODULES_DIR}/${umods[i]}" - ${umods[i]}_check_installed true + is_function "${umods[i]}_check_installed" \ + && ${umods[i]}_check_installed true else eerror "The module \"${umods[i]}\" does not exist" fi return 1 fi - mod=$( ${umods[i]}_provides ) + if is_function "${umods[i]}_provide" ; then + mod=$( ${umods[i]}_provide ) + else + mod="${umods[i]}" + fi for (( j=0; j<nmods; j++ )); do [[ -z ${MODULES[j]} ]] && continue if [[ ${PROVIDES[j]} == "${mod}" && ${umods[i]} != "${MODULES[j]}" ]]; then @@ -269,84 +278,82 @@ modules_check_user() { } # void modules_sort(void) - +# +# Sort our modules modules_sort() { - local -a modnums sort_history modafter modbefore - local i j k p changed_something nmods="${#MODULES[@]}" - - # Sort our modules - # We do this by assigning numbers to each module - # We also assign modbefore and modafter so we don't - # shell out as much because it's expensive on CPU. - modnums=() - for (( i=0; i<nmods; i++ )); do - modnums[i]="${i}" - [[ $( type -t "${MODULES[i]}_after" ) == "function" ]] \ - && modafter[i]=$( ${MODULES[i]}_after ) - [[ $( type -t "${MODULES[i]}_before" ) == "function" ]] \ - && modbefore[i]=$( ${MODULES[i]}_before ) + local i j nmods=${#MODULES[@]} m + local -a provide=() provide_list=() after=() dead=() sorted=() sortedp=() + + # Make our provide list + for ((i=0; i<nmods; i++)); do + dead[i]="false" + if [[ ${MODULES[i]} != "${PROVIDES[i]}" ]] ; then + local provided=false + for ((j=0; j<${#provide[@]}; j++)); do + if [[ ${provide[j]} == "${PROVIDES[i]}" ]]; then + provide_list[j]="${provide_list[j]} ${MODULES[i]}" + provided=true + fi + done + if ! ${provided}; then + provide[j]="${PROVIDES[i]}" + provide_list[j]="${MODULES[i]}" + fi + fi done - # Then we swap numbers based on and after/before flags - # until we don't swap anymore. The sort_history array prevents - # the possibility of an infinite loop - sort_history[0]="${modnums[*]}" - for (( k=1; 1; k++ )); do - changed_something=false - for (( i=0; i<nmods; i++ )); do - for p in ${modafter[i]}; do - for (( j=0; j<nmods; j++ )); do - [[ ${p} != "${MODULES[j]}" && ${p} != "${PROVIDES[j]}" ]] \ - && continue - - if [[ ${modnums[i]} -lt "${modnums[j]}" ]]; then - tmp="${modnums[i]}" - modnums[i]="${modnums[j]}" - modnums[j]="${tmp}" - changed_something=true - fi - done - done - for p in ${modbefore[i]}; do - for (( j=0; j<nmods; j++ )); do - [[ ${p} != "${MODULES[j]}" && ${p} != "${PROVIDES[j]}" ]] \ - && continue - - if [[ ${modnums[i]} -gt "${modnums[j]}" ]]; then - tmp="${modnums[i]}" - modnums[i]="${modnums[j]}" - modnums[j]="${tmp}" - changed_something=true + # Create an after array, which holds which modules the module at + # index i must be after + for ((i=0; i<nmods; i++)); do + if is_function "${MODULES[i]}_after" ; then + after[i]=" ${after[i]} $(${MODULES[i]}_after) " + fi + if is_function "${MODULES[i]}_before" ; then + for m in $(${MODULES[i]}_before); do + for ((j=0; j<nmods; j++)) ; do + if [[ ${PROVIDES[j]} == "${m}" ]]; then + after[j]=" ${after[j]} ${MODULES[i]} " + break fi done done - done - ${changed_something} || break - - # Make sure we aren't repeating a previous state - # First time through, k=1, k/2=0 - sort_history[k]="${modnums[*]}" - if [[ ${sort_history[k]} == "${sort_history[k/2]}" ]]; then - eerror "Detected an infinite loop sorting modules; blundering ahead" - break fi done - # Finally we sort our modules in number order - um="" - for (( i=0; i<nmods; i++ )); do - um="${um}${modnums[i]} ${MODULES[i]} ${PROVIDES[i]}\n" + # Replace the after list modules with real modules + for ((i=0; i<nmods; i++)); do + if [[ -n ${after[i]} ]]; then + for ((j=0; j<${#provide[@]}; j++)); do + after[i]="${after[i]// ${provide[j]} / ${provide_list[j]} }" + done + fi done + + # We then use the below code to provide a topologial sort + module_after_visit() { + local name=$1 i x - p=( $( echo -e "${um}" | sort -n | cut -d' ' -f2,3 ) ) - MODULES=() - PROVIDES=() - j=0 - for (( i=0; i<${#p[@]}; i+=2 )); do - MODULES[j]="${p[i]}" - PROVIDES[j]="${p[i+1]}" - (( j++ )) + for ((i=0; i<nmods; i++)); do + [[ ${MODULES[i]} == "$1" ]] && break + done + + ${dead[i]} && return + dead[i]="true" + + for x in ${after[i]} ; do + module_after_visit "${x}" + done + + sorted=( "${sorted[@]}" "${MODULES[i]}" ) + sortedp=( "${sortedp[@]}" "${PROVIDES[i]}" ) + } + + for x in ${MODULES[@]}; do + module_after_visit "${x}" done + + MODULES=( "${sorted[@]}" ) + PROVIDES=( "${sortedp[@]}" ) } # bool modules_check_depends(bool showprovides) @@ -355,7 +362,7 @@ modules_check_depends() { local missingdeps p interface=false for (( i=0; i<nmods; i++ )); do - if [[ $( type -t "${MODULES[i]}_need" ) == "function" ]]; then + if is_function "${MODULES[i]}_need" ; then for needmod in $( ${MODULES[i]}_need ); do missingdeps=true for (( j=0; j<nmods; j++ )); do @@ -372,7 +379,15 @@ modules_check_depends() { done fi - ${MODULES[i]}_check_depends || return 1 + if is_function "${MODULES[i]}_functions" ; then + for f in $( ${MODULES[i]}_functions ); do + if ! is_function "${f}" ; then + eerror "${MODULES[i]}: missing required function \"${f}\"" + return 1 + fi + done + fi + [[ ${PROVIDES[i]} == "interface" ]] && interface=true if ${showprovides} ; then @@ -418,57 +433,63 @@ modules_load() { j="${#modules_force[@]}" for (( i=0; i<j; i++ )); do module_load_minimum "${MODULES_DIR}/${modules_force[i]}" || return 1 - ${modules_force[i]}_check_installed || unset modules_force[i] - done - modules_force=( "${modules_force[@]}" ) - - # Strip any duplicate modules providing the same thing - j="${#modules_force[@]}" - for (( i=0; i<j-1; i++ )); do - [[ -z ${modules_force[i]} ]] && continue - for (( k=i+1; k<j; k++ )); do - [[ -z ${modules_force[k]} ]] && continue - [[ $( ${modules_force[i]}_provides ) \ - == $( ${modules_force[k]}_provides ) ]] \ - && unset modules_force[k] - done + if is_function "${modules_force[i]}_check_installed" ; then + ${modules_force[i]}_check_installed || unset modules_force[i] + fi done - MODULES=( "${modules_force[@]}" ) fi - # We now buffer the _provides functions for a big speed boost j="${#MODULES[@]}" for (( i=0; i<j; i++ )); do - PROVIDES[i]=$( ${MODULES[i]}_provides ) + # Now load our dependencies - we need to use the MODULE variable + # here as the after/before/need functions use it + MODULE="${MODULES[i]}" + ${MODULE}_depend + + # If no provide is given, assume module name + if is_function "${MODULES[i]}_provide" ; then + PROVIDES[i]=$( ${MODULES[i]}_provide ) + else + PROVIDES[i]="${MODULES[i]}" + fi done - if [[ -z ${modules_force[@]} ]]; then + if [[ -n ${modules_force[@]} ]]; then + # Strip any duplicate modules providing the same thing + j="${#MODULES[@]}" + for (( i=0; i<j-1; i++ )); do + [[ -z ${MODULES[i]} ]] && continue + for (( k=i+1; k<j; k++ )); do + if [[ ${PROVIDES[i]} == ${PROVIDES[k]} ]]; then + unset MODULES[k] + unset PROVIDES[k] + fi + done + done + MODULES=( "${MODULES[@]}" ) + PROVIDES=( "${PROVIDES[@]}" ) + else if ${starting}; then modules_check_user || return 1 + else + # Always prefer iproute2 for taking down interfaces + if is_function iproute2_provide ; then + function_wrap iproute2 $(iproute2_provide) + fi fi fi - - # Setup class wrappers: interface_up -> iproute2_up, for example + + # Wrap our modules j="${#MODULES[@]}" for (( i=0; i<j; i++ )); do function_wrap "${MODULES[i]}" "${PROVIDES[i]}" - - # Now load our dependencies - we need to use the MODULE variable - # here as the after/before/need functions use it - if [[ -z ${modules_force[@]} ]]; then - MODULE="${MODULES[i]}" - ${MODULE}_depend - fi done - - # Some modules may be installed, but not selected by user preference - # so we wrap these if needed j="${#WRAP_MODULES[@]}" for (( i=0; i<j; i++ )); do - function_wrap "${WRAP_MODULES[i]}" + function_wrap ${WRAP_MODULES[i]} done - + if [[ -z ${modules_force[@]} ]]; then modules_check_installed || return 1 modules_sort || return 1 @@ -506,7 +527,7 @@ iface_start() { # pre Start any modules with for mod in ${MODULES[@]}; do - if [[ $( type -t "${mod}_pre_start" ) == "function" ]]; then + if is_function "${mod}_pre_start" ; then ${mod}_pre_start "${iface}" || { eend 1; return 1; } fi done @@ -554,7 +575,7 @@ iface_start() { # Otherwise a default of NULL if [[ -z ${config} ]]; then # if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then - if [[ $( type -t "dhcp_start" ) == "function" ]]; then + if is_function "dhcp_start" ; then config=( "dhcp" ) ewarn "Configuration not set for ${iface} - assuming dhcp" else @@ -585,7 +606,7 @@ iface_start() { einfo "${conf[0]}" # Do we have a function for our config? - if [[ $( type -t "${conf[0]}_start" ) == "function" ]]; then + if is_function "${conf[0]}_start" ; then eindent ${conf[0]}_start "${iface}" ; x=$? eoutdent @@ -594,9 +615,9 @@ iface_start() { # We do this by testing if the 1st character is a digit elif [[ ${conf[0]:0:1} == [[:digit:]] || ${conf[0]} == *:* ]]; then x="0" - if [[ ${RC_AUTO_INTERFACE} == "yes" \ - && $(type -t address_exists ) == "function" ]]; then - if address_exists "${iface}" "${conf[0]}" ; then + if [[ ${RC_AUTO_INTERFACE} == "yes" ]] \ + && is_function arping_address_exists ; then + if arping_address_exists "${iface}" "${conf[0]}" ; then eerror "${conf[0]%%/*} already taken on ${iface}" x="1" fi @@ -629,7 +650,7 @@ iface_start() { # Start any modules with _post_start for mod in ${MODULES[@]}; do - if [[ $( type -t "${mod}_post_start" ) == "function" ]]; then + if is_function "${mod}_post_start" ; then ${mod}_post_start "${iface}" || return 1 fi done @@ -649,8 +670,7 @@ iface_stop() { # pre Stop any modules for mod in ${MODULES[@]}; do - [[ $( type -t "${mod}_pre_stop" ) == "function" ]] \ - && ${mod}_pre_stop "${iface}" + is_function "${mod}_pre_stop" && ${mod}_pre_stop "${iface}" done einfo "Bringing down ${iface}" @@ -667,7 +687,7 @@ iface_stop() { for i in ${aliases} ${iface}; do # Stop all our modules for mod in ${MODULES[@]}; do - [[ $( type -t "${mod}_stop" ) == "function" ]] && ${mod}_stop "${i}" + is_function "${mod}_stop" && ${mod}_stop "${i}" done # A module may have removed the interface @@ -690,8 +710,7 @@ iface_stop() { # post Stop any modules for mod in ${MODULES[@]}; do # We have already taken down the interface, so no need to error - [[ $( type -t "${mod}_post_stop" ) == "function" ]] \ - && ${mod}_post_stop "${iface}" + is_function "${mod}_post_stop" && ${mod}_post_stop "${iface}" done return 0 @@ -730,7 +749,7 @@ run_start() { fi # Call user-defined preup function if it exists - if [[ $( type -t preup ) == "function" ]]; then + if is_function preup ; then einfo "Running preup function" eindent ( preup "${iface}" ) @@ -762,7 +781,7 @@ run_start() { fi # Call user-defined postup function if it exists - if [[ $( type -t postup ) == "function" ]]; then + if is_function postup ; then einfo "Running postup function" eindent ( postup "${iface}" ) @@ -786,7 +805,7 @@ run_stop() { [[ -n ${ESSID} ]] && ESSIDVAR=$( bash_variable "${ESSID}" ) # Call user-defined predown function if it exists - if [[ $( type -t predown ) == "function" ]]; then + if is_function predown ; then einfo "Running predown function" eindent ( predown "${iface}" ) @@ -800,7 +819,7 @@ run_stop() { iface_stop "${iface}" || return 1 # always succeeds, btw # Call user-defined postdown function if it exists - if [[ $( type -t postdown ) == "function" ]]; then + if is_function postdown ; then einfo "Running postdown function" eindent ( postdown "${iface}" ) @@ -870,7 +889,7 @@ run() { else if [[ ${cmd} == "start" ]]; then # Call user-defined failup if it exists - if [[ $( type -t failup ) == "function" ]]; then + if is_function failup ; then einfo "Running failup function" eindent ( failup "${iface}" ) @@ -878,7 +897,7 @@ run() { fi else # Call user-defined faildown if it exists - if [[ $( type -t faildown ) == "function" ]]; then + if is_function faildown ; then einfo "Running faildown function" eindent ( faildown "${iface}" ) |