wifi: merge branch 'th/fix-wifi-scan-1'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/445
This commit is contained in:
Thomas Haller
2020-04-03 11:27:16 +02:00
15 changed files with 486 additions and 404 deletions

View File

@@ -2922,7 +2922,6 @@ wifi_list_finish (WifiListData *wifi_list_data,
guint i;
if ( !force_finished
&& scan_info->rescan_cutoff_msec != G_MAXINT64
&& scan_info->rescan_cutoff_msec > _device_wifi_get_last_scan (wifi_list_data->wifi)) {
/* wait longer... */
return;
@@ -3115,7 +3114,7 @@ do_device_wifi_list (NmCli *nmc, int argc, char **argv)
else if (nm_streq (rescan, "no"))
rescan_cutoff_msec = G_MININT64;
else if (nm_streq (rescan, "yes"))
rescan_cutoff_msec = G_MAXINT64;
rescan_cutoff_msec = nm_utils_get_timestamp_msec ();
else {
g_string_printf (nmc->return_text, _("Error: invalid rescan argument: '%s' not among [auto, no, yes]"), rescan);
return NMC_RESULT_ERROR_USER_INPUT;

View File

@@ -24,7 +24,6 @@ static const guint8 *volatile global_seed = NULL;
static const guint8 *
_get_hash_key_init (void)
{
static gsize g_lock;
/* the returned hash is aligned to guin64, hence, it is safe
* to use it as guint* or guint64* pointer. */
static union {
@@ -34,50 +33,49 @@ _get_hash_key_init (void)
guint64 _align_as_uint64;
} g_arr;
const guint8 *g;
union {
guint8 v8[HASH_KEY_SIZE];
guint vuint;
} t_arr;
again:
g = g_atomic_pointer_get (&global_seed);
if (G_LIKELY (g != NULL)) {
nm_assert (g == g_arr.v8);
return g;
}
{
CSipHash siph_state;
if (!G_UNLIKELY (g)) {
static gsize g_lock;
uint64_t h;
/* initialize a random key in t_arr. */
union {
guint vuint;
guint8 v8[HASH_KEY_SIZE];
guint8 _extra_entropy[3 * HASH_KEY_SIZE];
} t_arr;
nm_utils_random_bytes (&t_arr, sizeof (t_arr));
/* use siphash() of the key-size, to mangle the first guint. Otherwise,
* the first guint has only the entropy that nm_utils_random_bytes()
* generated for the first 4 bytes and relies on a good random generator.
/* We only initialize one random hash key. So we can spend some effort
* of getting this right. For one, we collect more random bytes than
* necessary.
*
* The first int is especially interesting for nm_hash_static() below, and we
* want to have it all the entropy of t_arr. */
c_siphash_init (&siph_state, t_arr.v8);
c_siphash_append (&siph_state, (const guint8 *) &t_arr, sizeof (t_arr));
h = c_siphash_finalize (&siph_state);
if (sizeof (guint) < sizeof (h))
t_arr.vuint = t_arr.vuint ^ ((guint) (h & 0xFFFFFFFFu)) ^ ((guint) (h >> 32));
* Then, the first guint of the seed should have all the entropy that we could
* obtain in sizeof(t_arr). For that, siphash(t_arr) and xor the first guint
* with hash.
* The first guint is especially interesting for nm_hash_static() below that
* doesn't use siphash itself. */
h = c_siphash_hash (t_arr.v8,
(const guint8 *) &t_arr,
sizeof (t_arr));
if (sizeof (h) > sizeof (guint))
t_arr.vuint = t_arr.vuint ^ ((guint) (h & G_MAXUINT)) ^ ((guint) (h >> 32));
else
t_arr.vuint = t_arr.vuint ^ ((guint) (h & 0xFFFFFFFFu));
t_arr.vuint = t_arr.vuint ^ ((guint) (h & G_MAXUINT));
if (!g_once_init_enter (&g_lock)) {
/* lost a race. The random key is already initialized. */
goto again;
}
memcpy (g_arr.v8, t_arr.v8, HASH_KEY_SIZE);
g = g_arr.v8;
g_atomic_pointer_set (&global_seed, g);
g_once_init_leave (&g_lock, 1);
}
if (!g_once_init_enter (&g_lock)) {
/* lost a race. The random key is already initialized. */
goto again;
}
memcpy (g_arr.v8, t_arr.v8, HASH_KEY_SIZE);
g = g_arr.v8;
g_atomic_pointer_set (&global_seed, g);
g_once_init_leave (&g_lock, 1);
nm_assert (g == g_arr.v8);
return g;
}
@@ -94,18 +92,24 @@ again:
guint
nm_hash_static (guint static_seed)
{
/* note that we only xor the static_seed with the key.
* We don't use siphash, which would mix the bits better.
* Note that this doesn't matter, because static_seed is not
* supposed to be a value that you are hashing (for that, use
* full siphash).
* Instead, different callers may set a different static_seed
* so that nm_hash_str(NULL) != nm_hash_ptr(NULL).
/* Note that we only xor the static_seed with the first guint of the key.
*
* Also, ensure that we don't return zero.
* We don't use siphash, which would mix the bits better with _get_hash_key().
* Note that nm_hash_static() isn't used to hash the static_seed. Instead, it
* is used to get a unique hash value in a static context. That means, every
* caller is responsible to choose a static_seed that is sufficiently
* distinct from all other callers. In other words, static_seed should be a
* unique constant with good entropy.
*
* Note that _get_hash_key_init() already xored the first guint of the
* key with the siphash of the entire static key. That means, even if
* we got bad randomness for the first guint, the first guint is also
* mixed with the randomness of the entire random key.
*
* Also, ensure that we don't return zero (like for nm_hash_complete()).
*/
return ((*((const guint *) _get_hash_key ())) ^ static_seed)
?: static_seed ?: 3679500967u;
return ((*((const guint *) _get_hash_key ())) ^ static_seed)
?: 3679500967u;
}
void
@@ -257,3 +261,25 @@ nm_ppdirect_equal (gconstpointer a, gconstpointer b)
return **s1 == **s2;
}
/*****************************************************************************/
guint
nm_pgbytes_hash (gconstpointer p)
{
GBytes *const*ptr = p;
gconstpointer arr;
gsize len;
arr = g_bytes_get_data (*ptr, &len);
return nm_hash_mem (1470631313u, arr, len);
}
gboolean
nm_pgbytes_equal (gconstpointer a, gconstpointer b)
{
GBytes *const*ptr_a = a;
GBytes *const*ptr_b = b;
return g_bytes_equal (*ptr_a, *ptr_b);
}

View File

@@ -88,15 +88,15 @@ nm_hash_complete (NMHashState *state)
/* we don't ever want to return a zero hash.
*
* NMPObject requires that in _idx_obj_part(), and it's just a good idea. */
return (((guint) (h >> 32)) ^ ((guint) h)) ?: 1396707757u;
return (((guint) (h >> 32)) ^ ((guint) h))
?: 1396707757u;
}
static inline void
nm_hash_update (NMHashState *state, const void *ptr, gsize n)
{
nm_assert (state);
nm_assert (ptr);
nm_assert (n > 0);
nm_assert (n == 0 || ptr);
/* Note: the data passed in here might be sensitive data (secrets),
* that we should nm_explicty_zero() afterwards. However, since
@@ -267,6 +267,18 @@ guint nm_str_hash (gconstpointer str);
nm_hash_complete (&_h); \
})
static inline guint
nm_hash_mem (guint static_seed, const void *ptr, gsize n)
{
NMHashState h;
if (n == 0)
return nm_hash_static (static_seed);
nm_hash_init (&h, static_seed);
nm_hash_update (&h, ptr, n);
return nm_hash_complete (&h);
}
/*****************************************************************************/
/* nm_pstr_*() are for hashing keys that are pointers to strings,
@@ -303,6 +315,11 @@ gboolean nm_ppdirect_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/
guint nm_pgbytes_hash (gconstpointer p);
gboolean nm_pgbytes_equal (gconstpointer a, gconstpointer b);
/*****************************************************************************/
#define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x"
/* sometimes we want to log a pointer directly, for providing context/information about

View File

@@ -811,7 +811,7 @@ supplicant_connection_timeout_cb (gpointer user_data)
state = nm_supplicant_interface_get_state (priv->supplicant.iface);
if (state != NM_SUPPLICANT_INTERFACE_STATE_COMPLETED
&& NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (state))
&& nm_supplicant_interface_state_is_operational (state))
priv->supplicant.lnk_timeout_id = g_timeout_add_seconds (SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self);
}
@@ -862,7 +862,7 @@ supplicant_interface_create_cb (NMSupplicantManager *supplicant_manager,
supplicant_connection_timeout_cb,
self);
if (NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (nm_supplicant_interface_get_state (iface)))
if (nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (iface)))
supplicant_iface_start (self);
}

View File

@@ -584,7 +584,7 @@ supplicant_connection_timeout_cb (gpointer user_data)
state = nm_supplicant_interface_get_state (priv->supplicant.iface);
if (state != NM_SUPPLICANT_INTERFACE_STATE_COMPLETED
&& NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (state))
&& nm_supplicant_interface_state_is_operational (state))
priv->supplicant.lnk_timeout_id = g_timeout_add_seconds (SUPPLICANT_LNK_TIMEOUT_SEC, supplicant_lnk_timeout_cb, self);
}
@@ -636,7 +636,7 @@ supplicant_interface_create_cb (NMSupplicantManager *supplicant_manager,
supplicant_connection_timeout_cb,
self);
if (NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (nm_supplicant_interface_get_state (iface)))
if (nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (iface)))
supplicant_iface_start (self);
}

View File

@@ -43,14 +43,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceIwd,
PROP_LAST_SCAN,
);
enum {
SCANNING_PROHIBITED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
GDBusObject * dbus_obj;
GDBusProxy * dbus_device_proxy;
@@ -79,9 +71,6 @@ struct _NMDeviceIwd {
struct _NMDeviceIwdClass {
NMDeviceClass parent;
/* Signals */
gboolean (*scanning_prohibited) (NMDeviceIwd *device, gboolean periodic);
};
/*****************************************************************************/
@@ -95,21 +84,22 @@ G_DEFINE_TYPE (NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE)
static void schedule_periodic_scan (NMDeviceIwd *self,
gboolean initial_scan);
static gboolean check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic);
/*****************************************************************************/
static void
_ap_dump (NMDeviceIwd *self,
NMLogLevel log_level,
const NMWifiAP *ap,
const char *prefix,
gint32 now_s)
const char *prefix)
{
char buf[1024];
buf[0] = '\0';
_NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-ap: %-7s %s",
prefix,
nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s));
nm_wifi_ap_to_string (ap, buf, sizeof (buf), 0));
}
/* Callers ensure we're not removing current_ap */
@@ -126,12 +116,12 @@ ap_add_remove (NMDeviceIwd *self,
ap->wifi_device = NM_DEVICE (self);
c_list_link_tail (&priv->aps_lst_head, &ap->aps_lst);
nm_dbus_object_export (NM_DBUS_OBJECT (ap));
_ap_dump (self, LOGL_DEBUG, ap, "added", 0);
_ap_dump (self, LOGL_DEBUG, ap, "added");
nm_device_wifi_emit_signal_access_point (NM_DEVICE (self), ap, TRUE);
} else {
ap->wifi_device = NULL;
c_list_unlink (&ap->aps_lst);
_ap_dump (self, LOGL_DEBUG, ap, "removed", 0);
_ap_dump (self, LOGL_DEBUG, ap, "removed");
}
_notify (self, PROP_ACCESS_POINTS);
@@ -357,7 +347,7 @@ get_ordered_networks_cb (GObject *source, GAsyncResult *res, gpointer user_data)
nm_wifi_ap_get_supplicant_path (ap));
if (new_ap) {
if (nm_wifi_ap_set_strength (ap, nm_wifi_ap_get_strength (new_ap))) {
_ap_dump (self, LOGL_TRACE, ap, "updated", 0);
_ap_dump (self, LOGL_TRACE, ap, "updated");
changed = TRUE;
}
g_hash_table_remove (new_aps,
@@ -973,15 +963,6 @@ _nm_device_iwd_get_aps (NMDeviceIwd *self)
return &NM_DEVICE_IWD_GET_PRIVATE (self)->aps_lst_head;
}
static gboolean
check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic)
{
gboolean prohibited = FALSE;
g_signal_emit (self, signals[SCANNING_PROHIBITED], 0, periodic, &prohibited);
return prohibited;
}
static void
scan_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
@@ -1091,7 +1072,7 @@ _nm_device_iwd_request_scan (NMDeviceIwd *self,
}
static gboolean
scanning_prohibited (NMDeviceIwd *self, gboolean periodic)
check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
@@ -2581,8 +2562,6 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
device_class->state_changed = device_state_changed;
klass->scanning_prohibited = scanning_prohibited;
obj_properties[PROP_MODE] =
g_param_spec_uint (NM_DEVICE_IWD_MODE, "", "",
NM_802_11_MODE_UNKNOWN,
@@ -2627,12 +2606,4 @@ nm_device_iwd_class_init (NMDeviceIwdClass *klass)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[SCANNING_PROHIBITED] =
g_signal_new (NM_DEVICE_IWD_SCANNING_PROHIBITED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMDeviceIwdClass, scanning_prohibited),
NULL, NULL, NULL,
G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
}

View File

@@ -25,8 +25,6 @@
#define NM_DEVICE_IWD_SCANNING NM_DEVICE_WIFI_SCANNING
#define NM_DEVICE_IWD_LAST_SCAN NM_DEVICE_WIFI_LAST_SCAN
#define NM_DEVICE_IWD_SCANNING_PROHIBITED NM_DEVICE_WIFI_SCANNING_PROHIBITED
typedef struct _NMDeviceIwd NMDeviceIwd;
typedef struct _NMDeviceIwdClass NMDeviceIwdClass;

View File

@@ -130,7 +130,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
gboolean scanning;
/* disconnect companion device, if it is connected */
if (nm_device_get_act_request (NM_DEVICE (priv->companion))) {
@@ -145,8 +144,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
}
/* wait with continuing configuration until the companion device is done scanning */
g_object_get (priv->companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL);
if (scanning) {
if (nm_device_wifi_get_scanning (NM_DEVICE_WIFI (priv->companion))) {
priv->stage1_waiting = TRUE;
return NM_ACT_STAGE_RETURN_POSTPONE;
}
@@ -237,6 +235,9 @@ companion_cleanup (NMDeviceOlpcMesh *self)
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
if (priv->companion) {
nm_device_wifi_scanning_prohibited_track (NM_DEVICE_WIFI (priv->companion),
self,
FALSE);
g_signal_handlers_disconnect_by_data (priv->companion, self);
g_clear_object (&priv->companion);
}
@@ -248,13 +249,14 @@ companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_d
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
gboolean scanning;
nm_assert (NM_IS_DEVICE_WIFI (companion));
nm_assert (priv->companion == (gpointer) companion);
if (!priv->stage1_waiting)
return;
g_object_get (companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL);
if (!scanning) {
if (!nm_device_wifi_get_scanning (NM_DEVICE_WIFI (companion))) {
priv->stage1_waiting = FALSE;
nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self), FALSE);
}
@@ -289,16 +291,6 @@ companion_state_changed_cb (NMDeviceWifi *companion,
NM_DEVICE_STATE_REASON_USER_REQUESTED);
}
static gboolean
companion_scan_prohibited_cb (NMDeviceWifi *companion, gboolean periodic, gpointer user_data)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (user_data);
NMDeviceState state = nm_device_get_state (NM_DEVICE (self));
/* Don't allow the companion to scan while configuring the mesh interface */
return (state >= NM_DEVICE_STATE_PREPARE) && (state <= NM_DEVICE_STATE_IP_CONFIG);
}
static gboolean
companion_autoconnect_allowed_cb (NMDeviceWifi *companion, gpointer user_data)
{
@@ -324,7 +316,7 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other)
if (!nm_utils_hwaddr_matches (my_addr, -1, their_addr, -1))
return FALSE;
g_assert (priv->companion == NULL);
nm_assert (priv->companion == NULL);
priv->companion = g_object_ref (other);
_LOGI (LOGD_OLPC, "found companion Wi-Fi device %s",
@@ -336,9 +328,6 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other)
g_signal_connect (G_OBJECT (other), "notify::" NM_DEVICE_WIFI_SCANNING,
G_CALLBACK (companion_notify_cb), self);
g_signal_connect (G_OBJECT (other), NM_DEVICE_WIFI_SCANNING_PROHIBITED,
G_CALLBACK (companion_scan_prohibited_cb), self);
g_signal_connect (G_OBJECT (other), NM_DEVICE_AUTOCONNECT_ALLOWED,
G_CALLBACK (companion_autoconnect_allowed_cb), self);
@@ -400,8 +389,24 @@ state_changed (NMDevice *device,
NMDeviceState old_state,
NMDeviceStateReason reason)
{
NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
if (new_state == NM_DEVICE_STATE_UNAVAILABLE)
find_companion (NM_DEVICE_OLPC_MESH (device));
find_companion (self);
if (priv->companion) {
gboolean temporarily_prohibited = FALSE;
if ( new_state >= NM_DEVICE_STATE_PREPARE
&& new_state <= NM_DEVICE_STATE_IP_CONFIG) {
/* Don't allow the companion to scan while configuring the mesh interface */
temporarily_prohibited = TRUE;
}
nm_device_wifi_scanning_prohibited_track (NM_DEVICE_WIFI (priv->companion),
self,
temporarily_prohibited);
}
}
static guint32

View File

@@ -228,7 +228,7 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags)
return FALSE;
supplicant_state = nm_supplicant_interface_get_state (priv->mgmt_iface);
return NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (supplicant_state);
return nm_supplicant_interface_state_is_operational (supplicant_state);
}
static gboolean
@@ -712,7 +712,7 @@ check_group_iface_ready (NMDeviceWifiP2P *self)
if (!priv->group_iface)
return;
if (!NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (nm_supplicant_interface_get_state (priv->group_iface)))
if (!nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (priv->group_iface)))
return;
if (!nm_supplicant_interface_get_p2p_group_joined (priv->group_iface))
@@ -910,7 +910,7 @@ device_state_changed (NMDevice *device,
break;
case NM_DEVICE_STATE_UNAVAILABLE:
if ( !priv->mgmt_iface
|| !NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (nm_supplicant_interface_get_state (priv->mgmt_iface)))
|| !nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (priv->mgmt_iface)))
_set_is_waiting_for_supplicant (self, TRUE);
break;
case NM_DEVICE_STATE_NEED_AUTH:
@@ -1080,7 +1080,7 @@ done:
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
_set_is_waiting_for_supplicant (self,
!priv->mgmt_iface
|| !NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (nm_supplicant_interface_get_state (priv->mgmt_iface)));
|| !nm_supplicant_interface_state_is_operational (nm_supplicant_interface_get_state (priv->mgmt_iface)));
}
void

View File

@@ -12,6 +12,7 @@
#include <unistd.h>
#include "nm-glib-aux/nm-ref-string.h"
#include "nm-glib-aux/nm-c-list.h"
#include "nm-device-wifi-p2p.h"
#include "nm-wifi-ap.h"
#include "nm-libnm-core-intern/nm-common-macros.h"
@@ -43,10 +44,9 @@
#include "devices/nm-device-logging.h"
_LOG_DECLARE_SELF(NMDeviceWifi);
/* All of these are in seconds */
#define SCAN_INTERVAL_MIN 3
#define SCAN_INTERVAL_STEP 20
#define SCAN_INTERVAL_MAX 120
#define SCAN_INTERVAL_SEC_MIN 3
#define SCAN_INTERVAL_SEC_STEP 20
#define SCAN_INTERVAL_SEC_MAX 120
#define SCAN_RAND_MAC_ADDRESS_EXPIRE_MIN 5
@@ -63,7 +63,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceWifi,
);
enum {
SCANNING_PROHIBITED,
P2P_DEVICE_CREATED,
LAST_SIGNAL
@@ -72,11 +71,11 @@ enum {
static guint signals[LAST_SIGNAL] = { 0 };
typedef struct {
gint8 invalid_strength_counter;
CList aps_lst_head;
GHashTable *aps_idx_by_supplicant_path;
CList scanning_prohibited_lst_head;
NMWifiAP * current_ap;
guint32 rate;
bool enabled:1; /* rfkilled or not */
@@ -85,9 +84,10 @@ typedef struct {
bool is_scanning:1;
bool hidden_probe_scan_warn:1;
gint64 last_scan; /* milliseconds */
gint64 last_scan_msec;
gint32 scheduled_scan_time; /* seconds */
guint8 scan_interval; /* seconds */
guint8 scan_interval_sec;
guint pending_scan_id;
guint ap_dump_id;
@@ -100,7 +100,7 @@ typedef struct {
NMActRequestGetSecretsCallId *wifi_secrets_id;
guint periodic_source_id;
guint periodic_update_id;
guint link_timeout_id;
guint32 failed_iface_count;
guint reacquire_iface_id;
@@ -125,9 +125,6 @@ struct _NMDeviceWifi
struct _NMDeviceWifiClass
{
NMDeviceClass parent;
/* Signals */
gboolean (*scanning_prohibited) (NMDeviceWifi *device, gboolean periodic);
};
/*****************************************************************************/
@@ -164,17 +161,10 @@ static void supplicant_iface_bss_changed_cb (NMSupplicantInterface *iface,
gboolean is_present,
NMDeviceWifi *self);
static void supplicant_iface_scan_done_cb (NMSupplicantInterface * iface,
NMDeviceWifi * self);
static void supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface,
GVariant *credentials,
NMDeviceWifi *self);
static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface,
GParamSpec * pspec,
NMDeviceWifi * self);
static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self);
@@ -183,6 +173,10 @@ static void supplicant_iface_notify_p2p_available (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self);
static void _requested_scan_set (NMDeviceWifi *self, gboolean value);
static void periodic_update (NMDeviceWifi *self);
static void request_wireless_scan (NMDeviceWifi *self,
gboolean periodic,
gboolean force_if_scanning,
@@ -199,19 +193,66 @@ static void recheck_p2p_availability (NMDeviceWifi *self);
/*****************************************************************************/
void
nm_device_wifi_scanning_prohibited_track (NMDeviceWifi *self,
gpointer tag,
gboolean temporarily_prohibited)
{
NMDeviceWifiPrivate *priv;
NMCListElem *elem;
g_return_if_fail (NM_IS_DEVICE_WIFI (self));
nm_assert (tag);
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
/* We track these with a simple CList. This would be not efficient, if
* there would be many users that need to be tracked at the same time (there
* aren't). In fact, most of the time there is no NMDeviceOlpcMesh and
* nobody tracks itself here. Optimize for that and simplicity. */
elem = nm_c_list_elem_find_first (&priv->scanning_prohibited_lst_head,
iter,
iter == tag);
if (!temporarily_prohibited) {
if (!elem)
return;
nm_c_list_elem_free (elem);
return;
}
if (elem)
return;
c_list_link_tail (&priv->scanning_prohibited_lst_head,
&nm_c_list_elem_new_stale (tag)->lst);
}
/*****************************************************************************/
static void
_ap_dump (NMDeviceWifi *self,
NMLogLevel log_level,
const NMWifiAP *ap,
const char *prefix,
gint32 now_s)
gint64 now_msec)
{
char buf[1024];
buf[0] = '\0';
_NMLOG (log_level, LOGD_WIFI_SCAN, "wifi-ap: %-7s %s",
prefix,
nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s));
nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_msec));
}
gboolean
nm_device_wifi_get_scanning (NMDeviceWifi *self)
{
g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), FALSE);
return NM_DEVICE_WIFI_GET_PRIVATE (self)->is_scanning;
}
static void
@@ -219,6 +260,7 @@ _notify_scanning (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gboolean scanning;
gboolean last_scan_changed = FALSE;
scanning = priv->sup_iface
&& nm_supplicant_interface_get_scanning (priv->sup_iface);
@@ -226,9 +268,42 @@ _notify_scanning (NMDeviceWifi *self)
if (scanning == priv->is_scanning)
return;
_LOGD (LOGD_WIFI, "wifi-scan: scanning-state: %s", scanning ? "scanning" : "idle");
priv->is_scanning = scanning;
_notify (self, PROP_SCANNING);
if ( !scanning
|| priv->last_scan_msec == 0) {
last_scan_changed = TRUE;
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
}
_LOGD (LOGD_WIFI,
"wifi-scan: scanning-state: %s%s",
scanning ? "scanning" : "idle",
last_scan_changed ? " (notify last-scan)" : "");
schedule_scan (self, TRUE);
nm_gobject_notify_together (self,
PROP_SCANNING,
last_scan_changed
? PROP_LAST_SCAN
: PROP_0);
if (!priv->is_scanning) {
_requested_scan_set (self, FALSE);
if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) {
/* Run a quick update of current AP when coming out of a scan */
periodic_update (self);
}
}
}
static void
supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self)
{
_notify_scanning (self);
}
static gboolean
@@ -278,10 +353,6 @@ supplicant_interface_acquire_cb (NMSupplicantManager *supplicant_manager,
NM_SUPPLICANT_INTERFACE_BSS_CHANGED,
G_CALLBACK (supplicant_iface_bss_changed_cb),
self);
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_SCAN_DONE,
G_CALLBACK (supplicant_iface_scan_done_cb),
self);
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS,
G_CALLBACK (supplicant_iface_wps_credentials_cb),
@@ -360,9 +431,9 @@ supplicant_interface_release (NMDeviceWifi *self)
nm_clear_g_source (&priv->pending_scan_id);
/* Reset the scan interval to be pretty frequent when disconnected */
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
priv->scan_interval_sec = SCAN_INTERVAL_SEC_MIN + SCAN_INTERVAL_SEC_STEP;
_LOGD (LOGD_WIFI, "wifi-scan: reset interval to %u seconds",
(unsigned) priv->scan_interval);
(unsigned) priv->scan_interval_sec);
nm_clear_g_source (&priv->ap_dump_id);
@@ -442,44 +513,48 @@ set_current_ap (NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available
static void
periodic_update (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
int ifindex = nm_device_get_ifindex (NM_DEVICE (self));
NMDeviceWifiPrivate *priv;
int ifindex;
guint32 new_rate;
int percent;
NMDeviceState state;
NMSupplicantInterfaceState supplicant_state;
/* BSSID and signal strength have meaningful values only if the device
* is activated and not scanning.
*/
state = nm_device_get_state (NM_DEVICE (self));
if (state != NM_DEVICE_STATE_ACTIVATED)
if (nm_device_get_state (NM_DEVICE (self)) != NM_DEVICE_STATE_ACTIVATED) {
/* BSSID and signal strength have meaningful values only if the device
* is activated and not scanning.
*/
return;
}
/* Only update current AP if we're actually talking to something, otherwise
* assume the old one (if any) is still valid until we're told otherwise or
* the connection fails.
*/
supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( supplicant_state < NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING
|| supplicant_state > NM_SUPPLICANT_INTERFACE_STATE_COMPLETED
|| nm_supplicant_interface_get_scanning (priv->sup_iface))
return;
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
/* In AP mode we currently have nothing to do. */
if (priv->mode == NM_802_11_MODE_AP)
if ( !nm_supplicant_interface_state_is_associated (nm_supplicant_interface_get_state (priv->sup_iface))
|| nm_supplicant_interface_get_scanning (priv->sup_iface)) {
/* Only update current AP if we're actually talking to something, otherwise
* assume the old one (if any) is still valid until we're told otherwise or
* the connection fails.
*/
return;
}
if (priv->mode == NM_802_11_MODE_AP) {
/* In AP mode we currently have nothing to do. */
return;
}
ifindex = nm_device_get_ifindex (NM_DEVICE (self));
if (ifindex <= 0)
g_return_if_reached ();
if (priv->current_ap) {
/* Smooth out the strength to work around crappy drivers */
int percent;
percent = nm_platform_wifi_get_quality (nm_device_get_platform (NM_DEVICE (self)), ifindex);
if (percent >= 0 || ++priv->invalid_strength_counter > 3) {
if ( percent >= 0
&& percent <= 100) {
if (nm_wifi_ap_set_strength (priv->current_ap, (gint8) percent)) {
#if NM_MORE_LOGGING
_ap_dump (self, LOGL_TRACE, priv->current_ap, "updated", 0);
#endif
}
priv->invalid_strength_counter = 0;
}
}
@@ -493,7 +568,7 @@ periodic_update (NMDeviceWifi *self)
static gboolean
periodic_update_cb (gpointer user_data)
{
periodic_update (NM_DEVICE_WIFI (user_data));
periodic_update (user_data);
return TRUE;
}
@@ -629,7 +704,7 @@ deactivate (NMDevice *device)
int ifindex = nm_device_get_ifindex (device);
NM80211Mode old_mode = priv->mode;
nm_clear_g_source (&priv->periodic_source_id);
nm_clear_g_source (&priv->periodic_update_id);
cleanup_association_attempt (self, TRUE);
@@ -1120,7 +1195,7 @@ ssids_options_to_ptrarray (GVariant *value, GError **error)
if (num_ssids > 32) {
g_set_error_literal (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ALLOWED,
NM_DEVICE_ERROR_INVALID_ARGUMENT,
"too many SSIDs requested to scan");
return NULL;
}
@@ -1137,7 +1212,7 @@ ssids_options_to_ptrarray (GVariant *value, GError **error)
if (len > 32) {
g_set_error (error,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ALLOWED,
NM_DEVICE_ERROR_INVALID_ARGUMENT,
"SSID at index %d more than 32 bytes", (int) i);
return NULL;
}
@@ -1163,8 +1238,7 @@ dbus_request_scan_cb (NMDevice *device,
gpointer user_data)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (device);
gs_unref_variant GVariant *scan_options = user_data;
gs_unref_ptrarray GPtrArray *ssids = NULL;
gs_unref_ptrarray GPtrArray *ssids = user_data;
if (error) {
g_dbus_method_invocation_return_gerror (context, error);
@@ -1179,28 +1253,6 @@ dbus_request_scan_cb (NMDevice *device,
return;
}
if (scan_options) {
gs_unref_variant GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL);
if (val) {
gs_free_error GError *ssid_error = NULL;
if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("aay"))) {
g_dbus_method_invocation_return_error_literal (context,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ALLOWED,
"Invalid 'ssid' scan option");
return;
}
ssids = ssids_options_to_ptrarray (val, &ssid_error);
if (ssid_error) {
g_dbus_method_invocation_return_gerror (context, ssid_error);
return;
}
}
}
request_wireless_scan (self, FALSE, FALSE, ssids);
g_dbus_method_invocation_return_value (context, NULL);
}
@@ -1213,6 +1265,29 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self,
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMDevice *device = NM_DEVICE (self);
gint64 last_scan;
gs_unref_ptrarray GPtrArray *ssids = NULL;
if (options) {
gs_unref_variant GVariant *val = g_variant_lookup_value (options, "ssids", NULL);
if (val) {
gs_free_error GError *ssid_error = NULL;
if (!g_variant_is_of_type (val, G_VARIANT_TYPE ("aay"))) {
g_dbus_method_invocation_return_error_literal (invocation,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_INVALID_ARGUMENT,
"Invalid 'ssid' scan option");
return;
}
ssids = ssids_options_to_ptrarray (val, &ssid_error);
if (ssid_error) {
g_dbus_method_invocation_return_gerror (invocation, ssid_error);
return;
}
}
}
if ( !priv->enabled
|| !priv->sup_iface
@@ -1235,7 +1310,12 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self,
last_scan = nm_supplicant_interface_get_last_scan (priv->sup_iface);
if ( last_scan > 0
&& (nm_utils_get_monotonic_timestamp_msec () - last_scan) < 10 * NM_UTILS_MSEC_PER_SEC) {
&& nm_utils_get_monotonic_timestamp_msec () < last_scan + (10 * NM_UTILS_MSEC_PER_SEC)) {
/* FIXME: we really should not outright reject a scan request in this case. We should
* ensure to start a scan request soon, possibly with rate limiting. And there is no
* need to tell the caller that we aren't going to scan...
*
* Same above, if we are currently scanning... */
g_dbus_method_invocation_return_error_literal (invocation,
NM_DEVICE_ERROR,
NM_DEVICE_ERROR_NOT_ALLOWED,
@@ -1250,16 +1330,19 @@ _nm_device_wifi_request_scan (NMDeviceWifi *self,
NM_AUTH_PERMISSION_WIFI_SCAN,
TRUE,
dbus_request_scan_cb,
options ? g_variant_ref (options) : NULL);
g_steal_pointer (&ssids));
}
static gboolean
scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
check_scanning_prohibited (NMDeviceWifi *self,
gboolean periodic)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
NMSupplicantInterfaceState supplicant_state;
g_return_val_if_fail (priv->sup_iface != NULL, TRUE);
nm_assert (NM_IS_SUPPLICANT_INTERFACE (priv->sup_iface));
if (!c_list_is_empty (&priv->scanning_prohibited_lst_head))
return TRUE;
/* Don't scan when a an AP or Ad-Hoc connection is active as it will
* disrupt connected clients or peers.
@@ -1296,11 +1379,11 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
}
/* Prohibit scans if the supplicant is busy */
supplicant_state = nm_supplicant_interface_get_state (priv->sup_iface);
if ( supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE
|| supplicant_state == NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE
if ( NM_IN_SET (nm_supplicant_interface_get_state (priv->sup_iface),
NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATING,
NM_SUPPLICANT_INTERFACE_STATE_ASSOCIATED,
NM_SUPPLICANT_INTERFACE_STATE_4WAY_HANDSHAKE,
NM_SUPPLICANT_INTERFACE_STATE_GROUP_HANDSHAKE)
|| nm_supplicant_interface_get_scanning (priv->sup_iface))
return TRUE;
@@ -1308,15 +1391,6 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
return FALSE;
}
static gboolean
check_scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
{
gboolean prohibited = FALSE;
g_signal_emit (self, signals[SCANNING_PROHIBITED], 0, periodic, &prohibited);
return prohibited;
}
static gboolean
hidden_filter_func (NMSettings *settings,
NMSettingsConnection *set_con,
@@ -1468,14 +1542,15 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gint32 now = nm_utils_get_monotonic_timestamp_sec ();
/* Cancel the pending scan if it would happen later than (now + the scan_interval) */
/* Cancel the pending scan if it would happen later than (now + the scan_interval_sec) */
if (priv->pending_scan_id) {
if (now + priv->scan_interval < priv->scheduled_scan_time)
if (now + priv->scan_interval_sec < priv->scheduled_scan_time)
nm_clear_g_source (&priv->pending_scan_id);
}
if (!priv->pending_scan_id) {
guint factor = 2, next_scan = priv->scan_interval;
guint factor = 2;
guint next_scan = priv->scan_interval_sec;
if ( nm_device_is_activating (NM_DEVICE (self))
|| (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED))
@@ -1485,40 +1560,25 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
request_wireless_scan_periodic,
self);
priv->scheduled_scan_time = now + priv->scan_interval;
if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) {
priv->scan_interval += (SCAN_INTERVAL_STEP / factor);
priv->scheduled_scan_time = now + priv->scan_interval_sec;
if (backoff && (priv->scan_interval_sec < (SCAN_INTERVAL_SEC_MAX / factor))) {
priv->scan_interval_sec += (SCAN_INTERVAL_SEC_STEP / factor);
/* Ensure the scan interval will never be less than 20s... */
priv->scan_interval = MAX(priv->scan_interval, SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP);
priv->scan_interval_sec = MAX(priv->scan_interval_sec, SCAN_INTERVAL_SEC_MIN + SCAN_INTERVAL_SEC_STEP);
/* ... or more than 120s */
priv->scan_interval = MIN(priv->scan_interval, SCAN_INTERVAL_MAX);
} else if (!backoff && (priv->scan_interval == 0)) {
priv->scan_interval_sec = MIN(priv->scan_interval_sec, SCAN_INTERVAL_SEC_MAX);
} else if (!backoff && (priv->scan_interval_sec == 0)) {
/* Invalid combination; would cause continual rescheduling of
* the scan and hog CPU. Reset to something minimally sane.
*/
priv->scan_interval = 5;
priv->scan_interval_sec = 5;
}
_LOGD (LOGD_WIFI, "wifi-scan: scheduled in %d seconds (interval now %d seconds)",
next_scan, priv->scan_interval);
next_scan, priv->scan_interval_sec);
}
}
static void
supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
_LOGD (LOGD_WIFI, "wifi-scan: scan-done callback");
priv->last_scan = nm_utils_get_monotonic_timestamp_msec ();
_notify (self, PROP_LAST_SCAN);
schedule_scan (self, TRUE);
_requested_scan_set (self, FALSE);
}
/****************************************************************************
* WPA Supplicant control stuff
*
@@ -1534,14 +1594,21 @@ ap_list_dump (gpointer user_data)
if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) {
NMWifiAP *ap;
gint32 now_s = nm_utils_get_monotonic_timestamp_sec ();
gint64 now_msec = nm_utils_get_monotonic_timestamp_msec ();
char str_buf[100];
_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%" G_GINT64_FORMAT " next:%u]",
now_s,
priv->last_scan / NM_UTILS_MSEC_PER_SEC,
_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u.%03u, last:%s, next:%u]",
(guint) (now_msec / NM_UTILS_MSEC_PER_SEC),
(guint) (now_msec % NM_UTILS_MSEC_PER_SEC),
priv->last_scan_msec > 0
? nm_sprintf_buf (str_buf,
"%u.%03u",
(guint) (priv->last_scan_msec / NM_UTILS_MSEC_PER_SEC),
(guint) (priv->last_scan_msec % NM_UTILS_MSEC_PER_SEC))
: "-1",
priv->scheduled_scan_time);
c_list_for_each_entry (ap, &priv->aps_lst_head, aps_lst)
_ap_dump (self, LOGL_DEBUG, ap, "dump", now_s);
_ap_dump (self, LOGL_DEBUG, ap, "dump", now_msec);
}
return G_SOURCE_REMOVE;
}
@@ -2091,7 +2158,7 @@ supplicant_iface_state (NMDeviceWifi *self,
nm_device_queue_recheck_available (NM_DEVICE (device),
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
priv->scan_interval = SCAN_INTERVAL_MIN;
priv->scan_interval_sec = SCAN_INTERVAL_SEC_MIN;
}
/* In these states we know the supplicant is actually talking to something */
@@ -2203,19 +2270,6 @@ supplicant_iface_assoc_cb (NMSupplicantInterface *iface,
}
}
static void
supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self)
{
_notify_scanning (self);
/* Run a quick update of current AP when coming out of a scan */
if ( !NM_DEVICE_WIFI_GET_PRIVATE (self)->is_scanning
&& nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED)
periodic_update (self);
}
static void
supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
GParamSpec *pspec,
@@ -2874,8 +2928,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
supplicant_connection_timeout_cb,
self);
if (!priv->periodic_source_id)
priv->periodic_source_id = g_timeout_add_seconds (6, periodic_update_cb, self);
if (!priv->periodic_update_id)
priv->periodic_update_id = g_timeout_add_seconds (6, periodic_update_cb, self);
/* We'll get stage3 started when the supplicant connects */
return NM_ACT_STAGE_RETURN_POSTPONE;
@@ -3050,7 +3104,7 @@ activation_success_handler (NMDevice *device)
update_seen_bssids_cache (self, priv->current_ap);
/* Reset scan interval to something reasonable */
priv->scan_interval = SCAN_INTERVAL_MIN + (SCAN_INTERVAL_STEP * 2);
priv->scan_interval_sec = SCAN_INTERVAL_SEC_MIN + (SCAN_INTERVAL_SEC_STEP * 2);
}
static void
@@ -3072,7 +3126,7 @@ device_state_changed (NMDevice *device,
*/
supplicant_interface_release (self);
nm_clear_g_source (&priv->periodic_source_id);
nm_clear_g_source (&priv->periodic_update_id);
cleanup_association_attempt (self, TRUE);
cleanup_supplicant_failures (self);
@@ -3111,7 +3165,7 @@ device_state_changed (NMDevice *device,
break;
case NM_DEVICE_STATE_DISCONNECTED:
/* Kick off a scan to get latest results */
priv->scan_interval = SCAN_INTERVAL_MIN;
priv->scan_interval_sec = SCAN_INTERVAL_SEC_MIN;
request_wireless_scan (self, FALSE, FALSE, NULL);
break;
default:
@@ -3266,13 +3320,13 @@ get_property (GObject *object, guint prop_id,
nm_dbus_utils_g_value_set_object_path (value, priv->current_ap);
break;
case PROP_SCANNING:
g_value_set_boolean (value, priv->is_scanning);
g_value_set_boolean (value, nm_device_wifi_get_scanning (self));
break;
case PROP_LAST_SCAN:
g_value_set_int64 (value,
priv->last_scan > 0
? nm_utils_monotonic_timestamp_as_boottime (priv->last_scan, NM_UTILS_NSEC_PER_MSEC)
: (gint64) -1);
priv->last_scan_msec > 0
? nm_utils_monotonic_timestamp_as_boottime (priv->last_scan_msec, NM_UTILS_NSEC_PER_MSEC)
: (gint64) -1);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -3306,6 +3360,7 @@ nm_device_wifi_init (NMDeviceWifi *self)
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
c_list_init (&priv->aps_lst_head);
c_list_init (&priv->scanning_prohibited_lst_head);
priv->aps_idx_by_supplicant_path = g_hash_table_new (nm_direct_hash, NULL);
priv->hidden_probe_scan_warn = TRUE;
@@ -3347,7 +3402,9 @@ dispose (GObject *object)
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
nm_clear_g_source (&priv->periodic_source_id);
nm_assert (c_list_is_empty (&priv->scanning_prohibited_lst_head));
nm_clear_g_source (&priv->periodic_update_id);
wifi_secrets_cancel (self);
@@ -3425,8 +3482,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
device_class->state_changed = device_state_changed;
klass->scanning_prohibited = scanning_prohibited;
obj_properties[PROP_MODE] =
g_param_spec_uint (NM_DEVICE_WIFI_MODE, "", "",
NM_802_11_MODE_UNKNOWN,
@@ -3473,14 +3528,6 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[SCANNING_PROHIBITED] =
g_signal_new (NM_DEVICE_WIFI_SCANNING_PROHIBITED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (NMDeviceWifiClass, scanning_prohibited),
NULL, NULL, NULL,
G_TYPE_BOOLEAN, 1, G_TYPE_BOOLEAN);
signals[P2P_DEVICE_CREATED] =
g_signal_new (NM_DEVICE_WIFI_P2P_DEVICE_CREATED,
G_OBJECT_CLASS_TYPE (object_class),

View File

@@ -24,7 +24,6 @@
#define NM_DEVICE_WIFI_SCANNING "scanning"
#define NM_DEVICE_WIFI_LAST_SCAN "last-scan"
#define NM_DEVICE_WIFI_SCANNING_PROHIBITED "scanning-prohibited"
#define NM_DEVICE_WIFI_P2P_DEVICE_CREATED "p2p-device-created"
typedef struct _NMDeviceWifi NMDeviceWifi;
@@ -42,4 +41,10 @@ void _nm_device_wifi_request_scan (NMDeviceWifi *self,
GPtrArray *nmtst_ssids_options_to_ptrarray (GVariant *value, GError **error);
gboolean nm_device_wifi_get_scanning (NMDeviceWifi *self);
void nm_device_wifi_scanning_prohibited_track (NMDeviceWifi *self,
gpointer tag,
gboolean temporarily_prohibited);
#endif /* __NETWORKMANAGER_DEVICE_WIFI_H__ */

View File

@@ -503,13 +503,14 @@ const char *
nm_wifi_ap_to_string (const NMWifiAP *self,
char *str_buf,
gulong buf_len,
gint32 now_s)
gint64 now_msec)
{
const NMWifiAPPrivate *priv;
const char *supplicant_id = "-";
const char *export_path;
guint32 chan;
gs_free char *ssid_to_free = NULL;
char str_buf_ts[100];
g_return_val_if_fail (NM_IS_WIFI_AP (self), NULL);
@@ -525,8 +526,10 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
else
export_path = "/";
nm_utils_get_monotonic_timestamp_msec_cached (&now_msec);
g_snprintf (str_buf, buf_len,
"%17s %-35s [ %c %3u %3u%% %c%c W:%04X R:%04X ] %3us sup:%s [nm:%s]",
"%17s %-35s [ %c %3u %3u%% %c%c W:%04X R:%04X ] %s sup:%s [nm:%s]",
priv->address ?: "(none)",
(ssid_to_free = _nm_utils_ssid_to_string (priv->ssid)),
(priv->mode == NM_802_11_MODE_ADHOC
@@ -545,8 +548,11 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
priv->wpa_flags & 0xFFFF,
priv->rsn_flags & 0xFFFF,
priv->last_seen_msec != G_MININT64
? (int) ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_sec ()) - (priv->last_seen_msec / 1000))
: -1,
? nm_sprintf_buf (str_buf_ts,
"%3u.%03us",
(guint) ((now_msec - priv->last_seen_msec) / 1000),
(guint) ((now_msec - priv->last_seen_msec) % 1000))
: " ",
supplicant_id,
export_path);
return str_buf;

View File

@@ -94,7 +94,7 @@ gboolean nm_wifi_ap_get_metered (const NMWifiAP *self);
const char *nm_wifi_ap_to_string (const NMWifiAP *self,
char *str_buf,
gulong buf_len,
gint32 now_s);
gint64 now_msec);
const char **nm_wifi_aps_get_paths (const CList *aps_lst_head,
gboolean include_without_ssid);

View File

@@ -59,7 +59,6 @@ enum {
STATE, /* change in the interface's state */
BSS_CHANGED, /* a new BSS appeared, was updated, or was removed. */
PEER_CHANGED, /* a new Peer appeared, was updated, or was removed */
SCAN_DONE, /* wifi scan is complete */
WPS_CREDENTIALS, /* WPS credentials received */
GROUP_STARTED, /* a new Group (interface) was created */
GROUP_FINISHED, /* a Group (interface) has been finished */
@@ -141,11 +140,16 @@ typedef struct _NMSupplicantInterfacePrivate {
NMSupplicantInterfaceState state;
NMSupplicantInterfaceState supp_state;
bool scanning:1;
bool scanning_property:1;
bool scanning_cached:1;
bool p2p_capable:1;
bool p2p_capable_property:1;
bool p2p_capable_cached:1;
bool p2p_group_is_owner:1;
bool p2p_group_owner_property:1;
bool p2p_group_owner_cached:1;
bool p2p_group_joined_cached:1;
bool is_ready_main:1;
bool is_ready_p2p_device:1;
@@ -433,11 +437,79 @@ _remove_network (NMSupplicantInterface *self)
/*****************************************************************************/
static gboolean
_prop_p2p_available_get (NMSupplicantInterfacePrivate *priv)
static void
_notify_maybe_scanning (NMSupplicantInterface *self)
{
return priv->is_ready_p2p_device
&& priv->p2p_capable;
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean scanning;
scanning = nm_supplicant_interface_state_is_operational (priv->state)
&& ( priv->scanning_property
|| priv->supp_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING);
if (priv->scanning_cached == scanning)
return;
if ( !scanning
&& !c_list_is_empty (&priv->bss_initializing_lst_head)) {
/* we would change state to indicate we no longer scan. However,
* we still have BSS instances to be initialized. Delay the
* state change further. */
return;
}
_LOGT ("scanning: %s", scanning ? "yes" : "no");
if (!scanning)
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
else {
/* while we are scanning, we set the timestamp to -1. */
priv->last_scan_msec = -1;
}
priv->scanning_cached = scanning;
_notify (self, PROP_SCANNING);
}
static void
_notify_maybe_p2p_available (NMSupplicantInterface *self)
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean value;
value = priv->is_ready_p2p_device
&& priv->p2p_capable_property;
if (priv->p2p_capable_cached == value)
return;
priv->p2p_capable_cached = value;
_notify (self, PROP_P2P_AVAILABLE);
}
static void
_notify_maybe_p2p_group (NMSupplicantInterface *self)
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean value_joined;
gboolean value_owner;
gboolean joined_changed;
gboolean owner_changed;
value_joined = priv->p2p_group_path
&& !priv->p2p_group_properties_cancellable;
value_owner = value_joined
&& priv->p2p_group_owner_property;
if ((joined_changed = (priv->p2p_group_joined_cached != value_joined)))
priv->p2p_group_joined_cached = value_joined;
if ((owner_changed = (priv->p2p_group_owner_cached != value_owner)))
priv->p2p_group_owner_cached = value_owner;
if (joined_changed)
_notify (self, PROP_P2P_GROUP_JOINED);
if (owner_changed)
_notify (self, PROP_P2P_GROUP_OWNER);
}
/*****************************************************************************/
@@ -457,6 +529,9 @@ _bss_info_changed_emit (NMSupplicantInterface *self,
NMSupplicantBssInfo *bss_info,
gboolean is_present)
{
_LOGT ("BSS %s %s",
bss_info->bss_path->str,
is_present ? "updated" : "deleted");
g_signal_emit (self,
signals[BSS_CHANGED],
0,
@@ -687,6 +762,8 @@ _bss_info_get_all_cb (GVariant *result,
_bss_info_properties_changed (self, bss_info, properties, TRUE);
_starting_check_ready (self);
_notify_maybe_scanning (self);
}
static void
@@ -1026,6 +1103,8 @@ set_state_down (NMSupplicantInterface *self,
_remove_network (self);
nm_clear_pointer (&priv->current_bss, nm_ref_string_unref);
_notify_maybe_scanning (self);
}
static void
@@ -1036,7 +1115,7 @@ set_state (NMSupplicantInterface *self, NMSupplicantInterfaceState new_state)
nm_assert (new_state > NM_SUPPLICANT_INTERFACE_STATE_STARTING);
nm_assert (new_state < NM_SUPPLICANT_INTERFACE_STATE_DOWN);
nm_assert (NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (new_state));
nm_assert (nm_supplicant_interface_state_is_operational (new_state));
nm_assert (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_STARTING);
nm_assert (priv->state < NM_SUPPLICANT_INTERFACE_STATE_DOWN);
@@ -1048,9 +1127,6 @@ set_state (NMSupplicantInterface *self, NMSupplicantInterfaceState new_state)
nm_supplicant_interface_state_to_string (new_state),
nm_supplicant_interface_state_to_string (priv->state));
if (old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
priv->state = new_state;
_emit_signal_state (self,
@@ -1069,35 +1145,20 @@ nm_supplicant_interface_get_current_bss (NMSupplicantInterface *self)
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->current_bss;
}
static inline gboolean
_prop_scanning_get (NMSupplicantInterfacePrivate *priv)
{
return ( priv->scanning
|| priv->supp_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
&& NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (priv->state);
}
gboolean
nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
{
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
return _prop_scanning_get (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self));
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->scanning_cached;
}
gint64
nm_supplicant_interface_get_last_scan (NMSupplicantInterface *self)
{
NMSupplicantInterfacePrivate *priv;
g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), FALSE);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
/* returns -1 if we are currently scanning. */
return _prop_scanning_get (priv)
? -1
: priv->last_scan_msec;
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan_msec;
}
#define MATCH_PROPERTY(p, n, v, t) (!strcmp (p, n) && g_variant_is_of_type (v, t))
@@ -1129,7 +1190,7 @@ parse_capabilities (NMSupplicantInterface *self, GVariant *capabilities)
/* Setting p2p_capable might toggle _prop_p2p_available_get(). However,
* we don't need to check for a property changed notification, because
* the caller did g_object_freeze_notify() and will perform the check. */
priv->p2p_capable = g_strv_contains (array, "p2p");
priv->p2p_capable_property = g_strv_contains (array, "p2p");
g_free (array);
}
@@ -1176,7 +1237,7 @@ _starting_check_ready (NMSupplicantInterface *self)
nm_assert (priv->state == NM_SUPPLICANT_INTERFACE_STATE_STARTING);
if (!NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (priv->supp_state)) {
if (!nm_supplicant_interface_state_is_operational (priv->supp_state)) {
_LOGW ("Supplicant state is unknown during initialization. Destroy the interface");
set_state_down (self, TRUE, "failure to get valid interface state");
return;
@@ -1264,37 +1325,19 @@ nm_supplicant_interface_get_auth_state (NMSupplicantInterface *self)
/*****************************************************************************/
static gboolean
_prop_p2p_group_joined_get (NMSupplicantInterfacePrivate *priv)
{
return priv->p2p_group_path
&& !priv->p2p_group_properties_cancellable;
}
static gboolean
_prop_p2p_group_is_owner_get (NMSupplicantInterfacePrivate *priv)
{
return _prop_p2p_group_joined_get (priv)
&& priv->p2p_group_is_owner;
}
static void
_p2p_group_properties_changed (NMSupplicantInterface *self,
GVariant *properties)
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean old_val_p2p_group_is_owner;
const char *s;
old_val_p2p_group_is_owner = _prop_p2p_group_is_owner_get (priv);
if (!properties)
priv->p2p_group_is_owner = FALSE;
priv->p2p_group_owner_property = FALSE;
else if (g_variant_lookup (properties, "Role", "&s", &s))
priv->p2p_group_is_owner = nm_streq (s, "GO");
priv->p2p_group_owner_property = nm_streq (s, "GO");
if (old_val_p2p_group_is_owner != _prop_p2p_group_is_owner_get (priv))
_notify (self, PROP_P2P_GROUP_OWNER);
_notify_maybe_p2p_group (self);
}
static void
@@ -1331,8 +1374,6 @@ _p2p_group_properties_get_all_cb (GVariant *result,
{
NMSupplicantInterface *self;
NMSupplicantInterfacePrivate *priv;
gboolean old_val_p2p_group_joined;
gboolean old_val_p2p_group_is_owner;
gs_unref_variant GVariant *properties = NULL;
if (nm_utils_error_is_cancelled (error))
@@ -1343,9 +1384,6 @@ _p2p_group_properties_get_all_cb (GVariant *result,
g_object_freeze_notify (G_OBJECT (self));
old_val_p2p_group_joined = _prop_p2p_group_joined_get (priv);
old_val_p2p_group_is_owner = _prop_p2p_group_is_owner_get (priv);
nm_clear_g_cancellable (&priv->p2p_group_properties_cancellable);
if (result)
@@ -1355,10 +1393,7 @@ _p2p_group_properties_get_all_cb (GVariant *result,
_starting_check_ready (self);
if (old_val_p2p_group_joined != _prop_p2p_group_joined_get (priv))
_notify (self, PROP_P2P_GROUP_JOINED);
if (old_val_p2p_group_is_owner != _prop_p2p_group_is_owner_get (priv))
_notify (self, PROP_P2P_GROUP_OWNER);
_notify_maybe_p2p_group (self);
g_object_thaw_notify (G_OBJECT (self));
}
@@ -1369,17 +1404,12 @@ _p2p_group_set_path (NMSupplicantInterface *self,
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
nm_auto_ref_string NMRefString *group_path = NULL;
gboolean old_val_p2p_group_joined;
gboolean old_val_p2p_group_is_owner;
group_path = nm_ref_string_new (nm_dbus_path_not_empty (path));
if (priv->p2p_group_path == group_path)
return;
old_val_p2p_group_joined = _prop_p2p_group_joined_get (priv);
old_val_p2p_group_is_owner = _prop_p2p_group_is_owner_get (priv);
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
&priv->p2p_group_properties_changed_id);
nm_clear_g_cancellable (&priv->p2p_group_properties_cancellable);
@@ -1407,10 +1437,7 @@ _p2p_group_set_path (NMSupplicantInterface *self,
}
_notify (self, PROP_P2P_GROUP_PATH);
if (old_val_p2p_group_joined != _prop_p2p_group_joined_get (priv))
_notify (self, PROP_P2P_GROUP_JOINED);
if (old_val_p2p_group_is_owner != _prop_p2p_group_is_owner_get (priv))
_notify (self, PROP_P2P_GROUP_OWNER);
_notify_maybe_p2p_group (self);
nm_assert_starting_has_pending_count (priv->starting_pending_count);
}
@@ -1762,13 +1789,8 @@ _properties_changed_main (NMSupplicantInterface *self,
g_variant_unref (v_v);
}
if (nm_g_variant_lookup (properties, "Scanning", "b", &v_b)) {
if (priv->scanning != (!!v_b)) {
if (priv->scanning)
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
priv->scanning = v_b;
}
}
if (nm_g_variant_lookup (properties, "Scanning", "b", &v_b))
priv->scanning_property = v_b;
if (nm_g_variant_lookup (properties, "Ifname", "&s", &v_s)) {
if (nm_utils_strdup_reset (&priv->ifname, v_s))
@@ -1855,6 +1877,8 @@ _properties_changed_main (NMSupplicantInterface *self,
if (do_set_state)
set_state (self, priv->supp_state);
_notify_maybe_scanning (self);
}
static void
@@ -2318,12 +2342,13 @@ scan_request_cb (GObject *source, GAsyncResult *result, gpointer user_data)
self = NM_SUPPLICANT_INTERFACE (user_data);
if (error) {
if (_nm_dbus_error_has_name (error, "fi.w1.wpa_supplicant1.Interface.ScanError"))
_LOGD ("could not get scan request result: %s", error->message);
_LOGD ("request-scan: could not get scan request result: %s", error->message);
else {
g_dbus_error_strip_remote_error (error);
_LOGW ("could not get scan request result: %s", error->message);
_LOGW ("request-scan: could not get scan request result: %s", error->message);
}
}
} else
_LOGT ("request-scan: request scanning success");
}
void
@@ -2339,7 +2364,8 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
/* Scan parameters */
_LOGT ("request-scan: request scanning (%u ssids)...", ssids_len);
g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
g_variant_builder_add (&builder, "{sv}", "Type", g_variant_new_string ("active"));
g_variant_builder_add (&builder, "{sv}", "AllowRoam", g_variant_new_boolean (FALSE));
@@ -2518,8 +2544,6 @@ _properties_changed (NMSupplicantInterface *self,
{
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
gboolean is_main;
gboolean old_val_scanning;
gboolean old_val_p2p_available;
nm_assert (!properties || g_variant_is_of_type (properties, G_VARIANT_TYPE ("a{sv}")));
@@ -2540,9 +2564,6 @@ _properties_changed (NMSupplicantInterface *self,
priv->starting_pending_count++;
old_val_scanning = _prop_scanning_get (priv);
old_val_p2p_available = _prop_p2p_available_get (priv);
if (is_main) {
priv->is_ready_main = TRUE;
_properties_changed_main (self, properties);
@@ -2554,10 +2575,8 @@ _properties_changed (NMSupplicantInterface *self,
priv->starting_pending_count--;
_starting_check_ready (self);
if (old_val_scanning != _prop_scanning_get (priv))
_notify (self, PROP_SCANNING);
if (old_val_p2p_available != _prop_p2p_available_get (priv))
_notify (self, PROP_P2P_AVAILABLE);
_notify_maybe_scanning (self);
_notify_maybe_p2p_available (self);
g_object_thaw_notify (G_OBJECT (self));
}
@@ -2707,16 +2726,6 @@ _signal_handle (NMSupplicantInterface *self,
if (!priv->is_ready_main)
return;
if (nm_streq (signal_name, "ScanDone")) {
priv->last_scan_msec = nm_utils_get_monotonic_timestamp_msec ();
_LOGT ("ScanDone signal received");
if (priv->state > NM_SUPPLICANT_INTERFACE_STATE_STARTING) {
nm_assert (priv->state < NM_SUPPLICANT_INTERFACE_STATE_DOWN);
g_signal_emit (self, signals[SCAN_DONE], 0);
}
return;
}
if (nm_streq (signal_name, "BSSAdded")) {
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oa{sv})")))
return;
@@ -2864,11 +2873,11 @@ _signal_cb (GDBusConnection *connection,
NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
priv->starting_pending_count++;
_signal_handle (self, signal_interface_name, signal_name, parameters);
priv->starting_pending_count--;
_starting_check_ready (self);
_notify_maybe_scanning (self);
}
/*****************************************************************************/
@@ -2876,13 +2885,13 @@ _signal_cb (GDBusConnection *connection,
gboolean
nm_supplicant_interface_get_p2p_available (NMSupplicantInterface *self)
{
return _prop_p2p_available_get (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self));
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->p2p_capable_cached;
}
gboolean
nm_supplicant_interface_get_p2p_group_joined (NMSupplicantInterface *self)
{
return _prop_p2p_group_joined_get (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self));
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->p2p_group_joined_cached;
}
const char*
@@ -2894,7 +2903,7 @@ nm_supplicant_interface_get_p2p_group_path (NMSupplicantInterface *self)
gboolean
nm_supplicant_interface_get_p2p_group_owner (NMSupplicantInterface *self)
{
return _prop_p2p_group_is_owner_get (NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self));
return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->p2p_group_owner_cached;
}
/*****************************************************************************/
@@ -2993,6 +3002,7 @@ nm_supplicant_interface_init (NMSupplicantInterface * self)
priv->state = NM_SUPPLICANT_INTERFACE_STATE_STARTING;
priv->supp_state = NM_SUPPLICANT_INTERFACE_STATE_INVALID;
priv->last_scan_msec = -1;
c_list_init (&self->supp_lst);
@@ -3288,14 +3298,6 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN);
signals[SCAN_DONE] =
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, 0);
signals[WPS_CREDENTIALS] =
g_signal_new (NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS,
G_OBJECT_CLASS_TYPE (object_class),

View File

@@ -35,12 +35,19 @@ typedef enum {
} NMSupplicantInterfaceState;
static inline gboolean
NM_SUPPLICANT_INTERFACE_STATE_IS_OPERATIONAL (NMSupplicantInterfaceState state)
nm_supplicant_interface_state_is_operational (NMSupplicantInterfaceState state)
{
return state > NM_SUPPLICANT_INTERFACE_STATE_STARTING
&& state < NM_SUPPLICANT_INTERFACE_STATE_DOWN;
}
static inline gboolean
nm_supplicant_interface_state_is_associated (NMSupplicantInterfaceState state)
{
return state >= NM_SUPPLICANT_INTERFACE_STATE_AUTHENTICATING
&& state <= NM_SUPPLICANT_INTERFACE_STATE_COMPLETED;
}
typedef enum {
NM_SUPPLICANT_AUTH_STATE_UNKNOWN,
NM_SUPPLICANT_AUTH_STATE_STARTED,
@@ -71,7 +78,6 @@ typedef enum {
#define NM_SUPPLICANT_INTERFACE_STATE "state"
#define NM_SUPPLICANT_INTERFACE_BSS_CHANGED "bss-changed"
#define NM_SUPPLICANT_INTERFACE_PEER_CHANGED "peer-changed"
#define NM_SUPPLICANT_INTERFACE_SCAN_DONE "scan-done"
#define NM_SUPPLICANT_INTERFACE_WPS_CREDENTIALS "wps-credentials"
#define NM_SUPPLICANT_INTERFACE_GROUP_STARTED "group-started"
#define NM_SUPPLICANT_INTERFACE_GROUP_FINISHED "group-finished"