2006-11-25 15:41:04 +00:00
|
|
|
/* NetworkManager -- Network link manager
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
|
*
|
2008-06-26 18:31:52 +00:00
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2006-11-25 15:41:04 +00:00
|
|
|
*
|
2017-04-13 10:42:32 +02:00
|
|
|
* Copyright (C) 2006 - 2017 Red Hat, Inc.
|
2008-11-04 22:36:51 +00:00
|
|
|
* Copyright (C) 2006 - 2008 Novell, Inc.
|
2006-11-25 15:41:04 +00:00
|
|
|
*/
|
|
|
|
|
|
2016-02-19 14:57:48 +01:00
|
|
|
#include "nm-default.h"
|
2014-11-13 10:07:02 -05:00
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
#include "nm-supplicant-interface.h"
|
2018-10-10 22:43:49 +02:00
|
|
|
#include "nm-supplicant-manager.h"
|
2016-09-28 15:58:24 +02:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
#include <stdio.h>
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2013-12-10 16:18:17 +01:00
|
|
|
#include "NetworkManagerUtils.h"
|
2006-12-19 19:15:31 +00:00
|
|
|
#include "nm-supplicant-config.h"
|
2015-02-02 02:31:30 -06:00
|
|
|
#include "nm-core-internal.h"
|
2019-04-15 09:23:31 +02:00
|
|
|
#include "nm-std-aux/nm-dbus-compat.h"
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2018-10-10 18:35:20 +02:00
|
|
|
#define WPAS_DBUS_IFACE_INTERFACE WPAS_DBUS_INTERFACE ".Interface"
|
|
|
|
|
#define WPAS_DBUS_IFACE_INTERFACE_WPS WPAS_DBUS_INTERFACE ".Interface.WPS"
|
|
|
|
|
#define WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE WPAS_DBUS_INTERFACE ".Interface.P2PDevice"
|
|
|
|
|
#define WPAS_DBUS_IFACE_BSS WPAS_DBUS_INTERFACE ".BSS"
|
2018-10-10 21:27:34 +02:00
|
|
|
#define WPAS_DBUS_IFACE_PEER WPAS_DBUS_INTERFACE ".Peer"
|
2018-10-10 23:08:15 +02:00
|
|
|
#define WPAS_DBUS_IFACE_GROUP WPAS_DBUS_INTERFACE ".Group"
|
2018-10-10 18:35:20 +02:00
|
|
|
#define WPAS_DBUS_IFACE_NETWORK WPAS_DBUS_INTERFACE ".Network"
|
|
|
|
|
#define WPAS_ERROR_INVALID_IFACE WPAS_DBUS_INTERFACE ".InvalidInterface"
|
|
|
|
|
#define WPAS_ERROR_EXISTS_ERROR WPAS_DBUS_INTERFACE ".InterfaceExists"
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
/*****************************************************************************/
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
typedef struct {
|
|
|
|
|
GDBusProxy *proxy;
|
|
|
|
|
gulong change_id;
|
|
|
|
|
} BssData;
|
|
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
typedef struct {
|
|
|
|
|
GDBusProxy *proxy;
|
|
|
|
|
gulong change_id;
|
|
|
|
|
} PeerData;
|
|
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
struct _AddNetworkData;
|
|
|
|
|
|
2017-06-03 14:41:29 +02:00
|
|
|
typedef struct {
|
|
|
|
|
NMSupplicantInterface *self;
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
char *type;
|
2017-06-03 14:41:29 +02:00
|
|
|
char *bssid;
|
|
|
|
|
char *pin;
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
GDBusProxy *proxy;
|
|
|
|
|
GCancellable *cancellable;
|
|
|
|
|
bool is_cancelling;
|
|
|
|
|
} WpsData;
|
2017-06-03 14:41:29 +02:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
typedef struct {
|
2017-02-15 10:14:54 +01:00
|
|
|
NMSupplicantInterface *self;
|
2017-02-14 19:30:21 +01:00
|
|
|
NMSupplicantConfig *cfg;
|
|
|
|
|
GCancellable *cancellable;
|
|
|
|
|
NMSupplicantInterfaceAssocCb callback;
|
|
|
|
|
gpointer user_data;
|
|
|
|
|
guint fail_on_idle_id;
|
|
|
|
|
guint blobs_left;
|
2017-02-15 10:14:54 +01:00
|
|
|
struct _AddNetworkData *add_network_data;
|
2017-02-14 19:30:21 +01:00
|
|
|
} AssocData;
|
|
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
typedef struct _AddNetworkData {
|
|
|
|
|
/* the assoc_data at the time when doing the call. */
|
|
|
|
|
AssocData *assoc_data;
|
|
|
|
|
} AddNetworkData;
|
|
|
|
|
|
2006-11-25 15:41:04 +00:00
|
|
|
enum {
|
2018-10-10 23:08:15 +02:00
|
|
|
STATE, /* change in the interface's state */
|
|
|
|
|
REMOVED, /* interface was removed by the supplicant */
|
|
|
|
|
BSS_UPDATED, /* a new BSS appeared or an existing had properties changed */
|
|
|
|
|
BSS_REMOVED, /* supplicant removed BSS from its scan list */
|
|
|
|
|
PEER_UPDATED, /* a new Peer appeared or an existing had properties changed */
|
|
|
|
|
PEER_REMOVED, /* supplicant removed Peer from its scan list */
|
|
|
|
|
SCAN_DONE, /* wifi scan is complete */
|
|
|
|
|
CREDENTIALS_REQUEST, /* 802.1x identity or password requested */
|
|
|
|
|
WPS_CREDENTIALS, /* WPS credentials received */
|
|
|
|
|
GROUP_STARTED, /* a new Group (interface) was created */
|
|
|
|
|
GROUP_FINISHED, /* a Group (interface) has been finished */
|
|
|
|
|
GROUP_FORMATION_FAILURE, /* P2P Group formation failed */
|
2006-11-25 15:41:04 +00:00
|
|
|
LAST_SIGNAL
|
|
|
|
|
};
|
2010-10-05 14:19:43 -05:00
|
|
|
static guint signals[LAST_SIGNAL] = { 0 };
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2016-01-19 16:08:29 +01:00
|
|
|
NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface,
|
|
|
|
|
PROP_IFACE,
|
2018-10-10 22:43:49 +02:00
|
|
|
PROP_OBJECT_PATH,
|
2018-10-10 23:08:15 +02:00
|
|
|
PROP_P2P_GROUP_JOINED,
|
2018-12-11 18:21:37 +01:00
|
|
|
PROP_P2P_GROUP_PATH,
|
2018-10-10 23:08:15 +02:00
|
|
|
PROP_P2P_GROUP_OWNER,
|
2009-05-13 11:16:29 -04:00
|
|
|
PROP_SCANNING,
|
2015-04-05 23:31:02 -05:00
|
|
|
PROP_CURRENT_BSS,
|
2016-06-30 18:20:48 +02:00
|
|
|
PROP_DRIVER,
|
2018-10-10 18:35:20 +02:00
|
|
|
PROP_P2P_AVAILABLE,
|
2017-01-18 17:41:12 +01:00
|
|
|
PROP_FAST_SUPPORT,
|
2016-01-19 16:08:29 +01:00
|
|
|
PROP_AP_SUPPORT,
|
2017-03-18 14:56:38 +01:00
|
|
|
PROP_PMF_SUPPORT,
|
2018-01-16 06:28:37 +09:00
|
|
|
PROP_FILS_SUPPORT,
|
2018-10-10 17:50:34 +02:00
|
|
|
PROP_P2P_SUPPORT,
|
|
|
|
|
PROP_WFD_SUPPORT,
|
2019-07-15 11:30:15 +00:00
|
|
|
PROP_FT_SUPPORT,
|
2019-07-15 11:30:19 +00:00
|
|
|
PROP_SHA384_SUPPORT,
|
2016-01-19 16:08:29 +01:00
|
|
|
);
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
typedef struct {
|
2015-02-01 03:19:32 -06:00
|
|
|
char * dev;
|
2016-06-30 18:20:48 +02:00
|
|
|
NMSupplicantDriver driver;
|
2015-02-01 03:19:32 -06:00
|
|
|
gboolean has_credreq; /* Whether querying 802.1x credentials is supported */
|
2017-01-18 17:41:12 +01:00
|
|
|
NMSupplicantFeature fast_support;
|
2015-10-06 20:02:40 -05:00
|
|
|
NMSupplicantFeature ap_support; /* Lightweight AP mode support */
|
2017-03-18 14:56:38 +01:00
|
|
|
NMSupplicantFeature pmf_support;
|
2018-01-16 06:28:37 +09:00
|
|
|
NMSupplicantFeature fils_support;
|
2018-10-10 17:50:34 +02:00
|
|
|
NMSupplicantFeature p2p_support;
|
|
|
|
|
NMSupplicantFeature wfd_support;
|
2019-07-15 11:30:15 +00:00
|
|
|
NMSupplicantFeature ft_support;
|
2019-07-15 11:30:19 +00:00
|
|
|
NMSupplicantFeature sha384_support;
|
2015-02-01 03:19:32 -06:00
|
|
|
guint32 max_scan_ssids;
|
|
|
|
|
guint32 ready_count;
|
|
|
|
|
|
|
|
|
|
char * object_path;
|
2017-02-14 01:30:25 +01:00
|
|
|
NMSupplicantInterfaceState state;
|
2015-02-01 03:19:32 -06:00
|
|
|
int disconnect_reason;
|
|
|
|
|
|
2018-08-26 18:21:25 +02:00
|
|
|
bool scanning:1;
|
2017-02-15 11:05:47 +01:00
|
|
|
|
|
|
|
|
bool scan_done_pending:1;
|
|
|
|
|
bool scan_done_success:1;
|
2015-02-01 03:19:32 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
GDBusProxy * wpas_proxy;
|
|
|
|
|
GCancellable * init_cancellable;
|
|
|
|
|
GDBusProxy * iface_proxy;
|
|
|
|
|
GCancellable * other_cancellable;
|
2018-10-10 18:35:20 +02:00
|
|
|
GDBusProxy * p2p_proxy;
|
2018-10-10 23:08:15 +02:00
|
|
|
GDBusProxy * group_proxy;
|
2018-10-10 18:35:20 +02:00
|
|
|
|
|
|
|
|
gboolean p2p_proxy_acquired;
|
2018-10-10 23:08:15 +02:00
|
|
|
gboolean group_proxy_acquired;
|
2018-10-10 18:35:20 +02:00
|
|
|
gboolean p2p_capable;
|
2017-02-14 19:30:21 +01:00
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
gboolean p2p_group_owner;
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
WpsData *wps_data;
|
2017-04-13 10:42:32 +02:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
AssocData * assoc_data;
|
|
|
|
|
|
2015-02-01 03:19:32 -06:00
|
|
|
char * net_path;
|
|
|
|
|
GHashTable * bss_proxies;
|
2015-04-05 23:31:02 -05:00
|
|
|
char * current_bss;
|
2015-02-01 03:19:32 -06:00
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
GHashTable * peer_proxies;
|
|
|
|
|
|
2018-06-15 13:57:30 +02:00
|
|
|
gint64 last_scan; /* timestamp as returned by nm_utils_get_monotonic_timestamp_ms() */
|
2015-02-01 03:19:32 -06:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
} NMSupplicantInterfacePrivate;
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2016-09-28 15:58:24 +02:00
|
|
|
struct _NMSupplicantInterface {
|
|
|
|
|
GObject parent;
|
|
|
|
|
NMSupplicantInterfacePrivate _priv;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct _NMSupplicantInterfaceClass {
|
|
|
|
|
GObjectClass parent;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (NMSupplicantInterface, nm_supplicant_interface, G_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
#define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSupplicantInterface, NM_IS_SUPPLICANT_INTERFACE)
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2016-01-21 15:21:37 +01:00
|
|
|
|
|
|
|
|
#define _NMLOG_DOMAIN LOGD_SUPPLICANT
|
|
|
|
|
#define _NMLOG_PREFIX_NAME "sup-iface"
|
|
|
|
|
#define _NMLOG(level, ...) \
|
|
|
|
|
G_STMT_START { \
|
|
|
|
|
char _sbuf[64]; \
|
2017-03-02 21:17:22 +01:00
|
|
|
const char *__ifname = self ? NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev : NULL; \
|
2016-01-21 15:21:37 +01:00
|
|
|
\
|
2017-03-02 21:17:22 +01:00
|
|
|
nm_log ((level), _NMLOG_DOMAIN, __ifname, NULL, \
|
2016-01-21 15:21:37 +01:00
|
|
|
"%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
|
|
|
|
|
_NMLOG_PREFIX_NAME, \
|
2017-03-02 21:17:22 +01:00
|
|
|
((self) ? nm_sprintf_buf (_sbuf, "[%p,%s]", (self), __ifname) : "") \
|
2016-01-21 15:21:37 +01:00
|
|
|
_NM_UTILS_MACRO_REST(__VA_ARGS__)); \
|
|
|
|
|
} G_STMT_END
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
static void scan_done_emit_signal (NMSupplicantInterface *self);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-15 00:11:16 +01:00
|
|
|
NM_UTILS_LOOKUP_STR_DEFINE (nm_supplicant_interface_state_to_string, NMSupplicantInterfaceState,
|
|
|
|
|
NM_UTILS_LOOKUP_DEFAULT_WARN ("unknown"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_INVALID, "invalid"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_INIT, "init"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_STARTING, "starting"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_READY, "ready"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_DISABLED, "disabled"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, "disconnected"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_INACTIVE, "inactive"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_SCANNING, "scanning"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING, "authenticating"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING, "associating"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED, "associated"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE, "4-way handshake"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE, "group handshake"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_COMPLETED, "completed"),
|
|
|
|
|
NM_UTILS_LOOKUP_STR_ITEM (NM_SUPPLICANT_INTERFACE_STATE_DOWN, "down"),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2006-11-25 18:23:06 +00:00
|
|
|
static void
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data_destroy (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
BssData *bss_data = user_data;
|
|
|
|
|
|
|
|
|
|
nm_clear_g_signal_handler (bss_data->proxy, &bss_data->change_id);
|
|
|
|
|
g_object_unref (bss_data->proxy);
|
|
|
|
|
g_slice_free (BssData, bss_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
bss_proxy_properties_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
char **invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
2012-02-20 15:06:05 -06:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
2012-06-07 15:04:14 -05:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->scanning)
|
2018-06-15 13:57:30 +02:00
|
|
|
priv->last_scan = nm_utils_get_monotonic_timestamp_ms ();
|
2012-02-20 15:06:05 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_signal_emit (self, signals[BSS_UPDATED], 0,
|
|
|
|
|
g_dbus_proxy_get_object_path (proxy),
|
|
|
|
|
changed_properties);
|
2012-02-22 14:44:05 -06:00
|
|
|
}
|
2012-02-20 15:06:05 -06:00
|
|
|
|
2015-09-30 17:05:40 +02:00
|
|
|
static GVariant *
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_proxy_get_properties (NMSupplicantInterface *self, GDBusProxy *proxy)
|
2015-09-30 17:05:40 +02:00
|
|
|
{
|
|
|
|
|
gs_strfreev char **properties = NULL;
|
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
char **iter;
|
|
|
|
|
|
|
|
|
|
iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
|
|
|
|
|
|
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
2017-02-15 11:05:47 +01:00
|
|
|
if (iter) {
|
|
|
|
|
while (*iter) {
|
|
|
|
|
GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
|
2015-09-30 17:05:40 +02:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
g_variant_builder_add (&builder, "{sv}", *iter++, copy);
|
|
|
|
|
g_variant_unref (copy);
|
|
|
|
|
}
|
2015-09-30 17:05:40 +02:00
|
|
|
}
|
|
|
|
|
return g_variant_builder_end (&builder);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-20 15:06:05 -06:00
|
|
|
static void
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_proxy_acquired_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-11-25 18:23:06 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
2017-02-15 11:05:47 +01:00
|
|
|
NMSupplicantInterfacePrivate *priv;
|
2015-02-02 02:31:30 -06:00
|
|
|
gs_free_error GError *error = NULL;
|
2017-02-15 11:05:47 +01:00
|
|
|
GVariant *props = NULL;
|
|
|
|
|
const char *object_path;
|
|
|
|
|
BssData *bss_data;
|
2017-06-02 19:53:43 +02:00
|
|
|
gboolean success;
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2017-06-02 19:53:43 +02:00
|
|
|
success = g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error);
|
|
|
|
|
if ( !success
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
2012-02-20 15:06:05 -06:00
|
|
|
return;
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
2017-02-15 11:05:47 +01:00
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-06-02 19:53:43 +02:00
|
|
|
if (!success) {
|
2017-02-15 11:05:47 +01:00
|
|
|
_LOGD ("failed to acquire BSS proxy: (%s)", error->message);
|
|
|
|
|
g_hash_table_remove (priv->bss_proxies,
|
|
|
|
|
g_dbus_proxy_get_object_path (proxy));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object_path = g_dbus_proxy_get_object_path (proxy);
|
|
|
|
|
bss_data = g_hash_table_lookup (priv->bss_proxies, object_path);
|
|
|
|
|
if (!bss_data)
|
2015-09-30 17:05:40 +02:00
|
|
|
return;
|
2012-06-07 15:04:14 -05:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data->change_id = g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (bss_proxy_properties_changed_cb), self);
|
2012-06-07 15:04:14 -05:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
props = bss_proxy_get_properties (self, proxy);
|
2017-02-15 11:17:55 +01:00
|
|
|
g_signal_emit (self, signals[BSS_UPDATED], 0,
|
2015-02-02 02:31:30 -06:00
|
|
|
g_dbus_proxy_get_object_path (proxy),
|
|
|
|
|
g_variant_ref_sink (props));
|
2017-02-15 11:05:47 +01:00
|
|
|
g_variant_unref (props);
|
|
|
|
|
|
|
|
|
|
if (priv->scan_done_pending)
|
|
|
|
|
scan_done_emit_signal (self);
|
2012-02-20 15:06:05 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_add_new (NMSupplicantInterface *self, const char *object_path)
|
2012-02-20 15:06:05 -06:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2015-02-02 02:31:30 -06:00
|
|
|
GDBusProxy *bss_proxy;
|
2017-02-15 11:05:47 +01:00
|
|
|
BssData *bss_data;
|
2012-02-20 15:06:05 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_return_if_fail (object_path != NULL);
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_hash_table_lookup (priv->bss_proxies, object_path))
|
|
|
|
|
return;
|
2006-12-04 05:45:05 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
bss_proxy = g_object_new (G_TYPE_DBUS_PROXY,
|
|
|
|
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
|
"g-name", WPAS_DBUS_SERVICE,
|
|
|
|
|
"g-object-path", object_path,
|
|
|
|
|
"g-interface-name", WPAS_DBUS_IFACE_BSS,
|
|
|
|
|
NULL);
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data = g_slice_new0 (BssData);
|
|
|
|
|
bss_data->proxy = bss_proxy;
|
2015-02-02 02:31:30 -06:00
|
|
|
g_hash_table_insert (priv->bss_proxies,
|
|
|
|
|
(char *) g_dbus_proxy_get_object_path (bss_proxy),
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data);
|
2015-02-02 02:31:30 -06:00
|
|
|
g_async_initable_init_async (G_ASYNC_INITABLE (bss_proxy),
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
priv->other_cancellable,
|
2017-02-15 11:05:47 +01:00
|
|
|
(GAsyncReadyCallback) bss_proxy_acquired_cb,
|
2015-02-02 02:31:30 -06:00
|
|
|
self);
|
2006-12-04 05:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
static void
|
|
|
|
|
peer_data_destroy (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
PeerData *peer_data = user_data;
|
|
|
|
|
|
|
|
|
|
nm_clear_g_signal_handler (peer_data->proxy, &peer_data->change_id);
|
|
|
|
|
g_object_unref (peer_data->proxy);
|
|
|
|
|
g_slice_free (PeerData, peer_data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
peer_proxy_properties_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
char **invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
|
|
|
|
g_signal_emit (self, signals[PEER_UPDATED], 0,
|
|
|
|
|
g_dbus_proxy_get_object_path (proxy),
|
|
|
|
|
changed_properties);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static GVariant *
|
|
|
|
|
peer_proxy_get_properties (NMSupplicantInterface *self, GDBusProxy *proxy)
|
|
|
|
|
{
|
|
|
|
|
gs_strfreev char **properties = NULL;
|
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
char **iter;
|
|
|
|
|
|
|
|
|
|
iter = properties = g_dbus_proxy_get_cached_property_names (proxy);
|
|
|
|
|
|
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
|
|
|
|
if (iter) {
|
|
|
|
|
while (*iter) {
|
|
|
|
|
GVariant *copy = g_dbus_proxy_get_cached_property (proxy, *iter);
|
|
|
|
|
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", *iter++, copy);
|
|
|
|
|
g_variant_unref (copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return g_variant_builder_end (&builder);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
peer_proxy_acquired_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
GVariant *props = NULL;
|
|
|
|
|
const char *object_path;
|
|
|
|
|
PeerData *peer_data;
|
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
success = g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error);
|
|
|
|
|
if ( !success
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
_LOGD ("failed to acquire Peer proxy: (%s)", error->message);
|
|
|
|
|
g_hash_table_remove (priv->peer_proxies,
|
|
|
|
|
g_dbus_proxy_get_object_path (proxy));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
object_path = g_dbus_proxy_get_object_path (proxy);
|
|
|
|
|
peer_data = g_hash_table_lookup (priv->peer_proxies, object_path);
|
|
|
|
|
if (!peer_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
peer_data->change_id = g_signal_connect (proxy, "g-properties-changed", G_CALLBACK (peer_proxy_properties_changed_cb), self);
|
|
|
|
|
|
|
|
|
|
props = peer_proxy_get_properties (self, proxy);
|
|
|
|
|
|
|
|
|
|
g_signal_emit (self, signals[PEER_UPDATED], 0,
|
|
|
|
|
g_dbus_proxy_get_object_path (proxy),
|
|
|
|
|
g_variant_ref_sink (props));
|
|
|
|
|
g_variant_unref (props);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
peer_add_new (NMSupplicantInterface *self, const char *object_path)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
GDBusProxy *peer_proxy;
|
|
|
|
|
PeerData *peer_data;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (object_path != NULL);
|
|
|
|
|
|
|
|
|
|
if (g_hash_table_lookup (priv->peer_proxies, object_path))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
peer_proxy = g_object_new (G_TYPE_DBUS_PROXY,
|
|
|
|
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
|
"g-name", WPAS_DBUS_SERVICE,
|
|
|
|
|
"g-object-path", object_path,
|
|
|
|
|
"g-interface-name", WPAS_DBUS_IFACE_PEER,
|
|
|
|
|
NULL);
|
|
|
|
|
peer_data = g_slice_new0 (PeerData);
|
|
|
|
|
peer_data->proxy = peer_proxy;
|
|
|
|
|
g_hash_table_insert (priv->peer_proxies,
|
|
|
|
|
(char *) g_dbus_proxy_get_object_path (peer_proxy),
|
|
|
|
|
peer_data);
|
|
|
|
|
g_async_initable_init_async (G_ASYNC_INITABLE (peer_proxy),
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) peer_proxy_acquired_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
static void
|
2017-02-14 01:30:25 +01:00
|
|
|
set_state (NMSupplicantInterface *self, NMSupplicantInterfaceState new_state)
|
2010-10-06 11:05:21 -05:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2017-02-14 01:30:25 +01:00
|
|
|
NMSupplicantInterfaceState old_state = priv->state;
|
2010-10-06 11:05:21 -05:00
|
|
|
|
|
|
|
|
if (new_state == priv->state)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* DOWN is a terminal state */
|
|
|
|
|
g_return_if_fail (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
|
|
|
|
|
2010-12-07 13:58:49 -06:00
|
|
|
/* Cannot regress to READY, STARTING, or INIT from higher states */
|
|
|
|
|
if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY)
|
2010-12-11 12:33:15 -06:00
|
|
|
g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY);
|
2010-10-06 11:05:21 -05:00
|
|
|
|
2012-05-02 13:04:23 -05:00
|
|
|
if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
2017-02-15 00:16:38 +01:00
|
|
|
nm_clear_g_cancellable (&priv->other_cancellable);
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->other_cancellable = g_cancellable_new ();
|
|
|
|
|
} else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) {
|
2017-02-15 00:16:38 +01:00
|
|
|
nm_clear_g_cancellable (&priv->init_cancellable);
|
|
|
|
|
nm_clear_g_cancellable (&priv->other_cancellable);
|
2015-02-02 02:31:30 -06:00
|
|
|
|
|
|
|
|
if (priv->iface_proxy)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (priv->iface_proxy, self);
|
2010-10-06 11:05:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv->state = new_state;
|
2012-06-07 15:04:14 -05:00
|
|
|
|
|
|
|
|
if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
|
|
|
|
|
|| old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
|
2018-06-15 13:57:30 +02:00
|
|
|
priv->last_scan = nm_utils_get_monotonic_timestamp_ms ();
|
2012-06-07 15:04:14 -05:00
|
|
|
|
2012-09-12 11:58:41 -05:00
|
|
|
/* Disconnect reason is no longer relevant when not in the DISCONNECTED state */
|
|
|
|
|
if (priv->state != NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED)
|
|
|
|
|
priv->disconnect_reason = 0;
|
|
|
|
|
|
|
|
|
|
g_signal_emit (self, signals[STATE], 0,
|
2017-02-14 01:30:25 +01:00
|
|
|
(int) priv->state,
|
|
|
|
|
(int) old_state,
|
|
|
|
|
(int) priv->disconnect_reason);
|
2010-10-06 11:05:21 -05:00
|
|
|
}
|
|
|
|
|
|
2017-02-14 01:30:25 +01:00
|
|
|
static NMSupplicantInterfaceState
|
2015-02-02 02:31:30 -06:00
|
|
|
wpas_state_string_to_enum (const char *str_state)
|
|
|
|
|
{
|
|
|
|
|
if (!strcmp (str_state, "interface_disabled"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_DISABLED;
|
|
|
|
|
else if (!strcmp (str_state, "disconnected"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED;
|
|
|
|
|
else if (!strcmp (str_state, "inactive"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE;
|
|
|
|
|
else if (!strcmp (str_state, "scanning"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_SCANNING;
|
|
|
|
|
else if (!strcmp (str_state, "authenticating"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING;
|
|
|
|
|
else if (!strcmp (str_state, "associating"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING;
|
|
|
|
|
else if (!strcmp (str_state, "associated"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED;
|
|
|
|
|
else if (!strcmp (str_state, "4way_handshake"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE;
|
|
|
|
|
else if (!strcmp (str_state, "group_handshake"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE;
|
|
|
|
|
else if (!strcmp (str_state, "completed"))
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_COMPLETED;
|
|
|
|
|
|
2017-02-14 01:30:25 +01:00
|
|
|
return NM_SUPPLICANT_INTERFACE_STATE_INVALID;
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
|
|
|
|
|
2006-12-04 05:45:05 +00:00
|
|
|
static void
|
2010-11-22 08:25:09 -06:00
|
|
|
set_state_from_string (NMSupplicantInterface *self, const char *new_state)
|
2006-12-04 05:45:05 +00:00
|
|
|
{
|
2017-02-14 01:30:25 +01:00
|
|
|
NMSupplicantInterfaceState state;
|
2010-10-11 20:35:54 -05:00
|
|
|
|
2010-11-22 08:25:09 -06:00
|
|
|
state = wpas_state_string_to_enum (new_state);
|
2017-02-14 01:30:25 +01:00
|
|
|
if (state == NM_SUPPLICANT_INTERFACE_STATE_INVALID) {
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGW ("unknown supplicant state '%s'", new_state);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-02-14 01:30:25 +01:00
|
|
|
set_state (self, state);
|
2006-12-04 05:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
2006-12-12 03:27:35 +00:00
|
|
|
static void
|
2010-11-22 08:25:09 -06:00
|
|
|
set_scanning (NMSupplicantInterface *self, gboolean new_scanning)
|
2006-12-12 03:27:35 +00:00
|
|
|
{
|
2010-11-22 08:25:09 -06:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2010-11-22 08:25:09 -06:00
|
|
|
if (priv->scanning != new_scanning) {
|
|
|
|
|
priv->scanning = new_scanning;
|
|
|
|
|
|
|
|
|
|
/* Cache time of last scan completion */
|
2012-06-07 13:45:51 -05:00
|
|
|
if (priv->scanning == FALSE)
|
2018-06-15 13:57:30 +02:00
|
|
|
priv->last_scan = nm_utils_get_monotonic_timestamp_ms ();
|
2010-10-11 20:35:54 -05:00
|
|
|
|
2016-01-19 16:08:29 +01:00
|
|
|
_notify (self, PROP_SCANNING);
|
2006-12-12 03:27:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-22 08:25:09 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
2017-02-02 17:16:27 +01:00
|
|
|
g_return_val_if_fail (self, FALSE);
|
2010-11-22 08:25:09 -06:00
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
if (priv->scanning)
|
|
|
|
|
return TRUE;
|
|
|
|
|
if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
|
|
|
|
|
return TRUE;
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-05 23:31:02 -05:00
|
|
|
const char *
|
|
|
|
|
nm_supplicant_interface_get_current_bss (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
return priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY ? priv->current_bss : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-15 13:57:30 +02:00
|
|
|
gint64
|
|
|
|
|
nm_supplicant_interface_get_last_scan (NMSupplicantInterface *self)
|
2012-06-07 15:04:14 -05:00
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
#define MATCH_PROPERTY(p, n, v, t) (!strcmp (p, n) && g_variant_is_of_type (v, t))
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2012-05-01 17:59:35 -05:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
|
2012-05-01 17:59:35 -05:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2018-10-10 18:35:20 +02:00
|
|
|
gboolean have_active = FALSE, have_p2p = FALSE, have_ssid = FALSE;
|
2015-02-02 02:31:30 -06:00
|
|
|
gint32 max_scan_ssids = -1;
|
|
|
|
|
const char **array;
|
2012-05-01 17:59:35 -05:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_return_if_fail (capabilities && g_variant_is_of_type (capabilities, G_VARIANT_TYPE_VARDICT));
|
2012-05-01 17:59:35 -05:00
|
|
|
|
2018-10-10 18:35:20 +02:00
|
|
|
if ( g_variant_lookup (capabilities, "Modes", "^a&s", &array)
|
|
|
|
|
&& array) {
|
|
|
|
|
if (g_strv_contains (array, "p2p"))
|
|
|
|
|
have_p2p = TRUE;
|
|
|
|
|
g_free (array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (priv->p2p_capable != have_p2p) {
|
|
|
|
|
priv->p2p_capable = have_p2p;
|
|
|
|
|
_notify (self, PROP_P2P_AVAILABLE);
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-17 11:40:50 +02:00
|
|
|
if ( g_variant_lookup (capabilities, "Scan", "^a&s", &array)
|
|
|
|
|
&& array) {
|
|
|
|
|
if (g_strv_contains (array, "active"))
|
2015-02-02 02:31:30 -06:00
|
|
|
have_active = TRUE;
|
2016-06-17 11:40:50 +02:00
|
|
|
if (g_strv_contains (array, "ssid"))
|
2015-02-02 02:31:30 -06:00
|
|
|
have_ssid = TRUE;
|
|
|
|
|
g_free (array);
|
2012-05-01 17:59:35 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_variant_lookup (capabilities, "MaxScanSSID", "i", &max_scan_ssids)) {
|
2012-05-01 17:59:35 -05:00
|
|
|
/* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */
|
2015-02-02 02:31:30 -06:00
|
|
|
if (max_scan_ssids > 0 && have_active && have_ssid) {
|
2012-05-01 17:59:35 -05:00
|
|
|
/* wpa_supplicant's WPAS_MAX_SCAN_SSIDS value is 16, but for speed
|
|
|
|
|
* and to ensure we don't disclose too many SSIDs from the hidden
|
|
|
|
|
* list, we'll limit to 5.
|
|
|
|
|
*/
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->max_scan_ssids = CLAMP (max_scan_ssids, 0, 5);
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGI ("supports %d scan SSIDs", priv->max_scan_ssids);
|
2012-09-12 11:58:41 -05:00
|
|
|
}
|
|
|
|
|
}
|
2010-11-22 08:25:09 -06:00
|
|
|
}
|
|
|
|
|
|
2012-05-02 13:04:23 -05:00
|
|
|
static void
|
|
|
|
|
iface_check_ready (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->ready_count && priv->state < NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
|
|
|
|
priv->ready_count--;
|
|
|
|
|
if (priv->ready_count == 0)
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-12-19 19:47:43 -06:00
|
|
|
gboolean
|
|
|
|
|
nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self,
|
|
|
|
|
const char *field,
|
|
|
|
|
const char *value,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
2015-02-02 02:31:30 -06:00
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
2011-12-19 19:47:43 -06:00
|
|
|
|
|
|
|
|
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (field != NULL, FALSE);
|
|
|
|
|
g_return_val_if_fail (value != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
g_return_val_if_fail (priv->has_credreq == TRUE, FALSE);
|
|
|
|
|
|
|
|
|
|
/* Need a network block object path */
|
|
|
|
|
g_return_val_if_fail (priv->net_path, FALSE);
|
2015-02-02 02:31:30 -06:00
|
|
|
reply = g_dbus_proxy_call_sync (priv->iface_proxy,
|
|
|
|
|
"NetworkReply",
|
|
|
|
|
g_variant_new ("(oss)",
|
|
|
|
|
priv->net_path,
|
|
|
|
|
field,
|
|
|
|
|
value),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
5000,
|
|
|
|
|
NULL,
|
|
|
|
|
error);
|
2015-04-21 09:52:25 -04:00
|
|
|
if (error && *error)
|
|
|
|
|
g_dbus_error_strip_remote_error (*error);
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
return !!reply;
|
2011-12-19 19:47:43 -06:00
|
|
|
}
|
|
|
|
|
|
2011-12-19 17:21:41 -06:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
iface_check_netreply_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2011-12-19 17:21:41 -06:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
/* We know NetworkReply is supported if the NetworkReply method returned
|
|
|
|
|
* successfully (which is unexpected since we sent a bogus network
|
|
|
|
|
* object path) or if we got an "InvalidArgs" (which indicates NetworkReply
|
|
|
|
|
* is supported). We know it's not supported if we get an
|
|
|
|
|
* "UnknownMethod" error.
|
|
|
|
|
*/
|
2011-12-19 17:21:41 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
variant = g_dbus_proxy_call_finish (proxy, result, &error);
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
2012-05-02 13:04:23 -05:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2011-12-19 17:21:41 -06:00
|
|
|
|
2015-03-27 09:04:41 -04:00
|
|
|
if (variant || _nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.InvalidArgs"))
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->has_credreq = TRUE;
|
2011-12-19 17:21:41 -06:00
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGD ("supplicant %s network credentials requests",
|
|
|
|
|
priv->has_credreq ? "supports" : "does not support");
|
2015-02-02 02:31:30 -06:00
|
|
|
|
|
|
|
|
iface_check_ready (self);
|
2011-12-19 17:21:41 -06:00
|
|
|
}
|
|
|
|
|
|
2019-01-09 11:36:52 +01:00
|
|
|
static void
|
|
|
|
|
iface_set_pmf_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
variant = g_dbus_proxy_call_finish (proxy, result, &error);
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
|
|
|
|
if (error)
|
2019-02-25 08:38:22 +01:00
|
|
|
_LOGW ("failed to set Pmf=1: %s", error->message);
|
2019-01-09 11:36:52 +01:00
|
|
|
|
|
|
|
|
iface_check_ready (self);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_supplicant_interface_get_p2p_group_joined (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->group_proxy_acquired;
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-11 18:21:37 +01:00
|
|
|
const char*
|
|
|
|
|
nm_supplicant_interface_get_p2p_group_path (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->group_proxy_acquired)
|
|
|
|
|
return g_dbus_proxy_get_object_path (priv->group_proxy);
|
|
|
|
|
else
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
gboolean
|
|
|
|
|
nm_supplicant_interface_get_p2p_group_owner (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->p2p_group_owner;
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-06 20:02:40 -05:00
|
|
|
NMSupplicantFeature
|
2012-09-18 17:33:57 -05:00
|
|
|
nm_supplicant_interface_get_ap_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ap_support;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 13:39:43 +02:00
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->pmf_support;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-16 06:28:37 +09:00
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_fils_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->fils_support;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 17:50:34 +02:00
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_p2p_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->p2p_support;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_wfd_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->wfd_support;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 11:30:15 +00:00
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_ft_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ft_support;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 11:30:19 +00:00
|
|
|
NMSupplicantFeature
|
|
|
|
|
nm_supplicant_interface_get_sha384_support (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->sha384_support;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-18 17:33:57 -05:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
|
2015-10-06 20:02:40 -05:00
|
|
|
NMSupplicantFeature ap_support)
|
2012-09-18 17:33:57 -05:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Use the best indicator of support between the supplicant global
|
|
|
|
|
* Capabilities property and the interface's introspection data.
|
|
|
|
|
*/
|
|
|
|
|
if (ap_support > priv->ap_support)
|
|
|
|
|
priv->ap_support = ap_support;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-18 17:41:12 +01:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_fast_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature fast_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->fast_support = fast_support;
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-18 14:56:38 +01:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_pmf_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature pmf_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->pmf_support = pmf_support;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-16 06:28:37 +09:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_fils_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature fils_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->fils_support = fils_support;
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 17:50:34 +02:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_p2p_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature p2p_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->p2p_support = p2p_support;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_wfd_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature wfd_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->wfd_support = wfd_support;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 11:30:15 +00:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_ft_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature ft_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->ft_support = ft_support;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-15 11:30:19 +00:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_sha384_support (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantFeature sha384_support)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
priv->sha384_support = sha384_support;
|
|
|
|
|
}
|
|
|
|
|
|
2017-06-03 14:41:29 +02:00
|
|
|
/*****************************************************************************/
|
2017-04-13 10:42:32 +02:00
|
|
|
|
|
|
|
|
static void
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
_wps_data_free (WpsData *data)
|
2017-04-13 10:42:32 +02:00
|
|
|
{
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_free (data->type);
|
2017-04-13 10:42:32 +02:00
|
|
|
g_free (data->pin);
|
|
|
|
|
g_free (data->bssid);
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_clear_object (&data->cancellable);
|
|
|
|
|
if (data->proxy && data->self)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (data->proxy, data->self);
|
|
|
|
|
g_clear_object (&data->proxy);
|
|
|
|
|
g_slice_free (WpsData, data);
|
2017-04-13 10:42:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
_wps_credentials_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *props,
|
|
|
|
|
gpointer user_data)
|
2017-04-13 10:42:32 +02:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
_LOGT ("wps: new credentials");
|
2017-04-13 10:42:32 +02:00
|
|
|
g_signal_emit (self, signals[WPS_CREDENTIALS], 0, props);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
_wps_handle_start_cb (GObject *source_object,
|
|
|
|
|
GAsyncResult *res,
|
|
|
|
|
gpointer user_data)
|
2017-04-13 10:42:32 +02:00
|
|
|
{
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
WpsData *data;
|
|
|
|
|
gs_unref_variant GVariant *result = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
|
|
|
|
|
if ( !result
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
data = user_data;
|
|
|
|
|
self = data->self;
|
|
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
|
_LOGT ("wps: started with success");
|
|
|
|
|
else
|
|
|
|
|
_LOGW ("wps: start failed with %s", error->message);
|
|
|
|
|
|
|
|
|
|
g_clear_object (&data->cancellable);
|
|
|
|
|
nm_clear_g_free (&data->type);
|
|
|
|
|
nm_clear_g_free (&data->pin);
|
|
|
|
|
nm_clear_g_free (&data->bssid);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_wps_handle_set_pc_cb (GObject *source_object,
|
|
|
|
|
GAsyncResult *res,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
WpsData *data;
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
gs_unref_variant GVariant *result = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2017-04-13 10:42:32 +02:00
|
|
|
GVariantBuilder start_args;
|
|
|
|
|
guint8 bssid_buf[ETH_ALEN];
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
|
|
|
|
|
if ( !result
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
2017-04-13 10:42:32 +02:00
|
|
|
return;
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
data = user_data;
|
|
|
|
|
self = data->self;
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
if (result)
|
|
|
|
|
_LOGT ("wps: ProcessCredentials successfully set, starting...");
|
|
|
|
|
else
|
|
|
|
|
_LOGW ("wps: ProcessCredentials failed to set (%s), starting...", error->message);
|
|
|
|
|
|
|
|
|
|
_nm_dbus_signal_connect (data->proxy, "Credentials", G_VARIANT_TYPE ("(a{sv})"),
|
|
|
|
|
G_CALLBACK (_wps_credentials_changed_cb), self);
|
2017-04-13 10:42:32 +02:00
|
|
|
|
|
|
|
|
g_variant_builder_init (&start_args, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_add (&start_args, "{sv}", "Role", g_variant_new_string ("enrollee"));
|
|
|
|
|
g_variant_builder_add (&start_args, "{sv}", "Type", g_variant_new_string (data->type));
|
|
|
|
|
if (data->pin)
|
|
|
|
|
g_variant_builder_add (&start_args, "{sv}", "Pin", g_variant_new_string (data->pin));
|
|
|
|
|
|
|
|
|
|
if (data->bssid) {
|
|
|
|
|
/* The BSSID is in fact not mandatory. If it is not set the supplicant would
|
|
|
|
|
* enroll with any BSS in range. */
|
|
|
|
|
if (!nm_utils_hwaddr_aton (data->bssid, bssid_buf, sizeof (bssid_buf)))
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
nm_assert_not_reached ();
|
2017-04-13 10:42:32 +02:00
|
|
|
g_variant_builder_add (&start_args, "{sv}", "Bssid",
|
|
|
|
|
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, bssid_buf,
|
|
|
|
|
ETH_ALEN, sizeof (guint8)));
|
|
|
|
|
}
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_dbus_proxy_call (data->proxy,
|
2017-04-13 10:42:32 +02:00
|
|
|
"Start",
|
|
|
|
|
g_variant_new ("(a{sv})", &start_args),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
data->cancellable,
|
|
|
|
|
_wps_handle_start_cb,
|
|
|
|
|
data);
|
2017-04-13 10:42:32 +02:00
|
|
|
}
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
static void
|
|
|
|
|
_wps_call_set_pc (WpsData *data)
|
2017-04-13 10:42:32 +02:00
|
|
|
{
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_dbus_proxy_call (data->proxy,
|
|
|
|
|
"org.freedesktop.DBus.Properties.Set",
|
|
|
|
|
g_variant_new ("(ssv)",
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE_WPS,
|
|
|
|
|
"ProcessCredentials",
|
|
|
|
|
g_variant_new_boolean (TRUE)),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
data->cancellable,
|
|
|
|
|
_wps_handle_set_pc_cb,
|
|
|
|
|
data);
|
|
|
|
|
}
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
static void
|
|
|
|
|
_wps_handle_proxy_cb (GObject *source_object,
|
|
|
|
|
GAsyncResult *res,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
WpsData *data;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
GDBusProxy *proxy;
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
|
|
|
|
|
if ( !proxy
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
data = user_data;
|
|
|
|
|
self = data->self;
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
if (!proxy) {
|
|
|
|
|
_LOGW ("wps: failure to create D-Bus proxy: %s", error->message);
|
|
|
|
|
_wps_data_free (data);
|
|
|
|
|
priv->wps_data = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data->proxy = proxy;
|
|
|
|
|
_LOGT ("wps: D-Bus proxy created. set ProcessCredentials...");
|
|
|
|
|
_wps_call_set_pc (data);
|
2017-04-13 10:42:32 +02:00
|
|
|
}
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
static void
|
|
|
|
|
_wps_handle_cancel_cb (GObject *source_object,
|
|
|
|
|
GAsyncResult *res,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
WpsData *data;
|
|
|
|
|
gs_unref_variant GVariant *result = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
|
|
|
|
|
if ( !result
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
data = user_data;
|
|
|
|
|
self = data->self;
|
|
|
|
|
|
|
|
|
|
if (!self) {
|
|
|
|
|
_wps_data_free (data);
|
|
|
|
|
if (result)
|
|
|
|
|
_LOGT ("wps: cancel completed successfully, after supplicant interface is gone");
|
|
|
|
|
else
|
|
|
|
|
_LOGW ("wps: cancel failed (%s), after supplicant interface is gone", error->message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
data->is_cancelling = FALSE;
|
|
|
|
|
|
|
|
|
|
if (!data->type) {
|
|
|
|
|
priv->wps_data = NULL;
|
|
|
|
|
_wps_data_free (data);
|
|
|
|
|
if (result)
|
|
|
|
|
_LOGT ("wps: cancel completed successfully");
|
|
|
|
|
else
|
|
|
|
|
_LOGW ("wps: cancel failed (%s)", error->message);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
|
_LOGT ("wps: cancel completed successfully, setting ProcessCredentials now...");
|
|
|
|
|
else
|
|
|
|
|
_LOGW ("wps: cancel failed (%s), setting ProcessCredentials now...", error->message);
|
|
|
|
|
_wps_call_set_pc (data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_wps_start (NMSupplicantInterface *self,
|
|
|
|
|
const char *type,
|
|
|
|
|
const char *bssid,
|
|
|
|
|
const char *pin)
|
2017-04-13 10:42:32 +02:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
WpsData *data = priv->wps_data;
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
if (type)
|
|
|
|
|
_LOGI ("wps: type %s start...", type);
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
if (!data) {
|
|
|
|
|
if (!type)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
data = g_slice_new0 (WpsData);
|
|
|
|
|
data->self = self;
|
|
|
|
|
data->type = g_strdup (type);
|
|
|
|
|
data->bssid = g_strdup (bssid);
|
|
|
|
|
data->pin = g_strdup (pin);
|
|
|
|
|
data->cancellable = g_cancellable_new ();
|
|
|
|
|
|
|
|
|
|
priv->wps_data = data;
|
|
|
|
|
|
|
|
|
|
_LOGT ("wps: create D-Bus proxy...");
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
|
|
|
|
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
|
|
|
|
NULL,
|
|
|
|
|
WPAS_DBUS_SERVICE,
|
|
|
|
|
priv->object_path,
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE_WPS,
|
|
|
|
|
data->cancellable,
|
|
|
|
|
_wps_handle_proxy_cb,
|
|
|
|
|
data);
|
2017-04-13 10:42:32 +02:00
|
|
|
return;
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
}
|
2017-04-13 10:42:32 +02:00
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_free (data->type);
|
|
|
|
|
g_free (data->bssid);
|
|
|
|
|
g_free (data->pin);
|
|
|
|
|
data->type = g_strdup (type);
|
|
|
|
|
data->bssid = g_strdup (bssid);
|
|
|
|
|
data->pin = g_strdup (pin);
|
|
|
|
|
|
|
|
|
|
if (!data->proxy) {
|
|
|
|
|
if (!type) {
|
|
|
|
|
nm_clear_g_cancellable (&data->cancellable);
|
|
|
|
|
priv->wps_data = NULL;
|
|
|
|
|
_wps_data_free (data);
|
|
|
|
|
|
|
|
|
|
_LOGT ("wps: abort creation of D-Bus proxy");
|
|
|
|
|
} else
|
|
|
|
|
_LOGT ("wps: new enrollment. Wait for D-Bus proxy...");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data->is_cancelling)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_LOGT ("wps: cancel previous enrollment...");
|
|
|
|
|
|
|
|
|
|
data->is_cancelling = TRUE;
|
2017-06-14 13:52:40 +02:00
|
|
|
nm_clear_g_cancellable (&data->cancellable);
|
|
|
|
|
data->cancellable = g_cancellable_new ();
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
g_signal_handlers_disconnect_by_data (data->proxy, self);
|
|
|
|
|
g_dbus_proxy_call (data->proxy,
|
2017-04-13 10:42:32 +02:00
|
|
|
"Cancel",
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
data->cancellable,
|
|
|
|
|
_wps_handle_cancel_cb,
|
|
|
|
|
data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self,
|
|
|
|
|
const char *type,
|
|
|
|
|
const char *bssid,
|
|
|
|
|
const char *pin)
|
|
|
|
|
{
|
|
|
|
|
_wps_start (self, type, bssid, pin);
|
2017-04-13 10:42:32 +02:00
|
|
|
}
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_cancel_wps (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
_wps_start (self, NULL, NULL, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2012-09-18 17:33:57 -05:00
|
|
|
static void
|
2015-10-06 21:31:04 -05:00
|
|
|
iface_introspect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2012-09-18 17:33:57 -05:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
const char *data;
|
2012-09-18 17:33:57 -05:00
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
variant = _nm_dbus_proxy_call_finish (proxy, result,
|
|
|
|
|
G_VARIANT_TYPE ("(s)"),
|
|
|
|
|
&error);
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
if (variant) {
|
2015-02-02 02:31:30 -06:00
|
|
|
g_variant_get (variant, "(&s)", &data);
|
2015-10-06 21:31:04 -05:00
|
|
|
|
|
|
|
|
/* The ProbeRequest method only exists if AP mode has been enabled */
|
2015-02-02 02:31:30 -06:00
|
|
|
if (strstr (data, "ProbeRequest"))
|
2015-10-06 20:02:40 -05:00
|
|
|
priv->ap_support = NM_SUPPLICANT_FEATURE_YES;
|
2012-09-18 17:33:57 -05:00
|
|
|
}
|
|
|
|
|
|
2013-06-05 08:01:46 -05:00
|
|
|
iface_check_ready (self);
|
2012-09-18 17:33:57 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-27 08:03:22 -04:00
|
|
|
static void
|
2017-02-15 11:05:47 +01:00
|
|
|
scan_done_emit_signal (NMSupplicantInterface *self)
|
2015-03-27 08:03:22 -04:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2017-02-15 11:05:47 +01:00
|
|
|
const char *object_path;
|
|
|
|
|
BssData *bss_data;
|
|
|
|
|
gboolean success;
|
2015-09-30 17:05:40 +02:00
|
|
|
GHashTableIter iter;
|
2015-03-27 08:03:22 -04:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
g_hash_table_iter_init (&iter, priv->bss_proxies);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &bss_data)) {
|
|
|
|
|
/* we have some BSS' that need to be initialized first. Delay
|
|
|
|
|
* emitting signal. */
|
|
|
|
|
if (!bss_data->change_id) {
|
|
|
|
|
priv->scan_done_pending = TRUE;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-27 08:03:22 -04:00
|
|
|
|
2017-02-15 11:17:55 +01:00
|
|
|
/* Emit BSS_UPDATED so that wifi device has the APs (in case it removed them) */
|
2015-09-30 17:05:40 +02:00
|
|
|
g_hash_table_iter_init (&iter, priv->bss_proxies);
|
2017-02-15 11:05:47 +01:00
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer *) &object_path, (gpointer *) &bss_data)) {
|
|
|
|
|
gs_unref_variant GVariant *props = NULL;
|
|
|
|
|
|
|
|
|
|
props = bss_proxy_get_properties (self, bss_data->proxy);
|
|
|
|
|
g_signal_emit (self, signals[BSS_UPDATED], 0,
|
|
|
|
|
object_path,
|
|
|
|
|
g_variant_ref_sink (props));
|
2015-09-30 17:05:40 +02:00
|
|
|
}
|
2017-02-02 22:30:37 +01:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
success = priv->scan_done_success;
|
|
|
|
|
priv->scan_done_success = FALSE;
|
|
|
|
|
priv->scan_done_pending = FALSE;
|
2017-02-02 22:30:37 +01:00
|
|
|
g_signal_emit (self, signals[SCAN_DONE], 0, success);
|
2015-03-27 08:03:22 -04:00
|
|
|
}
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
static void
|
|
|
|
|
wpas_iface_scan_done (GDBusProxy *proxy,
|
|
|
|
|
gboolean success,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Cache last scan completed time */
|
2018-06-15 13:57:30 +02:00
|
|
|
priv->last_scan = nm_utils_get_monotonic_timestamp_ms ();
|
2017-02-15 11:05:47 +01:00
|
|
|
priv->scan_done_success |= success;
|
|
|
|
|
scan_done_emit_signal (self);
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-18 17:33:57 -05:00
|
|
|
static void
|
2015-03-27 08:03:22 -04:00
|
|
|
wpas_iface_bss_added (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
GVariant *props,
|
|
|
|
|
gpointer user_data)
|
2012-09-18 17:33:57 -05:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
2012-09-18 17:33:57 -05:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-03-27 08:03:22 -04:00
|
|
|
if (priv->scanning)
|
2018-06-15 13:57:30 +02:00
|
|
|
priv->last_scan = nm_utils_get_monotonic_timestamp_ms ();
|
2012-09-18 17:33:57 -05:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_add_new (self, path);
|
2015-03-27 08:03:22 -04:00
|
|
|
}
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2015-03-27 08:03:22 -04:00
|
|
|
static void
|
|
|
|
|
wpas_iface_bss_removed (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2017-02-15 11:05:47 +01:00
|
|
|
BssData *bss_data;
|
2015-03-27 08:03:22 -04:00
|
|
|
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data = g_hash_table_lookup (priv->bss_proxies, path);
|
|
|
|
|
if (!bss_data)
|
|
|
|
|
return;
|
|
|
|
|
g_hash_table_steal (priv->bss_proxies, path);
|
2015-03-27 08:03:22 -04:00
|
|
|
g_signal_emit (self, signals[BSS_REMOVED], 0, path);
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_data_destroy (bss_data);
|
2015-03-27 08:03:22 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wpas_iface_network_request (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
const char *field,
|
|
|
|
|
const char *message,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (priv->has_credreq && priv->net_path && !g_strcmp0 (path, priv->net_path))
|
|
|
|
|
g_signal_emit (self, signals[CREDENTIALS_REQUEST], 0, field, message);
|
2012-09-18 17:33:57 -05:00
|
|
|
}
|
|
|
|
|
|
2006-11-25 15:41:04 +00:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
props_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
GStrv invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
2010-10-06 11:05:21 -05:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
2010-10-06 11:05:21 -05:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2015-02-02 02:31:30 -06:00
|
|
|
const char *s, **array, **iter;
|
|
|
|
|
gboolean b = FALSE;
|
|
|
|
|
gint32 i32;
|
|
|
|
|
GVariant *v;
|
|
|
|
|
|
2015-04-05 23:31:02 -05:00
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_variant_lookup (changed_properties, "Scanning", "b", &b))
|
|
|
|
|
set_scanning (self, b);
|
|
|
|
|
|
|
|
|
|
if ( g_variant_lookup (changed_properties, "State", "&s", &s)
|
|
|
|
|
&& priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) {
|
|
|
|
|
/* Only transition to actual wpa_supplicant interface states (ie,
|
|
|
|
|
* anything > READY) after the NMSupplicantInterface has had a
|
|
|
|
|
* chance to initialize, which is signalled by entering the READY
|
|
|
|
|
* state.
|
|
|
|
|
*/
|
|
|
|
|
set_state_from_string (self, s);
|
|
|
|
|
}
|
2010-10-06 11:05:21 -05:00
|
|
|
|
2015-09-30 13:08:05 +02:00
|
|
|
if (g_variant_lookup (changed_properties, "BSSs", "^a&o", &array)) {
|
2015-02-02 02:31:30 -06:00
|
|
|
iter = array;
|
|
|
|
|
while (*iter)
|
2017-02-15 11:05:47 +01:00
|
|
|
bss_add_new (self, *iter++);
|
2015-02-02 02:31:30 -06:00
|
|
|
g_free (array);
|
|
|
|
|
}
|
2010-10-06 11:05:21 -05:00
|
|
|
|
2015-04-05 23:31:02 -05:00
|
|
|
if (g_variant_lookup (changed_properties, "CurrentBSS", "&o", &s)) {
|
2018-04-11 17:05:00 +02:00
|
|
|
s = nm_utils_dbus_normalize_object_path (s);
|
|
|
|
|
if (!nm_streq0 (s, priv->current_bss)) {
|
2015-04-05 23:31:02 -05:00
|
|
|
g_free (priv->current_bss);
|
|
|
|
|
priv->current_bss = g_strdup (s);
|
2016-01-19 16:08:29 +01:00
|
|
|
_notify (self, PROP_CURRENT_BSS);
|
2015-04-05 23:31:02 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
v = g_variant_lookup_value (changed_properties, "Capabilities", G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
if (v) {
|
|
|
|
|
parse_capabilities (self, v);
|
|
|
|
|
g_variant_unref (v);
|
|
|
|
|
}
|
2012-09-18 17:33:57 -05:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_variant_lookup (changed_properties, "DisconnectReason", "i", &i32)) {
|
|
|
|
|
/* Disconnect reason is currently only given for deauthentication events,
|
|
|
|
|
* not disassociation; currently they are IEEE 802.11 "reason codes",
|
|
|
|
|
* defined by (IEEE 802.11-2007, 7.3.1.7, Table 7-22). Any locally caused
|
|
|
|
|
* deauthentication will be negative, while authentications caused by the
|
|
|
|
|
* AP will be positive.
|
|
|
|
|
*/
|
|
|
|
|
priv->disconnect_reason = i32;
|
2016-01-21 15:21:37 +01:00
|
|
|
if (priv->disconnect_reason != 0)
|
|
|
|
|
_LOGW ("connection disconnected (reason %d)", priv->disconnect_reason);
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
2015-04-05 23:31:02 -05:00
|
|
|
|
2018-10-10 22:43:49 +02:00
|
|
|
/* We may not have priv->dev set yet if this interface was created from a
|
|
|
|
|
* known wpa_supplicant interface without knowing the device name.
|
|
|
|
|
*/
|
|
|
|
|
if (priv->dev == NULL && g_variant_lookup (changed_properties, "Ifname", "&s", &s)) {
|
|
|
|
|
priv->dev = g_strdup (s);
|
|
|
|
|
_notify (self, PROP_IFACE);
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-05 23:31:02 -05:00
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
2010-10-06 11:05:21 -05:00
|
|
|
}
|
|
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
static void
|
|
|
|
|
group_props_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
char **invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
v = g_variant_lookup_value (properties, "BSSID", 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)
|
|
|
|
|
nm_wifi_p2p_group_set_bssid_bin (group, bytes);
|
|
|
|
|
g_variant_unref (v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
v = g_variant_lookup_value (properties, "SSID", G_VARIANT_TYPE_BYTESTRING);
|
|
|
|
|
if (v) {
|
|
|
|
|
bytes = g_variant_get_fixed_array (v, &len, 1);
|
|
|
|
|
len = MIN (32, len);
|
|
|
|
|
|
|
|
|
|
/* Stupid ieee80211 layer uses <hidden> */
|
|
|
|
|
if ( bytes && len
|
|
|
|
|
&& !(((len == 8) || (len == 9)) && !memcmp (bytes, "<hidden>", 8))
|
|
|
|
|
&& !nm_utils_is_empty_ssid (bytes, len))
|
|
|
|
|
nm_wifi_p2p_group_set_ssid (group, bytes, len);
|
|
|
|
|
|
|
|
|
|
g_variant_unref (v);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (g_variant_lookup (changed_properties, "Role", "s", &s)) {
|
|
|
|
|
priv->p2p_group_owner = g_strcmp0 (s, "GO") == 0;
|
|
|
|
|
_notify (self, PROP_P2P_GROUP_OWNER);
|
|
|
|
|
g_free (s);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-11 18:21:37 +01:00
|
|
|
/* NOTE: We do not seem to get any property change notifications for the Members
|
|
|
|
|
* property. However, we can keep track of these indirectly either by querying
|
|
|
|
|
* the groups that each peer is in or listening to the Join/Disconnect
|
|
|
|
|
* notifications.
|
|
|
|
|
*/
|
2018-10-10 23:08:15 +02:00
|
|
|
|
|
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
group_proxy_acquired_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gboolean success;
|
|
|
|
|
|
|
|
|
|
success = g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error);
|
|
|
|
|
if ( !success
|
|
|
|
|
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (!success) {
|
|
|
|
|
_LOGD ("failed to acquire Group proxy: (%s)", error->message);
|
|
|
|
|
g_clear_object (&priv->group_proxy);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
priv->group_proxy_acquired = TRUE;
|
|
|
|
|
_notify (self, PROP_P2P_GROUP_JOINED);
|
2018-12-11 18:21:37 +01:00
|
|
|
_notify (self, PROP_P2P_GROUP_PATH);
|
2018-10-10 23:08:15 +02:00
|
|
|
|
|
|
|
|
iface_check_ready (self);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
static void
|
|
|
|
|
p2p_props_changed_cb (GDBusProxy *proxy,
|
|
|
|
|
GVariant *changed_properties,
|
|
|
|
|
GStrv invalidated_properties,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
2018-10-10 23:08:15 +02:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2018-10-10 21:27:34 +02:00
|
|
|
const char **array, **iter;
|
2018-10-10 23:08:15 +02:00
|
|
|
const char *path = NULL;
|
2018-10-10 21:27:34 +02:00
|
|
|
|
|
|
|
|
g_object_freeze_notify (G_OBJECT (self));
|
|
|
|
|
|
|
|
|
|
if (g_variant_lookup (changed_properties, "Peers", "^a&o", &array)) {
|
|
|
|
|
iter = array;
|
|
|
|
|
while (*iter)
|
|
|
|
|
peer_add_new (self, *iter++);
|
|
|
|
|
g_free (array);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
if (g_variant_lookup (changed_properties, "Group", "&o", &path)) {
|
|
|
|
|
if (priv->group_proxy && g_strcmp0 (path, g_dbus_proxy_get_object_path (priv->group_proxy)) == 0) {
|
|
|
|
|
/* We already have the proxy, nothing to do. */
|
|
|
|
|
} else if (path && g_strcmp0 (path, "/") != 0) {
|
|
|
|
|
if (priv->group_proxy != NULL) {
|
2019-01-11 17:07:03 -02:00
|
|
|
_LOGW ("P2P: Unexpected update of the group object path");
|
2018-10-10 23:08:15 +02:00
|
|
|
priv->group_proxy_acquired = FALSE;
|
|
|
|
|
_notify (self, PROP_P2P_GROUP_JOINED);
|
2018-12-11 18:21:37 +01:00
|
|
|
_notify (self, PROP_P2P_GROUP_PATH);
|
2018-10-10 23:08:15 +02:00
|
|
|
g_clear_object (&priv->group_proxy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Delay ready state if we have not reached it yet. */
|
|
|
|
|
if (priv->ready_count)
|
|
|
|
|
priv->ready_count++;
|
|
|
|
|
|
|
|
|
|
priv->group_proxy = g_object_new (G_TYPE_DBUS_PROXY,
|
|
|
|
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
|
"g-name", WPAS_DBUS_SERVICE,
|
|
|
|
|
"g-object-path", path,
|
|
|
|
|
"g-interface-name", WPAS_DBUS_IFACE_GROUP,
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect (priv->group_proxy, "g-properties-changed", G_CALLBACK (group_props_changed_cb), self);
|
|
|
|
|
g_async_initable_init_async (G_ASYNC_INITABLE (priv->group_proxy),
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) group_proxy_acquired_cb,
|
|
|
|
|
self);
|
|
|
|
|
} else {
|
|
|
|
|
priv->group_proxy_acquired = FALSE;
|
|
|
|
|
_notify (self, PROP_P2P_GROUP_JOINED);
|
2018-12-11 18:21:37 +01:00
|
|
|
_notify (self, PROP_P2P_GROUP_PATH);
|
2018-10-10 23:08:15 +02:00
|
|
|
g_clear_object (&priv->group_proxy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
g_object_thaw_notify (G_OBJECT (self));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
p2p_device_found (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
|
|
|
|
peer_add_new (self, path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
p2p_device_lost (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
PeerData *peer_data;
|
|
|
|
|
|
|
|
|
|
peer_data = g_hash_table_lookup (priv->peer_proxies, path);
|
|
|
|
|
if (!peer_data)
|
|
|
|
|
return;
|
|
|
|
|
g_hash_table_steal (priv->peer_proxies, path);
|
|
|
|
|
g_signal_emit (self, signals[PEER_REMOVED], 0, path);
|
|
|
|
|
peer_data_destroy (peer_data);
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 23:08:15 +02:00
|
|
|
static void
|
|
|
|
|
p2p_group_started (GDBusProxy *proxy,
|
|
|
|
|
GVariant *params,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
NMSupplicantInterface *iface = NULL;
|
|
|
|
|
char *group_path = NULL;
|
|
|
|
|
char *iface_path = NULL;
|
|
|
|
|
|
|
|
|
|
/* There is one more parameter: the role, but we don't really care about that here. */
|
|
|
|
|
if (!g_variant_lookup (params, "group_object", "&o", &group_path)) {
|
|
|
|
|
_LOGW ("P2P: GroupStarted signal is missing the \"group_object\" parameter");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!g_variant_lookup (params, "interface_object", "&o", &iface_path)) {
|
|
|
|
|
_LOGW ("P2P: GroupStarted signal is missing the \"interface\" parameter");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (iface_path, priv->object_path) == 0) {
|
|
|
|
|
_LOGW ("P2P: GroupStarted on existing interface");
|
|
|
|
|
iface = g_object_ref (self);
|
|
|
|
|
} else {
|
|
|
|
|
iface = nm_supplicant_manager_create_interface_from_path (nm_supplicant_manager_get (),
|
|
|
|
|
iface_path);
|
|
|
|
|
if (iface == NULL) {
|
|
|
|
|
_LOGW ("P2P: Group interface already exists in GroupStarted handler, aborting further processing.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-11 17:07:03 -02:00
|
|
|
/* Signal existence of the (new) interface. */
|
2018-10-10 23:08:15 +02:00
|
|
|
g_signal_emit (self, signals[GROUP_STARTED], 0, iface);
|
|
|
|
|
g_object_unref (iface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
p2p_group_formation_failure (GDBusProxy *proxy,
|
|
|
|
|
const char *group,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
|
|
|
|
g_signal_emit (self, signals[GROUP_FORMATION_FAILURE], 0, group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
p2p_group_finished (GDBusProxy *proxy,
|
|
|
|
|
GVariant *params,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
const char *iface_path = NULL;
|
|
|
|
|
/* TODO: Group finished is called on the management interface!
|
|
|
|
|
* This means the signal consumer will currently need to assume which
|
|
|
|
|
* interface is finishing or it needs to match the object paths.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (!g_variant_lookup (params, "interface_object", "&o", &iface_path)) {
|
|
|
|
|
_LOGW ("P2P: GroupFinished signal is missing the \"interface\" parameter");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_LOGD ("P2P: GroupFinished signal on interface %s for interface %s", priv->object_path, iface_path);
|
|
|
|
|
|
|
|
|
|
/* Signal group finish interface (on management interface). */
|
|
|
|
|
g_signal_emit (self, signals[GROUP_FINISHED], 0, iface_path);
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
on_iface_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
|
|
|
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
2016-01-21 15:21:37 +01:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
_LOGW ("failed to acquire wpa_supplicant interface proxy: (%s)", error->message);
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-03-27 08:03:22 -04:00
|
|
|
_nm_dbus_signal_connect (priv->iface_proxy, "ScanDone", G_VARIANT_TYPE ("(b)"),
|
|
|
|
|
G_CALLBACK (wpas_iface_scan_done), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->iface_proxy, "BSSAdded", G_VARIANT_TYPE ("(oa{sv})"),
|
|
|
|
|
G_CALLBACK (wpas_iface_bss_added), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->iface_proxy, "BSSRemoved", G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
G_CALLBACK (wpas_iface_bss_removed), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->iface_proxy, "NetworkRequest", G_VARIANT_TYPE ("(oss)"),
|
|
|
|
|
G_CALLBACK (wpas_iface_network_request), self);
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2015-04-16 12:05:05 -05:00
|
|
|
/* Scan result aging parameters */
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
2017-03-18 14:45:35 +01:00
|
|
|
DBUS_INTERFACE_PROPERTIES ".Set",
|
2015-04-16 12:05:05 -05:00
|
|
|
g_variant_new ("(ssv)",
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE,
|
|
|
|
|
"BSSExpireAge",
|
|
|
|
|
g_variant_new_uint32 (250)),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
2017-03-18 14:45:35 +01:00
|
|
|
DBUS_INTERFACE_PROPERTIES ".Set",
|
2015-04-16 12:05:05 -05:00
|
|
|
g_variant_new ("(ssv)",
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE,
|
|
|
|
|
"BSSExpireCount",
|
|
|
|
|
g_variant_new_uint32 (2)),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
|
2019-02-25 08:35:12 +01:00
|
|
|
/* Check whether NetworkReply and AP mode are supported.
|
|
|
|
|
* ready_count was initialized to 1 in interface_add_done().
|
|
|
|
|
*/
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"NetworkReply",
|
|
|
|
|
g_variant_new ("(oss)",
|
|
|
|
|
"/fff",
|
|
|
|
|
"foobar",
|
|
|
|
|
"foobar"),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) iface_check_netreply_cb,
|
|
|
|
|
self);
|
|
|
|
|
|
2019-02-25 08:38:22 +01:00
|
|
|
if (priv->pmf_support == NM_SUPPLICANT_FEATURE_YES) {
|
|
|
|
|
/* Initialize global PMF setting to 'optional' */
|
|
|
|
|
priv->ready_count++;
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
DBUS_INTERFACE_PROPERTIES ".Set",
|
|
|
|
|
g_variant_new ("(ssv)",
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE,
|
|
|
|
|
"Pmf",
|
|
|
|
|
g_variant_new_string ("1")),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) iface_set_pmf_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
2019-01-09 11:36:52 +01:00
|
|
|
|
2017-02-05 23:18:08 +01:00
|
|
|
if (priv->ap_support == NM_SUPPLICANT_FEATURE_UNKNOWN) {
|
2015-02-02 02:31:30 -06:00
|
|
|
/* If the global supplicant capabilities property is not present, we can
|
|
|
|
|
* fall back to checking whether the ProbeRequest method is supported. If
|
|
|
|
|
* neither of these works we have no way of determining if AP mode is
|
|
|
|
|
* supported or not. hostap 1.0 and earlier don't support either of these.
|
|
|
|
|
*/
|
|
|
|
|
priv->ready_count++;
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
2015-04-13 10:28:17 -04:00
|
|
|
DBUS_INTERFACE_INTROSPECTABLE ".Introspect",
|
2015-02-02 02:31:30 -06:00
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
2015-10-06 21:31:04 -05:00
|
|
|
(GAsyncReadyCallback) iface_introspect_cb,
|
2015-02-02 02:31:30 -06:00
|
|
|
self);
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-10 18:35:20 +02:00
|
|
|
static void
|
|
|
|
|
on_p2p_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
|
|
|
|
|
if (!g_async_initable_init_finish (G_ASYNC_INITABLE (proxy), result, &error)) {
|
|
|
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
_LOGW ("failed to acquire wpa_supplicant p2p proxy: (%s)", error->message);
|
|
|
|
|
|
|
|
|
|
g_clear_object (&priv->p2p_proxy);
|
|
|
|
|
|
|
|
|
|
iface_check_ready (self);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2018-10-10 21:27:34 +02:00
|
|
|
_nm_dbus_signal_connect (priv->p2p_proxy, "DeviceFound", G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
G_CALLBACK (p2p_device_found), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->p2p_proxy, "DeviceLost", G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
G_CALLBACK (p2p_device_lost), self);
|
2018-10-10 23:08:15 +02:00
|
|
|
_nm_dbus_signal_connect (priv->p2p_proxy, "GroupStarted", G_VARIANT_TYPE ("(a{sv})"),
|
|
|
|
|
G_CALLBACK (p2p_group_started), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->p2p_proxy, "GroupFormationFailure", G_VARIANT_TYPE ("(s)"),
|
|
|
|
|
G_CALLBACK (p2p_group_formation_failure), self);
|
|
|
|
|
_nm_dbus_signal_connect (priv->p2p_proxy, "GroupFinished", G_VARIANT_TYPE ("(a{sv})"),
|
|
|
|
|
G_CALLBACK (p2p_group_finished), self);
|
2018-10-10 18:35:20 +02:00
|
|
|
/* TODO:
|
|
|
|
|
* * WpsFailed
|
|
|
|
|
* * FindStopped
|
|
|
|
|
* * GONegotationFailure
|
|
|
|
|
* * InvitationReceived
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
priv->p2p_proxy_acquired = TRUE;
|
|
|
|
|
_notify (self, PROP_P2P_AVAILABLE);
|
|
|
|
|
|
|
|
|
|
iface_check_ready (self);
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-25 15:41:04 +00:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
interface_add_done (NMSupplicantInterface *self, const char *path)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2007-02-05 12:14:09 +00:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGD ("interface added to supplicant");
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2018-10-10 18:35:20 +02:00
|
|
|
/* Iface ready check happens in iface_check_netreply_cb */
|
|
|
|
|
priv->ready_count = 1;
|
|
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->object_path = g_strdup (path);
|
2018-10-10 22:43:49 +02:00
|
|
|
_notify (self, PROP_OBJECT_PATH);
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->iface_proxy = g_object_new (G_TYPE_DBUS_PROXY,
|
|
|
|
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
|
"g-name", WPAS_DBUS_SERVICE,
|
|
|
|
|
"g-object-path", priv->object_path,
|
|
|
|
|
"g-interface-name", WPAS_DBUS_IFACE_INTERFACE,
|
|
|
|
|
NULL);
|
|
|
|
|
g_signal_connect (priv->iface_proxy, "g-properties-changed", G_CALLBACK (props_changed_cb), self);
|
|
|
|
|
g_async_initable_init_async (G_ASYNC_INITABLE (priv->iface_proxy),
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) on_iface_proxy_acquired,
|
|
|
|
|
self);
|
2018-10-10 18:35:20 +02:00
|
|
|
|
|
|
|
|
if (priv->p2p_support == NM_SUPPLICANT_FEATURE_YES) {
|
|
|
|
|
priv->ready_count++;
|
|
|
|
|
priv->p2p_proxy = g_object_new (G_TYPE_DBUS_PROXY,
|
|
|
|
|
"g-bus-type", G_BUS_TYPE_SYSTEM,
|
|
|
|
|
"g-flags", G_DBUS_PROXY_FLAGS_NONE,
|
|
|
|
|
"g-name", WPAS_DBUS_SERVICE,
|
|
|
|
|
"g-object-path", priv->object_path,
|
|
|
|
|
"g-interface-name", WPAS_DBUS_IFACE_INTERFACE_P2P_DEVICE,
|
|
|
|
|
NULL);
|
2018-10-10 21:27:34 +02:00
|
|
|
g_signal_connect (priv->p2p_proxy, "g-properties-changed", G_CALLBACK (p2p_props_changed_cb), self);
|
2018-10-10 18:35:20 +02:00
|
|
|
g_async_initable_init_async (G_ASYNC_INITABLE (priv->p2p_proxy),
|
|
|
|
|
G_PRIORITY_DEFAULT,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) on_p2p_proxy_acquired,
|
|
|
|
|
self);
|
|
|
|
|
}
|
2010-10-06 11:05:21 -05:00
|
|
|
}
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
interface_get_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2010-10-06 11:05:21 -05:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2015-03-27 08:45:35 -04:00
|
|
|
const char *path;
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
variant = _nm_dbus_proxy_call_finish (proxy, result,
|
|
|
|
|
G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
&error);
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
if (variant) {
|
|
|
|
|
g_variant_get (variant, "(&o)", &path);
|
2013-06-05 08:01:46 -05:00
|
|
|
interface_add_done (self, path);
|
2010-10-06 11:05:21 -05:00
|
|
|
} else {
|
2015-04-21 09:52:25 -04:00
|
|
|
g_dbus_error_strip_remote_error (error);
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGE ("error getting interface: %s", error->message);
|
2015-02-02 02:31:30 -06:00
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
interface_add_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
gs_unref_variant GVariant *variant = NULL;
|
2015-03-27 08:45:35 -04:00
|
|
|
const char *path;
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
variant = _nm_dbus_proxy_call_finish (proxy, result,
|
|
|
|
|
G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
&error);
|
2015-02-02 02:31:30 -06:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
if (variant) {
|
|
|
|
|
g_variant_get (variant, "(&o)", &path);
|
2015-02-02 02:31:30 -06:00
|
|
|
interface_add_done (self, path);
|
2015-03-27 09:04:41 -04:00
|
|
|
} else if (_nm_dbus_error_has_name (error, WPAS_ERROR_EXISTS_ERROR)) {
|
2015-02-02 02:31:30 -06:00
|
|
|
/* Interface already added, just get its object path */
|
|
|
|
|
g_dbus_proxy_call (priv->wpas_proxy,
|
|
|
|
|
"GetInterface",
|
|
|
|
|
g_variant_new ("(s)", priv->dev),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) interface_get_cb,
|
|
|
|
|
self);
|
|
|
|
|
} else if ( g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_EXEC_FAILED)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FORK_FAILED)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_FAILED)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMEOUT)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_NO_REPLY)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_TIMED_OUT)
|
|
|
|
|
|| g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND)) {
|
|
|
|
|
/* Supplicant wasn't running and could not be launched via service
|
|
|
|
|
* activation. Wait for it to start by moving back to the INIT
|
|
|
|
|
* state.
|
|
|
|
|
*/
|
2015-04-21 09:52:25 -04:00
|
|
|
g_dbus_error_strip_remote_error (error);
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGD ("failed to activate supplicant: %s", error->message);
|
2015-02-02 02:31:30 -06:00
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_INIT);
|
|
|
|
|
} else {
|
2015-04-21 09:52:25 -04:00
|
|
|
g_dbus_error_strip_remote_error (error);
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGE ("error adding interface: %s", error->message);
|
2015-02-02 02:31:30 -06:00
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-10-08 19:42:07 +02:00
|
|
|
static void
|
|
|
|
|
interface_removed_cb (GDBusProxy *proxy,
|
|
|
|
|
const char *path,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (g_strcmp0 (priv->object_path, path) != 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
_LOGD ("Received interface removed signal");
|
|
|
|
|
|
|
|
|
|
/* The interface may lose its last reference during signal handling otherwise. */
|
|
|
|
|
g_object_ref (self);
|
|
|
|
|
|
|
|
|
|
/* Invalidate the object path to prevent the manager from trying to remove
|
|
|
|
|
* a non-existing interface. */
|
|
|
|
|
g_clear_pointer (&priv->object_path, g_free);
|
2018-10-10 22:43:49 +02:00
|
|
|
_notify (self, PROP_OBJECT_PATH);
|
2018-10-08 19:42:07 +02:00
|
|
|
|
|
|
|
|
/* No need to clean up everything now, that will happen at dispose time. */
|
|
|
|
|
|
|
|
|
|
/* Interface is down and has been removed. */
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
|
|
|
|
g_signal_emit (self, signals[REMOVED], 0);
|
|
|
|
|
|
|
|
|
|
g_object_unref (self);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-29 23:11:04 -06:00
|
|
|
#if HAVE_WEXT
|
|
|
|
|
#define DEFAULT_WIFI_DRIVER "nl80211,wext"
|
|
|
|
|
#else
|
|
|
|
|
#define DEFAULT_WIFI_DRIVER "nl80211"
|
|
|
|
|
#endif
|
|
|
|
|
|
2006-11-25 15:41:04 +00:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
on_wpas_proxy_acquired (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
|
|
|
|
GDBusProxy *wpas_proxy;
|
|
|
|
|
GVariantBuilder props;
|
|
|
|
|
|
|
|
|
|
wpas_proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
|
|
|
|
|
if (!wpas_proxy) {
|
|
|
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
2016-01-21 15:21:37 +01:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
_LOGW ("failed to acquire wpa_supplicant proxy: (%s)", error->message);
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->wpas_proxy = wpas_proxy;
|
2010-10-11 20:30:40 -05:00
|
|
|
|
2018-10-08 19:42:07 +02:00
|
|
|
/* Watch for interface removal. */
|
|
|
|
|
_nm_dbus_signal_connect (priv->wpas_proxy, "InterfaceRemoved", G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
G_CALLBACK (interface_removed_cb), self);
|
|
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
/* Try to add the interface to the supplicant. If the supplicant isn't
|
|
|
|
|
* running, this will start it via D-Bus activation and return the response
|
|
|
|
|
* when the supplicant has started.
|
|
|
|
|
*/
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2018-10-10 22:43:49 +02:00
|
|
|
if (priv->dev != NULL) {
|
|
|
|
|
const char *driver_name = NULL;
|
|
|
|
|
|
|
|
|
|
switch (priv->driver) {
|
|
|
|
|
case NM_SUPPLICANT_DRIVER_WIRELESS:
|
|
|
|
|
driver_name = DEFAULT_WIFI_DRIVER;
|
|
|
|
|
break;
|
|
|
|
|
case NM_SUPPLICANT_DRIVER_WIRED:
|
|
|
|
|
driver_name = "wired";
|
|
|
|
|
break;
|
|
|
|
|
case NM_SUPPLICANT_DRIVER_MACSEC:
|
|
|
|
|
driver_name = "macsec_linux";
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-06-30 18:20:48 +02:00
|
|
|
|
2018-10-10 22:43:49 +02:00
|
|
|
g_return_if_fail (driver_name);
|
2016-06-30 18:20:48 +02:00
|
|
|
|
2018-10-10 22:43:49 +02:00
|
|
|
g_variant_builder_init (&props, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_add (&props, "{sv}",
|
|
|
|
|
"Driver",
|
|
|
|
|
g_variant_new_string (driver_name));
|
|
|
|
|
g_variant_builder_add (&props, "{sv}",
|
|
|
|
|
"Ifname",
|
|
|
|
|
g_variant_new_string (priv->dev));
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2018-10-10 22:43:49 +02:00
|
|
|
g_dbus_proxy_call (priv->wpas_proxy,
|
|
|
|
|
"CreateInterface",
|
|
|
|
|
g_variant_new ("(a{sv})", &props),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) interface_add_cb,
|
|
|
|
|
self);
|
|
|
|
|
} else if (priv->object_path) {
|
|
|
|
|
interface_add_done (self, priv->object_path);
|
|
|
|
|
} else {
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
2010-11-18 17:02:04 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
static void
|
2016-01-19 22:10:14 +01:00
|
|
|
interface_add (NMSupplicantInterface *self)
|
2015-02-02 02:31:30 -06:00
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
/* Can only start the interface from INIT state */
|
|
|
|
|
g_return_if_fail (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT);
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGD ("adding interface to supplicant");
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
/* Move to starting to prevent double-calls of interface_add() */
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_STARTING);
|
|
|
|
|
|
2017-02-15 00:16:38 +01:00
|
|
|
nm_clear_g_cancellable (&priv->init_cancellable);
|
2015-02-02 02:31:30 -06:00
|
|
|
priv->init_cancellable = g_cancellable_new ();
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
|
2018-10-08 19:42:07 +02:00
|
|
|
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
2015-02-02 02:31:30 -06:00
|
|
|
NULL,
|
|
|
|
|
WPAS_DBUS_SERVICE,
|
|
|
|
|
WPAS_DBUS_PATH,
|
|
|
|
|
WPAS_DBUS_INTERFACE,
|
|
|
|
|
priv->init_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) on_wpas_proxy_acquired,
|
|
|
|
|
self);
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
|
|
|
|
|
2015-02-01 03:08:16 -06:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
|
|
|
|
|
gboolean available)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2016-01-19 22:10:14 +01:00
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2010-10-06 11:05:21 -05:00
|
|
|
|
2015-02-01 03:08:16 -06:00
|
|
|
if (available) {
|
2010-10-06 11:05:21 -05:00
|
|
|
/* This can happen if the supplicant couldn't be activated but
|
|
|
|
|
* for some reason was started after the activation failure.
|
|
|
|
|
*/
|
|
|
|
|
if (priv->state == NM_SUPPLICANT_INTERFACE_STATE_INIT)
|
2016-01-19 22:10:14 +01:00
|
|
|
interface_add (self);
|
2010-10-06 11:05:21 -05:00
|
|
|
} else {
|
|
|
|
|
/* The supplicant stopped; so we must tear down the interface */
|
|
|
|
|
set_state (self, NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
log_result_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-12-19 19:15:31 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
reply = g_dbus_proxy_call_finish (proxy, result, &error);
|
2015-04-06 11:00:20 -05:00
|
|
|
if ( !reply
|
|
|
|
|
&& !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
|
2015-04-21 09:52:25 -04:00
|
|
|
&& !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) {
|
|
|
|
|
g_dbus_error_strip_remote_error (error);
|
2016-01-21 15:21:37 +01:00
|
|
|
nm_log_warn (_NMLOG_DOMAIN, "%s: failed to %s: %s",
|
|
|
|
|
_NMLOG_PREFIX_NAME, (const char *) user_data, error->message);
|
2015-04-21 09:52:25 -04:00
|
|
|
}
|
2007-02-05 12:14:09 +00:00
|
|
|
}
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
assoc_return (NMSupplicantInterface *self, GError *error, const char *message)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
AssocData *assoc_data;
|
|
|
|
|
|
|
|
|
|
assoc_data = g_steal_pointer (&priv->assoc_data);
|
|
|
|
|
if (!assoc_data)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
g_dbus_error_strip_remote_error (error);
|
|
|
|
|
_LOGW ("assoc[%p]: %s: %s", assoc_data, message, error->message);
|
|
|
|
|
} else
|
|
|
|
|
_LOGD ("assoc[%p]: association request successful", assoc_data);
|
|
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
if (assoc_data->add_network_data) {
|
|
|
|
|
/* signal that this request already completed */
|
|
|
|
|
assoc_data->add_network_data->assoc_data = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
nm_clear_g_source (&assoc_data->fail_on_idle_id);
|
|
|
|
|
nm_clear_g_cancellable (&assoc_data->cancellable);
|
|
|
|
|
|
|
|
|
|
if (assoc_data->callback)
|
|
|
|
|
assoc_data->callback (self, error, assoc_data->user_data);
|
|
|
|
|
|
|
|
|
|
g_object_unref (assoc_data->cfg);
|
|
|
|
|
g_slice_free (AssocData, assoc_data);
|
|
|
|
|
}
|
|
|
|
|
|
2006-12-19 19:15:31 +00:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
|
|
|
|
|
{
|
2007-02-05 12:14:09 +00:00
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
/* Cancel all pending calls related to a prior connection attempt */
|
2017-02-14 19:30:21 +01:00
|
|
|
if (priv->assoc_data) {
|
2017-06-27 09:29:18 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2017-02-14 19:30:21 +01:00
|
|
|
|
|
|
|
|
nm_utils_error_set_cancelled (&error, FALSE, "NMSupplicantInterface");
|
|
|
|
|
assoc_return (self, error, "abort due to disconnect");
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
2006-12-19 19:15:31 +00:00
|
|
|
|
|
|
|
|
/* Don't do anything if there is no connection to the supplicant yet. */
|
2007-02-05 12:14:09 +00:00
|
|
|
if (!priv->iface_proxy)
|
2006-12-19 19:15:31 +00:00
|
|
|
return;
|
|
|
|
|
|
2011-06-29 18:15:05 -05:00
|
|
|
/* Disconnect from the current AP */
|
|
|
|
|
if ( (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
|
|
|
|
|
&& (priv->state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED)) {
|
2015-02-02 02:31:30 -06:00
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"Disconnect",
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
NULL,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
"disconnect");
|
2006-12-19 19:15:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Remove any network that was added by NetworkManager */
|
2010-11-22 09:05:09 -06:00
|
|
|
if (priv->net_path) {
|
2015-02-02 02:31:30 -06:00
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"RemoveNetwork",
|
|
|
|
|
g_variant_new ("(o)", priv->net_path),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
"remove network");
|
2010-11-22 09:05:09 -06:00
|
|
|
g_free (priv->net_path);
|
|
|
|
|
priv->net_path = NULL;
|
2007-02-05 12:14:09 +00:00
|
|
|
}
|
2017-04-13 10:42:32 +02:00
|
|
|
|
|
|
|
|
/* Cancel any WPS enrollment, if any */
|
|
|
|
|
nm_supplicant_interface_cancel_wps (self);
|
2006-12-19 19:15:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-12-19 19:15:31 +00:00
|
|
|
{
|
2016-01-21 15:21:37 +01:00
|
|
|
NMSupplicantInterface *self;
|
2015-02-02 02:31:30 -06:00
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
2016-01-21 15:21:37 +01:00
|
|
|
gs_free_error GError *error = NULL;
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
reply = g_dbus_proxy_call_finish (proxy, result, &error);
|
2017-02-14 19:30:21 +01:00
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
if (error)
|
|
|
|
|
assoc_return (self, error, "failure to select network config");
|
|
|
|
|
else
|
|
|
|
|
assoc_return (self, NULL, NULL);
|
2006-12-19 19:15:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_call_select_network (NMSupplicantInterface *self)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2010-11-22 09:05:09 -06:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2007-10-20 20:31:29 +00:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"SelectNetwork",
|
|
|
|
|
g_variant_new ("(o)", priv->net_path),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->assoc_data->cancellable,
|
|
|
|
|
(GAsyncReadyCallback) assoc_select_network_cb,
|
|
|
|
|
self);
|
2007-10-20 20:31:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_add_blob_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2007-10-20 20:31:29 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
2016-01-21 15:21:37 +01:00
|
|
|
gs_free_error GError *error = NULL;
|
2007-10-20 20:31:29 +00:00
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
reply = g_dbus_proxy_call_finish (proxy, result, &error);
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
2015-02-02 02:31:30 -06:00
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2010-11-22 22:34:04 -06:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
if (error) {
|
|
|
|
|
assoc_return (self, error, "failure to set network certificates");
|
|
|
|
|
return;
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
2017-02-14 19:30:21 +01:00
|
|
|
|
|
|
|
|
priv->assoc_data->blobs_left--;
|
|
|
|
|
_LOGT ("assoc[%p]: blob added (%u left)", priv->assoc_data, priv->assoc_data->blobs_left);
|
|
|
|
|
if (priv->assoc_data->blobs_left == 0)
|
|
|
|
|
assoc_call_select_network (self);
|
2007-10-20 20:31:29 +00:00
|
|
|
}
|
|
|
|
|
|
2006-12-19 19:15:31 +00:00
|
|
|
static void
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_add_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-12-19 19:15:31 +00:00
|
|
|
{
|
2017-02-15 10:14:54 +01:00
|
|
|
AddNetworkData *add_network_data = user_data;
|
|
|
|
|
AssocData *assoc_data;
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2010-11-22 09:05:09 -06:00
|
|
|
GHashTable *blobs;
|
2010-11-22 22:34:04 -06:00
|
|
|
GHashTableIter iter;
|
2015-02-02 02:31:30 -06:00
|
|
|
const char *blob_name;
|
2018-08-12 16:51:16 +02:00
|
|
|
GBytes *blob_data;
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
assoc_data = add_network_data->assoc_data;
|
|
|
|
|
if (assoc_data)
|
|
|
|
|
assoc_data->add_network_data = NULL;
|
|
|
|
|
g_slice_free (AddNetworkData, add_network_data);
|
|
|
|
|
|
2015-03-27 08:45:35 -04:00
|
|
|
reply = _nm_dbus_proxy_call_finish (proxy, result,
|
|
|
|
|
G_VARIANT_TYPE ("(o)"),
|
|
|
|
|
&error);
|
2017-02-15 10:14:54 +01:00
|
|
|
|
|
|
|
|
if (!assoc_data) {
|
|
|
|
|
if (!error) {
|
|
|
|
|
gs_free char *net_path = NULL;
|
|
|
|
|
|
|
|
|
|
/* the assoc-request was already cancelled, but the AddNetwork request succeeded.
|
|
|
|
|
* Cleanup the created network.
|
|
|
|
|
*
|
|
|
|
|
* This cleanup action does not work when NetworkManager is about to exit
|
|
|
|
|
* and leaves the mainloop. During program shutdown, we may orphan networks. */
|
|
|
|
|
g_variant_get (reply, "(o)", &net_path);
|
|
|
|
|
g_dbus_proxy_call (proxy,
|
|
|
|
|
"RemoveNetwork",
|
|
|
|
|
g_variant_new ("(o)", net_path),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL,
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
2015-02-02 02:31:30 -06:00
|
|
|
return;
|
2017-02-15 10:14:54 +01:00
|
|
|
}
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (assoc_data->self);
|
2015-02-02 02:31:30 -06:00
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
if (error) {
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_return (self, error, "failure to add network");
|
2010-11-22 09:05:09 -06:00
|
|
|
return;
|
2006-12-19 19:15:31 +00:00
|
|
|
}
|
2010-11-22 09:05:09 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_variant_get (reply, "(o)", &priv->net_path);
|
|
|
|
|
|
|
|
|
|
/* Send blobs first; otherwise jump to selecting the network */
|
2017-02-14 19:30:21 +01:00
|
|
|
blobs = nm_supplicant_config_get_blobs (priv->assoc_data->cfg);
|
|
|
|
|
priv->assoc_data->blobs_left = g_hash_table_size (blobs);
|
2015-02-02 02:31:30 -06:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
_LOGT ("assoc[%p]: network added (%s) (%u blobs left)", priv->assoc_data, priv->net_path, priv->assoc_data->blobs_left);
|
2015-10-07 16:03:16 -05:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
if (priv->assoc_data->blobs_left == 0)
|
|
|
|
|
assoc_call_select_network (self);
|
|
|
|
|
else {
|
|
|
|
|
g_hash_table_iter_init (&iter, blobs);
|
|
|
|
|
while (g_hash_table_iter_next (&iter, (gpointer) &blob_name, (gpointer) &blob_data)) {
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"AddBlob",
|
|
|
|
|
g_variant_new ("(s@ay)",
|
|
|
|
|
blob_name,
|
2018-08-12 16:51:16 +02:00
|
|
|
nm_utils_gbytes_to_variant_ay (blob_data)),
|
2017-02-14 19:30:21 +01:00
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->assoc_data->cancellable,
|
|
|
|
|
(GAsyncReadyCallback) assoc_add_blob_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-10-07 16:03:16 -05:00
|
|
|
}
|
|
|
|
|
|
2006-12-19 19:15:31 +00:00
|
|
|
static void
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_set_ap_scan_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2006-12-19 19:15:31 +00:00
|
|
|
{
|
2015-02-02 02:31:30 -06:00
|
|
|
NMSupplicantInterface *self;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2017-02-15 10:14:54 +01:00
|
|
|
AddNetworkData *add_network_data;
|
2007-02-05 12:14:09 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
reply = g_dbus_proxy_call_finish (proxy, result, &error);
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
if (error) {
|
|
|
|
|
assoc_return (self, error, "failure to set AP scan mode");
|
2007-11-21 05:57:54 +00:00
|
|
|
return;
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
2007-11-21 05:57:54 +00:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
_LOGT ("assoc[%p]: set interface ap_scan to %d",
|
|
|
|
|
priv->assoc_data,
|
|
|
|
|
nm_supplicant_config_get_ap_scan (priv->assoc_data->cfg));
|
|
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
add_network_data = g_slice_new0 (AddNetworkData);
|
|
|
|
|
priv->assoc_data->add_network_data = add_network_data;
|
|
|
|
|
|
|
|
|
|
add_network_data->assoc_data = priv->assoc_data;
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"AddNetwork",
|
|
|
|
|
g_variant_new ("(@a{sv})", nm_supplicant_config_to_variant (priv->assoc_data->cfg)),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
2017-02-15 10:14:54 +01:00
|
|
|
NULL,
|
2017-02-14 19:30:21 +01:00
|
|
|
(GAsyncReadyCallback) assoc_add_network_cb,
|
2017-02-15 10:14:54 +01:00
|
|
|
add_network_data);
|
2017-02-14 19:30:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
|
assoc_fail_on_idle_cb (gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterface *self = user_data;
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2007-11-21 05:57:54 +00:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
priv->assoc_data->fail_on_idle_id = 0;
|
|
|
|
|
g_set_error (&error, NM_SUPPLICANT_ERROR, NM_SUPPLICANT_ERROR_CONFIG,
|
|
|
|
|
"EAP-FAST is not supported by the supplicant");
|
|
|
|
|
assoc_return (self, error, "failure due to missing supplicant support");
|
|
|
|
|
return G_SOURCE_REMOVE;
|
2006-11-25 15:41:04 +00:00
|
|
|
}
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
/**
|
|
|
|
|
* nm_supplicant_interface_assoc:
|
|
|
|
|
* @self: the supplicant interface instance
|
|
|
|
|
* @cfg: the configuration with the data for the association
|
|
|
|
|
* @callback: callback invoked when the association completes or fails.
|
|
|
|
|
* @user_data: data for the callback.
|
|
|
|
|
*
|
|
|
|
|
* Calls AddNetwork and SelectNetwork to start associating according to @cfg.
|
|
|
|
|
*
|
|
|
|
|
* The callback is invoked exactly once (always) and always asynchronously.
|
|
|
|
|
* The pending association can be aborted via nm_supplicant_interface_disconnect()
|
|
|
|
|
* or by destroying @self. In that case, the @callback is invoked synchornously with
|
|
|
|
|
* an error reason indicating cancellation/disposing (see nm_utils_error_is_cancelled()).
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_assoc (NMSupplicantInterface *self,
|
|
|
|
|
NMSupplicantConfig *cfg,
|
|
|
|
|
NMSupplicantInterfaceAssocCb callback,
|
|
|
|
|
gpointer user_data)
|
2006-11-25 15:41:04 +00:00
|
|
|
{
|
2007-02-05 12:14:09 +00:00
|
|
|
NMSupplicantInterfacePrivate *priv;
|
2017-02-14 19:30:21 +01:00
|
|
|
AssocData *assoc_data;
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_CONFIG (cfg));
|
2006-11-25 15:41:04 +00:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2006-12-19 19:15:31 +00:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
nm_supplicant_interface_disconnect (self);
|
2012-02-07 23:46:12 -06:00
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_data = g_slice_new0 (AssocData);
|
|
|
|
|
priv->assoc_data = assoc_data;
|
|
|
|
|
|
2017-02-15 10:14:54 +01:00
|
|
|
assoc_data->self = self;
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_data->cfg = g_object_ref (cfg);
|
|
|
|
|
assoc_data->callback = callback;
|
|
|
|
|
assoc_data->user_data = user_data;
|
|
|
|
|
|
|
|
|
|
_LOGD ("assoc[%p]: starting association...", assoc_data);
|
|
|
|
|
|
2012-02-07 23:46:12 -06:00
|
|
|
/* Make sure the supplicant supports EAP-FAST before trying to send
|
|
|
|
|
* it an EAP-FAST configuration.
|
|
|
|
|
*/
|
2017-01-18 17:41:12 +01:00
|
|
|
if ( priv->fast_support == NM_SUPPLICANT_FEATURE_NO
|
|
|
|
|
&& nm_supplicant_config_fast_required (cfg)) {
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_data->fail_on_idle_id = g_idle_add (assoc_fail_on_idle_cb, self);
|
|
|
|
|
return;
|
2012-02-07 23:46:12 -06:00
|
|
|
}
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
assoc_data->cancellable = g_cancellable_new();
|
|
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
DBUS_INTERFACE_PROPERTIES ".Set",
|
|
|
|
|
g_variant_new ("(ssv)",
|
|
|
|
|
WPAS_DBUS_IFACE_INTERFACE,
|
|
|
|
|
"ApScan",
|
|
|
|
|
g_variant_new_uint32 (nm_supplicant_config_get_ap_scan (priv->assoc_data->cfg))),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->assoc_data->cancellable,
|
|
|
|
|
(GAsyncReadyCallback) assoc_set_ap_scan_cb,
|
|
|
|
|
self);
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
}
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2010-11-22 08:40:21 -06:00
|
|
|
static void
|
2015-02-02 02:31:30 -06:00
|
|
|
scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
|
2010-11-22 08:40:21 -06:00
|
|
|
{
|
2016-01-21 15:21:37 +01:00
|
|
|
NMSupplicantInterface *self;
|
2015-02-02 02:31:30 -06:00
|
|
|
gs_unref_variant GVariant *reply = NULL;
|
|
|
|
|
gs_free_error GError *error = NULL;
|
2010-11-22 08:40:21 -06:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
reply = g_dbus_proxy_call_finish (proxy, result, &error);
|
|
|
|
|
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
|
|
|
|
return;
|
2012-05-02 11:41:47 -05:00
|
|
|
|
2016-01-21 15:21:37 +01:00
|
|
|
self = NM_SUPPLICANT_INTERFACE (user_data);
|
2015-04-21 09:52:25 -04:00
|
|
|
if (error) {
|
2015-08-18 11:25:33 +02:00
|
|
|
if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGD ("could not get scan request result: %s", error->message);
|
2015-08-18 11:25:33 +02:00
|
|
|
else {
|
|
|
|
|
g_dbus_error_strip_remote_error (error);
|
2016-01-21 15:21:37 +01:00
|
|
|
_LOGW ("could not get scan request result: %s", error->message);
|
2015-08-18 11:25:33 +02:00
|
|
|
}
|
2015-04-21 09:52:25 -04:00
|
|
|
}
|
2012-05-02 11:41:47 -05:00
|
|
|
}
|
|
|
|
|
|
2017-02-15 00:22:46 +01:00
|
|
|
void
|
2018-08-12 11:43:25 +02:00
|
|
|
nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
|
|
|
|
|
GBytes *const*ssids,
|
|
|
|
|
guint ssids_len)
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
{
|
2007-02-05 12:14:09 +00:00
|
|
|
NMSupplicantInterfacePrivate *priv;
|
2015-02-02 02:31:30 -06:00
|
|
|
GVariantBuilder builder;
|
|
|
|
|
guint i;
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
|
2017-02-15 00:22:46 +01:00
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
2010-11-22 08:40:21 -06:00
|
|
|
/* Scan parameters */
|
2015-02-02 02:31:30 -06:00
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new_string ("active"));
|
2016-11-07 16:31:19 -06:00
|
|
|
g_variant_builder_add (&builder, "{sv}", "AllowRoam", g_variant_new_boolean (FALSE));
|
2018-08-12 11:43:25 +02:00
|
|
|
if (ssids_len > 0) {
|
2015-02-02 02:31:30 -06:00
|
|
|
GVariantBuilder ssids_builder;
|
|
|
|
|
|
|
|
|
|
g_variant_builder_init (&ssids_builder, G_VARIANT_TYPE_BYTESTRING_ARRAY);
|
2018-08-12 11:43:25 +02:00
|
|
|
for (i = 0; i < ssids_len; i++) {
|
|
|
|
|
nm_assert (ssids[i]);
|
2015-02-02 02:31:30 -06:00
|
|
|
g_variant_builder_add (&ssids_builder, "@ay",
|
2018-08-12 11:43:25 +02:00
|
|
|
nm_utils_gbytes_to_variant_ay (ssids[i]));
|
2015-02-02 02:31:30 -06:00
|
|
|
}
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "SSIDs", g_variant_builder_end (&ssids_builder));
|
|
|
|
|
}
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_dbus_proxy_call (priv->iface_proxy,
|
|
|
|
|
"Scan",
|
|
|
|
|
g_variant_new ("(a{sv})", &builder),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) scan_request_cb,
|
|
|
|
|
self);
|
2006-11-26 Dan Williams <dcbw@redhat.com>
Scan using wpa_supplicant over DBus.
* src/nm-device-802-11-wireless.c
- remove wireless extensions netlink event handler bits
(wireless_event_helper, nm_device_802_11_wireless_event)
- remove wireless extensions scan event handler bits
(process_scan_results, add_new_ap_to_device_list, hexstr2bin,
hex2byte, hex2num, request_and_convert_scan_results,
free_process_scan_cb_data, scan_results_timeout,
schedule_scan_results_timeout, cancel_scan_results_timeout)
- Rename nm_device_802_11_wireless_scan() -> request_wireless_scan()
and request scans from the supplicant interface rather than directly
- Move functionality of convert_scan_results() to cull_scan_list() and
supplicant_iface_scanned_ap_cb()
- (supplicant_iface_scan_result_cb): new function; schedule a new scan
at the scan interval when the current scan has finished
- (supplicant_iface_state_cb): start scanning when the supplicant
interface enters the READY state, and stop scanning when it
enters the DOWN state
- (cull_scan_list): weed out old access points from the scan list
- (supplicant_iface_scanned_ap_cb): convert a supplicant scanned access
point into an NMAccessPoint and merge it into the device's scan list
* src/supplicant-manager/nm-supplicant-interface.c
src/supplicant-manager/nm-supplicant-interface.h
- Add a new signal "scan-result" which is issued when the supplicant
notifies NM that a scan has completed
- Add a new signal "scanned-ap" that notifies listeners of a new access
point found in the scan. Called once for each access point that
the supplicant interface object receives from the supplicant as a
result of the "scanResults" method call
- (wpas_iface_query_scan_results): don't wait 4s before querying
for the initial scan results
- (scan_request_cb): new function; send listeners the result
(success, error) of a wireless scan request
- (nm_supplicant_interface_request_scan): new function; ask the
supplicant to perform an immediate wireless scan
git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2128 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2006-11-26 20:49:48 +00:00
|
|
|
}
|
2006-12-04 05:45:05 +00:00
|
|
|
|
2017-02-15 00:11:16 +01:00
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2017-02-14 01:30:25 +01:00
|
|
|
NMSupplicantInterfaceState
|
2006-12-04 19:09:44 +00:00
|
|
|
nm_supplicant_interface_get_state (NMSupplicantInterface * self)
|
|
|
|
|
{
|
2007-02-05 12:14:09 +00:00
|
|
|
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NM_SUPPLICANT_INTERFACE_STATE_DOWN);
|
2006-12-04 19:09:44 +00:00
|
|
|
|
2007-02-05 12:14:09 +00:00
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->state;
|
2006-12-04 19:09:44 +00:00
|
|
|
}
|
|
|
|
|
|
2010-10-06 11:05:21 -05:00
|
|
|
const char *
|
|
|
|
|
nm_supplicant_interface_get_object_path (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
|
|
|
|
|
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->object_path;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-05 14:19:56 -05:00
|
|
|
const char *
|
|
|
|
|
nm_supplicant_interface_get_ifname (NMSupplicantInterface *self)
|
|
|
|
|
{
|
2011-03-14 01:05:51 -05:00
|
|
|
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), NULL);
|
2010-10-05 14:19:56 -05:00
|
|
|
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-01 17:59:35 -05:00
|
|
|
guint
|
|
|
|
|
nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0);
|
|
|
|
|
|
|
|
|
|
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-02 18:22:50 +02:00
|
|
|
/*****************************************************************************/
|
2018-10-15 15:11:34 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_p2p_start_find (NMSupplicantInterface *self,
|
|
|
|
|
guint timeout)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
g_return_if_fail (timeout > 0 && timeout <= 600);
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "Timeout", g_variant_new_int32 (timeout));
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_call (priv->p2p_proxy,
|
|
|
|
|
"Find",
|
|
|
|
|
g_variant_new ("(a{sv})", &builder),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_p2p_stop_find (NMSupplicantInterface *self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_call (priv->p2p_proxy,
|
|
|
|
|
"StopFind",
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) scan_request_cb,
|
|
|
|
|
self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2018-10-10 23:14:08 +02:00
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_p2p_connect (NMSupplicantInterface * self,
|
|
|
|
|
const char * peer,
|
|
|
|
|
const char * wps_method,
|
|
|
|
|
const char * wps_pin)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
GVariantBuilder builder;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Don't do anything if there is no connection to the supplicant yet. */
|
|
|
|
|
if (!priv->p2p_proxy || !priv->object_path)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Connect parameters */
|
|
|
|
|
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
|
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "wps_method", g_variant_new_string (wps_method));
|
|
|
|
|
|
|
|
|
|
if (wps_pin)
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "pin", g_variant_new_string (wps_pin));
|
|
|
|
|
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "peer", g_variant_new_object_path (peer));
|
|
|
|
|
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "join", g_variant_new_boolean (FALSE));
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "persistent", g_variant_new_boolean (FALSE));
|
|
|
|
|
g_variant_builder_add (&builder, "{sv}", "go_intent", g_variant_new_int32 (7));
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_call (priv->p2p_proxy,
|
|
|
|
|
"Connect",
|
|
|
|
|
g_variant_new ("(a{sv})", &builder),
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
"p2p connect");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_p2p_cancel_connect (NMSupplicantInterface * self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Don't do anything if there is no connection to the supplicant yet. */
|
|
|
|
|
if (!priv->p2p_proxy || !priv->object_path)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_call (priv->p2p_proxy,
|
|
|
|
|
"Cancel",
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
"cancel p2p connect");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
nm_supplicant_interface_p2p_disconnect (NMSupplicantInterface * self)
|
|
|
|
|
{
|
|
|
|
|
NMSupplicantInterfacePrivate *priv;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
|
|
|
|
|
|
|
|
|
|
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
|
|
|
|
/* Don't do anything if there is no connection to the supplicant. */
|
|
|
|
|
if (!priv->p2p_proxy || !priv->object_path)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
g_dbus_proxy_call (priv->p2p_proxy,
|
|
|
|
|
"Disconnect",
|
|
|
|
|
NULL,
|
|
|
|
|
G_DBUS_CALL_FLAGS_NONE,
|
|
|
|
|
-1,
|
|
|
|
|
priv->other_cancellable,
|
|
|
|
|
(GAsyncReadyCallback) log_result_cb,
|
|
|
|
|
"p2p disconnect");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2010-10-05 14:19:43 -05:00
|
|
|
static void
|
2017-02-15 00:11:16 +01:00
|
|
|
get_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
2010-10-05 14:19:43 -05:00
|
|
|
{
|
2017-02-15 00:11:16 +01:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE ((NMSupplicantInterface *) object);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2017-02-15 00:11:16 +01:00
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_SCANNING:
|
|
|
|
|
g_value_set_boolean (value, priv->scanning);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_CURRENT_BSS:
|
|
|
|
|
g_value_set_string (value, priv->current_bss);
|
|
|
|
|
break;
|
2018-10-10 23:08:15 +02:00
|
|
|
case PROP_P2P_GROUP_JOINED:
|
|
|
|
|
g_value_set_boolean (value, priv->p2p_capable && priv->group_proxy_acquired);
|
|
|
|
|
break;
|
2018-12-11 18:21:37 +01:00
|
|
|
case PROP_P2P_GROUP_PATH:
|
|
|
|
|
g_value_set_string (value, nm_supplicant_interface_get_p2p_group_path (NM_SUPPLICANT_INTERFACE (object)));
|
|
|
|
|
break;
|
2018-10-10 23:08:15 +02:00
|
|
|
case PROP_P2P_GROUP_OWNER:
|
|
|
|
|
g_value_set_boolean (value, priv->p2p_group_owner);
|
|
|
|
|
break;
|
2018-10-10 18:35:20 +02:00
|
|
|
case PROP_P2P_AVAILABLE:
|
|
|
|
|
g_value_set_boolean (value, priv->p2p_capable && priv->p2p_proxy_acquired);
|
|
|
|
|
break;
|
2017-02-15 00:11:16 +01:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-10-05 14:19:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
set_property (GObject *object,
|
|
|
|
|
guint prop_id,
|
|
|
|
|
const GValue *value,
|
|
|
|
|
GParamSpec *pspec)
|
|
|
|
|
{
|
2016-09-28 15:58:24 +02:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE ((NMSupplicantInterface *) object);
|
2016-01-19 16:08:29 +01:00
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
|
case PROP_IFACE:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->dev = g_value_dup_string (value);
|
2018-10-10 22:43:49 +02:00
|
|
|
break;
|
|
|
|
|
case PROP_OBJECT_PATH:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->object_path = g_value_dup_string (value);
|
2016-01-19 16:08:29 +01:00
|
|
|
break;
|
2016-06-30 18:20:48 +02:00
|
|
|
case PROP_DRIVER:
|
2016-01-19 16:08:29 +01:00
|
|
|
/* construct-only */
|
2016-06-30 18:20:48 +02:00
|
|
|
priv->driver = g_value_get_uint (value);
|
2016-01-19 16:08:29 +01:00
|
|
|
break;
|
2017-01-18 17:41:12 +01:00
|
|
|
case PROP_FAST_SUPPORT:
|
2016-01-19 16:08:29 +01:00
|
|
|
/* construct-only */
|
2017-01-18 17:41:12 +01:00
|
|
|
priv->fast_support = g_value_get_int (value);
|
2016-01-19 16:08:29 +01:00
|
|
|
break;
|
|
|
|
|
case PROP_AP_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->ap_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2017-03-18 14:56:38 +01:00
|
|
|
case PROP_PMF_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->pmf_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2018-01-16 06:28:37 +09:00
|
|
|
case PROP_FILS_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->fils_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2018-10-10 17:50:34 +02:00
|
|
|
case PROP_P2P_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->p2p_support = g_value_get_int (value);
|
|
|
|
|
break;
|
|
|
|
|
case PROP_WFD_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->wfd_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2019-07-15 11:30:15 +00:00
|
|
|
case PROP_FT_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->ft_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2019-07-15 11:30:19 +00:00
|
|
|
case PROP_SHA384_SUPPORT:
|
|
|
|
|
/* construct-only */
|
|
|
|
|
priv->sha384_support = g_value_get_int (value);
|
|
|
|
|
break;
|
2016-01-19 16:08:29 +01:00
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-10-05 14:19:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2017-02-15 00:11:16 +01:00
|
|
|
nm_supplicant_interface_init (NMSupplicantInterface * self)
|
2010-10-05 14:19:43 -05:00
|
|
|
{
|
2017-02-15 00:11:16 +01:00
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
2015-04-05 23:31:02 -05:00
|
|
|
|
2017-02-15 00:11:16 +01:00
|
|
|
priv->state = NM_SUPPLICANT_INTERFACE_STATE_INIT;
|
2017-10-13 16:12:35 +02:00
|
|
|
priv->bss_proxies = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, bss_data_destroy);
|
2018-10-10 21:27:34 +02:00
|
|
|
priv->peer_proxies = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, peer_data_destroy);
|
2017-02-15 00:11:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NMSupplicantInterface *
|
|
|
|
|
nm_supplicant_interface_new (const char *ifname,
|
2018-10-10 22:43:49 +02:00
|
|
|
const char *object_path,
|
2017-02-15 00:11:16 +01:00
|
|
|
NMSupplicantDriver driver,
|
|
|
|
|
NMSupplicantFeature fast_support,
|
2017-03-18 14:56:38 +01:00
|
|
|
NMSupplicantFeature ap_support,
|
2018-01-16 06:28:37 +09:00
|
|
|
NMSupplicantFeature pmf_support,
|
2018-10-10 17:50:34 +02:00
|
|
|
NMSupplicantFeature fils_support,
|
|
|
|
|
NMSupplicantFeature p2p_support,
|
2019-07-15 11:30:15 +00:00
|
|
|
NMSupplicantFeature wfd_support,
|
2019-07-15 11:30:19 +00:00
|
|
|
NMSupplicantFeature ft_support,
|
|
|
|
|
NMSupplicantFeature sha384_support)
|
2017-02-15 00:11:16 +01:00
|
|
|
{
|
2018-10-10 22:43:49 +02:00
|
|
|
/* One of ifname or path need to be set */
|
|
|
|
|
g_return_val_if_fail (ifname != NULL || object_path != NULL, NULL);
|
|
|
|
|
g_return_val_if_fail (ifname == NULL || object_path == NULL, NULL);
|
2017-02-15 00:11:16 +01:00
|
|
|
|
|
|
|
|
return g_object_new (NM_TYPE_SUPPLICANT_INTERFACE,
|
|
|
|
|
NM_SUPPLICANT_INTERFACE_IFACE, ifname,
|
2018-10-10 22:43:49 +02:00
|
|
|
NM_SUPPLICANT_INTERFACE_OBJECT_PATH, object_path,
|
2017-02-15 00:11:16 +01:00
|
|
|
NM_SUPPLICANT_INTERFACE_DRIVER, (guint) driver,
|
|
|
|
|
NM_SUPPLICANT_INTERFACE_FAST_SUPPORT, (int) fast_support,
|
|
|
|
|
NM_SUPPLICANT_INTERFACE_AP_SUPPORT, (int) ap_support,
|
2017-03-18 14:56:38 +01:00
|
|
|
NM_SUPPLICANT_INTERFACE_PMF_SUPPORT, (int) pmf_support,
|
2018-01-16 06:28:37 +09:00
|
|
|
NM_SUPPLICANT_INTERFACE_FILS_SUPPORT, (int) fils_support,
|
2018-10-10 17:50:34 +02:00
|
|
|
NM_SUPPLICANT_INTERFACE_P2P_SUPPORT, (int) p2p_support,
|
|
|
|
|
NM_SUPPLICANT_INTERFACE_WFD_SUPPORT, (int) wfd_support,
|
2019-07-15 11:30:15 +00:00
|
|
|
NM_SUPPLICANT_INTERFACE_FT_SUPPORT, (int) ft_support,
|
2019-07-15 11:30:19 +00:00
|
|
|
NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT, (int) sha384_support,
|
2017-02-15 00:11:16 +01:00
|
|
|
NULL);
|
2010-10-05 14:19:43 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
dispose (GObject *object)
|
|
|
|
|
{
|
2017-02-14 19:30:21 +01:00
|
|
|
NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (object);
|
|
|
|
|
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
|
|
|
|
|
|
supplicant: chain asynchronous requests for WPS
Don't have pending asynchronous requests in parallel, like setting
"ProcessCredentials" and "Start", or "Cancel" and "Start".
Instead, "Start" is only scheduled after "ProcessCredentials" completed
and "ProcessCredentials" is only scheduled after "Cancel" completed.
Also, handle the async response of these requests. For one, to achive the
chaining mentioned above and to log what happens and possible errors.
Upon new enrollment, a previously created GDBusProxy is now reused,
where the first operation is to Cancel the previous action.
Also, consistently <trace> log what is happening.
Not doing all of this is less lines of code. It's also simpler, and
faster. But in my opinion, it is (usually) better to check and wait for
return values, instead of firing off async requests uncontrolled. It
allows us to better know where we are and to log about each individual
step. This also makes all operations cancellable.
Undoubtedly, correctness and handling failures conflicts with simplicity
in this case -- or at least: what I think is "correctness" conflicts.
2017-04-28 16:22:37 +02:00
|
|
|
nm_supplicant_interface_cancel_wps (self);
|
|
|
|
|
if (priv->wps_data) {
|
|
|
|
|
/* we shut down, but an asynchronous Cancel request is pending.
|
|
|
|
|
* We don't want to cancel it, so mark wps-data that @self is gone.
|
|
|
|
|
* This way, _wps_handle_cancel_cb() knows it must no longer touch
|
|
|
|
|
* @self */
|
|
|
|
|
priv->wps_data->self = NULL;
|
|
|
|
|
priv->wps_data = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-14 19:30:21 +01:00
|
|
|
if (priv->assoc_data) {
|
2017-06-27 09:29:18 +02:00
|
|
|
gs_free_error GError *error = NULL;
|
2017-02-14 19:30:21 +01:00
|
|
|
|
|
|
|
|
nm_utils_error_set_cancelled (&error, TRUE, "NMSupplicantInterface");
|
|
|
|
|
assoc_return (self, error, "cancelled due to dispose of supplicant interface");
|
|
|
|
|
}
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2015-03-10 08:36:34 -05:00
|
|
|
if (priv->iface_proxy)
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_handlers_disconnect_by_data (priv->iface_proxy, object);
|
2015-02-01 01:16:45 -06:00
|
|
|
g_clear_object (&priv->iface_proxy);
|
2018-10-10 18:35:20 +02:00
|
|
|
if (priv->p2p_proxy)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (priv->p2p_proxy, object);
|
|
|
|
|
g_clear_object (&priv->p2p_proxy);
|
2018-10-10 23:08:15 +02:00
|
|
|
if (priv->group_proxy)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (priv->group_proxy, object);
|
|
|
|
|
g_clear_object (&priv->group_proxy);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2016-10-12 09:08:09 +02:00
|
|
|
nm_clear_g_cancellable (&priv->init_cancellable);
|
|
|
|
|
nm_clear_g_cancellable (&priv->other_cancellable);
|
2012-02-20 15:06:05 -06:00
|
|
|
|
2018-10-08 19:42:07 +02:00
|
|
|
if (priv->wpas_proxy)
|
|
|
|
|
g_signal_handlers_disconnect_by_data (priv->wpas_proxy, object);
|
2015-02-02 02:31:30 -06:00
|
|
|
g_clear_object (&priv->wpas_proxy);
|
2018-03-19 13:12:28 +01:00
|
|
|
g_clear_pointer (&priv->bss_proxies, g_hash_table_destroy);
|
2018-10-10 21:27:34 +02:00
|
|
|
g_clear_pointer (&priv->peer_proxies, g_hash_table_destroy);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2015-02-02 02:31:30 -06:00
|
|
|
g_clear_pointer (&priv->net_path, g_free);
|
|
|
|
|
g_clear_pointer (&priv->dev, g_free);
|
|
|
|
|
g_clear_pointer (&priv->object_path, g_free);
|
2015-04-05 23:31:02 -05:00
|
|
|
g_clear_pointer (&priv->current_bss, g_free);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (nm_supplicant_interface_parent_class)->dispose (object);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
|
|
|
|
|
{
|
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
|
|
object_class->dispose = dispose;
|
|
|
|
|
object_class->set_property = set_property;
|
|
|
|
|
object_class->get_property = get_property;
|
|
|
|
|
|
2016-01-19 16:08:29 +01:00
|
|
|
obj_properties[PROP_SCANNING] =
|
|
|
|
|
g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_SCANNING, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_CURRENT_BSS] =
|
|
|
|
|
g_param_spec_string (NM_SUPPLICANT_INTERFACE_CURRENT_BSS, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_IFACE] =
|
|
|
|
|
g_param_spec_string (NM_SUPPLICANT_INTERFACE_IFACE, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-10-10 22:43:49 +02:00
|
|
|
obj_properties[PROP_OBJECT_PATH] =
|
|
|
|
|
g_param_spec_string (NM_SUPPLICANT_INTERFACE_OBJECT_PATH, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-10-10 23:08:15 +02:00
|
|
|
obj_properties[PROP_P2P_GROUP_JOINED] =
|
|
|
|
|
g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_P2P_GROUP_JOINED, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-12-11 18:21:37 +01:00
|
|
|
obj_properties[PROP_P2P_GROUP_PATH] =
|
|
|
|
|
g_param_spec_string (NM_SUPPLICANT_INTERFACE_P2P_GROUP_PATH, "", "",
|
|
|
|
|
NULL,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-10-10 23:08:15 +02:00
|
|
|
obj_properties[PROP_P2P_GROUP_OWNER] =
|
|
|
|
|
g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_P2P_GROUP_OWNER, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-06-30 18:20:48 +02:00
|
|
|
obj_properties[PROP_DRIVER] =
|
|
|
|
|
g_param_spec_uint (NM_SUPPLICANT_INTERFACE_DRIVER, "", "",
|
|
|
|
|
0, G_MAXUINT, NM_SUPPLICANT_DRIVER_WIRELESS,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-10-10 18:35:20 +02:00
|
|
|
obj_properties[PROP_P2P_AVAILABLE] =
|
|
|
|
|
g_param_spec_boolean (NM_SUPPLICANT_INTERFACE_P2P_AVAILABLE, "", "",
|
|
|
|
|
FALSE,
|
|
|
|
|
G_PARAM_READABLE |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2017-01-18 17:41:12 +01:00
|
|
|
obj_properties[PROP_FAST_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_FAST_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-01-19 16:08:29 +01:00
|
|
|
obj_properties[PROP_AP_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_AP_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
2017-03-18 14:56:38 +01:00
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_PMF_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_PMF_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
2016-01-19 16:08:29 +01:00
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-01-16 06:28:37 +09:00
|
|
|
obj_properties[PROP_FILS_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_FILS_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2018-10-10 17:50:34 +02:00
|
|
|
obj_properties[PROP_P2P_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_P2P_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
|
obj_properties[PROP_WFD_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_WFD_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2019-07-15 11:30:15 +00:00
|
|
|
obj_properties[PROP_FT_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_FT_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2019-07-15 11:30:19 +00:00
|
|
|
obj_properties[PROP_SHA384_SUPPORT] =
|
|
|
|
|
g_param_spec_int (NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT, "", "",
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_YES,
|
|
|
|
|
NM_SUPPLICANT_FEATURE_UNKNOWN,
|
|
|
|
|
G_PARAM_WRITABLE |
|
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2016-01-19 16:08:29 +01:00
|
|
|
|
|
|
|
|
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
2015-04-05 23:31:02 -05:00
|
|
|
|
2010-10-05 14:19:43 -05:00
|
|
|
signals[STATE] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_STATE,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
2017-02-14 01:30:25 +01:00
|
|
|
G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
|
|
|
|
signals[REMOVED] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_REMOVED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 0);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2012-02-20 15:06:05 -06:00
|
|
|
signals[BSS_UPDATED] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_UPDATED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2012-03-02 18:17:34 -06:00
|
|
|
signals[BSS_REMOVED] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_BSS_REMOVED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
2018-10-10 21:27:34 +02:00
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
|
|
|
|
|
|
|
|
|
signals[PEER_UPDATED] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_PEER_UPDATED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_VARIANT);
|
|
|
|
|
|
|
|
|
|
signals[PEER_REMOVED] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_PEER_REMOVED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
2016-09-28 15:58:24 +02:00
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
2012-03-02 18:17:34 -06:00
|
|
|
|
2010-11-22 08:25:09 -06:00
|
|
|
signals[SCAN_DONE] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_SCAN_DONE,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2011-12-19 19:47:43 -06:00
|
|
|
signals[CREDENTIALS_REQUEST] =
|
2016-09-28 15:58:24 +02:00
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_CREDENTIALS_REQUEST,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING);
|
2010-10-05 14:19:43 -05:00
|
|
|
|
2017-04-13 10:42:32 +02:00
|
|
|
signals[WPS_CREDENTIALS] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_VARIANT);
|
2018-10-10 23:08:15 +02:00
|
|
|
|
|
|
|
|
signals[GROUP_STARTED] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_GROUP_STARTED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, NM_TYPE_SUPPLICANT_INTERFACE);
|
|
|
|
|
|
|
|
|
|
signals[GROUP_FINISHED] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_GROUP_FINISHED,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_STRING);
|
|
|
|
|
|
|
|
|
|
signals[GROUP_FORMATION_FAILURE] =
|
|
|
|
|
g_signal_new (NM_SUPPLICANT_INTERFACE_GROUP_FORMATION_FAILURE,
|
|
|
|
|
G_OBJECT_CLASS_TYPE (object_class),
|
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
|
0,
|
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
|
G_TYPE_NONE, 1, G_TYPE_VARIANT);
|
2017-04-13 10:42:32 +02:00
|
|
|
}
|