diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index c6d2a931d4..2023feb577 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -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); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index adce2fcf9c..2a2d276d92 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -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); diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 311b5a2c77..e512f2ca7d 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -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" diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index e0258523c0..0fdccb8ae5 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -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; } } diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index ed5d2c6252..188ed54eb6 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -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 : ""); + _LOGD (LOGD_WIFI, "wifi-scan: (%u) probe scanning SSID %s%s%s", + i, NM_PRINT_FMT_QUOTED (foo, "\"", foo, "\"", "")); 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) { diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 9d8ba42c61..96e9d19c5f 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -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 diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 5a2a2e58b5..a68aece8a8 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -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__ */ diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 38aadd2714..068bc85ea5 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -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 { diff --git a/src/nm-policy.c b/src/nm-policy.c index a8719d9f37..a2ff2945b2 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -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; diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c index c913a6960c..f932fe8b53 100644 --- a/src/supplicant/nm-supplicant-interface.c +++ b/src/supplicant/nm-supplicant-interface.c @@ -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