ctdb-scripts: Replace uses of "ctdb pnn" with ctdb_get_pnn()
[kamenim/samba-autobuild/.git] / ctdb / config / events.d / 11.natgw
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.
6 #
7
8 [ -n "$CTDB_BASE" ] || \
9     export CTDB_BASE=$(cd -P $(dirname "$0") ; dirname "$PWD")
10
11 . $CTDB_BASE/functions
12
13 service_name=natgw
14
15 loadconfig
16
17 [ -n "$CTDB_NATGW_NODES" ] || exit 0
18 export CTDB_NATGW_NODES
19
20 ctdb_setup_service_state_dir
21
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"
25
26 natgw_check_config ()
27 {
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"
35     fi
36     [ -n "$CTDB_NATGW_PRIVATE_NETWORK" ] || \
37         die "Invalid configuration: CTDB_NATGW_PRIVATE_NETWORK not set"
38
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"
41 }
42
43 natgw_write_config ()
44 {
45     _f="$1"
46
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
56 }
57
58 natgw_config_has_changed ()
59 {
60     natgw_write_config "$natgw_cfg_new"
61
62     # Non-existent old returns true, no log message
63     if [ ! -f "$natgw_cfg_old" ] ; then
64         return 0
65     fi
66
67     # Handle no change
68     if cmp "$natgw_cfg_old" "$natgw_cfg_new" >/dev/null 2>&1 ; then
69         return 1
70     fi
71
72     echo "NAT gateway configuration has changed"
73     return 0
74 }
75
76 natgw_set_capability ()
77 {
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
83     fi
84 }
85
86 _natgw_clear ()
87 {
88     _ip="${CTDB_NATGW_PUBLIC_IP%/*}"
89     _maskbits="${CTDB_NATGW_PUBLIC_IP#*/}"
90
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
97
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
103
104     iptables -D INPUT -p tcp --syn -d $_ip/32 -j REJECT 2>/dev/null
105 }
106
107 natgw_clear ()
108 {
109     if [ -r "$natgw_cfg_old" ] ; then
110         (. $natgw_cfg_old ; _natgw_clear)
111     else
112         _natgw_clear
113     fi
114 }
115
116 natgw_set_master ()
117 {
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
122
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
129
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"
137         fi
138
139         [ -n "$_gw" ] || continue
140         ip route add "$_net" metric 10 via "$_gw"
141     done
142 }
143
144 natgw_set_slave ()
145 {
146     _natgwip="$1"
147
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
152
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
156 }
157
158 natgw_ensure_master ()
159 {
160     set -- $(ctdb natgwlist)
161     natgwmaster="${1:--1}" # Default is -1 if natgwlist fails
162     natgwip="$2"
163
164     if [ "$natgwmaster" = "-1" ]; then
165         # Fail...
166         die "There is no NATGW master node"
167     fi
168 }
169
170 natgw_master_has_changed ()
171 {
172     if [ -r "$natgw_master_old" ] ; then
173         read _old_natgwmaster <"$natgw_master_old"
174     else
175         _old_natgwmaster=""
176     fi
177     [ "$_old_natgwmaster" != "$natgwmaster" ]
178 }
179
180 natgw_save_state ()
181 {
182     echo "$natgwmaster" >"$natgw_master_old"
183     # Created by natgw_config_has_changed()
184     mv "$natgw_cfg_new" "$natgw_cfg_old"
185 }
186
187
188 case "$1" in 
189     setup)
190         natgw_check_config
191         natgw_set_capability
192         ;;
193
194     startup)
195         natgw_check_config
196
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"
202         fi
203
204         # do not send out arp requests from loopback addresses
205         set_proc sys/net/ipv4/conf/all/arp_announce 2
206         ;;
207
208     updatenatgw|ipreallocated)
209         natgw_check_config
210
211         ctdb_get_pnn
212
213         natgw_set_capability
214         natgw_ensure_master
215
216         natgw_config_has_changed || natgw_master_has_changed || exit 0
217
218         natgw_clear
219
220         if [ "$pnn" = "$natgwmaster" ]; then
221             natgw_set_master
222         else
223             natgw_set_slave "$natgwip"
224         fi
225
226         # flush our route cache
227         set_proc sys/net/ipv4/route/flush 1
228
229         # Only update saved state when NATGW successfully updated
230         natgw_save_state
231         ;;
232
233     shutdown|removenatgw)
234         natgw_check_config
235         natgw_clear
236         ;;
237
238     *)
239         ctdb_standard_event_handler "@"
240         ;;
241 esac
242
243 exit 0