From cd9e682e58e22f211df10a997c1cee439f323e36 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Tue, 11 Nov 2025 09:49:04 +0000 Subject: [PATCH] import CS keepalived-2.2.8-6.el9 --- SOURCES/RHEL-40520-1.patch | 123 +++++++++++++++++ SOURCES/RHEL-40520-2.patch | 126 ++++++++++++++++++ ...EL-81939-check-child-register-again.patch} | 0 SPECS/keepalived.spec | 14 +- 4 files changed, 259 insertions(+), 4 deletions(-) create mode 100644 SOURCES/RHEL-40520-1.patch create mode 100644 SOURCES/RHEL-40520-2.patch rename SOURCES/{RHEL-81944-check-child-register-again.patch => RHEL-81939-check-child-register-again.patch} (100%) diff --git a/SOURCES/RHEL-40520-1.patch b/SOURCES/RHEL-40520-1.patch new file mode 100644 index 0000000..731f666 --- /dev/null +++ b/SOURCES/RHEL-40520-1.patch @@ -0,0 +1,123 @@ +commit 707bbdf8fa27b34f23adaf35cec8cb9be5d8d18b +Author: Quentin Armitage +Date: Sat Jan 27 15:32:41 2024 +0000 + + vrrp: Check interface for static routes if deleted + + route_is_ours() checked the outgoing interface for virtual routes + but not for static routes. This commit now adds checking of the + outgoing interface for static routes, and now moves the code to + compare routes into a separate function used for both virtual and + static routes. + + Signed-off-by: Quentin Armitage + +diff --git a/keepalived/core/keepalived_netlink.c b/keepalived/core/keepalived_netlink.c +index 1bde1e63..46598d90 100644 +--- a/keepalived/core/keepalived_netlink.c ++++ b/keepalived/core/keepalived_netlink.c +@@ -260,6 +260,39 @@ compare_addr(int family, void *addr1, ip_address_t *addr2) + addr1_p.in6->s6_addr32[3] != addr2->u.sin6_addr.s6_addr32[3]; + } + ++static bool ++compare_route(struct rtattr *tb[RTA_MAX + 1], ip_route_t *route, uint32_t table, int family, int mask_len, uint32_t priority, uint8_t tos) ++{ ++ union { ++ struct in_addr in; ++ struct in6_addr in6; ++ } default_addr; ++ ++ if (table != route->table || ++ family != route->family || ++ mask_len != route->dst->ifa.ifa_prefixlen || ++ priority != route->metric || ++ tos != route->tos) ++ return false; ++ ++ if (route->oif) { ++ if (!tb[RTA_OIF] || route->oif->ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF]))) ++ return false; ++ } else { ++ if (route->set && route->configured_ifindex && ++ (!tb[RTA_OIF] || route->configured_ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF])))) ++ return false; ++ } ++ ++ if (!tb[RTA_DST]) ++ memset(&default_addr, 0, sizeof(default_addr)); ++ ++ if (compare_addr(family, tb[RTA_DST] ? RTA_DATA(tb[RTA_DST]) : &default_addr, route->dst)) ++ return false; ++ ++ return true; ++} ++ + static ip_route_t * + route_is_ours(struct rtmsg* rt, struct rtattr *tb[RTA_MAX + 1], vrrp_t** ret_vrrp) + { +@@ -270,10 +303,6 @@ route_is_ours(struct rtmsg* rt, struct rtattr *tb[RTA_MAX + 1], vrrp_t** ret_vrr + uint8_t tos = rt->rtm_tos; + vrrp_t *vrrp; + ip_route_t *route; +- union { +- struct in_addr in; +- struct in6_addr in6; +- } default_addr; + + *ret_vrrp = NULL; + +@@ -284,48 +313,17 @@ route_is_ours(struct rtmsg* rt, struct rtattr *tb[RTA_MAX + 1], vrrp_t** ret_vrr + + list_for_each_entry(vrrp, &vrrp_data->vrrp, e_list) { + list_for_each_entry(route, &vrrp->vroutes, e_list) { +- if (table != route->table || +- family != route->family || +- mask_len != route->dst->ifa.ifa_prefixlen || +- priority != route->metric || +- tos != route->tos) +- continue; +- +- if (route->oif) { +- if (!tb[RTA_OIF] || route->oif->ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF]))) +- continue; +- } else { +- if (route->set && route->configured_ifindex && +- (!tb[RTA_OIF] || route->configured_ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF])))) +- continue; ++ if (compare_route(tb, route, table, family, mask_len, priority, tos)) { ++ *ret_vrrp = vrrp; ++ return route; + } +- +- if (!tb[RTA_DST]) +- memset(&default_addr, 0, sizeof(default_addr)); +- +- if (compare_addr(family, tb[RTA_DST] ? RTA_DATA(tb[RTA_DST]) : &default_addr, route->dst)) +- continue; +- +- *ret_vrrp = vrrp; +- return route; + } + } + + /* Now check the static routes */ + list_for_each_entry(route, &vrrp_data->static_routes, e_list) { +- if (table != route->table || +- family != route->family || +- mask_len != route->dst->ifa.ifa_prefixlen || +- tos != route->tos) +- continue; +- +- if (!tb[RTA_DST]) +- memset(&default_addr, 0, sizeof(default_addr)); +- +- if (compare_addr(family, tb[RTA_DST] ? RTA_DATA(tb[RTA_DST]) : &default_addr, route->dst)) +- continue; +- +- return route; ++ if (compare_route(tb, route, table, family, mask_len, priority, tos)) ++ return route; + } + + return NULL; diff --git a/SOURCES/RHEL-40520-2.patch b/SOURCES/RHEL-40520-2.patch new file mode 100644 index 0000000..3145e5d --- /dev/null +++ b/SOURCES/RHEL-40520-2.patch @@ -0,0 +1,126 @@ +commit a205e87ecd856f45ff7f84066edebca831738704 +Author: Quentin Armitage +Date: Sun Jun 9 17:07:18 2024 +0100 + + vrrp: remove need for route to have configured interface to track it + + If a virtual route did not have an interface configured, keepalived would + log a warning saying that it could not track the route, and then would + disable tracking of that route. + + It appears that it is not necessary to know the interface in order to track + the route, and in any event the netlink message received after adding the + route identifies the interface for the route if it is appropriate. + + So this commit removes the requirement to specify an interface in order to + track a route. + + Signed-off-by: Quentin Armitage + +diff --git a/keepalived/core/keepalived_netlink.c b/keepalived/core/keepalived_netlink.c +index 198d0e10..da3596fd 100644 +--- a/keepalived/core/keepalived_netlink.c ++++ b/keepalived/core/keepalived_netlink.c +@@ -276,9 +276,10 @@ compare_route(struct rtattr *tb[RTA_MAX + 1], ip_route_t *route, uint32_t table, + if (route->oif) { + if (!tb[RTA_OIF] || route->oif->ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF]))) + return false; +- } else { +- if (route->set && route->configured_ifindex && +- (!tb[RTA_OIF] || route->configured_ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF])))) ++ } else if (route->set) { ++ if (!tb[RTA_OIF] != !route->configured_ifindex) ++ return false; ++ if (tb[RTA_OIF] && route->configured_ifindex != *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF]))) + return false; + } + +@@ -2360,9 +2361,8 @@ netlink_route_filter(__attribute__((unused)) struct sockaddr_nl *snl, struct nlm + route->configured_ifindex = *PTR_CAST(uint32_t, RTA_DATA(tb[RTA_OIF])); + if (route->oif && route->oif->ifindex != route->configured_ifindex) + log_message(LOG_INFO, "route added index %" PRIu32 " != config index %u", route->configured_ifindex, route->oif->ifindex); +- } +- else +- log_message(LOG_INFO, "New route doesn't have i/f index"); ++ } else ++ route->configured_ifindex = 0; + + return 0; + } +diff --git a/keepalived/vrrp/vrrp.c b/keepalived/vrrp/vrrp.c +index 9486f935..2970591b 100644 +--- a/keepalived/vrrp/vrrp.c ++++ b/keepalived/vrrp/vrrp.c +@@ -1764,7 +1764,7 @@ vrrp_restore_interface(vrrp_t * vrrp, bool advF, bool force) + + /* remove virtual routes */ + if (!list_empty(&vrrp->vroutes)) +- vrrp_handle_iproutes(vrrp, IPROUTE_DEL, false); ++ vrrp_handle_iproutes(vrrp, IPROUTE_DEL, force); + + /* empty the delayed arp list */ + vrrp_remove_delayed_arp(vrrp); +diff --git a/keepalived/vrrp/vrrp_iproute.c b/keepalived/vrrp/vrrp_iproute.c +index c2791945..91311800 100644 +--- a/keepalived/vrrp/vrrp_iproute.c ++++ b/keepalived/vrrp/vrrp_iproute.c +@@ -531,9 +531,10 @@ netlink_rtlist(list_head_t *rt_list, int cmd, bool force) + + list_for_each_entry(ip_route, rt_list, e_list) { + if ((cmd == IPROUTE_DEL) == ip_route->set || force) { +- if (!netlink_route(ip_route, cmd)) +- ip_route->set = (cmd == IPROUTE_ADD); +- else if (cmd != IPROUTE_ADD) ++ if (!netlink_route(ip_route, cmd)) { ++ if (cmd == IPROUTE_DEL) ++ ip_route->set = false; ++ } else if (cmd != IPROUTE_ADD) + ip_route->set = false; + } + } +@@ -1871,21 +1872,6 @@ alloc_route(list_head_t *rt_list, const vector_t *strvec, bool allow_track_group + report_config_error(CONFIG_GENERAL_ERROR, "Route cannot be tracked if protocol is not RTPROT_KEEPALIVED(%d), resetting protocol", RTPROT_KEEPALIVED); + new->protocol = RTPROT_KEEPALIVED; + new->mask |= IPROUTE_BIT_PROTOCOL; +- +- if (!new->oif) { +- /* Alternative is to track oif from when route last added. +- * The interface will need to be added temporarily. tracking_obj_t will need +- * a flag to specify permanent track, and a counter for number of temporary +- * trackers. If the termporary tracker count becomes 0 and there is no permanent +- * track, then the tracking_obj_t will need to be removed. +- * +- * We also have a problem if using nexthop, since the route will only be deleted +- * when the interfaces for all of the hops have gone down. We would need to track +- * all of the interfaces being used, and only mark the route as down if all the +- * interfaces are down. */ +- report_config_error(CONFIG_GENERAL_ERROR, "Warning - cannot track route %s with no interface specified, not tracking", dest); +- new->dont_track = true; +- } + } + + if (new->track_group && !new->oif) { +diff --git a/keepalived/vrrp/vrrp_scheduler.c b/keepalived/vrrp/vrrp_scheduler.c +index fc40d59d..8c1747c6 100644 +--- a/keepalived/vrrp/vrrp_scheduler.c ++++ b/keepalived/vrrp/vrrp_scheduler.c +@@ -65,6 +65,8 @@ + #ifdef _WITH_LVS_ + #include "ipvswrapper.h" + #endif ++#include "keepalived_netlink.h" ++ + + /* For load testing recvmsg() */ + /* #define DEBUG_RECVMSG */ +@@ -266,7 +268,9 @@ vrrp_init_state(list_head_t *l) + #endif + + /* Set interface state */ +- vrrp_restore_interface(vrrp, false, false); ++ netlink_error_ignore = ESRCH; // returned if route does not exist ++ vrrp_restore_interface(vrrp, false, true); ++ netlink_error_ignore = 0; + if (is_up && + new_state != VRRP_STATE_FAULT && + !vrrp->num_script_init && diff --git a/SOURCES/RHEL-81944-check-child-register-again.patch b/SOURCES/RHEL-81939-check-child-register-again.patch similarity index 100% rename from SOURCES/RHEL-81944-check-child-register-again.patch rename to SOURCES/RHEL-81939-check-child-register-again.patch diff --git a/SPECS/keepalived.spec b/SPECS/keepalived.spec index e08ba16..bf869c4 100644 --- a/SPECS/keepalived.spec +++ b/SPECS/keepalived.spec @@ -11,14 +11,16 @@ Name: keepalived Summary: High Availability monitor built upon LVS, VRRP and service pollers Version: 2.2.8 -Release: 5%{?dist} +Release: 6%{?dist} License: GPLv2+ URL: http://www.keepalived.org/ Source0: http://www.keepalived.org/software/keepalived-%{version}.tar.gz Source1: keepalived.service Patch0: validate-ipset-names-better.patch -Patch1: RHEL-81944-check-child-register-again.patch +Patch1: RHEL-81939-check-child-register-again.patch +Patch2: RHEL-40520-1.patch +Patch3: RHEL-40520-2.patch Requires(post): systemd Requires(preun): systemd @@ -111,9 +113,13 @@ mkdir -p %{buildroot}%{_libexecdir}/keepalived %{_mandir}/man8/keepalived.8* %changelog -* Wed Oct 8 2025 Christine Caulfield - 2.2.8-5 +* Mon May 12 2025 Christine Caulfield - 2.2.8-6 +- fix "Keepalived claims that blackhole route doesn't have interface and can't be tracked" + Resolves: RHEL-40520 + +* Mon Mar 10 2025 Christine Caulfield - 2.2.8-5 - lvs: if lost misc check child register checker again - Resolves: RHEL-81944 + Resolves: RHEL-81939 * Mon Dec 2 2024 Christine Caulfield - 2.2.8-4 - Better validation of ipsetnames for CVE-2024-41184