+
+
+void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ int bssid_changed;
+ int timeout = 5000;
+
+ wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: "
+ "status code %d", MAC2STR(wpa_s->pending_bssid),
+ data->assoc_reject.status_code);
+
+ bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
+
+ /*
+ * For now, unconditionally terminate the previous authentication. In
+ * theory, this should not be needed, but mac80211 gets quite confused
+ * if the authentication is left pending.. Some roaming cases might
+ * benefit from using the previous authentication, so this could be
+ * optimized in the future.
+ */
+ if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
+ WLAN_REASON_DEAUTH_LEAVING) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Deauth request to the driver failed");
+ }
+ wpa_s->sme.prev_bssid_set = 0;
+
+ if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) {
+ struct wpa_blacklist *b;
+ b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid);
+ if (b && b->count < 3) {
+ /*
+ * Speed up next attempt if there could be other APs
+ * that could accept association.
+ */
+ timeout = 100;
+ }
+ }
+ wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ os_memset(wpa_s->bssid, 0, ETH_ALEN);
+ os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
+ if (bssid_changed)
+ wpas_notify_bssid_changed(wpa_s);
+
+ /*
+ * TODO: if more than one possible AP is available in scan results,
+ * could try the other ones before requesting a new scan.
+ */
+ wpa_supplicant_req_scan(wpa_s, timeout / 1000,
+ 1000 * (timeout % 1000));
+}
+
+
+void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_printf(MSG_DEBUG, "SME: Authentication timed out");
+ wpa_supplicant_req_scan(wpa_s, 5, 0);
+}
+
+
+void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_printf(MSG_DEBUG, "SME: Association timed out");
+ wpa_supplicant_mark_disassoc(wpa_s);
+ wpa_supplicant_req_scan(wpa_s, 5, 0);
+}
+
+
+void sme_event_disassoc(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_printf(MSG_DEBUG, "SME: Disassociation event received");
+ if (wpa_s->sme.prev_bssid_set &&
+ !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)) {
+ /*
+ * cfg80211/mac80211 can get into somewhat confused state if
+ * the AP only disassociates us and leaves us in authenticated
+ * state. For now, force the state to be cleared to avoid
+ * confusing errors if we try to associate with the AP again.
+ */
+ wpa_printf(MSG_DEBUG, "SME: Deauthenticate to clear driver "
+ "state");
+ wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
+ WLAN_REASON_DEAUTH_LEAVING);
+ }
+}