summaryrefslogtreecommitdiff
path: root/src/platform/nm-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/nm-platform.c')
-rw-r--r--src/platform/nm-platform.c169
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);