summaryrefslogtreecommitdiff
path: root/src/nm-ip6-config.c
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-09-19 09:40:13 +0200
committerThomas Haller <thaller@redhat.com>2017-09-19 11:49:29 +0200
commit03e1cc96a5dc3d9a9b86f60810a330332c484a94 (patch)
tree14179c0dd5531f115fccd42d5bd4718ff90e563c /src/nm-ip6-config.c
parent39d30a170dcb717d9c1dc980f0897d12f5c110f6 (diff)
downloadNetworkManager-03e1cc96a5dc3d9a9b86f60810a330332c484a94.tar.gz
core: fix handling IPv6 device-route and use correct route metric
Before commit 6698bf58bb53fb07838c52ca67293dd5352ec31c, we would rely on kernel to add the device-route for manual IPv6 routes. We broke that and now kernel would still add the device-route, however nm_platform_ip_route_sync() would delete it immediately after. That is because previously nm_platform_ip_route_sync() would ignore routes with rtm_protocol RTPRO_KERNEL. Now, it will sync and delete those too. Fix that by adding the device-route like we do it for IPv4. This also fixes an actual issue where the automatically added route always had route-metric 256. Instead, we now use the metric from ipv6.route-metric setting. Fixes: 6698bf58bb53fb07838c52ca67293dd5352ec31c
Diffstat (limited to 'src/nm-ip6-config.c')
-rw-r--r--src/nm-ip6-config.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index acb9ccb646..fce5fa8e90 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -115,6 +115,9 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMIP6Config,
static void _add_address (NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Address *new);
static void _add_route (NMIP6Config *self, const NMPObject *obj_new, const NMPlatformIP6Route *new, const NMPObject **out_obj_new);
+static const NMDedupMultiEntry *_lookup_route (const NMIP6Config *self,
+ const NMPObject *needle,
+ NMPlatformIPRouteCmpType cmp_type);
/*****************************************************************************/
@@ -527,6 +530,77 @@ nm_ip6_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
return self;
}
+void
+nm_ip6_config_add_device_routes (NMIP6Config *self,
+ guint32 default_route_metric)
+{
+ const NMIP6ConfigPrivate *priv;
+ const NMPlatformIP6Address *addr;
+ int ifindex;
+ NMDedupMultiIter iter;
+
+ g_return_if_fail (NM_IS_IP6_CONFIG (self));
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+
+ ifindex = nm_ip6_config_get_ifindex (self);
+ g_return_if_fail (ifindex > 0);
+
+ /* For IPv6 addresses received via SLAAC/autoconf, we explicitly add the
+ * device-routes (onlink) to NMIP6Config.
+ *
+ * For manually added IPv6 routes, add the device routes explicitly. */
+
+ nm_ip_config_iter_ip6_address_for_each (&iter, self, &addr) {
+ NMPObject *r;
+ NMPlatformIP6Route *route;
+ gboolean has_peer;
+ int routes_n, routes_i;
+
+ if (NM_FLAGS_HAS (addr->n_ifa_flags, IFA_F_NOPREFIXROUTE))
+ continue;
+
+ has_peer = !IN6_IS_ADDR_UNSPECIFIED (&addr->peer_address);
+
+ /* If we have an IPv6 peer, we add two /128 routes
+ * (unless, both addresses are identical). */
+ routes_n = ( has_peer
+ && !IN6_ARE_ADDR_EQUAL (&addr->address, &addr->peer_address))
+ ? 2 : 1;
+
+ for (routes_i = 0; routes_i < routes_n; routes_i++) {
+
+ r = nmp_object_new (NMP_OBJECT_TYPE_IP6_ROUTE, NULL);
+ route = NMP_OBJECT_CAST_IP6_ROUTE (r);
+
+ route->ifindex = ifindex;
+ route->rt_source = NM_IP_CONFIG_SOURCE_KERNEL;
+ route->metric = default_route_metric;
+
+ if (has_peer) {
+ if (routes_i == 0)
+ route->network = addr->address;
+ else
+ route->network = addr->peer_address;
+ route->plen = 128;
+ } else {
+ nm_utils_ip6_address_clear_host_address (&route->network, &addr->address, addr->plen);
+ route->plen = addr->plen;
+ }
+
+ nm_platform_ip_route_normalize (AF_INET6, (NMPlatformIPRoute *) route);
+
+ if (_lookup_route (self,
+ r,
+ NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID)) {
+ /* we already track this route. Don't add it again. */
+ nmp_object_unref (r);
+ } else
+ _add_route (self, r, NULL, NULL);
+ }
+ }
+}
+
gboolean
nm_ip6_config_commit (const NMIP6Config *self,
NMPlatform *platform,
@@ -1801,6 +1875,24 @@ nm_ip6_config_has_any_dad_pending (const NMIP6Config *self,
/*****************************************************************************/
+static const NMDedupMultiEntry *
+_lookup_route (const NMIP6Config *self,
+ const NMPObject *needle,
+ NMPlatformIPRouteCmpType cmp_type)
+{
+ const NMIP6ConfigPrivate *priv;
+
+ nm_assert (NM_IS_IP6_CONFIG (self));
+ nm_assert (NMP_OBJECT_GET_TYPE (needle) == NMP_OBJECT_TYPE_IP6_ROUTE);
+
+ priv = NM_IP6_CONFIG_GET_PRIVATE (self);
+
+ return _nm_ip_config_lookup_ip_route (priv->multi_idx,
+ &priv->idx_ip6_routes_,
+ needle,
+ cmp_type);
+}
+
void
nm_ip6_config_reset_routes_ndisc (NMIP6Config *self,
const NMNDiscRoute *routes,