mirror of
https://gitdl.cn/https://github.com/chakralinux/core.git
synced 2025-02-10 12:54:35 +08:00
122 lines
4.1 KiB
Diff
122 lines
4.1 KiB
Diff
From 77de91e5a8b1c1993ae65c54b37e0411e78e6fe6 Mon Sep 17 00:00:00 2001
|
|
From: Dan Winship <danw@gnome.org>
|
|
Date: Thu, 19 Apr 2012 18:27:12 +0000
|
|
Subject: core: don't fight with the kernel over the default IPv6 route
|
|
|
|
The kernel wants there to be a default route over every RA-ed IPv6
|
|
interface, and it gets confused and annoyed if we remove that default
|
|
route and replace it with our own (causing it to effectively drop all
|
|
further RAs on the floor, which is particularly bad if some of the
|
|
information in the earlier RA had an expiration time).
|
|
|
|
So, rather than replacing the kernel's default route(s), just add an
|
|
additional one of our own, with a lower (ie, higher priority) metric.
|
|
|
|
https://bugzilla.redhat.com/show_bug.cgi?id=785772
|
|
---
|
|
diff --git a/src/nm-system.c b/src/nm-system.c
|
|
index 91153ec..4cebb13 100644
|
|
--- a/src/nm-system.c
|
|
+++ b/src/nm-system.c
|
|
@@ -1023,7 +1023,7 @@ add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw)
|
|
}
|
|
|
|
static int
|
|
-replace_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
+add_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
{
|
|
struct rtnl_route *route = NULL;
|
|
struct nl_sock *nlh;
|
|
@@ -1037,22 +1037,36 @@ replace_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
route = nm_netlink_route_new (ifindex, AF_INET6, 0,
|
|
NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE,
|
|
NMNL_PROP_TABLE, RT_TABLE_MAIN,
|
|
+ NMNL_PROP_PRIO, 1,
|
|
NULL);
|
|
g_return_val_if_fail (route != NULL, -ENOMEM);
|
|
|
|
/* Add the new default route */
|
|
- err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_REPLACE);
|
|
- if (err == -NLE_EXIST) {
|
|
- /* FIXME: even though we use NLM_F_REPLACE the kernel won't replace
|
|
- * the route if it's the same. Suppress the pointless error.
|
|
- */
|
|
+ err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_CREATE);
|
|
+ if (err == -NLE_EXIST)
|
|
err = 0;
|
|
- }
|
|
|
|
rtnl_route_put (route);
|
|
return err;
|
|
}
|
|
|
|
+static struct rtnl_route *
|
|
+find_static_default_routes (struct rtnl_route *route,
|
|
+ struct nl_addr *dst,
|
|
+ const char *iface,
|
|
+ gpointer user_data)
|
|
+{
|
|
+ GList **def_routes = user_data;
|
|
+
|
|
+ if ( nl_addr_get_prefixlen (dst) == 0
|
|
+ && rtnl_route_get_protocol (route) == RTPROT_STATIC) {
|
|
+ rtnl_route_get (route);
|
|
+ *def_routes = g_list_prepend (*def_routes, route);
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
/*
|
|
* nm_system_replace_default_ip6_route
|
|
*
|
|
@@ -1062,12 +1076,35 @@ replace_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
gboolean
|
|
nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
{
|
|
- struct rtnl_route *gw_route = NULL;
|
|
+ GList *def_routes, *iter;
|
|
+ struct rtnl_route *route, *gw_route = NULL;
|
|
gboolean success = FALSE;
|
|
char *iface;
|
|
int err;
|
|
|
|
- err = replace_default_ip6_route (ifindex, gw);
|
|
+ /* We can't just use NLM_F_REPLACE here like in the IPv4 case, because
|
|
+ * the kernel doesn't like it if we replace the default routes it
|
|
+ * creates. (See rh#785772.) So we delete any non-kernel default routes,
|
|
+ * and then add a new default route of our own with a lower metric than
|
|
+ * the kernel ones.
|
|
+ */
|
|
+ def_routes = NULL;
|
|
+ nm_netlink_foreach_route (ifindex, AF_INET6, RT_SCOPE_UNIVERSE, TRUE,
|
|
+ find_static_default_routes, &def_routes);
|
|
+ for (iter = def_routes; iter; iter = iter->next) {
|
|
+ route = iter->data;
|
|
+ if (!nm_netlink_route_delete (route)) {
|
|
+ iface = nm_netlink_index_to_iface (ifindex);
|
|
+ nm_log_err (LOGD_DEVICE | LOGD_IP6,
|
|
+ "(%s): failed to delete existing IPv6 default route",
|
|
+ iface);
|
|
+ g_free (iface);
|
|
+ }
|
|
+ rtnl_route_put (route);
|
|
+ }
|
|
+ g_list_free (def_routes);
|
|
+
|
|
+ err = add_default_ip6_route (ifindex, gw);
|
|
if (err == 0)
|
|
return TRUE;
|
|
|
|
@@ -1091,7 +1128,7 @@ nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw)
|
|
goto out;
|
|
|
|
/* Try adding the original route again */
|
|
- err = replace_default_ip6_route (ifindex, gw);
|
|
+ err = add_default_ip6_route (ifindex, gw);
|
|
if (err != 0) {
|
|
nm_netlink_route_delete (gw_route);
|
|
nm_log_err (LOGD_DEVICE | LOGD_IP6,
|
|
--
|
|
cgit v0.9.0.2-2-gbebe
|