#! /bin/sh # /etc/rc.d/rc.inet1 # This script is used to bring up the various network interfaces. # # @(#)/etc/rc.d/rc.inet1 10.2 Sun Jul 24 12:45:56 PDT 2005 (pjv) # # Modified by Michiel Broek to add IPv6 support and to migrate to # use the iproute2 utilities. ############################ # READ NETWORK CONFIG FILE # ############################ # Get the configuration information from /etc/rc.d/rc.inet1.conf: . /etc/rc.d/rc.inet1.conf ########### # LOGGING # ########### # If possible, log events in /var/log/messages: if [ -f /var/run/syslogd.pid -a -x /usr/bin/logger ]; then LOGGER=/usr/bin/logger else # output to stdout/stderr: LOGGER=/bin/cat fi ############################ # DETERMINE INTERFACE LIST # ############################ # Compose a list of interfaces from /etc/rc.d/rc.inet1.conf (with a maximum # of 6 interfaces, but you can easily enlarge the interface limit # - send me a picture of such a box :-). # If a value for IFNAME[n] is not set, we assume it is an eth'n' interface. # This way, the new script is compatible with older rc.inet1.conf files. # The IFNAME array will be used to determine which interfaces to bring up/down. MAXNICS=${MAXNICS:-6} i=0 IP6=0 while [ $i -lt $MAXNICS ]; do IFNAME[$i]=${IFNAME[$i]:=eth${i}} if [ -n "${IP6ADDR[$i]}" -o "${USE_DHCP6[0]}" = "yes" ]; then IP6=1 fi i=$(($i+1)) done if [ "$DEBUG_ETH_UP" = "yes" ]; then echo "/etc/rc.d/rc.inet1: List of interfaces: '${IFNAME[@]}'" | $LOGGER fi # if we need ipv6 and it isn't available yet, load it now. if [ $IP6 = 1 -a ! -e /proc/net/if_inet6 ]; then echo "/etc/rc.d/rc.inet1: /sbin/modprobe ipv6" | $LOGGER /sbin/modprobe ipv6 fi ###################### # LOOPBACK FUNCTIONS # ###################### # Function to bring up the loopback interface. If loopback is # already up, do nothing. lo_up() { if grep lo: /proc/net/dev 1> /dev/null ; then if ! /sbin/ip addr show lo | grep "inet " 1> /dev/null ; then echo "/etc/rc.d/rc.inet1: /sbin/ip addr add 127.0.0.1/8 dev lo" | $LOGGER /sbin/ip addr add 127.0.0.1/8 dev lo echo "/etc/rc.d/rc.inet1: /sbin/ip link set lo up" | $LOGGER /sbin/ip link set lo up echo "/etc/rc.d/rc.inet1: /sbin/ip route add 127.0.0.0/8 via 127.0.0.1 dev lo scope link" | $LOGGER /sbin/ip route add 127.0.0.0/8 via 127.0.0.1 dev lo scope link fi fi } # Function to take down the loopback interface: lo_down() { if grep lo: /proc/net/dev 1> /dev/null ; then echo "/etc/rc.d/rc.inet1: /sbin/ip link set lo down" | $LOGGER /sbin/ip link set lo down echo "/etc/rc.d/rc.inet1: /sbin/ip addr flush dev lo" | $LOGGER /sbin/ip addr flush dev lo fi } ####################### # INTERFACE FUNCTIONS # ####################### # Function to assemble a bridge interface. br_open() { # argument is 'i' - the position of this interface in the IFNAME array. echo "/etc/rc.d/rc.inet1: /sbin/ip link add ${IFNAME[$1]} type bridge" | $LOGGER /sbin/ip link add ${IFNAME[$1]} type bridge ## Should be 0 for a dhcp client if [ "${BRIDGE_FORWARDDELAY[$i]}" ]; then echo "/etc/rc.d/rc.inet1: /sbin/brctl setfd ${IFNAME[$1]} ${BRIDGE_FORWARDDELAY[$i]}" | $LOGGER /sbin/brctl setfd ${IFNAME[$1]} ${BRIDGE_FORWARDDELAY[$i]} fi for BRIF in $(echo ${BRNICS[$1]}); do echo "/etc/rc.d/rc.inet1: /sbin/ip link set $BRIF down" | $LOGGER /sbin/ip link set $BRIF down echo "/etc/rc.d/rc.inet1: /sbin/ip addr flush dev $BRIF" | $LOGGER /sbin/ip addr flush dev $BRIF echo "/etc/rc.d/rc.inet1: /sbin/ip addr add 0.0.0.0 dev $BRIF" | $LOGGER /sbin/ip addr add 0.0.0.0 dev $BRIF echo "/etc/rc.d/rc.inet1: /sbin/ip link set $BRIF promisc on master ${IFNAME[$1]} up" | $LOGGER /sbin/ip link set $BRIF promisc on master ${IFNAME[$1]} up done } # Function to disassemble a bridge interface. br_close() { # argument is 'i' - the position of this interface in the IFNAME array. #for BRIF in $(echo ${BRNICS[$1]}); do for BRIF in $(ls --indicator-style=none /sys/class/net/${IFNAME[$1]}/brif/) do echo "/etc/rc.d/rc.inet1: /sbin/ip link set dev $BRIF nomaster" | $LOGGER /sbin/ip link set dev $BRIF nomaster done echo "/etc/rc.d/rc.inet1: /sbin/ip link set ${IFNAME[$1]} down" | $LOGGER /sbin/ip link set ${IFNAME[$1]} down echo "/etc/rc.d/rc.inet1: /sbin/ip addr flush dev ${IFNAME[$1]}" | $LOGGER /sbin/ip addr flush dev ${IFNAME[$1]} echo "/etc/rc.d/rc.inet1: /sbin/ip link del ${IFNAME[$1]} type bridge" | $LOGGER /sbin/ip link del ${IFNAME[$1]} type bridge } # Function to bring up a network interface. If the interface is # already up or does not yet exist (perhaps because the kernel driver # is not loaded yet), do nothing. if_up() { # Determine position 'i' of this interface in the IFNAME array: i=0 while [ $i -lt $MAXNICS ]; do [ "${IFNAME[$i]}" = "${1}" ] && break i=$(($i+1)) done # If the interface is a bridge, then create it first: [ -n "${BRNICS[$i]}" ] && br_open $i # If the interface isn't in the kernel yet (but there's an alias for it in # modules.conf), then it should be loaded first: if ! grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then # no interface yet if /sbin/modprobe -c | grep -v "^#" | grep -w "alias ${1}" | grep -vw "alias ${1} off" > /dev/null ; then echo "/etc/rc.d/rc.inet1: /sbin/modprobe ${1}" | $LOGGER /sbin/modprobe ${1} fi fi if grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then # interface exists # Don't listen to IPv6 RA if we don't need it and turn off ipv6. if [ -d "/proc/sys/net/ipv6" ]; then sysctl -q -w "net.ipv6.conf.${1}.accept_ra=0" sysctl -q -w "net.ipv6.conf.${1}.disable_ipv6=1" fi if ! grep ${1}: /proc/net/dev 1> /dev/null || \ ! /sbin/ip addr show ${1} up | grep "inet " 1> /dev/null ; then # interface not up or not configured if [ ! "${HWADDR[$i]}" = "" ]; then # Set hardware address _before_ the interface goes up: echo "/etc/rc.d/rc.inet1: /sbin/ip link set ${1} address ${HWADDR[$i]}" | $LOGGER /sbin/ip link set ${1} address ${HWADDR[$i]} fi if [ ! "${MTU[$i]}" = "" ]; then # Set MTU to something else than 1500 echo "/etc/rc.d/rc.inet1: /sbin/ip link set ${1} mtu ${MTU[$i]}" | $LOGGER /sbin/ip link set ${1} mtu ${MTU[$i]} fi if [ -x /etc/rc.d/rc.wireless ]; then . /etc/rc.d/rc.wireless ${1} start # Initialize any wireless parameters fi if [ "${USE_DHCP[$i]}" = "yes" ]; then # use DHCP to bring interface up # Clear DHCP_OPTIONS before adding new options to it: unset DHCP_OPTIONS # Set DHCP_OPTIONS for this interface: [ ${DHCP_HOSTNAME[$i]} ] && DHCP_OPTIONS="-h ${DHCP_HOSTNAME[$i]}" [ "${DHCP_KEEPRESOLV[$i]}" = "yes" ] && DHCP_OPTIONS="$DHCP_OPTIONS -C resolv.conf" [ "${DHCP_KEEPNTP[$i]}" = "yes" ] && DHCP_OPTIONS="$DHCP_OPTIONS -C ntp.conf" [ "${DHCP_KEEPGW[$i]}" = "yes" ] && DHCP_OPTIONS="$DHCP_OPTIONS -G" [ "${DHCP_DEBUG[$i]}" = "yes" ] && DHCP_OPTIONS="$DHCP_OPTIONS -d" [ "${DHCP_NOIPV4LL[$i]}" = "yes" ] && DHCP_OPTIONS="$DHCP_OPTIONS -L" [ ${DHCP_IPADDR[$i]} ] && DHCP_OPTIONS="$DHCP_OPTIONS -r ${DHCP_IPADDR[$i]}" echo "Polling for DHCP server on interface ${1}:" # If you set a timeout, you get one, even if the kernel doesn't think that # your device is connected, in case /sys isn't right (which it usually isn't # except right after the device is loaded, when it usually is): #### (start commented out) # This is deactivated for now since the kernel has been returning incorrect # results concerning whether the interface carrier is detected. #if [ "${DHCP_TIMEOUT[$i]}" = "" ]; then # ifconfig ${1} up && sleep 1 # CONNSTATUS="$(cat /sys/class/net/${1}/carrier 2> /dev/null)" # ifconfig ${1} down # if [ "$CONNSTATUS" = "0" ]; then # # The kernel has just told us the cable isn't even plugged in, but we will # # give any DHCP server a short chance to reply anyway: # echo "No carrier detected on ${1}. Reducing DHCP timeout to 10 seconds." # DHCP_TIMEOUT[$i]=10 # fi #fi #### (end commented out) # 10 seconds should be a reasonable default DHCP timeout. 30 was too much. echo "/etc/rc.d/rc.inet1: /sbin/dhcpcd -t ${DHCP_TIMEOUT[$i]:-10} ${DHCP_OPTIONS} ${1}" | $LOGGER /sbin/dhcpcd -t ${DHCP_TIMEOUT[$i]:-10} ${DHCP_OPTIONS} ${1} if [ "${USE_DHCP6[$i]}" = "yes" -a -x /sbin/dhclient ]; then # use DHCPv6 to bring interface up # Turn ipv6 and RA on for this interface sysctl -q -w "net.ipv6.conf.${1}.disable_ipv6=0" sysctl -q -w "net.ipv6.conf.${1}.accept_ra=1" echo "/etc/rc.d/rc.inet1: /sbin/dhclient -6 -e TIMEOUT=${DHCP_TIMEOUT[$i]:-10} ${1}" | $LOGGER echo "/etc/rc.d/rc.inet1: /sbin/dhclient -6 -e TIMEOUT=${DHCP_TIMEOUT[$i]:-10} ${1}" /sbin/dhclient -6 -e TIMEOUT=${DHCP_TIMEOUT[$i]:-10} ${1} else # Dynamic IPv4 interface but no DHCPv6, allow IPv6 autoconfigure. if [ -d "/proc/sys/net/ipv6" ]; then sysctl -q -w "net.ipv6.conf.${1}.accept_ra=1" sysctl -q -w "net.ipv6.conf.${1}.disable_ipv6=0" fi fi else # bring up interface using a static IP address if [ ! "${IPADDR[$i]}" = "" ]; then # skip unconfigured interfaces # Set up the network card: echo "/etc/rc.d/rc.inet1: /sbin/ip addr add ${IPADDR[$i]}/${NETMASK[$i]} brd + dev ${1}" | $LOGGER /sbin/ip addr add ${IPADDR[$i]}/${NETMASK[$i]} brd + dev ${1} echo "/etc/rc.d/rc.inet1: /sbin/ip link set ${1} up" | $LOGGER /sbin/ip link set ${1} up # IPv6 Scope:global address if [ ! "${IP6ADDR[$i]}" = "" ]; then # Turn ipv6 on for this interface sysctl -q -w "net.ipv6.conf.${1}.disable_ipv6=0" # Add one or more IPv6 addresses. for addr in ${IP6ADDR[$i]}; do echo "/etc/rc.d/rc.inet1: /sbin/ip addr add ${addr} dev ${1}" | $LOGGER /sbin/ip addr add ${addr} dev ${1} done fi else if [ "$DEBUG_ETH_UP" = "yes" ]; then echo "/etc/rc.d/rc.inet1: ${1} interface is not configured in /etc/rc.d/rc.inet1.conf" | $LOGGER fi fi fi else if [ "$DEBUG_ETH_UP" = "yes" ]; then echo "/etc/rc.d/rc.inet1: ${1} is already up, skipping" | $LOGGER fi fi else if [ "$DEBUG_ETH_UP" = "yes" ]; then echo "/etc/rc.d/rc.inet1: ${1} interface does not exist (yet)" | $LOGGER fi fi } # Function to take down a network interface: if_down() { # Determine position 'i' of this interface in the IFNAME array: i=0 while [ $i -lt $MAXNICS ]; do [ "${IFNAME[$i]}" = "${1}" ] && break i=$(($i+1)) done if grep `echo ${1}: | cut -f 1 -d :`: /proc/net/dev 1> /dev/null ; then if [ "${USE_DHCP[$i]}" = "yes" ]; then if [ "${USE_DHCP6[$i]}" = "yes" -a -e /var/run/dhclient6.pid ]; then echo "/etc/rc.d/rc.inet1: /sbin/dhclient -6 -r ${1}" | $LOGGER /sbin/dhclient -6 -r ${1} fi echo "/etc/rc.d/rc.inet1: /sbin/dhcpcd -k -d ${1}" | $LOGGER /sbin/dhcpcd -k -d ${1} 2> /dev/null sleep 1 fi # Shutdown interface, else a restart doesn't work. echo "/etc/rc.d/rc.inet1: /sbin/ip link set ${1} down" | $LOGGER /sbin/ip link set ${1} down echo "/etc/rc.d/rc.inet1: /sbin/ip addr flush dev ${1}" | $LOGGER /sbin/ip addr flush dev ${1} if [ -x /etc/rc.d/rc.wireless ]; then . /etc/rc.d/rc.wireless ${1} stop # Kill wireless daemons if any. fi # If the interface is a bridge, then destroy it now: [ -n "${BRNICS[$i]}" ] && br_close $i fi } ##################### # GATEWAY FUNCTIONS # ##################### # Function to bring up the gateway if there is not yet a default route: gateway_up() { if ! /sbin/ip -4 route show | grep "^default" 1> /dev/null ; then if [ ! "$GATEWAY" = "" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip route add 0.0.0.0/0 via ${GATEWAY} metric 1" | $LOGGER /sbin/ip route add 0.0.0.0/0 via ${GATEWAY} metric 1 fi fi if ! /sbin/ip -6 route show | grep "^default" 1> /dev/null ; then if [ ! "$GATEWAY6" = "" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip route add ::/0 via ${GATEWAY6} metric 1" | $LOGGER /sbin/ip route add ::/0 via ${GATEWAY6} metric 1 fi fi } # Function to take down an existing default gateway: gateway_down() { if /sbin/ip -4 route show | grep "^default" 1> /dev/null ; then if [ ! "$GATEWAY" = "" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip route del 0.0.0.0/0 via ${GATEWAY}" | $LOGGER /sbin/ip route del 0.0.0.0/0 via ${GATEWAY} fi fi if /sbin/ip -6 route show | grep "^default" 1> /dev/null ; then if [ ! "$GATEWAY6" = "" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip route del ::/0 via ${GATEWAY6}" | $LOGGER /sbin/ip route del ::/0 via ${GATEWAY6} fi fi } # Function to start the network: start() { # pre hook [ -x /etc/rc.d/rc.inet1-pre ] && /etc/rc.d/rc.inet1-pre start lo_up for i in ${IFNAME[@]} ; do if_up $i done # main hook [ -x /etc/rc.d/rc.inet1-main ] && /etc/rc.d/rc.inet1-main start gateway_up # post hook [ -x /etc/rc.d/rc.inet1-post ] && /etc/rc.d/rc.inet1-post start } # Function to stop the network: stop() { # post hook [ -x /etc/rc.d/rc.inet1-post ] && /etc/rc.d/rc.inet1-post stop gateway_down # main hook [ -x /etc/rc.d/rc.inet1-main ] && /etc/rc.d/rc.inet1-main stop for i in ${IFNAME[@]} ; do if_down $i done lo_down # pre hook [ -x /etc/rc.d/rc.inet1-pre ] && /etc/rc.d/rc.inet1-pre stop } ############ ### MAIN ### ############ case "$1" in 'start') # "start" brings up all configured interfaces: start ;; 'stop') # "stop" takes down all configured interfaces: stop ;; 'restart') # "restart" restarts the network: stop start ;; *_start) # Example: "eth1_start" will start the specified interface 'eth1' INTERFACE=`echo $1 | /bin/cut -d '_' -f 1` if_up $INTERFACE gateway_up ;; *_stop) # Example: "eth0_stop" will stop the specified interface 'eth0' INTERFACE=`echo $1 | /bin/cut -d '_' -f 1` if_down $INTERFACE ;; *_restart) # Example: "wlan0_restart" will take 'wlan0' down and up again INTERFACE=`echo $1 | /bin/cut -d '_' -f 1` if_down $INTERFACE sleep 1 if_up $INTERFACE gateway_up ;; 'up') # "up" does the same thing as "start" start ;; 'down') # "down" does the same thing as "stop" stop ;; *_up) # "*_up" does the same thing as "*_start" INTERFACE=`echo $1 | /bin/cut -d '_' -f 1` if_up $INTERFACE gateway_up ;; *_down) # "*_down" does the same thing as "*_stop" INTERFACE=`echo $1 | /bin/cut -d '_' -f 1` if_down $INTERFACE ;; *) # The default is to bring up all configured interfaces: start esac # End of /etc/rc.d/rc.inet1