diff options
Diffstat (limited to 'src/platform')
-rw-r--r-- | src/platform/nm-fake-platform.c | 21 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.c | 269 | ||||
-rw-r--r-- | src/platform/nm-linux-platform.h | 6 | ||||
-rw-r--r-- | src/platform/nm-platform-utils.c | 134 | ||||
-rw-r--r-- | src/platform/nm-platform-utils.h | 7 | ||||
-rw-r--r-- | src/platform/nm-platform.c | 162 | ||||
-rw-r--r-- | src/platform/nm-platform.h | 34 | ||||
-rw-r--r-- | src/platform/nmp-object.c | 4 | ||||
-rw-r--r-- | src/platform/nmp-object.h | 6 | ||||
-rw-r--r-- | src/platform/tests/monitor.c | 2 | ||||
-rw-r--r-- | src/platform/tests/test-common.h | 2 | ||||
-rw-r--r-- | src/platform/tests/test-general.c | 2 | ||||
-rw-r--r-- | src/platform/tests/test-link.c | 4 | ||||
-rw-r--r-- | src/platform/tests/test-nmp-object.c | 2 | ||||
-rw-r--r-- | src/platform/tests/test-route.c | 16 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils.c | 21 | ||||
-rw-r--r-- | src/platform/wifi/wifi-utils.h | 2 |
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); |