diff options
Diffstat (limited to 'src/platform/nm-platform.c')
-rw-r--r-- | src/platform/nm-platform.c | 169 |
1 files changed, 126 insertions, 43 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c index 9a40d6770f..ac24009548 100644 --- a/src/platform/nm-platform.c +++ b/src/platform/nm-platform.c @@ -1478,9 +1478,6 @@ nm_platform_ip4_route_add (int ifindex, g_return_val_if_fail (mss >= 0, FALSE); g_return_val_if_fail (klass->ip4_route_add, FALSE); - if (!metric) - metric = 1024; - return klass->ip4_route_add (platform, ifindex, network, plen, gateway, metric, mss); } @@ -1494,9 +1491,6 @@ nm_platform_ip6_route_add (int ifindex, g_return_val_if_fail (mss >= 0, FALSE); g_return_val_if_fail (klass->ip6_route_add, FALSE); - if (!metric) - metric = 1024; - return klass->ip6_route_add (platform, ifindex, network, plen, gateway, metric, mss); } @@ -1563,9 +1557,15 @@ array_contains_ip4_route (const GArray *routes, const NMPlatformIP4Route *route) guint len = routes ? routes->len : 0; guint i; - for (i = 0; i < len; i++) - if (!memcmp (&g_array_index (routes, NMPlatformIP4Route, i), route, sizeof (*route))) + for (i = 0; i < len; i++) { + NMPlatformIP4Route *c = &g_array_index (routes, NMPlatformIP4Route, i); + + if (route->network == c->network && + route->plen == c->plen && + route->gateway == c->gateway && + route->metric == c->metric) return TRUE; + } return FALSE; } @@ -1576,9 +1576,15 @@ array_contains_ip6_route (const GArray *routes, const NMPlatformIP6Route *route) guint len = routes ? routes->len : 0; guint i; - for (i = 0; i < len; i++) - if (!memcmp (&g_array_index (routes, NMPlatformIP6Route, i), route, sizeof (*route))) + for (i = 0; i < len; i++) { + NMPlatformIP6Route *c = &g_array_index (routes, NMPlatformIP6Route, i); + + if (IN6_ARE_ADDR_EQUAL (&route->network, &c->network) && + route->plen == c->plen && + IN6_ARE_ADDR_EQUAL (&route->gateway, &c->gateway) && + route->metric == c->metric) return TRUE; + } return FALSE; } @@ -1600,33 +1606,53 @@ nm_platform_ip4_route_sync (int ifindex, const GArray *known_routes) GArray *routes; NMPlatformIP4Route *route; const NMPlatformIP4Route *known_route; - int i; + gboolean success; + int i, i_type; /* Delete unknown routes */ routes = nm_platform_ip4_route_get_all (ifindex, FALSE); for (i = 0; i < routes->len; i++) { route = &g_array_index (routes, NMPlatformIP4Route, i); - route->ifindex = 0; if (!array_contains_ip4_route (known_routes, route)) nm_platform_ip4_route_delete (ifindex, route->network, route->plen, route->metric); } - g_array_free (routes, TRUE); - if (!known_routes) + if (!known_routes) { + g_array_free (routes, TRUE); return TRUE; + } /* Add missing routes */ - for (i = 0; i < known_routes->len; i++) { - known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP4Route, i); - if (!nm_platform_ip4_route_add (ifindex, - known_route->network, known_route->plen, known_route->gateway, - known_route->metric, known_route->mss)) - return FALSE; + if ((known_route->gateway == 0) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip4_route (routes, known_route)) { + success = nm_platform_ip4_route_add (ifindex, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv4 route to kernel: %s", + nm_platform_ip4_route_to_string (known_route)); + success = TRUE; + } + } + } } - return TRUE; + g_array_free (routes, TRUE); + return success; } /** @@ -1646,7 +1672,8 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) GArray *routes; NMPlatformIP6Route *route; const NMPlatformIP6Route *known_route; - int i; + gboolean success; + int i, i_type; /* Delete unknown routes */ routes = nm_platform_ip6_route_get_all (ifindex, FALSE); @@ -1657,22 +1684,42 @@ nm_platform_ip6_route_sync (int ifindex, const GArray *known_routes) if (!array_contains_ip6_route (known_routes, route)) nm_platform_ip6_route_delete (ifindex, route->network, route->plen, route->metric); } - g_array_free (routes, TRUE); - if (!known_routes) + if (!known_routes) { + g_array_free (routes, TRUE); return TRUE; + } /* Add missing routes */ - for (i = 0; i < known_routes->len; i++) { - known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); + for (i_type = 0, success = TRUE; i_type < 2 && success; i_type++) { + for (i = 0; i < known_routes->len && success; i++) { + known_route = &g_array_index (known_routes, NMPlatformIP6Route, i); - if (!nm_platform_ip6_route_add (ifindex, - known_route->network, known_route->plen, known_route->gateway, - known_route->metric, known_route->mss)) - return FALSE; + if (IN6_IS_ADDR_UNSPECIFIED (&known_route->gateway) ^ (i_type != 0)) { + /* Make two runs over the list of routes. On the first, only add + * device routes, on the second the others (gateway routes). */ + continue; + } + + /* Ignore routes that already exist */ + if (!array_contains_ip6_route (routes, known_route)) { + success = nm_platform_ip6_route_add (ifindex, + known_route->network, + known_route->plen, + known_route->gateway, + known_route->metric, + known_route->mss); + if (!success && known_route->source < NM_PLATFORM_SOURCE_USER) { + nm_log_dbg (LOGD_PLATFORM, "ignore error adding IPv6 route to kernel: %s", + nm_platform_ip6_route_to_string (known_route)); + success = TRUE; + } + } + } } - return TRUE; + g_array_free (routes, TRUE); + return success; } gboolean @@ -1684,6 +1731,34 @@ nm_platform_route_flush (int ifindex) /******************************************************************/ +static const char * +source_to_string (NMPlatformSource source) +{ + switch (source) { + case NM_PLATFORM_SOURCE_KERNEL: + return "kernel"; + case NM_PLATFORM_SOURCE_SHARED: + return "shared"; + case NM_PLATFORM_SOURCE_IP4LL: + return "ipv4ll"; + case NM_PLATFORM_SOURCE_PPP: + return "ppp"; + case NM_PLATFORM_SOURCE_WWAN: + return "wwan"; + case NM_PLATFORM_SOURCE_VPN: + return "vpn"; + case NM_PLATFORM_SOURCE_DHCP: + return "dhcp"; + case NM_PLATFORM_SOURCE_RDISC: + return "rdisc"; + case NM_PLATFORM_SOURCE_USER: + return "user"; + default: + break; + } + return "unknown"; +} + /** * nm_platform_ip4_address_to_string: * @route: pointer to NMPlatformIP4Address address structure @@ -1718,11 +1793,12 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address) s_dev = address->ifindex > 0 ? nm_platform_link_get_name (address->ifindex) : NULL; str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL; - g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s", + g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s src %s", s_address, address->plen, (guint)address->lifetime, (guint)address->preferred, (guint)address->timestamp, str_peer ? str_peer : "", - str_dev ? str_dev : ""); + str_dev ? str_dev : "", + source_to_string (address->source)); g_free (str_dev); g_free (str_peer); return buffer; @@ -1767,12 +1843,13 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address) rtnl_addr_flags2str(address->flags, s_flags, sizeof(s_flags)); str_flags = s_flags[0] ? g_strconcat (" flags ", s_flags, NULL) : NULL; - g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s%s", + g_snprintf (buffer, sizeof (buffer), "%s/%d lft %u pref %u time %u%s%s%s src %s", s_address, address->plen, (guint)address->lifetime, (guint)address->preferred, (guint)address->timestamp, str_peer ? str_peer : "", str_dev ? str_dev : "", - str_flags ? str_flags : ""); + str_flags ? str_flags : "", + source_to_string (address->source)); g_free (str_flags); g_free (str_dev); g_free (str_peer); @@ -1807,10 +1884,11 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route) s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL; str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL; - g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u", + g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u src %s", s_network, route->plen, s_gateway, str_dev ? str_dev : "", - route->metric, route->mss); + route->metric, route->mss, + source_to_string (route->source)); g_free (str_dev); return buffer; } @@ -1843,10 +1921,11 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route) s_dev = route->ifindex > 0 ? nm_platform_link_get_name (route->ifindex) : NULL; str_dev = s_dev ? g_strconcat (" dev ", s_dev, NULL) : NULL; - g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u", + g_snprintf (buffer, sizeof (buffer), "%s/%d via %s%s metric %u mss %u src %s", s_network, route->plen, s_gateway, str_dev ? str_dev : "", - route->metric, route->mss); + route->metric, route->mss, + source_to_string (route->source)); g_free (str_dev); return buffer; } @@ -1879,9 +1958,10 @@ int nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4Address *b) { _CMP_POINTER (a, b); - _CMP_FIELD_MEMCMP (a, b, address); - _CMP_FIELD_MEMCMP (a, b, peer_address); _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); + _CMP_FIELD (a, b, address); + _CMP_FIELD (a, b, peer_address); _CMP_FIELD (a, b, plen); _CMP_FIELD (a, b, timestamp); _CMP_FIELD (a, b, lifetime); @@ -1894,6 +1974,7 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A { _CMP_POINTER (a, b); _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, address); _CMP_FIELD_MEMCMP (a, b, peer_address); _CMP_FIELD (a, b, plen); @@ -1909,9 +1990,10 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route { _CMP_POINTER (a, b); _CMP_FIELD (a, b, ifindex); - _CMP_FIELD_MEMCMP (a, b, network); + _CMP_FIELD (a, b, source); + _CMP_FIELD (a, b, network); _CMP_FIELD (a, b, plen); - _CMP_FIELD_MEMCMP (a, b, gateway); + _CMP_FIELD (a, b, gateway); _CMP_FIELD (a, b, metric); _CMP_FIELD (a, b, mss); return 0; @@ -1922,6 +2004,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route { _CMP_POINTER (a, b); _CMP_FIELD (a, b, ifindex); + _CMP_FIELD (a, b, source); _CMP_FIELD_MEMCMP (a, b, network); _CMP_FIELD (a, b, plen); _CMP_FIELD_MEMCMP (a, b, gateway); |