#!/bin/sh #============================================================================ # Default Xen network start/stop script. # Xend calls a network script when it starts. # The script name to use is defined in /etc/xen/xend-config.sxp # in the network-script field. # # This script creates a bridge (default xenbr0), adds a device # (default eth0) to it, copies the IP addresses from the device # to the bridge and adjusts the routes accordingly. # # If all goes well, this should ensure that networking stays up. # However, some configurations are upset by this, especially # NFS roots. If the bridged setup does not meet your needs, # configure a different script, for example using routing instead. # # Usage: # # network (start|stop|status) {VAR=VAL}* # # Vars: # # bridge The bridge to use (default xenbr0). # netdev The interface to add to the bridge (default eth0). # antispoof Whether to use iptables to prevent spoofing (default yes). # # start: # Creates the bridge and enslaves netdev to it. # Copies the IP addresses from netdev to the bridge. # Deletes the routes to netdev and adds them on bridge. # # stop: # Removes netdev from the bridge. # Deletes the routes to bridge and adds them to netdev. # # status: # Print ifconfig for netdev and bridge. # Print routes. # #============================================================================ # Gentoo doesn't have ifup/ifdown: define appropriate alternatives which ifup >& /dev/null if [ "$?" != 0 -a -e /etc/conf.d/net ]; then ifup() { /etc/init.d/net.$1 start } ifdown() { /etc/init.d/net.$1 stop } fi # Exit if anything goes wrong. set -e # First arg is the operation. OP=$1 shift # Pull variables in args in to environment. for arg ; do export "${arg}" ; done bridge=${bridge:-xenbr0} netdev=${netdev:-eth0} antispoof=${antispoof:-no} echo "*network $OP bridge=$bridge netdev=$netdev antispoof=$antispoof" >&2 legacy_mask_to_prefix() { mask=$1 first=${mask%%.*} second=${mask#*.} third=${second#*.} fourth=${third#*.} second=${second%%.*} third=${third%%.*} declare -i INT FULLMASK BIT INT=$((((($first*256)+$second)*256+$third)*256+$fourth)) FULLMASK=4294967295 BIT=1 for bit in `seq 32 -1 0`; do if test $FULLMASK -eq $INT; then PREFIX=$bit; return; fi FULLMASK=$(($FULLMASK-$BIT)) BIT=$((BIT*2)) done echo "ERROR converting netmask $mask to prefix" exit 1 } # Usage: transfer_addrs src dst # Copy all IP addresses (including aliases) from device $src to device $dst. transfer_addrs () { local src=$1 local dst=$2 # Don't bother if $dst already has IP addresses. if ip addr show dev ${dst} | egrep -q '^ *inet ' ; then return fi # 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}/ " | sh -e # Remove automatic routes on destionation device ip route list | sed -ne " /dev ${dst}\( \|$\)/ { s/^/ip route del / p }" | sh -e } # Usage: del_addrs src del_addrs () { local src=$1 ip addr show dev ${src} | egrep '^ *inet ' | sed -e " s/inet/ip addr del/ s@\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\)/[0-9]\+@\1@ s/${src}/dev ${src}/ " | sh -e ip link set dev ${dst} up } # Usage: transfer_routes src dst # 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). transfer_routes () { 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 } # Usage: create_bridge bridge create_bridge () { local bridge=$1 # Don't create the bridge if it already exists. if ! brctl show | grep -q ${bridge} ; then brctl addbr ${bridge} brctl stp ${bridge} off brctl setfd ${bridge} 0 fi ip link set ${bridge} up } # Usage: add_to_bridge bridge dev add_to_bridge () { local bridge=$1 local dev=$2 # Don't add $dev to $bridge if it's already on a bridge. if ! brctl show | grep -q ${dev} ; then brctl addif ${bridge} ${dev} fi } # Usage: antispoofing dev bridge # Set the default forwarding policy for $dev to drop. # Allow forwarding to the bridge. antispoofing () { local dev=$1 local bridge=$2 iptables -P FORWARD DROP iptables -A FORWARD -m physdev --physdev-in ${dev} -j ACCEPT } # Usage: show_status dev bridge # Print ifconfig and routes. show_status () { local dev=$1 local bridge=$2 echo '============================================================' ip addr show ${dev} ip addr show ${bridge} echo ' ' brctl show ${bridge} echo ' ' ip route list echo ' ' route -n echo '============================================================' } op_start () { if [ "${bridge}" == "null" ] ; then return fi create_bridge ${bridge} if ! ip link show 2>/dev/null | grep -q "^[0-9]*: veth0"; then return fi if ip link show veth0 2>/dev/null >/dev/null; then mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'` eval `/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- -- ${netdev}` transfer_addrs ${netdev} veth0 if ! ifdown ${netdev}; then # if ifup didn't work, see if we have an ip= on cmd line if egrep 'ip=[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:' /proc/cmdline; then kip=`sed -e 's!.*ip=\([0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+\):.*!\1!' /proc/cmdline` kmask=`sed -e 's!.*ip=[^:]*:[^:]*:[^:]*:\([^:]*\):.*!\1!' /proc/cmdline` kgate=`sed -e 's!.*ip=[^:]*:[^:]*:\([^:]*\):.*!\1!' /proc/cmdline` ip link set ${netdev} down ip addr flush ${netdev} fi fi ip link set ${netdev} name p${netdev} ip link set veth0 name ${netdev} ip link set p${netdev} down arp off ip link set p${netdev} addr fe:ff:ff:ff:ff:ff ip addr flush p${netdev} ip link set ${netdev} addr ${mac} arp on add_to_bridge ${bridge} vif0.0 add_to_bridge ${bridge} p${netdev} ip link set ${bridge} up ip link set vif0.0 up ip link set p${netdev} up if ! ifup ${HWD_CONFIG_0} ${netdev} ; then if [ ${kip} ] ; then # use the addresses we grocked from /proc/cmdline if [ -z "${kmask}" ]; then PREFIX=32; else legacy_to_prefix ${kmask}; fi ip addr add ${kip}/${PREFIX} dev ${netdev} ip link set dev ${netdev} up [ ${kgate} ] && ip route add default via ${kgate} fi fi else # old style without veth0 transfer_addrs ${netdev} ${bridge} transfer_routes ${netdev} ${bridge} fi if [ ${antispoof} == 'yes' ] ; then antispoofing ${netdev} ${bridge} fi } op_stop () { if [ "${bridge}" == "null" ]; then return fi if ! ip link show ${bridge} >/dev/null 2>&1; then return fi if ip link show p${netdev} 2>/dev/null >/dev/null; then ip link set dev vif0.0 down mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'` transfer_addrs ${netdev} p${netdev} ifdown ${netdev} ip link set ${netdev} down arp off ip link set ${netdev} addr fe:ff:ff:ff:ff:ff ip link set p${netdev} down ip addr flush ${netdev} ip link set p${netdev} addr ${mac} arp on brctl delif ${bridge} p${netdev} brctl delif ${bridge} vif0.0 ip link set ${bridge} down ip link set ${netdev} name veth0 ip link set p${netdev} name ${netdev} ifup ${netdev} else transfer_routes ${bridge} ${netdev} ip link set ${bridge} down fi brctl delbr ${bridge} } case ${OP} in start) op_start ;; stop) op_stop ;; status) show_status ${netdev} ${bridge} ;; *) echo 'Unknown command: ' ${OP} >&2 echo 'Valid commands are: start, stop, status' >&2 exit 1 esac