ip6: add default gateway to NMIP6Config (bgo #676317)
authorPavel Šimerda <psimerda@redhat.com>
Wed, 23 May 2012 17:07:39 +0000 (19:07 +0200)
committerPavel Šimerda <psimerda@redhat.com>
Wed, 30 May 2012 17:07:11 +0000 (19:07 +0200)
Bug #676317 describes the following error:

  NetworkManager[30151]: <error> [1337348764.559121] [nm-system.c:1121]
  nm_system_replace_default_ip6_route(): (eth1): failed to set IPv6 default
  route: -7

The above error is caused by NetworkManager assuming default gateways
belong to addresses but failing to setup default gateways for addresses
learned through DHCPv6.

This commit doesn't fix the fundamental issue but can be viewed as an ugly
workaround that gets IPv6 connection up and running. It doesn't fix
the fundamental flaw of binding gateways to IP addresses. They are
configured separately in IPv6 and NM should use lifetimes and allow
default gateway reconfiguration.

squash

src/ip6-manager/nm-ip6-manager.c
src/nm-device.c
src/nm-ip6-config.c
src/nm-ip6-config.h
src/nm-policy.c

index 18f78fa..5889ca5 100644 (file)
@@ -1270,8 +1270,6 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
        struct rtnl_route *rtnlroute;
        struct nl_addr *nldest, *nlgateway;
        struct in6_addr *dest, *gateway;
-       gboolean defgw_set = FALSE;
-       struct in6_addr defgw;
        uint32_t metric;
        NMIP6Route *ip6route;
        int i;
@@ -1322,9 +1320,8 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
 
                if (rtnl_route_get_dst_len (rtnlroute) == 0) {
                        /* Default gateway route; don't add to normal routes but to each address */
-                       if (!defgw_set) {
-                               memcpy (&defgw, gateway, sizeof (defgw));
-                               defgw_set = TRUE;
+                       if (!nm_ip6_config_get_gateway (config)) {
+                               nm_ip6_config_set_gateway (config, gateway);
                        }
                        continue;
                }
@@ -1360,8 +1357,9 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
                nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr));
                nm_ip6_address_set_address (ip6addr, addr);
                nm_ip6_config_take_address (config, ip6addr);
-               if (defgw_set)
-                       nm_ip6_address_set_gateway (ip6addr, &defgw);
+               gateway = nm_ip6_config_get_gateway (config);
+               if (gateway)
+                       nm_ip6_address_set_gateway (ip6addr, gateway);
        }
 
        /* Add DNS servers */
index 02509e7..5499ccf 100644 (file)
@@ -1794,6 +1794,10 @@ merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src)
        for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++)
                nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i));
 
+       /* default gateway */
+       if (!nm_ip6_config_get_gateway (dst))
+               nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src));
+
        /* routes */
        for (i = 0; i < nm_ip6_config_get_num_routes (src); i++)
                nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i));
index 0429e30..d172f21 100644 (file)
@@ -53,6 +53,8 @@ typedef struct {
        GPtrArray *domains;
        GPtrArray *searches;
 
+       gboolean gateway_set;
+       struct in6_addr gateway;
        GSList *routes;
 
        gboolean never_default;
@@ -245,6 +247,33 @@ void nm_ip6_config_reset_nameservers (NMIP6Config *config)
 }
 
 void
+nm_ip6_config_set_gateway (NMIP6Config *config, struct in6_addr *gateway)
+{
+       NMIP6ConfigPrivate *priv;
+
+       g_return_if_fail (NM_IS_IP6_CONFIG (config));
+
+       priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+       if (!gateway) {
+               priv->gateway_set = FALSE;
+               return;
+       }
+       memcpy (&priv->gateway, gateway, sizeof (priv->gateway));
+       priv->gateway_set = TRUE;
+}
+
+struct in6_addr *
+nm_ip6_config_get_gateway (NMIP6Config *config)
+{
+       NMIP6ConfigPrivate *priv;
+
+       g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
+
+       priv = NM_IP6_CONFIG_GET_PRIVATE (config);
+       return priv->gateway_set ? &priv->gateway : NULL;
+}
+
+void
 nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route)
 {
        NMIP6ConfigPrivate *priv;
@@ -659,6 +688,7 @@ nm_ip6_config_init (NMIP6Config *config)
        priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr));
        priv->domains = g_ptr_array_sized_new (3);
        priv->searches = g_ptr_array_sized_new (3);
+       priv->gateway_set = FALSE;
 }
 
 static void
index 1e75a12..25ebe20 100644 (file)
@@ -67,6 +67,9 @@ const struct in6_addr *nm_ip6_config_get_nameserver      (NMIP6Config *config, g
 guint32       nm_ip6_config_get_num_nameservers (NMIP6Config *config);
 void          nm_ip6_config_reset_nameservers   (NMIP6Config *config);
 
+void nm_ip6_config_set_gateway                    (NMIP6Config *config, struct in6_addr *gateway);
+struct in6_addr * nm_ip6_config_get_gateway       (NMIP6Config *config);
+
 void          nm_ip6_config_take_route          (NMIP6Config *config, NMIP6Route *route);
 void          nm_ip6_config_add_route           (NMIP6Config *config, NMIP6Route *route);
 void          nm_ip6_config_replace_route       (NMIP6Config *config, guint32 i, NMIP6Route *new_route);
index 16cd117..dad7d6f 100644 (file)
@@ -639,7 +639,13 @@ update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update)
                g_assert (ip6_config);
                addr = nm_ip6_config_get_address (ip6_config, 0);
 
-               nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr));
+               
+               if (memcmp (&nm_ip6_address_get_gateway (addr)->s6_addr, &in6addr_any.s6_addr, 16) != 0)
+                       nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr));
+               else if (nm_ip6_config_get_gateway (ip6_config))
+                       nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_config_get_gateway (ip6_config));
+               else
+                       nm_log_warn (LOGD_IP6, "Default route not configured.");
 
                dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
        }