summaryrefslogtreecommitdiff
path: root/src/platform/nm-linux-platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/nm-linux-platform.c')
-rw-r--r--src/platform/nm-linux-platform.c243
1 files changed, 103 insertions, 140 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 82e673a3c1..baf4d7ccab 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -1864,8 +1864,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
else
obj->ip6_route.gateway = nh.gateway.addr6;
- if (is_v4)
- obj->ip4_route.scope_inv = nm_platform_route_scope_inv (rtm->rtm_scope);
+ if (is_v4) {
+ obj->ip4_route.rt_scope = rtm->rtm_scope;
+ obj->ip4_route.rt_scope_is_set = TRUE;
+ }
if (is_v4) {
if (_check_addr_or_errout (tb, RTA_PREFSRC, addr_len))
@@ -2229,77 +2231,79 @@ nla_put_failure:
static struct nl_msg *
_nl_msg_new_route (int nlmsg_type,
int nlmsg_flags,
- int family,
- int ifindex,
- NMIPConfigSource source,
- unsigned char scope,
- gconstpointer network,
- guint8 plen,
- gconstpointer gateway,
- guint32 metric,
- guint32 mss,
- gconstpointer pref_src)
+ const NMPObject *obj)
{
- struct nl_msg *msg;
- struct rtmsg rtmsg = {
- .rtm_family = family,
- .rtm_tos = 0,
- .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
- .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
- .rtm_scope = scope,
- .rtm_type = RTN_UNICAST,
- .rtm_flags = 0,
- .rtm_dst_len = plen,
- .rtm_src_len = 0,
- };
+ int addr_family;
+ gboolean is_v4;
+ const NMIPAddr *gateway;
NMIPAddr network_clean;
-
gsize addr_len;
+ struct nl_msg *msg;
- nm_assert (NM_IN_SET (family, AF_INET, AF_INET6));
+ nm_assert (NM_IN_SET (NMP_OBJECT_GET_TYPE (obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
nm_assert (NM_IN_SET (nlmsg_type, RTM_NEWROUTE, RTM_DELROUTE));
- nm_assert (network);
msg = nlmsg_alloc_simple (nlmsg_type, nlmsg_flags);
if (!msg)
- g_return_val_if_reached (NULL);
+ return NULL;
- if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
- goto nla_put_failure;
+ addr_family = NMP_OBJECT_GET_CLASS (obj)->addr_family;
+ is_v4 = (addr_family == AF_INET);
+ addr_len = is_v4 ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+
+ gateway = is_v4
+ ? (gpointer) &obj->ip4_route.gateway
+ : (gpointer) &obj->ip6_route.gateway;
+
+ {
+ struct rtmsg rtmsg = {
+ .rtm_family = addr_family,
+ .rtm_tos = 0,
+ .rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
+ .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (obj->ip_route.rt_source),
+ .rtm_scope = is_v4
+ ? nm_platform_route_scope_from_ip4_route (&obj->ip4_route)
+ : nm_platform_route_scope_for_ip6_gateway (&gateway->addr6),
+ .rtm_type = RTN_UNICAST,
+ .rtm_flags = 0,
+ .rtm_dst_len = obj->ip_route.plen,
+ .rtm_src_len = 0,
+ };
- addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
+ if (nlmsg_append (msg, &rtmsg, sizeof (rtmsg), NLMSG_ALIGNTO) < 0)
+ goto nla_put_failure;
+ }
- nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
+ nm_utils_ipx_address_clear_host_address (addr_family, &network_clean, obj->ip_route.network_ptr, obj->ip_route.plen);
NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
- NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
+ NLA_PUT_U32 (msg, RTA_PRIORITY, obj->ip_route.metric);
- if (pref_src)
- NLA_PUT (msg, RTA_PREFSRC, addr_len, pref_src);
+ if (is_v4 && obj->ip4_route.pref_src)
+ NLA_PUT (msg, RTA_PREFSRC, addr_len, &obj->ip4_route.pref_src);
- if (mss > 0) {
+ if (obj->ip_route.mss > 0) {
struct nlattr *metrics;
metrics = nla_nest_start (msg, RTA_METRICS);
if (!metrics)
goto nla_put_failure;
- NLA_PUT_U32 (msg, RTAX_ADVMSS, mss);
+ NLA_PUT_U32 (msg, RTAX_ADVMSS, obj->ip_route.mss);
nla_nest_end(msg, metrics);
}
/* We currently don't have need for multi-hop routes... */
- if ( gateway
- && memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
+ if (memcmp (gateway, &nm_ip_addr_zero, addr_len) != 0)
NLA_PUT (msg, RTA_GATEWAY, addr_len, gateway);
- NLA_PUT_U32 (msg, RTA_OIF, ifindex);
+ NLA_PUT_U32 (msg, RTA_OIF, obj->ip_route.ifindex);
return msg;
nla_put_failure:
nlmsg_free (msg);
- g_return_val_if_reached (NULL);
+ return NULL;
}
/******************************************************************/
@@ -3902,6 +3906,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
WaitForNlResponseResult seq_result = WAIT_FOR_NL_RESPONSE_RESULT_UNKNOWN;
+ gboolean success = FALSE;
int nle;
char s_buf[256];
const NMPObject *obj;
@@ -3925,9 +3930,15 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
nm_assert (seq_result);
- _NMLOG (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK
- ? LOGL_DEBUG
- : LOGL_ERR,
+ if (seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK)
+ success = TRUE;
+ else if ( (int) seq_result == -EEXIST
+ && NM_IN_SET (NMP_OBJECT_GET_TYPE (obj_id),
+ NMP_OBJECT_TYPE_IP4_ROUTE,
+ NMP_OBJECT_TYPE_IP6_ROUTE))
+ success = TRUE;
+
+ _NMLOG (success ? LOGL_DEBUG : LOGL_ERR,
"do-add-%s[%s]: %s",
NMP_OBJECT_GET_CLASS (obj_id)->obj_type_name,
nmp_object_to_string (obj_id, NMP_OBJECT_TO_STRING_ID, NULL, 0),
@@ -3950,7 +3961,7 @@ do_add_addrroute (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
/* Adding is only successful, if kernel reported success *and* we have the
* expected object in cache afterwards. */
- return obj && seq_result == WAIT_FOR_NL_RESPONSE_RESULT_RESPONSE_OK;
+ return obj && success;
}
static gboolean
@@ -3963,8 +3974,6 @@ do_delete_object (NMPlatform *platform, const NMPObject *obj_id, struct nl_msg *
gboolean success = TRUE;
const char *log_detail = "";
- event_handler_read_netlink (platform, FALSE);
-
nle = _nl_send_auto_with_seq (platform, nlmsg, &seq_result, NULL);
if (nle < 0) {
_LOGE ("do-delete-%s[%s]: failure sending netlink request \"%s\" (%d)",
@@ -4122,6 +4131,8 @@ link_delete (NMPlatform *platform, int ifindex)
NMPObject obj_id;
const NMPObject *obj;
+ delayed_action_handle_all (platform, TRUE);
+
obj = nmp_cache_lookup_link (priv->cache, ifindex);
if (!obj || !obj->_link.netlink.is_in_netlink)
return FALSE;
@@ -4132,6 +4143,8 @@ link_delete (NMPlatform *platform, int ifindex)
NULL,
0,
0);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
nmp_object_stackinit_id_link (&obj_id, ifindex);
return do_delete_object (platform, &obj_id, nlmsg);
@@ -5494,6 +5507,8 @@ ip4_address_delete (NMPlatform *platform, int ifindex, in_addr_t addr, guint8 pl
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
+ delayed_action_handle_all (platform, TRUE);
+
nlmsg = _nl_msg_new_address (RTM_DELADDR,
0,
AF_INET,
@@ -5519,6 +5534,8 @@ ip6_address_delete (NMPlatform *platform, int ifindex, struct in6_addr addr, gui
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
+ delayed_action_handle_all (platform, TRUE);
+
nlmsg = _nl_msg_new_address (RTM_DELADDR,
0,
AF_INET6,
@@ -5618,146 +5635,93 @@ 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;
+ nmp_object_stackinit_id_ip4_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
- 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);
+ NLM_F_CREATE | NLM_F_APPEND,
+ &obj_id);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
+
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;
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
nlmsg = _nl_msg_new_route (RTM_NEWROUTE,
- NLM_F_CREATE | NLM_F_REPLACE,
- AF_INET6,
- ifindex,
- source,
- !IN6_IS_ADDR_UNSPECIFIED (&gateway) ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK,
- &network,
- plen,
- &gateway,
- metric,
- mss,
- NULL);
-
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ NLM_F_CREATE | NLM_F_APPEND,
+ &obj_id);
+ if (!nlmsg)
+ g_return_val_if_reached (FALSE);
+
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, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
- if (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.
- *
- * Instead, make sure that we have the most recent state and process all
- * delayed actions (including re-reading data from netlink). */
- delayed_action_handle_all (platform, TRUE);
-
- if (!nmp_cache_lookup_obj (priv->cache, &obj_id)) {
- /* hmm... we are about to delete an IP4 route with metric 0. We must only
- * send the delete request if such a route really exists. Above we refreshed
- * the platform cache, still no such route exists.
- *
- * Be extra careful and reload the routes. We must be sure that such a
- * route doesn't exists, because when we add an IPv4 address, we immediately
- * afterwards try to delete the kernel-added device route with metric 0.
- * It might be, that we didn't yet get the notification about that route.
- *
- * FIXME: once our ip4_address_add() is sure that upon return we have
- * the latest state from in the platform cache, we might save this
- * additional expensive cache-resync. */
- do_request_one_type (platform, NMP_OBJECT_TYPE_IP4_ROUTE);
+ delayed_action_handle_all (platform, TRUE);
- if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
- return TRUE;
- }
- }
+ if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
+ return TRUE;
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
- AF_INET,
- ifindex,
- NM_IP_CONFIG_SOURCE_UNKNOWN,
- RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
- 0,
- NULL);
+ &obj_id);
if (!nlmsg)
- return FALSE;
+ g_return_val_if_reached (FALSE);
return do_delete_object (platform, &obj_id, nlmsg);
}
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)
{
+ NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
NMPObject obj_id;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ALL);
+
+ delayed_action_handle_all (platform, TRUE);
+
+ if (!nmp_cache_lookup_obj (priv->cache, &obj_id))
+ return TRUE;
nlmsg = _nl_msg_new_route (RTM_DELROUTE,
0,
- AF_INET6,
- ifindex,
- NM_IP_CONFIG_SOURCE_UNKNOWN,
- RT_SCOPE_NOWHERE,
- &network,
- plen,
- NULL,
- metric,
- 0,
- NULL);
+ &obj_id);
if (!nlmsg)
- return FALSE;
-
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
+ g_return_val_if_reached (FALSE);
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, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
+
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip4_route;
@@ -5765,14 +5729,13 @@ 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;
- metric = nm_utils_ip6_route_metric_normalize (metric);
+ nmp_object_stackinit_id_ip6_route (&obj_id, route, NM_PLATFORM_IP_ROUTE_ID_TYPE_ID);
- nmp_object_stackinit_id_ip6_route (&obj_id, ifindex, &network, plen, metric);
obj = nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, &obj_id);
if (nmp_object_is_visible (obj))
return &obj->ip6_route;
@@ -5928,7 +5891,7 @@ continue_reading:
int errsv = e->error > 0 ? e->error : -e->error;
/* Error message reported back from kernel. */
- _LOGD ("netlink: recvmsg: error message from kernel: %s (%d) for request %d",
+ _LOGT ("netlink: recvmsg: error message from kernel: %s (%d) for request %d",
strerror (errsv),
errsv,
nlmsg_hdr (msg)->nlmsg_seq);