[PATCH] dbus_new: add property to track reason for a state change

Dan Williams dcbw
Wed Oct 26 23:24:21 PDT 2011


On Mon, 2011-10-24 at 15:54 -0700, mukesh agrawal wrote:
> In the connection manager, it is sometimes useful to disambiguate the
> reason for a connection failure. For example, if a connection attempt
> fails due to WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT, it is more likely
> that the connection manager has the wrong key than if the connection
> attempt fails due to WLAN_REASON_DEAUTH_LEAVING.
> 
> This patch
> - adds a new D-Bus property, "StateChangeReason"

I'm not sure a property for the reason makes a ton of sense though.  The
reason codes are mostly useful over the state change, and if you know
what the previous state was.  The reasons are clearly useful in a state
change signal so that a client can process the information immediately,
but as a separate property there's not guarantee of atomicity with D-Bus
that both properties are bundled in the same properties changed
emission.  Next, if the client were to start up after the change
happened, it's unclear how they would meaningfully use the state change
reason which might have been valid 1 second ago or 5 minutes ago.

I think the best course here is to do what I explained in the thread
about not coalescing State signals:

1) New enum for all state change reasons; supplicant-specific, 802.11
reason/status codes, and EAP failures, etc.

2) New state changed signal that includes both the new state and the
reason code in one signal

Given that the reason code isn't very useful except when packaged with
the state change itself, we could just drop the reason as a property and
leave it as part of the new state signal emission.  Clients that care
about the reason can listen to the state change signal, ones that don't
can just listen for the property change.

Dan

> - adds a reason_code argument to wpa_supplicant_set_state
> - modifies wpa_supplicant_event_disassoc to pass the disconnect_reason
>   down to wpa_supplicant_set_state (via wpa_supplicant_mark_disassoc)
> - modifies sme_event_assoc_reject to pass the status_code down to
>   wpa_supplicant_set_state (via sme_deauth)
> - modifies wpa_supplicant_disassociate and wpa_supplicant_deauthenticate
>   to pass the reason_code down to wpa_supplicant_set_state
>   (via wpa_supplicant_clear_connection and wpa_supplicant_mark_disassoc)
> - sets the state change reason to -1 in all other cases (where no reason
>   is readily available)
> 
> Change-Id: I91e17f02d79c841c0a81ea71a547857bad2a7a27
> ---
>  wpa_supplicant/ap.c                     |    2 +-
>  wpa_supplicant/dbus/dbus_new.c          |    9 ++++++
>  wpa_supplicant/dbus/dbus_new.h          |    1 +
>  wpa_supplicant/dbus/dbus_new_handlers.c |   17 ++++++++++++
>  wpa_supplicant/dbus/dbus_new_handlers.h |    3 ++
>  wpa_supplicant/events.c                 |   42 +++++++++++++++++++-----------
>  wpa_supplicant/notify.c                 |    2 +
>  wpa_supplicant/scan.c                   |   12 ++++++---
>  wpa_supplicant/sme.c                    |   20 ++++++++------
>  wpa_supplicant/wpa_supplicant.c         |   34 +++++++++++++++++-------
>  wpa_supplicant/wpa_supplicant_i.h       |    9 +++++-
>  wpa_supplicant/wpas_glue.c              |   10 ++++---
>  12 files changed, 115 insertions(+), 46 deletions(-)
> 
> diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
> index 95279d3..494ea76 100644
> --- a/wpa_supplicant/ap.c
> +++ b/wpa_supplicant/ap.c
> @@ -297,7 +297,7 @@ static void wpas_ap_configured_cb(void *ctx)
>  {
>  	struct wpa_supplicant *wpa_s = ctx;
>  
> -	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED, LOCAL_REASON_UNKNOWN);
>  
>  	if (wpa_s->ap_configured_cb)
>  		wpa_s->ap_configured_cb(wpa_s->ap_configured_cb_ctx,
> diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
> index 49a0895..377e0da 100644
> --- a/wpa_supplicant/dbus/dbus_new.c
> +++ b/wpa_supplicant/dbus/dbus_new.c
> @@ -700,6 +700,11 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
>  			wpas_dbus_getter_current_auth_mode;
>  		prop = "CurrentAuthMode";
>  		break;
> +	case WPAS_DBUS_PROP_STATE_CHANGE_REASON:
> +		getter = (WPADBusPropertyAccessor)
> +			wpas_dbus_getter_state_change_reason;
> +		prop = "StateChangeReason";
> +		break;
>  	default:
>  		wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
>  			   __func__, property);
> @@ -1444,6 +1449,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
>  	  RW
>  	},
>  #endif /* CONFIG_WPS */
> +	{ "StateChangeReason", WPAS_DBUS_NEW_IFACE_INTERFACE, "i",
> +	  (WPADBusPropertyAccessor) wpas_dbus_getter_state_change_reason,
> +	  NULL, R
> +	},
>  	{ NULL, NULL, NULL, NULL, NULL, 0 }
>  };
>  
> diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
> index 377e381..eab8406 100644
> --- a/wpa_supplicant/dbus/dbus_new.h
> +++ b/wpa_supplicant/dbus/dbus_new.h
> @@ -32,6 +32,7 @@ enum wpas_dbus_prop {
>  	WPAS_DBUS_PROP_CURRENT_NETWORK,
>  	WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
>  	WPAS_DBUS_PROP_BSSS,
> +	WPAS_DBUS_PROP_STATE_CHANGE_REASON,
>  };
>  
>  enum wpas_dbus_bss_prop {
> diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
> index e954020..26975b2 100644
> --- a/wpa_supplicant/dbus/dbus_new_handlers.c
> +++ b/wpa_supplicant/dbus/dbus_new_handlers.c
> @@ -2459,6 +2459,23 @@ DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
>  
> 
>  /**
> + * wpas_dbus_getter_state_change_reason - Get reason code for last state change
> + * @message: Pointer to incoming dbus message
> + * @wpa_s: wpa_supplicant structure for a network interface
> + * Returns: A message containing value of state_change_reason variable. Value
> + * is -1 if reason is unknown to wpa_supplicant.
> + *
> + * Getter for "StateChangeReason" property.
> + */
> +DBusMessage * wpas_dbus_getter_state_change_reason(DBusMessage *message,
> +						   struct wpa_supplicant *wpa_s)
> +{
> +	return wpas_dbus_simple_property_getter(message, DBUS_TYPE_INT32,
> +						&wpa_s->state_change_reason);
> +}
> +
> +
> +/**
>   * wpas_dbus_getter_bridge_ifname - Get interface name
>   * @message: Pointer to incoming dbus message
>   * @wpa_s: wpa_supplicant structure for a network interface
> diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
> index 742d33c..97274e9 100644
> --- a/wpa_supplicant/dbus/dbus_new_handlers.h
> +++ b/wpa_supplicant/dbus/dbus_new_handlers.h
> @@ -152,6 +152,9 @@ DBusMessage * wpas_dbus_getter_current_network(DBusMessage *message,
>  DBusMessage * wpas_dbus_getter_current_auth_mode(DBusMessage *message,
>  						 struct wpa_supplicant *wpa_s);
>  
> +DBusMessage * wpas_dbus_getter_state_change_reason(DBusMessage *message,
> +						   struct wpa_supplicant *wpa_s);
> +
>  DBusMessage * wpas_dbus_getter_bsss(DBusMessage *message,
>  				    struct wpa_supplicant *wpa_s);
>  
> diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
> index 69d2191..3ee87d0 100644
> --- a/wpa_supplicant/events.c
> +++ b/wpa_supplicant/events.c
> @@ -109,7 +109,8 @@ static void wpa_supplicant_stop_countermeasures(void *eloop_ctx,
>  }
>  
> 
> -void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
> +void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s,
> +				  int32_t reason_code)
>  {
>  	int bssid_changed;
>  
> @@ -121,7 +122,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
>  	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
>  		return;
>  
> -	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
> +	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED, reason_code);
>  	bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
>  	os_memset(wpa_s->bssid, 0, ETH_ALEN);
>  	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
> @@ -672,7 +673,8 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s,
>  		 * we don't wait timeout seconds before transitioning
>  		 * to INACTIVE state.
>  		 */
> -		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
> +		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE,
> +					 LOCAL_REASON_UNKNOWN);
>  		return;
>  	}
>  	wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec);
> @@ -931,7 +933,8 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
>  	}
>  
>  	if (wpa_s->disconnected) {
> -		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
> +		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED,
> +					 LOCAL_REASON_UNKNOWN);
>  		wpa_scan_results_free(scan_res);
>  		return 0;
>  	}
> @@ -960,7 +963,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
>  		 */
>  		wpa_printf(MSG_INFO, "Fast reconnect failed");
>  		wpa_scan_results_free(scan_res);
> -		wpa_supplicant_mark_disassoc(wpa_s);
> +		wpa_supplicant_mark_disassoc(wpa_s, LOCAL_REASON_UNKNOWN);
>  	} else {
>  		wpa_scan_results_free(scan_res);
>  		wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
> @@ -1218,7 +1221,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
>  	if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0)
>  		return;
>  
> -	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED);
> +	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED, LOCAL_REASON_UNKNOWN);
>  	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
>  		os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
>  	if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ||
> @@ -1293,7 +1296,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
>  	    (wpa_s->current_ssid &&
>  	     wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) {
>  		wpa_supplicant_cancel_auth_timeout(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED,
> +					 LOCAL_REASON_UNKNOWN);
>  	} else if (!ft_completed) {
>  		/* Timeout for receiving the first EAPOL packet */
>  		wpa_supplicant_req_auth_timeout(wpa_s, 10, 0);
> @@ -1307,7 +1311,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
>  		 * handshake.
>  		 */
>  		wpa_supplicant_cancel_auth_timeout(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED,
> +					 LOCAL_REASON_UNKNOWN);
>  		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
>  		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
>  	} else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) &&
> @@ -1324,7 +1329,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
>  		 * up in authenticated.
>  		 */
>  		wpa_supplicant_cancel_auth_timeout(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED,
> +					 LOCAL_REASON_UNKNOWN);
>  		eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
>  		eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
>  	}
> @@ -1500,7 +1506,7 @@ static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s,
>  		wpa_printf(MSG_DEBUG, "Fast reconnect: Failed to trigger scan");
>  		wpa_supplicant_req_scan(wpa_s, 0, 100000);
>  	}
> -	wpa_supplicant_mark_disassoc(wpa_s);
> +	wpa_supplicant_mark_disassoc(wpa_s, reason_code);
>  
>  	if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME))
>  		sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid);
> @@ -1648,7 +1654,7 @@ wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s,
>  	case EVENT_INTERFACE_REMOVED:
>  		wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed");
>  		wpa_s->interface_removed = 1;
> -		wpa_supplicant_mark_disassoc(wpa_s);
> +		wpa_supplicant_mark_disassoc(wpa_s, LOCAL_REASON_UNKNOWN);
>  		l2_packet_deinit(wpa_s->l2);
>  		wpa_s->l2 = NULL;
>  #ifdef CONFIG_IBSS_RSN
> @@ -2206,21 +2212,25 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
>  #ifdef CONFIG_AP
>  			if (!wpa_s->ap_iface) {
>  				wpa_supplicant_set_state(wpa_s,
> -							 WPA_DISCONNECTED);
> +							 WPA_DISCONNECTED,
> +							 LOCAL_REASON_UNKNOWN);
>  				wpa_supplicant_req_scan(wpa_s, 0, 0);
>  			} else
>  				wpa_supplicant_set_state(wpa_s,
> -							 WPA_COMPLETED);
> +							 WPA_COMPLETED,
> +							 LOCAL_REASON_UNKNOWN);
>  #else /* CONFIG_AP */
> -			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
> +			wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED,
> +						 LOCAL_REASON_UNKNOWN);
>  			wpa_supplicant_req_scan(wpa_s, 0, 0);
>  #endif /* CONFIG_AP */
>  		}
>  		break;
>  	case EVENT_INTERFACE_DISABLED:
>  		wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled");
> -		wpa_supplicant_mark_disassoc(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
> +		wpa_supplicant_mark_disassoc(wpa_s, LOCAL_REASON_UNKNOWN);
> +		wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED,
> +					 LOCAL_REASON_UNKNOWN);
>  		break;
>  	case EVENT_CHANNEL_LIST_CHANGED:
>  		if (wpa_s->drv_priv == NULL)
> diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
> index 2053c3d..d3bb6b0 100644
> --- a/wpa_supplicant/notify.c
> +++ b/wpa_supplicant/notify.c
> @@ -83,6 +83,8 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
>  
>  	/* notify the new DBus API */
>  	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
> +	wpas_dbus_signal_prop_changed(wpa_s,
> +				      WPAS_DBUS_PROP_STATE_CHANGE_REASON);
>  
>  #ifdef CONFIG_P2P
>  	if (new_state == WPA_COMPLETED)
> diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
> index 4fb9bef..e9e2bc0 100644
> --- a/wpa_supplicant/scan.c
> +++ b/wpa_supplicant/scan.c
> @@ -260,14 +260,16 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
>  	}
>  
>  	if (wpa_s->disconnected && !wpa_s->scan_req) {
> -		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
> +		wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED,
> +					 LOCAL_REASON_UNKNOWN);
>  		return;
>  	}
>  
>  	if (!wpa_supplicant_enabled_networks(wpa_s->conf) &&
>  	    !wpa_s->scan_req) {
>  		wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan");
> -		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
> +		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE,
> +					 LOCAL_REASON_UNKNOWN);
>  		return;
>  	}
>  
> @@ -305,7 +307,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
>  	prev_state = wpa_s->wpa_state;
>  	if (wpa_s->wpa_state == WPA_DISCONNECTED ||
>  	    wpa_s->wpa_state == WPA_INACTIVE)
> -		wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
> +		wpa_supplicant_set_state(wpa_s, WPA_SCANNING,
> +					 LOCAL_REASON_UNKNOWN);
>  
>  	/* Find the starting point from which to continue scanning */
>  	ssid = wpa_s->conf->ssid;
> @@ -472,7 +475,8 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
>  	if (ret) {
>  		wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan");
>  		if (prev_state != wpa_s->wpa_state)
> -			wpa_supplicant_set_state(wpa_s, prev_state);
> +			wpa_supplicant_set_state(wpa_s, prev_state,
> +						 LOCAL_REASON_UNKNOWN);
>  		wpa_supplicant_req_scan(wpa_s, 1, 0);
>  	}
>  }
> diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
> index 325ffc5..4393b29 100644
> --- a/wpa_supplicant/sme.c
> +++ b/wpa_supplicant/sme.c
> @@ -244,7 +244,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
>  		wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
>  
>  	wpa_clear_keys(wpa_s, bss->bssid);
> -	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
> +	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING,
> +				 LOCAL_REASON_UNKNOWN);
>  	old_ssid = wpa_s->current_ssid;
>  	wpa_s->current_ssid = ssid;
>  	wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
> @@ -384,7 +385,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
>  		params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
>  		params.freq);
>  
> -	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
> +	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING, LOCAL_REASON_UNKNOWN);
>  
>  	if (params.wpa_ie == NULL ||
>  	    ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
> @@ -446,7 +447,7 @@ int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
>  }
>  
> 
> -static void sme_deauth(struct wpa_supplicant *wpa_s)
> +static void sme_deauth(struct wpa_supplicant *wpa_s, int32_t reason_code)
>  {
>  	int bssid_changed;
>  
> @@ -460,7 +461,7 @@ static void sme_deauth(struct wpa_supplicant *wpa_s)
>  	wpa_s->sme.prev_bssid_set = 0;
>  
>  	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
> -	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
> +	wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED, reason_code);
>  	os_memset(wpa_s->bssid, 0, ETH_ALEN);
>  	os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
>  	if (bssid_changed)
> @@ -484,7 +485,7 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
>  	 * benefit from using the previous authentication, so this could be
>  	 * optimized in the future.
>  	 */
> -	sme_deauth(wpa_s);
> +	sme_deauth(wpa_s, data->assoc_reject.status_code);
>  }
>  
> 
> @@ -501,7 +502,7 @@ void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
>  {
>  	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
>  	wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
> -	wpa_supplicant_mark_disassoc(wpa_s);
> +	wpa_supplicant_mark_disassoc(wpa_s, LOCAL_REASON_UNKNOWN);
>  }
>  
> 
> @@ -530,7 +531,7 @@ static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
>  	struct wpa_supplicant *wpa_s = eloop_ctx;
>  	if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
>  		wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
> -		sme_deauth(wpa_s);
> +		sme_deauth(wpa_s, LOCAL_REASON_UNKNOWN);
>  	}
>  }
>  
> @@ -540,7 +541,7 @@ static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
>  	struct wpa_supplicant *wpa_s = eloop_ctx;
>  	if (wpa_s->wpa_state == WPA_ASSOCIATING) {
>  		wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
> -		sme_deauth(wpa_s);
> +		sme_deauth(wpa_s, LOCAL_REASON_UNKNOWN);
>  	}
>  }
>  
> @@ -565,7 +566,8 @@ void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
>  	 */
>  	wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
>  		"to proceed after disconnection event");
> -	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
> +	wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING,
> +				 LOCAL_REASON_UNKNOWN);
>  	os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
>  
>  	/*
> diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
> index d8c2a2c..fc647fe 100644
> --- a/wpa_supplicant/wpa_supplicant.c
> +++ b/wpa_supplicant/wpa_supplicant.c
> @@ -562,18 +562,29 @@ static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s)
>   * wpa_supplicant_set_state - Set current connection state
>   * @wpa_s: Pointer to wpa_supplicant data
>   * @state: The new connection state
> + * @reason_code: IEEE 802.11 reason code, or LOCAL_REASON_UNKNOWN
>   *
>   * This function is called whenever the connection state changes, e.g.,
>   * association is completed for WPA/WPA2 4-Way Handshake is started.
>   */
>  void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
> -			      enum wpa_states state)
> +			      enum wpa_states state,
> +			      int32_t reason_code)
>  {
>  	enum wpa_states old_state = wpa_s->wpa_state;
>  
> -	wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s",
> +	wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s (reason %d)",
>  		wpa_supplicant_state_txt(wpa_s->wpa_state),
> -		wpa_supplicant_state_txt(state));
> +		wpa_supplicant_state_txt(state),
> +		reason_code);
> +
> +	/*
> +	 * NB: only update state_change_reason on true state change, to
> +	 * avoid clobbering state_change_reason when we deauthenticate
> +	 * following a disassociate event. see sme_event_disassoc.
> +	 */
> +	if (state != wpa_s->wpa_state)
> +		wpa_s->state_change_reason = reason_code;
>  
>  	if (state != WPA_SCANNING)
>  		wpa_supplicant_notify_scanning(wpa_s, 0);
> @@ -1294,7 +1305,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
>  		wpa_supplicant_set_wpa_none_key(wpa_s, ssid);
>  	}
>  
> -	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
> +	wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING, LOCAL_REASON_UNKNOWN);
>  	if (bss) {
>  		params.bssid = bss->bssid;
>  		params.ssid = bss->ssid;
> @@ -1387,7 +1398,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
>  		/* No need to timeout authentication since there is no key
>  		 * management. */
>  		wpa_supplicant_cancel_auth_timeout(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED,
> +					 LOCAL_REASON_UNKNOWN);
>  #ifdef CONFIG_IBSS_RSN
>  	} else if (ssid->mode == WPAS_MODE_IBSS &&
>  		   wpa_s->key_mgmt != WPA_KEY_MGMT_NONE &&
> @@ -1436,12 +1448,13 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
>  
> 
>  static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s,
> -					    const u8 *addr)
> +					    const u8 *addr,
> +					    int32_t reason_code)
>  {
>  	struct wpa_ssid *old_ssid;
>  
>  	wpa_clear_keys(wpa_s, addr);
> -	wpa_supplicant_mark_disassoc(wpa_s);
> +	wpa_supplicant_mark_disassoc(wpa_s, reason_code);
>  	old_ssid = wpa_s->current_ssid;
>  	wpa_s->current_ssid = NULL;
>  	wpa_s->current_bss = NULL;
> @@ -1474,7 +1487,7 @@ void wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s,
>  		addr = wpa_s->bssid;
>  	}
>  
> -	wpa_supplicant_clear_connection(wpa_s, addr);
> +	wpa_supplicant_clear_connection(wpa_s, addr, reason_code);
>  }
>  
> 
> @@ -1500,7 +1513,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s,
>  		addr = wpa_s->bssid;
>  	}
>  
> -	wpa_supplicant_clear_connection(wpa_s, addr);
> +	wpa_supplicant_clear_connection(wpa_s, addr, reason_code);
>  }
>  
> 
> @@ -2047,7 +2060,8 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
>  		wpa_supplicant_req_scan(wpa_s, interface_count, 100000);
>  		interface_count++;
>  	} else
> -		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
> +		wpa_supplicant_set_state(wpa_s, WPA_INACTIVE,
> +					 LOCAL_REASON_UNKNOWN);
>  
>  	return 0;
>  }
> diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
> index eaabe0f..71a7d0a 100644
> --- a/wpa_supplicant/wpa_supplicant_i.h
> +++ b/wpa_supplicant/wpa_supplicant_i.h
> @@ -546,6 +546,7 @@ struct wpa_supplicant {
>  	unsigned int wps_freq;
>  	int wps_fragment_size;
>  	int auto_reconnect_disabled;
> +	int32_t state_change_reason;
>  
>  	 /* Channel preferences for AP/P2P GO use */
>  	int best_24_freq;
> @@ -555,6 +556,8 @@ struct wpa_supplicant {
>  
> 
>  /* wpa_supplicant.c */
> +#define LOCAL_REASON_UNKNOWN (-1)
> +
>  int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid);
>  
>  int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s);
> @@ -574,7 +577,8 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr);
>  void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s,
>  				     int sec, int usec);
>  void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
> -			      enum wpa_states state);
> +			      enum wpa_states state,
> +			      int32_t reason_code);
>  struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s);
>  const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s);
>  void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s);
> @@ -625,7 +629,8 @@ void ieee80211_sta_free_hw_features(struct hostapd_hw_modes *hw_features,
>  void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid);
>  
>  /* events.c */
> -void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s);
> +void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s,
> +				  int32_t reason_code);
>  void wpa_supplicant_connect(struct wpa_supplicant *wpa_s,
>  			    struct wpa_bss *selected,
>  			    struct wpa_ssid *ssid);
> diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
> index 2662eec..6eb5db1 100644
> --- a/wpa_supplicant/wpas_glue.c
> +++ b/wpa_supplicant/wpas_glue.c
> @@ -295,7 +295,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
>  
>  	wpa_supplicant_cancel_scan(wpa_s);
>  	wpa_supplicant_cancel_auth_timeout(wpa_s);
> -	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +	wpa_supplicant_set_state(wpa_s, WPA_COMPLETED, LOCAL_REASON_UNKNOWN);
>  
>  }
>  
> @@ -305,10 +305,12 @@ static void wpa_supplicant_notify_eapol_done(void *ctx)
>  	struct wpa_supplicant *wpa_s = ctx;
>  	wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
>  	if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
> -		wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
> +		wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE,
> +					 LOCAL_REASON_UNKNOWN);
>  	} else {
>  		wpa_supplicant_cancel_auth_timeout(wpa_s);
> -		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
> +		wpa_supplicant_set_state(wpa_s, WPA_COMPLETED,
> +					 LOCAL_REASON_UNKNOWN);
>  	}
>  }
>  
> @@ -391,7 +393,7 @@ static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
>  
>  static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state)
>  {
> -	wpa_supplicant_set_state(wpa_s, state);
> +	wpa_supplicant_set_state(wpa_s, state, LOCAL_REASON_UNKNOWN);
>  }
>  
> 





More information about the Hostap mailing list