Use env var for logging script
[snf-network] / common.sh
1 #!/bin/bash
2
3 function try {
4
5   $1 &>/dev/null || true 
6
7 }
8
9 function clear_routed_setup_ipv4 {
10
11  arptables -D OUTPUT -o $INTERFACE --opcode request -j mangle
12  while ip rule del dev $INTERFACE; do :; done
13  iptables -D FORWARD -i $INTERFACE -p udp --dport 67 -j DROP
14
15 }
16
17 function clear_routed_setup_ipv6 {
18
19  while ip -6 rule del dev $INTERFACE; do :; done
20
21 }
22
23
24 function clear_routed_setup_firewall {
25
26   for oldchain in protected unprotected limited; do
27     iptables  -D FORWARD -o $INTERFACE -j $oldchain
28     ip6tables -D FORWARD -o $INTERFACE -j $oldchain
29   done
30
31 }
32
33 function clear_ebtables {
34
35   runlocked $RUNLOCKED_OPTS ebtables -D FORWARD -i $INTERFACE -j $FROM
36   runlocked $RUNLOCKED_OPTS ebtables -D INPUT -i $INTERFACE -j $FROM
37   runlocked $RUNLOCKED_OPTS ebtables -D FORWARD -o $INTERFACE -j $TO
38   runlocked $RUNLOCKED_OPTS ebtables -D OUTPUT -o $INTERFACE -j $TO
39
40   runlocked $RUNLOCKED_OPTS ebtables -X $FROM
41   runlocked $RUNLOCKED_OPTS ebtables -X $TO
42 }
43
44
45 function clear_nfdhcpd {
46
47   rm $NFDHCPD_STATE_DIR/$INTERFACE
48
49 }
50
51
52 function routed_setup_ipv4 {
53
54   if [ -z "$INTERFACE" -o -z "$NETWORK_GATEWAY" -o -z "$IP" -o -z "$TABLE" ]
55   then
56     return
57   fi
58
59         # mangle ARPs to come from the gw's IP
60         arptables -A OUTPUT -o $INTERFACE --opcode request -j mangle --mangle-ip-s    "$NETWORK_GATEWAY"
61
62         # route interface to the proper routing table
63         ip rule add dev $INTERFACE table $TABLE
64
65         # static route mapping IP -> INTERFACE
66         ip route replace $IP proto static dev $INTERFACE table $TABLE
67
68         # Enable proxy ARP
69         echo 1 > /proc/sys/net/ipv4/conf/$INTERFACE/proxy_arp
70
71   # Send GARP from host to upstream router
72   get_uplink $TABLE
73   echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind
74   $SNF_NETWORK_LOG $0 "arping  -c3 -I $UPLINK -U $IP"
75   arping  -c3 -I $UPLINK -U $IP
76   echo 0 > /proc/sys/net/ipv4/ip_nonlocal_bind
77
78 }
79
80 function routed_setup_ipv6 {
81         # Add a routing entry for the eui-64
82   get_uplink $TABLE "-6"
83   get_eui64 $MAC $NETWORK_SUBNET6
84
85   if [ -z "$EUI64" -o -z "$TABLE" -o -z "$INTERFACE" -o -z "$UPLINK" ]
86   then
87     return
88   fi
89
90         ip -6 rule add dev $INTERFACE table $TABLE
91         ip -6 ro replace $EUI64/128 dev $INTERFACE table $TABLE
92         ip -6 neigh add proxy $EUI64 dev $UPLINK
93
94         # disable proxy NDP since we're handling this on userspace
95         # this should be the default, but better safe than sorry
96         echo 0 > /proc/sys/net/ipv6/conf/$INTERFACE/proxy_ndp
97
98   # Send Unsolicited Neighbor Advertisement
99   $SNF_NETWORK_LOG $0 "ndsend $EUI64 $UPLINK"
100   ndsend $EUI64 $UPLINK
101
102 }
103
104 # pick a firewall profile per NIC, based on tags (and apply it)
105 function routed_setup_firewall {
106         # for latest ganeti there is no need to check other but uuid
107         ifprefixindex="synnefo:network:$INTERFACE_INDEX:"
108         ifprefixname="synnefo:network:$INTERFACE_NAME:"
109         ifprefixuuid="synnefo:network:$INTERFACE_UUID:"
110         for tag in $TAGS; do
111                 tag=${tag#$ifprefixindex}
112                 tag=${tag#$ifprefixname}
113                 tag=${tag#$ifprefixuuid}
114                 case $tag in
115                 protected)
116                         chain=protected
117                 ;;
118                 unprotected)
119                         chain=unprotected
120                 ;;
121                 limited)
122                         chain=limited
123                 ;;
124                 esac
125         done
126
127         if [ "x$chain" != "x" ]; then
128                 iptables  -A FORWARD -o $INTERFACE -j $chain
129                 ip6tables -A FORWARD -o $INTERFACE -j $chain
130         fi
131 }
132
133 function init_ebtables {
134
135   runlocked $RUNLOCKED_OPTS ebtables -N $FROM -P RETURN
136   runlocked $RUNLOCKED_OPTS ebtables -A FORWARD -i $INTERFACE -j $FROM
137   # This is needed for multicast packets
138   runlocked $RUNLOCKED_OPTS ebtables -A INPUT -i $INTERFACE -j $FROM
139
140   runlocked $RUNLOCKED_OPTS ebtables -N $TO -P RETURN
141   runlocked $RUNLOCKED_OPTS ebtables -A FORWARD -o $INTERFACE -j $TO
142   # This is needed for multicast packets
143   runlocked $RUNLOCKED_OPTS ebtables -A OUTPUT -o $INTERFACE -j $TO
144
145 }
146
147
148 function setup_ebtables {
149
150   # do not allow changes in ip-mac pair
151   if [ -n "$IP" ]; then
152     :; # runlocked $RUNLOCKED_OPTS ebtables -A $FROM --ip-source \! $IP -p ipv4 -j DROP
153   fi
154   runlocked $RUNLOCKED_OPTS ebtables -A $FROM -s \! $MAC -j DROP
155   # accept dhcp responses from host (nfdhcpd)
156   # this is actually not needed because nfdhcpd opens a socket and binds is with
157   # tap interface so dhcp response does not go through bridge
158   # runlocked $RUNLOCKED_OPTS ebtables -A $TO -s $INDEV_MAC -p ipv4 --ip-protocol=udp  --ip-destination-port=68 -j ACCEPT
159   # allow only packets from the same mac prefix
160   runlocked $RUNLOCKED_OPTS ebtables -A $TO -s \! $MAC/$MAC_MASK -j DROP
161 }
162
163 function setup_masq {
164
165   # allow packets from/to router (for masquerading)
166   # runlocked $RUNLOCKED_OPTS ebtables -A $TO -s $NODE_MAC -j ACCEPT
167   # runlocked $RUNLOCKED_OPTS ebtables -A INPUT -i $INTERFACE -j $FROM
168   # runlocked $RUNLOCKED_OPTS ebtables -A OUTPUT -o $INTERFACE -j $TO
169   return
170
171 }
172
173 function setup_nfdhcpd {
174         umask 022
175   FILE=$NFDHCPD_STATE_DIR/$INTERFACE
176   #IFACE is the interface from which the packet seems to arrive
177   #needed in bridged mode where the packets seems to arrive from the
178   #bridge and not from the tap
179         cat >$FILE <<EOF
180 INDEV=$INDEV
181 IP=$IP
182 MAC=$MAC
183 HOSTNAME=$INSTANCE
184 TAGS="$TAGS"
185 GATEWAY=$NETWORK_GATEWAY
186 SUBNET=$NETWORK_SUBNET
187 GATEWAY6=$NETWORK_GATEWAY6
188 SUBNET6=$NETWORK_SUBNET6
189 EUI64=$($MAC2EUI64 $MAC $NETWORK_SUBNET6 2>/dev/null)
190 EOF
191
192 }
193
194 function get_uplink {
195
196   local table=$1
197   local version=$2
198   UPLINK=$(ip "$version" route list table "$table" | grep "default via" | awk '{print $5}')
199
200 }
201
202 # Because we do not have IPv6 value in our environment
203 # we caclulate it based on the NIC's MAC and the IPv6 subnet (if any)
204 # first argument MAC second IPv6 subnet
205 # Changes global value EUI64
206 get_eui64 () {
207
208   local mac=$1
209   local prefix=$2
210
211   if [ -z "$prefix" ]; then
212     EUI64=
213   else
214     EUI64=$($MAC2EUI64 $mac $prefix)
215   fi
216
217 }
218
219
220 # DDNS related functions
221
222 # ommit zone statement
223 # nsupdate  will attempt determine the correct zone to update based on the rest of the input
224 send_command () {
225
226   local command="$1"
227   $SNF_NETWORK_LOG dnshook "$command"
228   nsupdate -k $KEYFILE > /dev/null << EOF
229   server $SERVER
230   $command
231   send
232 EOF
233
234 }
235
236
237 update_arecord () {
238
239   local action=$1
240   local command=
241   if [ -n "$IP" ]; then
242     command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL A $IP"
243     send_command "$command"
244   fi
245
246 }
247
248
249 update_aaaarecord () {
250
251   local action=$1
252   local command=
253   if [ -n "$EUI64" ]; then
254     command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL AAAA $EUI64"
255     send_command "$command"
256   fi
257
258 }
259
260
261 update_ptrrecord () {
262
263   local action=$1
264   local command=
265   if [ -n "$IP" ]; then
266     command="update $action $RLPART.$RZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
267     send_command "$command"
268   fi
269
270 }
271
272 update_ptr6record () {
273
274   local action=$1
275   local command=
276   if [ -n "$EUI64" ]; then
277     command="update $action $R6LPART$R6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
278     send_command "$command"
279   fi
280
281 }
282
283 update_all () {
284
285   local action=$1
286   update_arecord $action
287   update_aaaarecord $action
288   update_ptrrecord $action
289   update_ptr6record $action
290
291 }
292
293
294 # first argument is an eui64 (IPv6)
295 # sets GLOBAL args R6REC, R6ZONE, R6LPART
296 # lets assume eui64=2001:648:2ffc:1::1
297 # the following commands produce:
298 # R6REC=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
299 # R6ZONE=1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
300 # R6LPART=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
301 get_rev6_info () {
302
303   local eui64=$1
304   if [ -z "$eui64" ]; then
305     R6REC= ; R6ZONE= ; R6LPART= ;
306   else
307     R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
308     R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
309     R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
310   fi
311
312 }
313
314
315 # first argument is an ipv4
316 # sets args RZONE, RLPART
317 # lets assume IP=203.0.113.1
318 # RZONE="113.0.203.in-add.arpa"
319 # RLPART="1"
320 get_rev4_info () {
321
322   local ip=$1
323   if [ -z "$ip" ]; then
324     RZONE= ; RLPART= ;
325   else
326     OLDIFS=$IFS
327     IFS=". "
328     set -- $ip
329     a=$1 ; b=$2; c=$3; d=$4;
330     IFS=$OLDIFS
331     RZONE="$c.$b.$a.in-addr.arpa"
332     RLPART="$d"
333   fi
334
335 }
336
337
338 # Query nameserver for entries related to the specific instance
339 # An example output is the following:
340 # www.google.com has address 173.194.113.114
341 # www.google.com has address 173.194.113.115
342 # www.google.com has address 173.194.113.116
343 # www.google.com has address 173.194.113.112
344 # www.google.com has address 173.194.113.113
345 # www.google.com has IPv6 address 2a00:1450:4001:80b::1012
346 query_dns () {
347
348   HOSTQ="host -s -R 3 -W 3"
349   HOST_IP_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has address //p')
350   HOST_IP6_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has IPv6 address //p')
351
352 }