summaryrefslogtreecommitdiffstats
path: root/os-plugins/plugins/xen/files/xen.examples/scripts/vif-nat
blob: 75bdf5c444365e287634ee7db8d306797595c9c2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/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