diff -Nru network-manager-0.9.4.0/debian/changelog network-manager-0.9.4.0/debian/changelog --- network-manager-0.9.4.0/debian/changelog 2012-04-30 14:44:17.000000000 +0000 +++ network-manager-0.9.4.0/debian/changelog 2012-05-25 01:02:42.000000000 +0000 @@ -1,3 +1,16 @@ +network-manager (0.9.4.0-0ubuntu4.1) precise-proposed; urgency=low + + * debian/network-manager.upstart: add "and static-network-up" to ensure the + loopback device is really up before we start dnsmasq. (LP: #993379) + * debian/patches/git_kernel_ipv6_default_route_77de91e.patch: avoid fighting + with the kernel for what IPv6 default route should be set: let the kernel + set his own, then add a new route with a different metric so that we can + go back and remove it later. (LP: #988183) + * debian/patches/nm-ip6-rs.patch: avoid disconnections due to RDNSS expiry, + send a Router Sollicit to try and get new RDNSS data. (LP: #993571) + + -- Mathieu Trudel-Lapierre Thu, 24 May 2012 20:39:12 -0400 + network-manager (0.9.4.0-0ubuntu4) precise-proposed; urgency=low * debian/patches/quit_dhclient_on_exit.patch: make sure we kill dhclient when diff -Nru network-manager-0.9.4.0/debian/network-manager.upstart network-manager-0.9.4.0/debian/network-manager.upstart --- network-manager-0.9.4.0/debian/network-manager.upstart 2012-04-30 14:44:17.000000000 +0000 +++ network-manager-0.9.4.0/debian/network-manager.upstart 2012-05-25 01:02:42.000000000 +0000 @@ -6,7 +6,8 @@ description "network connection manager" start on (local-filesystems - and started dbus) + and started dbus + and static-network-up) stop on stopping dbus expect fork diff -Nru network-manager-0.9.4.0/debian/patches/git_kernel_ipv6_default_route_77de91e.patch network-manager-0.9.4.0/debian/patches/git_kernel_ipv6_default_route_77de91e.patch --- network-manager-0.9.4.0/debian/patches/git_kernel_ipv6_default_route_77de91e.patch 1970-01-01 00:00:00.000000000 +0000 +++ network-manager-0.9.4.0/debian/patches/git_kernel_ipv6_default_route_77de91e.patch 2012-05-25 01:02:42.000000000 +0000 @@ -0,0 +1,121 @@ +From 77de91e5a8b1c1993ae65c54b37e0411e78e6fe6 Mon Sep 17 00:00:00 2001 +From: Dan Winship +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 diff -Nru network-manager-0.9.4.0/debian/patches/nm-ip6-rs.patch network-manager-0.9.4.0/debian/patches/nm-ip6-rs.patch --- network-manager-0.9.4.0/debian/patches/nm-ip6-rs.patch 1970-01-01 00:00:00.000000000 +0000 +++ network-manager-0.9.4.0/debian/patches/nm-ip6-rs.patch 2012-05-25 01:02:42.000000000 +0000 @@ -0,0 +1,279 @@ +From 2e4843830ce95c69f820803efed87c8b652b175f Mon Sep 17 00:00:00 2001 +From: Dan Winship +Date: Wed, 2 May 2012 11:00:50 -0400 +Subject: [PATCH] core: send out an IPv6 router solicitation if RDNSS/DNSSL is + about to expire + +The kernel will send out a router solicitation if the routes are about +to expire, but it doesn't parse the RDNSS/DNSSL data, so it doesn't know +when they're about to expire. So send out a RS ourselves in that case. + +https://bugzilla.redhat.com/show_bug.cgi?id=753482 +--- + src/ip6-manager/nm-ip6-manager.c | 199 +++++++++++++++++++++++++++++++++++++-- + 1 file changed, 193 insertions(+), 6 deletions(-) + +Index: b/src/ip6-manager/nm-ip6-manager.c +=================================================================== +--- a/src/ip6-manager/nm-ip6-manager.c ++++ b/src/ip6-manager/nm-ip6-manager.c +@@ -18,8 +18,12 @@ + * Copyright (C) 2009 - 2010 Red Hat, Inc. + */ + ++#define _GNU_SOURCE /* for struct in6_pktinfo */ ++ + #include ++#include + #include ++#include + + #include + #include +@@ -32,6 +36,7 @@ + #include "NetworkManagerUtils.h" + #include "nm-marshal.h" + #include "nm-logging.h" ++#include "nm-utils.h" + + /* Pre-DHCP addrconf timeout, in seconds */ + #define NM_IP6_TIMEOUT 20 +@@ -102,9 +107,13 @@ typedef struct { + + GArray *rdnss_servers; + guint rdnss_timeout_id; ++ guint32 rdnss_timeout; + + GArray *dnssl_domains; + guint dnssl_timeout_id; ++ guint32 dnssl_timeout; ++ ++ time_t last_solicitation; + + guint ip6flags_poll_id; + +@@ -266,6 +275,124 @@ emit_config_changed (gpointer user_data) + return FALSE; + } + ++static int ++get_hwaddr (int ifindex, guint8 *buf) ++{ ++ struct rtnl_link *link; ++ struct nl_addr *addr; ++ int len; ++ ++ link = nm_netlink_index_to_rtnl_link (ifindex); ++ if (!link) ++ return -1; ++ ++ addr = rtnl_link_get_addr (link); ++ len = nl_addr_get_len (addr); ++ if (len > NM_UTILS_HWADDR_LEN_MAX) ++ len = -1; ++ else ++ memcpy (buf, nl_addr_get_binary_addr (addr), len); ++ ++ rtnl_link_put (link); ++ ++ return len; ++} ++ ++static void ++send_router_solicitation (NMIP6Device *device, const char *why) ++{ ++ int sock, hops; ++ struct sockaddr_in6 sin6; ++ struct nd_router_solicit rs; ++ struct nd_opt_hdr lladdr_hdr; ++ guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; ++ int hwaddr_len; ++ static const guint8 local_routers_addr[] = ++ { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; ++ struct msghdr mhdr; ++ struct iovec iov[3]; ++ struct cmsghdr *cmsg; ++ struct in6_pktinfo *ipi; ++ guint8 cmsgbuf[128]; ++ int cmsglen = 0; ++ time_t now; ++ ++ now = time (NULL); ++ if (device->last_solicitation > now - 5) ++ return; ++ device->last_solicitation = now; ++ ++ nm_log_dbg (LOGD_IP6, "(%s): %s: sending router solicitation", ++ device->iface, why); ++ ++ sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); ++ if (sock < 0) { ++ nm_log_dbg (LOGD_IP6, "(%s): could not create ICMPv6 socket: %s", ++ device->iface, g_strerror (errno)); ++ return; ++ } ++ ++ hops = 255; ++ if ( setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof (hops)) == -1 ++ || setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof (hops)) == -1) { ++ nm_log_dbg (LOGD_IP6, "(%s): could not set hop limit on ICMPv6 socket: %s", ++ device->iface, g_strerror (errno)); ++ close (sock); ++ return; ++ } ++ ++ /* Use the "all link-local routers" multicast address */ ++ memset (&sin6, 0, sizeof (sin6)); ++ memcpy (&sin6.sin6_addr, local_routers_addr, sizeof (sin6.sin6_addr)); ++ mhdr.msg_name = &sin6; ++ mhdr.msg_namelen = sizeof (sin6); ++ ++ /* Build the router solicitation */ ++ mhdr.msg_iov = iov; ++ memset (&rs, 0, sizeof (rs)); ++ rs.nd_rs_type = ND_ROUTER_SOLICIT; ++ iov[0].iov_len = sizeof (rs); ++ iov[0].iov_base = &rs; ++ ++ memset (hwaddr, 0, sizeof (hwaddr)); ++ hwaddr_len = get_hwaddr (device->ifindex, hwaddr); ++ ++ if (hwaddr_len > 0) { ++ memset (&lladdr_hdr, 0, sizeof (lladdr_hdr)); ++ lladdr_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; ++ lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + hwaddr_len + 7) % 8; ++ iov[1].iov_len = sizeof (lladdr_hdr); ++ iov[1].iov_base = &lladdr_hdr; ++ ++ iov[2].iov_len = (lladdr_hdr.nd_opt_len * 8) - 2; ++ iov[2].iov_base = hwaddr; ++ ++ mhdr.msg_iovlen = 3; ++ } else ++ mhdr.msg_iovlen = 1; ++ ++ /* Force this to go on the right device */ ++ memset (cmsgbuf, 0, sizeof (cmsgbuf)); ++ cmsg = (struct cmsghdr *) cmsgbuf; ++ cmsglen = CMSG_SPACE (sizeof (*ipi)); ++ cmsg->cmsg_len = CMSG_LEN (sizeof (*ipi)); ++ cmsg->cmsg_level = SOL_IPV6; ++ cmsg->cmsg_type = IPV6_PKTINFO; ++ ipi = (struct in6_pktinfo *) CMSG_DATA (cmsg); ++ ipi->ipi6_ifindex = device->ifindex; ++ ++ mhdr.msg_control = cmsg; ++ mhdr.msg_controllen = cmsglen; ++ ++ if (sendmsg (sock, &mhdr, 0) == -1) { ++ nm_log_dbg (LOGD_IP6, "(%s): could not send router solicitation: %s", ++ device->iface, g_strerror (errno)); ++ } ++ ++ close (sock); ++} ++ + static void set_rdnss_timeout (NMIP6Device *device); + + static gboolean +@@ -282,6 +409,22 @@ rdnss_expired (gpointer user_data) + return FALSE; + } + ++static gboolean ++rdnss_needs_refresh (gpointer user_data) ++{ ++ NMIP6Device *device = user_data; ++ gchar *msg; ++ ++ msg = g_strdup_printf ("IPv6 RDNSS due to expire in %d seconds", ++ device->rdnss_timeout); ++ send_router_solicitation (device, msg); ++ g_free (msg); ++ ++ set_rdnss_timeout (device); ++ ++ return FALSE; ++} ++ + static void + set_rdnss_timeout (NMIP6Device *device) + { +@@ -320,9 +463,23 @@ set_rdnss_timeout (NMIP6Device *device) + } + + if (expires) { +- device->rdnss_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), +- rdnss_expired, +- device); ++ gchar *msg; ++ ++ device->rdnss_timeout = MIN (expires - now, G_MAXUINT32 - 1); ++ ++ if (device->rdnss_timeout <= 5) { ++ msg = g_strdup_printf ("IPv6 RDNSS about to expire in %d seconds", ++ device->rdnss_timeout); ++ send_router_solicitation (device, msg); ++ g_free (msg); ++ device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout, ++ rdnss_expired, ++ device); ++ } else { ++ device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout / 2, ++ rdnss_needs_refresh, ++ device); ++ } + } + } + +@@ -342,6 +499,22 @@ dnssl_expired (gpointer user_data) + return FALSE; + } + ++static gboolean ++dnssl_needs_refresh (gpointer user_data) ++{ ++ NMIP6Device *device = user_data; ++ gchar *msg; ++ ++ msg = g_strdup_printf ("IPv6 DNSSL due to expire in %d seconds", ++ device->dnssl_timeout); ++ send_router_solicitation (device, msg); ++ g_free (msg); ++ ++ set_dnssl_timeout (device); ++ ++ return FALSE; ++} ++ + static void + set_dnssl_timeout (NMIP6Device *device) + { +@@ -376,9 +549,23 @@ set_dnssl_timeout (NMIP6Device *device) + } + + if (expires) { +- device->dnssl_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), +- dnssl_expired, +- device); ++ gchar *msg; ++ ++ device->dnssl_timeout = MIN (expires - now, G_MAXUINT32 - 1); ++ ++ if (device->dnssl_timeout <= 5) { ++ msg = g_strdup_printf ("IPv6 DNSSL about to expire in %d seconds", ++ device->dnssl_timeout); ++ send_router_solicitation (device, msg); ++ g_free (msg); ++ device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout, ++ dnssl_expired, ++ device); ++ } else { ++ device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout / 2, ++ dnssl_needs_refresh, ++ device); ++ } + } + } + diff -Nru network-manager-0.9.4.0/debian/patches/series network-manager-0.9.4.0/debian/patches/series --- network-manager-0.9.4.0/debian/patches/series 2012-04-30 14:44:17.000000000 +0000 +++ network-manager-0.9.4.0/debian/patches/series 2012-05-25 01:02:42.000000000 +0000 @@ -22,3 +22,5 @@ quit_dhclient_on_exit.patch lp949743_ensure_remoteconnection_disconnects_494f0a2.patch lp990011_use_tempaddr_sysctl_default.patch +git_kernel_ipv6_default_route_77de91e.patch +nm-ip6-rs.patch