summaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/nm-fake-platform.c21
-rw-r--r--src/platform/nm-linux-platform.c269
-rw-r--r--src/platform/nm-linux-platform.h6
-rw-r--r--src/platform/nm-platform-utils.c134
-rw-r--r--src/platform/nm-platform-utils.h7
-rw-r--r--src/platform/nm-platform.c162
-rw-r--r--src/platform/nm-platform.h34
-rw-r--r--src/platform/nmp-object.c4
-rw-r--r--src/platform/nmp-object.h6
-rw-r--r--src/platform/tests/monitor.c2
-rw-r--r--src/platform/tests/test-common.h2
-rw-r--r--src/platform/tests/test-general.c2
-rw-r--r--src/platform/tests/test-link.c4
-rw-r--r--src/platform/tests/test-nmp-object.c2
-rw-r--r--src/platform/tests/test-route.c16
-rw-r--r--src/platform/wifi/wifi-utils.c21
-rw-r--r--src/platform/wifi/wifi-utils.h2
17 files changed, 426 insertions, 268 deletions
diff --git a/src/platform/nm-fake-platform.c b/src/platform/nm-fake-platform.c
index 7b54507696..d0fb277462 100644
--- a/src/platform/nm-fake-platform.c
+++ b/src/platform/nm-fake-platform.c
@@ -31,9 +31,10 @@
#include "nm-utils.h"
#include "nm-core-utils.h"
+#include "nm-platform-utils.h"
#include "nmp-object.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
/*********************************************************************************************/
@@ -709,12 +710,13 @@ static gboolean
infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link)
{
NMFakePlatformLink *device, *parent_device;
- gs_free char *name = NULL;
+ char name[IFNAMSIZ];
parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE);
- name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key);
+ nm_utils_new_infiniband_name (name, parent_device->link.name, p_key);
+
if (!link_add (platform, name, NM_LINK_TYPE_INFINIBAND, NULL, 0, out_link))
return FALSE;
@@ -726,7 +728,6 @@ infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMP
device->lnk->lnk_infiniband.p_key = p_key;
device->lnk->lnk_infiniband.mode = "datagram";
device->link.parent = parent;
-
return TRUE;
}
@@ -739,7 +740,7 @@ infiniband_partition_delete (NMPlatform *platform, int parent, int p_key)
parent_device = link_get (platform, parent);
g_return_val_if_fail (parent_device != NULL, FALSE);
- name = g_strdup_printf ("%s.%04x", parent_device->link.name, p_key);
+ nm_utils_new_infiniband_name (name, parent_device->link.name, p_key);
return link_delete (platform, nm_platform_link_get_ifindex (platform, name));
}
@@ -911,7 +912,7 @@ ip4_address_add (NMPlatform *platform,
int i;
memset (&address, 0, sizeof (address));
- address.source = NM_IP_CONFIG_SOURCE_KERNEL;
+ address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = peer_addr;
@@ -962,7 +963,7 @@ ip6_address_add (NMPlatform *platform,
int i;
memset (&address, 0, sizeof (address));
- address.source = NM_IP_CONFIG_SOURCE_KERNEL;
+ address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
address.ifindex = ifindex;
address.address = addr;
address.peer_address = (IN6_IS_ADDR_UNSPECIFIED (&peer_addr) || IN6_ARE_ADDR_EQUAL (&addr, &peer_addr)) ? in6addr_any : peer_addr;
@@ -1207,9 +1208,8 @@ ip4_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
scope = gateway == 0 ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
memset (&route, 0, sizeof (route));
- route.source = NM_IP_CONFIG_SOURCE_KERNEL;
route.ifindex = ifindex;
- route.source = source;
+ route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
route.network = nm_utils_ip4_address_clear_host_address (network, plen);
route.plen = plen;
route.gateway = gateway;
@@ -1273,9 +1273,8 @@ ip6_route_add (NMPlatform *platform, int ifindex, NMIPConfigSource source,
metric = nm_utils_ip6_route_metric_normalize (metric);
memset (&route, 0, sizeof (route));
- route.source = NM_IP_CONFIG_SOURCE_KERNEL;
route.ifindex = ifindex;
- route.source = source;
+ route.rt_source = nmp_utils_ip_config_source_round_trip_rtprot (source);
nm_utils_ip6_address_clear_host_address (&route.network, &network, plen);
route.plen = plen;
route.gateway = gateway;
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 3eb7ff3f8d..4e41bc9b27 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -176,6 +176,11 @@
* Forward declarations and enums
******************************************************************/
+typedef enum {
+ INFINIBAND_ACTION_CREATE_CHILD,
+ INFINIBAND_ACTION_DELETE_CHILD,
+} InfinibandAction;
+
enum {
DELAYED_ACTION_IDX_REFRESH_ALL_LINKS,
DELAYED_ACTION_IDX_REFRESH_ALL_IP4_ADDRESSES,
@@ -303,23 +308,6 @@ _support_user_ipv6ll_detect (struct nlattr **tb)
* Various utilities
******************************************************************/
-static void
-clear_host_address (int family, const void *network, guint8 plen, void *dst)
-{
- g_return_if_fail (network);
-
- switch (family) {
- case AF_INET:
- *((in_addr_t *) dst) = nm_utils_ip4_address_clear_host_address (*((in_addr_t *) network), plen);
- break;
- case AF_INET6:
- nm_utils_ip6_address_clear_host_address ((struct in6_addr *) dst, (const struct in6_addr *) network, plen);
- break;
- default:
- g_assert_not_reached ();
- }
-}
-
static int
_vlan_qos_mapping_cmp_from (gconstpointer a, gconstpointer b, gpointer user_data)
{
@@ -588,12 +576,17 @@ _lookup_cached_link (const NMPCache *cache, int ifindex, gboolean *completed_fro
#define DEVTYPE_PREFIX "DEVTYPE="
static char *
-_linktype_read_devtype (const char *sysfs_path)
+_linktype_read_devtype (const char *ifname)
{
- gs_free char *uevent = g_strdup_printf ("%s/uevent", sysfs_path);
+ char uevent[NM_STRLEN ("/sys/class/net/123456789012345/uevent\0") + 100 /*safety*/];
char *contents = NULL;
char *cont, *end;
+ nm_sprintf_buf (uevent,
+ "/sys/class/net/%s/uevent",
+ NM_ASSERT_VALID_PATH_COMPONENT (ifname));
+ nm_assert (strlen (uevent) < sizeof (uevent) - 1);
+
if (!g_file_get_contents (uevent, &contents, NULL, NULL))
return NULL;
for (cont = contents; cont; cont = end) {
@@ -690,9 +683,8 @@ _linktype_get_type (NMPlatform *platform,
return NM_LINK_TYPE_IP6TNL;
if (ifname) {
+ char anycast_mask[NM_STRLEN ("/sys/class/net/123456789012345/anycast_mask\0") + 100 /*safety*/];
gs_free char *driver = NULL;
- gs_free char *sysfs_path = NULL;
- gs_free char *anycast_mask = NULL;
gs_free char *devtype = NULL;
/* Fallback OVS detection for kernel <= 3.16 */
@@ -709,12 +701,15 @@ _linktype_get_type (NMPlatform *platform,
}
}
- sysfs_path = g_strdup_printf ("/sys/class/net/%s", ifname);
- anycast_mask = g_strdup_printf ("%s/anycast_mask", sysfs_path);
+ nm_sprintf_buf (anycast_mask,
+ "/sys/class/net/%s/anycast_mask",
+ NM_ASSERT_VALID_PATH_COMPONENT (ifname));
+ nm_assert (strlen (anycast_mask) < sizeof (anycast_mask) - 1);
+
if (g_file_test (anycast_mask, G_FILE_TEST_EXISTS))
return NM_LINK_TYPE_OLPC_MESH;
- devtype = _linktype_read_devtype (sysfs_path);
+ devtype = _linktype_read_devtype (ifname);
for (i = 0; devtype && i < G_N_ELEMENTS (linktypes); i++) {
if (g_strcmp0 (devtype, linktypes[i].devtype) == 0) {
if (linktypes[i].nm_type == NM_LINK_TYPE_BNEP) {
@@ -729,7 +724,7 @@ _linktype_get_type (NMPlatform *platform,
}
/* Fallback for drivers that don't call SET_NETDEV_DEVTYPE() */
- if (wifi_utils_is_wifi (ifname, sysfs_path))
+ if (wifi_utils_is_wifi (ifname))
return NM_LINK_TYPE_WIFI;
if (arptype == ARPHRD_ETHER) {
@@ -803,9 +798,10 @@ _nl_nlmsg_type_to_str (guint16 type, char *buf, gsize len)
static gboolean
_parse_af_inet6 (NMPlatform *platform,
struct nlattr *attr,
- NMUtilsIPv6IfaceId *out_iid,
- guint8 *out_iid_is_valid,
- guint8 *out_addr_gen_mode_inv)
+ NMUtilsIPv6IfaceId *out_token,
+ gboolean *out_token_valid,
+ guint8 *out_addr_gen_mode_inv,
+ gboolean *out_addr_gen_mode_valid)
{
static struct nla_policy policy[IFLA_INET6_MAX+1] = {
[IFLA_INET6_FLAGS] = { .type = NLA_U32 },
@@ -819,7 +815,8 @@ _parse_af_inet6 (NMPlatform *platform,
struct nlattr *tb[IFLA_INET6_MAX+1];
int err;
struct in6_addr i6_token;
- gboolean iid_is_valid = FALSE;
+ gboolean token_valid = FALSE;
+ gboolean addr_gen_mode_valid = FALSE;
guint8 i6_addr_gen_mode_inv = 0;
gboolean success = FALSE;
@@ -836,8 +833,7 @@ _parse_af_inet6 (NMPlatform *platform,
if (_check_addr_or_errout (tb, IFLA_INET6_TOKEN, sizeof (struct in6_addr))) {
nla_memcpy (&i6_token, tb[IFLA_INET6_TOKEN], sizeof (struct in6_addr));
- if (!IN6_IS_ADDR_UNSPECIFIED (&i6_token))
- iid_is_valid = TRUE;
+ token_valid = TRUE;
}
/* Hack to detect support addrgenmode of the kernel. We only parse
@@ -852,21 +848,18 @@ _parse_af_inet6 (NMPlatform *platform,
* to signal "unset". */
goto errout;
}
+ addr_gen_mode_valid = TRUE;
}
success = TRUE;
- if (iid_is_valid) {
- out_iid->id_u8[7] = i6_token.s6_addr[15];
- out_iid->id_u8[6] = i6_token.s6_addr[14];
- out_iid->id_u8[5] = i6_token.s6_addr[13];
- out_iid->id_u8[4] = i6_token.s6_addr[12];
- out_iid->id_u8[3] = i6_token.s6_addr[11];
- out_iid->id_u8[2] = i6_token.s6_addr[10];
- out_iid->id_u8[1] = i6_token.s6_addr[9];
- out_iid->id_u8[0] = i6_token.s6_addr[8];
- *out_iid_is_valid = TRUE;
+ if (token_valid) {
+ *out_token_valid = token_valid;
+ nm_utils_ipv6_interface_identifier_get_from_addr (out_token, &i6_token);
+ }
+ if (addr_gen_mode_valid) {
+ *out_addr_gen_mode_valid = addr_gen_mode_valid;
+ *out_addr_gen_mode_inv = i6_addr_gen_mode_inv;
}
- *out_addr_gen_mode_inv = i6_addr_gen_mode_inv;
errout:
return success;
}
@@ -1441,6 +1434,8 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
NMPObject *lnk_data = NULL;
gboolean address_complete_from_cache = TRUE;
gboolean lnk_data_complete_from_cache = TRUE;
+ gboolean af_inet6_token_valid = FALSE;
+ gboolean af_inet6_addr_gen_mode_valid = FALSE;
if (!nlmsg_valid_hdr (nlh, sizeof (*ifi)))
return NULL;
@@ -1517,9 +1512,10 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
case AF_INET6:
_parse_af_inet6 (platform,
af_attr,
- &obj->link.inet6_token.iid,
- &obj->link.inet6_token.is_valid,
- &obj->link.inet6_addr_gen_mode_inv);
+ &obj->link.inet6_token,
+ &af_inet6_token_valid,
+ &obj->link.inet6_addr_gen_mode_inv,
+ &af_inet6_addr_gen_mode_valid);
break;
}
}
@@ -1561,7 +1557,9 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
if ( completed_from_cache
&& ( lnk_data_complete_from_cache
- || address_complete_from_cache)) {
+ || address_complete_from_cache
+ || !af_inet6_token_valid
+ || !af_inet6_addr_gen_mode_valid)) {
_lookup_cached_link (cache, obj->link.ifindex, completed_from_cache, &link_cached);
if (link_cached) {
if ( lnk_data_complete_from_cache
@@ -1580,6 +1578,10 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
}
if (address_complete_from_cache)
obj->link.addr = link_cached->link.addr;
+ if (!af_inet6_token_valid)
+ obj->link.inet6_token = link_cached->link.inet6_token;
+ if (!af_inet6_addr_gen_mode_valid)
+ obj->link.inet6_addr_gen_mode_inv = link_cached->link.inet6_addr_gen_mode_inv;
}
}
@@ -1666,7 +1668,7 @@ _new_from_nl_addr (struct nlmsghdr *nlh, gboolean id_only)
}
}
- obj->ip_address.source = NM_IP_CONFIG_SOURCE_KERNEL;
+ obj->ip_address.addr_source = NM_IP_CONFIG_SOURCE_KERNEL;
obj->ip_address.n_ifa_flags = tb[IFA_FLAGS]
? nla_get_u32 (tb[IFA_FLAGS])
@@ -1896,9 +1898,10 @@ _new_from_nl_route (struct nlmsghdr *nlh, gboolean id_only)
*
* This happens, because this route is not nmp_object_is_alive().
* */
- obj->ip_route.source = _NM_IP_CONFIG_SOURCE_RTM_F_CLONED;
- } else
- obj->ip_route.source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol);
+ obj->ip_route.rt_cloned = TRUE;
+ }
+
+ obj->ip_route.rt_source = nmp_utils_ip_config_source_from_rtprot (rtm->rtm_protocol);
obj_result = obj;
obj = NULL;
@@ -1951,7 +1954,8 @@ nmp_object_new_from_nl (NMPlatform *platform, const NMPCache *cache, struct nl_m
static gboolean
_nl_msg_new_link_set_afspec (struct nl_msg *msg,
- int addr_gen_mode)
+ int addr_gen_mode,
+ NMUtilsIPv6IfaceId *iid)
{
struct nlattr *af_spec;
struct nlattr *af_attr;
@@ -1961,11 +1965,19 @@ _nl_msg_new_link_set_afspec (struct nl_msg *msg,
if (!(af_spec = nla_nest_start (msg, IFLA_AF_SPEC)))
goto nla_put_failure;
- if (addr_gen_mode >= 0) {
+ if (addr_gen_mode >= 0 || iid) {
if (!(af_attr = nla_nest_start (msg, AF_INET6)))
goto nla_put_failure;
- NLA_PUT_U8 (msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode);
+ if (addr_gen_mode >= 0)
+ NLA_PUT_U8 (msg, IFLA_INET6_ADDR_GEN_MODE, addr_gen_mode);
+
+ if (iid) {
+ struct in6_addr i6_token = { .s6_addr = { 0, } };
+
+ nm_utils_ipv6_addr_set_interface_identifier (&i6_token, *iid);
+ NLA_PUT (msg, IFLA_INET6_TOKEN, sizeof (struct in6_addr), &i6_token);
+ }
nla_nest_end (msg, af_attr);
}
@@ -2258,7 +2270,7 @@ _nl_msg_new_route (int nlmsg_type,
.rtm_family = family,
.rtm_tos = 0,
.rtm_table = RT_TABLE_MAIN, /* omit setting RTA_TABLE attribute */
- .rtm_protocol = nmp_utils_ip_config_source_to_rtprot (source),
+ .rtm_protocol = nmp_utils_ip_config_source_coerce_to_rtprot (source),
.rtm_scope = scope,
.rtm_type = RTN_UNICAST,
.rtm_flags = 0,
@@ -2282,7 +2294,7 @@ _nl_msg_new_route (int nlmsg_type,
addr_len = family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr);
- clear_host_address (family, network, plen, &network_clean);
+ nm_utils_ipx_address_clear_host_address (family, &network_clean, network, plen);
NLA_PUT (msg, RTA_DST, addr_len, &network_clean);
NLA_PUT_U32 (msg, RTA_PRIORITY, metric);
@@ -2485,6 +2497,7 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
gsize len;
char *actual;
gs_free char *actual_free = NULL;
+ int errsv;
g_return_val_if_fail (path != NULL, FALSE);
g_return_val_if_fail (value != NULL, FALSE);
@@ -2495,18 +2508,22 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
/* Don't write to suspicious locations */
g_assert (!strstr (path, "/../"));
- if (!nm_platform_netns_push (platform, &netns))
+ if (!nm_platform_netns_push (platform, &netns)) {
+ errno = ENETDOWN;
return FALSE;
+ }
fd = open (path, O_WRONLY | O_TRUNC);
if (fd == -1) {
- if (errno == ENOENT) {
+ errsv = errno;
+ if (errsv == ENOENT) {
_LOGD ("sysctl: failed to open '%s': (%d) %s",
- path, errno, strerror (errno));
+ path, errsv, strerror (errsv));
} else {
_LOGE ("sysctl: failed to open '%s': (%d) %s",
- path, errno, strerror (errno));
+ path, errsv, strerror (errsv));
}
+ errno = errsv;
return FALSE;
}
@@ -2527,26 +2544,43 @@ sysctl_set (NMPlatform *platform, const char *path, const char *value)
actual[len] = '\0';
/* Try to write the entire value three times if a partial write occurs */
+ errsv = 0;
for (tries = 0, nwrote = 0; tries < 3 && nwrote != len; tries++) {
nwrote = write (fd, actual, len);
if (nwrote == -1) {
- if (errno == EINTR) {
+ errsv = errno;
+ if (errsv == EINTR) {
_LOGD ("sysctl: interrupted, will try again");
continue;
}
break;
}
}
- if (nwrote == -1 && errno != EEXIST) {
+ if (nwrote == -1 && errsv != EEXIST) {
_LOGE ("sysctl: failed to set '%s' to '%s': (%d) %s",
- path, value, errno, strerror (errno));
+ path, value, errsv, strerror (errsv));
} else if (nwrote < len) {
_LOGE ("sysctl: failed to set '%s' to '%s' after three attempts",
path, value);
}
- close (fd);
- return (nwrote == len);
+ if (nwrote != len) {
+ if (close (fd) != 0) {
+ if (errsv != 0)
+ errno = errsv;
+ } else if (errsv != 0)
+ errno = errsv;
+ else
+ errno = EIO;
+ return FALSE;
+ }
+ if (close (fd) != 0) {
+ /* errno is already properly set. */
+ return FALSE;
+ }
+
+ /* success. errno is undefined (no need to set). */
+ return TRUE;
}
static GSList *sysctl_clear_cache_list;
@@ -3724,6 +3758,16 @@ cache_lookup_link (NMPlatform *platform, int ifindex)
return obj_cache;
}
+const NMPlatformObject *const*
+nm_linux_platform_lookup (NMPlatform *platform, const NMPCacheId *cache_id, guint *out_len)
+{
+ g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), NULL);
+ g_return_val_if_fail (cache_id, NULL);
+
+ return nmp_cache_lookup_multi (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache,
+ cache_id, out_len);
+}
+
static GArray *
link_get_all (NMPlatform *platform)
{
@@ -4294,8 +4338,22 @@ link_set_user_ipv6ll_enabled (NMPlatform *platform, int ifindex, gboolean enable
0,
0);
if ( !nlmsg
- || !_nl_msg_new_link_set_afspec (nlmsg,
- mode))
+ || !_nl_msg_new_link_set_afspec (nlmsg, mode, NULL))
+ g_return_val_if_reached (FALSE);
+
+ return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS;
+}
+
+static gboolean
+link_set_token (NMPlatform *platform, int ifindex, NMUtilsIPv6IfaceId iid)
+{
+ nm_auto_nlmsg struct nl_msg *nlmsg = NULL;
+
+ _LOGD ("link: change %d: token: set IPv6 address generation token to %s",
+ ifindex, nm_utils_inet6_interface_identifier_to_token (iid, NULL));
+
+ nlmsg = _nl_msg_new_link (RTM_NEWLINK, 0, ifindex, NULL, 0, 0);
+ if (!nlmsg || !_nl_msg_new_link_set_afspec (nlmsg, -1, &iid))
g_return_val_if_reached (FALSE);
return do_change_link (platform, ifindex, nlmsg) == NM_PLATFORM_ERROR_SUCCESS;
@@ -5095,57 +5153,67 @@ link_release (NMPlatform *platform, int master, int slave)
/******************************************************************/
static gboolean
-_infiniband_partition_action (NMPlatform *platform, int parent, int p_key, const char *action, char **ifname)
+_infiniband_partition_action (NMPlatform *platform,
+ InfinibandAction action,
+ int parent,
+ int p_key,
+ const NMPlatformLink **out_link)
{
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
const NMPObject *obj_parent;
- gs_free char *path = NULL;
- gs_free char *id = NULL;
+ const NMPObject *obj;
+ char path[NM_STRLEN ("/sys/class/net/%s/%s") + IFNAMSIZ + 100];
+ char id[20];
+ char name[IFNAMSIZ];
+ gboolean success;
+
+ nm_assert (NM_IN_SET (action, INFINIBAND_ACTION_CREATE_CHILD, INFINIBAND_ACTION_DELETE_CHILD));
+ nm_assert (p_key > 0 && p_key <= 0xffff && p_key != 0x8000);
obj_parent = nmp_cache_lookup_link (priv->cache, parent);
- if (!obj_parent || !obj_parent->link.name[0])
- g_return_val_if_reached (FALSE);
+ if (!obj_parent || !obj_parent->link.name[0]) {
+ errno = ENOENT;
+ return FALSE;
+ }
- *ifname = g_strdup_printf ("%s.%04x", obj_parent->link.name, p_key);
+ nm_sprintf_buf (path,
+ "/sys/class/net/%s/%s",
+ NM_ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name),
+ (action == INFINIBAND_ACTION_CREATE_CHILD
+ ? "create_child"
+ : "delete_child"));
+ nm_sprintf_buf (id, "0x%04x", p_key);
+ success = nm_platform_sysctl_set (platform, path, id);
+ if (!success) {
+ if ( action == INFINIBAND_ACTION_DELETE_CHILD
+ && errno == ENODEV)
+ return TRUE;
+ return FALSE;
+ }
- path = g_strdup_printf ("/sys/class/net/%s/%s",
- NM_ASSERT_VALID_PATH_COMPONENT (obj_parent->link.name),
- action);
- id = g_strdup_printf ("0x%04x", p_key);
+ nm_utils_new_infiniband_name (name, obj_parent->link.name, p_key);
+ do_request_link (platform, 0, name);
- return nm_platform_sysctl_set (platform, path, id);
-}
+ if (action == INFINIBAND_ACTION_DELETE_CHILD)
+ return TRUE;
+ obj = nmp_cache_lookup_link_full (priv->cache, 0, name, FALSE,
+ NM_LINK_TYPE_INFINIBAND, NULL, NULL);
+ if (out_link)
+ *out_link = obj ? &obj->link : NULL;
+ return !!obj;
+}
static gboolean
infiniband_partition_add (NMPlatform *platform, int parent, int p_key, const NMPlatformLink **out_link)
{
- const NMPObject *obj;
- gs_free char *ifname = NULL;
-
- if (!_infiniband_partition_action (platform, parent, p_key, "create_child", &ifname))
- return FALSE;
-
- do_request_link (platform, 0, ifname);
-
- obj = nmp_cache_lookup_link_full (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache,
- 0, ifname, FALSE, NM_LINK_TYPE_INFINIBAND, NULL, NULL);
- if (out_link)
- *out_link = obj ? &obj->link : NULL;
- return !!obj;
+ return _infiniband_partition_action (platform, INFINIBAND_ACTION_CREATE_CHILD, parent, p_key, out_link);
}
static gboolean
infiniband_partition_delete (NMPlatform *platform, int parent, int p_key)
{
- gs_free char *ifname = NULL;
-
- if (!_infiniband_partition_action (platform, parent, p_key, "delete_child", &ifname)) {
- if (errno != ENODEV)
- return FALSE;
- }
-
- return TRUE;
+ return _infiniband_partition_action (platform, INFINIBAND_ACTION_DELETE_CHILD, parent, p_key, NULL);
}
/******************************************************************/
@@ -5570,7 +5638,7 @@ ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NM
nm_assert (NMP_OBJECT_GET_CLASS (NMP_OBJECT_UP_CAST (routes[i])) == klass);
if ( with_rtprot_kernel
- || routes[i]->source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
+ || routes[i]->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
g_array_append_vals (array, routes[i], 1);
}
return array;
@@ -6397,6 +6465,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
platform_class->link_get_udev_device = link_get_udev_device;
platform_class->link_set_user_ipv6ll_enabled = link_set_user_ipv6ll_enabled;
+ platform_class->link_set_token = link_set_token;
platform_class->link_set_address = link_set_address;
platform_class->link_get_permanent_address = link_get_permanent_address;
diff --git a/src/platform/nm-linux-platform.h b/src/platform/nm-linux-platform.h
index 4ae2fd1400..3b2a440e52 100644
--- a/src/platform/nm-linux-platform.h
+++ b/src/platform/nm-linux-platform.h
@@ -52,4 +52,10 @@ NMPlatform *nm_linux_platform_new (gboolean netns_support);
void nm_linux_platform_setup (void);
+struct _NMPCacheId;
+
+const NMPlatformObject *const *nm_linux_platform_lookup (NMPlatform *platform,
+ const struct _NMPCacheId *cache_id,
+ guint *out_len);
+
#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index b4542adf8d..068801ee69 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -144,8 +144,7 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
struct ethtool_perm_addr e;
guint8 _extra_data[NM_UTILS_HWADDR_LEN_MAX + 1];
} edata;
- static const guint8 zeros[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
- static guint8 ones[NM_UTILS_HWADDR_LEN_MAX] = { 0 };
+ guint i;
if (!ifname)
return FALSE;
@@ -157,18 +156,23 @@ nmp_utils_ethtool_get_permanent_address (const char *ifname,
if (!ethtool_get (ifname, &edata.e))
return FALSE;
- g_assert (edata.e.size <= NM_UTILS_HWADDR_LEN_MAX);
-
- /* Some drivers might return a permanent address of all zeros.
- * Reject that (rh#1264024) */
- if (memcmp (edata.e.data, zeros, edata.e.size) == 0)
+ if (edata.e.size > NM_UTILS_HWADDR_LEN_MAX)
+ return FALSE;
+ if (edata.e.size < 1)
return FALSE;
- /* Some drivers return a permanent address of all ones. Reject that too */
- if (G_UNLIKELY (ones[0] != 0xFF))
- memset (ones, 0xFF, sizeof (ones));
- if (memcmp (edata.e.data, ones, edata.e.size) == 0)
+ if (NM_IN_SET (edata.e.data[0], 0, 0xFF)) {
+ /* Some drivers might return a permanent address of all zeros.
+ * Reject that (rh#1264024)
+ *
+ * Some drivers return a permanent address of all ones. Reject that too */
+ for (i = 1; i < edata.e.size; i++) {
+ if (edata.e.data[0] != edata.e.data[i])
+ goto not_all_0or1;
+ }
return FALSE;
+ }
+not_all_0or1:
memcpy (buf, edata.e.data, edata.e.size);
*length = edata.e.size;
@@ -433,14 +437,35 @@ nmp_utils_device_exists (const char *name)
return g_file_test (sysdir, G_FILE_TEST_EXISTS);
}
-guint
-nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source)
+NMIPConfigSource
+nmp_utils_ip_config_source_from_rtprot (guint8 rtprot)
{
- switch (source) {
- case NM_IP_CONFIG_SOURCE_UNKNOWN:
+ return ((int) rtprot) + 1;
+}
+
+NMIPConfigSource
+nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source)
+{
+ /* when adding a route to kernel for a give @source, the resulting route
+ * will be put into the cache with a source of NM_IP_CONFIG_SOURCE_RTPROT_*.
+ * This function returns that. */
+ return nmp_utils_ip_config_source_from_rtprot (nmp_utils_ip_config_source_coerce_to_rtprot (source));
+}
+
+guint8
+nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source)
+{
+ /* when adding a route to kernel, we coerce the @source field
+ * to rtm_protocol. This is not lossless as we map different
+ * source values to the same RTPROT uint8 value. */
+ if (source <= NM_IP_CONFIG_SOURCE_UNKNOWN)
return RTPROT_UNSPEC;
+
+ if (source <= _NM_IP_CONFIG_SOURCE_RTPROT_LAST)
+ return source - 1;
+
+ switch (source) {
case NM_IP_CONFIG_SOURCE_KERNEL:
- case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
return RTPROT_KERNEL;
case NM_IP_CONFIG_SOURCE_DHCP:
return RTPROT_DHCP;
@@ -453,18 +478,32 @@ nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source)
}
NMIPConfigSource
-nmp_utils_ip_config_source_from_rtprot (guint rtprot)
+nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source)
{
- switch (rtprot) {
- case RTPROT_UNSPEC:
+ /* When we receive a route from kernel and put it into the platform cache,
+ * we preserve the protocol field by converting it to a NMIPConfigSource
+ * via nmp_utils_ip_config_source_from_rtprot().
+ *
+ * However, that is not the inverse of nmp_utils_ip_config_source_coerce_to_rtprot().
+ * Instead, to go back to the original value, you need another step:
+ * nmp_utils_ip_config_source_coerce_from_rtprot (nmp_utils_ip_config_source_from_rtprot (rtprot)).
+ *
+ * This might partly restore the original source value, but of course that
+ * is not really possible because nmp_utils_ip_config_source_coerce_to_rtprot()
+ * is not injective.
+ * */
+ switch (source) {
+ case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC:
return NM_IP_CONFIG_SOURCE_UNKNOWN;
- case RTPROT_KERNEL:
- return NM_IP_CONFIG_SOURCE_RTPROT_KERNEL;
- case RTPROT_REDIRECT:
+
+ case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
+ case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT:
return NM_IP_CONFIG_SOURCE_KERNEL;
- case RTPROT_RA:
+
+ case NM_IP_CONFIG_SOURCE_RTPROT_RA:
return NM_IP_CONFIG_SOURCE_RDISC;
- case RTPROT_DHCP:
+
+ case NM_IP_CONFIG_SOURCE_RTPROT_DHCP:
return NM_IP_CONFIG_SOURCE_DHCP;
default:
@@ -472,3 +511,50 @@ nmp_utils_ip_config_source_from_rtprot (guint rtprot)
}
}
+const char *
+nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len)
+{
+ const char *s = NULL;
+ nm_utils_to_string_buffer_init (&buf, &len); \
+
+ if (!len)
+ return buf;
+
+ switch (source) {
+ case NM_IP_CONFIG_SOURCE_UNKNOWN: s = "unknown"; break;
+
+ case NM_IP_CONFIG_SOURCE_RTPROT_UNSPEC: s = "rt-unspec"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_REDIRECT: s = "rt-redirect"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL: s = "rt-kernel"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_BOOT: s = "rt-boot"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_STATIC: s = "rt-static"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_DHCP: s = "rt-dhcp"; break;
+ case NM_IP_CONFIG_SOURCE_RTPROT_RA: s = "rt-ra"; break;
+
+ case NM_IP_CONFIG_SOURCE_KERNEL: s = "kernel"; break;
+ case NM_IP_CONFIG_SOURCE_SHARED: s = "shared"; break;
+ case NM_IP_CONFIG_SOURCE_IP4LL: s = "ipv4ll"; break;
+ case NM_IP_CONFIG_SOURCE_PPP: s = "ppp"; break;
+ case NM_IP_CONFIG_SOURCE_WWAN: s = "wwan"; break;
+ case NM_IP_CONFIG_SOURCE_VPN: s = "vpn"; break;
+ case NM_IP_CONFIG_SOURCE_DHCP: s = "dhcp"; break;
+ case NM_IP_CONFIG_SOURCE_RDISC: s = "rdisc"; break;
+ case NM_IP_CONFIG_SOURCE_USER: s = "user"; break;
+ default:
+ break;
+ }
+
+ if (source >= 1 && source <= 0x100) {
+ if (s)
+ g_snprintf (buf, len, "%s", s);
+ else
+ g_snprintf (buf, len, "rt-%d", ((int) source) - 1);
+ } else {
+ if (s)
+ g_strlcpy (buf, s, len);
+ else
+ g_snprintf (buf, len, "(%d)", source);
+ }
+ return buf;
+}
+
diff --git a/src/platform/nm-platform-utils.h b/src/platform/nm-platform-utils.h
index f259474719..456c08652d 100644
--- a/src/platform/nm-platform-utils.h
+++ b/src/platform/nm-platform-utils.h
@@ -54,7 +54,10 @@ const char *nmp_utils_udev_get_driver (GUdevDevice *device);
gboolean nmp_utils_device_exists (const char *name);
-guint nmp_utils_ip_config_source_to_rtprot (NMIPConfigSource source);
-NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint rtprot);
+NMIPConfigSource nmp_utils_ip_config_source_from_rtprot (guint8 rtprot) _nm_const;
+guint8 nmp_utils_ip_config_source_coerce_to_rtprot (NMIPConfigSource source) _nm_const;
+NMIPConfigSource nmp_utils_ip_config_source_coerce_from_rtprot (NMIPConfigSource source) _nm_const;
+NMIPConfigSource nmp_utils_ip_config_source_round_trip_rtprot (NMIPConfigSource source) _nm_const;
+const char * nmp_utils_ip_config_source_to_string (NMIPConfigSource source, char *buf, gsize len);
#endif /* __NM_PLATFORM_UTILS_H__ */
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 26ac766d63..a6afcf33a9 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -387,6 +387,20 @@ nm_platform_sysctl_get_int_checked (NMPlatform *self, const char *path, guint ba
/******************************************************************/
+static int
+_link_get_all_presort (gconstpointer p_a,
+ gconstpointer p_b)
+{
+ const NMPlatformLink *a = p_a;
+ const NMPlatformLink *b = p_b;
+
+ if (a->ifindex < b->ifindex)
+ return -1;
+ if (a->ifindex > b->ifindex)
+ return 1;
+ return 0;
+}
+
/**
* nm_platform_link_get_all:
* self: platform instance
@@ -409,15 +423,17 @@ nm_platform_link_get_all (NMPlatform *self)
if (!links || links->len == 0)
return links;
+ /* first sort the links by their ifindex. Below we will sort further by moving
+ * children/slaves to the end. */
+ g_array_sort (links, _link_get_all_presort);
+
unseen = g_hash_table_new (g_direct_hash, g_direct_equal);
for (i = 0; i < links->len; i++) {
item = &g_array_index (links, NMPlatformLink, i);
- _LOGt ("link-get: %3d: %s", i, nm_platform_link_to_string (item, NULL, 0));
-
- nm_assert (item->ifindex > 0 && !g_hash_table_contains (unseen, GINT_TO_POINTER (item->ifindex)));
-
- g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL);
+ nm_assert (item->ifindex > 0);
+ if (!nm_g_hash_table_insert (unseen, GINT_TO_POINTER (item->ifindex), NULL))
+ nm_assert_not_reached ();
}
#ifndef G_DISABLE_ASSERT
@@ -468,8 +484,6 @@ nm_platform_link_get_all (NMPlatform *self)
if (item->parent > 0 && g_hash_table_contains (unseen, GINT_TO_POINTER (item->parent)))
continue;
- _LOGt ("link-get: add %3d -> %3d: %s", i, j, nm_platform_link_to_string (item, NULL, 0));
-
g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
g_array_index (result, NMPlatformLink, j++) = *item;
item->ifindex = 0;
@@ -481,8 +495,6 @@ nm_platform_link_get_all (NMPlatform *self)
* This can happen for veth pairs where each peer is parent of the other end. */
item = &g_array_index (links, NMPlatformLink, first_idx);
- _LOGt ("link-get: add (loop) %3d -> %3d: %s", first_idx, j, nm_platform_link_to_string (item, NULL, 0));
-
g_hash_table_remove (unseen, GINT_TO_POINTER (item->ifindex));
g_array_index (result, NMPlatformLink, j++) = *item;
item->ifindex = 0;
@@ -888,33 +900,25 @@ nm_platform_link_uses_arp (NMPlatform *self, int ifindex)
}
/**
- * nm_platform_link_get_ipv6_token:
+ * nm_platform_link_set_ipv6_token:
* @self: platform instance
* @ifindex: Interface index
* @iid: Tokenized interface identifier
*
- * Returns IPv6 tokenized interface identifier. If the platform or OS doesn't
- * support IPv6 tokenized interface identifiers, or the token is not set
- * this call will fail and return %FALSE.
+ * Sets then IPv6 tokenized interface identifier.
*
* Returns: %TRUE a tokenized identifier was available
*/
gboolean
-nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid)
+nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid)
{
- const NMPlatformLink *pllink;
-
_CHECK_SELF (self, klass, FALSE);
g_return_val_if_fail (ifindex >= 0, FALSE);
- g_return_val_if_fail (iid, FALSE);
-
+ g_return_val_if_fail (iid.id, FALSE);
- pllink = nm_platform_link_get (self, ifindex);
- if (pllink && pllink->inet6_token.is_valid) {
- *iid = pllink->inet6_token.iid;
- return TRUE;
- }
+ if (klass->link_set_token)
+ return klass->link_set_token (self, ifindex, iid);
return FALSE;
}
@@ -1895,21 +1899,27 @@ _infiniband_add_add_or_delete (NMPlatform *self,
gboolean add,
const NMPlatformLink **out_link)
{
- gs_free char *parent_name = NULL;
- gs_free char *name = NULL;
+ char name[IFNAMSIZ];
+ const NMPlatformLink *parent_link;
NMPlatformError plerr;
_CHECK_SELF (self, klass, NM_PLATFORM_ERROR_BUG);
g_return_val_if_fail (parent >= 0, NM_PLATFORM_ERROR_BUG);
- g_return_val_if_fail (p_key >= 0, NM_PLATFORM_ERROR_BUG);
+ g_return_val_if_fail (p_key >= 0 && p_key <= 0xffff, NM_PLATFORM_ERROR_BUG);
+
+ /* the special keys 0x0000 and 0x8000 are not allowed. */
+ if (NM_IN_SET (p_key, 0, 0x8000))
+ return NM_PLATFORM_ERROR_UNSPECIFIED;
+
+ parent_link = nm_platform_link_get (self, parent);
+ if (!parent_link)
+ return NM_PLATFORM_ERROR_NOT_FOUND;
- parent_name = g_strdup (nm_platform_link_get_name (self, parent));
- if ( !parent_name
- || nm_platform_link_get_type (self, parent) != NM_LINK_TYPE_INFINIBAND)
+ if (parent_link->type != NM_LINK_TYPE_INFINIBAND)
return NM_PLATFORM_ERROR_WRONG_TYPE;
- name = g_strdup_printf ("%s.%04x", parent_name, p_key);
+ nm_utils_new_infiniband_name (name, parent_link->name, p_key);
if (add) {
plerr = _link_add_check_existing (self, name, NM_LINK_TYPE_INFINIBAND, out_link);
@@ -1917,7 +1927,7 @@ _infiniband_add_add_or_delete (NMPlatform *self,
return plerr;
_LOGD ("link: adding infiniband partition %s for parent '%s' (%d), key %d",
- name, parent_name, parent, p_key);
+ name, parent_link->name, parent, p_key);
if (!klass->infiniband_partition_add (self, parent, p_key, out_link))
return NM_PLATFORM_ERROR_UNSPECIFIED;
} else {
@@ -2894,7 +2904,7 @@ nm_platform_ip4_route_add (NMPlatform *self,
NMPlatformIP4Route route = { 0 };
route.ifindex = ifindex;
- route.source = source;
+ route.rt_source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;
@@ -2921,7 +2931,7 @@ nm_platform_ip6_route_add (NMPlatform *self,
NMPlatformIP6Route route = { 0 };
route.ifindex = ifindex;
- route.source = source;
+ route.rt_source = source;
route.network = network;
route.plen = plen;
route.gateway = gateway;
@@ -3012,38 +3022,6 @@ nm_platform_vlan_qos_mapping_to_string (const char *name,
}
static const char *
-source_to_string (NMIPConfigSource source)
-{
- switch (source) {
- case NM_IP_CONFIG_SOURCE_RTPROT_KERNEL:
- return "rtprot-kernel";
- case _NM_IP_CONFIG_SOURCE_RTM_F_CLONED:
- return "rtm-f-cloned";
- case NM_IP_CONFIG_SOURCE_KERNEL:
- return "kernel";
- case NM_IP_CONFIG_SOURCE_SHARED:
- return "shared";
- case NM_IP_CONFIG_SOURCE_IP4LL:
- return "ipv4ll";
- case NM_IP_CONFIG_SOURCE_PPP:
- return "ppp";
- case NM_IP_CONFIG_SOURCE_WWAN:
- return "wwan";
- case NM_IP_CONFIG_SOURCE_VPN:
- return "vpn";
- case NM_IP_CONFIG_SOURCE_DHCP:
- return "dhcp";
- case NM_IP_CONFIG_SOURCE_RDISC:
- return "rdisc";
- case NM_IP_CONFIG_SOURCE_USER:
- return "user";
- default:
- break;
- }
- return "unknown";
-}
-
-static const char *
_lifetime_to_string (guint32 timestamp, guint32 lifetime, gint32 now, char *buf, size_t buf_size)
{
if (lifetime == NM_PLATFORM_LIFETIME_PERMANENT)
@@ -3081,7 +3059,7 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
GString *str_flags;
char str_addrmode[30];
gs_free char *str_addr = NULL;
- gs_free char *str_inet6_token = NULL;
+ char str_inet6_token[NM_UTILS_INET_ADDRSTRLEN];
const char *str_link_type;
if (!nm_utils_to_string_buffer_init_null (link, &buf, &len))
@@ -3118,8 +3096,6 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
if (link->addr.len)
str_addr = nm_utils_hwaddr_ntoa (link->addr.data, MIN (link->addr.len, sizeof (link->addr.data)));
- if (link->inet6_token.is_valid)
- str_inet6_token = nm_utils_hwaddr_ntoa (&link->inet6_token.iid, sizeof (link->inet6_token.iid));
str_link_type = nm_link_type_to_string (link->type);
@@ -3153,8 +3129,8 @@ nm_platform_link_to_string (const NMPlatformLink *link, char *buf, gsize len)
link->inet6_addr_gen_mode_inv ? nm_platform_link_inet6_addrgenmode2str (_nm_platform_uint8_inv (link->inet6_addr_gen_mode_inv), str_addrmode, sizeof (str_addrmode)) : "",
str_addr ? " addr " : "",
str_addr ? str_addr : "",
- str_inet6_token ? " inet6token " : "",
- str_inet6_token ? str_inet6_token : "",
+ link->inet6_token.id ? " inet6token " : "",
+ link->inet6_token.id ? nm_utils_inet6_interface_identifier_to_token (link->inet6_token, str_inet6_token) : "",
link->driver ? " driver " : "",
link->driver ? link->driver : "");
g_string_free (str_flags, TRUE);
@@ -3471,7 +3447,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu
char s_peer[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char str_label[32];
- char str_lft[30], str_pref[30], str_time[50];
+ char str_lft[30], str_pref[30], str_time[50], s_source[50];
char *str_peer = NULL;
const char *str_lft_p, *str_pref_p, *str_time_p;
gint32 now = nm_utils_get_monotonic_timestamp_s ();
@@ -3510,7 +3486,7 @@ nm_platform_ip4_address_to_string (const NMPlatformIP4Address *address, char *bu
str_dev,
_to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)),
str_label,
- source_to_string (address->source));
+ nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)));
g_free (str_peer);
return buf;
}
@@ -3582,7 +3558,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu
char s_flags[TO_STRING_IFA_FLAGS_BUF_SIZE];
char s_address[INET6_ADDRSTRLEN];
char s_peer[INET6_ADDRSTRLEN];
- char str_lft[30], str_pref[30], str_time[50];
+ char str_lft[30], str_pref[30], str_time[50], s_source[50];
char str_dev[TO_STRING_DEV_BUF_SIZE];
char *str_peer = NULL;
const char *str_lft_p, *str_pref_p, *str_time_p;
@@ -3616,7 +3592,7 @@ nm_platform_ip6_address_to_string (const NMPlatformIP6Address *address, char *bu
str_peer ? str_peer : "",
str_dev,
_to_string_ifa_flags (address->n_ifa_flags, s_flags, sizeof (s_flags)),
- source_to_string (address->source));
+ nmp_utils_ip_config_source_to_string (address->addr_source, s_source, sizeof (s_source)));
g_free (str_peer);
return buf;
}
@@ -3639,7 +3615,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
char s_network[INET_ADDRSTRLEN], s_gateway[INET_ADDRSTRLEN];
char s_pref_src[INET_ADDRSTRLEN];
char str_dev[TO_STRING_DEV_BUF_SIZE];
- char str_scope[30];
+ char str_scope[30], s_source[50];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -3656,6 +3632,7 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
" metric %"G_GUINT32_FORMAT
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
+ "%s" /* cloned */
"%s%s" /* scope */
"%s%s" /* pref-src */
"",
@@ -3665,7 +3642,8 @@ nm_platform_ip4_route_to_string (const NMPlatformIP4Route *route, char *buf, gsi
str_dev,
route->metric,
route->mss,
- source_to_string (route->source),
+ 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))) : "",
route->pref_src ? " pref-src " : "",
@@ -3689,7 +3667,7 @@ const char *
nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsize len)
{
char s_network[INET6_ADDRSTRLEN], s_gateway[INET6_ADDRSTRLEN];
- char str_dev[TO_STRING_DEV_BUF_SIZE];
+ char str_dev[TO_STRING_DEV_BUF_SIZE], s_source[50];
if (!nm_utils_to_string_buffer_init_null (route, &buf, &len))
return buf;
@@ -3706,6 +3684,7 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
" metric %"G_GUINT32_FORMAT
" mss %"G_GUINT32_FORMAT
" src %s" /* source */
+ "%s" /* cloned */
"",
s_network,
route->plen,
@@ -3713,7 +3692,8 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
str_dev,
route->metric,
route->mss,
- source_to_string (route->source));
+ nmp_utils_ip_config_source_to_string (route->rt_source, s_source, sizeof (s_source)),
+ route->rt_cloned ? " cloned" : "");
return buf;
}
@@ -3808,13 +3788,11 @@ nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
_CMP_FIELD (a, b, arptype);
_CMP_FIELD (a, b, addr.len);
_CMP_FIELD (a, b, inet6_addr_gen_mode_inv);
- _CMP_FIELD (a, b, inet6_token.is_valid);
_CMP_FIELD_STR_INTERNED (a, b, kind);
_CMP_FIELD_STR_INTERNED (a, b, driver);
if (a->addr.len)
_CMP_FIELD_MEMCMP_LEN (a, b, addr.data, a->addr.len);
- if (a->inet6_token.is_valid)
- _CMP_FIELD_MEMCMP (a, b, inet6_token.iid);
+ _CMP_FIELD_MEMCMP (a, b, inet6_token);
return 0;
}
@@ -3935,10 +3913,10 @@ nm_platform_ip4_address_cmp (const NMPlatformIP4Address *a, const NMPlatformIP4A
{
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD (a, b, source);
_CMP_FIELD (a, b, address);
_CMP_FIELD (a, b, plen);
_CMP_FIELD (a, b, peer_address);
+ _CMP_FIELD (a, b, addr_source);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
_CMP_FIELD (a, b, preferred);
@@ -3954,14 +3932,12 @@ nm_platform_ip6_address_cmp (const NMPlatformIP6Address *a, const NMPlatformIP6A
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD (a, b, source);
_CMP_FIELD_MEMCMP (a, b, address);
-
+ _CMP_FIELD (a, b, plen);
p_a = nm_platform_ip6_address_get_peer (a);
p_b = nm_platform_ip6_address_get_peer (b);
_CMP_DIRECT_MEMCMP (p_a, p_b, sizeof (*p_a));
-
- _CMP_FIELD (a, b, plen);
+ _CMP_FIELD (a, b, addr_source);
_CMP_FIELD (a, b, timestamp);
_CMP_FIELD (a, b, lifetime);
_CMP_FIELD (a, b, preferred);
@@ -3974,14 +3950,15 @@ nm_platform_ip4_route_cmp (const NMPlatformIP4Route *a, const NMPlatformIP4Route
{
_CMP_SELF (a, b);
_CMP_FIELD (a, b, ifindex);
- _CMP_FIELD (a, b, source);
_CMP_FIELD (a, b, network);
_CMP_FIELD (a, b, plen);
- _CMP_FIELD (a, b, gateway);
_CMP_FIELD (a, b, metric);
+ _CMP_FIELD (a, b, gateway);
+ _CMP_FIELD (a, b, rt_source);
_CMP_FIELD (a, b, mss);
_CMP_FIELD (a, b, scope_inv);
_CMP_FIELD (a, b, pref_src);
+ _CMP_FIELD (a, b, rt_cloned);
return 0;
}
@@ -3990,12 +3967,13 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
{
_CMP_SELF (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);
_CMP_FIELD (a, b, metric);
+ _CMP_FIELD_MEMCMP (a, b, gateway);
+ _CMP_FIELD (a, b, rt_source);
_CMP_FIELD (a, b, mss);
+ _CMP_FIELD (a, b, rt_cloned);
return 0;
}
@@ -4128,7 +4106,7 @@ _vtr_v4_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout
{
return nm_platform_ip4_route_add (self,
ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.source,
+ route->rx.rt_source,
route->r4.network,
route->rx.plen,
route->r4.gateway,
@@ -4142,7 +4120,7 @@ _vtr_v6_route_add (NMPlatform *self, int ifindex, const NMPlatformIPXRoute *rout
{
return nm_platform_ip6_route_add (self,
ifindex > 0 ? ifindex : route->rx.ifindex,
- route->rx.source,
+ route->rx.rt_source,
route->r6.network,
route->rx.plen,
route->r6.gateway,
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 19724f1c19..72f4f6720a 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -49,8 +49,6 @@
/******************************************************************/
-typedef struct _NMPlatform NMPlatform;
-
/* workaround for older libnl version, that does not define these flags. */
#ifndef IFA_F_MANAGETEMPADDR
#define IFA_F_MANAGETEMPADDR 0x100
@@ -98,6 +96,11 @@ typedef struct {
guint8 addr_ptr[1];
in_addr_t addr4;
struct in6_addr addr6;
+
+ /* NMIPAddr is really a union for IP addresses.
+ * However, as ethernet addresses fit in here nicely, ruse
+ * it also for an ethernet MAC address. */
+ guint8 addr_eth[6 /*ETH_ALEN*/];
};
} NMIPAddr;
@@ -144,11 +147,8 @@ struct _NMPlatformLink {
guint8 len;
} addr;
- /* rtnl_link_inet6_get_token() */
- struct {
- NMUtilsIPv6IfaceId iid;
- guint8 is_valid;
- } inet6_token;
+ /* rtnl_link_inet6_get_token(), IFLA_INET6_TOKEN */
+ NMUtilsIPv6IfaceId inet6_token;
/* The bitwise inverse of rtnl_link_inet6_get_addr_gen_mode(). It is inverse
* to have a default of 0 -- meaning: unspecified. That way, a struct
@@ -200,7 +200,7 @@ typedef struct {
#define __NMPlatformIPAddress_COMMON \
__NMPlatformObject_COMMON; \
- NMIPConfigSource source; \
+ NMIPConfigSource addr_source; \
\
/* Timestamp in seconds in the reference system of nm_utils_get_monotonic_timestamp_*().
*
@@ -303,8 +303,21 @@ typedef union {
#define __NMPlatformIPRoute_COMMON \
__NMPlatformObject_COMMON; \
- NMIPConfigSource source; \
+ \
+ /* The NMIPConfigSource. For routes that we receive from cache this corresponds
+ * to the rtm_protocol field (and is one of the NM_IP_CONFIG_SOURCE_RTPROT_* values).
+ * When adding a route, the source will be coerced to the protocol using
+ * nmp_utils_ip_config_source_coerce_to_rtprot(). */ \
+ NMIPConfigSource rt_source; \
+ \
guint8 plen; \
+ \
+ /* the route has rtm_flags set to RTM_F_CLONED. Such a route
+ * is hidden by platform and does not exist from the point-of-view
+ * of platform users. This flag is internal to track those hidden
+ * routes. Such a route is not alive, according to nmp_object_is_alive(). */ \
+ bool rt_cloned:1; \
+ \
guint32 metric; \
guint32 mss; \
;
@@ -507,6 +520,7 @@ typedef struct {
GObject *(*link_get_udev_device) (NMPlatform *self, int ifindex);
gboolean (*link_set_user_ipv6ll_enabled) (NMPlatform *, int ifindex, gboolean enabled);
+ gboolean (*link_set_token) (NMPlatform *, int ifindex, NMUtilsIPv6IfaceId iid);
gboolean (*link_get_permanent_address) (NMPlatform *,
int ifindex,
@@ -717,7 +731,6 @@ gboolean nm_platform_link_is_up (NMPlatform *self, int ifindex);
gboolean nm_platform_link_is_connected (NMPlatform *self, int ifindex);
gboolean nm_platform_link_uses_arp (NMPlatform *self, int ifindex);
guint32 nm_platform_link_get_mtu (NMPlatform *self, int ifindex);
-gboolean nm_platform_link_get_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId *iid);
gboolean nm_platform_link_get_user_ipv6ll_enabled (NMPlatform *self, int ifindex);
gconstpointer nm_platform_link_get_address (NMPlatform *self, int ifindex, size_t *length);
int nm_platform_link_get_master (NMPlatform *self, int slave);
@@ -741,6 +754,7 @@ const char *nm_platform_link_get_udi (NMPlatform *self, int ifindex);
GObject *nm_platform_link_get_udev_device (NMPlatform *self, int ifindex);
gboolean nm_platform_link_set_user_ipv6ll_enabled (NMPlatform *self, int ifindex, gboolean enabled);
+gboolean nm_platform_link_set_ipv6_token (NMPlatform *self, int ifindex, NMUtilsIPv6IfaceId iid);
gboolean nm_platform_link_get_permanent_address (NMPlatform *self, int ifindex, guint8 *buf, size_t *length);
gboolean nm_platform_link_set_address (NMPlatform *self, int ifindex, const void *address, size_t length);
diff --git a/src/platform/nmp-object.c b/src/platform/nmp-object.c
index eb7e1ca401..55ffd7cffb 100644
--- a/src/platform/nmp-object.c
+++ b/src/platform/nmp-object.c
@@ -915,12 +915,12 @@ _vt_cmd_obj_is_alive_ipx_route (const NMPObject *obj)
*
* If nmp_object_from_nl() would just return NULL, we couldn't look
* into the cache to see if it contains a route that now disappears
- * (because it is cloned).
+ * (because it changed to be cloned).
*
* Instead we create a dead object, and nmp_cache_update_netlink()
* will remove the old version of the update.
**/
- return obj->object.ifindex > 0 && (obj->ip_route.source != _NM_IP_CONFIG_SOURCE_RTM_F_CLONED);
+ return obj->object.ifindex > 0 && !obj->ip_route.rt_cloned;
}
gboolean
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index c5241037d5..d295f7a078 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -94,9 +94,9 @@ typedef enum { /*< skip >*/
NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
} NMPCacheIdType;
-typedef struct _NMPObject NMPObject;
+typedef struct _NMPCacheId NMPCacheId;
-typedef struct {
+struct _NMPCacheId {
union {
NMMultiIndexId base;
guint8 _id_type; /* NMPCacheIdType as guint8 */
@@ -136,7 +136,7 @@ typedef struct {
struct in6_addr _misaligned_network;
} routes_by_destination_ip6;
};
-} NMPCacheId;
+};
extern NMPCacheId _nmp_cache_id_static;
#define NMP_CACHE_ID_STATIC (&_nmp_cache_id_static)
diff --git a/src/platform/tests/monitor.c b/src/platform/tests/monitor.c
index 3af34be42c..937eea1154 100644
--- a/src/platform/tests/monitor.c
+++ b/src/platform/tests/monitor.c
@@ -25,7 +25,7 @@
#include "nm-linux-platform.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
NMTST_DEFINE ();
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index 0e3cf10ba4..143b9b5272 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -8,7 +8,7 @@
#include "nm-fake-platform.h"
#include "nm-linux-platform.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
#define DEVICE_NAME "nm-test-device"
diff --git a/src/platform/tests/test-general.c b/src/platform/tests/test-general.c
index d8d925614b..f67f00892f 100644
--- a/src/platform/tests/test-general.c
+++ b/src/platform/tests/test-general.c
@@ -25,7 +25,7 @@
#include "nm-platform-utils.h"
#include "nm-linux-platform.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
/******************************************************************/
diff --git a/src/platform/tests/test-link.c b/src/platform/tests/test-link.c
index 9d548aabdb..db8ad5a2e1 100644
--- a/src/platform/tests/test-link.c
+++ b/src/platform/tests/test-link.c
@@ -30,7 +30,7 @@
#include "nm-platform-utils.h"
#include "test-common.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
#define LO_INDEX 1
#define LO_NAME "lo"
@@ -1861,7 +1861,7 @@ _test_netns_setup (gpointer fixture, gconstpointer test_data)
{
/* the singleton platform instance has netns support disabled.
* Destroy the instance before the test and re-create it afterwards. */
- g_object_unref (nm_platform_get ());
+ g_object_unref (NM_PLATFORM_GET);
}
static void
diff --git a/src/platform/tests/test-nmp-object.c b/src/platform/tests/test-nmp-object.c
index d77170b364..9d4f69de4c 100644
--- a/src/platform/tests/test-nmp-object.c
+++ b/src/platform/tests/test-nmp-object.c
@@ -22,7 +22,7 @@
#include "nmp-object.h"
-#include "nm-test-utils.h"
+#include "nm-test-utils-core.h"
struct {
GList *udev_devices;
diff --git a/src/platform/tests/test-route.c b/src/platform/tests/test-route.c
index a50392a66f..360404e944 100644
--- a/src/platform/tests/test-route.c
+++ b/src/platform/tests/test-route.c
@@ -23,9 +23,9 @@
#include <linux/rtnetlink.h>
#include "nm-core-utils.h"
-#include "test-common.h"
+#include "nm-platform-utils.h"
-#include "nm-test-utils.h"
+#include "test-common.h"
#define DEVICE_NAME "nm-test-device"
@@ -178,7 +178,7 @@ test_ip4_route (void)
/* Test route listing */
routes = nm_platform_ip4_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
- rts[0].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[0].network = gateway;
rts[0].plen = 32;
rts[0].ifindex = ifindex;
@@ -186,7 +186,7 @@ test_ip4_route (void)
rts[0].metric = metric;
rts[0].mss = mss;
rts[0].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_LINK);
- rts[1].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[1].network = network;
rts[1].plen = plen;
rts[1].ifindex = ifindex;
@@ -194,7 +194,7 @@ test_ip4_route (void)
rts[1].metric = metric;
rts[1].mss = mss;
rts[1].scope_inv = nm_platform_route_scope_inv (RT_SCOPE_UNIVERSE);
- rts[2].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[2].network = 0;
rts[2].plen = 0;
rts[2].ifindex = ifindex;
@@ -265,21 +265,21 @@ test_ip6_route (void)
/* Test route listing */
routes = nm_platform_ip6_route_get_all (NM_PLATFORM_GET, ifindex, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT | NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT);
memset (rts, 0, sizeof (rts));
- rts[0].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[0].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[0].network = gateway;
rts[0].plen = 128;
rts[0].ifindex = ifindex;
rts[0].gateway = in6addr_any;
rts[0].metric = nm_utils_ip6_route_metric_normalize (metric);
rts[0].mss = mss;
- rts[1].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[1].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[1].network = network;
rts[1].plen = plen;
rts[1].ifindex = ifindex;
rts[1].gateway = gateway;
rts[1].metric = nm_utils_ip6_route_metric_normalize (metric);
rts[1].mss = mss;
- rts[2].source = NM_IP_CONFIG_SOURCE_USER;
+ rts[2].rt_source = nmp_utils_ip_config_source_round_trip_rtprot (NM_IP_CONFIG_SOURCE_USER);
rts[2].network = in6addr_any;
rts[2].plen = 0;
rts[2].ifindex = ifindex;
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index 38e5a0545e..9b981f3b38 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -21,16 +21,18 @@
#include "nm-default.h"
+#include "wifi-utils.h"
+
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
-#include "wifi-utils.h"
#include "wifi-utils-private.h"
#include "wifi-utils-nl80211.h"
#if HAVE_WEXT
#include "wifi-utils-wext.h"
#endif
+#include "nm-core-utils.h"
gpointer
wifi_data_new (const char *iface, int ifindex, gsize len)
@@ -162,19 +164,20 @@ wifi_utils_deinit (WifiData *data)
}
gboolean
-wifi_utils_is_wifi (const char *iface, const char *sysfs_path)
+wifi_utils_is_wifi (const char *iface)
{
- char phy80211_path[255];
+ char phy80211_path[NM_STRLEN ("/sys/class/net/123456789012345/phy80211\0") + 100 /*safety*/];
struct stat s;
g_return_val_if_fail (iface != NULL, FALSE);
- if (sysfs_path) {
- /* Check for nl80211 sysfs paths */
- g_snprintf (phy80211_path, sizeof (phy80211_path), "%s/phy80211", sysfs_path);
- if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR)))
- return TRUE;
- }
+ nm_sprintf_buf (phy80211_path,
+ "/sys/class/net/%s/phy80211",
+ NM_ASSERT_VALID_PATH_COMPONENT (iface));
+ nm_assert (strlen (phy80211_path) < sizeof (phy80211_path) - 1);
+
+ if ((stat (phy80211_path, &s) == 0 && (s.st_mode & S_IFDIR)))
+ return TRUE;
#if HAVE_WEXT
if (wifi_wext_is_wifi (iface))
diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h
index 21dac9e9cc..f0a5a7e7f1 100644
--- a/src/platform/wifi/wifi-utils.h
+++ b/src/platform/wifi/wifi-utils.h
@@ -29,7 +29,7 @@
typedef struct WifiData WifiData;
-gboolean wifi_utils_is_wifi (const char *iface, const char *sysfs_path);
+gboolean wifi_utils_is_wifi (const char *iface);
WifiData *wifi_utils_init (const char *iface, int ifindex, gboolean check_scan);