diff options
Diffstat (limited to 'src/platform/nm-linux-platform.c')
-rw-r--r-- | src/platform/nm-linux-platform.c | 119 |
1 files changed, 70 insertions, 49 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 11c2e965b2..885b066b17 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -304,6 +304,16 @@ _support_user_ipv6ll_detect (struct nlattr **tb) ******************************************************************/ static void +_ip6_route_normalize_metric (const NMPlatformIP6Route **route, NMPlatformIP6Route *r_storage) +{ + if ((*route)->metric != nm_utils_ip6_route_metric_normalize ((*route)->metric)) { + *r_storage = **route; + r_storage->metric = nm_utils_ip6_route_metric_normalize ((*route)->metric); + *route = r_storage; + } +} + +static void clear_host_address (int family, const void *network, guint8 plen, void *dst) { g_return_if_fail (network); @@ -3876,6 +3886,16 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg * event_handler_read_netlink (platform, FALSE); + if (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) { + /* for routes, we set the flags to NLM_F_CREATE | NLM_F_APPEND. This will fail with EEXIST + * if the route already exists, which is just splendind. + * + * So, first check the cache whether we expect the route to exist, and if so, set the + * flags to REPLACE. */ + if (nmp_cache_lookup_obj (priv->cache, obj_id)) + nlmsg_hdr (nlmsg)->nlmsg_flags |= NLM_F_REPLACE; + } + nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL); if (nle < 0) { _LOGE ("do-add-%s[%s]: failure sending netlink request \"%s\" (%d)", @@ -5548,65 +5568,64 @@ ip6_route_get_all (NMPlatform *platform, int ifindex, NMPlatformGetRouteFlags fl } static gboolean -ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, - in_addr_t network, guint8 plen, in_addr_t gateway, - in_addr_t pref_src, guint32 metric, guint32 mss) +ip4_route_add (NMPlatform *platform, const NMPlatformIP4Route *route) { NMPObject obj_id; nm_auto_nlmsg struct nl_msg *nlmsg = NULL; nlmsg = _nl_msg_new_route (RTM_NEWROUTE, - NLM_F_CREATE | NLM_F_REPLACE, + NLM_F_CREATE | NLM_F_APPEND, AF_INET, - ifindex, - source, - gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, - &network, - plen, - &gateway, - metric, - mss, - pref_src ? &pref_src : NULL); - - nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric); + route->ifindex, + route->rt_source, + route->gateway ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, + &route->network, + route->plen, + &route->gateway, + route->metric, + route->mss, + route->pref_src ? &route->pref_src : NULL); + + nmp_object_stackinit_id_ip4_route (&obj_id, route); return do_add_addrroute (platform, &obj_id, nlmsg); } static gboolean -ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source, - struct in6_addr network, guint8 plen, struct in6_addr gateway, - guint32 metric, guint32 mss) +ip6_route_add (NMPlatform *platform, const NMPlatformIP6Route *route) { NMPObject obj_id; nm_auto_nlmsg struct nl_msg *nlmsg = NULL; + NMPlatformIP6Route r_storage; + + _ip6_route_normalize_metric (&route, &r_storage); nlmsg = _nl_msg_new_route (RTM_NEWROUTE, - NLM_F_CREATE | NLM_F_REPLACE, + NLM_F_CREATE | NLM_F_APPEND, AF_INET6, - ifindex, - source, - !IN6_IS_ADDR_UNSPECIFIED (&gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, - &network, - plen, - &gateway, - metric, - mss, + route->ifindex, + route->rt_source, + !IN6_IS_ADDR_UNSPECIFIED (&route->gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, + &route->network, + route->plen, + &route->gateway, + route->metric, + route->mss, NULL); - nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric); + nmp_object_stackinit_id_ip6_route (&obj_id, route); return do_add_addrroute (platform, &obj_id, nlmsg); } static gboolean -ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric) +ip4_route_delete (NMPlatform *platform, const NMPlatformIP4Route *route) { NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform); nm_auto_nlmsg struct nl_msg *nlmsg = NULL; NMPObject obj_id; - nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric); + nmp_object_stackinit_id_ip4_route (&obj_id, route); - if (metric == 0) { + if (route->metric == 0) { /* Deleting an IPv4 route with metric 0 does not only delete an exectly matching route. * If no route with metric 0 exists, it might delete another route to the same destination. * For nm_platform_ip4_route_delete() we don't want this semantic. @@ -5638,13 +5657,13 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p nlmsg = _nl_msg_new_route (RTM_DELROUTE, 0, AF_INET, - ifindex, + route->ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN, RT_SCOPE_NOWHERE, - &network, - plen, - NULL, - metric, + &route->network, + route->plen, + &route->gateway, + route->metric, 0, NULL); if (!nlmsg) @@ -5654,40 +5673,41 @@ ip4_route_delete (NMPlatform *platform, int ifindex, in_addr_t network, guint8 p } static gboolean -ip6_route_delete (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) +ip6_route_delete (NMPlatform *platform, const NMPlatformIP6Route *route) { nm_auto_nlmsg struct nl_msg *nlmsg = NULL; NMPObject obj_id; + NMPlatformIP6Route r_storage; - metric = nm_utils_ip6_route_metric_normalize (metric); + _ip6_route_normalize_metric (&route, &r_storage); nlmsg = _nl_msg_new_route (RTM_DELROUTE, 0, AF_INET6, - ifindex, + route->ifindex, NM_IP_CONFIG_SOURCE_UNKNOWN, RT_SCOPE_NOWHERE, - &network, - plen, - NULL, - metric, + &route->network, + route->plen, + &route->gateway, + route->metric, 0, NULL); if (!nlmsg) return FALSE; - nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric); + nmp_object_stackinit_id_ip6_route (&obj_id, route); return do_delete_object (platform, &obj_id, nlmsg); } static const NMPlatformIP4Route * -ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen, guint32 metric) +ip4_route_get (NMPlatform *platform, const NMPlatformIP4Route *route) { NMPObject obj_id; const NMPObject *obj; - nmp_object_stackinit_id_ip4_route (&obj_id, ifindex, network, plen, metric); + nmp_object_stackinit_id_ip4_route (&obj_id, route); obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id); if (nmp_object_is_visible (obj)) return &obj->ip4_route; @@ -5695,14 +5715,15 @@ ip4_route_get (NMPlatform *platform, int ifindex, in_addr_t network, guint8 plen } static const NMPlatformIP6Route * -ip6_route_get (NMPlatform *platform, int ifindex, struct in6_addr network, guint8 plen, guint32 metric) +ip6_route_get (NMPlatform *platform, const NMPlatformIP6Route *route) { NMPObject obj_id; const NMPObject *obj; + NMPlatformIP6Route r_storage; - metric = nm_utils_ip6_route_metric_normalize (metric); + _ip6_route_normalize_metric (&route, &r_storage); - nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric); + nmp_object_stackinit_id_ip6_route (&obj_id, route); obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id); if (nmp_object_is_visible (obj)) return &obj->ip6_route; |