diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/wifi/nm-device-iwd.c | 44 | ||||
| -rw-r--r-- | src/devices/wifi/nm-iwd-manager.c | 52 | ||||
| -rw-r--r-- | src/devices/wifi/nm-wifi-p2p-peer.c | 15 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.c | 34 | ||||
| -rw-r--r-- | src/dns/nm-dns-manager.h | 2 | ||||
| -rw-r--r-- | src/initrd/nmi-cmdline-reader.c | 28 | ||||
| -rw-r--r-- | src/initrd/tests/test-cmdline-reader.c | 56 | ||||
| -rw-r--r-- | src/nm-ip4-config.c | 32 | ||||
| -rw-r--r-- | src/nm-ip4-config.h | 18 | ||||
| -rw-r--r-- | src/nm-ip6-config.c | 21 | ||||
| -rw-r--r-- | src/nm-ip6-config.h | 3 | ||||
| -rw-r--r-- | src/platform/nm-linux-platform.c | 25 | ||||
| -rw-r--r-- | src/platform/tests/test-platform-general.c | 37 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-interface.c | 11 | ||||
| -rw-r--r-- | src/supplicant/nm-supplicant-types.h | 2 |
15 files changed, 314 insertions, 66 deletions
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c index fb113f83..64ac3de7 100644 --- a/src/devices/wifi/nm-device-iwd.c +++ b/src/devices/wifi/nm-device-iwd.c @@ -1952,36 +1952,39 @@ schedule_periodic_scan(NMDeviceIwd *self, gboolean initial_scan) { NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE(self); GVariant * value; - gboolean disconnected; + gboolean disconnected = TRUE; guint interval; - if (!priv->can_scan || priv->scan_requested) - return; - - value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); - disconnected = nm_streq0(get_variant_state(value), "disconnected"); - g_variant_unref(value); + if (priv->can_scan) { + value = g_dbus_proxy_get_cached_property(priv->dbus_station_proxy, "State"); + disconnected = nm_streq0(get_variant_state(value), "disconnected"); + g_variant_unref(value); + } /* Start scan immediately after a disconnect, mode change or - * device UP, otherwise wait a period dependent on the current - * state. + * device UP, otherwise wait 10 seconds. When connected, update + * AP list mainly on UI requests. * * (initial_scan && disconnected) override priv->scanning below * because of an IWD quirk where a device will often be in the * autoconnect state and scanning at the time of our initial_scan, - * but our logic will the send it a Disconnect() causing IWD to + * but our logic will then send it a Disconnect() causing IWD to * exit autoconnect and interrupt the ongoing scan, meaning that * we still want a new scan ASAP. */ - if (initial_scan && disconnected) + if (!priv->can_scan || !disconnected || priv->scan_requested || priv->scanning) + interval = -1; + else if (initial_scan) interval = 0; - else if (!priv->periodic_scan_id && !priv->scanning) - interval = disconnected ? 10 : 20; + else if (!priv->periodic_scan_id) + interval = 10; else return; nm_clear_g_source(&priv->periodic_scan_id); - priv->periodic_scan_id = g_timeout_add_seconds(interval, periodic_scan_timeout_cb, self); + + if (interval != (guint) -1) + priv->periodic_scan_id = g_timeout_add_seconds(interval, periodic_scan_timeout_cb, self); } static void @@ -2384,7 +2387,6 @@ powered_changed(NMDeviceIwd *self, gboolean new_powered) update_aps(self); } else { set_can_scan(self, FALSE); - nm_clear_g_source(&priv->periodic_scan_id); priv->scanning = FALSE; priv->scan_requested = FALSE; priv->can_connect = FALSE; @@ -2600,17 +2602,7 @@ dispose(GObject *object) nm_clear_g_cancellable(&priv->cancellable); - nm_clear_g_source(&priv->periodic_scan_id); - - cleanup_association_attempt(self, TRUE); - - g_clear_object(&priv->dbus_device_proxy); - g_clear_object(&priv->dbus_station_proxy); - g_clear_object(&priv->dbus_ap_proxy); - g_clear_object(&priv->dbus_adhoc_proxy); - g_clear_object(&priv->dbus_obj); - - remove_all_aps(self); + nm_device_iwd_set_dbus_object(self, NULL); G_OBJECT_CLASS(nm_device_iwd_parent_class)->dispose(object); diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c index bdff20ac..6a562014 100644 --- a/src/devices/wifi/nm-iwd-manager.c +++ b/src/devices/wifi/nm-iwd-manager.c @@ -632,6 +632,38 @@ interface_removed(GDBusObjectManager *object_manager, } static void +object_added(GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) +{ + GList *interfaces, *iter; + + interfaces = g_dbus_object_get_interfaces(object); + + for (iter = interfaces; iter; iter = iter->next) { + GDBusInterface *interface = G_DBUS_INTERFACE(iter->data); + + interface_added(NULL, object, interface, user_data); + } + + g_list_free_full(interfaces, g_object_unref); +} + +static void +object_removed(GDBusObjectManager *object_manager, GDBusObject *object, gpointer user_data) +{ + GList *interfaces, *iter; + + interfaces = g_dbus_object_get_interfaces(object); + + for (iter = interfaces; iter; iter = iter->next) { + GDBusInterface *interface = G_DBUS_INTERFACE(iter->data); + + interface_removed(NULL, object, interface, user_data); + } + + g_list_free_full(interfaces, g_object_unref); +} + +static void connection_removed(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer user_data) { NMIwdManager * self = user_data; @@ -697,22 +729,6 @@ _om_has_name_owner(GDBusObjectManager *object_manager) } static void -object_added(NMIwdManager *self, GDBusObject *object) -{ - GList *interfaces, *iter; - - interfaces = g_dbus_object_get_interfaces(object); - - for (iter = interfaces; iter; iter = iter->next) { - GDBusInterface *interface = G_DBUS_INTERFACE(iter->data); - - interface_added(NULL, object, interface, self); - } - - g_list_free_full(interfaces, g_object_unref); -} - -static void release_object_manager(NMIwdManager *self) { NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); @@ -852,12 +868,14 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) "interface-removed", G_CALLBACK(interface_removed), self); + g_signal_connect(priv->object_manager, "object-added", G_CALLBACK(object_added), self); + g_signal_connect(priv->object_manager, "object-removed", G_CALLBACK(object_removed), self); g_hash_table_remove_all(priv->known_networks); objects = g_dbus_object_manager_get_objects(object_manager); for (iter = objects; iter; iter = iter->next) - object_added(self, G_DBUS_OBJECT(iter->data)); + object_added(NULL, G_DBUS_OBJECT(iter->data), self); g_list_free_full(objects, g_object_unref); diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/devices/wifi/nm-wifi-p2p-peer.c index fe6ad0a0..a194f168 100644 --- a/src/devices/wifi/nm-wifi-p2p-peer.c +++ b/src/devices/wifi/nm-wifi-p2p-peer.c @@ -47,7 +47,8 @@ struct _NMWifiP2PPeerPrivate { char *address; GBytes *wfd_ies; - char ** groups; + + const char **groups; guint8 strength; @@ -281,7 +282,7 @@ nm_wifi_p2p_peer_get_groups(const NMWifiP2PPeer *peer) { g_return_val_if_fail(NM_IS_WIFI_P2P_PEER(peer), NULL); - return (const char *const *) NM_WIFI_P2P_PEER_GET_PRIVATE(peer)->groups; + return NM_WIFI_P2P_PEER_GET_PRIVATE(peer)->groups; } const char * @@ -404,6 +405,14 @@ nm_wifi_p2p_peer_update_from_properties(NMWifiP2PPeer *peer, const NMSupplicantP changed |= nm_wifi_p2p_peer_set_wfd_ies(peer, peer_info->ies); changed |= nm_wifi_p2p_peer_set_last_seen(peer, peer_info->last_seen_msec / 1000u); + /* We currently only use the groups information internally to check if + * the peer is still joined. */ + if (!_nm_utils_strv_equal((char **) priv->groups, (char **) peer_info->groups)) { + g_free(priv->groups); + priv->groups = nm_utils_strv_dup_packed(peer_info->groups, -1); + changed |= TRUE; + } + g_object_thaw_notify(G_OBJECT(peer)); return changed; @@ -566,7 +575,7 @@ finalize(GObject *object) g_free(priv->serial); g_free(priv->address); g_bytes_unref(priv->wfd_ies); - g_strfreev(priv->groups); + g_free(priv->groups); G_OBJECT_CLASS(nm_wifi_p2p_peer_parent_class)->finalize(object); } diff --git a/src/dns/nm-dns-manager.c b/src/dns/nm-dns-manager.c index 87187d69..635e94f6 100644 --- a/src/dns/nm-dns-manager.c +++ b/src/dns/nm-dns-manager.c @@ -1326,19 +1326,37 @@ static void rebuild_domain_lists(NMDnsManager *self) { NMDnsIPConfigData *ip_data; - gs_unref_hashtable GHashTable *ht = NULL; - gboolean default_route_found = FALSE; + gs_unref_hashtable GHashTable *ht = NULL; + gs_unref_hashtable GHashTable *wildcard_entries = NULL; CList * head; head = _ip_config_lst_head(self); c_list_for_each_entry (ip_data, head, ip_config_lst) { - NMIPConfig *ip_config = ip_data->ip_config; + NMIPConfig *ip_config = ip_data->ip_config; + gboolean add_wildcard = FALSE; if (!nm_ip_config_get_num_nameservers(ip_config)) continue; - if (nm_ip_config_best_default_route_get(ip_config)) { - default_route_found = TRUE; - break; + if (nm_ip_config_best_default_route_get(ip_config)) + add_wildcard = TRUE; + else { + /* If a VPN has never-default=no but doesn't get a default + * route (this can happen for example when the server + * pushes routes with openconnect), and there are no + * search or routing domains, then the name servers pushed + * by the server would be unused. It is preferable in this + * case to use the VPN DNS server for all queries. */ + if (ip_data->ip_config_type == NM_DNS_IP_CONFIG_TYPE_VPN + && !nm_ip_config_get_never_default(ip_data->ip_config) + && nm_ip_config_get_num_searches(ip_data->ip_config) == 0 + && nm_ip_config_get_num_domains(ip_data->ip_config) == 0) + add_wildcard = TRUE; + } + + if (add_wildcard) { + if (!wildcard_entries) + wildcard_entries = g_hash_table_new(nm_direct_hash, NULL); + g_hash_table_add(wildcard_entries, ip_data); } } @@ -1373,13 +1391,13 @@ rebuild_domain_lists(NMDnsManager *self) /* Add wildcard lookup domain to connections with the default route. * If there is no default route, add the wildcard domain to all non-VPN * connections */ - if (default_route_found) { + if (wildcard_entries) { /* FIXME: this heuristic of which device has a default route does * not work with policy routing (as used by default with WireGuard). * We should have a more stable mechanism where an NMIPConfig indicates * whether it is suitable for certain operations (like having an automatically * added "~" domain). */ - if (nm_ip_config_best_default_route_get(ip_config)) + if (g_hash_table_contains(wildcard_entries, ip_data)) domains[num_dom1++] = "~"; } else { if (ip_data->ip_config_type != NM_DNS_IP_CONFIG_TYPE_VPN) diff --git a/src/dns/nm-dns-manager.h b/src/dns/nm-dns-manager.h index 3f90dc87..f91d1556 100644 --- a/src/dns/nm-dns-manager.h +++ b/src/dns/nm-dns-manager.h @@ -22,7 +22,7 @@ typedef enum { enum { NM_DNS_PRIORITY_DEFAULT_NORMAL = 100, - NM_DNS_PRIORITY_DEFAULT_VPN = 50, + NM_DNS_PRIORITY_DEFAULT_VPN = -50, }; struct _NMDnsConfigData; diff --git a/src/initrd/nmi-cmdline-reader.c b/src/initrd/nmi-cmdline-reader.c index f2c60c25..5e610e15 100644 --- a/src/initrd/nmi-cmdline-reader.c +++ b/src/initrd/nmi-cmdline-reader.c @@ -137,10 +137,21 @@ reader_create_connection(Reader * reader, multi_connect, NULL); - if (mac) { - setting = nm_setting_wired_new(); + if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { + setting = nm_setting_infiniband_new(); nm_connection_add_setting(connection, setting); - g_object_set(setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + g_object_set(setting, NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", NULL); + } + + if (mac) { + if (nm_streq0(type_name, NM_SETTING_INFINIBAND_SETTING_NAME)) { + setting = (NMSetting *) nm_connection_get_setting_infiniband(connection); + g_object_set(setting, NM_SETTING_INFINIBAND_MAC_ADDRESS, mac, NULL); + } else { + setting = nm_setting_wired_new(); + nm_connection_add_setting(connection, setting); + g_object_set(setting, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); + } } return connection; @@ -180,7 +191,7 @@ reader_get_connection(Reader * reader, if (nm_utils_is_valid_iface_name(iface_spec, NULL)) ifname = iface_spec; else { - mac = nm_utils_hwaddr_canonical(iface_spec, ETH_ALEN); + mac = nm_utils_hwaddr_canonical(iface_spec, -1); if (!mac) _LOGW(LOGD_CORE, "invalid interface '%s'", iface_spec); } @@ -219,8 +230,13 @@ reader_get_connection(Reader * reader, if (!create_if_missing) return NULL; - if (!type_name) - type_name = NM_SETTING_WIRED_SETTING_NAME; + if (!type_name) { + if (NM_STR_HAS_PREFIX(ifname, "ib") + || (mac && nm_utils_hwaddr_valid(mac, INFINIBAND_ALEN))) + type_name = NM_SETTING_INFINIBAND_SETTING_NAME; + else + type_name = NM_SETTING_WIRED_SETTING_NAME; + } connection = reader_create_connection(reader, ifname ?: mac, diff --git a/src/initrd/tests/test-cmdline-reader.c b/src/initrd/tests/test-cmdline-reader.c index 6de4dd9d..c3511332 100644 --- a/src/initrd/tests/test-cmdline-reader.c +++ b/src/initrd/tests/test-cmdline-reader.c @@ -1722,6 +1722,60 @@ test_dhcp_vendor_class_id(void) g_assert(nm_setting_ip4_config_get_dhcp_vendor_class_identifier(s_ip4) == NULL); } +static void +test_infiniband_iface(void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const * ARGV = NM_MAKE_STRV("ip=ib1:dhcp"); + NMConnection * connection; + NMSettingInfiniband * s_ib; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 1); + g_assert_cmpstr(hostname, ==, NULL); + + connection = g_hash_table_lookup(connections, "ib1"); + g_assert(connection); + nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_connection_type(connection), + ==, + NM_SETTING_INFINIBAND_SETTING_NAME); + s_ib = nm_connection_get_setting_infiniband(connection); + g_assert(s_ib); +} + +static void +test_infiniband_mac(void) +{ + gs_unref_hashtable GHashTable *connections = NULL; + const char *const * ARGV = + NM_MAKE_STRV("ip=00-11-22-33-44-55-66-77-88-99-aa-bb-cc-dd-ee-ff-00-11-22-33:dhcp"); + NMConnection * connection; + NMSettingInfiniband *s_ib; + gs_free char * hostname = NULL; + + connections = nmi_cmdline_reader_parse(TEST_INITRD_DIR "/sysfs", ARGV, &hostname); + g_assert(connections); + g_assert_cmpint(g_hash_table_size(connections), ==, 1); + g_assert_cmpstr(hostname, ==, NULL); + + connection = g_hash_table_lookup(connections, + "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); + g_assert(connection); + nmtst_assert_connection_verifies_without_normalization(connection); + g_assert_cmpstr(nm_connection_get_connection_type(connection), + ==, + NM_SETTING_INFINIBAND_SETTING_NAME); + g_assert_cmpstr(nm_connection_get_interface_name(connection), ==, NULL); + s_ib = nm_connection_get_setting_infiniband(connection); + g_assert(s_ib); + g_assert_cmpstr(nm_setting_infiniband_get_mac_address(s_ib), + ==, + "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33"); +} + NMTST_DEFINE(); int @@ -1762,6 +1816,8 @@ main(int argc, char **argv) g_test_add_func("/initrd/cmdline/bootif/off", test_bootif_off); g_test_add_func("/initrd/cmdline/neednet", test_neednet); g_test_add_func("/initrd/cmdline/dhcp/vendor_class_id", test_dhcp_vendor_class_id); + g_test_add_func("/initrd/cmdline/infiniband/iface", test_infiniband_iface); + g_test_add_func("/initrd/cmdline/infiniband/mac", test_infiniband_mac); return g_test_run(); } diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index ea08450d..9d2b459d 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -283,6 +283,7 @@ NM_GOBJECT_PROPERTIES_DEFINE(NMIP4Config, typedef struct { bool metered : 1; + bool never_default : 1; guint32 mtu; int ifindex; NMIPConfigSource mtu_source; @@ -895,6 +896,8 @@ nm_ip4_config_merge_setting(NMIP4Config * self, nm_ip4_config_mdns_set(self, mdns); nm_ip4_config_llmnr_set(self, llmnr); + nm_ip4_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting)); + g_object_thaw_notify(G_OBJECT(self)); } @@ -1122,6 +1125,11 @@ nm_ip4_config_merge(NMIP4Config * dst, nm_ip4_config_set_metered(dst, nm_ip4_config_get_metered(dst) || nm_ip4_config_get_metered(src)); + /* never default */ + nm_ip4_config_set_never_default(dst, + nm_ip4_config_get_never_default(dst) + || nm_ip4_config_get_never_default(src)); + /* DNS priority */ if (nm_ip4_config_get_dns_priority(src)) nm_ip4_config_set_dns_priority(dst, nm_ip4_config_get_dns_priority(src)); @@ -1856,6 +1864,12 @@ nm_ip4_config_replace(NMIP4Config *dst, const NMIP4Config *src, gboolean *releva has_minor_changes = TRUE; } + /* never default */ + if (src_priv->never_default != dst_priv->never_default) { + dst_priv->never_default = src_priv->never_default; + has_minor_changes = TRUE; + } + #if NM_MORE_ASSERTS /* config_equal does not compare *all* the fields, therefore, we might have has_minor_changes * regardless of config_equal. But config_equal must correspond to has_relevant_changes. */ @@ -2729,6 +2743,24 @@ nm_ip4_config_get_metered(const NMIP4Config *self) /*****************************************************************************/ +void +nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default) +{ + NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self); + + priv->never_default = never_default; +} + +gboolean +nm_ip4_config_get_never_default(const NMIP4Config *self) +{ + const NMIP4ConfigPrivate *priv = NM_IP4_CONFIG_GET_PRIVATE(self); + + return priv->never_default; +} + +/*****************************************************************************/ + const NMPObject * nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index fcbdd714..ccfca74c 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -244,6 +244,9 @@ NMIPConfigSource nm_ip4_config_get_mtu_source(const NMIP4Config *self); void nm_ip4_config_set_metered(NMIP4Config *self, gboolean metered); gboolean nm_ip4_config_get_metered(const NMIP4Config *self); +void nm_ip4_config_set_never_default(NMIP4Config *self, gboolean never_default); +gboolean nm_ip4_config_get_never_default(const NMIP4Config *self); + const NMPObject *nm_ip4_config_nmpobj_lookup(const NMIP4Config *self, const NMPObject *needle); gboolean nm_ip4_config_nmpobj_remove(NMIP4Config *self, const NMPObject *needle); @@ -519,6 +522,21 @@ nm_ip_config_set_config_flags(NMIPConfig *self, NMIPConfigFlags flags, NMIPConfi mask); } +static inline gboolean +nm_ip_config_get_never_default(const NMIPConfig *self) +{ + _NM_IP_CONFIG_DISPATCH(self, nm_ip4_config_get_never_default, nm_ip6_config_get_never_default); +} + +static inline void +nm_ip_config_set_never_default(NMIPConfig *self, gboolean never_default) +{ + _NM_IP_CONFIG_DISPATCH_VOID(self, + nm_ip4_config_set_never_default, + nm_ip6_config_set_never_default, + never_default); +} + #define _NM_IP_CONFIG_DISPATCH_SET_OP(_return, dst, src, v4_func, v6_func, ...) \ G_STMT_START \ { \ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index bd250875..407aa1d6 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -64,6 +64,7 @@ typedef struct { NMDedupMultiIdxType idx_ip6_routes; }; NMIPConfigFlags config_flags; + bool never_default : 1; } NMIP6ConfigPrivate; struct _NMIP6Config { @@ -128,6 +129,24 @@ nm_ip6_config_set_privacy(NMIP6Config *self, NMSettingIP6ConfigPrivacy privacy) /*****************************************************************************/ +void +nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default) +{ + NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self); + + priv->never_default = never_default; +} + +gboolean +nm_ip6_config_get_never_default(const NMIP6Config *self) +{ + const NMIP6ConfigPrivate *priv = NM_IP6_CONFIG_GET_PRIVATE(self); + + return priv->never_default; +} + +/*****************************************************************************/ + const NMDedupMultiHeadEntry * nm_ip6_config_lookup_addresses(const NMIP6Config *self) { @@ -635,6 +654,8 @@ nm_ip6_config_merge_setting(NMIP6Config * self, if (priority) nm_ip6_config_set_dns_priority(self, priority); + nm_ip6_config_set_never_default(self, nm_setting_ip_config_get_never_default(setting)); + g_object_thaw_notify(G_OBJECT(self)); } diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 49046dc8..a5a28a1a 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -175,6 +175,9 @@ const char *nm_ip6_config_get_dns_option(const NMIP6Config *self, guint i); void nm_ip6_config_set_dns_priority(NMIP6Config *self, int priority); int nm_ip6_config_get_dns_priority(const NMIP6Config *self); +void nm_ip6_config_set_never_default(NMIP6Config *self, gboolean never_default); +gboolean nm_ip6_config_get_never_default(const NMIP6Config *self); + const NMPObject *nm_ip6_config_nmpobj_lookup(const NMIP6Config *self, const NMPObject *needle); gboolean nm_ip6_config_nmpobj_remove(NMIP6Config *self, const NMPObject *needle); diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c index 05125fa8..3fa70bbc 100644 --- a/src/platform/nm-linux-platform.c +++ b/src/platform/nm-linux-platform.c @@ -26,6 +26,7 @@ #include <poll.h> #include <sys/ioctl.h> #include <sys/socket.h> +#include <sys/statvfs.h> #include <unistd.h> #include "nm-std-aux/unaligned.h" @@ -9523,12 +9524,34 @@ constructed(GObject *_object) } } +/* Similar to systemd's path_is_read_only_fs(), at + * https://github.com/systemd/systemd/blob/v246/src/basic/stat-util.c#L132 */ +static int +path_is_read_only_fs(const char *path) +{ + struct statvfs st; + + if (statvfs(path, &st) < 0) + return -errno; + + if (st.f_flag & ST_RDONLY) + return TRUE; + + /* On NFS, statvfs() might not reflect whether we can actually + * write to the remote share. Let's try again with + * access(W_OK) which is more reliable, at least sometimes. */ + if (access(path, W_OK) < 0 && errno == EROFS) + return TRUE; + + return FALSE; +} + NMPlatform * nm_linux_platform_new(gboolean log_with_ptr, gboolean netns_support) { gboolean use_udev = FALSE; - if (nmp_netns_is_initial() && access("/sys", W_OK) == 0) + if (nmp_netns_is_initial() && path_is_read_only_fs("/sys") == FALSE) use_udev = TRUE; return g_object_new(NM_TYPE_LINUX_PLATFORM, diff --git a/src/platform/tests/test-platform-general.c b/src/platform/tests/test-platform-general.c index f98f84c9..703c886e 100644 --- a/src/platform/tests/test-platform-general.c +++ b/src/platform/tests/test-platform-general.c @@ -555,6 +555,20 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) gs_free guint64 *rand_map = NULL; gsize i, j; +#if !defined(__amd64__) + /* The test generates a random array of NMPlatformIPXAddress (by crudely randomizing the memory, + * not the structures themself) and then compares the sorted result with the expected output. + * The sole purpose is to ensure that the sorting order stays stable. + * + * This only works on an architecture for which the test was made, otherwise + * the expected data does not match (due to different layout of the structures + * in memory). + * + * That's fine. Skip the test. */ + g_test_skip("skip test on non-amd64 architecture"); + return; +#endif + /* * First we create a list of addresses filled with (stable) random bytes. * We tweak some fields explicitly (stable randomly), so that we cover all @@ -692,14 +706,16 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) } if (PRINT_RESULT) { - g_print("\n\n\t\t[%d] = (\n", TEST_DATA_I); + g_print("\n [%d] = (", TEST_DATA_I); for (i = 0; i < ELM_SIZE * N_ADDRESSES;) { - g_print("\t\t\t\""); + if (i > 0) + g_print("\n "); + g_print("\""); for (j = 0; j < 40 && i < ELM_SIZE * N_ADDRESSES; j++, i++) g_print("%02x", addresses[i]); - g_print("\"\n"); + g_print("\""); } - g_print("\t\t),\n\n"); + g_print("),\n"); return; } @@ -713,6 +729,19 @@ test_platform_ip_address_pretty_sort_cmp(gconstpointer test_data) NULL, 0, &bin_len); + + if (bin_len != ELM_SIZE * N_ADDRESSES || memcmp(addresses, bin_arr, bin_len) != 0) { + char *addresses_str = nm_utils_bin2hexstr(addresses, ELM_SIZE * N_ADDRESSES, -1); + + g_error(">>> test_platform_ip_address_pretty_sort_cmp() will fail:\n" + ">>> addresses[%zu]: %s\n" + ">>> expected [%zu]: %s\n", + ELM_SIZE * N_ADDRESSES, + addresses_str, + bin_len, + EXPECTED_BUFFER[TEST_DATA_I]); + } + g_assert_cmpmem(addresses, ELM_SIZE * N_ADDRESSES, bin_arr, bin_len); } } diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index 1f6252f6..77254c7e 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -833,8 +833,11 @@ _peer_info_destroy(NMSupplicantPeerInfo *peer_info) g_free(peer_info->model); g_free(peer_info->model_number); g_free(peer_info->serial); + g_free(peer_info->groups); g_bytes_unref(peer_info->ies); + nm_ref_string_unref(peer_info->peer_path); + nm_g_slice_free(peer_info); } @@ -854,6 +857,7 @@ _peer_info_properties_changed(NMSupplicantInterface *self, { GVariant * v_v; const char * v_s; + const char ** v_strv; gint32 v_i32; const guint8 *arr_data; gsize arr_len; @@ -878,6 +882,13 @@ _peer_info_properties_changed(NMSupplicantInterface *self, if (nm_g_variant_lookup(properties, "Serial", "&s", &v_s)) nm_utils_strdup_reset(&peer_info->serial, v_s); + if (nm_g_variant_lookup(properties, "Groups", "^a&o", &v_strv)) { + g_free(peer_info->groups); + peer_info->groups = nm_utils_strv_dup_packed(v_strv, -1); + + g_free(v_strv); + } + v_v = nm_g_variant_lookup_value(properties, "DeviceAddress", G_VARIANT_TYPE_BYTESTRING); if (v_v) { arr_data = g_variant_get_fixed_array(v_v, &arr_len, 1); diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h index dc1e3c35..e35059af 100644 --- a/src/supplicant/nm-supplicant-types.h +++ b/src/supplicant/nm-supplicant-types.h @@ -185,6 +185,8 @@ typedef struct _NMSupplicantPeerInfo { char *model_number; char *serial; + const char **groups; + GBytes *ies; gint64 last_seen_msec; |