iwd: Add basic P2P device class for IWD

Similarly as with wpa_supplicant, create NMDeviceIwdP2P objects for P2P
devices based on data from IWD -- not in NMWifiFactory::create_device
because that is only triggered for system netdevs and a P2P-Device
virtual interface has no netdev.  Unlike NMDeviceWifiP2P,
NMDeviceIwdP2P's iface property is a unique string that likely doesn't
match any system interface name -- in theory there doesn't need to be
any related netdev on the system (such as an Infrastructure-mode
interface) before a P2P-Device is added.

[thaller@redhat.com: modified original patch]
This commit is contained in:
Andrew Zaborowski 2021-11-06 06:16:00 +01:00 committed by Thomas Haller
parent 6bf080a7bb
commit 51ef157096
No known key found for this signature in database
GPG Key ID: 29C2366E4DFC5728
7 changed files with 1356 additions and 15 deletions

View File

@ -3935,6 +3935,8 @@ if WITH_IWD
src_core_devices_wifi_libnm_wifi_base_la_SOURCES += \
src/core/devices/wifi/nm-device-iwd.c \
src/core/devices/wifi/nm-device-iwd.h \
src/core/devices/wifi/nm-device-iwd-p2p.c \
src/core/devices/wifi/nm-device-iwd-p2p.h \
src/core/devices/wifi/nm-iwd-manager.c \
src/core/devices/wifi/nm-iwd-manager.h \
$(NULL)

View File

@ -4,6 +4,7 @@ iwd_sources = files()
if enable_iwd
iwd_sources += files(
'nm-device-iwd.c',
'nm-device-iwd-p2p.c',
'nm-iwd-manager.c',
)
endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,36 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2021 Intel Corporation
*/
#ifndef __NM_DEVICE_IWD_P2P_H__
#define __NM_DEVICE_IWD_P2P_H__
#include "devices/nm-device.h"
#include "nm-device-wifi-p2p.h"
#define NM_TYPE_DEVICE_IWD_P2P (nm_device_iwd_p2p_get_type())
#define NM_DEVICE_IWD_P2P(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2P))
#define NM_DEVICE_IWD_P2P_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2PClass))
#define NM_IS_DEVICE_IWD_P2P(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DEVICE_IWD_P2P))
#define NM_IS_DEVICE_IWD_P2P_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DEVICE_IWD_P2P))
#define NM_DEVICE_IWD_P2P_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DEVICE_IWD_P2P, NMDeviceIwdP2PClass))
#define NM_DEVICE_IWD_P2P_PEERS NM_DEVICE_WIFI_P2P_PEERS
#define NM_DEVICE_IWD_P2P_GROUPS NM_DEVICE_WIFI_P2P_GROUPS
typedef struct _NMDeviceIwdP2P NMDeviceIwdP2P;
typedef struct _NMDeviceIwdP2PClass NMDeviceIwdP2PClass;
GType nm_device_iwd_p2p_get_type(void);
NMDeviceIwdP2P *nm_device_iwd_p2p_new(GDBusObject *object);
void nm_device_iwd_p2p_remove(NMDeviceIwdP2P *p2p);
void nm_device_iwd_p2p_peer_add_remove(NMDeviceIwdP2P *p2p, GDBusObject *peer_obj, bool add);
#endif /* __NM_DEVICE_IWD_P2P_H__ */

View File

@ -15,6 +15,7 @@
#include "libnm-core-intern/nm-core-internal.h"
#include "nm-manager.h"
#include "nm-device-iwd.h"
#include "nm-device-iwd-p2p.h"
#include "nm-wifi-utils.h"
#include "libnm-glib-aux/nm-uuid.h"
#include "libnm-glib-aux/nm-random-utils.h"
@ -25,6 +26,14 @@
/*****************************************************************************/
enum {
P2P_DEVICE_ADDED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
typedef struct {
const char *name;
NMIwdNetworkSecurity security;
@ -50,6 +59,7 @@ typedef struct {
char *last_state_dir;
char *warned_state_dir;
bool netconfig_enabled;
GHashTable *p2p_devices;
} NMIwdManagerPrivate;
struct _NMIwdManager {
@ -420,6 +430,66 @@ set_device_dbus_object(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *objec
nm_device_iwd_set_dbus_object(NM_DEVICE_IWD(device), object);
}
static void
add_p2p_device(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
const char *path = g_dbus_object_get_object_path(object);
NMDeviceIwdP2P *p2p;
gs_unref_object GDBusInterface *wiphy = NULL;
const char *phy_name;
if (g_hash_table_contains(priv->p2p_devices, path))
return;
wiphy = g_dbus_object_get_interface(object, NM_IWD_WIPHY_INTERFACE);
if (!wiphy)
return;
phy_name = get_property_string_or_null(G_DBUS_PROXY(wiphy), "Name");
if (!phy_name) {
_LOGE("Name not cached for phy at %s", path);
return;
}
p2p = nm_device_iwd_p2p_new(object);
if (!p2p) {
_LOGE("Can't create NMDeviceIwdP2P for phy at %s", path);
return;
}
g_hash_table_insert(priv->p2p_devices, g_strdup(path), p2p);
g_signal_emit(self, signals[P2P_DEVICE_ADDED], 0, p2p, phy_name);
/* There should be no peer objects before the device object appeared so don't
* try to look for them and notify the new device. */
}
static void
remove_p2p_device(NMIwdManager *self, GDBusProxy *proxy, GDBusObject *object)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
const char *path = g_dbus_object_get_object_path(object);
NMDeviceIwdP2P *p2p = g_hash_table_lookup(priv->p2p_devices, path);
if (!p2p)
return;
g_hash_table_remove(priv->p2p_devices, path);
}
static NMDeviceIwdP2P *
get_p2p_device_from_peer(NMIwdManager *self, GDBusProxy *proxy)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self);
const char *device_path = get_property_string_or_null(proxy, "Device");
if (!device_path)
return NULL;
return g_hash_table_lookup(priv->p2p_devices, device_path);
}
static void
known_network_update_cb(GObject *source, GAsyncResult *res, gpointer user_data)
{
@ -999,6 +1069,22 @@ interface_added(GDBusObjectManager *object_manager,
return;
}
if (nm_streq(iface_name, NM_IWD_P2P_INTERFACE)) {
add_p2p_device(self, proxy, object);
return;
}
if (nm_streq(iface_name, NM_IWD_P2P_PEER_INTERFACE)) {
NMDeviceIwdP2P *p2p = get_p2p_device_from_peer(self, proxy);
/* This is more conveniently done with a direct call than a signal because
* this way we only notify the interested NMDeviceIwdP2P. */
if (p2p)
nm_device_iwd_p2p_peer_add_remove(p2p, object, TRUE);
return;
}
}
static void
@ -1052,6 +1138,20 @@ interface_removed(GDBusObjectManager *object_manager,
return;
}
if (nm_streq(iface_name, NM_IWD_P2P_INTERFACE)) {
remove_p2p_device(self, proxy, object);
return;
}
if (nm_streq(iface_name, NM_IWD_P2P_PEER_INTERFACE)) {
NMDeviceIwdP2P *p2p = get_p2p_device_from_peer(self, proxy);
if (p2p)
nm_device_iwd_p2p_peer_add_remove(p2p, object, FALSE);
return;
}
}
static void
@ -1705,6 +1805,8 @@ nm_iwd_manager_init(NMIwdManager *self)
g_free,
(GDestroyNotify) known_network_data_free);
priv->p2p_devices = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_object_unref);
prepare_object_manager(self);
}
@ -1738,6 +1840,8 @@ dispose(GObject *object)
nm_clear_g_free(&priv->last_state_dir);
nm_clear_g_free(&priv->warned_state_dir);
g_hash_table_unref(nm_steal_pointer(&priv->p2p_devices));
G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object);
}
@ -1747,4 +1851,16 @@ nm_iwd_manager_class_init(NMIwdManagerClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS(klass);
object_class->dispose = dispose;
signals[P2P_DEVICE_ADDED] = g_signal_new(NM_IWD_MANAGER_P2P_DEVICE_ADDED,
G_OBJECT_CLASS_TYPE(object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
NULL,
G_TYPE_NONE,
2,
NM_TYPE_DEVICE,
G_TYPE_STRING);
}

View File

@ -13,20 +13,22 @@
#define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM
#define NM_IWD_SERVICE "net.connman.iwd"
#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon"
#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager"
#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter"
#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device"
#define NM_IWD_NETWORK_INTERFACE "net.connman.iwd.Network"
#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent"
#define NM_IWD_WSC_INTERFACE "net.connman.iwd.SimpleConfiguration"
#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork"
#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent"
#define NM_IWD_AP_INTERFACE "net.connman.iwd.AccessPoint"
#define NM_IWD_ADHOC_INTERFACE "net.connman.iwd.AdHoc"
#define NM_IWD_STATION_INTERFACE "net.connman.iwd.Station"
#define NM_IWD_P2P_PEER_INTERFACE "net.connman.iwd.p2p.Peer"
#define NM_IWD_P2P_WFD_INTERFACE "net.connman.iwd.p2p.Display"
#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon"
#define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager"
#define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter"
#define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device"
#define NM_IWD_NETWORK_INTERFACE "net.connman.iwd.Network"
#define NM_IWD_AGENT_INTERFACE "net.connman.iwd.Agent"
#define NM_IWD_WSC_INTERFACE "net.connman.iwd.SimpleConfiguration"
#define NM_IWD_KNOWN_NETWORK_INTERFACE "net.connman.iwd.KnownNetwork"
#define NM_IWD_SIGNAL_AGENT_INTERFACE "net.connman.iwd.SignalLevelAgent"
#define NM_IWD_AP_INTERFACE "net.connman.iwd.AccessPoint"
#define NM_IWD_ADHOC_INTERFACE "net.connman.iwd.AdHoc"
#define NM_IWD_STATION_INTERFACE "net.connman.iwd.Station"
#define NM_IWD_P2P_INTERFACE "net.connman.iwd.p2p.Device"
#define NM_IWD_P2P_PEER_INTERFACE "net.connman.iwd.p2p.Peer"
#define NM_IWD_P2P_SERVICE_MANAGER_INTERFACE "net.connman.iwd.p2p.ServiceManager"
#define NM_IWD_P2P_WFD_INTERFACE "net.connman.iwd.p2p.Display"
#define NM_TYPE_IWD_MANAGER (nm_iwd_manager_get_type())
#define NM_IWD_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_IWD_MANAGER, NMIwdManager))
@ -37,6 +39,8 @@
#define NM_IWD_MANAGER_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_IWD_MANAGER, NMIwdManagerClass))
#define NM_IWD_MANAGER_P2P_DEVICE_ADDED "p2p-device-added"
typedef struct _NMIwdManager NMIwdManager;
typedef struct _NMIwdManagerClass NMIwdManagerClass;

View File

@ -14,6 +14,8 @@
#include "nm-device-wifi-p2p.h"
#include "nm-device-olpc-mesh.h"
#include "nm-device-iwd.h"
#include "nm-device-iwd-p2p.h"
#include "nm-iwd-manager.h"
#include "settings/nm-settings-connection.h"
#include "libnm-platform/nm-platform.h"
#include "nm-config.h"
@ -67,6 +69,19 @@ p2p_device_created(NMDeviceWifi *device, NMDeviceWifiP2P *p2p_device, NMDeviceFa
g_signal_emit_by_name(self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device);
}
#if WITH_IWD
static void
iwd_p2p_device_added(NMIwdManager *iwd,
NMDeviceIwdP2P *p2p_device,
const char *phy_name,
NMDeviceFactory *self)
{
nm_log_info(LOGD_PLATFORM | LOGD_WIFI, "Wi-Fi P2P device added on %s", phy_name);
g_signal_emit_by_name(self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device);
}
#endif
static NMDevice *
create_device(NMDeviceFactory *factory,
const char *iface,
@ -138,8 +153,23 @@ create_device(NMDeviceFactory *factory,
return device;
}
#if WITH_IWD
else if (!g_ascii_strcasecmp(backend, "iwd"))
else if (!g_ascii_strcasecmp(backend, "iwd")) {
NMIwdManager *iwd = nm_iwd_manager_get();
if (!g_signal_handler_find(iwd,
G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
0,
0,
NULL,
G_CALLBACK(iwd_p2p_device_added),
factory))
g_signal_connect(iwd,
NM_IWD_MANAGER_P2P_DEVICE_ADDED,
G_CALLBACK(iwd_p2p_device_added),
factory);
return nm_device_iwd_new(iface);
}
#endif
nm_log_warn(LOGD_PLATFORM | LOGD_WIFI,