#!/bin/sh
#============================================================================
# multinet-common
#
# Version = 2.0.1
# Date = 2007-11-29
#
# 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 scripts
#
#============================================================================

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"

####  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  *****************************************

manage_routing() {
# Saves and restores the ip forward and Network Address Translation state
#  that exist before the script runs
#
# This function reads the start,stop parameter from the $CMD_OPT 
#  variable and responds respectively.

  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

      #------------------------------------------------------------------
      # 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
        sysctl -q -w net.bridge.bridge-nf-call-iptables="0"
        NAT_DONE="yes"
      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 $NETWORK_SAVE_PATH/init_ip_fwd_state
    ;;
  esac
}

manage_susefirewall2() {
  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
        echo "0" > $NETWORK_SAVE_PATH/sf2
        return 0
      else
        return 1
      fi
    ;;
    start)
      if [ -e $NETWORK_SAVE_PATH/sf2 ] && grep "0" $NETWORK_SAVE_PATH/sf2
      then
        echo ""
        echo "============================================================"
        echo "Starting SuSEfirewall2"
        echo "============================================================"
        /etc/init.d/SuSEfirewall2_setup start > /dev/null
        rm -rf $NETWORK_SAVE_PATH/sf2
        return 0
      else
        return 1
      fi
    ;;
  esac
}

manage_iptables() {
# Saves and restores the iptables rules that exist before the script runs
#
# This function reads the start,stop parameter from the $CMD_OPT 
#  variable and responds respectively.

  case $1 in
    stop)
      echo ""
      echo "============================================================"
      echo "Saving iptables rules"
      echo "============================================================"

      #----------------------------------------------------------------
      #  Saving iptables rules for $TABLE to a file
      #----------------------------------------------------------------
      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 "============================================================"

      #----------------------------------------------------------------
      #  Restoring iptables rules for $TABLE 
      #----------------------------------------------------------------
      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
}

#*****  Traditional Bridge Helper Functions  ********************************

setup_bridge_port() {
    local dev="$1"

    # take interface down ...
    ip link set ${dev} down

    # ... and configure it
    ip link set ${dev} arp off
    ip link set ${dev} multicast off
    ip link set ${dev} addr fe:ff:ff:ff:ff:ff
    ip addr flush ${dev}
}

create_bridge () {
# Usage: create_bridge bridge
    local bridge=$1

    # Don't create the bridge if it already exists.
    if [ ! -e "/sys/class/net/${bridge}/bridge" ]; then
	brctl addbr ${bridge}
	brctl stp ${bridge} off
	brctl setfd ${bridge} 0
        ip link set ${bridge} arp off
        ip link set ${bridge} multicast off
    fi
    ip link set ${bridge} up
}

add_to_bridge () {
# Usage: add_to_bridge bridge dev
    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
	ip link set ${dev} up || true
	return
    fi
    brctl addif ${bridge} ${dev}
    ip link set ${dev} up
}

add_to_bridge2() {
    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 () {
# Usage: transfer_addrs src dst
# Copy all IP addresses (including aliases) from device $src to device $dst.
    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 destination device
    ip route list | sed -ne "
/dev ${dst}\( \|$\)/ {
  s/^/ip route del /
  p
}" | sh -e
}

transfer_routes () {
# 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).
    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() {
##
# link_exists interface
#
# Returns 0 if the interface named exists (whether up or down), 1 otherwise.
#
    if ip link show "$1" >/dev/null 2>/dev/null
    then
        return 0
    else
        return 1
    fi
}

antispoofing () {
# Set 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() {
    local netdev=$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" = "$netdev" ] || [ "$etherdevice" = "$netdev" ] ; then
                link_exists "$vlan" && vlans="$vlans $vlan"
        fi
    done
    echo "$vlans"
}

get_ifcfg_file() {
  local HWD_CONFIG_0=
  local netdev="$DEV"
  eval `/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- -- "$netdev" | grep "HWD_CONFIG_0="`
  if [ -n "$HWD_CONFIG_0" ]; then
    hwddev="$HWD_CONFIG_0"
  fi
}

find_bridged_netdev () {
# Find the netdev that is associated with the bridge by matching MAC addresses.
    local bridge=$1

    bmac=`ip link show ${bridge} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
    for i in `ls /sys/class/net/${bridge}/brif` ; do
	mac=`ip link show ${i} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
	if [ "${bmac}" = "$MAC" ] && [ ! "${bridge}" = "${i}" ] ; then
	    netdev=${i}
	    return 0
	fi
    done
    return 1
}

create_bonded_bridge() {

  # passed in variabiles:
  #  start|stop $DEV $VDEV $PDEV $BRIDGE $VIF0

  local netdev="$2"
  local vdev="$3"
  local pdev="$4"
  local bridge="$5"
  local vif0="$6"

  vlans=$(find_active_vlans "${netdev}")
  for vlan in $vlans ; do ifdown $vlan ; done

  case $1 in
    start)
      local NETDEV_IP=`ip addr show dev ${netdev}|egrep '^ *inet '|sed "s/^ *inet //"|cut -d " " -f 1`
      local BONDSLAVE_LIST=`ifstatus ${netdev} | egrep -i "slave interface" | cut -d ":" -f 2 | sed "s/ //"`
      local MAC=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
      local BRIDGE_NUM=${netdev##${netdev%%[0-9]*}}
      local GATEWAY=`ip route show | grep "^default" | cut -d " " -f 3`
      PDEV=eth${BRIDGE_NUM}
      new_netdev=eth${BRIDGE_NUM}

      #echo "netdev = ${netdev}"
      #echo "NETDEV_IP = $NETDEV_IP"
      #echo "GATEWAY = $GATEWAY"
      #echo "BONDSLAVE_LIST = $BONDSLAVE_LIST"
      #echo "MAC = $MAC"
      #echo "BRIDGE_NUM = $BRIDGE_NUM"
      #echo "new_netdev = $new_netdev"
      #echo "vdev = $vdev"
      #echo "pdev = $pdev"
      #echo "bridge = $bridge"
      #echo "vif0 = $vif0"
      #read

      #ip link set ${bridge} arp on

      #####  We must reconfigure the bonded interface first  #####
      #echo "bring bonded interface ${netdev} down";read
      ip link set ${netdev} down
      ip link set ${netdev} arp off
      ip link set ${netdev} multicast off
      ip link set ${netdev} addr fe:ff:ff:ff:ff:ff
      ip addr flush ${netdev}

      #echo "rename the bondslave interfaces";read
      for DEV in $BONDSLAVE_LIST
      do
        ip link set ${DEV} name p${DEV}
      done

      #echo "bring ${netdev} back up with new bondslave names";read
      ifup ${netdev}
      #ip link set ${netdev} arp on
      #ip link set ${netdev} multicast on

      #####  Here is where we attach the bridge ports to the bridge  #####
      #echo "bring up the bridge ${bridge}";read
      ip link set ${bridge} up

      #echo "add ${netdev} to bridge as a bridge port";read
      add_to_bridge2 ${bridge} ${netdev}

      #echo "add ${vif0} to bridge as a ${bridge} port";read
      add_to_bridge ${bridge} ${vif0}

      #echo "clean up ${vif0} (arp off, change MAC, flush IP address, etc.)";read
      setup_bridge_port ${vif0}

      #echo "bring ${vif0} up";read
      ip link set ${vif0} up
      
      #####  Next we must configure the new interface for Dom0  #####
      #echo "make sure the ${vdev} interface is down";read
      ip link set ${vdev} down

      #echo "rename ${vdev} to ${pdev}";read
      ip link set ${vdev} name ${pdev}

      #echo "transfer ${netdev}'s MAC address to ${pdev} and turn arp on";read
      ip link set ${pdev} addr $MAC arp on

      #echo "bring new ${pdev} interface up";read
      ip link set ${pdev} up

      #echo "transfer ${netdev}'s IP address to ${pdev}";read
      ip addr add dev ${pdev} $NETDEV_IP brd +

      #echo "remove ${netdev}'s IP address";read
      ip addr del dev ${netdev} $NETDEV_IP

      #echo "transfer ${netdev}'s routes to ${pdev}";read
      #if ! echo ${netdev} | grep -qi "bond"
      #then
        transfer_routes ${netdev} ${pdev}
      #fi

      #echo "add new default route via ${pdev}";read
      ip route add default via $GATEWAY
    ;;
    stop)
      local BRIDGE_NUM=${netdev##${netdev%%[0-9]*}}
      local pdev=eth${BRIDGE_NUM}
      local new_netdev=eth${BRIDGE_NUM}
      local GATEWAY=`ip route show | grep "^default" | cut -d " " -f 3`
      local NETDEV_IP=`ip addr show dev ${pdev}|egrep '^ *inet '|sed "s/^ *inet //"|cut -d " " -f 1`
      local BONDSLAVE_LIST=`ifstatus ${netdev} | egrep -i "slave interface" | cut -d ":" -f 2 | sed "s/ //"`
      local MAC=`ip link show ${pdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
      
      #echo "netdev = ${netdev}"
      #echo "NETDEV_IP = $NETDEV_IP"
      #echo "BONDSLAVE_LIST = $BONDSLAVE_LIST"
      #echo "MAC = $MAC"
      #echo "BRIDGE_NUM = $BRIDGE_NUM"
      #echo "new_netdev = $new_netdev"
      #echo "vdev = $vdev"
      #echo "pdev = $pdev"
      #echo "bridge = $bridge"
      #echo "vif0 = $vif0"
      #read

      #####  First we reset the virtual interface ${pdev}  #####
      #echo "bring ${pdev} down";read
      ip link set ${pdev} down arp off
      ip link set ${pdev} addr fe:ff:ff:ff:ff:ff
      ip addr flush ${pdev}
      
      #####  Then we reset the bridge port ${vif0}  #####
      #echo "bring ${vif0} down";read
      ip link set dev ${vif0} down
      
      #####  Then we reset the bonded interface ${netdev}  #####
      #echo "bring the bonded interface ${netdev} down";read
      ip link set ${netdev} down
      #ip link set ${netdev} down arp off
      #ip link set ${netdev} addr fe:ff:ff:ff:ff:ff
      ip addr flush ${netdev}
      
      #####  Then we remove the bridge port interfaces from the bridge  #####
      #echo "removing ${netdev} from ${bridge}";read
      brctl delif ${bridge} ${netdev}

      #echo "removing ${vif0} from ${bridge}";read
      brctl delif ${bridge} ${vif0}
      
      #####  Then we rename the  virtual interface back to its original name  #####
      #echo "rename ${pdev} to ${vdev}";read
      ip link set ${pdev} name ${vdev}
      
      #####  Then we reset the renamed bond slave interface ${pdev}
      for DEV in $BONDSLAVE_LIST
      do
        local OLD_DEV=`echo ${DEV}|sed "s/p//"`
        #echo "bring the bond slave ${DEV} down";read
        ip link set ${DEV} down
        #echo "rename the bond slave ${DEV} to ${OLD_DEV}";read
        ip link set ${DEV} name ${OLD_DEV}
      done
      
      #####  And then we restart the bonded interface  #####
      #echo "bring bonded interface back up";read
      ifup ${netdev}
      
      #####  Then we bring the bridge ${bridge} down  #####
      #echo "bring the bridge ${bridge} down";read
      ip link set ${bridge} down
    ;;
  esac

  for vlan in $vlans ; do ifup $vlan ; done
}

create_normal_bridge() {

  # passed in variabiles:
  #  start|stop $DEV $VDEV $PDEV $BRIDGE $VIF0

  local netdev="$2"
  local vdev="$3"
  local pdev="$4"
  local bridge="$5"
  local vif0="$6"

  case $1 in 
    start)
	local mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`

        # Ensure there is an IP to transfer
	#echo "Ensure there is an IP to transfer. (ifup ${netdev})";read
	ifup ${netdev}

        # Transfer the IP address to the virtual interface
	#echo "Transfer the IP address from ${netdev} to ${vdev}";read
	transfer_addrs ${netdev} ${vdev}

        # Find and bring down any active VLANs
	#echo "Find and bring down any active VLANs";read
	local vlans=$(find_active_vlans "${netdev}")
	for vlan in $vlans ; do ifdown $vlan ; done

        # Bring down interface
	#echo "Bring down interface (ifdown ${netdev})";read
	ifdown ${netdev}

        # Rename physical and virtual interfaces
	#echo "Rename ${netdev} to ${pdev} & ${vdev} to ${netdev}";read
	ip link set ${netdev} name ${pdev}
	ip link set ${vdev} name ${netdev}

        # Configure $pdev and $vif0 as bridge ports
	#echo "Configure ${pdev} and ${vif0} as bridge ports";read
	setup_bridge_port ${pdev}
	setup_bridge_port ${vif0}

        # Assign the physical MAC to the new interface
	#echo "Assign the physical MAC to ${netdev}";read
	ip link set ${netdev} addr ${mac} arp on

        # Bring bridge up and add interfaces to it
	#echo "Bring ${bridge} up and add ${vif0} and ${pdev} to it";read
	ip link set ${bridge} up
	add_to_bridge  ${bridge} ${vif0}
	add_to_bridge2 ${bridge} ${pdev}

        # Bring new interface up
	#echo "Bring up ${netdev} and ${hwddev}";read
	ip link set ${netdev} up
	ifup ${hwddev}

        # Bring VLANs back up
	#echo "Bring VLANs back up";read
	for vlan in $vlans ; do ifup $vlan ; done
    ;;
    stop)
      # Bring down ${vif0}
      #echo "Bring down ${vif0}";read
      ip link set dev ${vif0} down

      local mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`

      # Transfer IP address back to original interface
      #echo "Transfer IP address from ${netdev} to ${pdev}";read
      transfer_addrs ${netdev} ${pdev}

      # Find and bring down any active VLANs
      #echo "Find and bring down any active VLANs";read
      vlans=$(find_active_vlans "${netdev}")
      for vlan in $vlans ; do ifdown $vlan ; done

      # Bring down virtual network interface
      #echo "Bring down ${netdev}";read
      ifdown ${netdev}

      # Clean up virtual network interfaces (MAC, arp, etc.)
      #echo "Clean up virtual network interfaces (MAC, arp, etc.)";read
      ip link set ${netdev} down arp off
      ip link set ${netdev} addr fe:ff:ff:ff:ff:ff

      # Bring down physical network interface
      #echo "Bring down ${pdev}";read
      ip link set ${pdev} down

      # Flush address(es) from virtual network interface
      #echo "Flush address(es) from ${netdev}";read
      ip addr flush ${netdev}

      # Change MAC address on physical interface
      #echo "Change MAC address on ${pdev}";read
      ip link set ${pdev} addr ${mac} arp on

      # Remove interfaces from bridge
      #echo "Remove interfaces ${pdev} and ${vif0} from ${bridge}";read
      brctl delif ${bridge} ${pdev}
      brctl delif ${bridge} ${vif0}

      # Bring down bridge
      #echo "Bring down ${bridge}";read
      ip link set ${bridge} down

      # Rename physical and virtual network interfaces
      #echo "Rename ${netdev} to ${vdev} & ${pdev} to ${netdev}";read
      ip link set ${netdev} name ${vdev}
      ip link set ${pdev} name ${netdev}

      # Bring renamed physical interface up
      #echo "Bring up ${netdev}";read
      ifup ${netdev}

      # Bring VLANs back up
      #echo "Bring VLANs back up";read
      for vlan in $vlans ; do ifup $vlan ; done
    ;;
  esac

}

#*****  NAT/HostOnly Helper Functions  **************************************

setup_host_interface() {
# Configure the MAC and IP address of a virtual device.
#
# This function is called by other fuctions.
#
# usage:  setup_host_interface  <virtual net device> <MAC Addr> <IP Addr>

  local DEV="$1"
  local MAC="$2"
  local IPADDR="$3"

  case $CMD_OPT in
    start)    
      # take the interface down
      ip link set $DEV down

      # ... and configure it
      ip link set $DEV addr $MAC
      ip addr flush $DEV
      ip addr add $IPADDR brd + dev $DEV

      # bring it back up
      ip link set $DEV up
      ip link set $DEV arp on
    ;;
    stop)
      # take the interface down
      ip link set $DEV down

      # unconfigure it
      ip link set $DEV addr fe:ff:ff:ff:ff:ff
      ip addr flush $DEV
    ;;
    status)
      ip addr show $DEV
    ;;
  esac
}

#*****  Network Type Creation Functions  ************************************

create_bridged_networks() {
# Creates traditional bridges on physical devices in Dom0.
#
# Variables passed in in order: $NET_DEV $NET_NUMBER

  local DEV=$1
  local NUMBER=$2
  local NAME=$BRIDGE_NAME$NUMBER
  local BRIDGE="$NAME"
  local VDEV="veth$VIF_COUNT"
  local PDEV="p$DEV"
  local VIF0="vif0.$VIF_COUNT"
  local VIF_NUM=$VIF_COUNT

  # Test if $BRIDGE is set
  if [ "$BRIDGE" = "null" ]
  then
      return
  fi

  case $CMD_OPT in
    start)
      if /sbin/ip link show $DEV | grep -qw UP
      then
        echo "" 
        echo "============================================================"
        echo "Configuring Virtual Network: $NAME"
        echo "                    of type: $TYPE"
        echo "    on-  Physical Interface: $DEV"
        echo "          Virtual Interface: vif$NUMBER"
        echo "============================================================"
        echo "" 
        #$SCRIPT_PATH/network_bridge $CMD_OPT netdev=$DEV bridge=$NAME vifnum=$VIF_NUM
        #network_bridge $DEV $NAME $VIF_NUM
  
        # Check if vethX exists and if pethX exists and is up. Fail if not
        if ! link_exists "$VDEV"
        then
          if link_exists "$PDEV"
          then
              # The device is already up.
              return
          else
              # output error message
              echo "
Link $VDEV is missing.
This may be because you have reached the limit of the number of interfaces
that the loopback driver supports.  If the loopback driver is a module, you
may raise this limit by passing it as a parameter (nloopbacks=<N>); if the
driver is compiled statically into the kernel, then you may set the parameter
using loopback.nloopbacks=<N> on the domain 0 kernel command line.
" >&2
              exit 1
          fi
        fi
  
        # Create the bridge
        create_bridge $BRIDGE
  
        # Find the corresponding ifcfg-eth-xxx file and source it
        get_ifcfg_file
        . /etc/sysconfig/network/ifcfg-${hwddev}
  
        # Check if physical interface is bonded or not and in vethX exists
        # Create bridge appropriately
        if [ ! "$BONDING_MASTER" = "yes" ] && link_exists "$VDEV"
        then
          # Create bridge with nornal network interface (i.e. ethX)
          create_normal_bridge start $DEV $VDEV $PDEV $BRIDGE $VIF0
        elif [ "$BONDING_MASTER" = "yes" ]
        then
          # Create bridge with bonded network interface
          create_bonded_bridge start $DEV $VDEV $PDEV $BRIDGE $VIF0
        else
          # Create old style bridge without $VDEV
          transfer_addrs  ${netdev} $BRIDGE
          transfer_routes ${netdev} $BRIDGE
        fi
  
        if [ "${antispoof}" = "yes" ]
        then
          antispoofing
        fi
  
        echo "" 
      else
        echo " Physical Interface $DEV is not up. Skipping $NAME"
      fi
    ;;
    stop)
      # Check if bridge exists.  Fail if not
      if ! link_exists "$BRIDGE"; then
	return
      fi

      echo "" 
      echo "============================================================"
      echo "Removing Virtual Network:  $NAME"
      echo "                 of type:  $TYPE"
      echo "from- Physical Interface:  $DEV"
      echo "       Virtual Interface:  vif$NUMBER"
      echo "============================================================"
      echo "" 

      # Find the corresponding ifcfg-eth-xxx file and source it
      if brctl show | grep "$BRIDGE" | grep -q "bond[0-9]"
      then
        hwddev=`brctl show | grep "$BRIDGE" | sed '/s.*bond\(.*\)/bond\1/g'`
        netdev=${hwddev}
      else
        get_ifcfg_file
      fi
      . /etc/sysconfig/network/ifcfg-${hwddev}

      # Check if physical interface is bonded or not and in pethX exists
      # Remove bridge appropriately
      if [ ! "$BONDING_MASTER" = "yes" ] && link_exists "$PDEV"
      then
        # Remove bridge with normal network interface (i.e. ethX)
        create_normal_bridge stop $DEV $VDEV $PDEV $BRIDGE $VIF0
      elif [ "$BONDING_MASTER" = "yes" ]
      then
        # Remove brisge with bonded network interface
        create_bonded_bridge stop $DEV $VDEV $PDEV $BRIDGE $VIF0
      else
        # Remove old style bridge without $VDEV
	if [ ${netdev} = $BRIDGE ]
        then
	    find_bridged_netdev $BRIDGE
	fi
	ip link set dev ${vif0} down
	transfer_routes $BRIDGE ${netdev}
	ip link set $BRIDGE down
      fi

      # Remove the bridge
      brctl delbr $BRIDGE

    ;;
    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
}

create_local_networks() {
# Creates bridges attached to virtual devices in Dom0 and enables nat or routing
#  on the bridges if specified.
#
# This fuction reads the start,stop,status parameter from the $CMD_OPT variable
#  and responds respectively.
#
# Variables passed in in order:
#     $NET_DEV $NET_TYPE $NET_NUMBER $NET_DEV_MAC $NET_DEV_IP $NET_DHCP_SRV


    # Set local function variables
    local DEV=$1
    local TYPE=$2
    local NUMBER=$3
    case $TYPE in
      hostonly)
        local NAME=$HOSTONLY_NAME$NUMBER
      ;;
      nat)
        local NAME=$NAT_NAME$NUMBER
      ;;
      route)
        local NAME=$ROUTE_NAME$NUMBER
      ;;
    esac
    local MAC=$4
    local IPADDR=$5
    local DHCP_SRV=$6
    local VIF=vif0.$VIF_COUNT

    local NAT_GW_IP=`echo $IPADDR|cut -d "," -f 3|cut -d "/" -f 1`
    local NAT_INTIF=$DEV
    local ROUTE_INTIF=$DEV
    
    case $CMD_OPT in
      start)
        if ! brctl show | grep -qw $DEV && /sbin/ip address show $DEV > /dev/null
        then
          #------------------------------------------------------------------
          # Create the bridge
          #------------------------------------------------------------------
          echo "" 
          echo "============================================================"
          echo "Configuring Virtual Network:   $NAME"
          echo "                    of type:   $TYPE"
          echo ""
          echo "     on-  Virtual Interface:   $VIF"
          echo "             Virtual Device:   $DEV"
          
          create_bridge $NAME > /dev/null 2>&1
          setup_bridge_port $VIF > /dev/null 2>&1
          add_to_bridge $NAME $VIF > /dev/null 2>&1
          setup_host_interface $DEV $MAC $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_EXTERNAL_INTERFACE"
            ;;
            ROUTE|route)  # Set up the bridge as Routed network
              echo "                    Gateway:   $NAT_GW_IP"
              echo "         External Interface:   $NAT_EXTERNAL_INTERFACE"
              iptables -t nat -A PREROUTING -i $ROUTE_INTIF -j ACCEPT
              #iptables -t filter -A FORWARD -i $NAT_INTIF -j ACCEPT
              #iptables -t filter -A FORWARD -i $NAT_INTIF -j ACCEPT
            ;;
            HOSTONLY|hostonly)  # Set up the bridge as hostonly network
              if [ "$IP_FWD" = "on" ]
              then
                iptables -t nat -A PREROUTING -i $NAT_INTIF -j DROP
              fi
            ;;
            esac
            echo "============================================================"
        else
          #------------------------------------------------------------------
          # Skip this bridge
          #------------------------------------------------------------------
          echo " Virtual Interface $DEV is already attached to a bridge or it does not exist."
          echo " Skipping $NAME"
        fi
      ;;
      stop)
        #------------------------------------------------------------------
        # Remove the bridge
        #------------------------------------------------------------------
        echo "" 
        echo "============================================================"
        echo "Removing Virtual Network:    $NAME"
        echo "                 of type:    $TYPE"
        echo ""
        echo " from- Virtual Interface:    $VIF"
        echo "          Virtual Device:    $DEV"
        
        #------------------------------------------------------------------
        #  First remove the hostonly / NAT / Routed configuration
        #------------------------------------------------------------------
        case $TYPE in
          NAT|nat)
            
          ;;
          ROUTE|route)
            # Clean out the bridge specific routing iptables rule
            iptables -t nat -D PREROUTING -i $ROUTE_INTIF -j ACCEPT
            #iptables -t filter -D FORWARD -i $DEV -j ACCEPT
            #iptables -t filter -D FORWARD -i $NAT_INTIF -j ACCEPT
          ;;
          HOSTONLY|hostonly)
            # Clean out the bridge specific nat iptables rule
            iptables -t nat -D PREROUTING -i $NAT_INTIF -j DROP
          ;;
        esac

        echo "============================================================"

        #------------------------------------------------------------------
        #  Then unconfigure the veth
        #------------------------------------------------------------------
        setup_host_interface $DEV $MAC $IPADDR > /dev/null 2>&1

        #------------------------------------------------------------------
        #  remove vif from the bridge
        #------------------------------------------------------------------
        brctl delif $NAME $VIF

        #------------------------------------------------------------------
        #  unconfigure the vif
        #------------------------------------------------------------------
        ip link set $VIF down
        ip link set $VIF addr fe:ff:ff:ff:ff:ff
        ip link set $VIF multicast on
        ip link set $VIF arp on
        ip addr flush $VIF

        #------------------------------------------------------------------
        #  and finaly unconfigure the bridge
        #------------------------------------------------------------------
        ip link set $NAME down
        brctl delbr $NAME
      ;;
      status)
        #------------------------------------------------------------------
        #  Show the status of the bridge
        #------------------------------------------------------------------
        echo "" 
        echo "============================================================"
        echo "Status of Virtual Network: $NAME"
        echo "                  of type: $TYPE"
        echo "   on-  Virtual Interface: $VIF"
        echo "           Virtual Device: $DEV"
        echo "============================================================"
        brctl show | grep -w "^$NAME"
        echo ""
        ip addr show $DEV
        echo "============================================================"
      ;;
      *)
        echo "The function create_local_networks requires the CMD_OPT variable"
        echo "to be set to one of the following:  start|stop|status"
        exit 1
      ;;
    esac
}

create_nohost_networks() {
# Creates bridges attached to an external interface but no devices in Dom0.
#
# This function reads the start,stop,status parameter from the $CMD_OPT 
#  variable and responds respectively.
#
# Variables passed in in order:  $NET_DEV $NET_NUMBER

  echo "" 
  echo "============================================================"
  local DEV=$1
  local PDEV=p$DEV
  local MAC=`ip link show $DEV | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
  local NUMBER=$2
  local NAME=$NOHOST_NAME$NUMBER

  case $CMD_OPT in
    start)
      if ! brctl show | grep -qw "^$NAME"
      then
        echo "" 
        echo "============================================================"
        echo "Configuring Virtual Network:   $NAME"
        echo "                    of type:   $TYPE"
        echo "        on-  Virtual Device:   $DEV"

        #  create the bridge
        create_bridge $NAME

        # back up the interface's info (MAC, etc)
        echo $MAC > $NETWORK_SAVE_PATH/$DEV-info

        # configure the interface as a bridge port
        setup_bridge_port $DEV

        # rename the physical interface
        ip link set $DEV name $PDEV

        # add the interface to the bridge
        add_to_bridge $NAME $PDEV
      fi
    ;;
    stop)
      if brctl show | grep -qw "^$NAME"
      then
        echo "============================================================"
        echo "Removing Virtual Network:    $NAME"
        echo "                 of type:    $TYPE"
        echo ""

        # bring the bridge down
        ip link set $NAME down

        # remove the interface from the bridge
        brctl delif $NAME $PDEV

        # remove the bridge
        brctl delbr $NAME

        # bring the interface down
        ip link set down $PDEV

        # reset the interface back to normal
        ip link set $PDEV arp on
        ip link set $PDEV multicast on

        # reset the interface back to its original name and MAC
        ip link set $PDEV name $DEV
        ip link set $DEV addr `cat $NETWORK_SAVE_PATH/$DEV-info`
        rm -f `cat $NETWORK_SAVE_PATH/$DEV-info`

        # bring the interface back up
        ifup $DEV
      fi
    ;;
    status)
      brctl show $NAME | grep -w "^$NAME"
    ;;
    *)
      echo "The function create_nohost_networks requires the CMD_OPT variable"
      echo "to be set to one of the following:  start|stop|status"
      exit 1
    ;;
  esac
  echo "============================================================"
}

create_empty_networks() {
# Creates bridges attached to no devices in Dom0.
#
# This function reads the start,stop,status parameter from the $CMD_OPT 
#  variable and responds respectively.
#
#  Variables passed in in order:  $NET_NUMBER

  echo "" 
  echo "============================================================"
  local NUMBER=$1
  local NAME=$EMPTY_NAME$NUMBER

  case $CMD_OPT in
    start)
      if ! brctl show | grep -qw "^$NAME"
      then
        echo "Configuring Virtual Network:   $NAME"
        echo "                    of type:   $TYPE"
        create_bridge $NAME
      fi
    ;;
    stop)
      if brctl show | grep -qw "^$NAME"
      then
        echo "Removing Virtual Network:   $NAME"
        echo "                 of type:   $TYPE"
        ip link set $NAME down
        brctl delbr $NAME
      fi
    ;;
    status)
    brctl show $NAME | grep -w "^$NAME"
    ;;
    *)
      echo "The function create_empty_networks requires the CMD_OPT variable"
      echo "to be set to one of the following:  start|stop|status"
      exit 1
    ;;
  esac
  echo "============================================================"
}



