From 99b37d768f6100aaec6767e85a6f9e70ff4354e1 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 3 Mar 2016 15:35:14 +0100 Subject: [PATCH] iface-helper: fix RA processing with more than one router We construct new IP6Config on each rdisc_config_changed(). That's not a smart thing to do, since that makes us throw away the previous configuration. In case the two routers on the same network, the first RA triggers rdisc_config_changed() for changed gateway and addresses. On handling the second RA rdisc_config_changed() doesn't add the address, resulting in the address being removed on ip6 config sync. A side effect of this is that the address is still tentative, resulting in DAD retry and an new address being added. So the networking still works, but at the expense of a single DAD failure and an address that's perhaps different from what was expected. --- src/nm-iface-helper.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index cc59835f58..225464c094 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -130,9 +130,8 @@ dhcp4_state_changed (NMDhcpClient *client, static void rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_data) { - static NMIP6Config *last_config = NULL; + static NMIP6Config *rdisc_config = NULL; NMIP6Config *existing; - NMIP6Config *ip6_config; static int system_support = -1; guint32 ifa_flags = 0x00; int i; @@ -157,21 +156,25 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da ifa_flags |= IFA_F_MANAGETEMPADDR; } - ip6_config = nm_ip6_config_new (ifindex); + existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr); + if (rdisc_config) + nm_ip6_config_subtract (existing, rdisc_config); + else + rdisc_config = nm_ip6_config_new (ifindex); if (changed & NM_RDISC_CONFIG_GATEWAYS) { /* Use the first gateway as ordered in router discovery cache. */ if (rdisc->gateways->len) { NMRDiscGateway *gateway = &g_array_index (rdisc->gateways, NMRDiscGateway, 0); - nm_ip6_config_set_gateway (ip6_config, &gateway->address); + nm_ip6_config_set_gateway (rdisc_config, &gateway->address); } else - nm_ip6_config_set_gateway (ip6_config, NULL); + nm_ip6_config_set_gateway (rdisc_config, NULL); } if (changed & NM_RDISC_CONFIG_ADDRESSES) { /* Rebuild address list from router discovery cache. */ - nm_ip6_config_reset_addresses (ip6_config); + nm_ip6_config_reset_addresses (rdisc_config); /* rdisc->addresses contains at most max_addresses entries. * This is different from what the kernel does, which @@ -193,13 +196,13 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da address.source = NM_IP_CONFIG_SOURCE_RDISC; address.n_ifa_flags = ifa_flags; - nm_ip6_config_add_address (ip6_config, &address); + nm_ip6_config_add_address (rdisc_config, &address); } } if (changed & NM_RDISC_CONFIG_ROUTES) { /* Rebuild route list from router discovery cache. */ - nm_ip6_config_reset_routes (ip6_config); + nm_ip6_config_reset_routes (rdisc_config); for (i = 0; i < rdisc->routes->len; i++) { NMRDiscRoute *discovered_route = &g_array_index (rdisc->routes, NMRDiscRoute, i); @@ -217,7 +220,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da route.source = NM_IP_CONFIG_SOURCE_RDISC; route.metric = global_opt.priority_v6; - nm_ip6_config_add_route (ip6_config, &route); + nm_ip6_config_add_route (rdisc_config, &route); } } } @@ -236,18 +239,9 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, gpointer user_da nm_platform_sysctl_set (NM_PLATFORM_GET, nm_utils_ip6_property_path (global_opt.ifname, "mtu"), val); } - existing = nm_ip6_config_capture (ifindex, FALSE, global_opt.tempaddr); - if (last_config) - nm_ip6_config_subtract (existing, last_config); - - nm_ip6_config_merge (existing, ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); + nm_ip6_config_merge (existing, rdisc_config, NM_IP_CONFIG_MERGE_DEFAULT); if (!nm_ip6_config_commit (existing, ifindex, TRUE)) nm_log_warn (LOGD_IP6, "(%s): failed to apply IPv6 config", global_opt.ifname); - - if (last_config) - g_object_unref (last_config); - last_config = nm_ip6_config_new (ifindex); - nm_ip6_config_replace (last_config, ip6_config, NULL); } static void