You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
resource-agents/SOURCES/RHEL-32265-2-IPsrcaddr-add-...

366 lines
13 KiB

From 12d73d53026d219be67c0d5353010ba08ab49e98 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 28 May 2024 09:45:55 +0200
Subject: [PATCH 1/3] findif.sh: add metric for IPv6 support and fail when
matching more than 1 route
---
heartbeat/findif.sh | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/heartbeat/findif.sh b/heartbeat/findif.sh
index 13484f827..ca5d1a5c1 100644
--- a/heartbeat/findif.sh
+++ b/heartbeat/findif.sh
@@ -196,10 +196,13 @@ findif()
{
local match="$OCF_RESKEY_ip"
local family
+ local proto
local scope
local nic="$OCF_RESKEY_nic"
local netmask="$OCF_RESKEY_cidr_netmask"
local brdcast="$OCF_RESKEY_broadcast"
+ local metric
+ local routematch
echo $match | grep -qs ":"
if [ $? = 0 ] ; then
@@ -215,10 +218,19 @@ findif()
fi
if [ -n "$nic" ] ; then
# NIC supports more than two.
- set -- $(ip -o -f $family route list match $match $scope | grep "dev $nic " | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
+ routematch=$(ip -o -f $family route list match $match $proto $scope | grep "dev $nic " | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
else
- set -- $(ip -o -f $family route list match $match $scope | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
+ routematch=$(ip -o -f $family route list match $match $proto $scope | sed -e 's,^\([0-9.]\+\) ,\1/32 ,;s,^\([0-9a-f:]\+\) ,\1/128 ,' | sort -t/ -k2,2nr)
fi
+ if [ "$family" = "inet6" ]; then
+ routematch=$(echo "$routematch" | grep -v "^default")
+ fi
+
+ if [ $(echo "$routematch" | wc -l) -gt 1 ]; then
+ ocf_exit_reason "More than 1 routes match $match. Unable to decide which route to use."
+ return $OCF_ERR_GENERIC
+ fi
+ set -- $routematch
if [ $# = 0 ] ; then
case $OCF_RESKEY_ip in
127.*)
@@ -255,6 +267,7 @@ findif()
return $OCF_ERR_GENERIC
fi
fi
- echo "$nic netmask $netmask broadcast $brdcast"
+ metric=$(echo "$@" | sed "s/.*metric[[:blank:]]\([^ ]\+\).*/\1/")
+ echo "$nic netmask $netmask broadcast $brdcast metric $metric"
return $OCF_SUCCESS
}
From 488c096d63fe0f7e15938e65483ba20628080198 Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 28 May 2024 09:47:11 +0200
Subject: [PATCH 2/3] IPaddr2: use metric for IPv6
---
heartbeat/IPaddr2 | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/heartbeat/IPaddr2 b/heartbeat/IPaddr2
index 5f30b8f98..091bea418 100755
--- a/heartbeat/IPaddr2
+++ b/heartbeat/IPaddr2
@@ -561,10 +561,11 @@ ip_init() {
if
[ $rc -eq 0 ]
then
- NICINFO=`echo "$NICINFO" | sed -e 's/netmask\ //;s/broadcast\ //'`
+ NICINFO=`echo "$NICINFO" | sed -e 's/netmask\ //;s/broadcast\ //;s/metric\ //'`
NIC=`echo "$NICINFO" | cut -d" " -f1`
NETMASK=`echo "$NICINFO" | cut -d" " -f2`
BRDCAST=`echo "$NICINFO" | cut -d" " -f3`
+ METRIC=`echo "$NICINFO" | cut -d" " -f4`
else
# findif couldn't find the interface
if ocf_is_probe; then
@@ -659,13 +660,14 @@ delete_interface () {
# Add an interface
#
add_interface () {
- local cmd msg extra_opts ipaddr netmask broadcast iface label
+ local cmd msg extra_opts ipaddr netmask broadcast iface label metric
ipaddr="$1"
netmask="$2"
broadcast="$3"
iface="$4"
label="$5"
+ metric="$6"
if [ "$FAMILY" = "inet" ] && ocf_is_true $OCF_RESKEY_run_arping &&
check_binary arping; then
@@ -688,6 +690,9 @@ add_interface () {
fi
extra_opts=""
+ if [ "$FAMILY" = "inet6" ]; then
+ extra_opts="$extra_opts metric $metric"
+ fi
if [ "$FAMILY" = "inet6" ] && ocf_is_true "${OCF_RESKEY_nodad}"; then
extra_opts="$extra_opts nodad"
fi
@@ -1083,7 +1088,7 @@ ip_start() {
done
fi
- add_interface $OCF_RESKEY_ip $NETMASK ${BRDCAST:-none} $NIC $IFLABEL
+ add_interface "$OCF_RESKEY_ip" "$NETMASK" "${BRDCAST:-none}" "$NIC" "$IFLABEL" "$METRIC"
rc=$?
if [ $rc -ne $OCF_SUCCESS ]; then
From d1c4d1969381d3e35cfaaaaae522e5687a9ed88a Mon Sep 17 00:00:00 2001
From: Oyvind Albrigtsen <oalbrigt@redhat.com>
Date: Tue, 28 May 2024 09:47:56 +0200
Subject: [PATCH 3/3] IPsrcaddr: add IPv6 support
---
heartbeat/IPsrcaddr | 116 ++++++++++++++++++++++++++++++++------------
1 file changed, 85 insertions(+), 31 deletions(-)
diff --git a/heartbeat/IPsrcaddr b/heartbeat/IPsrcaddr
index c732ce8df..1c87d5b7f 100755
--- a/heartbeat/IPsrcaddr
+++ b/heartbeat/IPsrcaddr
@@ -60,6 +60,7 @@ OCF_RESKEY_cidr_netmask_default=""
OCF_RESKEY_destination_default="0.0.0.0/0"
OCF_RESKEY_proto_default=""
OCF_RESKEY_metric_default=""
+OCF_RESKEY_pref_default=""
OCF_RESKEY_table_default=""
: ${OCF_RESKEY_ipaddress=${OCF_RESKEY_ipaddress_default}}
@@ -67,6 +68,7 @@ OCF_RESKEY_table_default=""
: ${OCF_RESKEY_destination=${OCF_RESKEY_destination_default}}
: ${OCF_RESKEY_proto=${OCF_RESKEY_proto_default}}
: ${OCF_RESKEY_metric=${OCF_RESKEY_metric_default}}
+: ${OCF_RESKEY_pref=${OCF_RESKEY_pref_default}}
: ${OCF_RESKEY_table=${OCF_RESKEY_table_default}}
#######################################################################
@@ -75,10 +77,13 @@ OCF_RESKEY_table_default=""
USAGE="usage: $0 {start|stop|status|monitor|validate-all|meta-data}";
- CMDSHOW="$IP2UTIL route show $TABLE to exact $OCF_RESKEY_destination"
-CMDCHANGE="$IP2UTIL route change to "
+echo "$OCF_RESKEY_ipaddress" | grep -q ":" && FAMILY="inet6" || FAMILY="inet"
+[ "$FAMILY" = "inet6" ] && [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] && OCF_RESKEY_destination="::/0"
-if [ "$OCF_RESKEY_destination" != "0.0.0.0/0" ]; then
+ CMDSHOW="$IP2UTIL -f $FAMILY route show $TABLE to exact $OCF_RESKEY_destination"
+CMDCHANGE="$IP2UTIL -f $FAMILY route change to "
+
+if [ "$OCF_RESKEY_destination" != "0.0.0.0/0" ] && [ "$OCF_RESKEY_destination" != "::/0" ]; then
CMDSHOW="$CMDSHOW src $OCF_RESKEY_ipaddress"
fi
@@ -153,6 +158,14 @@ Metric. Only needed if incorrect metric value is used.
<content type="string" default="${OCF_RESKEY_metric_default}" />
</parameter>
+<parameter name="pref">
+<longdesc lang="en">
+IPv6 route preference (low, medium or high). Only needed if incorrect pref value is used.
+</longdesc>
+<shortdesc lang="en">IPv6 route preference.</shortdesc>
+<content type="string" default="${OCF_RESKEY_pref_default}" />
+</parameter>
+
<parameter name="table">
<longdesc lang="en">
Table to modify and use for interface lookup. E.g. "local".
@@ -196,12 +209,21 @@ errorexit() {
# where the src clause "src Y.Y.Y.Y" may or may not be present
WS="[[:blank:]]"
-OCTET="[0-9]\{1,3\}"
-IPADDR="\($OCTET\.\)\{3\}$OCTET"
+case "$FAMILY" in
+ inet)
+ GROUP="[0-9]\{1,3\}"
+ IPADDR="\($GROUP\.\)\{3\}$GROUP"
+ ;;
+ inet6)
+ GROUP="[0-9a-f]\{0,4\}"
+ IPADDR="\($GROUP\:\)\{0,\}$GROUP"
+ ;;
+esac
SRCCLAUSE="src$WS$WS*\($IPADDR\)"
-MATCHROUTE="\(.*${WS}\)\($SRCCLAUSE\)\($WS.*\|$\)"
-METRICCLAUSE=".*\(metric$WS[^ ]\+\)"
+MATCHROUTE="\(.*${WS}\)proto [^ ]\+\(.*${WS}\)\($SRCCLAUSE\)\($WS.*\|$\)"
+METRICCLAUSE=".*\(metric$WS[^ ]\+\).*"
PROTOCLAUSE=".*\(proto$WS[^ ]\+\).*"
+PREFCLAUSE=".*\(pref$WS[^ ]\+\).*"
FINDIF=findif
# findif needs that to be set
@@ -216,17 +238,17 @@ srca_read() {
errorexit "more than 1 matching route exists"
# But there might still be no matching route
- [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] && [ -z "$ROUTE" ] && \
+ ([ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] || [ "$OCF_RESKEY_destination" = "::/0" ]) && [ -z "$ROUTE" ] && \
! ocf_is_probe && [ "$__OCF_ACTION" != stop ] && errorexit "no matching route exists"
# Sed out the source ip address if it exists
- SRCIP=`echo $ROUTE | sed -n "s/$MATCHROUTE/\3/p"`
+ SRCIP=`echo $ROUTE | sed -n "s/$MATCHROUTE/\4/p"`
# and what remains after stripping out the source ip address clause
- ROUTE_WO_SRC=`echo $ROUTE | sed "s/$MATCHROUTE/\1\5/"`
+ ROUTE_WO_SRC=`echo $ROUTE | sed "s/$MATCHROUTE/\1\2\6/"`
# using "src <ip>" only returns output if there's a match
- if [ "$OCF_RESKEY_destination" != "0.0.0.0/0" ]; then
+ if [ "$OCF_RESKEY_destination" != "0.0.0.0/0" ] && [ "$OCF_RESKEY_destination" != "::/0" ]; then
[ -z "$ROUTE" ] && return 1 || return 0
fi
@@ -249,12 +271,15 @@ srca_start() {
rc=$OCF_SUCCESS
ocf_log info "The ip route has been already set.($NETWORK, $INTERFACE, $ROUTE_WO_SRC)"
else
- $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC || \
- errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC' failed"
+ # NetworkManager manages routes with proto static/kernel
+ [ -z "$OCF_RESKEY_proto" ] && echo "$PROTO" | grep -q "proto \(kernel\|static\)" && PROTO="proto keepalived"
- if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
- $CMDCHANGE $ROUTE_WO_SRC src $1 || \
- errorexit "command '$CMDCHANGE $ROUTE_WO_SRC src $1' failed"
+ $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC $PREF || \
+ errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $PROTO src $1 $METRIC $PREF' failed"
+
+ if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] || [ "$OCF_RESKEY_destination" = "::/0" ]; then
+ $CMDCHANGE $ROUTE_WO_SRC $PROTO src $1 || \
+ errorexit "command '$CMDCHANGE $ROUTE_WO_SRC $PROTO src $1' failed"
fi
rc=$?
fi
@@ -290,14 +315,15 @@ srca_stop() {
fi
PRIMARY_IP="$($IP2UTIL -4 -o addr show dev $INTERFACE primary | awk '{split($4,a,"/");print a[1]}')"
- OPTS="proto kernel scope $SCOPE src $PRIMARY_IP"
+ OPTS="proto kernel scope $SCOPE"
+ [ "$FAMILY" = "inet" ] && OPTS="$OPTS src $PRIMARY_IP"
- $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC || \
- errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC' failed"
+ $IP2UTIL route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC $PREF || \
+ errorexit "command 'ip route replace $TABLE $NETWORK dev $INTERFACE $OPTS $METRIC $PREF' failed"
- if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
- $CMDCHANGE $ROUTE_WO_SRC src $PRIMARY_IP || \
- errorexit "command '$CMDCHANGE $ROUTE_WO_SRC src $PRIMARY_IP' failed"
+ if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] || [ "$OCF_RESKEY_destination" = "::/0" ]; then
+ $CMDCHANGE $ROUTE_WO_SRC proto static || \
+ errorexit "command '$CMDCHANGE $ROUTE_WO_SRC proto static' failed"
fi
return $?
@@ -330,7 +356,7 @@ CheckIP() {
case $ip in
*[!0-9.]*) #got invalid char
false;;
- .*|*.) #begin or end by ".", which is invalid
+ .*|*.) #begin or end with ".", which is invalid
false;;
*..*) #consecutive ".", which is invalid
false;;
@@ -356,6 +382,18 @@ CheckIP() {
return $? # This return is unnecessary, this comment too :)
}
+CheckIP6() {
+ ip="$1"
+ case $ip in
+ *[!0-9a-f:]*) #got invalid char
+ false;;
+ *:::*) # more than 2 consecutive ":", which is invalid
+ false;;
+ *::*::*) # more than 1 "::", which is invalid
+ false;;
+ esac
+}
+
#
# Find out which interface or alias serves the given IP address
# The argument is an IP address, and its output
@@ -396,8 +434,7 @@ find_interface_solaris() {
# is an (aliased) interface name (e.g., "eth0" and "eth0:0").
#
find_interface_generic() {
-
- local iface=`$IP2UTIL -o -f inet addr show | grep "\ $BASEIP" \
+ local iface=`$IP2UTIL -o -f $FAMILY addr show | grep "\ $BASEIP" \
| cut -d ' ' -f2 | grep -v '^ipsec[0-9][0-9]*$'`
if [ -z "$iface" ]; then
return $OCF_ERR_GENERIC
@@ -502,7 +539,9 @@ srca_validate_all() {
# The IP address should be in good shape
if CheckIP "$ipaddress"; then
- :
+ :
+ elif CheckIP6 "$ipaddress"; then
+ :
else
ocf_exit_reason "Invalid IP address [$ipaddress]"
return $OCF_ERR_CONFIGURED
@@ -570,21 +609,36 @@ rc=$?
}
INTERFACE=`echo $findif_out | awk '{print $1}'`
-LISTROUTE=`$IP2UTIL route list dev $INTERFACE scope link $PROTO match $ipaddress`
+case "$FAMILY" in
+ inet)
+ LISTCMD="$IP2UTIL -f $FAMILY route list dev $INTERFACE scope link $PROTO match $ipaddress"
+ ;;
+ inet6)
+ LISTCMD="$IP2UTIL -f $FAMILY route list dev $INTERFACE $PROTO match $ipaddress"
+ ;;
+esac
+LISTROUTE=`$LISTCMD`
+
[ -z "$PROTO" ] && PROTO=`echo $LISTROUTE | sed -n "s/$PROTOCLAUSE/\1/p"`
if [ -n "$OCF_RESKEY_metric" ]; then
METRIC="metric $OCF_RESKEY_metric"
-elif [ -z "$TABLE" ] || [ "${TABLE#table }" = "main" ]; then
+elif [ -z "$TABLE" ] || [ "${TABLE#table }" = "main" ] || [ "$FAMILY" = "inet6" ]; then
METRIC=`echo $LISTROUTE | sed -n "s/$METRICCLAUSE/\1/p"`
else
METRIC=""
fi
-if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] ;then
+if [ "$FAMILY" = "inet6" ]; then
+ if [ -z "$OCF_RESKEY_pref" ]; then
+ PREF=`echo $LISTROUTE | sed -n "s/$PREFCLAUSE/\1/p"`
+ else
+ PREF="pref $OCF_RESKEY_pref"
+ fi
+fi
+if [ "$OCF_RESKEY_destination" = "0.0.0.0/0" ] || [ "$OCF_RESKEY_destination" = "::/0" ] ;then
NETWORK=`echo $LISTROUTE | grep -m 1 -o '^[^ ]*'`
if [ -z "$NETWORK" ]; then
- err_str="command '$IP2UTIL route list dev $INTERFACE scope link $PROTO"
- err_str="$err_str match $ipaddress' failed to find a matching route"
+ err_str="command '$LISTCMD' failed to find a matching route"
if [ "$__OCF_ACTION" = "start" ]; then
ocf_exit_reason "$err_str"