Statistics
| Branch: | Tag: | Revision:

root / common.sh @ cc09dec1

History | View | Annotate | Download (9.8 kB)

1
#!/bin/bash
2

    
3
source /etc/default/snf-network
4

    
5
function try {
6

    
7
  $1 &>/dev/null || true
8

    
9
}
10

    
11
function clear_routed_setup_ipv4 {
12

    
13
 arptables -D OUTPUT -o $INTERFACE --opcode request -j mangle
14
 while ip rule del dev $INTERFACE; do :; done
15
 iptables -D FORWARD -i $INTERFACE -p udp --dport 67 -j DROP
16

    
17
}
18

    
19
function clear_routed_setup_ipv6 {
20

    
21
 while ip -6 rule del dev $INTERFACE; do :; done
22

    
23
}
24

    
25
function delete_neighbor_proxy {
26

    
27
  if [ -z "$EUI64" -z -o "$UPLINK6" ]; then
28
    return
29
  fi
30

    
31
  $SNF_NETWORK_LOG $0 "ip -6 neigh del proxy $EUI64 dev $UPLINK6"
32
  ip -6 neigh del proxy $EUI64 dev $UPLINK6
33

    
34
}
35

    
36
function clear_routed_setup_firewall {
37

    
38
  for oldchain in protected unprotected limited; do
39
    iptables  -D FORWARD -o $INTERFACE -j $oldchain
40
    ip6tables -D FORWARD -o $INTERFACE -j $oldchain
41
  done
42

    
43
}
44

    
45
function clear_ebtables {
46

    
47
  runlocked $RUNLOCKED_OPTS ebtables -D FORWARD -i $INTERFACE -j $FROM
48
  runlocked $RUNLOCKED_OPTS ebtables -D INPUT -i $INTERFACE -j $FROM
49
  runlocked $RUNLOCKED_OPTS ebtables -D FORWARD -o $INTERFACE -j $TO
50
  runlocked $RUNLOCKED_OPTS ebtables -D OUTPUT -o $INTERFACE -j $TO
51

    
52
  runlocked $RUNLOCKED_OPTS ebtables -X $FROM
53
  runlocked $RUNLOCKED_OPTS ebtables -X $TO
54
}
55

    
56

    
57
function clear_nfdhcpd {
58

    
59
  rm $NFDHCPD_STATE_DIR/$INTERFACE
60

    
61
}
62

    
63

    
64
function routed_setup_ipv4 {
65

    
66
  if [ -z "$INTERFACE" -o -z "$NETWORK_GATEWAY" -o -z "$IP" -o -z "$TABLE" ]
67
  then
68
    return
69
  fi
70

    
71
	# mangle ARPs to come from the gw's IP
72
	arptables -A OUTPUT -o $INTERFACE --opcode request -j mangle --mangle-ip-s    "$NETWORK_GATEWAY"
73

    
74
	# route interface to the proper routing table
75
	ip rule add dev $INTERFACE table $TABLE
76

    
77
	# static route mapping IP -> INTERFACE
78
	ip route replace $IP proto static dev $INTERFACE table $TABLE
79

    
80
	# Enable proxy ARP
81
	echo 1 > /proc/sys/net/ipv4/conf/$INTERFACE/proxy_arp
82

    
83
}
84

    
85
function send_garp {
86

    
87
  if [ -z "$IP" -o -z "$UPLINK" ]; then
88
    return
89
  fi
90

    
91
  # Send GARP from host to upstream router
92
  echo 1 > /proc/sys/net/ipv4/ip_nonlocal_bind
93
  $SNF_NETWORK_LOG $0 "arpsend -U -i $IP -c1 $UPLINK"
94
  arpsend -U -i $IP -c1 $UPLINK
95
  echo 0 > /proc/sys/net/ipv4/ip_nonlocal_bind
96

    
97
}
98

    
99
function routed_setup_ipv6 {
100

    
101
  if [ -z "$EUI64" -o -z "$TABLE" -o -z "$INTERFACE" -o -z "$UPLINK6" ]
102
  then
103
    return
104
  fi
105
	# Add a routing entry for the eui-64
106
	ip -6 rule add dev $INTERFACE table $TABLE
107
	ip -6 ro replace $EUI64/128 dev $INTERFACE table $TABLE
108
	ip -6 neigh add proxy $EUI64 dev $UPLINK6
109

    
110
	# disable proxy NDP since we're handling this on userspace
111
	# this should be the default, but better safe than sorry
112
	echo 0 > /proc/sys/net/ipv6/conf/$INTERFACE/proxy_ndp
113

    
114
  # Send Unsolicited Neighbor Advertisement
115
  $SNF_NETWORK_LOG $0 "ndsend $EUI64 $UPLINK6"
116
  ndsend $EUI64 $UPLINK6
117

    
118
}
119

    
120
# pick a firewall profile per NIC, based on tags (and apply it)
121
function routed_setup_firewall {
122
	# for latest ganeti there is no need to check other but uuid
123
	ifprefixindex="synnefo:network:$INTERFACE_INDEX:"
124
	ifprefixname="synnefo:network:$INTERFACE_NAME:"
125
	ifprefixuuid="synnefo:network:$INTERFACE_UUID:"
126
	for tag in $TAGS; do
127
		tag=${tag#$ifprefixindex}
128
		tag=${tag#$ifprefixname}
129
		tag=${tag#$ifprefixuuid}
130
		case $tag in
131
		protected)
132
			chain=protected
133
		;;
134
		unprotected)
135
			chain=unprotected
136
		;;
137
		limited)
138
			chain=limited
139
		;;
140
		esac
141
	done
142

    
143
	if [ "x$chain" != "x" ]; then
144
		iptables  -A FORWARD -o $INTERFACE -j $chain
145
		ip6tables -A FORWARD -o $INTERFACE -j $chain
146
	fi
147
}
148

    
149
function init_ebtables {
150

    
151
  runlocked $RUNLOCKED_OPTS ebtables -N $FROM -P RETURN
152
  runlocked $RUNLOCKED_OPTS ebtables -A FORWARD -i $INTERFACE -j $FROM
153
  # This is needed for multicast packets
154
  runlocked $RUNLOCKED_OPTS ebtables -A INPUT -i $INTERFACE -j $FROM
155

    
156
  runlocked $RUNLOCKED_OPTS ebtables -N $TO -P RETURN
157
  runlocked $RUNLOCKED_OPTS ebtables -A FORWARD -o $INTERFACE -j $TO
158
  # This is needed for multicast packets
159
  runlocked $RUNLOCKED_OPTS ebtables -A OUTPUT -o $INTERFACE -j $TO
160

    
161
}
162

    
163

    
164
function setup_ebtables {
165

    
166
  # do not allow changes in ip-mac pair
167
  if [ -n "$IP" ]; then
168
    :; # runlocked $RUNLOCKED_OPTS ebtables -A $FROM --ip-source \! $IP -p ipv4 -j DROP
169
  fi
170
  runlocked $RUNLOCKED_OPTS ebtables -A $FROM -s \! $MAC -j DROP
171
  # accept dhcp responses from host (nfdhcpd)
172
  # this is actually not needed because nfdhcpd opens a socket and binds is with
173
  # tap interface so dhcp response does not go through bridge
174
  # INDEV_MAC=$(cat /sys/class/net/$INDEV/address)
175
  # runlocked $RUNLOCKED_OPTS ebtables -A $TO -s $INDEV_MAC -p ipv4 --ip-protocol=udp  --ip-destination-port=68 -j ACCEPT
176
  # allow only packets from the same mac prefix
177
  runlocked $RUNLOCKED_OPTS ebtables -A $TO -s \! $MAC/$MAC_MASK -j DROP
178
}
179

    
180
function setup_masq {
181

    
182
  # allow packets from/to router (for masquerading)
183
  # runlocked $RUNLOCKED_OPTS ebtables -A $TO -s $NODE_MAC -j ACCEPT
184
  # runlocked $RUNLOCKED_OPTS ebtables -A INPUT -i $INTERFACE -j $FROM
185
  # runlocked $RUNLOCKED_OPTS ebtables -A OUTPUT -o $INTERFACE -j $TO
186
  return
187

    
188
}
189

    
190
function setup_nfdhcpd {
191
	umask 022
192
  FILE=$NFDHCPD_STATE_DIR/$INTERFACE
193
  #IFACE is the interface from which the packet seems to arrive
194
  #needed in bridged mode where the packets seems to arrive from the
195
  #bridge and not from the tap
196
	cat >$FILE <<EOF
197
INDEV=$INDEV
198
IP=$IP
199
MAC=$MAC
200
HOSTNAME=$INSTANCE
201
TAGS="$TAGS"
202
GATEWAY=$NETWORK_GATEWAY
203
SUBNET=$NETWORK_SUBNET
204
GATEWAY6=$NETWORK_GATEWAY6
205
SUBNET6=$NETWORK_SUBNET6
206
EUI64=$EUI64
207
EOF
208

    
209
}
210

    
211
function get_uplink {
212

    
213
  local table=$1
214
  UPLINK=$(ip route list table $table | grep "default via" | awk '{print $5}')
215
  UPLINK6=$(ip -6 route list table $table | grep "default via" | awk '{print $5}')
216
  if [ -n "$UPLINK" -o -n "$UPLINK6" ]; then
217
    $SNF_NETWORK_LOG $0 "* Table $table: uplink -> $UPLINK, uplink6 -> $UPLINK6"
218
  fi
219

    
220
}
221

    
222
# Because we do not have IPv6 value in our environment
223
# we caclulate it based on the NIC's MAC and the IPv6 subnet (if any)
224
# first argument MAC second IPv6 subnet
225
# Changes global value EUI64
226
get_eui64 () {
227

    
228
  local mac=$1
229
  local prefix=$2
230

    
231
  if [ -z "$prefix" ]; then
232
    EUI64=
233
  else
234
    EUI64=$($MAC2EUI64 $mac $prefix)
235
    $SNF_NETWORK_LOG $0 "* $mac + $prefix -> $EUI64"
236
  fi
237

    
238
}
239

    
240

    
241
# DDNS related functions
242

    
243
# ommit zone statement
244
# nsupdate  will attempt determine the correct zone to update based on the rest of the input
245
send_command () {
246

    
247
  local command="$1"
248
  $SNF_NETWORK_LOG $0 "* $command"
249
  nsupdate -k $KEYFILE > /dev/null << EOF
250
  server $SERVER
251
  $command
252
  send
253
EOF
254

    
255
}
256

    
257

    
258
update_arecord () {
259

    
260
  local action=$1
261
  local command=
262
  if [ -n "$IP" ]; then
263
    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL A $IP"
264
    send_command "$command"
265
  fi
266

    
267
}
268

    
269

    
270
update_aaaarecord () {
271

    
272
  local action=$1
273
  local command=
274
  if [ -n "$EUI64" ]; then
275
    command="update $action $GANETI_INSTANCE_NAME.$FZONE $TTL AAAA $EUI64"
276
    send_command "$command"
277
  fi
278

    
279
}
280

    
281

    
282
update_ptrrecord () {
283

    
284
  local action=$1
285
  local command=
286
  if [ -n "$IP" ]; then
287
    command="update $action $RLPART.$RZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
288
    send_command "$command"
289
  fi
290

    
291
}
292

    
293
update_ptr6record () {
294

    
295
  local action=$1
296
  local command=
297
  if [ -n "$EUI64" ]; then
298
    command="update $action $R6LPART$R6ZONE. $TTL PTR $GANETI_INSTANCE_NAME.$FZONE"
299
    send_command "$command"
300
  fi
301

    
302
}
303

    
304
update_all () {
305

    
306
  local action=$1
307
  $SNF_NETWORK_LOG $0 "Update ($action) dns for $GANETI_INSTANCE_NAME $IP $EUI64"
308
  update_arecord $action
309
  update_aaaarecord $action
310
  update_ptrrecord $action
311
  update_ptr6record $action
312

    
313
}
314

    
315

    
316
# first argument is an eui64 (IPv6)
317
# sets GLOBAL args R6REC, R6ZONE, R6LPART
318
# lets assume eui64=2001:648:2ffc:1::1
319
# the following commands produce:
320
# 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
321
# R6ZONE=1.0.0.0.c.f.f.2.8.4.6.0.1.0.0.2.ip6.arpa
322
# R6LPART=1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.
323
get_rev6_info () {
324

    
325
  local eui64=$1
326
  if [ -z "$eui64" ]; then
327
    R6REC= ; R6ZONE= ; R6LPART= ;
328
  else
329
    R6REC=$(host $eui64 | egrep -o '([[:alnum:]]\.){32}ip6.arpa' )
330
    R6ZONE=$(echo $R6REC | awk -F. 'BEGIN{rpart="";} { for (i=32;i>16;i=i-1) rpart=$i "." rpart; } END{print rpart "ip6.arpa";}')
331
    R6LPART=$(echo $R6REC | awk -F. 'BEGIN{lpart="";} { for (i=16;i>0;i=i-1) lpart=$i "." lpart; } END{print lpart;}')
332
  fi
333

    
334
}
335

    
336

    
337
# first argument is an ipv4
338
# sets args RZONE, RLPART
339
# lets assume IP=203.0.113.1
340
# RZONE="113.0.203.in-add.arpa"
341
# RLPART="1"
342
get_rev4_info () {
343

    
344
  local ip=$1
345
  if [ -z "$ip" ]; then
346
    RZONE= ; RLPART= ;
347
  else
348
    OLDIFS=$IFS
349
    IFS=". "
350
    set -- $ip
351
    a=$1 ; b=$2; c=$3; d=$4;
352
    IFS=$OLDIFS
353
    RZONE="$c.$b.$a.in-addr.arpa"
354
    RLPART="$d"
355
  fi
356

    
357
}
358

    
359
get_ebtables_chains () {
360

    
361
  local iface=$1
362
  FROM=FROM${iface^^}
363
  TO=TO${iface^^}
364

    
365
}
366

    
367
get_instance_info () {
368

    
369
  if [ -z "$GANETI_INSTANCE_NAME" -a -n "$INSTANCE" ]; then
370
    GANETI_INSTANCE_NAME=$INSTANCE
371
  fi
372

    
373
}
374

    
375
get_mode_info () {
376

    
377
  local iface=$1
378
  local mode=$2
379
  local link=$3
380

    
381
  TABLE=
382
  INDEV=
383

    
384
  if [ "$mode" = "routed" ]; then
385
    TABLE=$link
386
    INDEV=$iface
387
  elif [ "$mode" = "bridged" ]; then
388
    INDEV=$link
389
  fi
390

    
391
}
392

    
393

    
394
# Use environment variables to calculate desired info
395
# IP, MAC, LINK, TABLE, BRIDGE,
396
# NETWORK_SUBNET, NETWORK_GATEWAY, NETWORK_SUBNET6, NETWORK_GATEWAY6
397
function get_info {
398

    
399
  $SNF_NETWORK_LOG $0 "Getting info for $INTERFACE of $GANETI_INSTANCE_NAME"
400
  get_instance_info
401
  get_mode_info $INTERFACE $MODE $LINK
402
  get_ebtables_chains $INTERFACE
403
  get_rev4_info $IP
404
  get_eui64 $MAC $NETWORK_SUBNET6
405
  get_rev6_info $EUI64
406
  get_uplink $TABLE
407

    
408
}
409

    
410

    
411
# Query nameserver for entries related to the specific instance
412
# An example output is the following:
413
# www.google.com has address 173.194.113.114
414
# www.google.com has address 173.194.113.115
415
# www.google.com has address 173.194.113.116
416
# www.google.com has address 173.194.113.112
417
# www.google.com has address 173.194.113.113
418
# www.google.com has IPv6 address 2a00:1450:4001:80b::1012
419
query_dns () {
420

    
421
  HOSTQ="host -s -R 3 -W 3"
422
  HOST_IP_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has address //p')
423
  HOST_IP6_ALL=$($HOSTQ $GANETI_INSTANCE_NAME.$FZONE $SERVER | sed -n 's/.*has IPv6 address //p')
424

    
425
}