#!/sbin/runscript # Copyright (c) 2004-2005 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # 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 # For pcmcia users. note that pcmcia must be added to the same # runlevel as the net.* script that needs it. depend() { need localmount use coldplug 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} return 0 } # Define where our modules are MODULES_DIR="/lib/rcscripts/net.modules.d" # Some defaults background="${background:-no}" # 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 MODULE will be set. after() { eval "${MODULE}_after() { echo \"$*\"; }" } before() { eval "${MODULE}_before() { echo \"$*\"; }" } need() { eval "${MODULE}_need() { echo \"$*\"; }" } installed() { # We deliberately misspell this as _installed will probably be used # at some point eval "${MODULE}_instlled() { echo \"$*\"; }" } provide() { eval "${MODULE}_provide() { echo \"$*\"; }" } functions() { eval "${MODULE}_functions() { echo \"$*\"; }" } variables() { eval "${MODULE}_variables() { echo \"$*\"; }" } # void go_background(void) # # Setup for backgrounding network script go_background() { einfo "Backgrounding ..." mark_service_inactive "net.${iface}" exit 0 } # 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 depend; do is_function "${MODULE}_${f}" && continue eerror "${MODULE} does not support the required function ${f}" return 1 done 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 i j inst # Populate the MODULES array # Basically we treat evey file in ${MODULES_DIR} as a module MODULES=( $( cd "${MODULES_DIR}" ; ls ) ) j="${#MODULES[@]}" for (( i=0; i/dev/null fi # Call user-defined preup function if it exists if is_function preup ; then einfo "Running preup function" eindent ( preup "${iface}" ) eend "$?" "preup ${iface} failed" || return 1 eoutdent fi # If config is set to noop and the interface is up with an address # then we don't start it local config eval config=( \"\$\{config_${IFVAR}\[@\]\}\" ) if [[ ${config[0]} == "noop" ]] && interface_is_up "${iface}" true ; then einfo "Keeping current configuration for ${iface}" eend 0 else # Remove noop from the config var [[ ${config[0]} == "noop" ]] \ && eval "config_${IFVAR}=( "\"\$\{config\[@\]:1\}\"" )" # There may be existing ip address info - so we strip it interface_del_addresses "${iface}" # Start the interface if ! iface_start "${iface}" ; then interface_exists "${iface}" && interface_down "${iface}" eend 1 return 1 fi fi # Call user-defined postup function if it exists if is_function postup ; then einfo "Running postup function" eindent ( postup "${iface}" ) eoutdent fi return 0 } # bool run_stop(char *iface) { # # Brings down ${iface}. If predown call returns non-zero, then # stop returns non-zero to indicate failure bringing down device. # In all other cases stop returns 0 to indicate success. run_stop() { local iface="$1" IFVAR=$( bash_variable "$1" ) x # Load our ESSID variable so users can use it in predown() instead # of having to write code. local ESSID=$( get_options "ESSID" ) ESSIDVAR [[ -n ${ESSID} ]] && ESSIDVAR=$( bash_variable "${ESSID}" ) # Call user-defined predown function if it exists if is_function predown ; then einfo "Running predown function" eindent ( predown "${iface}" ) eend $? "predown ${iface} failed" || return 1 eoutdent elif is_net_fs /; then eerror "root filesystem is network mounted -- can't stop ${iface}" return 1 fi iface_stop "${iface}" || return 1 # always succeeds, btw # Call user-defined postdown function if it exists if is_function postdown ; then einfo "Running postdown function" eindent ( postdown "${iface}" ) eoutdent fi return 0 } # bool run(char *iface, char *cmd) # # Main start/stop entry point # We load modules here and remove any functions that they # added as we may be called inside the same shell scope for another interface run() { local iface="$1" cmd="$2" r=1 RC_INDENTATION="${RC_INDENTATION}" local starting=true local -a MODULES mods local IN_BACKGROUND="${IN_BACKGROUND}" # No point in backgrounding if we're already there ... # This is also required so we can select the "best" interface if [[ ${IN_BACKGROUND} == "true" || ${IN_BACKGROUND} == "1" ]]; then IN_BACKGROUND=true background=false else IN_BACKGROUND=false fi # We need to override the exit function as runscript.sh now checks # for it. We need it so we can mark the service as inactive ourselves. unset -f exit eindent [[ ${cmd} == "stop" ]] && starting=false # We force lo to only use these modules for a major speed boost [[ ${iface} == "lo" ]] && modules_force=( "iproute2" "ifconfig" "system" ) if modules_load "${iface}" "${starting}" ; then if [[ ${cmd} == "stop" ]]; then # Reverse the module list for stopping mods=( "${MODULES[@]}" ) for ((i = 0; i < ${#mods[@]}; i++)); do MODULES[i]=${mods[((${#mods[@]} - i - 1))]} done run_stop "${iface}" && r=0 remove_state "${iface}" else run_start "${iface}" && r=0 fi fi # Only apply best state if we're on auto if [[ ${r} == "0" ]]; then local siface="" if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then siface=$( select_best_interface ) if [[ -n ${siface} ]]; then einfo "Selecting best interface: ${siface}" fi elif [[ ${cmd} == "start" ]]; then siface="${iface}" fi [[ -n ${siface} ]] && apply_state "${siface}" else if [[ ${cmd} == "start" ]]; then # Call user-defined failup if it exists if is_function failup ; then einfo "Running failup function" eindent ( failup "${iface}" ) eoutdent fi else # Call user-defined faildown if it exists if is_function faildown ; then einfo "Running faildown function" eindent ( faildown "${iface}" ) eoutdent fi fi fi return "${r}" } # void link_file(char *file) # # Move a config file from /etc to ${netdir} and creates a link if needed. # This enables net-scripts to control the config file for interface management # and allow /etc to become read only. link_file() { local file="$1" local link=$( readlink "/etc/${file}" 2>/dev/null ) if [[ ${link} != "${netdir}/${file}" ]]; then if [[ -f "/etc/${file}" ]]; then vewarn "Moving /etc/${file} to ${netdir}/${file} and creating link" mv "/etc/${file}" "${netdir}" ln -snf "${netdir}/${file}" "/etc/${file}" fi fi } # bool start(void) # # Start entry point so that we only have one function # which localises variables and unsets functions start() { if [[ ${IN_HOTPLUG} == "1" ]]; then # If we've been called by hotplug, check if we have # a policy for the interface for not starting local x ifvar=$( bash_variable "${IFACE}" ) eval x=\"\$\{hotplug_${ifvar}\}\" if [[ ${x} == "no" || ${x} == "false" ]]; then eerror "Not starting interface ${IFACE} due to hotplug policy" unset -f exit mark_service_stopped "net.${IFACE}" exit 1 fi fi if [[ ! -d "${statedir}/${IFACE}" ]]; then if ! mkdir -m 0755 -p "${statedir}/${IFACE}" ; then eerror "Unable to create state directory!" return 1 fi fi if [[ ${RC_AUTO_INTERFACE} == "yes" ]]; then link_file "resolv.conf" link_file "ntp.conf" link_file "yp.conf" fi einfo "Starting ${IFACE}" run "${IFACE}" start } # bool stop(void) # # Stop entry point so that we only have one function # which localises variables and unsets functions stop() { einfo "Stopping ${IFACE}" run "${IFACE}" stop } # vim:ts=4