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.c408
1 files changed, 289 insertions, 119 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 500db9b621..6fdfda27a2 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2870,14 +2870,7 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
/**
* nm_platform_ip4_route_add:
* @self:
- * @ifindex:
- * @source:
- * network:
- * plen:
- * gateway:
- * pref_src:
- * metric:
- * mss:
+ * @route:
*
* For kernel, a gateway can be either explicitly set or left
* at zero (0.0.0.0). In addition, there is the scope of the IPv4
@@ -2898,99 +2891,69 @@ nm_platform_ip6_route_get_all (NMPlatform *self, int ifindex, NMPlatformGetRoute
* Returns: %TRUE in case of success.
*/
gboolean
-nm_platform_ip4_route_add (NMPlatform *self,
- int ifindex, NMIPConfigSource source,
- in_addr_t network, guint8 plen,
- in_addr_t gateway, in_addr_t pref_src,
- guint32 metric, guint32 mss)
+nm_platform_ip4_route_add (NMPlatform *self, const NMPlatformIP4Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- g_return_val_if_fail (plen <= 32, FALSE);
+ g_return_val_if_fail (route, FALSE);
+ g_return_val_if_fail (route->plen <= 32, FALSE);
- if (_LOGD_ENABLED ()) {
- NMPlatformIP4Route route = { 0 };
-
- route.ifindex = ifindex;
- route.rt_source = source;
- route.network = network;
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
- route.pref_src = pref_src;
-
- _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (&route, NULL, 0));
- }
- return klass->ip4_route_add (self, ifindex, source, network, plen, gateway, pref_src, metric, mss);
+ _LOGD ("route: adding or updating IPv4 route: %s", nm_platform_ip4_route_to_string (route, NULL, 0));
+ return klass->ip4_route_add (self, route);
}
gboolean
-nm_platform_ip6_route_add (NMPlatform *self,
- int ifindex, NMIPConfigSource source,
- struct in6_addr network, guint8 plen, struct in6_addr gateway,
- guint32 metric, guint32 mss)
+nm_platform_ip6_route_add (NMPlatform *self, const NMPlatformIP6Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- g_return_val_if_fail (plen <= 128, FALSE);
+ g_return_val_if_fail (route, FALSE);
+ g_return_val_if_fail (route->plen <= 128, FALSE);
- if (_LOGD_ENABLED ()) {
- NMPlatformIP6Route route = { 0 };
-
- route.ifindex = ifindex;
- route.rt_source = source;
- route.network = network;
- route.plen = plen;
- route.gateway = gateway;
- route.metric = metric;
- route.mss = mss;
-
- _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (&route, NULL, 0));
- }
- return klass->ip6_route_add (self, ifindex, source, network, plen, gateway, metric, mss);
+ _LOGD ("route: adding or updating IPv6 route: %s", nm_platform_ip6_route_to_string (route, NULL, 0));
+ return klass->ip6_route_add (self, route);
}
gboolean
-nm_platform_ip4_route_delete (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+nm_platform_ip4_route_delete (NMPlatform *self, const NMPlatformIP4Route *route)
{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
-
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv4 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet4_ntop (network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip4_route_delete (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, FALSE);
+
+ _LOGD ("route: deleting IPv4 route %s", nm_platform_ip4_route_to_string (route, NULL, 0));
+ return klass->ip4_route_delete (self, route);
}
gboolean
-nm_platform_ip6_route_delete (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+nm_platform_ip6_route_delete (NMPlatform *self, const NMPlatformIP6Route *route)
{
- char str_dev[TO_STRING_DEV_BUF_SIZE];
-
_CHECK_SELF (self, klass, FALSE);
- _LOGD ("route: deleting IPv6 route %s/%d, metric=%"G_GUINT32_FORMAT", ifindex %d%s",
- nm_utils_inet6_ntop (&network, NULL), plen, metric, ifindex,
- _to_string_dev (self, ifindex, str_dev, sizeof (str_dev)));
- return klass->ip6_route_delete (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, FALSE);
+
+ _LOGD ("route: deleting IPv6 route %s", nm_platform_ip6_route_to_string (route, NULL, 0));
+ return klass->ip6_route_delete (self, route);
}
const NMPlatformIP4Route *
-nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric)
+nm_platform_ip4_route_get (NMPlatform *self, const NMPlatformIP4Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip4_route_get (self ,ifindex, network, plen, metric);
+ g_return_val_if_fail (route, NULL);
+
+ return klass->ip4_route_get (self, route);
}
const NMPlatformIP6Route *
-nm_platform_ip6_route_get (NMPlatform *self, int ifindex, struct in6_addr network, guint8 plen, guint32 metric)
+nm_platform_ip6_route_get (NMPlatform *self, const NMPlatformIP6Route *route)
{
_CHECK_SELF (self, klass, FALSE);
- return klass->ip6_route_get (self, ifindex, network, plen, metric);
+ g_return_val_if_fail (route, NULL);
+
+ return klass->ip6_route_get (self, route);
}
/******************************************************************/
@@ -3626,6 +3589,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_scope[30], s_source[50];
+ guint8 scope;
+ gboolean scope_print;
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -3635,6 +3600,9 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
_to_string_dev (NULL, route->ifindex, str_dev, sizeof (str_dev));
+ scope = nm_platform_route_scope_from_ip4_route (route);
+ scope_print = route->rt_scope_is_set || scope != RT_SCOPE_NOWHERE;
+
g_snprintf (buf, len,
"%s/%d"
" via %s"
@@ -3654,8 +3622,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
route->mss,
nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)),
route->rt_cloned ? " cloned" : "",
- route->scope_inv ? " scope " : "",
- route->scope_inv ? (nm_platform_route_scope2str (nm_platform_route_scope_inv (route->scope_inv), str_scope, sizeof (str_scope))) : "",
+ scope_print ? " scope " : "",
+ scope_print ? nm_platform_route_scope2str (scope, str_scope, sizeof (str_scope)) : "",
route->pref_src ? " pref-src " : "",
route->pref_src ? inet_ntop (AF_INET, &route->pref_src, s_pref_src, sizeof(s_pref_src)) : "");
return buf;
@@ -3960,35 +3928,256 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
int
nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b)
{
+ return nm_platform_ip4_route_cmp_full (a, b, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+}
+
+int
+nm_platform_ip4_route_cmp_full (const NMPlatformIP4Route *a, const NMPlatformIP4Route *b, NMPlatformIPRouteIdType id_type)
+{
+ guint8 rtprot_a, rtprot_b;
+ guint8 scope_a, scope_b;
+ guint32 network_a, network_b;
+
_CMP_SELF (a, b);
+
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD (a, b, network);
+
+ network_a = nm_utils_ip4_address_clear_host_address (a->network, a->plen);
+ network_b = nm_utils_ip4_address_clear_host_address (b->network, b->plen);
+ _CMP_DIRECT (network_a, network_b);
+
_CMP_FIELD (a, b, plen);
_CMP_FIELD (a, b, metric);
_CMP_FIELD (a, b, gateway);
- _CMP_FIELD (a, b, rt_source);
+
+ rtprot_a = nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source);
+ rtprot_b = nmp_utils_ip_config_source_coerce_to_rtprot (b->rt_source);
+ _CMP_DIRECT (rtprot_a, rtprot_b);
+
_CMP_FIELD (a, b, mss);
- _CMP_FIELD (a, b, scope_inv);
+
+ scope_a = nm_platform_route_scope_from_ip4_route (a);
+ scope_b = nm_platform_route_scope_from_ip4_route (b);
+ _CMP_DIRECT (scope_a, scope_b);
+
_CMP_FIELD (a, b, pref_src);
_CMP_FIELD (a, b, rt_cloned);
+
+ /* currently we have two id-types, ID and ALL. Let ALL be a stricter
+ * ordering then ID, but yield the same order. Thus, above we first check
+ * all the ID fields, only if those are all equal, dig deeper. */
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ break;
+ default:
+ _CMP_FIELD (a, b, network);
+ _CMP_FIELD (a, b, rt_source);
+ _CMP_FIELD (a, b, rt_scope);
+ _CMP_FIELD (a, b, rt_scope_is_set);
+ break;
+ }
return 0;
}
+guint
+nm_platform_ip4_route_hash_full (const NMPlatformIP4Route *a, NMPlatformIPRouteIdType id_type)
+{
+ guint h = 0x8202baf9;
+
+ if (!a)
+ return h;
+
+ h += (h * 33) + ((guint) a->ifindex);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_utils_ip4_address_clear_host_address (a->network, a->plen));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->network);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->plen);
+ h += (h * 33) + ((guint) a->metric);
+ h += (h * 33) + ((guint) a->gateway);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->rt_source);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->mss);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_platform_route_scope_from_ip4_route (a));
+ break;
+ default:
+ h += (h * 33) + (((guint) a->rt_scope) + (((guint) a->rt_scope_is_set) << 8));
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->pref_src);
+ h += (h * 33) + ((guint) a->rt_cloned);
+
+ return h;
+}
+
+NMPlatformIP4Route *
+nm_platform_ip4_route_normalize (NMPlatformIP4Route *dst, const NMPlatformIP4Route *src, NMPlatformIPRouteIdType id_type)
+{
+ nm_assert (dst);
+
+ if (src && src != dst)
+ *dst = *src;
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ dst->network = nm_utils_ip4_address_clear_host_address (dst->network, dst->plen);
+ dst->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (dst->rt_source);
+ dst->rt_scope = nm_platform_route_scope_from_ip4_route (dst);
+ dst->rt_scope_is_set = TRUE;
+ break;
+ default:
+ break;
+ }
+ return dst;
+}
+
int
nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b)
{
+ return nm_platform_ip6_route_cmp_full (a, b, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+}
+
+int
+nm_platform_ip6_route_cmp_full (const NMPlatformIP6Route *a, const NMPlatformIP6Route *b, NMPlatformIPRouteIdType id_type)
+{
+ struct in6_addr network_a, network_b;
+ guint32 metric_a, metric_b;
+ guint8 rtprot_a, rtprot_b;
+
_CMP_SELF (a, b);
+
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD_MEMCMP (a, b, network);
+
+ nm_utils_ip6_address_clear_host_address (&network_a, &a->network, a->plen);
+ nm_utils_ip6_address_clear_host_address (&network_b, &b->network, b->plen);
+ _CMP_DIRECT_MEMCMP (&network_a, &network_b, sizeof (struct in6_addr));
+
_CMP_FIELD (a, b, plen);
- _CMP_FIELD (a, b, metric);
+
+ metric_a = nm_utils_ip6_route_metric_normalize (a->metric);
+ metric_b = nm_utils_ip6_route_metric_normalize (b->metric);
+ _CMP_DIRECT (metric_a, metric_b);
+
_CMP_FIELD_MEMCMP (a, b, gateway);
- _CMP_FIELD (a, b, rt_source);
+
+ rtprot_a = nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source);
+ rtprot_b = nmp_utils_ip_config_source_coerce_to_rtprot (b->rt_source);
+ _CMP_DIRECT (rtprot_a, rtprot_b);
+
_CMP_FIELD (a, b, mss);
_CMP_FIELD (a, b, rt_cloned);
+
+ /* currently we have two id-types, ID and ALL. Let ALL be a stricter
+ * ordering then ID, but yield the same order. Thus, above we first check
+ * all the ID fields, only if those are all equal, dig deeper. */
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ break;
+ default:
+ _CMP_FIELD_MEMCMP (a, b, network);
+ _CMP_FIELD (a, b, metric);
+ _CMP_FIELD (a, b, rt_source);
+ break;
+ }
return 0;
}
+guint
+nm_platform_ip6_route_hash_full (const NMPlatformIP6Route *a, NMPlatformIPRouteIdType id_type)
+{
+ struct in6_addr network;
+
+ guint h = 0x0569b8f4;
+
+ if (!a)
+ return h;
+
+ h += (h * 33) + ((guint) a->ifindex);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ nm_utils_ip6_address_clear_host_address (&network, &a->network, a->plen);
+ h += (h * 33) + ((guint) network.s6_addr32[0]);
+ h += (h * 33) + ((guint) network.s6_addr32[1]);
+ h += (h * 33) + ((guint) network.s6_addr32[2]);
+ h += (h * 33) + ((guint) network.s6_addr32[3]);
+ break;
+ default:
+ h += (h * 33) + ((guint) a->network.s6_addr32[0]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[1]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[2]);
+ h += (h * 33) + ((guint) a->network.s6_addr32[3]);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->plen);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nm_utils_ip6_route_metric_normalize (a->metric));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->metric);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[0]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[1]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[2]);
+ h += (h * 33) + ((guint) a->gateway.s6_addr32[3]);
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ h += (h * 33) + ((guint) nmp_utils_ip_config_source_coerce_to_rtprot (a->rt_source));
+ break;
+ default:
+ h += (h * 33) + ((guint) a->rt_source);
+ break;
+ }
+
+ h += (h * 33) + ((guint) a->mss);
+ h += (h * 33) + ((guint) a->rt_cloned);
+ return h;
+}
+
+NMPlatformIP6Route *
+nm_platform_ip6_route_normalize (NMPlatformIP6Route *dst, const NMPlatformIP6Route *src, NMPlatformIPRouteIdType id_type)
+{
+ nm_assert (dst);
+
+ if (src && src != dst)
+ *dst = *src;
+
+ switch (id_type) {
+ case NM_PLATFORM_IP_ROUTE_ID_TYPE_ID:
+ nm_utils_ip6_address_clear_host_address (&dst->network, &dst->network, dst->plen);
+ dst->rt_source = nmp_utils_ip_config_source_round_trip_rtprot (dst->rt_source);
+ dst->metric = nm_utils_ip6_route_metric_normalize (dst->metric);
+ break;
+ default:
+ break;
+ }
+ return dst;
+}
+
/**
* nm_platform_ip_address_cmp_expiry:
* @a: a NMPlatformIPAddress to compare
@@ -4114,50 +4303,45 @@ nm_platform_netns_push (NMPlatform *platform, NMPNetns **netns)
/******************************************************************/
static gboolean
-_vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
+_vtr_v4_route_add (NMPlatform *self, const NMPlatformIPXRoute *route, int ifindex, gint64 metric)
{
- return nm_platform_ip4_route_add (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.rt_source,
- route->r4.network,
- route->rx.plen,
- route->r4.gateway,
- route->r4.pref_src,
- metric >= 0 ? (guint32) metric : route->rx.metric,
- route->rx.mss);
+ NMPlatformIPXRoute r_storage;
+
+ if ( (ifindex > 0 && ifindex != route->rx.ifindex)
+ || (metric >= 0 && metric != route->rx.metric)) {
+ r_storage.r4 = route->r4;
+ r_storage.rx.ifindex = ifindex;
+ r_storage.rx.metric = metric;
+ route = &r_storage;
+ }
+ return nm_platform_ip4_route_add (self, &route->r4);
}
static gboolean
-_vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route, gint64 metric)
+_vtr_v6_route_add (NMPlatform *self, const NMPlatformIPXRoute *route, int ifindex, gint64 metric)
{
- return nm_platform_ip6_route_add (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.rt_source,
- route->r6.network,
- route->rx.plen,
- route->r6.gateway,
- metric >= 0 ? (guint32) metric : route->rx.metric,
- route->rx.mss);
+ NMPlatformIPXRoute r_storage;
+
+ if ( (ifindex > 0 && ifindex != route->rx.ifindex)
+ || (metric >= 0 && metric != route->rx.metric)) {
+ r_storage.r6 = route->r6;
+ r_storage.rx.ifindex = ifindex;
+ r_storage.rx.metric = nm_utils_ip6_route_metric_normalize (metric);
+ route = &r_storage;
+ }
+ return nm_platform_ip6_route_add (self, &route->r6);
}
static gboolean
-_vtr_v4_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
+_vtr_v4_route_delete (NMPlatform *self, const NMPlatformIPXRoute *route)
{
- return nm_platform_ip4_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r4.network,
- route->rx.plen,
- route->rx.metric);
+ return nm_platform_ip4_route_delete (self, &route->r4);
}
static gboolean
-_vtr_v6_route_delete (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *route)
+_vtr_v6_route_delete (NMPlatform *self, const NMPlatformIPXRoute *route)
{
- return nm_platform_ip6_route_delete (self,
- ifindex > 0 ? ifindex : route->rx.ifindex,
- route->r6.network,
- route->rx.plen,
- route->rx.metric);
+ return nm_platform_ip6_route_delete (self, &route->r6);
}
static guint32
@@ -4166,18 +4350,6 @@ _vtr_v4_metric_normalize (guint32 metric)
return metric;
}
-static gboolean
-_vtr_v4_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip4_route_delete (self, ifindex, 0, 0, metric);
-}
-
-static gboolean
-_vtr_v6_route_delete_default (NMPlatform *self, int ifindex, guint32 metric)
-{
- return nm_platform_ip6_route_delete (self, ifindex, in6addr_any, 0, metric);
-}
-
/******************************************************************/
const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
@@ -4189,7 +4361,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v4 = {
.route_get_all = nm_platform_ip4_route_get_all,
.route_add = _vtr_v4_route_add,
.route_delete = _vtr_v4_route_delete,
- .route_delete_default = _vtr_v4_route_delete_default,
.metric_normalize = _vtr_v4_metric_normalize,
};
@@ -4202,7 +4373,6 @@ const NMPlatformVTableRoute nm_platform_vtable_route_v6 = {
.route_get_all = nm_platform_ip6_route_get_all,
.route_add = _vtr_v6_route_add,
.route_delete = _vtr_v6_route_delete,
- .route_delete_default = _vtr_v6_route_delete_default,
.metric_normalize = nm_utils_ip6_route_metric_normalize,
};