ctdb-eventscripts: Make 11.natgw stateful
[Samba.git] / ctdb / config / events.d / 11.natgw
blobe107f47db7780a936cee5f6aadf366f7b2aad9d2
1 #!/bin/sh
2 # Script to set up one of the nodes as a NAT gateway for all other nodes.
3 # This is used to ensure that all nodes in the cluster can still originate
4 # traffic to the external network even if there are no public addresses
5 # available.
8 [ -n "$CTDB_BASE" ] || \
9 export CTDB_BASE=$(cd -P $(dirname "$0") ; dirname "$PWD")
11 . $CTDB_BASE/functions
13 service_name=natgw
15 loadconfig
17 [ -n "$CTDB_NATGW_NODES" ] || exit 0
18 export CTDB_NATGW_NODES
20 ctdb_setup_service_state_dir
22 natgw_cfg_new="${service_state_dir}/cfg_new"
23 natgw_cfg_old="${service_state_dir}/cfg_old"
24 natgw_master_old="${service_state_dir}/master_old"
26 natgw_check_config ()
28 [ -r "$CTDB_NATGW_NODES" ] || \
29 die "error: CTDB_NATGW_NODES=${CTDB_NATGW_NODES} unreadable"
30 if [ "$CTDB_NATGW_SLAVE_ONLY" != "yes" ] ; then
31 [ -n "$CTDB_NATGW_PUBLIC_IP" ] || \
32 die "Invalid configuration: CTDB_NATGW_PUBLIC_IP not set"
33 [ -n "$CTDB_NATGW_PUBLIC_IFACE" ] || \
34 die "Invalid configuration: CTDB_NATGW_PUBLIC_IFACE not set"
36 [ -n "$CTDB_NATGW_PRIVATE_NETWORK" ] || \
37 die "Invalid configuration: CTDB_NATGW_PRIVATE_NETWORK not set"
39 # The default is to create a single default route
40 [ -n "$CTDB_NATGW_STATIC_ROUTES" ] || CTDB_NATGW_STATIC_ROUTES="0.0.0.0/0"
43 natgw_write_config ()
45 _f="$1"
47 cat >"$_f" <<EOF
48 CTDB_NATGW_NODES="$CTDB_NATGW_NODES"
49 CTDB_NATGW_PUBLIC_IP="$CTDB_NATGW_PUBLIC_IP"
50 CTDB_NATGW_PUBLIC_IFACE="$CTDB_NATGW_PUBLIC_IFACE"
51 CTDB_NATGW_DEFAULT_GATEWAY="$CTDB_NATGW_DEFAULT_GATEWAY"
52 CTDB_NATGW_PRIVATE_NETWORK="$CTDB_NATGW_PRIVATE_NETWORK"
53 CTDB_NATGW_STATIC_ROUTES="$CTDB_NATGW_STATIC_ROUTES"
54 CTDB_NATGW_SLAVE_ONLY="$CTDB_NATGW_SLAVE_ONLY"
55 EOF
58 natgw_config_has_changed ()
60 natgw_write_config "$natgw_cfg_new"
62 # Non-existent old returns true, no log message
63 if [ ! -f "$natgw_cfg_old" ] ; then
64 return 0
67 # Handle no change
68 if cmp "$natgw_cfg_old" "$natgw_cfg_new" >/dev/null 2>&1 ; then
69 return 1
72 echo "NAT gateway configuration has changed"
73 return 0
76 natgw_set_capability ()
78 # Set NATGW capability depending on configuration
79 if [ "$CTDB_NATGW_SLAVE_ONLY" = "yes" ] ; then
80 ctdb setnatgwstate off
81 else
82 ctdb setnatgwstate on
86 _natgw_clear ()
88 _ip="${CTDB_NATGW_PUBLIC_IP%/*}"
89 _maskbits="${CTDB_NATGW_PUBLIC_IP#*/}"
91 delete_ip_from_iface \
92 $CTDB_NATGW_PUBLIC_IFACE $_ip $_maskbits >/dev/null 2>&1
93 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
94 _net="${_net_gw%@*}"
95 ip route del "$_net" metric 10 >/dev/null 2>/dev/null
96 done
98 # Delete the masquerading setup from a previous iteration where we
99 # were the NAT-GW
100 iptables -D POSTROUTING -t nat \
101 -s $CTDB_NATGW_PRIVATE_NETWORK ! -d $CTDB_NATGW_PRIVATE_NETWORK \
102 -j MASQUERADE >/dev/null 2>/dev/null
104 iptables -D INPUT -p tcp --syn -d $_ip/32 -j REJECT 2>/dev/null
107 natgw_clear ()
109 if [ -r "$natgw_cfg_old" ] ; then
110 (. $natgw_cfg_old ; _natgw_clear)
111 else
112 _natgw_clear
116 natgw_set_master ()
118 set_proc sys/net/ipv4/ip_forward 1
119 iptables -A POSTROUTING -t nat \
120 -s $CTDB_NATGW_PRIVATE_NETWORK ! -d $CTDB_NATGW_PRIVATE_NETWORK \
121 -j MASQUERADE
123 # block all incoming connections to the NATGW IP address
124 ctdb_natgw_public_ip_host="${CTDB_NATGW_PUBLIC_IP%/*}/32"
125 iptables -D INPUT -p tcp --syn \
126 -d $ctdb_natgw_public_ip_host -j REJECT 2>/dev/null
127 iptables -I INPUT -p tcp --syn \
128 -d $ctdb_natgw_public_ip_host -j REJECT 2>/dev/null
130 ip addr add $CTDB_NATGW_PUBLIC_IP dev $CTDB_NATGW_PUBLIC_IFACE
131 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
132 _net="${_net_gw%@*}"
133 if [ "$_net" != "$_net_gw" ] ; then
134 _gw="${_net_gw#*@}"
135 else
136 _gw="$CTDB_NATGW_DEFAULT_GATEWAY"
139 [ -n "$_gw" ] || continue
140 ip route add "$_net" metric 10 via "$_gw"
141 done
144 natgw_set_slave ()
146 _natgwip="$1"
148 for _net_gw in $CTDB_NATGW_STATIC_ROUTES ; do
149 _net="${_net_gw%@*}"
150 ip route add "$_net" via "$_natgwip" metric 10
151 done
153 # Make sure winbindd does not stay bound to this address if we are
154 # no longer NATGW master
155 smbcontrol winbindd ip-dropped $CTDB_NATGW_PUBLIC_IP >/dev/null 2>&1
158 natgw_ensure_master ()
160 set -- $(ctdb natgwlist)
161 natgwmaster="${1:--1}" # Default is -1 if natgwlist fails
162 natgwip="$2"
164 if [ "$natgwmaster" = "-1" ]; then
165 # Fail...
166 die "There is no NATGW master node"
170 natgw_master_has_changed ()
172 if [ -r "$natgw_master_old" ] ; then
173 read _old_natgwmaster <"$natgw_master_old"
174 else
175 _old_natgwmaster=""
177 [ "$_old_natgwmaster" != "$natgwmaster" ]
180 natgw_save_state ()
182 echo "$natgwmaster" >"$natgw_master_old"
183 # Created by natgw_config_has_changed()
184 mv "$natgw_cfg_new" "$natgw_cfg_old"
188 case "$1" in
189 setup)
190 natgw_check_config
191 natgw_set_capability
194 startup)
195 natgw_check_config
197 # Error if CTDB_NATGW_PUBLIC_IP is listed in public addresses
198 ip_pat=$(echo "$CTDB_NATGW_PUBLIC_IP" | sed -e 's@\.@\\.@g')
199 if grep -q "^${ip_pat}[[:space:]]" \
200 "${CTDB_PUBLIC_ADDRESSES:-${CTDB_BASE}/public_addresses}" ; then
201 die "ERROR: CTDB_NATGW_PUBLIC_IP same as a public address"
204 # do not send out arp requests from loopback addresses
205 set_proc sys/net/ipv4/conf/all/arp_announce 2
208 updatenatgw|ipreallocated)
209 natgw_check_config
211 mypnn=$(ctdb pnn | cut -d: -f2)
213 natgw_set_capability
214 natgw_ensure_master
216 natgw_config_has_changed || natgw_master_has_changed || exit 0
218 natgw_clear
220 if [ "$mypnn" = "$natgwmaster" ]; then
221 natgw_set_master
222 else
223 natgw_set_slave "$natgwip"
226 # flush our route cache
227 set_proc sys/net/ipv4/route/flush 1
229 # Only update saved state when NATGW successfully updated
230 natgw_save_state
233 shutdown|removenatgw)
234 natgw_check_config
235 natgw_clear
239 ctdb_standard_event_handler "@"
241 esac
243 exit 0