#!/sbin/runscript # Copyright 1999-2004 Gentoo Technologies, Inc. # Distributed under the terms of the GNU General Public License v2 # $Header: /home/cvsroot/gentoo-src/rc-scripts/init.d/net.eth0,v 1.41 2004/05/10 14:16:35 agriffis Exp $ #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 hotplug pcmcia need net.uml0 net.eth0 } checkconfig() { if [[ -z "${ifconfig_IFACE}" ]]; then eerror "Please make sure that /etc/conf.d/net has \$ifconfig_$IFACE set" eerror "(or \$iface_$IFACE for old-style configuration)" return 1 fi if [[ -n "${vlans_IFACE}" && ! -x /sbin/vconfig ]]; then eerror "For VLAN (802.1q) support, emerge net-misc/vconfig" return 1 fi } # Fix bug 50039 (init.d/net.eth0 localization) # Some other commands in this script might need to be wrapped, but # we'll get them one-by-one. Note that LC_ALL trumps LC_anything_else # according to locale(7) ifconfig() { LC_ALL=C /sbin/ifconfig "$@" } # setup_vars: setup variables based on $1 and content of /etc/conf.d/net # The following variables are set, which should be declared local by # the calling routine. # status_IFACE (up or '') # vlans_IFACE (space-separated list) # ifconfig_IFACE (array of ifconfig lines, replaces iface_IFACE) # dhcpcd_IFACE (command-line args for dhcpcd) # routes_IFACE (array of route lines) # inet6_IFACE (array of inet6 lines) # ifconfig_fallback_IFACE (fallback ifconfig if dhcp fails) setup_vars() { local i iface="${1//\./_}" status_IFACE="$(ifconfig ${1} 2>${devnull} | gawk '$1 == "UP" {print "up"}')" eval vlans_IFACE=\"\$\{iface_${iface}_vlans\}\" eval ifconfig_IFACE=( \"\$\{ifconfig_$iface\[@\]\}\" ) eval dhcpcd_IFACE=\"\$\{dhcpcd_$iface\}\" eval routes_IFACE=( \"\$\{routes_$iface\[@\]\}\" ) eval inet6_IFACE=( \"\$\{inet6_$iface\[@\]\}\" ) eval ifconfig_fallback_IFACE=( \"\$\{ifconfig_fallback_$iface\[@\]\}\" ) # Support for Tuntap and bridging devices (jacob@jjoseph.org) eval type_IFACE=\"\$\{type_$iface\}\" eval tunuser_IFACE=\"\$\{tunuser_$iface\}\" eval brports_IFACE=\"\$\{brports_$iface\}\" # BACKWARD COMPATIBILITY: populate the ifconfig_IFACE array # if iface_IFACE is set (fex. iface_eth0 instead of ifconfig_eth0) eval local iface_IFACE=\"\$\{iface_$iface\}\" if [[ -n ${iface_IFACE} && -z ${ifconfig_IFACE} ]]; then # Make sure these get evaluated as arrays local -a aliases broadcasts netmasks # Start with the primary interface ifconfig_IFACE=( "${iface_IFACE}" ) # ..then add aliases eval aliases=( \$\{alias_$iface\} ) eval broadcasts=( \$\{broadcast_$iface\} ) eval netmasks=( \$\{netmask_$iface\} ) for ((i = 0; i < ${#aliases[@]}; i = i + 1)); do ifconfig_IFACE[i+1]="${aliases[i]} ${broadcasts[i]:+broadcast ${broadcasts[i]}} ${netmasks[i]:+netmask ${netmasks[i]}}" done fi # BACKWARD COMPATIBILITY: check for space-separated inet6 addresses if [[ ${#inet6_IFACE[@]} == 1 && ${inet6_IFACE} == *' '* ]]; then inet6_IFACE=( ${inet6_IFACE} ) fi } iface_start() { local IFACE=${1} i x retval checkconfig || return 1 if [[ ${ifconfig_IFACE} != dhcp ]]; then # First check the interface 'type' if [[ ${type_IFACE} = tuntap ]]; then # create the device, give it the right perms ebegin "Creating Tun/Tap Device ${IFACE}" /usr/bin/tunctl -u ${tunuser_IFACE} -t ${IFACE} eend $? || return $? elif [[ ${type_IFACE} = bridge ]]; then #set up bridge ebegin "Creating Bridge Device ${IFACE}" /sbin/brctl addbr ${IFACE} && \ /sbin/brctl setfd ${IFACE} 0 && \ /sbin/brctl sethello ${IFACE} 0 && \ /sbin/brctl stp ${IFACE} off eend $? || return $? fi # Show the address, but catch if this interface will be inet6 only i=${ifconfig_IFACE%% *} if [[ ${i} == *.*.*.* ]]; then ebegin "Bringing ${IFACE} up (${i})" else ebegin "Bringing ${IFACE} up" fi # ifconfig does not always return failure .. ifconfig ${IFACE} ${ifconfig_IFACE} >${devnull} && \ ifconfig ${IFACE} up &>${devnull} eend $? || return $? else # Check that eth0 was not brought up by the kernel ... if [[ ${status_IFACE} == up ]]; then einfo "Keeping kernel configuration for ${IFACE}" else ebegin "Bringing ${IFACE} up via DHCP" /sbin/dhcpcd ${dhcpcd_IFACE} ${IFACE} retval=$? eend $retval if [[ $retval == 0 ]]; then # DHCP succeeded, show address retrieved i=$(ifconfig ${IFACE} | grep -m1 -o 'inet addr:[^ ]*' | cut -d: -f2) [[ -n ${i} ]] && einfo " ${IFACE} received address ${i}" elif [[ -n "${ifconfig_fallback_IFACE}" ]]; then # DHCP failed, try fallback. # Show the address, but catch if this interface will be inet6 only i=${ifconfig_fallback_IFACE%% *} if [[ ${i} == *.*.*.* ]]; then ebegin "Using fallback configuration (${i}) for ${IFACE}" else ebegin "Using fallback configuration for ${IFACE}" fi ifconfig ${IFACE} ${ifconfig_fallback_IFACE} >${devnull} && \ ifconfig ${IFACE} up &>${devnull} eend $? || return $? else return $retval fi fi fi if [[ ${#ifconfig_IFACE[@]} -gt 1 ]]; then einfo " Adding aliases" for ((i = 1; i < ${#ifconfig_IFACE[@]}; i = i + 1)); do ebegin " ${IFACE}:${i} (${ifconfig_IFACE[i]%% *})" ifconfig ${IFACE}:${i} ${ifconfig_IFACE[i]} eend $? done fi if [[ -n ${inet6_IFACE} ]]; then einfo " Adding inet6 addresses" for ((i = 0; i < ${#inet6_IFACE[@]}; i = i + 1)); do ebegin " ${IFACE} inet6 add ${inet6_IFACE[i]}" ifconfig ${IFACE} inet6 add ${inet6_IFACE[i]} >${devnull} eend $? done fi if [ -n "${brports_IFACE}" ] then # add ports to existing bridge ebegin " Adding ports" for port in ${brports_IFACE} do ebegin " ${IFACE}-${port}" /sbin/ifconfig ${port} promisc && \ /sbin/brctl addif ${IFACE} ${port} || { retval=$? eend ${retval} "Failed to add port ${IFACE}-${port}" } done fi # Set static routes if [[ -n ${routes_IFACE} ]]; then einfo " Adding routes" for ((i = 0; i < ${#routes_IFACE[@]}; i = i + 1)); do ebegin " ${routes_IFACE[i]}" /sbin/route add ${routes_IFACE[i]} eend $? done fi # Set default route if applicable to this interface if [[ ${gateway} == ${IFACE}/* ]]; then local ogw=$(/bin/netstat -rn | awk '$1 == "0.0.0.0" {print $2}') local gw=${gateway#*/} if [[ ${ogw} != ${gw} ]]; then ebegin " Setting default gateway ($gw)" # First delete any existing route if it was setup by kernel... /sbin/route del default dev ${IFACE} &>${devnull} # Second delete old gateway if it was set... /sbin/route del default gw ${ogw} &>${devnull} # Third add our new default gateway /sbin/route add default gw ${gw} >${devnull} eend $? || { true # need to have some command in here # Note: This originally called stop, which is obviously # wrong since it's calling with a local version of IFACE. # The below code works correctly to abort configuration of # the interface, but is commented because we're assuming # that default route failure should not cause the interface # to be unconfigured. #local error=$? #ewarn "Aborting configuration of ${IFACE}" #iface_stop ${IFACE} #return ${error} } fi fi # Enabling rp_filter causes wacky packets to be auto-dropped by # the kernel. Note that we only do this if it is not set via # /etc/sysctl.conf ... if [[ -e /proc/sys/net/ipv4/conf/${IFACE}/rp_filter && \ -z "$(grep -s '^[^#]*rp_filter' /etc/sysctl.conf)" ]]; then echo -n 1 > /proc/sys/net/ipv4/conf/${IFACE}/rp_filter fi } # iface_stop: bring down an interface. Don't trust information in # /etc/conf.d/net since the configuration might have changed since # iface_start ran. Instead query for current configuration and bring # down the interface. iface_stop() { local IFACE=${1} i x aliases inet6 count # Try to do a simple down (no aliases, no inet6, no dhcp) aliases="$(ifconfig | grep -o "^$IFACE:[0-9]*" | tac)" inet6="$(ifconfig ${IFACE} | awk '$1 == "inet6" {print $2}')" # if [[ -z ${aliases} && -z ${inet6} && ! -e /var/run/dhcpcd-${IFACE}.pid ]]; then # ebegin "Bringing ${IFACE} down" # ifconfig ${IFACE} down &>/dev/null # eend 0 # return 0 # fi einfo "Bringing ${IFACE} down" # Stop aliases before primary interface. # Note this must be done in reverse order, since ifconfig eth0:1 # will remove eth0:2, etc. It might be sufficient to simply remove # the base interface but we're being safe here. for i in ${aliases} ${IFACE}; do # Delete all the inet6 addresses for this interface inet6="$(ifconfig ${i} | awk '$1 == "inet6" {print $3}')" if [[ -n ${inet6} ]]; then einfo " Removing inet6 addresses" for x in ${inet6}; do ebegin " ${IFACE} inet6 del ${x}" ifconfig ${i} inet6 del ${x} eend $? done fi # Stop DHCP (should be N/A for aliases) # Don't trust current configuration... investigate ourselves if /sbin/dhcpcd -z ${i} &>${devnull}; then ebegin " Releasing DHCP lease for ${IFACE}" for ((count = 0; count < 9; count = count + 1)); do /sbin/dhcpcd -z ${i} &>${devnull} || break sleep 1 done [[ ${count} -lt 9 ]] eend $? "Timed out" fi ebegin " Stopping ${i}" ifconfig ${i} down &>${devnull} eend 0 done # Always try to destroy the tuntap or bridge device # FIXME: Is there a way to check this ahead of time? [ -x /usr/bin/tunctl ] && /usr/bin/tunctl -d ${IFACE}&>${devnull} [ -x /sbin/brctl ] && /sbin/brctl delbr ${IFACE}&>${devnull} return 0 } start() { # These variables are set by setup_vars local status_IFACE vlans_IFACE dhcpcd_IFACE local -a ifconfig_IFACE routes_IFACE inet6_IFACE # Call user-defined preup function if it exists if [[ $(type -t preup) == function ]]; then einfo "Running preup function" preup ${IFACE} || { eerror "preup ${IFACE} failed" return 1 } fi # Start the primary interface and aliases setup_vars ${IFACE} iface_start ${IFACE} || return 1 # Start vlans local vlan for vlan in ${vlans_IFACE}; do /sbin/vconfig add ${IFACE} ${vlan} >${devnull} setup_vars ${IFACE}.${vlan} iface_start ${IFACE}.${vlan} done # Call user-defined postup function if it exists if [[ $(type -t postup) == function ]]; then einfo "Running postup function" postup ${IFACE} fi } stop() { # Call user-defined predown function if it exists if [[ $(type -t predown) == function ]]; then einfo "Running predown function" predown ${IFACE} fi # Don't depend on setup_vars since configuration might have changed. # Investigate current configuration instead. local vlan for vlan in $(ifconfig | grep -o "^${IFACE}\.[^ ]*"); do iface_stop ${vlan} /sbin/vconfig rem ${vlan} >${devnull} done iface_stop ${IFACE} || return 1 # always succeeds, btw # Call user-defined postdown function if it exists if [[ $(type -t postdown) == function ]]; then einfo "Running postdown function" postdown ${IFACE} fi } # vim:ts=4