core: fix routing crash with WWAN/PTP configurations

Some configurations won't have a gateway address, because they
are point-to-point (/32).  The previous code expected one and
asserted if a gateway was not found; but even without the
assertion, other code expected a non-NULL gateway.  Handle that
by defaulting the gateway to 0.0.0.0 (IPv4) or :: (IPv6) and
override that with a better gateway if we have one, otherwise
just use 0.0.0.0/:: since we already know the IP config we're
settings should be the default one.
This commit is contained in:
Dan Williams 2012-10-16 19:30:57 -05:00 committed by Jiří Klimeš
parent c0458cb433
commit 3d9d70822c

View file

@ -569,10 +569,9 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
NMVPNConnection *vpn = NULL;
NMActiveConnection *best_ac = NULL;
NMIP4Config *ip4_config = NULL, *parent_ip4;
NMIP4Address *addr = NULL, *tmp_addr;
const char *ip_iface = NULL;
int ip_ifindex = -1;
guint32 parent_mss;
guint32 gw_addr = 0, parent_mss;
guint32 i;
/* Note that we might have an IPv4 VPN tunneled over an IPv6-only device,
@ -588,15 +587,18 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
if (!force_update && best && (best == policy->default_device4))
return;
/* We set the default route to the first gateway we find */
/* We set the default route to the first gateway we find. If we don't find
* a gateway (WWAN, point-to-point, etc) then we just use 0.0.0.0
*/
for (i = 0; i < nm_ip4_config_get_num_addresses (ip4_config); i++) {
tmp_addr = nm_ip4_config_get_address (ip4_config, i);
if (nm_ip4_address_get_gateway (tmp_addr)) {
addr = tmp_addr;
NMIP4Address *addr;
addr = nm_ip4_config_get_address (ip4_config, i);
if (nm_ip4_address_get_gateway (addr)) {
gw_addr = nm_ip4_address_get_gateway (addr);
break;
}
}
g_assert (addr);
if (vpn) {
parent = nm_vpn_connection_get_parent_device (vpn);
@ -604,14 +606,14 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update)
parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0;
nm_system_replace_default_ip4_route_vpn (ip_ifindex,
nm_ip4_address_get_gateway (addr),
gw_addr,
nm_vpn_connection_get_ip4_internal_gateway (vpn),
nm_ip4_config_get_mss (ip4_config),
nm_device_get_ip_ifindex (parent),
parent_mss);
} else {
nm_system_replace_default_ip4_route (ip_ifindex,
nm_ip4_address_get_gateway (addr),
gw_addr,
nm_ip4_config_get_mss (ip4_config));
}
@ -732,11 +734,11 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
NMVPNConnection *vpn = NULL;
NMActiveConnection *best_ac = NULL;
NMIP6Config *ip6_config = NULL, *parent_ip6;
NMIP6Address *addr = NULL, *tmp_addr;
const char *ip_iface = NULL;
int ip_ifindex = -1;
guint32 parent_mss;
guint32 i;
const struct in6_addr *gw_addr;
/* Note that we might have an IPv6 VPN tunneled over an IPv4-only device,
* so we can get (vpn != NULL && best == NULL).
@ -751,15 +753,27 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
if (!force_update && best && (best == policy->default_device6))
return;
/* We set the default route to the first gateway we find */
/* If no better gateway is found, use ::; not all configurations will
* have a gateway, especially WWAN/Point-to-Point connections.
*/
gw_addr = &in6addr_any;
/* Look for a gateway paired with one of the addresses */
for (i = 0; i < nm_ip6_config_get_num_addresses (ip6_config); i++) {
tmp_addr = nm_ip6_config_get_address (ip6_config, i);
if (nm_ip6_address_get_gateway (tmp_addr)) {
addr = tmp_addr;
NMIP6Address *addr;
addr = nm_ip6_config_get_address (ip6_config, i);
if (nm_ip6_address_get_gateway (addr)) {
gw_addr = nm_ip6_address_get_gateway (addr);
break;
}
}
g_assert (addr);
/* If we don't find a paired gateway, try the generic IPv6 gateway */
g_assert (gw_addr);
if ( (memcmp (gw_addr->s6_addr, in6addr_any.s6_addr, sizeof (in6addr_any.s6_addr)) == 0)
&& nm_ip6_config_get_gateway (ip6_config))
gw_addr = nm_ip6_config_get_gateway (ip6_config);
if (vpn) {
parent = nm_vpn_connection_get_parent_device (vpn);
@ -767,18 +781,16 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update)
parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0;
nm_system_replace_default_ip6_route_vpn (ip_ifindex,
nm_ip6_address_get_gateway (addr),
gw_addr,
nm_vpn_connection_get_ip6_internal_gateway (vpn),
nm_ip6_config_get_mss (ip6_config),
nm_device_get_ip_ifindex (parent),
parent_mss);
} else {
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_gateway (ip6_config))
nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_config_get_gateway (ip6_config));
if (gw_addr)
nm_system_replace_default_ip6_route (ip_ifindex, gw_addr);
else
nm_log_dbg (LOGD_IP6, "missing default IPv6 route");
nm_log_dbg (LOGD_IP6, "missing default IPv6 gateway");
}
update_default_ac (policy, best_ac, nm_active_connection_set_default6);