#!/sbin/runscript
# Copyright (c) 2004-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header$
# Contributed by Roy Marples (uberlord@gentoo.org)
# Many thanks to Aron Griffis (agriffis@gentoo.org)
# for help, ideas and patches
#NB: Config is in /etc/conf.d/net
if [[ -n ${NET_DEBUG} ]]; then
set -x
devnull=/dev/stderr
else
devnull=/dev/null
fi
# For pcmcia users. note that pcmcia must be added to the same
# runlevel as the net.* script that needs it.
depend() {
use coldplug hotplug pcmcia usb isdn wlan
# 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}
}
# Define where our modules are
MODULES_DIR=/lib/rcscripts/net.modules.d
# Load some functions shared between ourselves and our dhcp helpers
source ${MODULES_DIR}/helpers.d/functions
# Make some wrappers to fudge after/before/need/use depend flags.
# These are callbacks so mods[i] will be set.
after() {
local x="$*"
[[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
eval "${MODULE}_after() { echo \"$x\"; }"
}
before() {
local x="$*"
[[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
eval "${MODULE}_before() { echo \"$x\"; }"
}
need() {
local x="$*"
[[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
eval "${MODULE}_need() { echo \"$x\"; }"
}
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\"; }"
}
sort() {
LC_ALL=C /bin/sort "$@"
}
# void module_class_wrap(char *module, char *provides)
# Setup class wrappers: interface_up -> iproute2_up, for example
module_class_wrap() {
local module=${1} provides=${2} x
# Don't wrap functions if another module already has
[[ $( type -t ${provides}_provides ) == function ]] && return
for x in $( typeset -f | grep -o ^${module}_'[^ ]*' ); do
eval "${provides}${x#${module}}() { ${x} \"\$@\"; }"
done
}
# bool module_load_minimum(char *module)
#
# Does the minimum checking on a module - even when forcing
module_load_minimum() {
local f=${1} MODULE=${1##*/}
if [[ ! -f ${f} ]]; then
eerror "${f} does not exist"
return 1
fi
if ! source ${f} ; then
eerror "${MODULE} failed a sanity check"
return 1
fi
for f in check_installed provides check_depends depend; do
[[ $( type -t ${MODULE}_${f} ) == function ]] && continue
eerror "${MODULE} does not support the required function ${f}"
return 1
done
# Wrap our before/after/need/use functions
${MODULE}_depend
return 0
}
# bool modules_load_auto()
#
# Load and check each module for sanity
# If the module is not installed, the functions are to be removed
modules_load_auto() {
local e f i j beforefuncs afterfuncs diffs unload
# Populate the MODULES array
MODULES=( $( find ${MODULES_DIR}/ -maxdepth 1 -type f ! -name ".*" | sort ) )
# Each of these sources into the global namespace, so it's
# important that module functions and variables are prefixed with
# the module name, for example iproute2_
beforefuncs="$( typeset -F )"
j=${#MODULES[@]}
loaded_interface=false
for (( i=0; i<j; i++ )); do
unload=false
module_load_minimum ${MODULES[i]} || unload=true
MODULES[i]=${MODULES[i]##*/}
! ${unload} && ${MODULES[i]}_check_installed false || unload=true
if [[ ${MODULES[i]} == interface ]]; then
eerror "interface is a reserved name - cannot load a module called interface"
return 1
fi
afterfuncs="$( typeset -F )"
if ${unload} ; then
unset MODULES[i]
unsetfuncs="${unsetfuncs} $( diff -U0 <( echo "${beforefuncs}" ) <( echo "${a$ | awk 'BEGIN { ORS = " "; } /+declare -f/ { print $3; }' )"
fi
beforefuncs="${afterfuncs}"
done
MODULES=( "${MODULES[@]}" )
return 0
}
# bool modules_check_installed(void)
#
# Ensure that all modules have the required modules loaded
# This enables us to remove modules from the MODULES array
# Whilst other modules can still explicitly call them
# One example of this is essidnet which configures network
# settings for the specific ESSID connected to as the user
# may be using a daemon to configure wireless instead of our
# iwconfig module
modules_check_installed() {
local i j missingdeps nmods=${#MODULES[@]}
for (( i=0; i<nmods; i++ )); do
[[ $( type -t ${MODULES[i]}_instlled ) != function ]] && continue
for j in $( ${MODULES[i]}_instlled ); do
missingdeps=true
if [[ $( type -t ${j}_check_installed ) == function ]]; then
${j}_check_installed && missingdeps=false
fi
${missingdeps} && unset MODULES[i] && unset PROVIDES[i] && break
done
done
MODULES=( "${MODULES[@]}" )
PROVIDES=( "${PROVIDES[@]}" )
}
# bool modules_check_user(void)
modules_check_user() {
local -a umods
local i j k l npref nmods=${#MODULES[@]}
# Has the interface got any specific modules?
eval umods=( \"\$\{modules_${iface}\[@\]\}\" )
# Global setting follows interface-specific setting
umods=( "${umods[@]}" "${modules[@]}" )
# Add our preferred modules
npref=3
umods=( "${umods[@]}" "ifconfig" "dhcpcd" "iwconfig" )
# First we strip any modules that conflict from user settings
# So if the user specifies pump then we don't use dhcpcd
for (( i=0; i<${#umods[@]}; i++ )); do
# Some users will inevitably put "dhcp" in their modules
# list. To keep users from screwing up their system this
# way, ignore this setting so that the default dhcp
# module will be used.
[[ ${umods[i]} == dhcp ]] && continue
# We remove any modules we explicitly don't want
if [[ ${umods[i]} == !* ]]; then
for (( j=0; j<nmods; j++ )); do
[[ -z ${MODULES[j]} ]] && continue
if [[ ${umods[i]:1} == ${MODULES[j]} || ${umods[i]:1} == ${PROVIDES[j$ # We may need to setup a class wrapper for it even though
# we don't use it directly
${MODULES[j]}_check_installed && module_class_wrap ${MODULES[$
unset MODULES[j]
unset PROVIDES[j]
break
fi
done
continue
fi
if [[ $( type -t ${umods[i]}_provides ) != function ]]; then
# If the module is one of our preferred modules, then
# ignore this error; whatever is available will be
# used instead.
(( i < ${#umods[@]} - npref )) || continue
eerror "${umods[i]} is not a valid module (missing provides)"
return 1
fi
# Ensure that the user specified module has its package installed
if (( i < ${#umods[@]} - npref )); then
# $1==true causes check_installed to report its own errors
${umods[i]}_check_installed true || return 1
else
# If this happens on a preferred modules, ignore it;
# whatever is available will be used instead.
${umods[i]}_check_installed false || continue
fi
mod=$( ${umods[i]}_provides )
for (( j=0; j<nmods; j++ )); do
[[ -z ${MODULES[j]} ]] && continue
if [[ ${PROVIDES[j]} == ${mod} && ${umods[i]} != ${MODULES[j]} ]]; then
# We don't have a match - now ensure that we still provide an alterna$ # This is to handle our preferred modules.
for (( l=0; l<nmods; l++ )); do
[[ ${l} -eq ${j} || -z ${MODULES[l]} ]] && continue
if [[ ${PROVIDES[l]} == ${mod} ]]; then
unset MODULES[j]
unset PROVIDES[j]
break
fi
done
fi
done
done
# Then we strip conflicting modules.
# We only need to do this for 3rd party modules that conflict with
# our own modules and the preferred list AND the user modules
# list doesn't specify a preference.
for (( i=0; i<nmods-1; i++ )); do
[[ -z ${MODULES[i]} ]] && continue
for (( j=i+1; j<nmods; j++)); do