ip6: add default gateway to NMIP6Config (bgo #676317)

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.
This commit is contained in:
Pavel Šimerda
2012-05-23 19:07:39 +02:00
committed by Dan Williams
parent 1c0e2a1ec3
commit 8a059b1496
5 changed files with 48 additions and 10 deletions

View 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;
@@ -1321,11 +1319,9 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
gateway = nl_addr_get_binary_addr (nlgateway);
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;
}
/* Default gateway route; cache the router's address for later */
if (!nm_ip6_config_get_defgw (config))
nm_ip6_config_set_defgw (config, gateway);
continue;
}
@@ -1348,6 +1344,8 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex)
/* Add addresses */
for (rtnladdr = FIRST_ADDR (priv->addr_cache); rtnladdr; rtnladdr = NEXT_ADDR (rtnladdr)) {
const struct in6_addr *defgw;
if (rtnl_addr_get_ifindex (rtnladdr) != device->ifindex)
continue;
@@ -1360,8 +1358,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);
defgw = nm_ip6_config_get_defgw (config);
if (defgw)
nm_ip6_address_set_gateway (ip6addr, defgw);
}
/* Add DNS servers */

View 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_defgw (dst))
nm_ip6_config_set_defgw (dst, nm_ip6_config_get_defgw (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));

View File

@@ -53,6 +53,8 @@ typedef struct {
GPtrArray *domains;
GPtrArray *searches;
gboolean defgw_set;
struct in6_addr defgw;
GSList *routes;
gboolean never_default;
@@ -244,6 +246,30 @@ void nm_ip6_config_reset_nameservers (NMIP6Config *config)
g_array_remove_range (priv->nameservers, 0, priv->nameservers->len);
}
void
nm_ip6_config_set_defgw (NMIP6Config *config, const struct in6_addr *defgw)
{
NMIP6ConfigPrivate *priv;
g_return_if_fail (NM_IS_IP6_CONFIG (config));
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
if (defgw)
memcpy (&priv->defgw, defgw, sizeof (priv->defgw));
priv->defgw_set = !!defgw;
}
const struct in6_addr *
nm_ip6_config_get_defgw (NMIP6Config *config)
{
NMIP6ConfigPrivate *priv;
g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL);
priv = NM_IP6_CONFIG_GET_PRIVATE (config);
return priv->defgw_set ? &priv->defgw : NULL;
}
void
nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route)
{
@@ -659,6 +685,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->defgw_set = FALSE;
}
static void

View 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_defgw (NMIP6Config *config, const struct in6_addr *defgw);
const struct in6_addr *nm_ip6_config_get_defgw (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);

View File

@@ -648,7 +648,12 @@ 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, sizeof (in6addr_any.s6_addr)) != 0)
nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr));
else if (nm_ip6_config_get_defgw (ip6_config))
nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_config_get_defgw (ip6_config));
else
nm_log_dbg (LOGD_IP6, "missing default IPv6 route");
dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE;
}