From 42e60e327f92b7469fa1584682c09771017990fb Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 10 Oct 2018 17:23:42 +0200 Subject: core: Add basic P2P Wi-Fi Settings The support is rather basic and only allows connecting to a specific peer. However, this is actually already enough for many usecases. --- Makefile.am | 2 + clients/cli/connections.c | 1 + clients/common/nm-meta-setting-desc.c | 28 +++ clients/common/settings-docs.h.in | 2 + docs/libnm/libnm-docs.xml | 1 + libnm-core/meson.build | 2 + libnm-core/nm-core-enum-types.c.template | 1 + libnm-core/nm-core-internal.h | 1 + libnm-core/nm-core-types.h | 1 + libnm-core/nm-setting-p2p-wireless.c | 281 +++++++++++++++++++++++++++++++ libnm-core/nm-setting-p2p-wireless.h | 74 ++++++++ libnm/NetworkManager.h | 1 + libnm/libnm.ver | 4 + libnm/nm-autoptr.h | 1 + po/POTFILES.in | 1 + shared/nm-meta-setting.c | 7 + shared/nm-meta-setting.h | 1 + vapi/NM-1.0.metadata | 1 + 18 files changed, 410 insertions(+) create mode 100644 libnm-core/nm-setting-p2p-wireless.c create mode 100644 libnm-core/nm-setting-p2p-wireless.h diff --git a/Makefile.am b/Makefile.am index c8a5ed0617..f7f189b56c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -643,6 +643,7 @@ libnm_core_lib_h_pub_real = \ libnm-core/nm-setting-ovs-interface.h \ libnm-core/nm-setting-ovs-patch.h \ libnm-core/nm-setting-ovs-port.h \ + libnm-core/nm-setting-p2p-wireless.h \ libnm-core/nm-setting-ppp.h \ libnm-core/nm-setting-pppoe.h \ libnm-core/nm-setting-proxy.h \ @@ -711,6 +712,7 @@ libnm_core_lib_c_settings_real = \ libnm-core/nm-setting-ovs-interface.c \ libnm-core/nm-setting-ovs-patch.c \ libnm-core/nm-setting-ovs-port.c \ + libnm-core/nm-setting-p2p-wireless.c \ libnm-core/nm-setting-ppp.c \ libnm-core/nm-setting-pppoe.c \ libnm-core/nm-setting-proxy.c \ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 446424ba46..8155bfb960 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -796,6 +796,7 @@ const NmcMetaGenericInfo *const metagen_con_active_vpn[_NMC_GENERIC_INFO_TYPE_CO NM_SETTING_IP4_CONFIG_SETTING_NAME","\ NM_SETTING_IP6_CONFIG_SETTING_NAME","\ NM_SETTING_SERIAL_SETTING_NAME","\ + NM_SETTING_P2P_WIRELESS_SETTING_NAME","\ NM_SETTING_PPP_SETTING_NAME","\ NM_SETTING_PPPOE_SETTING_NAME","\ NM_SETTING_ADSL_SETTING_NAME","\ diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 4befce259a..6b76d80be3 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -7843,6 +7843,27 @@ static const NMMetaPropertyInfo *const property_infos_6LOWPAN[] = { NULL }; +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_P2P_WIRELESS +static const NMMetaPropertyInfo *const property_infos_P2P_WIRELESS[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_P2P_WIRELESS_PEER, + .is_cli_option = TRUE, + .property_alias = "peer", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Peer"), + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_security_wps_method_get_type, + ), + ), + ), + NULL +}; + /*****************************************************************************/ static void @@ -8008,6 +8029,7 @@ _setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) #define SETTING_PRETTY_NAME_WIRELESS_SECURITY N_("Wi-Fi security settings") #define SETTING_PRETTY_NAME_WPAN N_("WPAN settings") #define SETTING_PRETTY_NAME_6LOWPAN N_("6LOWPAN settings") +#define SETTING_PRETTY_NAME_P2P_WIRELESS N_("P2P Wi-Fi connection") #define NM_META_SETTING_VALID_PARTS(...) \ ((const NMMetaSettingValidPartItem *const[]) { __VA_ARGS__ NULL }) @@ -8282,6 +8304,12 @@ const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { NM_META_SETTING_VALID_PART_ITEM (WPAN, TRUE), ), ), + SETTING_INFO (P2P_WIRELESS, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (P2P_WIRELESS, TRUE), + ), + ), }; /*****************************************************************************/ diff --git a/clients/common/settings-docs.h.in b/clients/common/settings-docs.h.in index ca0150e694..7f1a59d5fa 100644 --- a/clients/common/settings-docs.h.in +++ b/clients/common/settings-docs.h.in @@ -263,6 +263,8 @@ #define DESCRIBE_DOC_NM_SETTING_OVS_PORT_LACP N_("LACP mode. One of \"active\", \"off\", or \"passive\".") #define DESCRIBE_DOC_NM_SETTING_OVS_PORT_TAG N_("The VLAN tag in the range 0-4095.") #define DESCRIBE_DOC_NM_SETTING_OVS_PORT_VLAN_MODE N_("The VLAN mode. One of \"access\", \"native-tagged\", \"native-untagged\", \"trunk\" or unset.") +#define DESCRIBE_DOC_NM_SETTING_P2P_WIRELESS_PEER N_("The P2P device that should be connected to. Currently this is the only way to create or join a group.") +#define DESCRIBE_DOC_NM_SETTING_P2P_WIRELESS_WPS_METHOD N_("Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use.") #define DESCRIBE_DOC_NM_SETTING_PPP_BAUD N_("If non-zero, instruct pppd to set the serial port to the specified baudrate. This value should normally be left as 0 to automatically choose the speed.") #define DESCRIBE_DOC_NM_SETTING_PPP_CRTSCTS N_("If TRUE, specify that pppd should set the serial port to use hardware flow control with RTS and CTS signals. This value should normally be set to FALSE.") #define DESCRIBE_DOC_NM_SETTING_PPP_LCP_ECHO_FAILURE N_("If non-zero, instruct pppd to presume the connection to the peer has failed if the specified number of LCP echo-requests go unanswered by the peer. The \"lcp-echo-interval\" property must also be set to a non-zero value if this property is used.") diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml index eb4f6cf585..df5d9bab31 100644 --- a/docs/libnm/libnm-docs.xml +++ b/docs/libnm/libnm-docs.xml @@ -218,6 +218,7 @@ print ("NetworkManager version " + client.get_version())]]> + diff --git a/libnm-core/meson.build b/libnm-core/meson.build index 812f12bbcc..e615b3451e 100644 --- a/libnm-core/meson.build +++ b/libnm-core/meson.build @@ -32,6 +32,7 @@ libnm_core_headers = files( 'nm-setting-ovs-interface.h', 'nm-setting-ovs-patch.h', 'nm-setting-ovs-port.h', + 'nm-setting-p2p-wireless.h', 'nm-setting-ppp.h', 'nm-setting-pppoe.h', 'nm-setting-proxy.h', @@ -87,6 +88,7 @@ libnm_core_settings_sources = files( 'nm-setting-ovs-interface.c', 'nm-setting-ovs-patch.c', 'nm-setting-ovs-port.c', + 'nm-setting-p2p-wireless.c', 'nm-setting-ppp.c', 'nm-setting-pppoe.c', 'nm-setting-proxy.c', diff --git a/libnm-core/nm-core-enum-types.c.template b/libnm-core/nm-core-enum-types.c.template index 605fa34ae4..0edb97dcc7 100644 --- a/libnm-core/nm-core-enum-types.c.template +++ b/libnm-core/nm-core-enum-types.c.template @@ -33,6 +33,7 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-patch.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-p2p-wireless.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-proxy.h" diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 6af293a013..f73d728b7d 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -63,6 +63,7 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-patch.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-p2p-wireless.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-serial.h" diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h index 89d99579e5..823001324e 100644 --- a/libnm-core/nm-core-types.h +++ b/libnm-core/nm-core-types.h @@ -57,6 +57,7 @@ typedef struct _NMSettingOvsBridge NMSettingOvsBridge; typedef struct _NMSettingOvsInterface NMSettingOvsInterface; typedef struct _NMSettingOvsPatch NMSettingOvsPatch; typedef struct _NMSettingOvsPort NMSettingOvsPort; +typedef struct _NMSettingP2PWireless NMSettingP2PWireless; typedef struct _NMSettingPpp NMSettingPpp; typedef struct _NMSettingPppoe NMSettingPppoe; typedef struct _NMSettingSerial NMSettingSerial; diff --git a/libnm-core/nm-setting-p2p-wireless.c b/libnm-core/nm-setting-p2p-wireless.c new file mode 100644 index 0000000000..e49ff0d995 --- /dev/null +++ b/libnm-core/nm-setting-p2p-wireless.c @@ -0,0 +1,281 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2019 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-setting-p2p-wireless.h" + +#include +#include + +#include "nm-utils.h" +#include "nm-common-macros.h" +#include "nm-utils-private.h" +#include "nm-setting-private.h" + +/** + * SECTION:nm-setting-p2p-wireless + * @short_description: Describes connection properties for 802.11 Wi-Fi P2P networks + * + * The #NMSettingP2PWireless object is a #NMSetting subclass that describes properties + * necessary for connection to 802.11 Wi-Fi P2P networks (aka Wi-Fi Direct). + **/ + +/** + * NMSettingP2PWireless: + * + * P2P Wi-Fi Settings + */ + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE_BASE ( + PROP_PEER, + PROP_WPS_METHOD, +#if 0 + PROP_WPS_PIN, + PROP_WPS_PIN_FLAGS, +#endif +); + +typedef struct { + char *peer_mac_address; + + NMSettingWirelessSecurityWpsMethod wps_method; +} NMSettingP2PWirelessPrivate; + +struct _NMSettingP2PWireless { + NMSetting parent; + NMSettingP2PWirelessPrivate _priv; +}; + +struct _NMSettingP2PWirelessClass { + NMSettingClass parent; +}; + +G_DEFINE_TYPE (NMSettingP2PWireless, nm_setting_p2p_wireless, NM_TYPE_SETTING) + +#define NM_SETTING_P2P_WIRELESS_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettingP2PWireless, NM_IS_SETTING_P2P_WIRELESS, NMSetting) + +/*****************************************************************************/ + +/** + * nm_setting_p2p_wireless_get_peer: + * @setting: the #NMSettingP2PWireless + * + * Returns: the #NMSettingP2PWireless:peer property of the setting + * + * Since: 1.16 + **/ +const char * +nm_setting_p2p_wireless_get_peer (NMSettingP2PWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_P2P_WIRELESS (setting), NULL); + + return NM_SETTING_P2P_WIRELESS_GET_PRIVATE (setting)->peer_mac_address; +} + +/** + * nm_setting_p2p_wireless_get_wps_method: + * @setting: the #NMSettingP2PWireless + * + * Returns: the #NMSettingP2PWireless:wps-method property of the setting + * + * Since: 1.16 + **/ +NMSettingWirelessSecurityWpsMethod +nm_setting_p2p_wireless_get_wps_method (NMSettingP2PWireless *setting) +{ + g_return_val_if_fail (NM_IS_SETTING_P2P_WIRELESS (setting), NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT); + + return NM_SETTING_P2P_WIRELESS_GET_PRIVATE (setting)->wps_method; +} + +static gboolean +verify (NMSetting *setting, NMConnection *connection, GError **error) +{ + NMSettingP2PWirelessPrivate *priv = NM_SETTING_P2P_WIRELESS_GET_PRIVATE (setting); + + if (!priv->peer_mac_address || !nm_utils_hwaddr_valid (priv->peer_mac_address, ETH_ALEN)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_P2P_WIRELESS_SETTING_NAME, NM_SETTING_P2P_WIRELESS_PEER); + return FALSE; + } + + if (priv->wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_PIN) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + return FALSE; + } + + if (priv->wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("P2P connections require WPS")); + return FALSE; + } + + if (priv->wps_method > NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DISABLED) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("P2P connections require WPS")); + return FALSE; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingP2PWireless *setting = NM_SETTING_P2P_WIRELESS (object); + + switch (prop_id) { + case PROP_PEER: + g_value_set_string (value, nm_setting_p2p_wireless_get_peer (setting)); + break; + case PROP_WPS_METHOD: + g_value_set_uint (value, nm_setting_p2p_wireless_get_wps_method (setting)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingP2PWirelessPrivate *priv = NM_SETTING_P2P_WIRELESS_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PEER: + g_free (priv->peer_mac_address); + priv->peer_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value), + ETH_ALEN); + break; + case PROP_WPS_METHOD: + priv->wps_method = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_setting_p2p_wireless_init (NMSettingP2PWireless *setting) +{ +} + +/** + * nm_setting_p2p_wireless_new: + * + * Creates a new #NMSettingP2PWireless object with default values. + * + * Returns: (transfer full): the new empty #NMSettingP2PWireless object + * + * Since: 1.16 + **/ +NMSetting * +nm_setting_p2p_wireless_new (void) +{ + return (NMSetting *) g_object_new (NM_TYPE_SETTING_P2P_WIRELESS, NULL); +} + +static void +finalize (GObject *object) +{ + NMSettingP2PWirelessPrivate *priv = NM_SETTING_P2P_WIRELESS_GET_PRIVATE (object); + + g_free (priv->peer_mac_address); + + G_OBJECT_CLASS (nm_setting_p2p_wireless_parent_class)->finalize (object); +} + +static void +nm_setting_p2p_wireless_class_init (NMSettingP2PWirelessClass *setting_p2p_wireless_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (setting_p2p_wireless_class); + NMSettingClass *setting_class = NM_SETTING_CLASS (setting_p2p_wireless_class); + + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + setting_class->verify = verify; + + /** + * NMSettingP2PWireless:peer: + * + * The P2P device that should be connected to. Currently this is the only + * way to create or join a group. + * + * Since: 1.16 + */ + /* ---keyfile--- + * property: peer + * format: usual hex-digits-and-colons notation + * description: MAC address in traditional hex-digits-and-colons notation + * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete) + * (e.g. 0;34;104;18;121;162). + * ---end--- + */ + obj_properties[PROP_PEER] = + g_param_spec_string (NM_SETTING_P2P_WIRELESS_PEER, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + + /** + * NMSettingP2PWireless:wps-method: + * + * Flags indicating which mode of WPS is to be used. + * + * There's little point in changing the default setting as NetworkManager will + * automatically determine the best method to use. + * + * Since: 1.16 + */ + obj_properties[PROP_WPS_METHOD] = + g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, "", "", + 0, + G_MAXUINT32, + NM_SETTING_WIRELESS_SECURITY_WPS_METHOD_DEFAULT, + G_PARAM_READWRITE | + NM_SETTING_PARAM_FUZZY_IGNORE | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); + + _nm_setting_class_commit (setting_class, NM_META_SETTING_TYPE_P2P_WIRELESS); +} diff --git a/libnm-core/nm-setting-p2p-wireless.h b/libnm-core/nm-setting-p2p-wireless.h new file mode 100644 index 0000000000..4880867198 --- /dev/null +++ b/libnm-core/nm-setting-p2p-wireless.h @@ -0,0 +1,74 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2019 Red Hat, Inc. + */ + +#ifndef __NM_SETTING_P2P_WIRELESS_H__ +#define __NM_SETTING_P2P_WIRELESS_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include "nm-setting.h" +#include "nm-setting-wireless-security.h" + +G_BEGIN_DECLS + +#define NM_TYPE_SETTING_P2P_WIRELESS (nm_setting_p2p_wireless_get_type ()) +#define NM_SETTING_P2P_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_P2P_WIRELESS, NMSettingP2PWireless)) +#define NM_SETTING_P2P_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_P2P_WIRELESS, NMSettingP2PWirelessClass)) +#define NM_IS_SETTING_P2P_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_P2P_WIRELESS)) +#define NM_IS_SETTING_P2P_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_P2P_WIRELESS)) +#define NM_SETTING_P2P_WIRELESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_P2P_WIRELESS, NMSettingP2PWirelessClass)) + +#define NM_SETTING_P2P_WIRELESS_SETTING_NAME "p2p-wireless" + +/** + * NM_SETTING_P2P_WIRELESS_PEER: + * + * The mac address of the peer to connect to. + */ +#define NM_SETTING_P2P_WIRELESS_PEER "peer" +#define NM_SETTING_P2P_WIRELESS_WPS_METHOD "wps-method" +#if 0 +#define NM_SETTING_P2P_WIRELESS_WPS_PIN "wps-pin" +#endif + +#if 0 +#define NM_SETTING_P2P_WIRELESS_GO_INTENT "go-intent" +/* Not sure how we could even handle this, i.e. would we need to store more information? */ +#define NM_SETTING_P2P_WIRELESS_PERSISTENT "persistent" +#endif + +typedef struct _NMSettingP2PWirelessClass NMSettingP2PWirelessClass; + +NM_AVAILABLE_IN_1_16 +GType nm_setting_p2p_wireless_get_type (void); + +NM_AVAILABLE_IN_1_16 +NMSetting *nm_setting_p2p_wireless_new (void); + +NM_AVAILABLE_IN_1_16 +const char *nm_setting_p2p_wireless_get_peer (NMSettingP2PWireless *setting); + +NM_AVAILABLE_IN_1_16 +NMSettingWirelessSecurityWpsMethod nm_setting_p2p_wireless_get_wps_method (NMSettingP2PWireless *setting); + +G_END_DECLS + +#endif /* __NM_SETTING_P2P_WIRELESS_H__ */ diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 759a413187..30ec7905a2 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -88,6 +88,7 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-patch.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-p2p-wireless.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-proxy.h" diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 652e01eb68..b30e47af7d 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1450,6 +1450,10 @@ global: nm_client_add_and_activate_connection2; nm_client_add_and_activate_connection2_finish; nm_device_get_connectivity; + nm_setting_p2p_wireless_get_peer; + nm_setting_p2p_wireless_get_type; + nm_setting_p2p_wireless_get_wps_method; + nm_setting_p2p_wireless_new; nm_team_link_watcher_get_vlanid; nm_team_link_watcher_new_arp_ping2; } libnm_1_14_0; diff --git a/libnm/nm-autoptr.h b/libnm/nm-autoptr.h index e96a03a099..bffacd39cd 100644 --- a/libnm/nm-autoptr.h +++ b/libnm/nm-autoptr.h @@ -64,6 +64,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingOvsBridge, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingOvsInterface, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingOvsPatch, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingOvsPort, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingP2PWireless, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingPpp, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingPppoe, g_object_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingProxy, g_object_unref) diff --git a/po/POTFILES.in b/po/POTFILES.in index 33192b1dd0..6700d5be82 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -82,6 +82,7 @@ libnm-core/nm-setting-ovs-interface.c libnm-core/nm-setting-ovs-patch.c libnm-core/nm-setting-ovs-port.c libnm-core/nm-setting-ovs-bridge.c +libnm-core/nm-setting-p2p-wireless.c libnm-core/nm-setting-ppp.c libnm-core/nm-setting-pppoe.c libnm-core/nm-setting-proxy.c diff --git a/shared/nm-meta-setting.c b/shared/nm-meta-setting.c index 3e79747fba..6256b06c00 100644 --- a/shared/nm-meta-setting.c +++ b/shared/nm-meta-setting.c @@ -50,6 +50,7 @@ #include "nm-setting-ovs-interface.h" #include "nm-setting-ovs-patch.h" #include "nm-setting-ovs-port.h" +#include "nm-setting-p2p-wireless.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" #include "nm-setting-proxy.h" @@ -305,6 +306,12 @@ const NMMetaSettingInfo nm_meta_setting_infos[] = { .setting_name = NM_SETTING_OVS_PORT_SETTING_NAME, .get_setting_gtype = nm_setting_ovs_port_get_type, }, + [NM_META_SETTING_TYPE_P2P_WIRELESS] = { + .meta_type = NM_META_SETTING_TYPE_P2P_WIRELESS, + .setting_priority = NM_SETTING_PRIORITY_HW_BASE, + .setting_name = NM_SETTING_P2P_WIRELESS_SETTING_NAME, + .get_setting_gtype = nm_setting_p2p_wireless_get_type, + }, [NM_META_SETTING_TYPE_PPPOE] = { .meta_type = NM_META_SETTING_TYPE_PPPOE, .setting_priority = NM_SETTING_PRIORITY_AUX, diff --git a/shared/nm-meta-setting.h b/shared/nm-meta-setting.h index 26c29beaa7..089acc8e9c 100644 --- a/shared/nm-meta-setting.h +++ b/shared/nm-meta-setting.h @@ -132,6 +132,7 @@ typedef enum { NM_META_SETTING_TYPE_OVS_INTERFACE, NM_META_SETTING_TYPE_OVS_PATCH, NM_META_SETTING_TYPE_OVS_PORT, + NM_META_SETTING_TYPE_P2P_WIRELESS, NM_META_SETTING_TYPE_PPP, NM_META_SETTING_TYPE_PPPOE, NM_META_SETTING_TYPE_PROXY, diff --git a/vapi/NM-1.0.metadata b/vapi/NM-1.0.metadata index ab43f3e174..98fd071e2d 100644 --- a/vapi/NM-1.0.metadata +++ b/vapi/NM-1.0.metadata @@ -28,6 +28,7 @@ SETTING_IP6_CONFIG_* parent="NM.SettingIP6Config" name="SETTIN SETTING_IP_TUNNEL_* parent="NM.SettingIPTunnel" name="SETTING_IP_TUNNEL_(.+)" SETTING_MACVLAN_* parent="NM.SettingMacvlan" name="SETTING_MACVLAN_(.+)" SETTING_OLPC_MESH_* parent="NM.SettingOlpcMesh" name="SETTING_OLPC_MESH_(.+)" +SETTING_P2P_WIRELESS_* parent="NM.SettingP2PWireless" name="SETTING_P2P_WIRELESS_(.+)" SETTING_PPP_* parent="NM.SettingPpp" name="SETTING_PPP_(.+)" SETTING_PPPOE_* parent="NM.SettingPppoe" name="SETTING_PPPOE_(.+)" SETTING_PROXY_* parent="NM.SettingProxy" name="SETTING_PROXY_(.+)" -- cgit v1.2.1 From 00e64d13320f5848a757765c8541e8160aa8e3e2 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 10 Oct 2018 23:30:46 +0200 Subject: core/devices: Add P2P Wifi device and peer tracking This only adds the new device type and simple peer list handling. --- Makefile.am | 128 +- clients/common/nm-client-utils.c | 1 + docs/api/Makefile.am | 51 +- docs/api/network-manager-docs.xml | 7 + introspection/meson.build | 2 + ...eedesktop.NetworkManager.Device.P2PWireless.xml | 65 + .../org.freedesktop.NetworkManager.P2PPeer.xml | 78 ++ libnm-core/nm-dbus-interface.h | 5 + src/devices/nm-device.c | 1 + src/devices/wifi/meson.build | 8 +- src/devices/wifi/nm-device-p2p-wifi.c | 1287 ++++++++++++++++++++ src/devices/wifi/nm-device-p2p-wifi.h | 56 + src/devices/wifi/nm-wifi-p2p-peer.c | 808 ++++++++++++ src/devices/wifi/nm-wifi-p2p-peer.h | 114 ++ src/nm-types.h | 1 + src/org.freedesktop.NetworkManager.conf | 4 + 16 files changed, 2532 insertions(+), 84 deletions(-) create mode 100644 introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml create mode 100644 introspection/org.freedesktop.NetworkManager.P2PPeer.xml create mode 100644 src/devices/wifi/nm-device-p2p-wifi.c create mode 100644 src/devices/wifi/nm-device-p2p-wifi.h create mode 100644 src/devices/wifi/nm-wifi-p2p-peer.c create mode 100644 src/devices/wifi/nm-wifi-p2p-peer.h diff --git a/Makefile.am b/Makefile.am index f7f189b56c..1b7289c011 100644 --- a/Makefile.am +++ b/Makefile.am @@ -389,30 +389,32 @@ introspection_libnmdbus_la_CPPFLAGS = $(GLIB_CFLAGS) introspection_sources = \ introspection/org.freedesktop.NetworkManager.AccessPoint.c \ introspection/org.freedesktop.NetworkManager.AccessPoint.h \ - introspection/org.freedesktop.NetworkManager.Connection.Active.c \ - introspection/org.freedesktop.NetworkManager.Connection.Active.h \ introspection/org.freedesktop.NetworkManager.AgentManager.c \ introspection/org.freedesktop.NetworkManager.AgentManager.h \ introspection/org.freedesktop.NetworkManager.Checkpoint.c \ introspection/org.freedesktop.NetworkManager.Checkpoint.h \ + introspection/org.freedesktop.NetworkManager.Connection.Active.c \ + introspection/org.freedesktop.NetworkManager.Connection.Active.h \ + introspection/org.freedesktop.NetworkManager.DHCP4Config.c \ + introspection/org.freedesktop.NetworkManager.DHCP4Config.h \ + introspection/org.freedesktop.NetworkManager.DHCP6Config.c \ + introspection/org.freedesktop.NetworkManager.DHCP6Config.h \ introspection/org.freedesktop.NetworkManager.Device.Adsl.c \ introspection/org.freedesktop.NetworkManager.Device.Adsl.h \ + introspection/org.freedesktop.NetworkManager.Device.Bluetooth.c \ + introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h \ introspection/org.freedesktop.NetworkManager.Device.Bond.c \ introspection/org.freedesktop.NetworkManager.Device.Bond.h \ introspection/org.freedesktop.NetworkManager.Device.Bridge.c \ introspection/org.freedesktop.NetworkManager.Device.Bridge.h \ - introspection/org.freedesktop.NetworkManager.Device.Bluetooth.c \ - introspection/org.freedesktop.NetworkManager.Device.Bluetooth.h \ introspection/org.freedesktop.NetworkManager.Device.Dummy.c \ introspection/org.freedesktop.NetworkManager.Device.Dummy.h \ - introspection/org.freedesktop.NetworkManager.Device.Wired.c \ - introspection/org.freedesktop.NetworkManager.Device.Wired.h \ introspection/org.freedesktop.NetworkManager.Device.Generic.c \ introspection/org.freedesktop.NetworkManager.Device.Generic.h \ - introspection/org.freedesktop.NetworkManager.Device.Infiniband.c \ - introspection/org.freedesktop.NetworkManager.Device.Infiniband.h \ introspection/org.freedesktop.NetworkManager.Device.IPTunnel.c \ introspection/org.freedesktop.NetworkManager.Device.IPTunnel.h \ + introspection/org.freedesktop.NetworkManager.Device.Infiniband.c \ + introspection/org.freedesktop.NetworkManager.Device.Infiniband.h \ introspection/org.freedesktop.NetworkManager.Device.Lowpan.c \ introspection/org.freedesktop.NetworkManager.Device.Lowpan.h \ introspection/org.freedesktop.NetworkManager.Device.Macsec.c \ @@ -423,12 +425,14 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.Device.Modem.h \ introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.c \ introspection/org.freedesktop.NetworkManager.Device.OlpcMesh.h \ + introspection/org.freedesktop.NetworkManager.Device.OvsBridge.c \ + introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.c \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.h \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.c \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.h \ - introspection/org.freedesktop.NetworkManager.Device.OvsBridge.c \ - introspection/org.freedesktop.NetworkManager.Device.OvsBridge.h \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.c \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.h \ introspection/org.freedesktop.NetworkManager.Device.Ppp.c \ introspection/org.freedesktop.NetworkManager.Device.Ppp.h \ introspection/org.freedesktop.NetworkManager.Device.Statistics.c \ @@ -443,28 +447,26 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.Device.Vlan.h \ introspection/org.freedesktop.NetworkManager.Device.Vxlan.c \ introspection/org.freedesktop.NetworkManager.Device.Vxlan.h \ + introspection/org.freedesktop.NetworkManager.Device.WiMax.c \ + introspection/org.freedesktop.NetworkManager.Device.WiMax.h \ introspection/org.freedesktop.NetworkManager.Device.WireGuard.c \ introspection/org.freedesktop.NetworkManager.Device.WireGuard.h \ + introspection/org.freedesktop.NetworkManager.Device.Wired.c \ + introspection/org.freedesktop.NetworkManager.Device.Wired.h \ introspection/org.freedesktop.NetworkManager.Device.Wireless.c \ introspection/org.freedesktop.NetworkManager.Device.Wireless.h \ - introspection/org.freedesktop.NetworkManager.Device.WiMax.c \ - introspection/org.freedesktop.NetworkManager.Device.WiMax.h \ introspection/org.freedesktop.NetworkManager.Device.Wpan.c \ introspection/org.freedesktop.NetworkManager.Device.Wpan.h \ introspection/org.freedesktop.NetworkManager.Device.c \ introspection/org.freedesktop.NetworkManager.Device.h \ - introspection/org.freedesktop.NetworkManager.DHCP4Config.c \ - introspection/org.freedesktop.NetworkManager.DHCP4Config.h \ - introspection/org.freedesktop.NetworkManager.DHCP6Config.c \ - introspection/org.freedesktop.NetworkManager.DHCP6Config.h \ introspection/org.freedesktop.NetworkManager.DnsManager.c \ introspection/org.freedesktop.NetworkManager.DnsManager.h \ introspection/org.freedesktop.NetworkManager.IP4Config.c \ introspection/org.freedesktop.NetworkManager.IP4Config.h \ introspection/org.freedesktop.NetworkManager.IP6Config.c \ introspection/org.freedesktop.NetworkManager.IP6Config.h \ - introspection/org.freedesktop.NetworkManager.c \ - introspection/org.freedesktop.NetworkManager.h \ + introspection/org.freedesktop.NetworkManager.P2PPeer.c \ + introspection/org.freedesktop.NetworkManager.P2PPeer.h \ introspection/org.freedesktop.NetworkManager.PPP.c \ introspection/org.freedesktop.NetworkManager.PPP.h \ introspection/org.freedesktop.NetworkManager.SecretAgent.c \ @@ -476,56 +478,62 @@ introspection_sources = \ introspection/org.freedesktop.NetworkManager.VPN.Connection.c \ introspection/org.freedesktop.NetworkManager.VPN.Connection.h \ introspection/org.freedesktop.NetworkManager.VPN.Plugin.c \ - introspection/org.freedesktop.NetworkManager.VPN.Plugin.h + introspection/org.freedesktop.NetworkManager.VPN.Plugin.h \ + introspection/org.freedesktop.NetworkManager.c \ + introspection/org.freedesktop.NetworkManager.h \ + $(NULL) nodist_introspection_libnmdbus_la_SOURCES = $(introspection_sources) DBUS_INTERFACE_DOCS = \ docs/api/dbus-org.freedesktop.NetworkManager.AccessPoint.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.AgentManager.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Checkpoint.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ docs/api/dbus-org.freedesktop.NetworkManager.DHCP6Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Bluetooth.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Bond.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Lowpan.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.PPP.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.AgentManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.WiMax.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wpan.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsBridge.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsInterface.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsPort.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.OvsBridge.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.P2PWireless.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Ppp.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Settings.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.WiMax.xml \ docs/api/dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.IP4Config.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.Wpan.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Device.xml \ docs/api/dbus-org.freedesktop.NetworkManager.DnsManager.xml \ - docs/api/dbus-org.freedesktop.NetworkManager.Device.Lowpan.xml + docs/api/dbus-org.freedesktop.NetworkManager.IP4Config.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.P2PPeer.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.PPP.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.Settings.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + docs/api/dbus-org.freedesktop.NetworkManager.xml \ + $(NULL) introspection/%.c: introspection/%.xml @$(MKDIR_P) introspection/ @@ -566,6 +574,7 @@ dbusinterfaces_DATA = \ introspection/org.freedesktop.NetworkManager.Device.OvsInterface.xml \ introspection/org.freedesktop.NetworkManager.Device.OvsPort.xml \ introspection/org.freedesktop.NetworkManager.Device.OvsBridge.xml \ + introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml \ introspection/org.freedesktop.NetworkManager.Device.Ppp.xml \ introspection/org.freedesktop.NetworkManager.Device.Statistics.xml \ introspection/org.freedesktop.NetworkManager.Device.Team.xml \ @@ -584,6 +593,7 @@ dbusinterfaces_DATA = \ introspection/org.freedesktop.NetworkManager.IP4Config.xml \ introspection/org.freedesktop.NetworkManager.IP6Config.xml \ introspection/org.freedesktop.NetworkManager.xml \ + introspection/org.freedesktop.NetworkManager.P2PPeer.xml \ introspection/org.freedesktop.NetworkManager.PPP.xml \ introspection/org.freedesktop.NetworkManager.SecretAgent.xml \ introspection/org.freedesktop.NetworkManager.Settings.Connection.xml \ @@ -3240,24 +3250,30 @@ if WITH_WIFI core_plugins += src/devices/wifi/libnm-device-plugin-wifi.la src_devices_wifi_libnm_device_plugin_wifi_la_SOURCES = \ - src/devices/wifi/nm-wifi-factory.c \ + src/devices/wifi/nm-device-olpc-mesh.c \ + src/devices/wifi/nm-device-olpc-mesh.h \ + src/devices/wifi/nm-device-p2p-wifi.c \ + src/devices/wifi/nm-device-p2p-wifi.h \ src/devices/wifi/nm-device-wifi.c \ src/devices/wifi/nm-device-wifi.h \ src/devices/wifi/nm-wifi-ap.c \ src/devices/wifi/nm-wifi-ap.h \ - src/devices/wifi/nm-wifi-utils.c \ - src/devices/wifi/nm-wifi-utils.h \ src/devices/wifi/nm-wifi-common.c \ src/devices/wifi/nm-wifi-common.h \ - src/devices/wifi/nm-device-olpc-mesh.c \ - src/devices/wifi/nm-device-olpc-mesh.h + src/devices/wifi/nm-wifi-factory.c \ + src/devices/wifi/nm-wifi-p2p-peer.c \ + src/devices/wifi/nm-wifi-p2p-peer.h \ + src/devices/wifi/nm-wifi-utils.c \ + src/devices/wifi/nm-wifi-utils.h \ + $(NULL) if WITH_IWD src_devices_wifi_libnm_device_plugin_wifi_la_SOURCES += \ src/devices/wifi/nm-device-iwd.c \ src/devices/wifi/nm-device-iwd.h \ src/devices/wifi/nm-iwd-manager.c \ - src/devices/wifi/nm-iwd-manager.h + src/devices/wifi/nm-iwd-manager.h \ + $(NULL) endif src_devices_wifi_libnm_device_plugin_wifi_la_CPPFLAGS = $(src_cppflags_device_plugin) diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 8ba2453ee8..1241131a11 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -352,6 +352,7 @@ NM_UTILS_LOOKUP_STR_DEFINE (nmc_device_reason_to_string, NMDeviceStateReason, NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, N_("A duplicate IP address was detected")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, N_("The selected IP method is not supported")), NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, N_("Failed to configure SR-IOV parameters")), + NM_UTILS_LOOKUP_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, N_("The Wi-Fi P2P peer could not be found")), ) NM_UTILS_LOOKUP_STR_DEFINE (nm_active_connection_state_reason_to_string, NMActiveConnectionStateReason, diff --git a/docs/api/Makefile.am b/docs/api/Makefile.am index 2baf40562f..7ec77963f2 100644 --- a/docs/api/Makefile.am +++ b/docs/api/Makefile.am @@ -42,42 +42,43 @@ MKHTML_OPTIONS=--path="$(abs_srcdir)" content_files = \ $(GENERATED_FILES) \ dbus-org.freedesktop.NetworkManager.AccessPoint.xml \ + dbus-org.freedesktop.NetworkManager.AgentManager.xml \ dbus-org.freedesktop.NetworkManager.Connection.Active.xml \ - dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ dbus-org.freedesktop.NetworkManager.DHCP6Config.xml \ - dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ - dbus-org.freedesktop.NetworkManager.xml \ - dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ - dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ - dbus-org.freedesktop.NetworkManager.Device.xml \ - dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ dbus-org.freedesktop.NetworkManager.Device.Bluetooth.xml \ - dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ - dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ - dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ dbus-org.freedesktop.NetworkManager.Device.Bond.xml \ - dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ - dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ - dbus-org.freedesktop.NetworkManager.PPP.xml \ - dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ - dbus-org.freedesktop.NetworkManager.Device.Adsl.xml \ - dbus-org.freedesktop.NetworkManager.AgentManager.xml \ - dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ - dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ dbus-org.freedesktop.NetworkManager.Device.Bridge.xml \ - dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ - dbus-org.freedesktop.NetworkManager.DHCP4Config.xml \ + dbus-org.freedesktop.NetworkManager.Device.Dummy.xml \ dbus-org.freedesktop.NetworkManager.Device.Generic.xml \ + dbus-org.freedesktop.NetworkManager.Device.IPTunnel.xml \ dbus-org.freedesktop.NetworkManager.Device.Infiniband.xml \ + dbus-org.freedesktop.NetworkManager.Device.Macsec.xml \ + dbus-org.freedesktop.NetworkManager.Device.Macvlan.xml \ dbus-org.freedesktop.NetworkManager.Device.Modem.xml \ - dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + dbus-org.freedesktop.NetworkManager.Device.OlpcMesh.xml \ + dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + dbus-org.freedesktop.NetworkManager.Device.Team.xml \ + dbus-org.freedesktop.NetworkManager.Device.Tun.xml \ dbus-org.freedesktop.NetworkManager.Device.Veth.xml \ - dbus-org.freedesktop.NetworkManager.Settings.xml \ - dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + dbus-org.freedesktop.NetworkManager.Device.Vlan.xml \ + dbus-org.freedesktop.NetworkManager.Device.Vxlan.xml \ dbus-org.freedesktop.NetworkManager.Device.WireGuard.xml \ - dbus-org.freedesktop.NetworkManager.IP4Config.xml \ - dbus-org.freedesktop.NetworkManager.Device.Statistics.xml \ + dbus-org.freedesktop.NetworkManager.Device.P2PWireless.xml \ + dbus-org.freedesktop.NetworkManager.Device.Wired.xml \ + dbus-org.freedesktop.NetworkManager.Device.Wireless.xml \ + dbus-org.freedesktop.NetworkManager.Device.xml \ dbus-org.freedesktop.NetworkManager.DnsManager.xml \ + dbus-org.freedesktop.NetworkManager.IP4Config.xml \ + dbus-org.freedesktop.NetworkManager.IP6Config.xml \ + dbus-org.freedesktop.NetworkManager.PPP.xml \ + dbus-org.freedesktop.NetworkManager.SecretAgent.xml \ + dbus-org.freedesktop.NetworkManager.Settings.Connection.xml \ + dbus-org.freedesktop.NetworkManager.Settings.xml \ + dbus-org.freedesktop.NetworkManager.VPN.Connection.xml \ + dbus-org.freedesktop.NetworkManager.VPN.Plugin.xml \ + dbus-org.freedesktop.NetworkManager.xml \ $(top_builddir)/libnm-core/nm-dbus-types.xml \ $(top_builddir)/libnm-core/nm-vpn-dbus-types.xml \ $(top_builddir)/man/nmcli.xml \ diff --git a/docs/api/network-manager-docs.xml b/docs/api/network-manager-docs.xml index 06ac37415d..8b7c8c6bf9 100644 --- a/docs/api/network-manager-docs.xml +++ b/docs/api/network-manager-docs.xml @@ -206,6 +206,7 @@ + @@ -247,6 +248,12 @@ + + The <literal>/org/freedesktop/NetworkManager/P2PPeer/*</literal> objects + + + + The <literal>/org/freedesktop/NetworkManager/Checkpoint/*</literal> objects diff --git a/introspection/meson.build b/introspection/meson.build index ef2ad9c1af..e5bbe2a284 100644 --- a/introspection/meson.build +++ b/introspection/meson.build @@ -23,6 +23,7 @@ ifaces = [ 'org.freedesktop.NetworkManager.Device.OvsInterface', 'org.freedesktop.NetworkManager.Device.OvsPort', 'org.freedesktop.NetworkManager.Device.OvsBridge', + 'org.freedesktop.NetworkManager.Device.P2PWireless', 'org.freedesktop.NetworkManager.Device.Ppp', 'org.freedesktop.NetworkManager.Device.Statistics', 'org.freedesktop.NetworkManager.Device.Team', @@ -42,6 +43,7 @@ ifaces = [ 'org.freedesktop.NetworkManager.IP4Config', 'org.freedesktop.NetworkManager.IP6Config', 'org.freedesktop.NetworkManager', + 'org.freedesktop.NetworkManager.P2PPeer', 'org.freedesktop.NetworkManager.PPP', 'org.freedesktop.NetworkManager.SecretAgent', 'org.freedesktop.NetworkManager.Settings.Connection', diff --git a/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml new file mode 100644 index 0000000000..fa85b83f9d --- /dev/null +++ b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/introspection/org.freedesktop.NetworkManager.P2PPeer.xml b/introspection/org.freedesktop.NetworkManager.P2PPeer.xml new file mode 100644 index 0000000000..1a1cf71308 --- /dev/null +++ b/introspection/org.freedesktop.NetworkManager.P2PPeer.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index aac4d7eadd..924140edef 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -44,6 +44,7 @@ #define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired" #define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl" #define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless" +#define NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS NM_DBUS_INTERFACE_DEVICE ".P2PWireless" #define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth" #define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh" #define NM_DBUS_INTERFACE_DEVICE_OVS_INTERFACE NM_DBUS_INTERFACE_DEVICE ".OvsInterface" @@ -51,6 +52,8 @@ #define NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE NM_DBUS_INTERFACE_DEVICE ".OvsBridge" #define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint" #define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint" +#define NM_DBUS_PATH_P2P_PEER NM_DBUS_PATH "/P2PPeer" +#define NM_DBUS_INTERFACE_P2P_PEER NM_DBUS_INTERFACE ".P2PPeer" #define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem" #define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax" #define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp" @@ -563,6 +566,7 @@ typedef enum { * @NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE: a duplicate IP address was detected * @NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED: The selected IP method is not supported * @NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED: configuration of SR-IOV parameters failed + * @NM_DEVICE_STATE_REASON_PEER_NOT_FOUND: The Wi-Fi P2P peer could not be found * * Device state change reason codes */ @@ -634,6 +638,7 @@ typedef enum { NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE = 64, NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED = 65, NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED = 66, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND = 67, } NMDeviceStateReason; /** diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index 17cc454603..c2396d77c8 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -742,6 +742,7 @@ NM_UTILS_LOOKUP_STR_DEFINE (nm_device_state_reason_to_str, NMDeviceStateReason, NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_ADDRESS_DUPLICATE, "ip-address-duplicate"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_IP_METHOD_UNSUPPORTED, "ip-method-unsupported"), NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_SRIOV_CONFIGURATION_FAILED, "sriov-configuration-failed"), + NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_REASON_PEER_NOT_FOUND, "peer-not-found"), ); #define reason_to_string_a(reason) NM_UTILS_LOOKUP_STR_A (nm_device_state_reason_to_str, reason) diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build index dd2be5406b..d2b807fc95 100644 --- a/src/devices/wifi/meson.build +++ b/src/devices/wifi/meson.build @@ -1,13 +1,15 @@ common_sources = files( 'nm-wifi-ap.c', + 'nm-wifi-p2p-peer.c', 'nm-wifi-utils.c', ) sources = common_sources + files( - 'nm-wifi-factory.c', - 'nm-wifi-common.c', - 'nm-device-wifi.c', 'nm-device-olpc-mesh.c', + 'nm-device-p2p-wifi.c', + 'nm-device-wifi.c', + 'nm-wifi-common.c', + 'nm-wifi-factory.c', ) if enable_iwd diff --git a/src/devices/wifi/nm-device-p2p-wifi.c b/src/devices/wifi/nm-device-p2p-wifi.c new file mode 100644 index 0000000000..a57b2be089 --- /dev/null +++ b/src/devices/wifi/nm-device-p2p-wifi.c @@ -0,0 +1,1287 @@ +/* NetworkManager -- P2P Wi-Fi Device + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-device-p2p-wifi.h" + +#include + +#include "supplicant/nm-supplicant-manager.h" +#include "supplicant/nm-supplicant-interface.h" + +#include "nm-manager.h" +#include "nm-utils.h" +#include "nm-wifi-p2p-peer.h" +#include "NetworkManagerUtils.h" +#include "devices/nm-device-private.h" +#include "settings/nm-settings.h" +#include "nm-setting-p2p-wireless.h" +#include "nm-act-request.h" +#include "nm-ip4-config.h" +#include "platform/nm-platform.h" +#include "nm-manager.h" +#include "nm-core-internal.h" +#include "platform/nmp-object.h" + +#include "devices/nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceP2PWifi); + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceP2PWifi, + PROP_GROUP_OWNER, + //PROP_SSID, + //PROP_BSSID, + PROP_PEERS, + PROP_WFDIES, /* TODO: Make this a property of the setting and Find feature + * making the device stateless. + */ + + PROP_MGMT_IFACE, +); + +enum { + SCANNING_PROHIBITED, + + LAST_SIGNAL +}; + +//static guint signals[LAST_SIGNAL] = { 0 }; + +typedef struct { + NMSupplicantManager *sup_mgr; + + /* NOTE: In theory management and group ifaces could be identical. However, + * in practice, this cannot happen currently as NMDeviceP2PWifi is only + * created for existing non-P2P interfaces. + * (i.e. a single standalone P2P interface is not supported at this point) + */ + NMSupplicantInterface *mgmt_iface; + NMSupplicantInterface *group_iface; + + CList peers_lst_head; + GBytes *wfd_ies; + + guint sup_timeout_id; + guint peer_dump_id; + guint peer_missing_id; + + gboolean group_owner; +} NMDeviceP2PWifiPrivate; + +struct _NMDeviceP2PWifi { + NMDevice parent; + NMDeviceP2PWifiPrivate _priv; +}; + +struct _NMDeviceP2PWifiClass { + NMDeviceClass parent; +}; + +G_DEFINE_TYPE (NMDeviceP2PWifi, nm_device_p2p_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_P2P_WIFI_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceP2PWifi, NM_IS_DEVICE_P2P_WIFI, NMDevice) + +/*****************************************************************************/ + +static const NMDBusInterfaceInfoExtended interface_info_device_p2p_wifi; +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_added; +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_removed; + +static void supplicant_group_interface_release (NMDeviceP2PWifi *self); +static void supplicant_interfaces_release (NMDeviceP2PWifi *self); + +/*****************************************************************************/ + +static void +_peer_dump (NMDeviceP2PWifi *self, + NMLogLevel log_level, + const NMWifiP2PPeer *peer, + const char *prefix, + gint32 now_s) +{ + char buf[1024]; + + _NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-peer: %-7s %s", + prefix, + nm_wifi_p2p_peer_to_string (peer, buf, sizeof (buf), now_s)); +} + +static gboolean +peer_list_dump (gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->peer_dump_id = 0; + + if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) { + NMWifiP2PPeer *peer; + gint32 now_s = nm_utils_get_monotonic_timestamp_s (); + + _LOGD (LOGD_WIFI_SCAN, "P2P Peers: [now:%u]", now_s); + c_list_for_each_entry (peer, &priv->peers_lst_head, peers_lst) + _peer_dump (self, LOGL_DEBUG, peer, "dump", now_s); + } + return G_SOURCE_REMOVE; +} + +static void +schedule_peer_list_dump (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if ( !priv->peer_dump_id + && _LOGD_ENABLED (LOGD_WIFI_SCAN)) + priv->peer_dump_id = g_timeout_add_seconds (1, peer_list_dump, self); +} + +/*****************************************************************************/ + +static gboolean +check_connection_peer_joined (NMDeviceP2PWifi *device) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (device); + NMConnection *conn = nm_device_get_applied_connection (NM_DEVICE (device)); + NMWifiP2PPeer *peer; + const char* group; + const char * const * groups; + + if (!conn || !priv->group_iface) + return FALSE; + + /* Comparing the object path found on the group_iface with the peers + * found on the mgmt_iface is legal. */ + group = nm_supplicant_interface_get_p2p_group_path (priv->group_iface); + if (!group) + return FALSE; + + /* NOTE: We currently only support connections to a specific peer */ + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, conn); + if (!peer) + return FALSE; + + groups = nm_wifi_p2p_peer_get_groups (peer); + if ( !groups + || !g_strv_contains (groups, group)) + return FALSE; + + return TRUE; +} + +static gboolean +disconnect_on_connection_peer_missing_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + _LOGW (LOGD_WIFI, "Peer requested in connection is missing for too long, failing connection."); + + priv->peer_missing_id = 0; + + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return FALSE; +} + +static void +update_disconnect_on_connection_peer_missing (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMDeviceState state; + + state = nm_device_get_state (NM_DEVICE (self)); + if ( state < NM_DEVICE_STATE_IP_CONFIG + || state > NM_DEVICE_STATE_ACTIVATED) { + nm_clear_g_source (&priv->peer_missing_id); + return; + } + + if (check_connection_peer_joined (self)) { + if (nm_clear_g_source (&priv->peer_missing_id)) + _LOGD (LOGD_WIFI, "Peer requested in connection is joined, removing timeout"); + return; + } + + if (priv->peer_missing_id == 0) { + _LOGD (LOGD_WIFI, "Peer requested in connection is missing, adding timeout"); + priv->peer_missing_id = g_timeout_add_seconds (5, disconnect_on_connection_peer_missing_cb, self); + } +} + +static gboolean +is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMSupplicantInterfaceState supplicant_state; + + if (!priv->mgmt_iface) + return FALSE; + + supplicant_state = nm_supplicant_interface_get_state (priv->mgmt_iface); + if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_READY + || supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) + return FALSE; + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->check_connection_compatible (device, connection, error)) + return FALSE; + + /* TODO: Allow limitting the interface using the HW-address? */ + + /* We don't need to check anything else here. The P2P device will only + * exists if we are able to establish a P2P connection, and there should + * be no further restrictions necessary. + */ + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + NMConnection *const*existing_connections, + GError **error) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + gs_free char *setting_name = NULL; + NMSettingP2PWireless *s_p2p_wireless; + NMWifiP2PPeer *peer; + const char *setting_peer; + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + + if (!specific_object) { + /* If not given a specific object, we need at minimum a peer address */ + if (!s_p2p_wireless) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'p2p-wireless' setting is required if no Peer path was given."); + return FALSE; + } + + setting_peer = nm_setting_p2p_wireless_get_peer (s_p2p_wireless); + if (!setting_peer) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'p2p-wireless' setting with a valid Peer is required if no Peer path was given."); + return FALSE; + } + + } else { + peer = nm_wifi_p2p_peer_lookup_for_device (NM_DEVICE (self), specific_object); + if (!peer) { + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, + "The P2P peer %s is unknown.", + specific_object); + return FALSE; + } + + setting_peer = nm_wifi_p2p_peer_get_address (peer); + g_assert (setting_peer); + } + + /* Add a P2P wifi setting if one doesn't exist yet */ + if (!s_p2p_wireless) { + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_setting_p2p_wireless_new ()); + nm_connection_add_setting (connection, NM_SETTING (s_p2p_wireless)); + } + + g_object_set (G_OBJECT (s_p2p_wireless), NM_SETTING_P2P_WIRELESS_PEER, setting_peer, NULL); + + setting_name = g_strdup_printf ("P2P Peer %s", setting_peer); + nm_utils_complete_generic (nm_device_get_platform (device), + connection, + NM_SETTING_P2P_WIRELESS_SETTING_NAME, + existing_connections, + setting_name, + setting_name, + NULL, + TRUE); + + return TRUE; +} + +/* + * supplicant_find_timeout_cb + * + * Called when the supplicant has been unable to find the peer we want to connect to. + */ +static gboolean +supplicant_find_timeout_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->sup_timeout_id = 0; + + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (nm_device_is_activating (device)) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, + "Activation: (p2p-wifi) could not find peer, failing activation"); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + } + + return G_SOURCE_REMOVE; +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMActStageReturn ret; + NMActRequest *req; + NMConnection *connection; + NMSettingP2PWireless *s_p2p_wireless; + NMWifiP2PPeer *peer; + + nm_clear_g_source (&priv->sup_timeout_id); + + ret = NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage1_prepare (device, out_failure_reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + if (!priv->mgmt_iface) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + req = nm_device_get_act_request (NM_DEVICE (self)); + g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_applied_connection (req); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + g_return_val_if_fail (s_p2p_wireless, NM_ACT_STAGE_RETURN_FAILURE); + + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (!peer) { + /* Set up a timeout on the find attempt and run a find for the same period of time */ + priv->sup_timeout_id = g_timeout_add_seconds (10, + supplicant_find_timeout_cb, + self); + + nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10); + + return NM_ACT_STAGE_RETURN_POSTPONE; + } + + /* TODO: Set WFD IEs on supplicant manager here! */ + + return NM_ACT_STAGE_RETURN_SUCCESS; +} + +static void +cleanup_p2p_connect_attempt (NMDeviceP2PWifi *self, gboolean disconnect) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->peer_missing_id); + + if (priv->mgmt_iface) + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (disconnect && priv->group_iface) + nm_supplicant_interface_p2p_disconnect (priv->group_iface); +} + +/* + * supplicant_connection_timeout_cb + * + * Called when the supplicant has been unable to connect to a peer + * within a specified period of time. + */ +static gboolean +supplicant_connection_timeout_cb (gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + priv->sup_timeout_id = 0; + + nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface); + + if (nm_device_is_activating (device)) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, + "Activation: (p2p-wifi) connecting took too long, failing activation"); + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + } + + return G_SOURCE_REMOVE; +} + +static NMActStageReturn +act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMConnection *connection; + NMWifiP2PPeer *peer; + + nm_clear_g_source (&priv->sup_timeout_id); + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + nm_assert (NM_IS_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS))); + + /* The prepare stage ensures that the peer has been found */ + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (!peer) { + NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_PEER_NOT_FOUND); + return NM_ACT_STAGE_RETURN_FAILURE; + } + + /* TODO: Grab secrets if we don't have them yet! */ + + /* TODO: Fix "pbc" being hardcoded here! */ + nm_supplicant_interface_p2p_connect (priv->mgmt_iface, + nm_wifi_p2p_peer_get_supplicant_path (peer), + "pbc", NULL); + + /* Set up a timeout on the connect attempt */ + priv->sup_timeout_id = g_timeout_add_seconds (45, + supplicant_connection_timeout_cb, + self); + + /* We'll get stage3 started when the P2P group has been started */ + return NM_ACT_STAGE_RETURN_POSTPONE; +} + +/*****************************************************************************/ + +static void +emit_signal_p2p_peer_add_remove (NMDeviceP2PWifi *device, + NMWifiP2PPeer *peer, + gboolean is_added /* or else is_removed */) +{ + nm_dbus_object_emit_signal (NM_DBUS_OBJECT (device), + &interface_info_device_p2p_wifi, + is_added + ? &nm_signal_info_p2p_wireless_peer_added + : &nm_signal_info_p2p_wireless_peer_removed, + "(o)", + nm_dbus_object_get_path (NM_DBUS_OBJECT (peer))); +} + +static void +peer_add_remove (NMDeviceP2PWifi *self, + gboolean is_adding, /* or else removing */ + NMWifiP2PPeer *peer, + gboolean recheck_available_connections) +{ + NMDevice *device = NM_DEVICE (self); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if (is_adding) { + g_object_ref (peer); + peer->wifi_device = device; + c_list_link_tail (&priv->peers_lst_head, &peer->peers_lst); + nm_dbus_object_export (NM_DBUS_OBJECT (peer)); + _peer_dump (self, LOGL_DEBUG, peer, "added", 0); + + emit_signal_p2p_peer_add_remove (self, peer, TRUE); + } else { + peer->wifi_device = NULL; + c_list_unlink (&peer->peers_lst); + _peer_dump (self, LOGL_DEBUG, peer, "removed", 0); + } + + _notify (self, PROP_PEERS); + + if (!is_adding) { + emit_signal_p2p_peer_add_remove (self, peer, FALSE); + nm_dbus_object_clear_and_unexport (&peer); + } + + if (is_adding) { + /* If we are in prepare state, then we are currently runnign a find + * to search for the requested peer. */ + if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) { + NMConnection *connection; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + + peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection); + if (peer) { + /* A peer for the connection was found, cancel the timeout and go to configure state. */ + nm_clear_g_source (&priv->sup_timeout_id); + nm_device_activate_schedule_stage2_device_config (device); + } + } + + /* TODO: We may want to re-check auto-activation here, otherwise it will never work. */ + } + + update_disconnect_on_connection_peer_missing (self); + +#if 0 + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); + if (recheck_available_connections) + nm_device_recheck_available_connections (NM_DEVICE (self)); +#endif +} + +static void +remove_all_peers (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMWifiP2PPeer *peer; + + if (c_list_is_empty (&priv->peers_lst_head)) + return; + + while ((peer = c_list_first_entry (&priv->peers_lst_head, NMWifiP2PPeer, peers_lst))) + peer_add_remove (self, FALSE, peer, FALSE); + + nm_device_recheck_available_connections (NM_DEVICE (self)); +} + +/*****************************************************************************/ + + +static NMActStageReturn +act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMConnection *connection; + NMSettingIPConfig *s_ip4; + const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_ip4 = nm_connection_get_setting_ip4_config (connection); + if (s_ip4) + method = nm_setting_ip_config_get_method (s_ip4); + + /* Indicate that a critical protocol is about to start */ + if ( !priv->group_owner + && nm_streq (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage3_ip4_config_start (device, out_config, out_failure_reason); +} + +static NMActStageReturn +act_stage3_ip6_config_start (NMDevice *device, + NMIP6Config **out_config, + NMDeviceStateReason *out_failure_reason) +{ + NMConnection *connection; + NMSettingIPConfig *s_ip6; + const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; + + connection = nm_device_get_applied_connection (device); + g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE); + + s_ip6 = nm_connection_get_setting_ip6_config (connection); + if (s_ip6) + method = nm_setting_ip_config_get_method (s_ip6); + + /* Indicate that a critical protocol is about to start */ + if (NM_IN_STRSET (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO + NM_SETTING_IP6_CONFIG_METHOD_DHCP)) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), TRUE); + + return NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->act_stage3_ip6_config_start (device, out_config, out_failure_reason); +} + +static void +deactivate (NMDevice *device) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + int ifindex = nm_device_get_ip_ifindex (device); + + cleanup_p2p_connect_attempt (self, TRUE); + + /* Clear any critical protocol notification in the Wi-Fi stack */ + if (ifindex > 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), ifindex, FALSE); +} + +static guint32 +get_configured_mtu (NMDevice *device, NMDeviceMtuSource *out_source) +{ + *out_source = NM_DEVICE_MTU_SOURCE_NONE; + return 0; +} + +static const char * +get_auto_ip_config_method (NMDevice *device, int addr_family) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + /* Override the AUTO method to mean shared if we are group owner. */ + if ( priv->group_iface + && nm_supplicant_interface_get_p2p_group_owner (priv->group_iface)) { + if (addr_family == AF_INET) + return NM_SETTING_IP4_CONFIG_METHOD_SHARED; + + if (addr_family == AF_INET6) + return NM_SETTING_IP6_CONFIG_METHOD_SHARED; + } + + return NULL; +} + +static gboolean +unmanaged_on_quit (NMDevice *self) +{ + return TRUE; +} + +static void +supplicant_iface_state_cb (NMSupplicantInterface *iface, + int new_state_i, + int old_state_i, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDevice *device = NM_DEVICE (self); + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; + + if (new_state == old_state) + return; + + _LOGI (LOGD_DEVICE | LOGD_WIFI, + "supplicant management interface state: %s -> %s", + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + _LOGD (LOGD_WIFI, "supplicant ready"); + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + + supplicant_interfaces_release (self); + break; + default: + break; + } +} + +static void +supplicant_iface_peer_updated_cb (NMSupplicantInterface *iface, + const char *object_path, + GVariant *properties, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + NMWifiP2PPeer *found_peer; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + found_peer = nm_wifi_p2p_peers_find_by_supplicant_path (&priv->peers_lst_head, object_path); + if (found_peer) { + if (!nm_wifi_p2p_peer_update_from_properties (found_peer, object_path, properties)) + return; + + update_disconnect_on_connection_peer_missing (self); + _peer_dump (self, LOGL_DEBUG, found_peer, "updated", 0); + } else { + gs_unref_object NMWifiP2PPeer *peer = NULL; + + peer = nm_wifi_p2p_peer_new_from_properties (object_path, properties); + if (!peer) { + _LOGD (LOGD_WIFI, "invalid P2P peer properties received for %s", object_path); + return; + } + + peer_add_remove (self, TRUE, peer, TRUE); + } + + schedule_peer_list_dump (self); +} + +static void +supplicant_iface_peer_removed_cb (NMSupplicantInterface *iface, + const char *object_path, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + NMWifiP2PPeer *peer; + + g_return_if_fail (self != NULL); + g_return_if_fail (object_path != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + peer = nm_wifi_p2p_peers_find_by_supplicant_path (&priv->peers_lst_head, object_path); + if (!peer) + return; + + peer_add_remove (self, FALSE, peer, TRUE); + schedule_peer_list_dump (self); +} + +static void +check_group_iface_ready (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self);; + + if (!priv->group_iface) + return; + + if (nm_supplicant_interface_get_state (priv->group_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + return; + + if (!nm_supplicant_interface_get_p2p_group_joined (priv->group_iface)) + return; + + nm_clear_g_source (&priv->sup_timeout_id); + update_disconnect_on_connection_peer_missing (self); + + nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); +} + +static void +supplicant_group_iface_state_cb (NMSupplicantInterface *iface, + int new_state_i, + int old_state_i, + int disconnect_reason, + gpointer user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + NMSupplicantInterfaceState new_state = new_state_i; + NMSupplicantInterfaceState old_state = old_state_i; + + if (new_state == old_state) + return; + + _LOGI (LOGD_DEVICE | LOGD_WIFI, + "P2P Group supplicant interface state: %s -> %s", + nm_supplicant_interface_state_to_string (old_state), + nm_supplicant_interface_state_to_string (new_state)); + + switch (new_state) { + case NM_SUPPLICANT_INTERFACE_STATE_READY: + _LOGD (LOGD_WIFI, "P2P Group supplicant ready"); + + if (!nm_device_set_ip_iface (device, nm_supplicant_interface_get_ifname (priv->group_iface))) { + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED); + break; + } + + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + + check_group_iface_ready (self); + break; + case NM_SUPPLICANT_INTERFACE_STATE_DOWN: + supplicant_group_interface_release (self); + + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + break; + default: + break; + } +} + +static void +supplicant_group_iface_group_finished_cb (NMSupplicantInterface *iface, + void *user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + + supplicant_group_interface_release (self); + + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); +} + +static void +supplicant_iface_group_joined_updated_cb (NMSupplicantInterface *iface, + GParamSpec *pspec, + void *user_data) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (user_data); + + check_group_iface_ready (self); +} + +static void +supplicant_iface_group_started_cb (NMSupplicantInterface *iface, + NMSupplicantInterface *group_iface, + NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + if (!nm_device_is_activating (NM_DEVICE (self))) { + _LOGW (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant notified a group start but we are not trying to connect! Ignoring the event."); + return; + } + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + supplicant_group_interface_release (self); + priv->group_iface = g_object_ref (group_iface); + + /* We need to wait for the interface to be ready and the group + * information to be resolved. */ + g_signal_connect (priv->group_iface, + "notify::" NM_SUPPLICANT_INTERFACE_P2P_GROUP_JOINED, + G_CALLBACK (supplicant_iface_group_joined_updated_cb), + self); + + g_signal_connect (priv->group_iface, + NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_group_iface_state_cb), + self); + + g_signal_connect (priv->group_iface, NM_SUPPLICANT_INTERFACE_GROUP_FINISHED, + G_CALLBACK (supplicant_group_iface_group_finished_cb), + self); + + if (nm_supplicant_interface_get_state (priv->group_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + + check_group_iface_ready (self); +} + +static void +supplicant_group_interface_release (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if (priv->group_iface) { + /* Tell the supplicant to disconnect from the current Group/Peer */ + nm_supplicant_interface_p2p_disconnect (priv->group_iface); + + /* Clear supplicant interface signal handlers */ + g_signal_handlers_disconnect_by_data (priv->group_iface, self); + + g_clear_object (&priv->group_iface); + } +} + +static void +supplicant_interfaces_release (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv; + + g_return_if_fail (self != NULL); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: Releasing WPA supplicant interfaces."); + + nm_clear_g_source (&priv->peer_dump_id); + remove_all_peers (self); + + if (priv->mgmt_iface) { + /* Clear supplicant interface signal handlers */ + g_signal_handlers_disconnect_by_data (priv->mgmt_iface, self); + + g_clear_object (&priv->mgmt_iface); + + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + } + + supplicant_group_interface_release (self); +} + +static void +device_state_changed (NMDevice *device, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + +#if 0 + if (new_state > NM_DEVICE_STATE_ACTIVATED) + wifi_secrets_cancel (self); +#endif + + update_disconnect_on_connection_peer_missing (self); + + if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) { + /* Clean up the supplicant interface because in these states the + * device cannot be used. + * Do not clean up for the UNMANAGED to UNAVAILABLE transition which + * will happen during initialization. + */ + if (priv->mgmt_iface && old_state > new_state) + supplicant_interfaces_release (self); + + /* TODO: More cleanup needed? */ + } else + nm_assert (priv->mgmt_iface != NULL); + + switch (new_state) { + case NM_DEVICE_STATE_UNMANAGED: + break; + case NM_DEVICE_STATE_UNAVAILABLE: + if (!priv->mgmt_iface || nm_supplicant_interface_get_state (priv->mgmt_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_add_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); + + break; + case NM_DEVICE_STATE_NEED_AUTH: + /* Disconnect? */ + break; + case NM_DEVICE_STATE_IP_CHECK: + /* Clear any critical protocol notification in the wifi stack */ + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), FALSE); + break; + case NM_DEVICE_STATE_ACTIVATED: + //activation_success_handler (device); + break; + case NM_DEVICE_STATE_FAILED: + /* Clear any critical protocol notification in the wifi stack. + * At this point the IP device may have been removed already. */ + if (nm_device_get_ip_ifindex (device) > 0) + nm_platform_wifi_indicate_addressing_running (nm_device_get_platform (device), nm_device_get_ip_ifindex (device), FALSE); + break; + case NM_DEVICE_STATE_DISCONNECTED: + break; + default: + break; + } +} + +/*****************************************************************************/ + +NMSupplicantInterface * +nm_device_p2p_wifi_get_mgmt_iface (NMDeviceP2PWifi *self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + return priv->mgmt_iface; +} + +void +nm_device_p2p_wifi_set_mgmt_iface (NMDeviceP2PWifi *self, + NMSupplicantInterface *iface) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + /* Don't do anything if nothing changed. */ + if (priv->mgmt_iface == iface) + return; + + supplicant_interfaces_release (self); + + if (iface == NULL) { + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant management interface cleared."); + return; + } + + _LOGD (LOGD_DEVICE | LOGD_WIFI, "P2P: WPA supplicant management interface changed to %s.", nm_supplicant_interface_get_object_path (iface)); + + priv->mgmt_iface = g_object_ref (iface); + + /* We are not waiting on the supplicant anymore if the state is ready. */ + if (nm_supplicant_interface_get_state (priv->mgmt_iface) >= NM_SUPPLICANT_INTERFACE_STATE_READY) + nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE); + + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_STATE, + G_CALLBACK (supplicant_iface_state_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_PEER_UPDATED, + G_CALLBACK (supplicant_iface_peer_updated_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_PEER_REMOVED, + G_CALLBACK (supplicant_iface_peer_removed_cb), + self, + 0); + g_signal_connect_object (priv->mgmt_iface, NM_SUPPLICANT_INTERFACE_GROUP_STARTED, + G_CALLBACK (supplicant_iface_group_started_cb), + self, + 0); +} + +void +nm_device_p2p_wifi_remove (NMDeviceP2PWifi* self) +{ + g_signal_emit_by_name (self, NM_DEVICE_REMOVED); +} + +/*****************************************************************************/ + +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( + "PeerAdded", + .args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("peer", "o"), + ), +); + +static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT ( + "PeerRemoved", + .args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("peer", "o"), + ), +); + +static const NMDBusInterfaceInfoExtended interface_info_device_p2p_wifi = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS, + .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( + &nm_signal_info_p2p_wireless_peer_added, + &nm_signal_info_p2p_wireless_peer_removed, + ), + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("HwAddress", "s", NM_DEVICE_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("GroupOwner", "b", NM_DEVICE_P2P_WIFI_GROUP_OWNER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Peers", "ao", NM_DEVICE_P2P_WIFI_PEERS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("WFDIEs", "ay", NM_DEVICE_P2P_WIFI_WFDIES), + ), + ), + .legacy_property_changed = FALSE, +}; + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + const char **list; + + switch (prop_id) { + case PROP_MGMT_IFACE: + g_value_set_object (value, priv->mgmt_iface); + break; + case PROP_GROUP_OWNER: + g_value_set_boolean (value, priv->group_owner); + break; + case PROP_PEERS: + list = nm_wifi_p2p_peers_get_paths (&priv->peers_lst_head); + g_value_take_boxed (value, nm_utils_strv_make_deep_copied (list)); + break; + case PROP_WFDIES: + g_value_take_variant (value, nm_utils_gbytes_to_variant_ay (priv->wfd_ies)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + + switch (prop_id) { + case PROP_MGMT_IFACE: + /* construct-only */ + nm_device_p2p_wifi_set_mgmt_iface (self, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_device_p2p_wifi_init (NMDeviceP2PWifi * self) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + c_list_init (&priv->peers_lst_head); +} + +static void +constructed (GObject *object) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->constructed (object); + + /* Connect to the supplicant manager */ + priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ()); + + nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE); +} + +NMDevice* +nm_device_p2p_wifi_new (NMSupplicantInterface *mgmt_iface, const char *iface) +{ + return g_object_new (NM_TYPE_DEVICE_P2P_WIFI, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "802.11 P2P WiFi", + NM_DEVICE_DEVICE_TYPE, NM_TYPE_DEVICE_P2P_WIFI, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, + NM_DEVICE_P2P_WIFI_MGMT_IFACE, mgmt_iface, + NULL); +} + +static void +dispose (GObject *object) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (object); + + g_clear_object (&priv->sup_mgr); + + supplicant_interfaces_release (self); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceP2PWifi *peer = NM_DEVICE_P2P_WIFI (object); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (peer); + + nm_assert (c_list_is_empty (&priv->peers_lst_head)); + + g_bytes_unref (priv->wfd_ies); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->finalize (object); +} + +static void +nm_device_p2p_wifi_class_init (NMDeviceP2PWifiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_device_p2p_wifi); + + device_class->connection_type_supported = NM_SETTING_P2P_WIRELESS_SETTING_NAME; + device_class->connection_type_check_compatible = NM_SETTING_P2P_WIRELESS_SETTING_NAME; + device_class->link_types = NM_DEVICE_DEFINE_LINK_TYPES (NM_LINK_TYPE_P2P_WIFI); + + /* Do we need compatibility checking or is the default good enough? */ + device_class->is_available = is_available; + device_class->check_connection_compatible = check_connection_compatible; + device_class->complete_connection = complete_connection; + + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->act_stage2_config = act_stage2_config; + device_class->get_configured_mtu = get_configured_mtu; + device_class->get_auto_ip_config_method = get_auto_ip_config_method; + device_class->act_stage3_ip4_config_start = act_stage3_ip4_config_start; + device_class->act_stage3_ip6_config_start = act_stage3_ip6_config_start; + + device_class->deactivate = deactivate; + device_class->unmanaged_on_quit = unmanaged_on_quit; + + device_class->state_changed = device_state_changed; + + /*klass->scanning_prohibited = scanning_prohibited;*/ + + obj_properties[PROP_GROUP_OWNER] = + g_param_spec_boolean (NM_DEVICE_P2P_WIFI_GROUP_OWNER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_PEERS] = + g_param_spec_boxed (NM_DEVICE_P2P_WIFI_PEERS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WFDIES] = + g_param_spec_variant (NM_DEVICE_P2P_WIFI_WFDIES, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MGMT_IFACE] = + g_param_spec_object (NM_DEVICE_P2P_WIFI_MGMT_IFACE, "", "", + NM_TYPE_SUPPLICANT_INTERFACE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + /* obj_properties[PROP_SCANNING] = */ + /* g_param_spec_boolean (NM_DEVICE_WIFI_SCANNING, "", "", */ + /* FALSE, */ + /* G_PARAM_READABLE | */ + /* G_PARAM_STATIC_STRINGS); */ + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} diff --git a/src/devices/wifi/nm-device-p2p-wifi.h b/src/devices/wifi/nm-device-p2p-wifi.h new file mode 100644 index 0000000000..128914e055 --- /dev/null +++ b/src/devices/wifi/nm-device-p2p-wifi.h @@ -0,0 +1,56 @@ +/* NetworkManager -- P2P Wi-Fi Device + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2018 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_P2P_WIFI_H__ +#define __NM_DEVICE_P2P_WIFI_H__ + +#include "devices/nm-device.h" +#include "supplicant/nm-supplicant-interface.h" + +#define NM_TYPE_DEVICE_P2P_WIFI (nm_device_p2p_wifi_get_type ()) +#define NM_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifi)) +#define NM_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) +#define NM_IS_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_IS_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_DEVICE_P2P_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) + +#define NM_DEVICE_P2P_WIFI_GROUP_OWNER "group-owner" +#define NM_DEVICE_P2P_WIFI_PEERS "peers" +#define NM_DEVICE_P2P_WIFI_GROUPS "groups" +#define NM_DEVICE_P2P_WIFI_WFDIES "WFDIEs" + +#define NM_DEVICE_P2P_WIFI_MGMT_IFACE "mgmt-iface" + + +typedef struct _NMDeviceP2PWifi NMDeviceP2PWifi; +typedef struct _NMDeviceP2PWifiClass NMDeviceP2PWifiClass; + +GType nm_device_p2p_wifi_get_type (void); + +NMDevice* nm_device_p2p_wifi_new (NMSupplicantInterface *mgmt_iface, + const char* iface); + +NMSupplicantInterface * nm_device_p2p_wifi_get_mgmt_iface (NMDeviceP2PWifi *self); +void nm_device_p2p_wifi_set_mgmt_iface (NMDeviceP2PWifi *self, + NMSupplicantInterface *iface); + +void nm_device_p2p_wifi_remove (NMDeviceP2PWifi *self); + +#endif /* __NM_DEVICE_P2P_WIFI_H__ */ diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/devices/wifi/nm-wifi-p2p-peer.c new file mode 100644 index 0000000000..417365907c --- /dev/null +++ b/src/devices/wifi/nm-wifi-p2p-peer.c @@ -0,0 +1,808 @@ +/* NetworkManager -- P2P Wi-Fi Peer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-wifi-p2p-peer.h" + +#include +#include + +#include "nm-setting-wireless.h" + +#include "nm-wifi-utils.h" +#include "NetworkManagerUtils.h" +#include "nm-utils.h" +#include "nm-core-internal.h" +#include "platform/nm-platform.h" +#include "devices/nm-device.h" +#include "nm-dbus-manager.h" + +/*****************************************************************************/ + +NM_GOBJECT_PROPERTIES_DEFINE (NMWifiP2PPeer, + PROP_NAME, + PROP_MANUFACTURER, + PROP_MODEL, + PROP_MODEL_NUMBER, + PROP_SERIAL, + //PROP_PRIMARY_DEVICE_TYPE, { "PrimaryDeviceType", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay", + // "devicecapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + // "groupcapability", WPAS_DBUS_NEW_IFACE_P2P_PEER, "y", + // "SecondaryDeviceTypes", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + // "VendorExtension", WPAS_DBUS_NEW_IFACE_P2P_PEER, "aay", + PROP_WFD_IES, + PROP_GROUPS, + + PROP_HW_ADDRESS, + //PROP_MODE, + PROP_STRENGTH, + PROP_LAST_SEEN, + + //PROP_MAX_BITRATE, + // One of the following (FLAGS would simply mirror/use the same as AP flags) + PROP_FLAGS, + //PROP_CONFIG_METHOD, +); + +struct _NMWifiP2PPeerPrivate { + char *supplicant_path; /* D-Bus object path of this Peer from wpa_supplicant */ + + /* Scanned or cached values */ + char * name; + char * manufacturer; + char * model; + char * model_number; + char * serial; + + char * address; + + GBytes * wfd_ies; + char ** groups; + + guint8 strength; + + NM80211ApFlags flags; /* General flags */ + + /* Non-scanned attributes */ + gint32 last_seen; /* Timestamp when the Peer was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ +}; + +typedef struct _NMWifiP2PPeerPrivate NMWifiP2PPeerPrivate; + +struct _NMWifiP2PPeerClass { + NMDBusObjectClass parent; +}; + +G_DEFINE_TYPE (NMWifiP2PPeer, nm_wifi_p2p_peer, NM_TYPE_DBUS_OBJECT) + +#define NM_WIFI_P2P_PEER_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMWifiP2PPeer, NM_IS_WIFI_P2P_PEER) + +/*****************************************************************************/ + +const char * +nm_wifi_p2p_peer_get_supplicant_path (NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->supplicant_path; +} + +const char * +nm_wifi_p2p_peer_get_name (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->name; +} + +gboolean +nm_wifi_p2p_peer_set_name (NMWifiP2PPeer *peer, const char *name) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (name, priv->name) == 0) + return FALSE; + + g_clear_pointer (&priv->name, g_free); + if (name) + priv->name = g_strdup (name); + + _notify (peer, PROP_NAME); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_manufacturer (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->manufacturer; +} + +gboolean +nm_wifi_p2p_peer_set_manufacturer (NMWifiP2PPeer *peer, const char *manufacturer) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (manufacturer, priv->manufacturer) == 0) + return FALSE; + + g_clear_pointer (&priv->manufacturer, g_free); + if (manufacturer) + priv->manufacturer = g_strdup (manufacturer); + + _notify (peer, PROP_MANUFACTURER); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_model (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model; +} + +gboolean +nm_wifi_p2p_peer_set_model (NMWifiP2PPeer *peer, const char *model) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (model, priv->model) == 0) + return FALSE; + + g_clear_pointer (&priv->model, g_free); + if (model) + priv->model = g_strdup (model); + + _notify (peer, PROP_MODEL); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_model_number (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model_number; +} + +gboolean +nm_wifi_p2p_peer_set_model_number (NMWifiP2PPeer *peer, const char *model_number) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (model_number, priv->model_number) == 0) + return FALSE; + + g_clear_pointer (&priv->model_number, g_free); + if (model_number) + priv->model_number = g_strdup (model_number); + + _notify (peer, PROP_MODEL_NUMBER); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_serial (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->serial; +} + +gboolean +nm_wifi_p2p_peer_set_serial (NMWifiP2PPeer *peer, const char *serial) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if (g_strcmp0 (serial, priv->serial) == 0) + return FALSE; + + g_clear_pointer (&priv->serial, g_free); + if (serial) + priv->serial = g_strdup (serial); + + _notify (peer, PROP_SERIAL); + return TRUE; +} + +GBytes * +nm_wifi_p2p_peer_get_wfd_ies (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->wfd_ies; +} + +gboolean +nm_wifi_p2p_peer_set_wfd_ies (NMWifiP2PPeer *peer, GBytes *wfd_ies) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (nm_gbytes_equal0 (priv->wfd_ies, wfd_ies)) + return FALSE; + + g_bytes_unref (priv->wfd_ies); + priv->wfd_ies = wfd_ies ? g_bytes_ref (wfd_ies) : NULL; + + _notify (peer, PROP_WFD_IES); + return TRUE; +} + +const char *const* +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; +} + +static gboolean +nm_wifi_p2p_peer_set_groups (NMWifiP2PPeer *peer, const char** groups) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + g_return_val_if_fail (groups != NULL, FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (_nm_utils_strv_equal (priv->groups, (char **) groups)) + return FALSE; + + g_strfreev (priv->groups); + priv->groups = g_strdupv ((char**) groups); + + _notify (peer, PROP_GROUPS); + return TRUE; +} + +const char * +nm_wifi_p2p_peer_get_address (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->address; +} + +static gboolean +nm_wifi_p2p_peer_set_address_bin (NMWifiP2PPeer *peer, const guint8 addr[static ETH_ALEN]) +{ + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if ( priv->address + && nm_utils_hwaddr_matches (addr, ETH_ALEN, priv->address, -1)) + return FALSE; + + g_free (priv->address); + priv->address = nm_utils_hwaddr_ntoa (addr, ETH_ALEN); + _notify (peer, PROP_HW_ADDRESS); + return TRUE; +} + +gboolean +nm_wifi_p2p_peer_set_address (NMWifiP2PPeer *peer, const char *addr) +{ + guint8 addr_buf[ETH_ALEN]; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + if ( !addr + || !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf))) + g_return_val_if_reached (FALSE); + + return nm_wifi_p2p_peer_set_address_bin (peer, addr_buf); +} + +gint8 +nm_wifi_p2p_peer_get_strength (NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), 0); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->strength; +} + +gboolean +nm_wifi_p2p_peer_set_strength (NMWifiP2PPeer *peer, const gint8 strength) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (priv->strength != strength) { + priv->strength = strength; + _notify (peer, PROP_STRENGTH); + return TRUE; + } + return FALSE; +} + +NM80211ApFlags +nm_wifi_p2p_peer_get_flags (const NMWifiP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NM_802_11_AP_FLAGS_NONE); + + return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->flags; +} + +static gboolean +nm_wifi_p2p_peer_set_last_seen (NMWifiP2PPeer *peer, gint32 last_seen) +{ + NMWifiP2PPeerPrivate *priv; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + if (priv->last_seen != last_seen) { + priv->last_seen = last_seen; + _notify (peer, PROP_LAST_SEEN); + return TRUE; + } + return FALSE; +} + + +/*****************************************************************************/ + +gboolean +nm_wifi_p2p_peer_update_from_properties (NMWifiP2PPeer *peer, + const char *supplicant_path, + GVariant *properties) +{ + NMWifiP2PPeerPrivate *priv; + const guint8 *bytes; + GVariant *v; + gsize len; + const char *s; + const char **sv; + gint32 i32; + gboolean changed = FALSE; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), FALSE); + g_return_val_if_fail (properties, FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer); + + g_object_freeze_notify (G_OBJECT (peer)); + + if (g_variant_lookup (properties, "level", "i", &i32)) + changed |= nm_wifi_p2p_peer_set_strength (peer, nm_wifi_utils_level_to_quality (i32)); + + if (g_variant_lookup (properties, "DeviceName", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_name (peer, s); + + if (g_variant_lookup (properties, "Manufacturer", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_manufacturer (peer, s); + + if (g_variant_lookup (properties, "Model", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_model (peer, s); + + if (g_variant_lookup (properties, "ModelNumber", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_model_number (peer, s); + + if (g_variant_lookup (properties, "Serial", "&s", &s)) + changed |= nm_wifi_p2p_peer_set_serial (peer, s); + + v = g_variant_lookup_value (properties, "DeviceAddress", G_VARIANT_TYPE_BYTESTRING); + if (v) { + bytes = g_variant_get_fixed_array (v, &len, 1); + if ( len == ETH_ALEN + && memcmp (bytes, nm_ip_addr_zero.addr_eth, ETH_ALEN) != 0 + && memcmp (bytes, (char[ETH_ALEN]) { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, ETH_ALEN) != 0) + changed |= nm_wifi_p2p_peer_set_address_bin (peer, bytes); + g_variant_unref (v); + } + + /* The IEs property contains the WFD R1 subelements */ + v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING); + if (v) { + gs_unref_bytes GBytes *b = NULL; + + bytes = g_variant_get_fixed_array (v, &len, 1); + b = g_bytes_new (bytes, len); + changed |= nm_wifi_p2p_peer_set_wfd_ies (peer, b); + g_variant_unref (v); + } + + v = g_variant_lookup_value (properties, "Groups", G_VARIANT_TYPE_OBJECT_PATH_ARRAY); + if (v) { + sv = g_variant_get_objv (v, NULL); + changed |= nm_wifi_p2p_peer_set_groups (peer, sv); + g_free (sv); + } + + /*if (max_rate) + changed |= nm_wifi_p2p_peer_set_max_bitrate (peer, max_rate / 1000);*/ + + if (!priv->supplicant_path) { + priv->supplicant_path = g_strdup (supplicant_path); + changed = TRUE; + } + + changed |= nm_wifi_p2p_peer_set_last_seen (peer, nm_utils_get_monotonic_timestamp_s ()); + + g_object_thaw_notify (G_OBJECT (peer)); + + return changed; +} + +const char * +nm_wifi_p2p_peer_to_string (const NMWifiP2PPeer *self, + char *str_buf, + gsize buf_len, + gint32 now_s) +{ + const NMWifiP2PPeerPrivate *priv; + const char *supplicant_id = "-"; + const char* export_path; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (self), NULL); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + if (priv->supplicant_path) + supplicant_id = strrchr (priv->supplicant_path, '/') ?: supplicant_id; + + export_path = nm_dbus_object_get_path (NM_DBUS_OBJECT (self)); + if (export_path) + export_path = strrchr (export_path, '/') ?: export_path; + else + export_path = "/"; + + g_snprintf (str_buf, buf_len, + "%17s [n:%s, m:%s, mod:%s, mod_num:%s, ser:%s] %3us sup:%s [nm:%s]", + priv->address ?: "(none)", + priv->name, + priv->manufacturer, + priv->model, + priv->model_number, + priv->serial, + priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1, + supplicant_id, + export_path); + + return str_buf; +} + +gboolean +nm_wifi_p2p_peer_check_compatible (NMWifiP2PPeer *self, + NMConnection *connection) +{ + NMWifiP2PPeerPrivate *priv; + NMSettingP2PWireless *s_p2p_wireless; + const char *hwaddr; + + g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + s_p2p_wireless = NM_SETTING_P2P_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS)); + if (s_p2p_wireless == NULL) + return FALSE; + + hwaddr = nm_setting_p2p_wireless_get_peer (s_p2p_wireless); + if ( hwaddr + && ( !priv->address + || !nm_utils_hwaddr_matches (hwaddr, -1, priv->address, -1))) + return FALSE; + + return TRUE; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER (object); + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_uint (value, priv->flags); + break; + case PROP_NAME: + g_value_set_string (value, priv->name); + break; + case PROP_MANUFACTURER: + g_value_set_string (value, priv->manufacturer); + break; + case PROP_MODEL: + g_value_set_string (value, priv->model); + break; + case PROP_MODEL_NUMBER: + g_value_set_string (value, priv->model_number); + break; + case PROP_SERIAL: + g_value_set_string (value, priv->serial); + break; + case PROP_WFD_IES: + g_value_take_variant (value, nm_utils_gbytes_to_variant_ay (priv->wfd_ies)); + break; + case PROP_GROUPS: + g_value_set_variant (value, + g_variant_new_strv ( (const char*const*) priv->groups + ?: NM_PTRARRAY_EMPTY (const char *), + -1)); + break; + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->address); + break; + case PROP_STRENGTH: + g_value_set_uchar (value, priv->strength); + break; + case PROP_LAST_SEEN: + g_value_set_int (value, + priv->last_seen > 0 + ? (int) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) + : -1); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +nm_wifi_p2p_peer_init (NMWifiP2PPeer *self) +{ + NMWifiP2PPeerPrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerPrivate); + + self->_priv = priv; + + c_list_init (&self->peers_lst); + + priv->flags = NM_802_11_AP_FLAGS_NONE; + priv->last_seen = -1; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peer_new_from_properties (const char *supplicant_path, GVariant *properties) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (supplicant_path != NULL, NULL); + g_return_val_if_fail (properties != NULL, NULL); + + peer = (NMWifiP2PPeer *) g_object_new (NM_TYPE_WIFI_P2P_PEER, NULL); + nm_wifi_p2p_peer_update_from_properties (peer, supplicant_path, properties); + + /* ignore peers with invalid or missing address */ + if (!nm_wifi_p2p_peer_get_address (peer)) { + g_object_unref (peer); + return NULL; + } + + return peer; +} + +static void +finalize (GObject *object) +{ + NMWifiP2PPeer *self = NM_WIFI_P2P_PEER (object); + NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (self); + + nm_assert (!self->wifi_device); + nm_assert (c_list_is_empty (&self->peers_lst)); + + g_free (priv->supplicant_path); + g_free (priv->name); + g_free (priv->manufacturer); + g_free (priv->model); + g_free (priv->model_number); + g_free (priv->serial); + g_free (priv->address); + g_bytes_unref (priv->wfd_ies); + g_strfreev (priv->groups); + + G_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->finalize (object); +} + +static const NMDBusInterfaceInfoExtended interface_info_p2p_peer = { + .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( + NM_DBUS_INTERFACE_P2P_PEER, + .properties = NM_DEFINE_GDBUS_PROPERTY_INFOS ( + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Flags", "u", NM_WIFI_P2P_PEER_FLAGS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Name", "s", NM_WIFI_P2P_PEER_NAME), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Manufacturer", "s", NM_WIFI_P2P_PEER_MANUFACTURER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Model", "s", NM_WIFI_P2P_PEER_MODEL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("ModelNumber", "s", NM_WIFI_P2P_PEER_MODEL_NUMBER), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Serial", "s", NM_WIFI_P2P_PEER_SERIAL), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("WfdIEs", "ay", NM_WIFI_P2P_PEER_WFD_IES), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Groups", "as", NM_WIFI_P2P_PEER_GROUPS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("HwAddress", "s", NM_WIFI_P2P_PEER_HW_ADDRESS), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("Strength", "y", NM_WIFI_P2P_PEER_STRENGTH), + NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE ("LastSeen", "i", NM_WIFI_P2P_PEER_LAST_SEEN), + ), + ), + .legacy_property_changed = FALSE, +}; + +static void +nm_wifi_p2p_peer_class_init (NMWifiP2PPeerClass *p2p_peer_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (p2p_peer_class); + NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (p2p_peer_class); + + g_type_class_add_private (object_class, sizeof (NMWifiP2PPeerPrivate)); + + dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_NUMBERED (NM_DBUS_PATH_P2P_PEER); + dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_p2p_peer); + + object_class->get_property = get_property; + object_class->finalize = finalize; + + obj_properties[PROP_FLAGS] = + g_param_spec_uint (NM_WIFI_P2P_PEER_FLAGS, "", "", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_NAME] = + g_param_spec_string (NM_WIFI_P2P_PEER_NAME, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MANUFACTURER] = + g_param_spec_string (NM_WIFI_P2P_PEER_MANUFACTURER, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODEL] = + g_param_spec_string (NM_WIFI_P2P_PEER_MODEL, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_MODEL_NUMBER] = + g_param_spec_string (NM_WIFI_P2P_PEER_MODEL_NUMBER, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_SERIAL] = + g_param_spec_string (NM_WIFI_P2P_PEER_SERIAL, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_WFD_IES] = + g_param_spec_variant (NM_WIFI_P2P_PEER_WFD_IES, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_GROUPS] = + g_param_spec_variant (NM_WIFI_P2P_PEER_GROUPS, "", "", + G_VARIANT_TYPE ("as"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_HW_ADDRESS] = + g_param_spec_string (NM_WIFI_P2P_PEER_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_STRENGTH] = + g_param_spec_uchar (NM_WIFI_P2P_PEER_STRENGTH, "", "", + 0, G_MAXINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_LAST_SEEN] = + g_param_spec_int (NM_WIFI_P2P_PEER_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); +} + +/*****************************************************************************/ + +const char ** +nm_wifi_p2p_peers_get_paths (const CList *peers_lst_head) +{ + NMWifiP2PPeer *peer; + const char **list; + const char *path; + gsize i, n; + + n = c_list_length (peers_lst_head); + list = g_new (const char *, n + 1); + + i = 0; + if (n > 0) { + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + nm_assert (i < n); + path = nm_dbus_object_get_path (NM_DBUS_OBJECT (peer)); + nm_assert (path); + + list[i++] = path; + } + nm_assert (i <= n); + } + list[i] = NULL; + return list; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peers_find_first_compatible (const CList *peers_lst_head, + NMConnection *connection) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (connection, NULL); + + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + if (nm_wifi_p2p_peer_check_compatible (peer, connection)) + return peer; + } + return NULL; +} + +NMWifiP2PPeer * +nm_wifi_p2p_peers_find_by_supplicant_path (const CList *peers_lst_head, const char *path) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (path != NULL, NULL); + + c_list_for_each_entry (peer, peers_lst_head, peers_lst) { + if (nm_streq0 (path, nm_wifi_p2p_peer_get_supplicant_path (peer))) + return peer; + } + return NULL; +} + +/*****************************************************************************/ + +NMWifiP2PPeer * +nm_wifi_p2p_peer_lookup_for_device (NMDevice *device, const char *exported_path) +{ + NMWifiP2PPeer *peer; + + g_return_val_if_fail (NM_IS_DEVICE (device), NULL); + + peer = (NMWifiP2PPeer *) nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (device)), + exported_path); + if ( !peer + || !NM_IS_WIFI_P2P_PEER (peer) + || peer->wifi_device != device) + return NULL; + + return peer; +} diff --git a/src/devices/wifi/nm-wifi-p2p-peer.h b/src/devices/wifi/nm-wifi-p2p-peer.h new file mode 100644 index 0000000000..13c4add6cd --- /dev/null +++ b/src/devices/wifi/nm-wifi-p2p-peer.h @@ -0,0 +1,114 @@ +/* NetworkManager -- P2P Wi-Fi Peer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright (C) 2018 Red Hat, Inc. + */ + +#ifndef __NM_WIFI_P2P_PEER_H__ +#define __NM_WIFI_P2P_PEER_H__ + +#include "nm-dbus-object.h" +#include "nm-dbus-interface.h" +#include "nm-connection.h" + +#define NM_TYPE_WIFI_P2P_PEER (nm_wifi_p2p_peer_get_type ()) +#define NM_WIFI_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeer)) +#define NM_WIFI_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass)) +#define NM_IS_WIFI_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_P2P_PEER)) +#define NM_IS_WIFI_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_P2P_PEER)) +#define NM_WIFI_P2P_PEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass)) + +#define NM_WIFI_P2P_PEER_FLAGS "flags" +#define NM_WIFI_P2P_PEER_NAME "name" +#define NM_WIFI_P2P_PEER_MANUFACTURER "manufacturer" +#define NM_WIFI_P2P_PEER_MODEL "model" +#define NM_WIFI_P2P_PEER_MODEL_NUMBER "model-number" +#define NM_WIFI_P2P_PEER_SERIAL "serial" +#define NM_WIFI_P2P_PEER_WFD_IES "wfd-ies" +#define NM_WIFI_P2P_PEER_GROUPS "groups" +#define NM_WIFI_P2P_PEER_HW_ADDRESS "hw-address" +#define NM_WIFI_P2P_PEER_STRENGTH "strength" +#define NM_WIFI_P2P_PEER_LAST_SEEN "last-seen" + +typedef struct { + NMDBusObject parent; + NMDevice *wifi_device; + CList peers_lst; + struct _NMWifiP2PPeerPrivate *_priv; +} NMWifiP2PPeer; + +typedef struct _NMWifiP2PPeerClass NMWifiP2PPeerClass; + +GType nm_wifi_p2p_peer_get_type (void); + +NMWifiP2PPeer * nm_wifi_p2p_peer_new_from_properties (const char *supplicant_path, + GVariant *properties); + +gboolean nm_wifi_p2p_peer_update_from_properties (NMWifiP2PPeer *peer, + const char *supplicant_path, + GVariant *properties); + +gboolean nm_wifi_p2p_peer_check_compatible (NMWifiP2PPeer *self, + NMConnection *connection); + +const char * nm_wifi_p2p_peer_get_supplicant_path (NMWifiP2PPeer *peer); + +const char * nm_wifi_p2p_peer_get_name (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_name (NMWifiP2PPeer *peer, + const char *name); +const char * nm_wifi_p2p_peer_get_manufacturer (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_manufacturer (NMWifiP2PPeer *peer, + const char *manufacturer); +const char * nm_wifi_p2p_peer_get_model (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_model (NMWifiP2PPeer *peer, + const char *model); +const char * nm_wifi_p2p_peer_get_model_number (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_model_number (NMWifiP2PPeer *peer, + const char *number); +const char * nm_wifi_p2p_peer_get_serial (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_serial (NMWifiP2PPeer *peer, + const char *serial); + +GBytes * nm_wifi_p2p_peer_get_wfd_ies (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_wfd_ies (NMWifiP2PPeer *peer, + GBytes *bytes); + +const char *const*nm_wifi_p2p_peer_get_groups (const NMWifiP2PPeer *peer); + +const char * nm_wifi_p2p_peer_get_address (const NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_address (NMWifiP2PPeer *peer, + const char *addr); +gint8 nm_wifi_p2p_peer_get_strength (NMWifiP2PPeer *peer); +gboolean nm_wifi_p2p_peer_set_strength (NMWifiP2PPeer *peer, + gint8 strength); +NM80211ApFlags nm_wifi_p2p_peer_get_flags (const NMWifiP2PPeer *self); + +const char *nm_wifi_p2p_peer_to_string (const NMWifiP2PPeer *self, + char *str_buf, + gsize buf_len, + gint32 now_s); + +const char **nm_wifi_p2p_peers_get_paths (const CList *peers_lst_head); + +NMWifiP2PPeer *nm_wifi_p2p_peers_find_first_compatible (const CList *peers_lst_head, + NMConnection *connection); + +NMWifiP2PPeer *nm_wifi_p2p_peers_find_by_supplicant_path (const CList *peers_lst_head, const char *path); + +NMWifiP2PPeer *nm_wifi_p2p_peer_lookup_for_device (NMDevice *device, const char *exported_path); + +#endif /* __NM_WIFI_P2P_PEER_H__ */ diff --git a/src/nm-types.h b/src/nm-types.h index 277e0f6ccf..9a384e5800 100644 --- a/src/nm-types.h +++ b/src/nm-types.h @@ -152,6 +152,7 @@ typedef enum { NM_LINK_TYPE_WIMAX, NM_LINK_TYPE_WPAN, NM_LINK_TYPE_6LOWPAN, + NM_LINK_TYPE_P2P_WIFI, /* Software types */ NM_LINK_TYPE_BNEP = 0x10000, /* Bluetooth Ethernet emulation */ diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index fa74b280de..2bc7b4de94 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -84,6 +84,8 @@ send_interface="org.freedesktop.NetworkManager.WiMax.Nsp"/> + + -- cgit v1.2.1 From 959886892aa35d159d886cfddbbc856bf07bce6d Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 10 Oct 2018 23:32:22 +0200 Subject: core/devices: Automatically create P2P device for wifi devices If a wifi device supports P2P mode, then create a further P2P device for it automatically. --- src/devices/wifi/nm-device-wifi.c | 86 ++++++++++++++++++++++++++++++++++++++ src/devices/wifi/nm-device-wifi.h | 1 + src/devices/wifi/nm-wifi-factory.c | 23 +++++++++- 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index e0be38c3f7..4ba14ac336 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -22,6 +22,7 @@ #include "nm-default.h" #include "nm-device-wifi.h" +#include "nm-device-p2p-wifi.h" #include #include @@ -79,6 +80,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi, enum { SCANNING_PROHIBITED, + P2P_DEVICE_CREATED, LAST_SIGNAL }; @@ -124,6 +126,8 @@ typedef struct { guint wps_timeout_id; NMSettingWirelessWakeOnWLan wowlan_restore; + + NMDeviceP2PWifi *p2p_device; } NMDeviceWifiPrivate; struct _NMDeviceWifi @@ -186,6 +190,10 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, GParamSpec *pspec, NMDeviceWifi *self); +static void supplicant_iface_notify_p2p_available (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceWifi *self); + static void request_wireless_scan (NMDeviceWifi *self, gboolean periodic, gboolean force_if_scanning, @@ -198,6 +206,8 @@ static void ap_add_remove (NMDeviceWifi *self, static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset); +static void recheck_p2p_availability (NMDeviceWifi *self); + /*****************************************************************************/ static void @@ -291,6 +301,10 @@ supplicant_interface_acquire (NMDeviceWifi *self) "notify::" NM_SUPPLICANT_INTERFACE_CURRENT_BSS, G_CALLBACK (supplicant_iface_notify_current_bss), self); + g_signal_connect (priv->sup_iface, + "notify::" NM_SUPPLICANT_INTERFACE_P2P_AVAILABLE, + G_CALLBACK (supplicant_iface_notify_p2p_available), + self); _notify_scanning (self); @@ -347,6 +361,11 @@ supplicant_interface_release (NMDeviceWifi *self) g_clear_object (&priv->sup_iface); } + if (priv->p2p_device) { + /* Signal to P2P device to also release its reference */ + nm_device_p2p_wifi_set_mgmt_iface (priv->p2p_device, NULL); + } + _notify_scanning (self); } @@ -2028,6 +2047,10 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, && new_state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED) priv->ssid_found = TRUE; + if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY && + new_state >= NM_SUPPLICANT_INTERFACE_STATE_READY) + recheck_p2p_availability (self); + switch (new_state) { case NM_SUPPLICANT_INTERFACE_STATE_READY: _LOGD (LOGD_WIFI, "supplicant ready"); @@ -2204,6 +2227,61 @@ supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, } } +/* We bind the existance of the P2P device to a wifi device that is being + * managed by NetworkManager and is capable of P2P operation. + * Note that some care must be taken here, because we don't want to re-create + * the device every time the supplicant interface is destroyed (e.g. due to + * a suspend/resume cycle). + * Therefore, this function will be called when a change in the P2P capability + * is detected and the supplicant interface has been initialised. + */ +static void +recheck_p2p_availability (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDeviceP2PWifi *p2p_device; + gboolean p2p_available; + + g_object_get (priv->sup_iface, + NM_SUPPLICANT_INTERFACE_P2P_AVAILABLE, &p2p_available, + NULL); + + if (p2p_available && !priv->p2p_device) { + g_autofree char *iface_name = NULL; + /* Create a P2P device. "p2p-dev-" is the same prefix as chosen by + * wpa_supplicant internally. + */ + iface_name = g_strconcat ("p2p-dev-", nm_device_get_iface (NM_DEVICE (self)), NULL); + p2p_device = NM_DEVICE_P2P_WIFI (nm_device_p2p_wifi_new (priv->sup_iface, iface_name)); + priv->p2p_device = p2p_device; + + g_signal_emit (self, signals[P2P_DEVICE_CREATED], 0, priv->p2p_device); + g_object_add_weak_pointer (G_OBJECT (p2p_device), (gpointer*) &priv->p2p_device); + g_object_unref (p2p_device); + + } else if (p2p_available && priv->p2p_device) { + nm_device_p2p_wifi_set_mgmt_iface (priv->p2p_device, priv->sup_iface); + + } else if (!p2p_available && priv->p2p_device) { + /* Destroy the P2P device. */ + g_object_remove_weak_pointer (G_OBJECT (priv->p2p_device), (gpointer*) &priv->p2p_device); + nm_device_p2p_wifi_remove (priv->p2p_device); + priv->p2p_device = NULL; + } +} + +static void +supplicant_iface_notify_p2p_available (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceWifi *self) +{ + /* Do not update when the interface is still initializing. */ + if (nm_supplicant_interface_get_state (iface) < NM_SUPPLICANT_INTERFACE_STATE_READY) + return; + + recheck_p2p_availability (self); +} + static gboolean handle_auth_or_fail (NMDeviceWifi *self, NMActRequest *req, @@ -3426,4 +3504,12 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited), NULL, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN); + + signals[P2P_DEVICE_CREATED] = + g_signal_new (NM_DEVICE_WIFI_P2P_DEVICE_CREATED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, NM_TYPE_DEVICE); } diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index 1c555f5fe1..116ad11e48 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -40,6 +40,7 @@ #define NM_DEVICE_WIFI_LAST_SCAN "last-scan" #define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited" +#define NM_DEVICE_WIFI_P2P_DEVICE_CREATED "p2p-device-created" typedef struct _NMDeviceWifi NMDeviceWifi; typedef struct _NMDeviceWifiClass NMDeviceWifiClass; diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c index 4e9d1ecb20..e220c3a4cb 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/devices/wifi/nm-wifi-factory.c @@ -26,6 +26,7 @@ #include "nm-setting-wireless.h" #include "nm-setting-olpc-mesh.h" #include "nm-device-wifi.h" +#include "nm-device-p2p-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-iwd.h" #include "settings/nm-settings-connection.h" @@ -68,6 +69,18 @@ nm_device_factory_create (GError **error) /*****************************************************************************/ +static void +p2p_device_created (NMDeviceWifi *device, + NMDeviceP2PWifi *p2p_device, + NMDeviceFactory *self) +{ + nm_log_info (LOGD_PLATFORM | LOGD_WIFI, + "P2P Wifi device controlled by wifi interface %s created", + nm_device_get_iface (NM_DEVICE (device))); + + g_signal_emit_by_name (self, NM_DEVICE_FACTORY_DEVICE_ADDED, p2p_device); +} + static NMDevice * create_device (NMDeviceFactory *factory, const char *iface, @@ -98,6 +111,7 @@ create_device (NMDeviceFactory *factory, NM_PRINT_FMT_QUOTE_STRING (backend), WITH_IWD ? " (iwd support enabled)" : ""); if (!backend || !strcasecmp (backend, "wpa_supplicant")) { + NMDevice *device; NMDeviceWifiCapabilities capabilities; NM80211Mode mode; @@ -120,7 +134,14 @@ create_device (NMDeviceFactory *factory, return NULL; } - return nm_device_wifi_new (iface, capabilities); + device = nm_device_wifi_new (iface, capabilities); + + g_signal_connect_object (device, NM_DEVICE_WIFI_P2P_DEVICE_CREATED, + G_CALLBACK (p2p_device_created), + factory, + 0); + + return device; } #if WITH_IWD else if (!strcasecmp (backend, "iwd")) -- cgit v1.2.1 From adb8338408cd3d9696bc9dad7206f7848cef5ef4 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 18 Oct 2018 11:06:10 +0200 Subject: libnm: Add class to handle P2P peers This adds the introspection data and P2P peer handling to libnm. To be usable the P2P device handling is also needed. --- Makefile.am | 2 + docs/libnm/libnm-docs.xml | 1 + libnm/NetworkManager.h | 1 + libnm/libnm.ver | 12 + libnm/meson.build | 2 + libnm/nm-client.c | 3 + libnm/nm-p2p-peer.c | 550 ++++++++++++++++++++++++++++++++++++++++++++++ libnm/nm-p2p-peer.h | 101 +++++++++ libnm/nm-types.h | 1 + 9 files changed, 673 insertions(+) create mode 100644 libnm/nm-p2p-peer.c create mode 100644 libnm/nm-p2p-peer.h diff --git a/Makefile.am b/Makefile.am index 1b7289c011..e43ed6bb96 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1057,6 +1057,7 @@ libnm_lib_h_pub_real = \ libnm/nm-dhcp-config.h \ libnm/nm-ip-config.h \ libnm/nm-object.h \ + libnm/nm-p2p-peer.h \ libnm/nm-remote-connection.h \ libnm/nm-secret-agent-old.h \ libnm/nm-types.h \ @@ -1122,6 +1123,7 @@ libnm_lib_c_real = \ libnm/nm-ip6-config.c \ libnm/nm-manager.c \ libnm/nm-object.c \ + libnm/nm-p2p-peer.c \ libnm/nm-remote-connection.c \ libnm/nm-remote-settings.c \ libnm/nm-secret-agent-old.c \ diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml index df5d9bab31..b164d3f375 100644 --- a/docs/libnm/libnm-docs.xml +++ b/docs/libnm/libnm-docs.xml @@ -274,6 +274,7 @@ print ("NetworkManager version " + client.get_version())]]> + diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 30ec7905a2..8c5f3c782c 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -60,6 +60,7 @@ #include "nm-enum-types.h" #include "nm-ip-config.h" #include "nm-object.h" +#include "nm-p2p-peer.h" #include "nm-remote-connection.h" #include "nm-setting-6lowpan.h" #include "nm-setting-8021x.h" diff --git a/libnm/libnm.ver b/libnm/libnm.ver index b30e47af7d..66bf8d6e08 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1450,6 +1450,18 @@ global: nm_client_add_and_activate_connection2; nm_client_add_and_activate_connection2_finish; nm_device_get_connectivity; + nm_p2p_peer_connection_valid; + nm_p2p_peer_filter_connections; + nm_p2p_peer_get_flags; + nm_p2p_peer_get_hw_address; + nm_p2p_peer_get_last_seen; + nm_p2p_peer_get_manufacturer; + nm_p2p_peer_get_model; + nm_p2p_peer_get_model_number; + nm_p2p_peer_get_name; + nm_p2p_peer_get_serial; + nm_p2p_peer_get_strength; + nm_p2p_peer_get_type; nm_setting_p2p_wireless_get_peer; nm_setting_p2p_wireless_get_type; nm_setting_p2p_wireless_get_wps_method; diff --git a/libnm/meson.build b/libnm/meson.build index 2e44a6a49b..dc674447b5 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -62,6 +62,7 @@ libnm_headers = files( 'nm-dhcp-config.h', 'nm-ip-config.h', 'nm-object.h', + 'nm-p2p-peer.h', 'nm-remote-connection.h', 'nm-secret-agent-old.h', 'nm-types.h', @@ -132,6 +133,7 @@ libnm_sources = files( 'nm-ip6-config.c', 'nm-manager.c', 'nm-object.c', + 'nm-p2p-peer.c', 'nm-remote-connection.c', 'nm-remote-settings.c', 'nm-secret-agent-old.c', diff --git a/libnm/nm-client.c b/libnm/nm-client.c index e2522229bc..c9f919d412 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -83,6 +83,7 @@ #include "nm-ip4-config.h" #include "nm-ip6-config.h" #include "nm-manager.h" +#include "nm-p2p-peer.h" #include "nm-remote-connection.h" #include "nm-remote-settings.h" #include "nm-vpn-connection.h" @@ -2715,6 +2716,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager type = NM_TYPE_IP4_CONFIG; else if (strcmp (ifname, NM_DBUS_INTERFACE_IP6_CONFIG) == 0) type = NM_TYPE_IP6_CONFIG; + else if (strcmp (ifname, NM_DBUS_INTERFACE_P2P_PEER) == 0) + type = NM_TYPE_P2P_PEER; else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0) type = NM_TYPE_REMOTE_CONNECTION; else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS) == 0) diff --git a/libnm/nm-p2p-peer.c b/libnm/nm-p2p-peer.c new file mode 100644 index 0000000000..67e0392de4 --- /dev/null +++ b/libnm/nm-p2p-peer.c @@ -0,0 +1,550 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-p2p-peer.h" + +#include + +#include "nm-connection.h" +#include "nm-setting-connection.h" +#include "nm-setting-p2p-wireless.h" +#include "nm-utils.h" + +#include "nm-dbus-interface.h" +#include "nm-object-private.h" + +G_DEFINE_TYPE (NMP2PPeer, nm_p2p_peer, NM_TYPE_OBJECT) + +#define NM_P2P_PEER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_P2P_PEER, NMP2PPeerPrivate)) + +typedef struct { + NM80211ApFlags flags; + + char *name; + char *manufacturer; + char *model; + char *model_number; + char *serial; + + char *hw_address; + + guint8 strength; + int last_seen; +} NMP2PPeerPrivate; + +enum { + PROP_0, + PROP_FLAGS, + PROP_NAME, + PROP_MANUFACTURER, + PROP_MODEL, + PROP_MODEL_NUMBER, + PROP_SERIAL, + PROP_WFDIES, + PROP_HW_ADDRESS, + PROP_STRENGTH, + PROP_LAST_SEEN, + + LAST_PROP +}; + +/** + * nm_p2p_peer_get_flags: + * @peer: a #NMP2PPeer + * + * Gets the flags of the P2P peer. + * + * Returns: the flags + * + * Since: 1.16 + **/ +NM80211ApFlags +nm_p2p_peer_get_flags (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NM_802_11_AP_FLAGS_NONE); + + return NM_P2P_PEER_GET_PRIVATE (peer)->flags; +} + +/** + * nm_p2p_peer_get_name: + * @peer: a #NMP2PPeer + * + * Gets the name of the P2P peer. + * + * Returns: the name + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_name (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->name; +} + +/** + * nm_p2p_peer_get_manufacturer: + * @peer: a #NMP2PPeer + * + * Gets the manufacturer of the P2P peer. + * + * Returns: the manufacturer + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_manufacturer (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->manufacturer; +} + +/** + * nm_p2p_peer_get_model: + * @peer: a #NMP2PPeer + * + * Gets the model of the P2P peer. + * + * Returns: the model + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_model (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->model; +} + +/** + * nm_p2p_peer_get_model_number: + * @peer: a #NMP2PPeer + * + * Gets the model number of the P2P peer. + * + * Returns: the model number + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_model_number (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->model_number; +} + +/** + * nm_p2p_peer_get_serial: + * @peer: a #NMP2PPeer + * + * Gets the serial number of the P2P peer. + * + * Returns: the serial number + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_serial (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->serial; +} + +/** + * nm_p2p_peer_get_hw_address: + * @peer: a #NMP2PPeer + * + * Gets the hardware address of the P2P peer. + * + * Returns: the hardware adress + * + * Since: 1.16 + **/ +const char * +nm_p2p_peer_get_hw_address (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), NULL); + + return NM_P2P_PEER_GET_PRIVATE (peer)->hw_address; +} + +/** + * nm_p2p_peer_get_strength: + * @peer: a #NMP2PPeer + * + * Gets the current signal strength of the P2P peer as a percentage. + * + * Returns: the signal strength (0 to 100) + * + * Since: 1.16 + **/ +guint8 +nm_p2p_peer_get_strength (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), 0); + + return NM_P2P_PEER_GET_PRIVATE (peer)->strength; +} + +/** + * nm_p2p_peer_get_last_seen: + * @peer: a #NMP2PPeer + * + * Returns the timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * P2P peer was seen. A value of -1 means the P2P peer has never been seen. + * + * Returns: the last seen time in seconds + * + * Since: 1.16 + **/ +int +nm_p2p_peer_get_last_seen (NMP2PPeer *peer) +{ + g_return_val_if_fail (NM_IS_P2P_PEER (peer), -1); + + return NM_P2P_PEER_GET_PRIVATE (peer)->last_seen; +} + +/** + * nm_p2p_peer_connection_valid: + * @peer: an #NMP2PPeer to validate @connection against + * @connection: an #NMConnection to validate against @peer + * + * Validates a given connection against a given Wi-Fi P2P peer to ensure that + * the connection may be activated with that peer. The connection must match the + * @peer's address and in the future possibly other attributes. + * + * Returns: %TRUE if the connection may be activated with this Wi-Fi P2P Peer, + * %FALSE if it cannot be. + * + * Since: 1.16 + **/ +gboolean +nm_p2p_peer_connection_valid (NMP2PPeer *peer, NMConnection *connection) +{ + NMSettingConnection *s_con; + NMSettingP2PWireless *s_p2p_wifi; + const char *ctype; + const char *hw_address; + const char *setting_peer; + + s_con = nm_connection_get_setting_connection (connection); + if (!s_con) + return FALSE; + + ctype = nm_setting_connection_get_connection_type (s_con); + if (!ctype || !nm_streq (ctype, NM_SETTING_P2P_WIRELESS_SETTING_NAME)) + return FALSE; + + s_p2p_wifi = (NMSettingP2PWireless*) nm_connection_get_setting (connection, NM_TYPE_SETTING_P2P_WIRELESS); + if (!s_p2p_wifi) + return FALSE; + + /* HW Address check */ + hw_address = nm_p2p_peer_get_hw_address (peer); + if (!hw_address) + return FALSE; + setting_peer = nm_setting_p2p_wireless_get_peer (s_p2p_wifi); + if ( !setting_peer + || g_strcmp0 (hw_address, setting_peer)) + return FALSE; + + return TRUE; +} + +/** + * nm_p2p_peer_filter_connections: + * @peer: an #NMP2PPeer to filter connections for + * @connections: (element-type NMConnection): an array of #NMConnections to + * filter + * + * Filters a given array of connections for a given #NMP2PPeer object and + * returns connections which may be activated with the P2P peer. Any + * returned connections will match the @peers's HW address and in the future + * possibly other attributes. + * + * To obtain the list of connections that are compatible with this P2P peer, + * use nm_client_get_connections() and then filter the returned list for a given + * #NMDevice using nm_device_filter_connections() and finally filter that list + * with this function. + * + * Returns: (transfer container) (element-type NMConnection): an array of + * #NMConnections that could be activated with the given @peer. The array should + * be freed with g_ptr_array_unref() when it is no longer required. + * + * Since: 1.16 + **/ +GPtrArray * +nm_p2p_peer_filter_connections (NMP2PPeer *peer, const GPtrArray *connections) +{ + GPtrArray *filtered; + int i; + + filtered = g_ptr_array_new_with_free_func (g_object_unref); + for (i = 0; i < connections->len; i++) { + NMConnection *candidate = connections->pdata[i]; + + if (nm_p2p_peer_connection_valid (peer, candidate)) + g_ptr_array_add (filtered, g_object_ref (candidate)); + } + + return filtered; +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMP2PPeer *peer = NM_P2P_PEER (object); + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_flags (value, nm_p2p_peer_get_flags (peer)); + break; + case PROP_NAME: + g_value_set_string (value, nm_p2p_peer_get_name (peer)); + break; + case PROP_MANUFACTURER: + g_value_set_string (value, nm_p2p_peer_get_manufacturer (peer)); + break; + case PROP_MODEL: + g_value_set_string (value, nm_p2p_peer_get_model (peer)); + break; + case PROP_MODEL_NUMBER: + g_value_set_string (value, nm_p2p_peer_get_model_number (peer)); + break; + case PROP_SERIAL: + g_value_set_string (value, nm_p2p_peer_get_serial (peer)); + break; + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_p2p_peer_get_hw_address (peer)); + break; + case PROP_STRENGTH: + g_value_set_uchar (value, nm_p2p_peer_get_strength (peer)); + break; + case PROP_LAST_SEEN: + g_value_set_int (value, nm_p2p_peer_get_last_seen (peer)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_p2p_peer_init (NMP2PPeer *peer) +{ + NM_P2P_PEER_GET_PRIVATE (peer)->last_seen = -1; +} + +static void +finalize (GObject *object) +{ + NMP2PPeerPrivate *priv = NM_P2P_PEER_GET_PRIVATE (object); + + g_free (priv->name); + g_free (priv->manufacturer); + g_free (priv->model); + g_free (priv->model_number); + g_free (priv->serial); + + G_OBJECT_CLASS (nm_p2p_peer_parent_class)->finalize (object); +} + +static void +init_dbus (NMObject *object) +{ + NMP2PPeerPrivate *priv = NM_P2P_PEER_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_P2P_PEER_FLAGS, &priv->flags }, + { NM_P2P_PEER_NAME, &priv->name }, + { NM_P2P_PEER_MANUFACTURER, &priv->manufacturer }, + { NM_P2P_PEER_MODEL, &priv->model }, + { NM_P2P_PEER_MODEL_NUMBER, &priv->model_number }, + { NM_P2P_PEER_SERIAL, &priv->serial }, + { NM_P2P_PEER_HW_ADDRESS, &priv->hw_address }, + { NM_P2P_PEER_STRENGTH, &priv->strength }, + { NM_P2P_PEER_LAST_SEEN, &priv->last_seen }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_p2p_peer_parent_class)->init_dbus (object); + + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_P2P_PEER, + property_info); +} + +static void +nm_p2p_peer_class_init (NMP2PPeerClass *peer_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (peer_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (peer_class); + + g_type_class_add_private (peer_class, sizeof (NMP2PPeerPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + /* properties */ + + /** + * NMP2PPeer:flags: + * + * The flags of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_FLAGS, + g_param_spec_flags (NM_P2P_PEER_FLAGS, "", "", + NM_TYPE_802_11_AP_FLAGS, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:name: + * + * The name of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_NAME, + g_param_spec_string (NM_P2P_PEER_NAME, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:manufacturer: + * + * The manufacturer of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_MANUFACTURER, + g_param_spec_string (NM_P2P_PEER_MANUFACTURER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:model: + * + * The model of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_MODEL, + g_param_spec_string (NM_P2P_PEER_MODEL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:model-number: + * + * The hardware address of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_MODEL_NUMBER, + g_param_spec_string (NM_P2P_PEER_MODEL_NUMBER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:serial: + * + * The serial number of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_SERIAL, + g_param_spec_string (NM_P2P_PEER_SERIAL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:hw-address: + * + * The hardware address of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_P2P_PEER_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:strength: + * + * The current signal strength of the P2P peer. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_STRENGTH, + g_param_spec_uchar (NM_P2P_PEER_STRENGTH, "", "", + 0, G_MAXUINT8, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMP2PPeer:last-seen: + * + * The timestamp (in CLOCK_BOOTTIME seconds) for the last time the + * P2P peer was found. A value of -1 means the peer has never been seen. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_P2P_PEER_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} diff --git a/libnm/nm-p2p-peer.h b/libnm/nm-p2p-peer.h new file mode 100644 index 0000000000..881f83abdf --- /dev/null +++ b/libnm/nm-p2p-peer.h @@ -0,0 +1,101 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + */ + +#ifndef __NM_P2P_PEER_H__ +#define __NM_P2P_PEER_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include "nm-object.h" + +G_BEGIN_DECLS + +#define NM_TYPE_P2P_PEER (nm_p2p_peer_get_type ()) +#define NM_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_P2P_PEER, NMP2PPeer)) +#define NM_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_P2P_PEER, NMP2PPeerClass)) +#define NM_IS_P2P_PEER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_P2P_PEER)) +#define NM_IS_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_P2P_PEER)) +#define NM_P2P_PEER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_P2P_PEER, NMP2PPeerClass)) + +#define NM_P2P_PEER_FLAGS "flags" +#define NM_P2P_PEER_NAME "name" +#define NM_P2P_PEER_MANUFACTURER "manufacturer" +#define NM_P2P_PEER_MODEL "model" +#define NM_P2P_PEER_MODEL_NUMBER "model-number" +#define NM_P2P_PEER_SERIAL "serial" +#define NM_P2P_PEER_WFDIES "WFDIEs" +#define NM_P2P_PEER_HW_ADDRESS "hw-address" +#define NM_P2P_PEER_STRENGTH "strength" +#define NM_P2P_PEER_LAST_SEEN "last-seen" + +/** + * NMP2PPeer: + */ +NM_AVAILABLE_IN_1_16 +struct _NMP2PPeer { + NMObject parent; +}; + +NM_AVAILABLE_IN_1_16 +typedef struct { + NMObjectClass parent; + + /*< private >*/ + gpointer padding[4]; +} NMP2PPeerClass; + +NM_AVAILABLE_IN_1_16 +GType nm_p2p_peer_get_type (void); + +NM_AVAILABLE_IN_1_16 +NM80211ApFlags nm_p2p_peer_get_flags (NMP2PPeer *peer); + +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_name (NMP2PPeer *peer); +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_manufacturer (NMP2PPeer *peer); +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_model (NMP2PPeer *peer); +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_model_number (NMP2PPeer *peer); +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_serial (NMP2PPeer *peer); + +NM_AVAILABLE_IN_1_16 +const char * nm_p2p_peer_get_hw_address (NMP2PPeer *peer); + +NM_AVAILABLE_IN_1_16 +guint8 nm_p2p_peer_get_strength (NMP2PPeer *peer); +NM_AVAILABLE_IN_1_16 +int nm_p2p_peer_get_last_seen (NMP2PPeer *peer); + +NM_AVAILABLE_IN_1_16 +GPtrArray * nm_p2p_peer_filter_connections (NMP2PPeer *peer, + const GPtrArray *connections); + +NM_AVAILABLE_IN_1_16 +gboolean nm_p2p_peer_connection_valid (NMP2PPeer *peer, + NMConnection *connection); + +G_END_DECLS + +#endif /* __NM_P2P_PEER_H__ */ diff --git a/libnm/nm-types.h b/libnm/nm-types.h index bb77e642df..97415cbf3f 100644 --- a/libnm/nm-types.h +++ b/libnm/nm-types.h @@ -59,6 +59,7 @@ typedef struct _NMDeviceWireGuard NMDeviceWireGuard; typedef struct _NMDeviceWpan NMDeviceWpan; typedef struct _NMDhcpConfig NMDhcpConfig; typedef struct _NMIPConfig NMIPConfig; +typedef struct _NMP2PPeer NMP2PPeer; typedef struct _NMObject NMObject; typedef struct _NMRemoteConnection NMRemoteConnection; typedef struct _NMVpnConnection NMVpnConnection; -- cgit v1.2.1 From 6420a2c1fdb55b43fcf662ef1d53001f3835c9e6 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 18 Oct 2018 11:36:54 +0200 Subject: libnm: Add NMDeviceP2PWifi --- Makefile.am | 2 + docs/libnm/libnm-docs.xml | 1 + libnm/NetworkManager.h | 1 + libnm/libnm.ver | 4 + libnm/meson.build | 2 + libnm/nm-client.c | 6 + libnm/nm-device-p2p-wifi.c | 467 +++++++++++++++++++++++++++++++++++++++++++++ libnm/nm-device-p2p-wifi.h | 79 ++++++++ libnm/nm-types.h | 1 + po/POTFILES.in | 1 + 10 files changed, 564 insertions(+) create mode 100644 libnm/nm-device-p2p-wifi.c create mode 100644 libnm/nm-device-p2p-wifi.h diff --git a/Makefile.am b/Makefile.am index e43ed6bb96..7a75a6637f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1044,6 +1044,7 @@ libnm_lib_h_pub_real = \ libnm/nm-device-ovs-interface.h \ libnm/nm-device-ovs-port.h \ libnm/nm-device-ovs-bridge.h \ + libnm/nm-device-p2p-wifi.h \ libnm/nm-device-ppp.h \ libnm/nm-device-team.h \ libnm/nm-device-tun.h \ @@ -1104,6 +1105,7 @@ libnm_lib_c_real = \ libnm/nm-device-ovs-interface.c \ libnm/nm-device-ovs-port.c \ libnm/nm-device-ovs-bridge.c \ + libnm/nm-device-p2p-wifi.c \ libnm/nm-device-ppp.c \ libnm/nm-device-team.c \ libnm/nm-device-tun.c \ diff --git a/docs/libnm/libnm-docs.xml b/docs/libnm/libnm-docs.xml index b164d3f375..03f6835737 100644 --- a/docs/libnm/libnm-docs.xml +++ b/docs/libnm/libnm-docs.xml @@ -261,6 +261,7 @@ print ("NetworkManager version " + client.get_version())]]> + diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h index 8c5f3c782c..1f98e50b11 100644 --- a/libnm/NetworkManager.h +++ b/libnm/NetworkManager.h @@ -46,6 +46,7 @@ #include "nm-device-ovs-interface.h" #include "nm-device-ovs-port.h" #include "nm-device-ovs-bridge.h" +#include "nm-device-p2p-wifi.h" #include "nm-device-ppp.h" #include "nm-device-team.h" #include "nm-device-tun.h" diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 66bf8d6e08..e2ff5f37fe 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1450,6 +1450,10 @@ global: nm_client_add_and_activate_connection2; nm_client_add_and_activate_connection2_finish; nm_device_get_connectivity; + nm_device_p2p_wifi_get_group_owner; + nm_device_p2p_wifi_get_hw_address; + nm_device_p2p_wifi_get_peers; + nm_device_p2p_wifi_get_type; nm_p2p_peer_connection_valid; nm_p2p_peer_filter_connections; nm_p2p_peer_get_flags; diff --git a/libnm/meson.build b/libnm/meson.build index dc674447b5..dee4e36bdf 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -50,6 +50,7 @@ libnm_headers = files( 'nm-device-ovs-interface.h', 'nm-device-ovs-port.h', 'nm-device-ovs-bridge.h', + 'nm-device-p2p-wifi.h', 'nm-device-ppp.h', 'nm-device-team.h', 'nm-device-tun.h', @@ -115,6 +116,7 @@ libnm_sources = files( 'nm-device-ovs-interface.c', 'nm-device-ovs-port.c', 'nm-device-ovs-bridge.c', + 'nm-device-p2p-wifi.c', 'nm-device-ppp.c', 'nm-device-team.c', 'nm-device-tun.c', diff --git a/libnm/nm-client.c b/libnm/nm-client.c index c9f919d412..e5902ad051 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -41,6 +41,7 @@ #include "introspection/org.freedesktop.NetworkManager.h" #include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h" +#include "introspection/org.freedesktop.NetworkManager.Device.P2PWireless.h" #include "introspection/org.freedesktop.NetworkManager.Device.h" #include "introspection/org.freedesktop.NetworkManager.DnsManager.h" #include "introspection/org.freedesktop.NetworkManager.Settings.h" @@ -68,6 +69,7 @@ #include "nm-device-ovs-interface.h" #include "nm-device-ovs-port.h" #include "nm-device-ovs-bridge.h" +#include "nm-device-p2p-wifi.h" #include "nm-device-ppp.h" #include "nm-device-team.h" #include "nm-device-tun.h" @@ -2612,6 +2614,8 @@ proxy_type (GDBusObjectManagerClient *manager, return NMDBUS_TYPE_MANAGER_PROXY; else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_WIRELESS) == 0) return NMDBUS_TYPE_DEVICE_WIFI_PROXY; + else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS) == 0) + return NMDBUS_TYPE_DEVICE_P2P_WIFI_PROXY; else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE) == 0) return NMDBUS_TYPE_DEVICE_PROXY; else if (strcmp (interface_name, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0) @@ -2690,6 +2694,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager type = NM_TYPE_DEVICE_OVS_PORT; else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE) == 0) type = NM_TYPE_DEVICE_OVS_BRIDGE; + else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS) == 0) + type = NM_TYPE_DEVICE_P2P_WIFI; else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_PPP) == 0) type = NM_TYPE_DEVICE_PPP; else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TEAM) == 0) diff --git a/libnm/nm-device-p2p-wifi.c b/libnm/nm-device-p2p-wifi.c new file mode 100644 index 0000000000..d4f54335eb --- /dev/null +++ b/libnm/nm-device-p2p-wifi.c @@ -0,0 +1,467 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-device-p2p-wifi.h" + +#include + +#include "nm-setting-connection.h" +#include "nm-setting-p2p-wireless.h" +#include "nm-utils.h" + +#include "nm-p2p-peer.h" +#include "nm-object-private.h" +#include "nm-core-internal.h" +#include "nm-dbus-helpers.h" + +#include "introspection/org.freedesktop.NetworkManager.Device.P2PWireless.h" + +G_DEFINE_TYPE (NMDeviceP2PWifi, nm_device_p2p_wifi, NM_TYPE_DEVICE) + +#define NM_DEVICE_P2P_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiPrivate)) + +void _nm_device_p2p_wifi_set_p2p_wireless_enabled (NMDeviceP2PWifi *device, gboolean enabled); +static void state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data); + +typedef struct { + NMDeviceP2PWifi *device; + GSimpleAsyncResult *simple; +} RequestScanInfo; + +typedef struct { + NMDBusDeviceP2PWifi *proxy; + + char *hw_address; + + gboolean group_owner; + GByteArray *wfd_ies; + GPtrArray *peers; +} NMDeviceP2PWifiPrivate; + +enum { + PROP_0, + PROP_HW_ADDRESS, + PROP_GROUP_OWNER, + PROP_WFDIES, + PROP_PEERS, + + LAST_PROP +}; + +enum { + PEER_ADDED, + PEER_REMOVED, + + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; + +/** + * nm_device_p2p_wifi_get_hw_address: + * @device: a #NMDeviceP2PWifi + * + * Gets the actual hardware (MAC) address of the #NMDeviceP2PWifi + * + * Returns: the actual hardware address. This is the internal string used by the + * device, and must not be modified. + * + * Since: 1.16 + **/ +const char * +nm_device_p2p_wifi_get_hw_address (NMDeviceP2PWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_P2P_WIFI (device), NULL); + + return nm_str_not_empty (NM_DEVICE_P2P_WIFI_GET_PRIVATE (device)->hw_address); +} + +/** + * nm_device_p2p_wifi_get_group_owner: + * @device: a #NMDeviceP2PWifi + * + * Gets whether the device is currently the P2P group owner. This is only + * valid when a connection is established. + * + * Returns: Whether the device is the P2P group owner. + * + * Since: 1.16 + **/ +gboolean +nm_device_p2p_wifi_get_group_owner (NMDeviceP2PWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_P2P_WIFI (device), FALSE); + + return NM_DEVICE_P2P_WIFI_GET_PRIVATE (device)->group_owner; +} + +/** + * nm_device_p2p_wifi_get_peers: + * @device: a #NMDeviceP2PWifi + * + * Gets all the found peers of the #NMDeviceP2PWifi. + * + * Returns: (element-type NMP2PPeer): a #GPtrArray containing all the + * found #NMP2PPeers. + * The returned array is owned by the client and should not be modified. + * + * Since: 1.16 + **/ +const GPtrArray * +nm_device_p2p_wifi_get_peers (NMDeviceP2PWifi *device) +{ + g_return_val_if_fail (NM_IS_DEVICE_P2P_WIFI (device), NULL); + + return NM_DEVICE_P2P_WIFI_GET_PRIVATE (device)->peers; +} + +/** + * nm_device_p2p_wifi_get_peer_by_path: + * @device: a #NMDeviceP2PWifi + * @path: the object path of the peer + * + * Gets a #NMP2PPeer by path. + * + * Returns: (transfer none): the peer or %NULL if none is found. + * + * Since: 1.16 + **/ +NMP2PPeer * +nm_device_p2p_wifi_get_peer_by_path (NMDeviceP2PWifi *device, + const char *path) +{ + const GPtrArray *peers; + int i; + NMP2PPeer *peer = NULL; + + g_return_val_if_fail (NM_IS_DEVICE_P2P_WIFI (device), NULL); + g_return_val_if_fail (path != NULL, NULL); + + peers = nm_device_p2p_wifi_get_peers (device); + if (!peers) + return NULL; + + for (i = 0; i < peers->len; i++) { + NMP2PPeer *candidate = g_ptr_array_index (peers, i); + if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) { + peer = candidate; + break; + } + } + + return peer; +} + +static void +clean_up_peers (NMDeviceP2PWifi *self, gboolean in_dispose) +{ + NMDeviceP2PWifiPrivate *priv; + GPtrArray *peers; + int i; + + g_return_if_fail (NM_IS_DEVICE_P2P_WIFI (self)); + + priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + peers = priv->peers; + + if (in_dispose) + priv->peers = NULL; + else { + priv->peers = g_ptr_array_new (); + + for (i = 0; i < peers->len; i++) { + NMP2PPeer *peer = NM_P2P_PEER (g_ptr_array_index (peers, i)); + + g_signal_emit (self, signals[PEER_REMOVED], 0, peer); + } + } + + g_ptr_array_unref (peers); +} + +static gboolean +connection_compatible (NMDevice *device, NMConnection *connection, GError **error) +{ + if (!NM_DEVICE_CLASS (nm_device_p2p_wifi_parent_class)->connection_compatible (device, connection, error)) + return FALSE; + + if (!nm_connection_is_type (connection, NM_SETTING_P2P_WIRELESS_SETTING_NAME)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + _("The connection was not a P2P Wi-Fi connection.")); + return FALSE; + } + + return TRUE; +} + +static GType +get_setting_type (NMDevice *device) +{ + return NM_TYPE_SETTING_WIRELESS; +} + +static const char * +get_hw_address (NMDevice *device) +{ + return nm_device_p2p_wifi_get_hw_address (NM_DEVICE_P2P_WIFI (device)); +} + +static GVariant * +nm_device_p2p_wifi_get_wfdies_as_variant (const NMDeviceP2PWifi *self) +{ + const NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + if (priv->wfd_ies) { + return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + priv->wfd_ies->data, priv->wfd_ies->len, 1); + } else + return g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0); +} + +/*****************************************************************************/ + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (object); + + switch (prop_id) { + case PROP_HW_ADDRESS: + g_value_set_string (value, nm_device_p2p_wifi_get_hw_address (self)); + break; + case PROP_GROUP_OWNER: + g_value_set_enum (value, nm_device_p2p_wifi_get_group_owner (self)); + break; + case PROP_WFDIES: + g_value_take_variant (value, nm_device_p2p_wifi_get_wfdies_as_variant (self)); + break; + case PROP_PEERS: + g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_p2p_wifi_get_peers (self))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_device_p2p_wifi_init (NMDeviceP2PWifi *device) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (device); + + g_signal_connect (device, + "notify::" NM_DEVICE_STATE, + G_CALLBACK (state_changed_cb), + NULL); + + priv->peers = g_ptr_array_new (); +} + +static void +state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data) +{ +#if 0 + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (device); + + switch (nm_device_get_state (device)) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + case NM_DEVICE_STATE_DISCONNECTED: + case NM_DEVICE_STATE_FAILED: + /* TODO: Do something? */ + break; + default: + break; + } +#endif +} + +static void +init_dbus (NMObject *object) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (object); + const NMPropertiesInfo property_info[] = { + { NM_DEVICE_P2P_WIFI_HW_ADDRESS, &priv->hw_address }, + { NM_DEVICE_P2P_WIFI_GROUP_OWNER, &priv->group_owner }, + { NM_DEVICE_P2P_WIFI_WFDIES, &priv->wfd_ies }, + { NM_DEVICE_P2P_WIFI_PEERS, &priv->peers, NULL, NM_TYPE_P2P_PEER, "peer" }, + { NULL }, + }; + + NM_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->init_dbus (object); + + priv->proxy = NMDBUS_DEVICE_P2P_WIFI (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS)); + _nm_object_register_properties (object, + NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS, + property_info); +} + +static void +dispose (GObject *object) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (object); + + if (priv->peers) + clean_up_peers (NM_DEVICE_P2P_WIFI (object), TRUE); + + g_clear_object (&priv->proxy); + if (priv->wfd_ies) + g_byte_array_unref (priv->wfd_ies); + priv->wfd_ies = NULL; + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (object); + + g_free (priv->hw_address); + + G_OBJECT_CLASS (nm_device_p2p_wifi_parent_class)->finalize (object); +} + +static void +nm_device_p2p_wifi_class_init (NMDeviceP2PWifiClass *wifi_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (wifi_class); + NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wifi_class); + NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class); + + g_type_class_add_private (wifi_class, sizeof (NMDeviceP2PWifiPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->finalize = finalize; + + nm_object_class->init_dbus = init_dbus; + + device_class->connection_compatible = connection_compatible; + device_class->get_setting_type = get_setting_type; + device_class->get_hw_address = get_hw_address; + + /* properties */ + + /** + * NMDeviceP2PWifi:hw-address: + * + * The hardware (MAC) address of the device. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_DEVICE_P2P_WIFI_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + + /** + * NMDeviceP2PWifi:group-owner: + * + * Whether the device is currently the group owner. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_GROUP_OWNER, + g_param_spec_boolean (NM_DEVICE_P2P_WIFI_GROUP_OWNER, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceP2PWifi:wfd-ies: + * + * Whether the device is currently the group owner. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_WFDIES, + g_param_spec_variant (NM_DEVICE_P2P_WIFI_WFDIES, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /** + * NMDeviceP2PWifi:peers: (type GPtrArray(NMP2PPeer)) + * + * List of all P2P Wi-Fi peers the device can see. + * + * Since: 1.16 + **/ + g_object_class_install_property + (object_class, PROP_PEERS, + g_param_spec_boxed (NM_DEVICE_P2P_WIFI_PEERS, "", "", + G_TYPE_PTR_ARRAY, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + /* signals */ + + /** + * NMDeviceP2PWifi::peer-added: + * @device: the P2P Wi-Fi device that received the signal + * @peer: the new access point + * + * Notifies that a #NMP2PPeer is added to the P2P Wi-Fi device. + * + * Since: 1.16 + **/ + signals[PEER_ADDED] = + g_signal_new ("peer-added", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceP2PWifiClass, peer_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); + + /** + * NMDeviceP2PWifi::peer-removed: + * @device: the P2P Wi-Fi device that received the signal + * @peer: the removed access point + * + * Notifies that a #NMP2PPeer is removed from the P2P Wi-Fi device. + * + * Since: 1.16 + **/ + signals[PEER_REMOVED] = + g_signal_new ("peer-removed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMDeviceP2PWifiClass, peer_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, + G_TYPE_OBJECT); +} diff --git a/libnm/nm-device-p2p-wifi.h b/libnm/nm-device-p2p-wifi.h new file mode 100644 index 0000000000..74779f2097 --- /dev/null +++ b/libnm/nm-device-p2p-wifi.h @@ -0,0 +1,79 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2018 Red Hat, Inc. + */ + +#ifndef __NM_DEVICE_P2P_WIFI_H__ +#define __NM_DEVICE_P2P_WIFI_H__ + +#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION) +#error "Only can be included directly." +#endif + +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_P2P_WIFI (nm_device_p2p_wifi_get_type ()) +#define NM_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifi)) +#define NM_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) +#define NM_IS_DEVICE_P2P_WIFI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_IS_DEVICE_P2P_WIFI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_P2P_WIFI)) +#define NM_DEVICE_P2P_WIFI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_P2P_WIFI, NMDeviceP2PWifiClass)) + +#define NM_DEVICE_P2P_WIFI_HW_ADDRESS "hw-address" +#define NM_DEVICE_P2P_WIFI_GROUP_OWNER "group-owner" +#define NM_DEVICE_P2P_WIFI_PEERS "peers" +#define NM_DEVICE_P2P_WIFI_WFDIES "wfdies" + +/** + * NMDeviceP2PWifi: + */ +struct _NMDeviceP2PWifi { + NMDevice parent; +}; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*peer_added) (NMDeviceP2PWifi *device, NMP2PPeer *peer); + void (*peer_removed) (NMDeviceP2PWifi *device, NMP2PPeer *peer); + + /*< private >*/ + gpointer padding[4]; +} NMDeviceP2PWifiClass; + +GType nm_device_p2p_wifi_get_type (void); + +const char * nm_device_p2p_wifi_get_hw_address (NMDeviceP2PWifi *device); +gboolean nm_device_p2p_wifi_get_group_owner (NMDeviceP2PWifi *device); + +#if 0 +gboolean nm_device_p2p_wifi_get_wfdies (NMDeviceP2PWifi *device); +#endif + +NMP2PPeer * nm_device_p2p_wifi_get_peer_by_path (NMDeviceP2PWifi *device, + const char *path); + +const GPtrArray * nm_device_p2p_wifi_get_peers (NMDeviceP2PWifi *device); + + +G_END_DECLS + +#endif /* __NM_DEVICE_P2P_WIFI_H__ */ diff --git a/libnm/nm-types.h b/libnm/nm-types.h index 97415cbf3f..0cf8186f5c 100644 --- a/libnm/nm-types.h +++ b/libnm/nm-types.h @@ -54,6 +54,7 @@ typedef struct _NMDeviceTun NMDeviceTun; typedef struct _NMDeviceVlan NMDeviceVlan; typedef struct _NMDeviceVxlan NMDeviceVxlan; typedef struct _NMDeviceWifi NMDeviceWifi; +typedef struct _NMDeviceP2PWifi NMDeviceP2PWifi; typedef struct _NMDeviceWimax NMDeviceWimax; typedef struct _NMDeviceWireGuard NMDeviceWireGuard; typedef struct _NMDeviceWpan NMDeviceWpan; diff --git a/po/POTFILES.in b/po/POTFILES.in index 6700d5be82..31a614fc8a 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -152,6 +152,7 @@ libnm/nm-device-olpc-mesh.c libnm/nm-device-ovs-bridge.c libnm/nm-device-ovs-interface.c libnm/nm-device-ovs-port.c +libnm/nm-device-p2p-wifi.c libnm/nm-device-team.c libnm/nm-device-vlan.c libnm/nm-device-vxlan.c -- cgit v1.2.1 From dd0c59c468fb8bf8b728dec1592be1589e9a04eb Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 18 Oct 2018 10:51:48 +0200 Subject: core/devices: Add DBus methods to start/stop a P2P find By default the find will run for 30s. This can be increased or decreased in the range of 1-600s by setting "Timeout" in the options parameter. --- src/devices/wifi/nm-device-p2p-wifi.c | 79 +++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/devices/wifi/nm-device-p2p-wifi.c b/src/devices/wifi/nm-device-p2p-wifi.c index a57b2be089..80fda59c47 100644 --- a/src/devices/wifi/nm-device-p2p-wifi.c +++ b/src/devices/wifi/nm-device-p2p-wifi.c @@ -1012,6 +1012,68 @@ device_state_changed (NMDevice *device, } } +static void +impl_device_p2p_wifi_start_find (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (obj); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + gs_unref_variant GVariant *options = NULL; + int timeout; + + g_variant_get (parameters, "(@a{sv})", &options); + + if (!g_variant_lookup (options, "Timeout", "^ai", &timeout)) { + /* Default to running a find for 30s. */ + timeout = 30; + } + + /* Reject unreasonable timeout values. */ + if (timeout <= 0 || timeout > 600) { + g_dbus_method_invocation_return_error_literal (invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "The timeout for a find operation needs to be in the range of 1-600s."); + + return; + } + + if (!priv->mgmt_iface) { + g_dbus_method_invocation_return_error_literal (invocation, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "WPA Supplicant management interface is currently unavailable."); + + return; + } + + nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, timeout); + + g_dbus_method_invocation_return_value (invocation, NULL); +} + +static void +impl_device_p2p_wifi_stop_find (NMDBusObject *obj, + const NMDBusInterfaceInfoExtended *interface_info, + const NMDBusMethodInfoExtended *method_info, + GDBusConnection *connection, + const char *sender, + GDBusMethodInvocation *invocation, + GVariant *parameters) +{ + NMDeviceP2PWifi *self = NM_DEVICE_P2P_WIFI (obj); + NMDeviceP2PWifiPrivate *priv = NM_DEVICE_P2P_WIFI_GET_PRIVATE (self); + + nm_supplicant_interface_p2p_stop_find (priv->mgmt_iface); + + g_dbus_method_invocation_return_value (invocation, NULL); +} + /*****************************************************************************/ NMSupplicantInterface * @@ -1090,6 +1152,23 @@ static const GDBusSignalInfo nm_signal_info_p2p_wireless_peer_removed = NM_DEFIN static const NMDBusInterfaceInfoExtended interface_info_device_p2p_wifi = { .parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT ( NM_DBUS_INTERFACE_DEVICE_P2P_WIRELESS, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "StartFind", + .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( + NM_DEFINE_GDBUS_ARG_INFO ("options", "a{sv}"), + ), + ), + .handle = impl_device_p2p_wifi_start_find, + ), + NM_DEFINE_DBUS_METHOD_INFO_EXTENDED ( + NM_DEFINE_GDBUS_METHOD_INFO_INIT ( + "StopFind", + ), + .handle = impl_device_p2p_wifi_stop_find, + ), + ), .signals = NM_DEFINE_GDBUS_SIGNAL_INFOS ( &nm_signal_info_p2p_wireless_peer_added, &nm_signal_info_p2p_wireless_peer_removed, -- cgit v1.2.1 From 6b74d006e6b7d11eadaeb072378fd0b181f649f8 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Thu, 18 Oct 2018 11:14:09 +0200 Subject: libnm: Add routines to start/stop a P2P find operation --- ...eedesktop.NetworkManager.Device.P2PWireless.xml | 20 +++++++ libnm/libnm.ver | 2 + libnm/nm-device-p2p-wifi.c | 70 ++++++++++++++++++++++ libnm/nm-device-p2p-wifi.h | 6 ++ 4 files changed, 98 insertions(+) diff --git a/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml index fa85b83f9d..6f7bdeaeb6 100644 --- a/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml +++ b/introspection/org.freedesktop.NetworkManager.Device.P2PWireless.xml @@ -41,6 +41,26 @@ --> + + + + + + + + +