#!/bin/bash # /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) ############################ # 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 ] && [ -x /usr/bin/logger ]; then LOGGER=/usr/bin/logger else # output to stdout/stderr: LOGGER=/bin/cat fi # Handy wrapper for verbose logging debug_log() { if [ "$DEBUG_ETH_UP" = "yes" ]; then echo "/etc/rc.d/rc.inet1: $*" | $LOGGER 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 while [ $i -lt $MAXNICS ]; do IFNAME[$i]=${IFNAME[$i]:=eth${i}} i=$(($i+1)) done debug_log "List of interfaces: '${IFNAME[*]}'" ###################### # LOOPBACK FUNCTIONS # ###################### # Function to bring up the loopback interface. If loopback is # already up, do nothing. lo_up() { if [ -e /sys/class/net/lo ]; then if ! /sbin/ip link show dev lo | grep -wq -e "state UP" -e "state UNKNOWN" ; then echo "/etc/rc.d/rc.inet1: /sbin/ip address add 127.0.0.1/8 dev lo" | $LOGGER /sbin/ip address add 127.0.0.1/8 dev lo /sbin/ip link set dev lo up echo "/etc/rc.d/rc.inet1: /sbin/ip route add 127.0.0.0/8 dev lo" | $LOGGER /sbin/ip route add 127.0.0.0/8 dev lo fi fi } # Function to take down the loopback interface: lo_down() { if [ -e /sys/class/net/lo ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip link set dev lo down" | $LOGGER /sbin/ip link set dev lo down fi } ####################### # INTERFACE FUNCTIONS # ####################### # Function to create virtual interfaces virtif_create() { # argument is 'i' - the position of this interface in the VIRTIFNAME array. # this loop goes from i=0 to i=number_of_configured_virtual_interfaces_minus_one # which means it doesn't do anything if there are none. for i in $(seq 0 $((${#VIRTIFNAME[@]} - 1))); do /sbin/ip tuntap add dev ${VIRTIFNAME[$i]} mode ${VIRTIFTYPE[$i]} user ${VIRTIFUSER[$i]} group ${VIRTIFGROUP[$i]} done } # Function to destory virtual interfaces virtif_destroy() { # argument is 'i' - the position of this interface in the VIRTIFNAME array. for i in $(seq 0 $((${#VIRTIFNAME[@]} - 1))); do /sbin/ip tuntap del dev ${VIRTIFNAME[$i]} mode ${VIRTIFTYPE[$i]} done } # Function to assemble a bridge interface. br_open() { # argument is 'i' - the position of this interface in the IFNAME array. /sbin/ip link add name ${IFNAME[$1]} type bridge for BRIF in ${BRNICS[$1]}; do /sbin/ip link set dev $BRIF down /sbin/ip address add 0.0.0.0 dev $BRIF /sbin/ip link set dev $BRIF master ${IFNAME[$1]} /sbin/ip link set dev $BRIF up done /sbin/ip link set dev ${IFNAME[$1]} up } # Function to disassemble a bridge interface. br_close() { /sbin/ip link set dev ${IFNAME[$1]} down # argument is 'i' - the position of this interface in the IFNAME array. #for BRIF in ${BRNICS[$1]}; do for BRIF in $(ls --indicator-style=none /sys/class/net/${IFNAME[$1]}/brif/) do /sbin/ip link set dev $BRIF nomaster done /sbin/ip link set dev ${IFNAME[$1]} down /sbin/ip link del ${IFNAME[$1]} } # 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 "i" is greater or equal to "MAXNICS" at this point, it means we didn't # find an entry in IFNAME array corresponding to "$1", which likely means # there are more interfaces configured than MAXNICS. Let's err on the # side of caution and do nothing instead of possibly doing the wrong thing. if [ $i -ge $MAXNICS ]; then echo "/etc/rc.d/rc.inet1: skipping ${1}, you might need to increase MAXNICS" | $LOGGER return fi # If the interface is a bridge, then create it first: [ -n "${BRNICS[$i]}" ] && br_open $i # Skip unconfigured interfaces: if [ -z "${IPADDR[$i]}" ] && [ "${USE_DHCP[$i]}" != "yes" ] && [ -z "${IPADDR6[$i]}" ] && \ [ "${USE_DHCP6[$i]}" != "yes" ] && [ "${USE_STATELESS6[$i]}" != "yes" ]; then debug_log "skipping ${1} early, interface is not configured in /etc/rc.d/rc.inet1.conf" return 0 fi # 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 [ ! -e /sys/class/net/${1%%:*} ]; 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 [ -e /sys/class/net/${1%%:*} ]; then # interface exists if ! /sbin/ip address show scope global dev ${1} 2>/dev/null | grep -Ewq '(inet|inet6)' || \ ! /sbin/ip link show dev ${1} | grep -wq "state UP" ; then # interface not up or not configured # Set hardware address _before_ the interface goes up: if [ -n "${HWADDR[$i]}" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip link set dev ${1} address ${HWADDR[$i]}" | $LOGGER /sbin/ip link set dev ${1} address ${HWADDR[$i]} fi # Initialize any wireless parameters: if [ -x /etc/rc.d/rc.wireless ]; then . /etc/rc.d/rc.wireless ${1} start fi IF_UP=0 # Slackware historically favours DHCP over fixed IP to configure interfaces, so keep that tradition: if [ "${USE_DHCP[$i]}" = "yes" ] || [ "${USE_DHCP6[$i]}" = "yes" ]; then # use dhcpcd to bring interface up # Disable v6 IP auto configuration before trying to set up the interface: [ "${USE_DHCP6[$i]}" = "yes" ] && echo "0" >/proc/sys/net/ipv6/conf/$1/autoconf # Declare DHCP_OPTIONS array before adding new options to it: declare -a DHCP_OPTIONS=() # Set DHCP_OPTIONS for this interface: if [ "${USE_DHCP[$i]}" = "yes" ] && [ "${USE_DHCP6[$i]}" != "yes" ]; then # only try v4 dhcp DHCP_OPTIONS+=("-4") elif [ "${USE_DHCP[$i]}" != "yes" ] && [ "${USE_DHCP6[$i]}" = "yes" ]; then # only try v6 dhcp DHCP_OPTIONS+=("-6") fi [ -n "${DHCP_HOSTNAME[$i]}" ] && DHCP_OPTIONS+=("-h" "${DHCP_HOSTNAME[$i]}") [ "${DHCP_KEEPRESOLV[$i]}" = "yes" ] && DHCP_OPTIONS+=("-C" "resolv.conf") [ "${DHCP_KEEPNTP[$i]}" = "yes" ] && DHCP_OPTIONS+=("-C" "ntp.conf") [ "${DHCP_KEEPGW[$i]}" = "yes" ] && DHCP_OPTIONS+=("-G") [ "${DHCP_DEBUG[$i]}" = "yes" ] && DHCP_OPTIONS+=("-d") [ "${DHCP_NOIPV4LL[$i]}" = "yes" ] && DHCP_OPTIONS+=("-L") [ -n "${DHCP_IPADDR[$i]}" ] && DHCP_OPTIONS+=("-r" "${DHCP_IPADDR[$i]}") echo "Polling for DHCP server on interface ${1}:" # 15 seconds should be a reasonable default DHCP timeout. 30 was too much. echo "/etc/rc.d/rc.inet1: /sbin/dhcpcd -L -t ${DHCP_TIMEOUT[$i]:-15} ${DHCP_OPTIONS[@]} ${1}" | $LOGGER if /sbin/dhcpcd -L -t "${DHCP_TIMEOUT[$i]:-15}" "${DHCP_OPTIONS[@]}" ${1}; then IF_UP=1 else echo "/etc/rc.d/rc.inet1: failed to obtain DHCP lease for ${1}" | $LOGGER fi fi if [ "${USE_DHCP[$i]}" != "yes" ] && [ -n "${IPADDR[$i]}" ]; then # use a fixed v4 IP to bring interface up if [ -z "${NETMASK[$i]}" ]; then echo "/etc/rc.d/rc.inet1: no NETMASK set for ${1} - assuming /24 (aka, 255.255.255.0)" | $LOGGER NETMASK[$i]="24" fi echo "/etc/rc.d/rc.inet1: /sbin/ip -4 address add ${IPADDR[$i]}/${NETMASK[$i]##/} broadcast + dev ${1}" | $LOGGER if /sbin/ip -4 address add ${IPADDR[$i]}/${NETMASK[$i]##/} broadcast + dev ${1} && \ /sbin/ip link set dev ${1} up; then IF_UP=1 else echo "/etc/rc.d/rc.inet1: failed to a set IP ${IPADDR[$i]} for ${1}" | $LOGGER fi fi if [ "${USE_DHCP6[$i]}" != "yes" ] && [ -n "${IPADDR6[$i]}" ]; then # use a fixed v6 IP to bring up/add to the interface # Disable v6 IP auto configuration before trying to configure with a fixed IP: echo "0" >/proc/sys/net/ipv6/conf/$1/autoconf if [ -z "${NETMASK6[$i]}" ]; then echo "/etc/rc.d/rc.inet1: no NETMASK6 set for ${1} - assuming /64" | $LOGGER NETMASK6[$i]="64" fi echo "/etc/rc.d/rc.inet1: /sbin/ip -6 address add ${IPADDR6[$i]}/${NETMASK6[$i]##/} dev ${1}" | $LOGGER if /sbin/ip -6 address add ${IPADDR6[$i]}/${NETMASK6[$i]##/} dev ${1} && \ /sbin/ip link set dev ${1} up; then IF_UP=1 else echo "/etc/rc.d/rc.inet1: failed to a set IP ${IPADDR6[$i]} for ${1}" | $LOGGER fi fi if [ "${USE_DHCP6[$i]}" != "yes" ] && [ -z "${IPADDR6[$i]}" ] && \ [ "${USE_STATELESS6[$i]}" = "yes" ]; then # interface should configure itself via stateless RA auto config: echo "/etc/rc.d/rc.inet1: using stateless Router Advertisement auto configuration for ${1}" | $LOGGER # Enable accepting of router advertisment packets, and auto configuration of interfaces: echo "1" >/proc/sys/net/ipv6/conf/$1/accept_ra echo "1" >/proc/sys/net/ipv6/conf/$1/autoconf # Bring the interface up: /sbin/ip link set dev ${1} up echo "Waiting for Router Announcement on ${1}..." for ((j = 20; j--;)); do # wait a max of 10 seconds for the interface to configure /sbin/ip -6 address show dynamic dev ${1} 2>/dev/null | grep -Ewq 'inet6' && break sleep 0.5 done if ! /sbin/ip -6 address show dynamic dev ${1} 2>/dev/null | grep -Ewq 'inet6'; then echo "/etc/rc.d/rc.inet1: failed to auto configure ${1} after 10 seconds" | $LOGGER else IF_UP=1 fi # Don't continue on to alias configuration. return fi if [ "${USE_DHCP[$i]}" != "yes" ] && [ "${USE_DHCP6[$i]}" != "yes" ] && [ -n "${IPADDR6[$i]}" ] && \ [ -z "${IPADDR6[$i]}" ]; then # interface is unconfigured debug_log "${1} interface is not configured in /etc/rc.d/rc.inet1.conf" return fi # Add extra IPv4 and v6 addresses, if defined, to the interface only if it came up: if (($IF_UP == 1)); then if [ -n "${IPALIASES[$i]}" ]; then num=0 for ipalias in ${IPALIASES[$i]}; do ip="${ipalias%/*}" nm="${ipalias#*/}" [ -z "$nm" ] || [ "$ip" == "$nm" ] && nm="24" echo "/etc/rc.d/rc.inet1: /sbin/ip -4 address add ${ip}/${nm} dev ${1} label ${1}:${num}" | $LOGGER /sbin/ip -4 address add ${ip}/${nm} dev ${1} label ${1}:${num} num=$(($num + 1)) done fi if [ -n "${IPALIASES6[$i]}" ]; then for ipalias in ${IPALIASES6[$i]}; do ip="${ipalias%/*}" nm="${ipalias#*/}" [ -z "$nm" ] || [ "$ip" == "$nm" ] && nm="64" # Unlike IPv4, v6 addresses don't get a label: echo "/etc/rc.d/rc.inet1: /sbin/ip -6 address add ${ip}/${nm} dev ${1}" | $LOGGER /sbin/ip -6 address add ${ip}/${nm} dev ${1} done fi fi # Force an MTU (possibly over-riding that set by DHCP): if [ -n "${MTU[$i]}" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip link set dev ${1} mtu ${MTU[$i]}" | $LOGGER /sbin/ip link set dev ${1} mtu ${MTU[$i]} fi # Set promiscuous mode on the interface: if [ "${PROMISCUOUS[$i]}" = "yes" ]; then /sbin/ip link set dev ${1} promisc on fi else debug_log "${1} is already up, skipping" fi else debug_log "${1} interface does not exist (yet)" 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 [ $i -ge $MAXNICS ]; then echo "/etc/rc.d/rc.inet1: skipping ${1}, you might need to increase MAXNICS" | $LOGGER return fi if [ -e /sys/class/net/${1%%:*} ]; then if [ "${USE_DHCP[$i]}" = "yes" ] || [ "${USE_DHCP6[$i]}" = "yes" ]; then # take down dhcpcd # When using -k, dhcpcd requires some command line options to match those used to invoke it: if [ "${USE_DHCP[$i]}" = "yes" ] && [ "${USE_DHCP6[$i]}" != "yes" ]; then # only v4 dhcp DHCP_OPTIONS="-4" elif [ "${USE_DHCP[$i]}" != "yes" ] && [ "${USE_DHCP6[$i]}" = "yes" ]; then # only v6 dhcp DHCP_OPTIONS="-6" fi echo "/etc/rc.d/rc.inet1: /sbin/dhcpcd $DHCP_OPTIONS -k -d ${1}" | $LOGGER if ! /sbin/dhcpcd $DHCP_OPTIONS -k -d ${1} 2>/dev/null; then echo "/etc/rc.d/rc.inet1: failed to stop dhcpcd for interface ${1}" | $LOGGER fi sleep 2 fi if [ -n "${IPADDR[$i]}" ] || [ -n "${IPADDR6[$i]}" ]; then # flush any fixed IPs echo "/etc/rc.d/rc.inet1: /sbin/ip address flush dev ${1}" | $LOGGER /sbin/ip address flush dev ${1} fi if [ "${USE_STATELESS6[$i]}" = "yes" ]; then # disable stateless RA auto config # Disable auto configuration of the interface: echo "/etc/rc.d/rc.inet1: disabling stateless Router Advertisement auto configuration on ${1}" | $LOGGER echo "0" >/proc/sys/net/ipv6/conf/$1/autoconf sleep 1 fi # Bring the interface down: echo "/etc/rc.d/rc.inet1: /sbin/ip link set dev ${1} down" | $LOGGER /sbin/ip link set dev ${1} down # One final flush of the interface: /sbin/ip address flush dev ${1} # Kill wireless daemons if any: if [ -x /etc/rc.d/rc.wireless ]; then . /etc/rc.d/rc.wireless ${1} stop fi # If the interface is a bridge, then destroy it now: if [ -n "${BRNICS[$i]}" ]; then br_close $i fi fi } ##################### # GATEWAY FUNCTIONS # ##################### # Function to bring up the gateway if there is not yet a default route: gateway_up() { if ! /sbin/ip route show | grep -wq default ; then if [ -n "$GATEWAY" ]; then echo "/etc/rc.d/rc.inet1: /sbin/ip route add default via ${GATEWAY}" | $LOGGER /sbin/ip route add default via ${GATEWAY} | $LOGGER fi fi } # Function to take down an existing default gateway: gateway_down() { if /sbin/ip route show | grep -wq default ; then echo "/etc/rc.d/rc.inet1: /sbin/ip route del default" | $LOGGER /sbin/ip route del default fi } # Function to start the network: start() { lo_up virtif_create for i in "${IFNAME[@]}" ; do if_up $i done gateway_up } # Function to stop the network: stop() { gateway_down for i in "${IFNAME[@]}" ; do if_down $i done virtif_destroy lo_down } ############ ### MAIN ### ############ case "$1" in start|up) # "start" (or "up") brings up all configured interfaces: start ;; stop|down) # "stop" (or "down") takes down all configured interfaces: stop ;; restart) # "restart" restarts the network: stop start ;; lo_start|lo_up) # Start the loopback interface: lo_up ;; lo_stop|lo_down) # Stop the loopback interface: lo_down ;; *_start|*_up) # Example: "eth1_start" (or "eth1_up") will start the specified interface 'eth1' INTERFACE=$(echo $1 | /bin/cut -d '_' -f 1) if_up $INTERFACE gateway_up ;; *_stop|*_down) # Example: "eth0_stop" (or "eth0_down") 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 ;; *) # The default is to bring up all configured interfaces: start esac # End of /etc/rc.d/rc.inet1