all: merge branch 'th/device-pending-action-bgo777831' (part 2, wifi-scan)

Delay startup complete until Wi-Fi device completed scan and
autoactivation.

https://bugzilla.gnome.org/show_bug.cgi?id=777831
This commit is contained in:
Thomas Haller 2017-02-10 14:42:39 +01:00
commit f3504c9bc2
10 changed files with 420 additions and 371 deletions

View file

@ -91,10 +91,6 @@ gboolean nm_device_dhcp6_renew (NMDevice *device, gboolean release);
void nm_device_recheck_available_connections (NMDevice *device);
void nm_device_queued_state_clear (NMDevice *device);
NMDeviceState nm_device_queued_state_peek (NMDevice *device);
gboolean nm_device_get_enslaved (NMDevice *device);
NMDevice *nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex);

View file

@ -73,9 +73,64 @@ _LOG_DECLARE_SELF (NMDevice);
#include "introspection/org.freedesktop.NetworkManager.Device.h"
#include "introspection/org.freedesktop.NetworkManager.Device.Statistics.h"
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
/*****************************************************************************/
#define NM_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDevice, NM_IS_DEVICE)
#define DHCP_RESTART_TIMEOUT 120
#define DHCP_NUM_TRIES_MAX 3
#define DEFAULT_AUTOCONNECT TRUE
/*****************************************************************************/
typedef void (*ActivationHandleFunc) (NMDevice *self);
typedef struct {
ActivationHandleFunc func;
guint id;
} ActivationHandleData;
typedef enum {
CLEANUP_TYPE_KEEP,
CLEANUP_TYPE_REMOVED,
CLEANUP_TYPE_DECONFIGURE,
} CleanupType;
typedef enum {
IP_NONE = 0,
IP_WAIT,
IP_CONF,
IP_DONE,
IP_FAIL
} IpState;
typedef struct {
NMDevice *slave;
gulong watch_id;
bool slave_is_enslaved;
bool configure;
} SlaveInfo;
typedef struct {
NMDevice *device;
guint idle_add_id;
int ifindex;
} DeleteOnDeactivateData;
typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean);
typedef struct {
ArpingCallback callback;
NMDevice *device;
NMIP4Config **configs;
} ArpingData;
typedef enum {
HW_ADDR_TYPE_UNSET = 0,
HW_ADDR_TYPE_PERMANENT,
HW_ADDR_TYPE_EXPLICIT,
HW_ADDR_TYPE_GENERATED,
} HwAddrType;
/*****************************************************************************/
enum {
STATE_CHANGED,
@ -136,82 +191,6 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDevice,
PROP_RX_BYTES,
);
#define DEFAULT_AUTOCONNECT TRUE
/*****************************************************************************/
#define PENDING_ACTION_DHCP4 "dhcp4"
#define PENDING_ACTION_DHCP6 "dhcp6"
#define PENDING_ACTION_AUTOCONF6 "autoconf6"
#define DHCP_RESTART_TIMEOUT 120
#define DHCP_NUM_TRIES_MAX 3
typedef void (*ActivationHandleFunc) (NMDevice *self);
typedef struct {
ActivationHandleFunc func;
guint id;
} ActivationHandleData;
typedef enum {
CLEANUP_TYPE_KEEP,
CLEANUP_TYPE_REMOVED,
CLEANUP_TYPE_DECONFIGURE,
} CleanupType;
typedef enum {
IP_NONE = 0,
IP_WAIT,
IP_CONF,
IP_DONE,
IP_FAIL
} IpState;
typedef struct {
NMDeviceState state;
NMDeviceStateReason reason;
guint id;
} QueuedState;
typedef struct {
NMDevice *slave;
gulong watch_id;
bool slave_is_enslaved;
bool configure;
} SlaveInfo;
typedef struct {
NMLogDomain log_domain;
guint timeout;
guint watch;
GPid pid;
const char *binary;
const char *address;
guint deadline;
} PingInfo;
typedef struct {
NMDevice *device;
guint idle_add_id;
int ifindex;
} DeleteOnDeactivateData;
typedef void (*ArpingCallback) (NMDevice *, NMIP4Config **, gboolean);
typedef struct {
ArpingCallback callback;
NMDevice *device;
NMIP4Config **configs;
} ArpingData;
typedef enum {
HW_ADDR_TYPE_UNSET = 0,
HW_ADDR_TYPE_PERMANENT,
HW_ADDR_TYPE_EXPLICIT,
HW_ADDR_TYPE_GENERATED,
} HwAddrType;
typedef struct _NMDevicePrivate {
bool in_state_changed;
@ -220,7 +199,13 @@ typedef struct _NMDevicePrivate {
NMDeviceState state;
NMDeviceStateReason state_reason;
QueuedState queued_state;
struct {
guint id;
/* The @state/@reason is only valid, when @id is set. */
NMDeviceState state;
NMDeviceStateReason reason;
} queued_state;
guint queued_ip4_config_id;
guint queued_ip6_config_id;
GSList *pending_actions;
@ -238,7 +223,8 @@ typedef struct _NMDevicePrivate {
const guint8 hw_addr_len; /* read-only */
guint8 hw_addr_len_;
};
guint8 /*HwAddrType*/ hw_addr_type;
HwAddrType hw_addr_type:5;
bool real:1;
@ -358,7 +344,15 @@ typedef struct _NMDevicePrivate {
guint num_tries_left;
} dhcp4;
PingInfo gw_ping;
struct {
NMLogDomain log_domain;
guint timeout;
guint watch;
GPid pid;
const char *binary;
const char *address;
guint deadline;
} gw_ping;
/* dnsmasq stuff for shared connections */
NMDnsMasqManager *dnsmasq_manager;
@ -451,6 +445,12 @@ typedef struct _NMDevicePrivate {
} NMDevicePrivate;
G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT)
#define NM_DEVICE_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDevice, NM_IS_DEVICE)
/*****************************************************************************/
static void nm_device_set_proxy_config (NMDevice *self, GHashTable *options);
static gboolean nm_device_set_ip4_config (NMDevice *self,
@ -489,7 +489,7 @@ static void _set_state_full (NMDevice *self,
NMDeviceState state,
NMDeviceStateReason reason,
gboolean quitting);
static void queued_state_clear (NMDevice *device);
static gboolean queued_ip4_config_change (gpointer user_data);
static gboolean queued_ip6_config_change (gpointer user_data);
static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data);
@ -504,36 +504,27 @@ static void _cancel_activation (NMDevice *self);
/*****************************************************************************/
#define QUEUED_PREFIX "queued state change to "
static const char *state_table[] = {
[NM_DEVICE_STATE_UNKNOWN] = QUEUED_PREFIX "unknown",
[NM_DEVICE_STATE_UNMANAGED] = QUEUED_PREFIX "unmanaged",
[NM_DEVICE_STATE_UNAVAILABLE] = QUEUED_PREFIX "unavailable",
[NM_DEVICE_STATE_DISCONNECTED] = QUEUED_PREFIX "disconnected",
[NM_DEVICE_STATE_PREPARE] = QUEUED_PREFIX "prepare",
[NM_DEVICE_STATE_CONFIG] = QUEUED_PREFIX "config",
[NM_DEVICE_STATE_NEED_AUTH] = QUEUED_PREFIX "need-auth",
[NM_DEVICE_STATE_IP_CONFIG] = QUEUED_PREFIX "ip-config",
[NM_DEVICE_STATE_IP_CHECK] = QUEUED_PREFIX "ip-check",
[NM_DEVICE_STATE_SECONDARIES] = QUEUED_PREFIX "secondaries",
[NM_DEVICE_STATE_ACTIVATED] = QUEUED_PREFIX "activated",
[NM_DEVICE_STATE_DEACTIVATING] = QUEUED_PREFIX "deactivating",
[NM_DEVICE_STATE_FAILED] = QUEUED_PREFIX "failed",
};
static const char *
queued_state_to_string (NMDeviceState state)
{
if ((gsize) state < G_N_ELEMENTS (state_table))
return state_table[state];
return state_table[NM_DEVICE_STATE_UNKNOWN];
}
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (queued_state_to_string, NMDeviceState,
NM_UTILS_LOOKUP_DEFAULT ( NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "???"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNKNOWN, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unknown"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNMANAGED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unmanaged"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_UNAVAILABLE, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "unavailable"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DISCONNECTED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "disconnected"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_PREPARE, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "prepare"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_CONFIG, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "config"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_NEED_AUTH, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "need-auth"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CONFIG, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-config"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_IP_CHECK, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "ip-check"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_SECONDARIES, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "secondaries"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_ACTIVATED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "activated"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_DEACTIVATING, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "deactivating"),
NM_UTILS_LOOKUP_STR_ITEM (NM_DEVICE_STATE_FAILED, NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "failed"),
);
static const char *
state_to_string (NMDeviceState state)
{
return queued_state_to_string (state) + strlen (QUEUED_PREFIX);
return queued_state_to_string (state) + NM_STRLEN (NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE);
}
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason,
@ -1932,8 +1923,9 @@ carrier_changed (NMDevice *self, gboolean carrier)
}
} else {
if (priv->state == NM_DEVICE_STATE_UNAVAILABLE) {
if (nm_device_queued_state_peek (self) >= NM_DEVICE_STATE_DISCONNECTED)
nm_device_queued_state_clear (self);
if ( priv->queued_state.id
&& priv->queued_state.state >= NM_DEVICE_STATE_DISCONNECTED)
queued_state_clear (self);
} else {
nm_device_queue_state (self, NM_DEVICE_STATE_UNAVAILABLE,
NM_DEVICE_STATE_REASON_CARRIER);
@ -1989,7 +1981,7 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier)
klass->carrier_changed (self, TRUE);
if (nm_clear_g_source (&priv->carrier_wait_id)) {
nm_device_remove_pending_action (self, "carrier wait", TRUE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE);
_carrier_wait_check_queued_act_request (self);
}
} else if ( state <= NM_DEVICE_STATE_DISCONNECTED
@ -3921,6 +3913,9 @@ recheck_available (gpointer user_data)
priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE;
}
if (priv->recheck_available.call_id == 0)
nm_device_remove_pending_action (self, NM_PENDING_ACTION_RECHECK_AVAILABLE, TRUE);
return G_SOURCE_REMOVE;
}
@ -3933,8 +3928,12 @@ nm_device_queue_recheck_available (NMDevice *self,
priv->recheck_available.available_reason = available_reason;
priv->recheck_available.unavailable_reason = unavailable_reason;
if (!priv->recheck_available.call_id)
if (!priv->recheck_available.call_id) {
priv->recheck_available.call_id = g_idle_add (recheck_available, self);
nm_device_add_pending_action (self, NM_PENDING_ACTION_RECHECK_AVAILABLE,
FALSE /* cannot assert, because of how recheck_available() first clears
the call-id and postpones removing the pending-action. */);
}
}
void
@ -4971,7 +4970,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
/* Stop any ongoing DHCP transaction on this device */
nm_clear_g_signal_handler (priv->dhcp4.client, &priv->dhcp4.state_sigid);
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|| cleanup_type == CLEANUP_TYPE_REMOVED)
@ -5199,7 +5198,7 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config)
NULL,
NULL);
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
return TRUE;
}
@ -5424,7 +5423,7 @@ dhcp4_start (NMDevice *self,
G_CALLBACK (dhcp4_state_changed),
self);
nm_device_add_pending_action (self, PENDING_ACTION_DHCP4, TRUE);
nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP4, TRUE);
/* DHCP devices will be notified by the DHCP manager when stuff happens */
return NM_ACT_STAGE_RETURN_POSTPONE;
@ -5726,7 +5725,7 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release)
g_clear_object (&priv->dhcp6.client);
}
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
if (priv->dhcp6.config) {
nm_exported_object_clear_and_unexport (&priv->dhcp6.config);
@ -5970,7 +5969,7 @@ dhcp6_lease_change (NMDevice *self)
nm_device_get_applied_connection (self),
self, NULL, NULL, NULL);
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
return TRUE;
}
@ -6256,7 +6255,7 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason)
s_ip6 = nm_connection_get_setting_ip6_config (connection);
if (!nm_setting_ip_config_get_may_fail (s_ip6) ||
!strcmp (nm_setting_ip_config_get_method (s_ip6), NM_SETTING_IP6_CONFIG_METHOD_DHCP))
nm_device_add_pending_action (self, PENDING_ACTION_DHCP6, TRUE);
nm_device_add_pending_action (self, NM_PENDING_ACTION_DHCP6, TRUE);
if (wait_for_ll) {
NMActStageReturn ret;
@ -7031,7 +7030,7 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr)
}
if (!nm_setting_ip_config_get_may_fail (nm_connection_get_setting_ip6_config (connection)))
nm_device_add_pending_action (self, PENDING_ACTION_AUTOCONF6, TRUE);
nm_device_add_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, TRUE);
/* ensure link local is ready... */
ret = linklocal6_start (self);
@ -7053,7 +7052,7 @@ addrconf6_cleanup (NMDevice *self)
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_changed_id);
nm_clear_g_signal_handler (priv->ndisc, &priv->ndisc_timeout_id);
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE);
g_clear_object (&priv->ac_ip6_config);
g_clear_object (&priv->ndisc);
@ -7921,7 +7920,7 @@ activate_stage5_ip4_config_commit (NMDevice *self)
arp_announce (self);
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP4, FALSE);
/* Enter the IP_CHECK state if this is the first method to complete */
_set_ip_state (self, AF_INET, IP_DONE);
@ -8058,8 +8057,8 @@ activate_stage5_ip6_config_commit (NMDevice *self)
return;
}
}
nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE);
nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_DHCP6, FALSE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_AUTOCONF6, FALSE);
/* Start IPv6 forwarding if we need it */
method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG);
@ -9745,7 +9744,7 @@ carrier_wait_timeout (gpointer user_data)
NMDevice *self = NM_DEVICE (user_data);
NM_DEVICE_GET_PRIVATE (self)->carrier_wait_id = 0;
nm_device_remove_pending_action (self, "carrier wait", TRUE);
nm_device_remove_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE);
_carrier_wait_check_queued_act_request (self);
@ -9827,7 +9826,7 @@ nm_device_bring_up (NMDevice *self, gboolean block, gboolean *no_firmware)
*/
if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) {
if (!nm_clear_g_source (&priv->carrier_wait_id))
nm_device_add_pending_action (self, "carrier wait", TRUE);
nm_device_add_pending_action (self, NM_PENDING_ACTION_CARRIER_WAIT, TRUE);
priv->carrier_wait_id = g_timeout_add_seconds (5, carrier_wait_timeout, self);
}
@ -11241,7 +11240,9 @@ nm_device_supports_vlans (NMDevice *self)
/**
* nm_device_add_pending_action():
* @self: the #NMDevice to add the pending action to
* @action: a static string that identifies the action
* @action: a static string that identifies the action. The string instance must
* stay valid until the pending action is removed (that is, the string is
* not cloned, but ownership stays with the caller).
* @assert_not_yet_pending: if %TRUE, assert that the @action is currently not yet pending.
* Otherwise, ignore duplicate scheduling of the same action silently.
*
@ -11276,7 +11277,7 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser
count++;
}
priv->pending_actions = g_slist_append (priv->pending_actions, g_strdup (action));
priv->pending_actions = g_slist_prepend (priv->pending_actions, (char *) action);
count++;
_LOGD (LOGD_DEVICE, "add_pending_action (%d): '%s'", count, action);
@ -11290,7 +11291,7 @@ nm_device_add_pending_action (NMDevice *self, const char *action, gboolean asser
/**
* nm_device_remove_pending_action():
* @self: the #NMDevice to remove the pending action from
* @action: a static string that identifies the action
* @action: a string that identifies the action.
* @assert_is_pending: if %TRUE, assert that the @action is pending.
* If %FALSE, don't do anything if the current action is not pending and
* return %FALSE.
@ -11317,7 +11318,6 @@ nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean as
_LOGD (LOGD_DEVICE, "remove_pending_action (%d): '%s'",
count + g_slist_length (iter->next), /* length excluding 'iter' */
action);
g_free (iter->data);
priv->pending_actions = g_slist_delete_link (priv->pending_actions, iter);
if (priv->pending_actions == NULL)
_notify (self, PROP_HAS_PENDING_ACTION);
@ -11383,8 +11383,7 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type)
NULL);
}
/* Clear any queued transitions */
nm_device_queued_state_clear (self);
queued_state_clear (self);
_cleanup_ip4_pre (self, cleanup_type);
_cleanup_ip6_pre (self, cleanup_type);
@ -11889,8 +11888,7 @@ _set_state_full (NMDevice *self,
priv->state = state;
priv->state_reason = reason;
/* Clear any queued transitions */
nm_device_queued_state_clear (self);
queued_state_clear (self);
dispatcher_cleanup (self);
if (priv->deactivating_cancellable)
@ -12202,33 +12200,32 @@ nm_device_state_changed (NMDevice *self,
}
static gboolean
queued_set_state (gpointer user_data)
queued_state_set (gpointer user_data)
{
NMDevice *self = NM_DEVICE (user_data);
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
NMDeviceState new_state;
NMDeviceStateReason new_reason;
if (priv->queued_state.id) {
_LOGD (LOGD_DEVICE, "running queued state change to %s (id %d)",
state_to_string (priv->queued_state.state),
priv->queued_state.id);
nm_assert (priv->queued_state.id);
/* Clear queued state struct before triggering state change, since
* the state change may queue another state.
*/
priv->queued_state.id = 0;
new_state = priv->queued_state.state;
new_reason = priv->queued_state.reason;
nm_device_queued_state_clear (self);
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
state_to_string (priv->queued_state.state),
reason_to_string (priv->queued_state.reason),
priv->queued_state.id,
"change state");
nm_device_state_changed (self, new_state, new_reason);
nm_device_remove_pending_action (self, queued_state_to_string (new_state), TRUE);
} else {
g_warn_if_fail (priv->queued_state.state == NM_DEVICE_STATE_UNKNOWN);
g_warn_if_fail (priv->queued_state.reason == NM_DEVICE_STATE_REASON_NONE);
}
return FALSE;
/* Clear queued state struct before triggering state change, since
* the state change may queue another state.
*/
priv->queued_state.id = 0;
new_state = priv->queued_state.state;
new_reason = priv->queued_state.reason;
nm_device_state_changed (self, new_state, new_reason);
nm_device_remove_pending_action (self, queued_state_to_string (new_state), TRUE);
return G_SOURCE_REMOVE;
}
void
@ -12242,8 +12239,16 @@ nm_device_queue_state (NMDevice *self,
priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->queued_state.id && priv->queued_state.state == state)
if (priv->queued_state.id && priv->queued_state.state == state) {
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s%s%s%s",
state_to_string (priv->queued_state.state),
reason_to_string (priv->queued_state.reason),
priv->queued_state.id,
"ignore queuing same state change",
NM_PRINT_FMT_QUOTED (priv->queued_state.reason != reason,
" (reason differs: ", reason_to_string (reason), ")", ""));
return;
}
/* Add pending action for the new state before clearing the queued states, so
* that we don't accidently pop all pending states and reach 'startup complete' */
@ -12251,45 +12256,41 @@ nm_device_queue_state (NMDevice *self,
/* We should only ever have one delayed state transition at a time */
if (priv->queued_state.id) {
_LOGW (LOGD_DEVICE, "overwriting previously queued state change to %s (%s)",
_LOGW (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
state_to_string (priv->queued_state.state),
reason_to_string (priv->queued_state.reason));
nm_device_queued_state_clear (self);
reason_to_string (priv->queued_state.reason),
priv->queued_state.id,
"replace previously queued state change");
nm_clear_g_source (&priv->queued_state.id);
nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE);
}
priv->queued_state.state = state;
priv->queued_state.reason = reason;
priv->queued_state.id = g_idle_add (queued_set_state, self);
priv->queued_state.id = g_idle_add (queued_state_set, self);
_LOGD (LOGD_DEVICE, "queued state change to %s due to %s (id %d)",
state_to_string (state), reason_to_string (reason),
priv->queued_state.id);
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
state_to_string (state),
reason_to_string (reason),
priv->queued_state.id,
"queue state change");
}
NMDeviceState
nm_device_queued_state_peek (NMDevice *self)
{
NMDevicePrivate *priv;
g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_STATE_UNKNOWN);
priv = NM_DEVICE_GET_PRIVATE (self);
return priv->queued_state.id ? priv->queued_state.state : NM_DEVICE_STATE_UNKNOWN;
}
void
nm_device_queued_state_clear (NMDevice *self)
static void
queued_state_clear (NMDevice *self)
{
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self);
if (priv->queued_state.id) {
_LOGD (LOGD_DEVICE, "clearing queued state transition (id %d)",
priv->queued_state.id);
nm_clear_g_source (&priv->queued_state.id);
nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE);
}
memset (&priv->queued_state, 0, sizeof (priv->queued_state));
if (!priv->queued_state.id)
return;
_LOGD (LOGD_DEVICE, "queue-state[%s, reason:%s, id:%u]: %s",
state_to_string (priv->queued_state.state),
reason_to_string (priv->queued_state.reason),
priv->queued_state.id,
"clear queued state change");
nm_clear_g_source (&priv->queued_state.id);
nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE);
}
NMDeviceState
@ -12584,7 +12585,9 @@ nm_device_hw_addr_is_explict (NMDevice *self)
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
priv = NM_DEVICE_GET_PRIVATE (self);
return !NM_IN_SET (priv->hw_addr_type, HW_ADDR_TYPE_PERMANENT, HW_ADDR_TYPE_UNSET);
return !NM_IN_SET ((HwAddrType) priv->hw_addr_type,
HW_ADDR_TYPE_PERMANENT,
HW_ADDR_TYPE_UNSET);
}
static gboolean
@ -13143,7 +13146,7 @@ finalize (GObject *object)
g_free (priv->hw_addr);
g_free (priv->hw_addr_perm);
g_free (priv->hw_addr_initial);
g_slist_free_full (priv->pending_actions, g_free);
g_slist_free (priv->pending_actions);
g_slist_free_full (priv->dad6_failed_addrs, g_free);
g_clear_pointer (&priv->physical_port_id, g_free);
g_free (priv->udi);

View file

@ -30,6 +30,21 @@
#include "nm-rfkill-manager.h"
#include "NetworkManagerUtils.h"
#define NM_PENDING_ACTION_AUTOACTIVATE "autoactivate"
#define NM_PENDING_ACTION_DHCP4 "dhcp4"
#define NM_PENDING_ACTION_DHCP6 "dhcp6"
#define NM_PENDING_ACTION_AUTOCONF6 "autoconf6"
#define NM_PENDING_ACTION_RECHECK_AVAILABLE "recheck-available"
#define NM_PENDING_ACTION_CARRIER_WAIT "carrier-wait"
#define NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT "waiting-for-supplicant"
#define NM_PENDING_ACTION_WIFI_SCAN "wifi-scan"
#define NM_PENDING_ACTION_WAITING_FOR_COMPANION "waiting-for-companion"
#define NM_PENDING_ACTIONPREFIX_QUEUED_STATE_CHANGE "queued-state-change-"
#define NM_PENDING_ACTIONPREFIX_ACTIVATION "activation-"
/* Properties */
#define NM_DEVICE_UDI "udi"
#define NM_DEVICE_IFACE "interface"

View file

@ -377,7 +377,7 @@ device_added_cb (NMManager *manager, NMDevice *other, gpointer user_data)
nm_device_queue_recheck_available (NM_DEVICE (self),
NM_DEVICE_STATE_REASON_NONE,
NM_DEVICE_STATE_REASON_NONE);
nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE);
nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, TRUE);
}
}
@ -399,7 +399,7 @@ find_companion (NMDeviceOlpcMesh *self)
if (priv->companion)
return;
nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE);
nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, TRUE);
/* Try to find the companion if it's already known to the NMManager */
for (list = nm_manager_get_devices (priv->manager); list ; list = g_slist_next (list)) {
@ -407,7 +407,7 @@ find_companion (NMDeviceOlpcMesh *self)
nm_device_queue_recheck_available (NM_DEVICE (self),
NM_DEVICE_STATE_REASON_NONE,
NM_DEVICE_STATE_REASON_NONE);
nm_device_remove_pending_action (NM_DEVICE (self), "waiting for companion", TRUE);
nm_device_remove_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_COMPANION, TRUE);
break;
}
}

View file

@ -95,6 +95,7 @@ typedef struct {
bool enabled:1; /* rfkilled or not */
bool requested_scan:1;
bool ssid_found:1;
bool is_scanning:1;
gint32 last_scan;
gint32 scheduled_scan_time;
@ -182,7 +183,7 @@ static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self);
static void request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options);
static void request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options);
static void ap_add_remove (NMDeviceWifi *self,
guint signum,
@ -196,18 +197,34 @@ static void _hw_addr_set_scanning (NMDeviceWifi *self, gboolean do_reset);
/*****************************************************************************/
static void
constructed (GObject *object)
_ap_dump (NMDeviceWifi *self,
const NMWifiAP *ap,
const char *prefix,
gint32 now_s)
{
char buf[1024];
buf[0] = '\0';
_LOGD (LOGD_WIFI_SCAN, "wifi-ap: %-7s %s",
prefix,
nm_wifi_ap_to_string (ap, buf, sizeof (buf), now_s));
}
static void
_notify_scanning (NMDeviceWifi *self)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gboolean scanning;
G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
scanning = priv->sup_iface
&& nm_supplicant_interface_get_scanning (priv->sup_iface);
if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP)
_LOGI (LOGD_PLATFORM | LOGD_WIFI, "driver supports Access Point (AP) mode");
if (scanning == priv->is_scanning)
return;
/* Connect to the supplicant manager */
priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ());
_LOGD (LOGD_WIFI, "wifi-scan: scanning-state: %s", scanning ? "scanning" : "idle");
priv->is_scanning = scanning;
_notify (self, PROP_SCANNING);
}
static gboolean
@ -239,7 +256,7 @@ supplicant_interface_acquire (NMDeviceWifi *self)
}
if (nm_supplicant_interface_get_state (priv->sup_iface) < NM_SUPPLICANT_INTERFACE_STATE_READY)
nm_device_add_pending_action (NM_DEVICE (self), "waiting for supplicant", FALSE);
nm_device_add_pending_action (NM_DEVICE (self), NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, FALSE);
g_signal_connect (priv->sup_iface,
NM_SUPPLICANT_INTERFACE_STATE,
@ -262,7 +279,7 @@ supplicant_interface_acquire (NMDeviceWifi *self)
G_CALLBACK (supplicant_iface_scan_done_cb),
self);
g_signal_connect (priv->sup_iface,
"notify::scanning",
"notify::"NM_SUPPLICANT_INTERFACE_SCANNING,
G_CALLBACK (supplicant_iface_notify_scanning_cb),
self);
g_signal_connect (priv->sup_iface,
@ -270,6 +287,8 @@ supplicant_interface_acquire (NMDeviceWifi *self)
G_CALLBACK (supplicant_iface_notify_current_bss),
self);
_notify_scanning (self);
return TRUE;
}
@ -286,9 +305,9 @@ _requested_scan_set (NMDeviceWifi *self, gboolean value)
priv->requested_scan = value;
if (value)
nm_device_add_pending_action ((NMDevice *) self, "scan", TRUE);
nm_device_add_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE);
else
nm_device_remove_pending_action ((NMDevice *) self, "scan", TRUE);
nm_device_remove_pending_action ((NMDevice *) self, NM_PENDING_ACTION_WIFI_SCAN, TRUE);
}
static void
@ -306,8 +325,8 @@ supplicant_interface_release (NMDeviceWifi *self)
/* Reset the scan interval to be pretty frequent when disconnected */
priv->scan_interval = SCAN_INTERVAL_MIN + SCAN_INTERVAL_STEP;
_LOGD (LOGD_WIFI_SCAN, "reset scanning interval to %d seconds",
priv->scan_interval);
_LOGD (LOGD_WIFI, "wifi-scan: reset interval to %u seconds",
(unsigned) priv->scan_interval);
nm_clear_g_source (&priv->ap_dump_id);
@ -320,6 +339,8 @@ supplicant_interface_release (NMDeviceWifi *self)
g_clear_object (&priv->sup_iface);
}
_notify_scanning (self);
}
static NMWifiAP *
@ -541,7 +562,7 @@ deactivate (NMDevice *device)
/* Ensure we trigger a scan after deactivating a Hotspot */
if (old_mode == NM_802_11_MODE_AP)
request_wireless_scan (self, NULL);
request_wireless_scan (self, FALSE, NULL);
}
static void
@ -1165,7 +1186,7 @@ request_scan_cb (NMDevice *device,
priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
request_wireless_scan (self, new_scan_options);
request_wireless_scan (self, FALSE, new_scan_options);
g_dbus_method_invocation_return_value (context, NULL);
}
@ -1400,21 +1421,22 @@ ssids_options_to_ptrarray (GVariant *value)
}
static void
request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
request_wireless_scan (NMDeviceWifi *self, gboolean force_if_scanning, GVariant *scan_options)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gboolean backoff = FALSE;
GPtrArray *ssids = NULL;
gboolean new_scan_requested = FALSE;
nm_clear_g_source (&priv->pending_scan_id);
if (priv->requested_scan) {
if (!force_if_scanning && priv->requested_scan) {
/* There's already a scan in progress */
return;
}
if (check_scanning_allowed (self)) {
_LOGD (LOGD_WIFI_SCAN, "scanning requested");
_LOGD (LOGD_WIFI, "wifi-scan: scanning requested");
if (scan_options) {
GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL);
@ -1423,14 +1445,14 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
if (g_variant_is_of_type (val, G_VARIANT_TYPE ("aay")))
ssids = ssids_options_to_ptrarray (val);
else
_LOGD (LOGD_WIFI_SCAN, "ignoring invalid 'ssids' scan option");
_LOGD (LOGD_WIFI, "wifi-scan: ignoring invalid 'ssids' scan option");
g_variant_unref (val);
}
}
if (!ssids)
ssids = build_hidden_probe_list (self);
if (nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN)) {
if (_LOGD_ENABLED (LOGD_WIFI)) {
if (ssids) {
const GByteArray *ssid;
guint i;
@ -1441,12 +1463,12 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
foo = ssid->len > 0
? nm_utils_ssid_to_utf8 (ssid->data, ssid->len)
: NULL;
_LOGD (LOGD_WIFI_SCAN, "(%d) probe scanning SSID '%s'",
i, foo ? foo : "<hidden>");
_LOGD (LOGD_WIFI, "wifi-scan: (%u) probe scanning SSID %s%s%s",
i, NM_PRINT_FMT_QUOTED (foo, "\"", foo, "\"", "<hidden>"));
g_free (foo);
}
} else
_LOGD (LOGD_WIFI_SCAN, "no SSIDs to probe scan");
_LOGD (LOGD_WIFI, "wifi-scan: no SSIDs to probe scan");
}
_hw_addr_set_scanning (self, FALSE);
@ -1455,12 +1477,16 @@ request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options)
/* success */
backoff = TRUE;
_requested_scan_set (self, TRUE);
new_scan_requested = TRUE;
}
if (ssids)
g_ptr_array_unref (ssids);
} else
_LOGD (LOGD_WIFI_SCAN, "scan requested but not allowed at this time");
_LOGD (LOGD_WIFI, "wifi-scan: scanning requested but not allowed at this time");
if (!new_scan_requested)
_requested_scan_set (self, FALSE);
schedule_scan (self, backoff);
}
@ -1472,7 +1498,7 @@ request_wireless_scan_periodic (gpointer user_data)
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
priv->pending_scan_id = 0;
request_wireless_scan (self, NULL);
request_wireless_scan (self, FALSE, NULL);
return G_SOURCE_REMOVE;
}
@ -1519,7 +1545,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff)
priv->scan_interval = 5;
}
_LOGD (LOGD_WIFI_SCAN, "scheduled scan in %d seconds (interval now %d seconds)",
_LOGD (LOGD_WIFI, "wifi-scan: scheduled in %d seconds (interval now %d seconds)",
next_scan, priv->scan_interval);
}
}
@ -1531,7 +1557,7 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface,
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
_LOGD (LOGD_WIFI_SCAN, "scan %s", success ? "successful" : "failed");
_LOGD (LOGD_WIFI, "wifi-scan: scan-done callback: %s", success ? "successful" : "failed");
priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
schedule_scan (self, success);
@ -1549,17 +1575,22 @@ ap_list_dump (gpointer user_data)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (user_data);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gs_free NMWifiAP **list = NULL;
gsize i;
priv->ap_dump_id = 0;
_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]",
nm_utils_get_monotonic_timestamp_s (),
priv->last_scan,
priv->scheduled_scan_time);
list = ap_list_get_sorted (self, TRUE);
for (i = 0; list[i]; i++)
nm_wifi_ap_dump (list[i], "dump ", nm_device_get_iface (NM_DEVICE (self)));
if (_LOGD_ENABLED (LOGD_WIFI_SCAN)) {
gs_free NMWifiAP **list = NULL;
gsize i;
gint32 now_s = nm_utils_get_monotonic_timestamp_s ();
_LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]",
now_s,
priv->last_scan,
priv->scheduled_scan_time);
list = ap_list_get_sorted (self, TRUE);
for (i = 0; list[i]; i++)
_ap_dump (self, list[i], "dump", now_s);
}
return G_SOURCE_REMOVE;
}
@ -1568,10 +1599,9 @@ schedule_ap_list_dump (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
if (!nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN))
return;
nm_clear_g_source (&priv->ap_dump_id);
priv->ap_dump_id = g_timeout_add_seconds (1, ap_list_dump, self);
if ( !priv->ap_dump_id
&& _LOGD_ENABLED (LOGD_WIFI_SCAN))
priv->ap_dump_id = g_timeout_add_seconds (1, ap_list_dump, self);
}
static void
@ -1633,7 +1663,7 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
ap = nm_wifi_ap_new_from_properties (object_path, properties);
if (!ap) {
_LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path);
_LOGD (LOGD_WIFI, "invalid AP properties received for %s", object_path);
return;
}
@ -1646,21 +1676,21 @@ supplicant_iface_new_bss_cb (NMSupplicantInterface *iface,
ssid = nm_wifi_ap_get_ssid (ap);
if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) {
/* Yay, matched it, no longer treat as hidden */
_LOGD (LOGD_WIFI_SCAN, "matched hidden AP %s => '%s'",
_LOGD (LOGD_WIFI, "matched hidden AP %s => '%s'",
nm_wifi_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len));
} else {
/* Didn't have an entry for this AP in the database */
_LOGD (LOGD_WIFI_SCAN, "failed to match hidden AP %s",
_LOGD (LOGD_WIFI, "failed to match hidden AP %s",
nm_wifi_ap_get_address (ap));
}
}
found_ap = get_ap_by_supplicant_path (self, object_path);
if (found_ap) {
nm_wifi_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self)));
_ap_dump (self, ap, "updated", 0);
nm_wifi_ap_update_from_properties (found_ap, object_path, properties);
} else {
nm_wifi_ap_dump (ap, "added ", nm_device_get_iface (NM_DEVICE (self)));
_ap_dump (self, ap, "added", 0);
ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE);
}
@ -1695,7 +1725,7 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface,
ap = get_ap_by_supplicant_path (self, object_path);
if (ap) {
nm_wifi_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self)));
_ap_dump (self, ap, "updated", 0);
nm_wifi_ap_update_from_properties (ap, object_path, properties);
schedule_ap_list_dump (self);
}
@ -1723,7 +1753,7 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface,
*/
nm_wifi_ap_set_fake (ap, TRUE);
} else {
nm_wifi_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self)));
_ap_dump (self, ap, "removed", 0);
ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE);
schedule_ap_list_dump (self);
}
@ -2022,7 +2052,6 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
NMDevice *device = NM_DEVICE (self);
NMDeviceState devstate;
gboolean scanning;
gboolean recheck_available = FALSE;
if (new_state == old_state)
return;
@ -2042,11 +2071,13 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
switch (new_state) {
case NM_SUPPLICANT_INTERFACE_STATE_READY:
_LOGD (LOGD_WIFI_SCAN, "supplicant ready");
recheck_available = TRUE;
_LOGD (LOGD_WIFI, "supplicant ready");
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;
if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY)
nm_device_remove_pending_action (device, "waiting for supplicant", TRUE);
nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE);
break;
case NM_SUPPLICANT_INTERFACE_STATE_COMPLETED:
remove_supplicant_interface_error_handler (self);
@ -2104,11 +2135,13 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
}
break;
case NM_SUPPLICANT_INTERFACE_STATE_DOWN:
recheck_available = TRUE;
nm_device_queue_recheck_available (NM_DEVICE (device),
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
cleanup_association_attempt (self, FALSE);
if (old_state < NM_SUPPLICANT_INTERFACE_STATE_READY)
nm_device_remove_pending_action (device, "waiting for supplicant", TRUE);
nm_device_remove_pending_action (device, NM_PENDING_ACTION_WAITING_FOR_SUPPLICANT, TRUE);
/* If the device is already in UNAVAILABLE state then the state change
* is a NOP and the interface won't be re-acquired in the device state
@ -2122,23 +2155,19 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface,
_LOGI (LOGD_DEVICE | LOGD_WIFI, "supplicant interface keeps failing, giving up");
break;
case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE:
_requested_scan_set (self, FALSE);
request_wireless_scan (self, NULL);
/* we would clear _requested_scan_set() and trigger a new scan.
* However, we don't want to cancel the current pending action, so force
* a new scan request. */
request_wireless_scan (self, TRUE, NULL);
break;
default:
break;
}
if (recheck_available) {
nm_device_queue_recheck_available (NM_DEVICE (device),
NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE,
NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
}
/* Signal scanning state changes */
if ( new_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING
|| old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING)
_notify (self, PROP_SCANNING);
_notify_scanning (self);
}
static void
@ -2176,17 +2205,11 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface,
GParamSpec *pspec,
NMDeviceWifi *self)
{
NMDeviceState state;
gboolean scanning;
scanning = nm_supplicant_interface_get_scanning (iface);
_LOGD (LOGD_WIFI_SCAN, "now %s", scanning ? "scanning" : "idle");
_notify (self, PROP_SCANNING);
_notify_scanning (self);
/* Run a quick update of current AP when coming out of a scan */
state = nm_device_get_state (NM_DEVICE (self));
if (!scanning && state == NM_DEVICE_STATE_ACTIVATED)
if ( !NM_DEVICE_WIFI_GET_PRIVATE (self)->is_scanning
&& nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED)
periodic_update (self);
}
@ -3011,7 +3034,7 @@ device_state_changed (NMDevice *device,
case NM_DEVICE_STATE_DISCONNECTED:
/* Kick off a scan to get latest results */
priv->scan_interval = SCAN_INTERVAL_MIN;
request_wireless_scan (self, NULL);
request_wireless_scan (self, FALSE, NULL);
break;
default:
break;
@ -3085,6 +3108,87 @@ set_enabled (NMDevice *device, gboolean enabled)
/*****************************************************************************/
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gsize i;
char **list;
switch (prop_id) {
case PROP_MODE:
g_value_set_uint (value, priv->mode);
break;
case PROP_BITRATE:
g_value_set_uint (value, priv->rate);
break;
case PROP_CAPABILITIES:
g_value_set_uint (value, priv->capabilities);
break;
case PROP_ACCESS_POINTS:
list = (char **) ap_list_get_sorted_paths (self, TRUE);
for (i = 0; list[i]; i++)
list[i] = g_strdup (list[i]);
g_value_take_boxed (value, list);
break;
case PROP_ACTIVE_ACCESS_POINT:
nm_utils_g_value_set_object_path (value, priv->current_ap);
break;
case PROP_SCANNING:
g_value_set_boolean (value, priv->is_scanning);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDeviceWifi *device = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
switch (prop_id) {
case PROP_CAPABILITIES:
/* construct-only */
priv->capabilities = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_device_wifi_init (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
priv->mode = NM_802_11_MODE_INFRA;
priv->aps = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
constructed (GObject *object)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object);
if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP)
_LOGI (LOGD_PLATFORM | LOGD_WIFI, "driver supports Access Point (AP) mode");
/* Connect to the supplicant manager */
priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ());
}
NMDevice *
nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities)
{
@ -3098,15 +3202,6 @@ nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities)
NULL);
}
static void
nm_device_wifi_init (NMDeviceWifi *self)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
priv->mode = NM_802_11_MODE_INFRA;
priv->aps = g_hash_table_new (g_str_hash, g_str_equal);
}
static void
dispose (GObject *object)
{
@ -3143,62 +3238,6 @@ finalize (GObject *object)
G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object);
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMDeviceWifi *self = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
gsize i;
char **list;
switch (prop_id) {
case PROP_MODE:
g_value_set_uint (value, priv->mode);
break;
case PROP_BITRATE:
g_value_set_uint (value, priv->rate);
break;
case PROP_CAPABILITIES:
g_value_set_uint (value, priv->capabilities);
break;
case PROP_ACCESS_POINTS:
list = (char **) ap_list_get_sorted_paths (self, TRUE);
for (i = 0; list[i]; i++)
list[i] = g_strdup (list[i]);
g_value_take_boxed (value, list);
break;
case PROP_ACTIVE_ACCESS_POINT:
nm_utils_g_value_set_object_path (value, priv->current_ap);
break;
case PROP_SCANNING:
g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->sup_iface));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMDeviceWifi *device = NM_DEVICE_WIFI (object);
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device);
switch (prop_id) {
case PROP_CAPABILITIES:
/* construct-only */
priv->capabilities = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
nm_device_wifi_class_init (NMDeviceWifiClass *klass)
{

View file

@ -206,16 +206,19 @@ void
nm_wifi_ap_set_address (NMWifiAP *ap, const char *addr)
{
NMWifiAPPrivate *priv;
guint8 addr_buf[ETH_ALEN];
g_return_if_fail (NM_IS_WIFI_AP (ap));
g_return_if_fail (addr != NULL);
g_return_if_fail (nm_utils_hwaddr_valid (addr, ETH_ALEN));
if ( !addr
|| !nm_utils_hwaddr_aton (addr, addr_buf, sizeof (addr_buf)))
g_return_if_reached ();
priv = NM_WIFI_AP_GET_PRIVATE (ap);
if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) {
if ( !priv->address
|| !nm_utils_hwaddr_matches (addr_buf, sizeof (addr_buf), priv->address, -1)) {
g_free (priv->address);
priv->address = g_strdup (addr);
priv->address = nm_utils_hwaddr_ntoa (addr_buf, sizeof (addr_buf));
_notify (ap, PROP_HW_ADDRESS);
}
}
@ -572,50 +575,44 @@ add_group_ciphers (NMWifiAP *ap, NMSettingWirelessSecurity *sec)
nm_wifi_ap_set_rsn_flags (ap, priv->rsn_flags | flags);
}
static char
mode_to_char (NMWifiAP *self)
const char *
nm_wifi_ap_to_string (const NMWifiAP *self,
char *str_buf,
gulong buf_len,
gint32 now_s)
{
NMWifiAPPrivate *priv = NM_WIFI_AP_GET_PRIVATE (self);
if (priv->mode == NM_802_11_MODE_ADHOC)
return '*';
if (priv->hotspot)
return '#';
if (priv->fake)
return '-';
return ' ';
}
void
nm_wifi_ap_dump (NMWifiAP *self,
const char *prefix,
const char *ifname)
{
NMWifiAPPrivate *priv;
const NMWifiAPPrivate *priv;
const char *supplicant_id = "-";
guint32 chan;
char b1[200];
g_return_if_fail (NM_IS_WIFI_AP (self));
g_return_val_if_fail (NM_IS_WIFI_AP (self), NULL);
priv = NM_WIFI_AP_GET_PRIVATE (self);
chan = nm_utils_wifi_freq_to_channel (priv->freq);
if (priv->supplicant_path)
supplicant_id = strrchr (priv->supplicant_path, '/');
nm_log_dbg (LOGD_WIFI_SCAN, "%s[%s%c] %-32s[%s%u %3u%% %c W:%04X R:%04X] [%3u] %s%s",
prefix,
g_snprintf (str_buf, buf_len,
"%17s %-32s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us %s",
priv->address ?: "(none)",
mode_to_char (self),
priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)",
chan > 99 ? "" : (chan > 9 ? " " : " "),
nm_sprintf_buf (b1, "%s%s%s",
NM_PRINT_FMT_QUOTED (priv->ssid, "\"", nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len), "\"", "(none)")),
(priv->mode == NM_802_11_MODE_ADHOC
? '*'
: (priv->hotspot
? '#'
: (priv->fake
? 'f'
: 'a'))),
chan,
priv->strength,
priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : ' ',
priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_',
priv->wpa_flags & 0xFFFF,
priv->rsn_flags & 0xFFFF,
priv->last_seen > 0 ? (nm_utils_get_monotonic_timestamp_s () - priv->last_seen) : -1,
ifname,
priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1,
supplicant_id);
return str_buf;
}
static guint

View file

@ -89,8 +89,9 @@ gboolean nm_wifi_ap_get_fake (const NMWifiAP *ap);
void nm_wifi_ap_set_fake (NMWifiAP *ap,
gboolean fake);
void nm_wifi_ap_dump (NMWifiAP *self,
const char *prefix,
const char *ifname);
const char *nm_wifi_ap_to_string (const NMWifiAP *self,
char *str_buf,
gulong buf_len,
gint32 now_s);
#endif /* __NM_WIFI_AP_H__ */

View file

@ -567,7 +567,7 @@ nm_active_connection_set_device (NMActiveConnection *self, NMDevice *device)
G_CALLBACK (device_metered_changed), self);
if (!priv->assumed) {
priv->pending_activation_id = g_strdup_printf ("activation::%p", (void *)self);
priv->pending_activation_id = g_strdup_printf (NM_PENDING_ACTIONPREFIX_ACTIVATION"%p", (void *)self);
nm_device_add_pending_action (device, priv->pending_activation_id, TRUE);
}
} else {

View file

@ -943,7 +943,7 @@ activate_data_free (ActivateData *data)
{
NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (data->policy);
nm_device_remove_pending_action (data->device, "autoactivate", TRUE);
nm_device_remove_pending_action (data->device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE);
priv->pending_activation_checks = g_slist_remove (priv->pending_activation_checks, data);
if (data->autoactivate_id)
@ -1253,7 +1253,7 @@ schedule_activate_check (NMPolicy *self, NMDevice *device)
return;
}
nm_device_add_pending_action (device, "autoactivate", TRUE);
nm_device_add_pending_action (device, NM_PENDING_ACTION_AUTOACTIVATE, TRUE);
data = g_slice_new0 (ActivateData);
data->policy = self;

View file

@ -352,7 +352,7 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self)
{
NMSupplicantInterfacePrivate *priv;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (self, FALSE);
priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
if (priv->scanning)
@ -562,8 +562,6 @@ wpas_iface_scan_done (GDBusProxy *proxy,
/* Cache last scan completed time */
priv->last_scan = nm_utils_get_monotonic_timestamp_s ();
g_signal_emit (self, signals[SCAN_DONE], 0, success);
/* Emit NEW_BSS so that wifi device has the APs (in case it removed them) */
g_hash_table_iter_init (&iter, priv->bss_proxies);
while (g_hash_table_iter_next (&iter, (gpointer) &bss_path, (gpointer) &bss_proxy)) {
@ -577,6 +575,8 @@ wpas_iface_scan_done (GDBusProxy *proxy,
}
}
}
g_signal_emit (self, signals[SCAN_DONE], 0, success);
}
static void
@ -1269,7 +1269,6 @@ scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
return;
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);
@ -1278,7 +1277,6 @@ scan_request_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
_LOGW ("could not get scan request result: %s", error->message);
}
}
g_signal_emit (self, signals[SCAN_DONE], 0, error ? FALSE : TRUE);
}
gboolean