diff options
| -rw-r--r-- | debian/changelog | 2 | ||||
| -rw-r--r-- | debian/patches/13-dont-replace-kernel-default-route-for-IPv6.patch | 120 | ||||
| -rw-r--r-- | debian/patches/series | 1 |
3 files changed, 123 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog index 9cc8ecaf..2b0f099a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -7,6 +7,8 @@ network-manager (0.9.4.0-4) UNRELEASED; urgency=low * debian/network-manager.maintscript: Use new versioning scheme as recommended by dpkg-maintscript-helper which better handles local modifications and (bin)NMUs. + * debian/patches/13-dont-replace-kernel-default-route-for-IPv6.patch: Don't + fight with the kernel over the default IPv6 route. (Closes: #670818) -- Michael Biebl <biebl@debian.org> Tue, 15 May 2012 01:46:40 +0200 diff --git a/debian/patches/13-dont-replace-kernel-default-route-for-IPv6.patch b/debian/patches/13-dont-replace-kernel-default-route-for-IPv6.patch new file mode 100644 index 00000000..552976c2 --- /dev/null +++ b/debian/patches/13-dont-replace-kernel-default-route-for-IPv6.patch @@ -0,0 +1,120 @@ +commit 77de91e5a8b1c1993ae65c54b37e0411e78e6fe6 +Author: Dan Winship <danw@gnome.org> +Date: Thu Apr 19 14:27:12 2012 -0400 + + 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, diff --git a/debian/patches/series b/debian/patches/series index d9c8f38d..0db45e84 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -4,3 +4,4 @@ 10-format-security.patch 11-initialize-nm-remote-settings.patch 12-initialize-gerror.patch +13-dont-replace-kernel-default-route-for-IPv6.patch |