#!/bin/sh #============================================================================ # multinet-common.sh # # Version = 3.0.1 # Date = 2008-02-07 # # Maintainer(s) = Ron Terry - ron (at) pronetworkconsulting (dot) com # # The latest version can be found at: # # http://pronetworkconsulting.com/linux/scripts/network-multinet.html # # Description: # # Function library for network-multinet and all other multinet related # network scripts # # Vars (should not need to be changed): # # BRIDGE_NAME -Name of bridged networks # HOSTONLY_NAME -Name of hostonly networks # NAT_NAME -Name of NAT networks # ROUTE_NAME -Name of routed networks # NOHOST_NAME -Name of nohost networks # EMPTY_NAME -Name of empty networks # # DEFAULT_DEV -default network interface name # DEFAULT_PDEV -default pysical interface name # DEFAULT_VDEV -default virtual interface name # # NETWORKTAB -File that contains a list of the virtual networks that # have been created (typically /etc/xen/networktab) # # NETWORK_SAVE_PATH -Path to save network configuration information in # IPTABLES_SAVE_FILE -File in which to save backed-up iptables rules so that # they may be restored when the script is stopped # SF2_SYSCONFIG_FILE -Path to the /etc/sysconfig/ file for SuSEfirewall2 # # PLUGIN_DIR -directory containing the plug-in network configuration # scrips # # DHCPD_CONF_FILE -Path to the dhcpd config file # DHCP_SYSCONFIG_FILE -Path to the dhcpd sysconfig file # # IFCFG_FILE_DIR -Directory that contains the network interface # configuration files (ifcfg-xxxx) # #============================================================================ BRIDGE_NAME="xenbr" HOSTONLY_NAME="xenhost" NAT_NAME="xennat" ROUTE_NAME="xenroute" NOHOST_NAME="xennohost" EMPTY_NAME="xenempty" DEFAULT_DEV="eth" DEFAULT_PDEV="peth" DEFAULT_VDEV="veth" NETWORKTAB="/etc/xen/networktab" SCRIPT_PATH="/etc/xen/scripts" NETWORK_SAVE_PATH="/var/lib/xend/network-save" IPTABLES_SAVE_FILE="$NETWORK_SAVE_PATH/iptables-save" SF2_SYSCONFIG_FILE="/etc/sysconfig/SuSEfirewall2" PLUGIN_DIR="/etc/xen/scripts/multinet.d" DHCPD_CONF_FILE="/etc/dhcpd.conf" DHCP_SYSCONFIG_FILE="/etc/sysconfig/dhcpd" IFCFG_FILE_DIR="/etc/sysconfig/network" #### Script Functions ##################################################### #***** Generic Functions ************************************************** evalVariables() { for arg in "$@" do if expr 'index' "$arg" '=' '>' '1' >/dev/null then eval "$arg" fi done } findCommand() { for arg in "$@" do if ! expr 'index' "$arg" '=' >/dev/null then command="$arg" return fi done } #***** Firewall/Routing Functions ***************************************** find_default_interface() { local DEV=$1 case ${DEV} in default) DEV=`ip route list | awk '/^default / { print $NF }'` ;; *) if ! ip addr show | grep " ${DEV}:" then #echo "${DEV} does not exist. Using default." DEV=`ip route show | awk '/^default / { print $NF }'` fi ;; esac echo ${DEV} } find_nat_external_interface() { #------------------------------------------------------------------ # Find the external NAT network interface #------------------------------------------------------------------ case $NAT_EXTERNAL_INTERFACE in default) NAT_EXTERNAL_INTERFACE=`ip route show | awk '/^default / { print $NF }'` ;; *) if ! [ ip addr show | grep " $NAT_EXTERNAL_INTERFACE:" ] then #echo "$NAT_EXTERNAL_INTERFACE does not exist. Using default." NAT_EXTERNAL_INTERFACE=`ip route show | awk '/^default / { print $NF }'` fi ;; esac } configure_routing() { # Saves and restores the ip forward and Network Address Translation state # that exist before the script runs # # The values start|stop are passed into this function and it behaves respectivly case $1 in start) #------------------------------------------------------------------ # Determine the initial state of the ip_forward parameter #------------------------------------------------------------------ case `cat /proc/sys/net/ipv4/ip_forward` in 0) INIT_IP_FWD="off" echo "0" > $NETWORK_SAVE_PATH/init_ip_fwd_state ;; 1) INIT_IP_FWD="on" echo "1" > $NETWORK_SAVE_PATH/init_ip_fwd_state ;; esac #------------------------------------------------------------------ # Determine if we need to enable ip_forward #------------------------------------------------------------------ if echo $NETWORK_LIST | grep -qE "(nat|NAT|route|ROUTE)" then IP_FWD="on" echo "" echo "============================================================" echo "Enabling IP Forwarding" echo "============================================================" echo 1 > /proc/sys/net/ipv4/ip_forward else IP_FWD="off" echo "" echo "============================================================" echo "Disabling IP Forwarding" echo "============================================================" echo 0 > /proc/sys/net/ipv4/ip_forward fi ;; stop) #------------------------------------------------------------------ # Set the ip_forward value back to its original state #------------------------------------------------------------------ echo "" echo "============================================================" echo "Restoring IP Forwarding to its original state" echo "============================================================" case `cat $NETWORK_SAVE_PATH/init_ip_fwd_state` in 0) #echo "ip_forward = 0" echo "0" > /proc/sys/net/ipv4/ip_forward ;; 1) #echo "ip_forward = 0" echo "1" > /proc/sys/net/ipv4/ip_forward ;; *) #echo "Original state unknown. Using default value." #echo "ip_forward = 0" echo "0" > /proc/sys/net/ipv4/ip_forward ;; esac #------------------------------------------------------------------ # Clean up init_ip_fwd_state file #------------------------------------------------------------------ rm -f $NETWORK_SAVE_PATH/init_ip_fwd_state ;; esac } configure_nat() { #------------------------------------------------------------------ # Find the external NAT network interface #------------------------------------------------------------------ #find_nat_external_interface NAT_EXTERNAL_INTERFACE=`find_default_interface $NAT_EXTERNAL_INTERFACE` #case $NAT_EXTERNAL_INTERFACE in # default) # NAT_EXTERNAL_INTERFACE=`ip route show | awk '/^default / { print $NF }'` # ;; # *) # if ! [ ip addr show | grep " $NAT_EXTERNAL_INTERFACE:" ] # then # #echo "$NAT_EXTERNAL_INTERFACE does not exist. Using default." # NAT_EXTERNAL_INTERFACE=`ip route show | awk '/^default / { print $NF }'` # fi # ;; #esac #------------------------------------------------------------------ # Determine if we need to enable NAT #------------------------------------------------------------------ if echo $NETWORK_LIST | grep -qE "(nat|NAT)" then echo "" echo "============================================================" echo "Enabling Network Adress Translation" echo "============================================================" iptables -t nat -A POSTROUTING -o $NAT_EXTERNAL_INTERFACE -j MASQUERADE modprobe bridge sysctl -q -w net.bridge.bridge-nf-call-iptables="0" NAT_DONE="yes" fi } use_sf2() { # This function determins whether or not to use the SuSEfirewall2 # to configure routing, NAT, and firewall rules. # # The values start|stop are passed into this fuction case $1 in start) if [ -e /etc/init.d/SuSEfirewall2_setup ] && /etc/init.d/SuSEfirewall2_setup status | grep -iwq "running" then echo "Determining how to configure the firewall and routing:" echo " Using SuSEfirewall2" echo "yes" > $NETWORK_SAVE_PATH/use_sf2 else echo "Determining how to configure the firewall and routing:" echo " Using iptables" echo "no" > $NETWORK_SAVE_PATH/use_sf2 fi ;; stop) if [ -e $NETWORK_SAVE_PATH/use_sf2 ] then rm -rf $NETWORK_SAVE_PATH/use_sf2 fi ;; esac } update_sf2_config() { # This function backs up the initial values in /etc/sysconfig/SuSEfirewall2 # and then modifies them with the values required for the Xen network # environment when it is started. It also restores the initial values when # it is stopped # # The values start|stop are passed into this fuction case $CMD_OPT in start) # Back-up initial values echo " -Backing up initial SuSEfirewall2 parameters" grep "^FW_DEV_EXT=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_DEV_INT=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_DEV_DMZ=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_ROUTE=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_MASQUERADE=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_MASQ_DEV=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_MASQ_NETS=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_NOMASQ_NETS=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_FORWARD=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 grep "^FW_FORWARD_ALWAYS_INOUT_DEV=" $SF2_SYSCONFIG_FILE >> $NETWORK_SAVE_PATH/sf2 # Update values for Xen networking #find_nat_external_interface local DEV=`find_default_interface` $NAT_EXTERNAL_INTERFACE #case $NAT_EXTERNAL_INTERFACE in # default) # local DEV=`ip route list | awk '/^default / { print $NF }'` # ;; # *) # local DEV="$NAT_EXTERNAL_INTERFACE" # ;; #esac # Find the HWD_CONFIG_0 file neame for SLE10 if [ -x /sbin/getcfg ] then local NAT_DEV="`/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- -- "$DEV" | grep "HWD_CONFIG_0="|cut -d '"' -f 2`" else local NAT_DEV="$DEV" fi echo " -Updating SuSEfirewall2 parameters for the Xen network environment" sed -i "s/^FW_DEV_EXT=\"\(.*\)\"$/FW_DEV_EXT=\"\1 $NAT_DEV\"/g" $SF2_SYSCONFIG_FILE sed -i 's/^FW_ROUTE="no"/FW_ROUTE="yes"/g' $SF2_SYSCONFIG_FILE sed -i 's/^FW_MASQUERADE="no"/FW_MASQUERADE="yes"/g' $SF2_SYSCONFIG_FILE sed -i "s/^FW_MASQ_DEV=.*/FW_MASQ_DEV=\"$NAT_DEV\"/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_FORWARD_ALWAYS_INOUT_DEV=.*/FW_FORWARD_ALWAYS_INOUT_DEV=\"xenbr+ xennat+ xenhost+ xenroute+ xennohost+ xenempty+\"/g" $SF2_SYSCONFIG_FILE ;; stop) # Restore the original values echo " -Restoring initial SuSEfirewall2 parameters" sed -i "s/^FW_DEV_EXT=.*/`grep "^FW_DEV_EXT=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_DEV_INT=.*/`grep "^FW_DEV_INT=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_DEV_DMZ=.*/`grep "^FW_DEV_DMZ=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_ROUTE=.*/`grep "^FW_ROUTE=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_MASQUERADE=.*/`grep "^FW_MASQUERADE=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s/^FW_MASQ_DEV=.*/`grep "^FW_MASQ_DEV=" $NETWORK_SAVE_PATH/sf2`/g" $SF2_SYSCONFIG_FILE sed -i "s+^FW_MASQ_NETS=.*+`grep "^FW_MASQ_NETS=" $NETWORK_SAVE_PATH/sf2`+g" $SF2_SYSCONFIG_FILE sed -i "s+^FW_NOMASQ_NETS=.*+`grep "^FW_NOMASQ_NETS=" $NETWORK_SAVE_PATH/sf2`+g" $SF2_SYSCONFIG_FILE sed -i "s+^FW_FORWARD=.*+`grep "^FW_FORWARD=" $NETWORK_SAVE_PATH/sf2`+g" $SF2_SYSCONFIG_FILE sed -i "s+^FW_FORWARD_ALWAYS_INOUT_DEV=.*+`grep "^FW_FORWARD_ALWAYS_INOUT_DEV=" $NETWORK_SAVE_PATH/sf2`+g" $SF2_SYSCONFIG_FILE rm -f $NETWORK_SAVE_PATH/sf2 ;; esac } update_sf2_interfaces() { # This function modifies the internal interfaces and the values that define which # networks can be masqueraded in the /etc/sysconfig/SuSEfirewall2 file. # # Usage: update_sf2_interfaces start|stop $DEV $TYPE $IPADDR local DEV="$2" local NETWORK_TYPE="$3" local IPADDR="`ipcalc $4|grep Network:|sed "s/Network: *//g"|cut -d " " -f 1`" #local MACADDR="$5" local FW_INT_IFACE="$DEV" case $1 in start) # Add an internal interface echo echo " SuSEfirwall2 is present:" echo " Adding $FW_INT_IFACE as an internal interface" sed -i "s/\(^FW_DEV_INT=\".*\)\"$/\1 $FW_INT_IFACE\"/g" $SF2_SYSCONFIG_FILE case $NETWORK_TYPE in nat) # Add a NATed network echo " Adding $IPADDR as a NATed network" sed -i "s+\(^FW_MASQ_NETS=\".*\)\"$+\1 $IPADDR\"+g" $SF2_SYSCONFIG_FILE sed -i "s+\(^FW_FORWARD=\".*\)\"$+\1 $IPADDR\"+g" $SF2_SYSCONFIG_FILE ;; hostonly) # Add a non-NATed network echo " Adding $IPADDR as a non-NATed network" sed -i "s+\(^FW_NOMASQ_NETS=\".*\)\"$+\1 $IPADDR\"+g" $SF2_SYSCONFIG_FILE ;; route) # Add a routed network echo " Adding $IPADDR as a routed network" sed -i "s+\(^FW_FORWARD=\".*\)\"$+\1 $IPADDR\"+g" $SF2_SYSCONFIG_FILE ;; esac ;; stop) # Remove an internal interface echo echo " SuSEfirwall2 is present:" echo " Removing $FW_INT_IFACE as an internal interface" sed -i "s/\(^FW_DEV_INT=\".*\) $FW_INT_IFACE\(.*\)\"$/\1\2\"/g" $SF2_SYSCONFIG_FILE case $NETWORK_TYPE in nat) # Remove a NATed network echo " Removing $IPADDR as a NATed network" sed -i "s+\(^FW_MASQ_NETS=\".*\) $IPADDR\(.*\)\"$+\1\2\"+g" $SF2_SYSCONFIG_FILE sed -i "s+\(^FW_FORWARD=\".*\) $IPADDR\(.*\)\"$+\1\2\"+g" $SF2_SYSCONFIG_FILE ;; hostonly) # Remove a non-NATed network echo " Removing $IPADDR as a non-NATed network" sed -i "s+\(^FW_NOMASQ_NETS=\".*\) $IPADDR\(.*\)\"$+\1\2\"+g" $SF2_SYSCONFIG_FILE ;; route) # Remove a routed network echo " Removing $IPADDR as a routed network" sed -i "s+\(^FW_FORWARD=\".*\) $IPADDR\(.*\)\"$+\1\2\"+g" $SF2_SYSCONFIG_FILE ;; esac ;; esac } handle_sf2() { # This function starts and stops the SuSEfirewall2 # # Usage: handle_sf2 start|stop|restart case $1 in stop) if [ -e /etc/init.d/SuSEfirewall2_setup ] && /etc/init.d/SuSEfirewall2_setup status | grep -iwq "running" then echo "" echo "============================================================" echo "Stopping SuSEfirewall2" echo "============================================================" /etc/init.d/SuSEfirewall2_setup stop > /dev/null 2>&1 return 0 else return 1 fi ;; start) if [ -e $NETWORK_SAVE_PATH/use_sf2 ] && grep "yes" $NETWORK_SAVE_PATH/use_sf2 then echo "" echo "============================================================" echo "Starting SuSEfirewall2" echo "============================================================" /etc/init.d/SuSEfirewall2_setup start > /dev/null 2>&1 return 0 else return 1 fi ;; restart) if [ -e $NETWORK_SAVE_PATH/use_sf2 ] && grep "yes" $NETWORK_SAVE_PATH/use_sf2 then echo "" echo "============================================================" echo "Restarting SuSEfirewall2" echo "============================================================" /etc/init.d/SuSEfirewall2_setup restart > /dev/null 2>&1 return 0 else return 1 fi ;; esac } manage_iptables() { # This function saves and restores the iptables rules that exist # before the Xen network script runs # # The following values can be passed into this fuction: # start|stop case $1 in stop) echo "" echo "============================================================" echo "Saving iptables rules" echo "============================================================" echo #---------------------------------------------------------------- # Saving iptables rules for $TABLE to a file #---------------------------------------------------------------- echo " -----------------------" for TABLE in `iptables-save |grep '*'|cut -d '*' -f 2` do echo " Saving table: $TABLE" iptables-save -t $TABLE > $IPTABLES_SAVE_FILE@$TABLE echo " Flushing table: $TABLE" iptables -F -t $TABLE echo " -----------------------" done #---------------------------------------------------------------- # Deleting any custom chain #---------------------------------------------------------------- for CHAIN in `iptables-save |grep ^:|cut -d ":" -f 2|cut -d " " -f 1` do case $CHAIN in INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING) #do nothing ;; *) echo "Deteting chain: $CHAIN" iptables -X $CHAIN ;; esac done ;; start) echo "" echo "============================================================" echo "Restoring iptables rules" echo "============================================================" echo #---------------------------------------------------------------- # Restoring iptables rules for $TABLE #---------------------------------------------------------------- echo " -----------------------" for TABLE in `ls $IPTABLES_SAVE_FILE*|cut -d "@" -f 2` do echo " Restoring table: $TABLE" iptables-restore < $IPTABLES_SAVE_FILE@$TABLE rm $IPTABLES_SAVE_FILE@$TABLE echo " -----------------------" done ;; esac } manage_firewall() { # This function determins how the firewall is being managed # (either with SuSEfirewall2 or not) and then manages the # configuration of routing and the firewall accordingly. # # The following values can be passed into this function: # prestart|poststart|prestop|poststop echo echo "============================================================" echo "Configuring the firewall and routing: $1" echo "============================================================" case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) echo " SUSEfirewall2 is present and enabled." echo " Using SUSEfirewall2 for firewall and routing:" case $1 in prestart) handle_sf2 stop update_sf2_config start ;; poststart) handle_sf2 start ;; prestop) handle_sf2 stop update_sf2_config stop ;; poststop) handle_sf2 start ;; esac ;; *) case $1 in prestart) if [ -e /etc/init.d/SuSEfirewall2_setup ] then echo echo " SuSEfirewall2 is present but not enabled:" echo " (Updating SuSEfirewall2 just in case.)" update_sf2_config start fi # Backup and flush existing firewall rules manage_iptables stop # Enable ip forwarding if required configure_routing start ;; poststart) # Configure NAT if required configure_nat ;; prestop) if [ -e /etc/init.d/SuSEfirewall2_setup ] then echo echo "SuSEfirwall2 is present but not enabled:" # Restore original SuSEfirewall2 configuration update_sf2_config stop fi # Restore ip forwarding to the origiunal state configure_routing stop ;; poststop) # Restore original firewall rules manage_iptables start ;; esac ;; esac } #***** Traditional Bridge Helper Functions ******************************** create_bridge() { # This function creates a bridge. # # Usage: create_bridge $BRIDGE # # Vars: $BRIDGE -Name of the bridge local BRIDGE=$1 # Don't create the bridge if it already exists. if [ ! -e "/sys/class/net/${BRIDGE}/bridge" ] then # Create the bridge #echo "Creating bridge: $BRIDGE";read brctl addbr ${BRIDGE} brctl stp ${BRIDGE} off brctl setfd ${BRIDGE} 0 fi } delete_bridge() { # This function deletes a bridge. # # Usage: delete_bridge $BRIDGE # # Vars: $BRIDGE -Name of the bridge local BRIDGE=$1 # Don't try to delete the bridge if it doesn't exist. if [ -e "/sys/class/net/${BRIDGE}/bridge" ]; then # Remove any remaining bridge ports #echo "Removing any remaining bridge ports";read local BRIDGE_PORTS="`ls /sys/class/net/${BRIDGE}/brif`" for PORT in $BRIDGE_PORTS do brctl delif $BRIDGE $PORT done # Bring the bridge down #echo "Bringing down $BRIDGE";read ip link set ${BRIDGE} down # Bring the bridge down #echo "Remove any addresses from $BRIDGE";read ip addr flush ${BRIDGE} > /dev/null 2>&1 # Remove the bridge #echo "Removing $BRIDGE";read brctl delbr ${BRIDGE} fi } add_to_bridge() { # This function adds a network interface to a bridge as a bridge port. # # Usage: add_to_bridge $BRIDGE $DEV # # Vars: $BRIDGE -Name of the bridge # $DEV -Interface to add to the bridge local BRIDGE=$1 local DEV=$2 # Don't add $dev to $bridge if it's already on a bridge. if [ -e "/sys/class/net/${BRIDGE}/brif/${DEV}" ]; then return fi brctl addif ${BRIDGE} ${DEV} ip link set ${DEV} up } add_to_bridge2() { # This function waits for a network interface to come up and then adds it # to a bridge as a bridge port by calling the add_to_bridge function. # # Usage: add_to_bridge2 $BRIDGE $DEV # # Vars: $BRIDGE -Name of the bridge # $DEV -Name of the interface to add to the bridge local BRIDGE=$1 local DEV=$2 local MAXTRIES=10 echo -n " Waiting for ${DEV} to negotiate link." ip link set ${DEV} up for i in `seq ${MAXTRIES}` ; do if ifconfig ${DEV} | grep -q RUNNING ; then break else echo -n '.' sleep 1 fi done if [ ${i} -eq ${MAXTRIES} ] then echo '(link isnt in running state)' fi add_to_bridge ${BRIDGE} ${DEV} } transfer_addrs() { # This function transfers all IP addresses (including aliases) from one # network interface to another # # Usage: transfer_addrs $DEV $BRIDGE # transfer_addrs $BRIDGE $DEV # # Vars: $DEV/$SRC -Source interface # $BRIDGE/$DST -Destination interface local SRC=$1 local DST=$2 # Ensure there is an address to transfer # echo "Ensure there is an address to transfer";echo "ifup ${SRC}";echo "ip link set ${DST} up";read if ! ip addr show $SRC| grep -qw "UP" then ip link set $SRC up #ifup $SRC > /dev/null 2>&1 fi # Don't bother if $DST already has IP addresses. if ip addr show dev ${DST} | egrep -q '^ *inet ' ; then return fi # Record default route on ${SRC} DEFAULT_GW=`ip route show dev ${SRC} | fgrep default | sed 's/default via //'` # Address lines start with 'inet' and have the device in them. # Replace 'inet' with 'ip addr add' and change the device name $SRC # to 'dev $SRC'. ip addr show dev ${SRC} | egrep '^ *inet ' | sed -e " s/inet/ip addr add/ s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+/[0-9]\+\)@\1@ s/${SRC}/dev ${DST} label ${DST}/ s/secondary// " | sh -e # Remove automatic routes on destination device ip route list | sed -ne " /dev ${DST}\( \|$\)/ { s/^/ip route del / p }" | sh -e } transfer_routes() { # This function transfers the routes from one network interface to another # by doing the following: # # Get all IP routes to device $SRC, delete them, and # add the same routes to device $DST. # The original routes have to be deleted, otherwise adding them # for $dst fails (duplicate routes). # # Usage: transfer_routes $SRC $DST local SRC=$1 local DST=$2 # List all routes and grep the ones with $src in. # Stick 'ip route del' on the front to delete. # Change $src to $dst and use 'ip route add' to add. ip route list | sed -ne " /dev ${SRC}\( \|$\)/ { h s/^/ip route del / P g s/${SRC}/${DST}/ s/^/ip route add / P d }" | sh -e } link_exists() { # This function returns 0 if the interface named exists # (whether up or down), 1 otherwise. # # Usage: link_exists if ip link show "$1" >/dev/null 2>/dev/null then return 0 else return 1 fi } antispoofing() { # This fuction sets the default forwarding policy for $dev to drop. # Allow forwarding to the bridge. iptables -P FORWARD DROP iptables -F FORWARD iptables -A FORWARD -m physdev --physdev-in ${pdev} -j ACCEPT iptables -A FORWARD -m physdev --physdev-in ${vif0} -j ACCEPT } find_active_vlans() { # This function discovers active vlans and returns them # # Usage: find_active_vlans $DEV # # Vars: $DEV # $VLAN # $VLANS local DEV=$1 local VLAN local VLANS VLANS="" for vifcfg in /etc/sysconfig/network/ifcfg-vlan* ; do VLAN=${vifcfg/*\/ifcfg-} if [ "$VLAN" = "vlan*" ]; then continue fi . $vifcfg etherdevice="$ETHERDEVICE" if [ -x /sbin/getcfg-interface ] then etherdevice=$(/sbin/getcfg-interface "$ETHERDEVICE") fi if [ "$ETHERDEVICE" = "$DEV" ] || [ "$etherdevice" = "$DEV" ] then link_exists "$VLAN" && VLANS="$VLANS $VLAN" fi done echo "$VLANS" } create_normal_bridge() { # This fuction creates a bridge on a normal network interface # # Usage: create_normal_bridge start|stop $DEV $BRIDGE # # Vars: $DEV -Network interface name # $BRIDGE -Name of the bridge local DEV="$2" local BRIDGE="$3" local BONDED="no" if [ -e /sys/class/net/$DEV/bonding ] then BONDED="yes" fi # Find and bring down any active VLANs local VLANS=$(find_active_vlans "${DEV}") for VLAN in $VLANS do ifdown $VLAN > /dev/null 2>&1 done case $1 in start) # Create ${BRIDGE} #echo "Create the bridge. \(create_bridge ${BRIDGE}\)";read create_bridge ${BRIDGE} # Transfer IP address from ${DEV} to the ${BRIDGE} #echo "Transfer the IP address from ${DEV} to ${BRIDGE}";read transfer_addrs ${DEV} ${BRIDGE} # Flush addresses from ${DEV} #echo "Flush addresses from ${DEV}";read ip addr flush ${DEV} > /dev/null 2>&1 # Add ${DEV} to ${BRIDGE} #echo "Add ${DEV} to ${BRIDGE}";read brctl addif ${BRIDGE} ${DEV} # Bring up ${BRIDGE} #echo "Bring up ${BRIDGE}";read ip link set dev ${BRIDGE} up # If default route was on ${DEV}, then transfer it to ${BRIDGE} #echo "Add gw ${DEFAULT_GW}";read [ -n "${DEFAULT_GW}" ] && ip route add default dev ${BRIDGE} via ${DEFAULT_GW} ;; stop) # Remove interface from bridge brctl delif ${BRIDGE} ${DEV} # If interface is a bond, use ifdown and don't transfer addresses. # Addresses will be reassigned when ifup'ing the bond. #echo "Remove interface ${DEV} from ${BRIDGE}";read if [ "x${BONDED}" = "xyes" ] then ifdown ${DEV} else ip link set ${DEV} down # Transfer IP address back to original interface #echo "Transfer IP address from ${BRIDGE} to ${DEV}";read transfer_addrs ${BRIDGE} ${DEV} fi # Remove bridge ${BRIDGE} #echo "Remove the bridge";read delete_bridge ${BRIDGE} # If bonded, just ifup the bond. Otherwise use ip to bring up the interface # and if default route was on ${BRIDGE} transfer it back to ${DEV} if [ "x${BONDED}" = "xyes" ] then ifup ${DEV} else ip link set ${DEV} up [ -n "${DEFAULT_GW}" ] && ip route add default dev ${DEV} via ${DEFAULT_GW} fi ;; esac # Bring VLANs back up #echo "Bring VLANS back up";read for VLAN in $VLANS do #echo $VLAN ifup $VLAN > /dev/null 2>&1 done } #***** NAT/HostOnly Helper Functions ************************************** configure_bridge_as_dom0_interface() { # This function configures the IP address of a bridge to be a # network interface in Dom0. # # Usage: configure_dom0_bridge_interface $BRIDGE $IPADDR # # Vars: $BRIDGE -bridge name # $IPADDR -IP address to assign to the bridge local BRIDGE="$1" local IPADDR="$2" case $CMD_OPT in start) # Take the bridge down #echo "Taking the $BRIDGE down";read ip link set $BRIDGE down # Assign the bridge an IP address #echo"Assign $BRIDGE the IP address: $IPADDR";read ip addr flush $BRIDGE > /dev/null 2>&1 ip addr add $IPADDR brd + dev $BRIDGE # Bring the bridge back up #echo "Bridge $BRIDGE back up";read ip link set $BRIDGE up # Enable ARP in the bridge #echo "Enable ARP on $BRIDGE";read ip link set $BRIDGE arp on ;; stop) # Take the bridge down #echo "Taking $BRIDGE down";read ip link set $BRIDGE down # Remove IP address from the bridge #echo "Remove the IP address from $BRIDGE";read ip addr flush $BRIDGE > /dev/null 2>&1 ;; status) ip addr show $BRIDGE ;; esac } #***** Network Type Configuration Functions ******************************* configure_bridged_networks() { # This function creates traditional bridges on physical interfaces (eth) in Dom0. # # Usage: configure_bridged_networks start|stop|status $NET_DEV $NET_NUMBER # # Vars: $DEV -Network device to create the bridge on # $NUMBER -Number of the bridge being created/removed # $BRIDGE -Name of the bridge # Set local function variables local DEV=$2 local NUMBER=$3 local BRIDGE=$BRIDGE_NAME$NUMBER # Test if $BRIDGE is set if [ "$BRIDGE" = "null" ] then return fi case $1 in start) # Test if $BRIDGE already exists if [ -e "/sys/class/net/$BRIDGE/bridge" ] then # Skip this bridge #------------------------------------------------------------------ echo " $BRIDGE exists and is already configured." echo " Skipping $BRIDGE" return fi if /sbin/ip link show $DEV | grep -qw UP then echo "" echo "============================================================" echo "Configuring Virtual Network: $BRIDGE" echo " of type: bridge" echo " on- Physical Interface: $DEV" echo "============================================================" echo "" # Create bridge create_normal_bridge start $DEV $BRIDGE if [ "${antispoof}" = "yes" ] then antispoofing fi # Write entry into networktab #--------------------------------------------------------------------- echo "$BRIDGE,bridge,$NUMBER,$DEV,dhcp-off" >> $NETWORKTAB echo "" else echo " Physical Interface $DEV is not up. Skipping $BRIDGE" fi ;; stop) # Check if bridge exists. Fail if not #--------------------------------------------------------------------- if ! link_exists "$BRIDGE"; then echo "$BRIDGE does not exist. Skipping." return fi echo "" echo "============================================================" echo "Removing Virtual Network: $BRIDGE" echo " of type: bridge" echo "from- Physical Interface: $DEV" echo "============================================================" echo "" # Remove bridge with normal network interface (i.e. ethX) create_normal_bridge stop $DEV $BRIDGE # Remove entry from networktab file #--------------------------------------------------------------------- sed -i "/$BRIDGE/d" $NETWORKTAB ;; status) ;; *) echo "The function create_bridged_networks requires the CMD_OPT variable" echo "to be set to one of the following: start|stop|status" exit 1 ;; esac } configure_local_networks() { # This function creates bridges as network interfaces in Dom0 and # enables nat or routing on the bridges if specified. # # Usage: # create_local_networks start|stop|status $NET_DEV $NET_TYPE $NET_NUMBER $NET_DEV_IP $NET_DHCP_SRV # Set local function variables local DEV=$2 local TYPE=$3 local NUMBER=$4 case $TYPE in hostonly) local BRIDGE=$HOSTONLY_NAME$NUMBER ;; nat) local BRIDGE=$NAT_NAME$NUMBER ;; route) local BRIDGE=$ROUTE_NAME$NUMBER ;; esac local IPADDR=$5 local DHCP_SRV=$6 local IP="`echo $IPADDR | cut -d '/' -f 1`" local SNM="`ipcalc $IPADDR | grep Netmask | sed 's/Netmask: *//g' | cut -d ' ' -f 1`" local NAT_GW_IP=`echo $IPADDR|cut -d "," -f 3|cut -d "/" -f 1` local NAT_INTIF=$DEV local ROUTE_INTIF=$DEV # Determine what the NAT external interface is case $NAT_EXTERNAL_INTERFACE in default) # Set NAT interface to the interface with the default route local NAT_DEV=`ip route list | awk '/^default / { print $NF }'` ;; *) # Set the NAT interface to the specified interface NAT_DEV=$NAT_EXTERNAL_INTERFACE ;; esac #---- do start or stop -------------------------------------------- case $1 in start) if ! [ -e "/sys/class/net/$BRIDGE/bridge" ] then # Create the network #------------------------------------------------------------------ echo "" echo "============================================================" echo "Configuring Virtual Network: $BRIDGE" echo " of type: $TYPE" # Create the bridge create_bridge $BRIDGE > /dev/null 2>&1 # Configure the bridge as a Dom0 network interface configure_bridge_as_dom0_interface $BRIDGE $IPADDR > /dev/null 2>&1 # Set up the bridge as a hostonly / NAT / Routed network case $TYPE in NAT|nat) # Set up the bridge as NATed network echo " Gateway: $NAT_GW_IP" echo " External Interface: $NAT_DEV" # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces start $DEV $TYPE $IPADDR #fi case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; esac ;; ROUTE|route) # Set up the bridge as Routed network echo " Gateway: $NAT_GW_IP" echo " External Interface: $NAT_DEV" # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces start $DEV $TYPE $IPADDR #fi case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; *) #iptables -t nat -A PREROUTING -i $ROUTE_INTIF -j ACCEPT iptables -t nat -A PREROUTING -o $BRIDGE -j ACCEPT #iptables -t filter -A PREROUTING -i $ROUTE_INTIF -j ACCEPT #iptables -t filter -A PREROUTING -o $DEV -j ACCEPT ;; esac ;; HOSTONLY|hostonly) # Set up the bridge as hostonly network # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces start $DEV $TYPE $IPADDR #fi # Restart SuSEfirewall2 if we are using it or add custom iptables rules if not case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; *) if [ "$IP_FWD" = "on" ] then iptables -t nat -A PREROUTING -i $BRIDGE -j DROP fi ;; esac ;; esac # Configure DHCP for the network #--------------------------------------------------------------------- #if ! [ "$DHCP_SRV" = "dhcp-on" ] #then # echo # echo "DHCP disabled on this network." #else # create_xen_dhcp_config start $BRIDGE $DEV $TYPE $NUMBER $MAC $IPADDR $DHCP_SRV $IFCFG_FILE_NAME # # # Restart the dhcp server # /etc/init.d/dhcpd restart #fi # write entry into networktab #--------------------------------------------------------------------- echo "$BRIDGE,$TYPE,$NUMBER,$IPADDR,$DHCP_SRV" >> $NETWORKTAB echo "============================================================" else # Skip this bridge #------------------------------------------------------------------ echo " $BRIDGE exists and is already configured." echo " Skipping $BRIDGE" fi ;; stop) # Remove the network #------------------------------------------------------------------ echo "" echo "============================================================" echo "Removing Virtual Network: $BRIDGE" echo " of type: $TYPE" # First remove the hostonly / NAT / Routed configuration case $TYPE in NAT|nat) # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces stop $DEV $TYPE $IPADDR #fi case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; esac ;; ROUTE|route) # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces stop $DEV $TYPE $IPADDR #fi case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; *) # Clean out the bridge specific routing iptables rule #iptables -t nat -D PREROUTING -i $ROUTE_INTIF -j ACCEPT iptables -t nat -D PREROUTING -i $BRIDGE -j ACCEPT #iptables -t filter -D FORWARD -i $DEV -j ACCEPT #iptables -t filter -D FORWARD -i $NAT_INTIF -j ACCEPT ;; esac ;; HOSTONLY|hostonly) # Update SuSEfirewall2 if it exists #if [ -e "/etc/init.d/SuSEfirewall2_setup" ] #then # update_sf2_interfaces stop $DEV $TYPE $IPADDR #fi # Restart SuSEfirewall2 if we are using it or remove custom iptables rules if not case `cat $NETWORK_SAVE_PATH/use_sf2` in yes) handle_sf2 restart ;; *) if [ "$IP_FWD" = "on" ] then # Clean out the bridge specific nat iptables rule iptables -t nat -D PREROUTING -i $BRIDGE -j DROP fi ;; esac ;; esac #create_xen_dhcp_config stop $DEV $TYPE $NUMBER $MAC $IPADDR $DHCP_SRV echo "============================================================" # unconfigure the veth configure_bridge_as_dom0_interface $DEV $IPADDR > /dev/null 2>&1 # Remove the bridge #echo "Removing $BRIDGE";read delete_bridge $BRIDGE # Remove entry from networktab file #--------------------------------------------------------------------- sed -i "/$BRIDGE/d" $NETWORKTAB ;; status) #------------------------------------------------------------------ # Show the status of the bridge #------------------------------------------------------------------ echo "" echo "============================================================" echo "Status of Virtual Network: $BRIDGE" echo " of type: $TYPE" echo "============================================================" brctl show | grep -w "^$BRIDGE" echo "" ip addr show $BRIDGE echo "============================================================" ;; *) echo "The function requires one of the following options:" echo "start|stop|status" exit 1 ;; esac } configure_nohost_networks() { # This function creates bridges attached to an external interface but # no interfaces in Dom0. # # This function reads the start,stop,status parameter from the $CMD_OPT # variable and responds respectively. # # Usage: create_nohost_networks start|stop|status $NET_DEV $NET_NUMBER echo "" echo "============================================================" local DEV=$2 local MAC=`ip link show ${DEV} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'` local NUMBER=$3 local BRIDGE=${NOHOST_NAME}${NUMBER} case $1 in start) if ! [ -e "/sys/class/net/${BRIDGE}/bridge" ] then echo "" echo "============================================================" echo "Configuring Virtual Network: ${BRIDGE}" echo " of type: nohost" echo " on- Physical Interface: ${DEV}" # Create the network #--------------------------------------------------------------------- # Ensure there is a bridge to transfer to #echo "Create the bridge. \(create_bridge ${BRIDGE}\)";read create_bridge ${BRIDGE} # Configure $DEV as a bridge port #echo "Configure ${DEV} as a bridge port";read setup_bridge_port ${DEV} # Bring bridge up and add interfaces to it #echo "Bring ${BRIDGE} up and add ${DEV} to it";read ip link set ${BRIDGE} up #add_to_bridge2 ${BRIDGE} ${DEV} add_to_bridge ${BRIDGE} ${DEV} # Write entry into networktab file #--------------------------------------------------------------------- echo "${BRIDGE},nohost,${NUMBER},${DEV},,," >> ${NETWORKTAB} else # Skip this bridge #------------------------------------------------------------------ echo " $BRIDGE exists and is already configured." echo " Skipping $BRIDGE" fi ;; stop) if brctl show | grep -qw "^${BRIDGE}" then echo "============================================================" echo "Removing Virtual Network: ${BRIDGE}" echo " of type: nohost" echo "" # Remove the network #--------------------------------------------------------------------- # Remove interface from bridge #echo "Remove interface ${DEV} from ${BRIDGE}";read brctl delif ${BRIDGE} ${DEV} # Remove bridge ${BRIDGE} #echo "Remove the bridge";read delete_bridge ${BRIDGE} # Bring renamed physical interface up #echo "Bring up ${DEV}";read ifup ${DEV} > /dev/null 2>&1 # Remove entry from networktab file #--------------------------------------------------------------------- sed -i "/${BRIDGE}/d" $NETWORKTAB fi ;; status) brctl show $BRIDGE | grep -w "^$BRIDGE" ;; *) echo "The function requires one of the following options:" echo "start|stop|status" exit 1 ;; esac echo "============================================================" } configure_empty_networks() { # This function creates bridges attached to no devices in Dom0. # # Usage: create_empty_networks start|stop|status $NET_NUMBER echo "" echo "============================================================" local NUMBER=$2 local BRIDGE=$EMPTY_NAME$NUMBER case $1 in start) if ! [ -e "/sys/class/net/${BRIDGE}/bridge" ] then echo "Configuring Virtual Network: $BRIDGE" echo " of type: empty" # Create the network #--------------------------------------------------------------------- # create the bridge create_bridge $BRIDGE # Write entry into networktab file #--------------------------------------------------------------------- echo "$BRIDGE,empty,$NUMBER,,,," >> $NETWORKTAB else # Skip this bridge #------------------------------------------------------------------ echo " $BRIDGE exists and is already configured." echo " Skipping $BRIDGE" fi ;; stop) if brctl show | grep -qw "^$BRIDGE" then echo "Removing Virtual Network: $BRIDGE" echo " of type: empty" ip link set $BRIDGE down # Remove the network #--------------------------------------------------------------------- # remove the bridge delete_bridge $BRIDGE # Remove entry from networktab file #--------------------------------------------------------------------- sed -i "/$BRIDGE/d" $NETWORKTAB fi ;; status) brctl show $BRIDGE | grep -w "^$BRIDGE" ;; *) echo "The function requires one fo the following options:" echo "start|stop|status" exit 1 ;; esac echo "============================================================" } #***** Network Removal Functions ****************************************** remove_all_networks() { # This fuction removes all networks listed in the networktab file by calling # the network creation functions with the CMD_OPT variable set to "stop" CMD_OPT="stop" echo "============================================================" echo "Removing all virtual networks" echo "============================================================" for NETWORK in `cat $NETWORKTAB` do local NET_NAME="`echo $NETWORK | cut -d "," -f 1`" local NET_TYPE="`echo $NETWORK | cut -d "," -f 2`" local NET_NUMBER="`echo $NETWORK | cut -d "," -f 3`" local NET_DEV="`echo $NETWORK | cut -d "," -f 4`" local NET_DEV_MAC="`echo $NETWORK | cut -d "," -f 5`" local NET_DEV_IP="`echo $NETWORK | cut -d "," -f 6`" local NET_DHCP_SRV="`echo $NETWORK | cut -d "," -f 7`" # Remove the network #--------------------------------------------------------------------- case $NET_TYPE in bridge) configure_bridged_networks stop $NET_DEV $NET_NUMBER ;; nat|hostonly|route) configure_local_networks stop $NET_DEV $NET_TYPE $NET_NUMBER $NET_DEV_IP $NET_DHCP_SRV ;; nohost) configure_nohost_networks stop $NET_DEV $NET_NUMBER ;; empty) configure_empty_networks stop $NET_NUMBER ;; esac done } #***** DHCP Functions ***************************************************** create_xen_dhcp_config() { # This function enables/disables the DHCP server on virtual networks. # # Usage: # create_xen_dhcp_config start|stop $NET_NAME $NET_DEV_IP $NET_DHCP_SRV # Set local function variables #--------------------------------------------------------------------- local NAME=$1 local BRIDGE="$2" local IPCIDR="$3" local DHCPON="$4" local IFCFG_FILE_NAME="ifcfg-$DEV" local IPADDR=`echo $IPCIDR|cut -d "/" -f 1` local RANGE="`echo $IPADDR|cut -d "." -f 1,2,3`.`echo $XEN_DHCP_RANGE|cut -d "-" -f 1` - `echo $IPADDR|cut -d "." -f 1,2,3`.`echo $XEN_DHCP_RANGE|cut -d "-" -f 2`" local SUBNET=`ipcalc -n -b $IPCIDR|grep "Network:"|cut -d ":" -f 2|cut -d "/" -f 1` local NETMASK=`ipcalc -n -b $IPCIDR|grep "Netmask:"|cut -d ":" -f 2|cut -d "=" -f 1` local BRIDGE_NUM="$NUMBER" # Define DNS servers #--------------------------------------------------------------------- case $XEN_DHCP_DNS_SERVERS in gateway) # Use Dom0 as the DNS server local DNS=$IPADDR ;; *) # Specify DNS server(s) if test `echo $XEN_DHCP_DNS_SERVERS|grep -c ","` then local DNS=`echo $XEN_DHCP_DNS_SERVERS|sed "s/,/, /"` else local DNS=`echo $XEN_DHCP_DNS_SERVERS` fi ;; esac case $1 in start) # Echo out what we are doing #--------------------------------------------------------------------- echo "------------------------------------------------------------" echo " Enabling DHCP" echo " -------------------" echo " Subnet: $SUBNET" echo " Netmask: $NETMASK" echo " Range: $RANGE" echo " DNS Servers: $DNS" echo " Gateway: $IPADDR" echo "------------------------------------------------------------" # Create the dhcpd-xen.$DEV.conf file #--------------------------------------------------------------------- echo "ddns-update-style none;" > /etc/dhcpd-xen.$DEV.conf echo "subnet $SUBNET netmask $NETMASK {" >> /etc/dhcpd-xen.$DEV.conf echo " range `echo $RANGE | tr -d -`;" >> /etc/dhcpd-xen.$DEV.conf echo " default-lease-time 14400;" >> /etc/dhcpd-xen.$DEV.conf echo " max-lease-time 14400;" >> /etc/dhcpd-xen.$DEV.conf echo " option domain-name-servers $DNS;" >> /etc/dhcpd-xen.$DEV.conf echo " option routers $IPADDR;" >> /etc/dhcpd-xen.$DEV.conf echo "}" >> /etc/dhcpd-xen.$DEV.conf # Edit the dhcpd sysconfig file for xen #--------------------------------------------------------------------- #echo "editing DHCPD_INTERFACE in $DHCP_SYSCONFIG_FILE";read sed -i "s/^DHCPD_INTERFACE=\"\([^\"]*\)\"/DHCPD_INTERFACE=\"\1 $IFCFG_FILE_NAME\"/" $DHCP_SYSCONFIG_FILE #echo "editing DHCPD_CONF_INCLUDE_FILES in $DHCP_SYSCONFIG_FILE";read sed -i "s/^DHCPD_CONF_INCLUDE_FILES=\"\([^\"]*\)\"/DHCPD_CONF_INCLUDE_FILES=\"\1\/etc\/dhcpd-xen.$DEV.conf\"/" $DHCP_SYSCONFIG_FILE # Edit the dhcpd.conf file to include additional dhcpd configs for xen #--------------------------------------------------------------------- #echo "editing $DHCPD_CONF_FILE to add included config files";read echo "include \"/etc/dhcpd-xen.$DEV.conf\";" >> $DHCPD_CONF_FILE 2>/dev/null ;; stop) # delete the config file #--------------------------------------------------------------------- rm -f /etc/dhcpd-xen.$DEV.conf # remove the interface file from the /etc/sysconfig file #--------------------------------------------------------------------- sed -i "s/$IFCFG_FILE_NAME//g" $DHCP_SYSCONFIG_FILE # remove the included config file from the /etc/sysconfig file #--------------------------------------------------------------------- sed -i "s/\/etc\/dhcpd-xen.$DEV.conf//g" $DHCP_SYSCONFIG_FILE # remove the included config file from the dhcpd.conf file #--------------------------------------------------------------------- sed -i "/^include \"\/etc\/dhcpd-xen.$DEV.conf\"/d" $DHCPD_CONF_FILE 2>/dev/null ;; status) . $DHCPD_CONF_FILE echo echo "DHCP is running on the following interfaces:" echo " $DHCP_INTERFACE" echo ;; esac }