diff options
author | Martin Schwenke <martin@meltin.net> | 2014-11-21 14:46:00 +1100 |
---|---|---|
committer | Martin Schwenke <martins@samba.org> | 2014-12-05 21:02:40 +0100 |
commit | 6471541d6d2bc9f2af0ff92b280abbd1d933cf88 (patch) | |
tree | 17f8f97c8a4d292b3e9df64bd9bad13aa7260509 /ctdb | |
parent | c314ae0b2af4a902cdd003ec6d663fe5b62b003b (diff) | |
download | samba-6471541d6d2bc9f2af0ff92b280abbd1d933cf88.tar.gz samba-6471541d6d2bc9f2af0ff92b280abbd1d933cf88.tar.xz samba-6471541d6d2bc9f2af0ff92b280abbd1d933cf88.zip |
ctdb-scripts: Make 10.interface IPv6-safe
Add checking to "releaseip" and "updateip" to ensure that the given IP
address is really on the given interface with the given netmask. If
reality doesn't match the given arguments then believe reality.
Use new function iptables_wrapper() instead of calling iptables()
directly.
Use new function flush_route_cache() instead of doing IPv4-specific
/proc magic.
Remove setting of otherwise unused variable "failed".
Fix a test for which the error message has changed.
Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
Diffstat (limited to 'ctdb')
-rwxr-xr-x | ctdb/config/events.d/10.interface | 85 | ||||
-rwxr-xr-x | ctdb/config/functions | 6 | ||||
-rwxr-xr-x | ctdb/tests/eventscripts/10.interface.releaseip.002.sh | 5 |
3 files changed, 65 insertions, 31 deletions
diff --git a/ctdb/config/events.d/10.interface b/ctdb/config/events.d/10.interface index 8207fd3b20..51d1b974dc 100755 --- a/ctdb/config/events.d/10.interface +++ b/ctdb/config/events.d/10.interface @@ -137,6 +137,34 @@ monitor_interfaces() return 1 } +# Sets: iface, ip, maskbits, family +get_iface_ip_maskbits_family () +{ + _iface_in="$1" + ip="$2" + _maskbits_in="$3" + + set -- $(ip_maskbits_iface "$ip") + if [ -n "$1" ] ; then + maskbits="$1" + iface="$2" + family="$3" + + if [ "$iface" != "$_iface_in" ] ; then + printf \ + 'WARNING: Public IP %s hosted on interface %s but VNN says %s\n' \ + "$ip" "$iface" "$_iface_in" + fi + if [ "$maskbits" != "$_maskbits_in" ] ; then + printf \ + 'WARNING: Public IP %s has %s bit netmask but VNN says %s\n' \ + "$ip" "$maskbits" "$_maskbits_in" + fi + else + die "ERROR: Unable to determine interface for IP ${ip}" + fi +} + ctdb_check_args "$@" case "$1" in @@ -174,10 +202,13 @@ case "$1" in } # cope with the script being killed while we have the interface blocked - iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null + case "$ip" in + *:*) family="inet6" ;; + *) family="inet" ;; + esac + iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null - # flush our route cache - set_proc sys/net/ipv4/route/flush 1 + flush_route_cache ;; @@ -194,25 +225,23 @@ case "$1" in # 2) use netstat -tn to find existing connections, and kill them # 3) remove the IP from the interface # 4) remove the firewall rule - iface=$2 - ip=$3 - maskbits=$4 + shift + get_iface_ip_maskbits_family "$@" - failed=0 # we do an extra delete to cope with the script being killed - iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null - iptables -I INPUT -i $iface -d $ip -j DROP + iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null + iptables_wrapper $family -I INPUT -i $iface -d $ip -j DROP kill_tcp_connections $ip delete_ip_from_iface $iface $ip $maskbits || { - iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null - exit 1; + iptables_wrapper $family \ + -D INPUT -i $iface -d $ip -j DROP 2> /dev/null + exit 1 } - iptables -D INPUT -i $iface -d $ip -j DROP 2> /dev/null + iptables_wrapper $family -D INPUT -i $iface -d $ip -j DROP 2> /dev/null - # flush our route cache - set_proc sys/net/ipv4/route/flush 1 + flush_route_cache ;; ################################################## @@ -224,34 +253,36 @@ case "$1" in # we finally remove it from the old interface. # # 1) firewall this IP, so no new external packets arrive for it - # 2) add the IP to the new interface - # 3) remove the IP from the old interface + # 2) remove the IP from the old interface (and new interface, to be sure) + # 3) add the IP to the new interface # 4) remove the firewall rule # 5) use ctdb gratiousarp to propagate the new mac address # 6) use netstat -tn to find existing connections, and tickle them - oiface=$2 + _oiface=$2 niface=$3 - ip=$4 - maskbits=$5 + _ip=$4 + _maskbits=$5 + + get_iface_ip_maskbits_family "$_oiface" "$ip" "$maskbits" + oiface="$iface" - failed=0 # we do an extra delete to cope with the script being killed - iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null - iptables -I INPUT -i $oiface -d $ip -j DROP + iptables_wrapper $family -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null + iptables_wrapper $family -I INPUT -i $oiface -d $ip -j DROP delete_ip_from_iface $oiface $ip $maskbits 2>/dev/null delete_ip_from_iface $niface $ip $maskbits 2>/dev/null add_ip_to_iface $niface $ip $maskbits || { - iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null - exit 1; + iptables_wrapper $family \ + -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null + exit 1 } # cope with the script being killed while we have the interface blocked - iptables -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null + iptables_wrapper $family -D INPUT -i $oiface -d $ip -j DROP 2> /dev/null - # flush our route cache - set_proc sys/net/ipv4/route/flush 1 + flush_route_cache # propagate the new mac address ctdb gratiousarp $ip $niface diff --git a/ctdb/config/functions b/ctdb/config/functions index 9d91e6a61a..de373d6261 100755 --- a/ctdb/config/functions +++ b/ctdb/config/functions @@ -920,6 +920,12 @@ drop_all_public_ips () done <"${CTDB_PUBLIC_ADDRESSES:-/dev/null}" } +flush_route_cache () +{ + set_proc sys/net/ipv4/route/flush 1 + set_proc sys/net/ipv6/route/flush 1 +} + ######################################################## # Simple counters _ctdb_counter_common () { diff --git a/ctdb/tests/eventscripts/10.interface.releaseip.002.sh b/ctdb/tests/eventscripts/10.interface.releaseip.002.sh index 9bcb7f11d6..4b9726cfdc 100755 --- a/ctdb/tests/eventscripts/10.interface.releaseip.002.sh +++ b/ctdb/tests/eventscripts/10.interface.releaseip.002.sh @@ -9,9 +9,6 @@ setup_ctdb public_address=$(ctdb_get_1_public_address) ip="${public_address% *}" ; ip="${ip#* }" -required_result 1 <<EOF -RTNETLINK answers: Cannot assign requested address -Failed to del ${ip} on dev ${public_address%% *} -EOF +required_result 1 "ERROR: Unable to determine interface for IP ${ip}" simple_test $public_address |