#!/bin/bash #============================================================================ # /etc/xen/vif-nat # # Script for configuring a vif in routed-nat mode. # The hotplugging system will call this script if it is specified either in # the device configuration given to Xend, or the default Xend configuration # in /etc/xen/xend-config.sxp. If the script is specified in neither of those # places, then vif-bridge is the default. # # Usage: # vif-nat (add|remove|online|offline) # # Environment vars: # vif vif interface name (required). # XENBUS_PATH path to this device's details in the XenStore (required). # # Parameters: # dhcp Whether to alter the local DHCP configuration to include this # new host (default no). # # Read from the store: # ip list of IP networks for the vif, space-separated (default given in # this script). #============================================================================ dir=$(dirname "$0") . "$dir/vif-common.sh" # turn on dhcp feature by default if dhcpd is installed if [ -f /etc/dhcpd.conf ] then dhcp=${dhcp:-yes} else dhcp=${dhcp:-no} fi if [ "$dhcp" != 'no' ] then dhcpd_conf_file=$(find_dhcpd_conf_file) dhcpd_init_file=$(find_dhcpd_init_file) dhcpd_arg_file=$(find_dhcpd_arg_file) if [ -z "$dhcpd_conf_file" ] || [ -z "$dhcpd_init_file" ] || [ -z "$dhcpd_arg_file" ] then echo 'Failed to find dhcpd configuration or init or args file.' >&2 exit 1 fi fi domid=$(xenstore_read "$XENBUS_PATH/frontend-id") vifid=$(xenstore_read "$XENBUS_PATH/handle") vifid=$(( $vifid + 1 )) ip_from_dom() { local domid1=$(( $domid / 256 )) local domid2=$(( $domid % 256 )) echo "10.$domid1.$domid2.$vifid/16" } routing_ip() { echo $(echo $1 | awk -F. '{print $1"."$2"."$3"."$4 + 127}') } dotted_quad() { echo\ $(( ($1 & 0xFF000000) >> 24))\ .$(( ($1 & 0x00FF0000) >> 16))\ .$(( ($1 & 0x0000FF00) >> 8 ))\ .$(( $1 & 0x000000FF )) } if [ "$ip" = "" ] then ip=$(ip_from_dom) fi router_ip=$(routing_ip "$ip") # Split the given IP/bits pair. vif_ip=`echo ${ip} | awk -F/ '{print $1}'` hostname=$(xenstore_read "$XENBUS_PATH/domain" | tr -- '_.:/+' '-----') if [ "$vifid" != "1" ] then hostname="$hostname-$vifid" fi dhcparg_remove_entry() { local tmpfile=$(mktemp) sed -e "s/$vif //" "$dhcpd_arg_file" >"$tmpfile" if diff "$tmpfile" "$dhcpd_arg_file" >/dev/null then rm "$tmpfile" else mv "$tmpfile" "$dhcpd_arg_file" fi } dhcparg_add_entry() { dhcparg_remove_entry local tmpfile=$(mktemp) # handle Red Hat, SUSE, and Debian styles, with or without quotes sed -e 's/^DHCPDARGS="*\([^"]*\)"*/DHCPDARGS="\1'"$vif "'"/' \ "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" sed -e 's/^DHCPD_INTERFACE="*\([^"]*\)"*/DHCPD_INTERFACE="\1'"$vif "'"/' \ "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" sed -e 's/^INTERFACES="*\([^"]*\)"*/INTERFACES="\1'"$vif "'"/' \ "$dhcpd_arg_file" >"$tmpfile" && mv "$tmpfile" "$dhcpd_arg_file" rm -f "$tmpfile" } dhcp_remove_entry() { local tmpfile=$(mktemp) grep -v "host $hostname" "$dhcpd_conf_file" >"$tmpfile" if diff "$tmpfile" "$dhcpd_conf_file" >/dev/null then rm "$tmpfile" else mv "$tmpfile" "$dhcpd_conf_file" fi dhcparg_remove_entry } dhcp_up() { claim_lock "vif-nat-dhcp" dhcp_remove_entry mac=$(xenstore_read "$XENBUS_PATH/mac") echo >>"$dhcpd_conf_file" \ "host $hostname { hardware ethernet $mac; fixed-address $vif_ip; option routers $router_ip; option host-name \"$hostname\"; }" dhcparg_add_entry release_lock "vif-nat-dhcp" "$dhcpd_init_file" restart || true } dhcp_down() { claim_lock "vif-nat-dhcp" dhcp_remove_entry release_lock "vif-nat-dhcp" "$dhcpd_init_file" restart || true # We need to ignore failure because # ISC dhcpd 3 borks if there is nothing # for it to do, which is the case if # the outgoing interface is not # configured to offer leases and there # are no vifs. } case "$command" in online) if ip route | grep -q "dev $vif" then log debug "$vif already up" exit 0 fi do_or_die ip link set "$vif" up arp on do_or_die ip addr add "$router_ip" dev "$vif" do_or_die ip route add "$vif_ip" dev "$vif" src "$router_ip" echo 1 >/proc/sys/net/ipv4/conf/${vif}/proxy_arp [ "$dhcp" != 'no' ] && dhcp_up ;; offline) [ "$dhcp" != 'no' ] && dhcp_down do_without_error ifconfig "$vif" down ;; esac handle_iptable log debug "Successful vif-nat $command for $vif." if [ "$command" = "online" ] then success fi