#include "scan.h"
#include "offchannel.h"
#include "interworking.h"
+#include "mesh.h"
+#include "mesh_mpm.h"
+#include "wmm_ac.h"
#ifndef CONFIG_NO_SCAN_PROCESSING
}
+static void wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
+
+ if (!bss) {
+ wpa_supplicant_update_scan_results(wpa_s);
+
+ /* Get the BSS from the new scan results */
+ bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
+ }
+
+ if (bss)
+ wpa_s->current_bss = bss;
+}
+
+
static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s)
{
struct wpa_ssid *ssid, *old_ssid;
- struct wpa_bss *bss;
int res;
- if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid)
+ if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) {
+ wpa_supplicant_update_current_bss(wpa_s);
return 0;
+ }
wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association "
"information");
old_ssid = wpa_s->current_ssid;
wpa_s->current_ssid = ssid;
- bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
- if (!bss) {
- wpa_supplicant_update_scan_results(wpa_s);
-
- /* Get the BSS from the new scan results */
- bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid);
- }
-
- if (bss)
- wpa_s->current_bss = bss;
+ wpa_supplicant_update_current_bss(wpa_s);
wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
wpa_supplicant_initiate_eapol(wpa_s);
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);
-#ifdef CONFIG_SME
- wpa_s->sme.prev_bssid_set = 0;
-#endif /* CONFIG_SME */
+ sme_clear_on_disassoc(wpa_s);
#ifdef CONFIG_P2P
os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN);
#endif /* CONFIG_P2P */
wpa_s->current_bss = NULL;
wpa_s->assoc_freq = 0;
-#ifdef CONFIG_IEEE80211R
-#ifdef CONFIG_SME
- if (wpa_s->sme.ft_ies)
- sme_update_ft_ies(wpa_s, NULL, NULL, 0);
-#endif /* CONFIG_SME */
-#endif /* CONFIG_IEEE80211R */
if (bssid_changed)
wpas_notify_bssid_changed(wpa_s);
wpa_s->current_ssid = NULL;
eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_s->key_mgmt = 0;
+
+ wpas_rrm_reset(wpa_s);
}
}
-static int ht_supported(const struct hostapd_hw_modes *mode)
-{
- if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) {
- /*
- * The driver did not indicate whether it supports HT. Assume
- * it does to avoid connection issues.
- */
- return 1;
- }
-
- /*
- * IEEE Std 802.11n-2009 20.1.1:
- * An HT non-AP STA shall support all EQM rates for one spatial stream.
- */
- return mode->mcs_set[0] == 0xff;
-}
-
-
-static int vht_supported(const struct hostapd_hw_modes *mode)
-{
- if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) {
- /*
- * The driver did not indicate whether it supports VHT. Assume
- * it does to avoid connection issues.
- */
- return 1;
- }
-
- /*
- * A VHT non-AP STA shall support MCS 0-7 for one spatial stream.
- * TODO: Verify if this complies with the standard
- */
- return (mode->vht_mcs_set[0] & 0x3) != 3;
-}
-
-
static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
{
const struct hostapd_hw_modes *mode = NULL, *modes;
if (wpas_network_disabled(wpa_s, ssid))
continue;
if (ssid->mode == IEEE80211_MODE_IBSS ||
- ssid->mode == IEEE80211_MODE_AP)
+ ssid->mode == IEEE80211_MODE_AP ||
+ ssid->mode == IEEE80211_MODE_MESH)
return ssid;
}
}
return 0;
}
+ if (wnm_scan_process(wpa_s, 1) > 0)
+ goto scan_work_done;
+
if (sme_proc_obss_scan(wpa_s) > 0)
goto scan_work_done;
*/
return 1;
} else {
+#ifdef CONFIG_MESH
+ if (wpa_s->ifmsh) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Avoiding join because we already joined a mesh group");
+ return 0;
+ }
+#endif /* CONFIG_MESH */
wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
ssid = wpa_supplicant_pick_new_network(wpa_s);
if (ssid) {
#endif /* CONFIG_IBSS_RSN */
wpas_wps_notify_assoc(wpa_s, bssid);
+
+ if (data) {
+ wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies,
+ data->assoc_info.resp_ies_len,
+ &data->assoc_info.wmm_params);
+ }
}
return;
}
+ wmm_ac_notify_disassoc(wpa_s);
+
if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) {
wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - "
"pre-shared key may be incorrect");
}
if (!wpa_s->disconnected &&
(!wpa_s->auto_reconnect_disabled ||
- wpa_s->key_mgmt == WPA_KEY_MGMT_WPS)) {
+ wpa_s->key_mgmt == WPA_KEY_MGMT_WPS ||
+ wpas_wps_searching(wpa_s))) {
wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to "
- "reconnect (wps=%d wpa_state=%d)",
+ "reconnect (wps=%d/%d wpa_state=%d)",
wpa_s->key_mgmt == WPA_KEY_MGMT_WPS,
+ wpas_wps_searching(wpa_s),
wpa_s->wpa_state);
if (wpa_s->wpa_state == WPA_COMPLETED &&
wpa_s->current_ssid &&
struct wpa_supplicant *ifs;
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
- reg_init_str(info->type), reg_type_str(info->type),
+ reg_init_str(info->initiator), reg_type_str(info->type),
info->alpha2[0] ? " alpha2=" : "",
info->alpha2[0] ? info->alpha2 : "");
static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s,
- const u8 *frame, size_t len, int freq)
+ const u8 *frame, size_t len, int freq,
+ int rssi)
{
const struct ieee80211_mgmt *mgmt;
const u8 *payload;
" Category=%u DataLen=%d freq=%d MHz",
MAC2STR(mgmt->sa), category, (int) plen, freq);
+ if (category == WLAN_ACTION_WMM) {
+ wmm_ac_rx_action(wpa_s, mgmt->da, mgmt->sa, payload, plen);
+ return;
+ }
+
#ifdef CONFIG_IEEE80211R
if (category == WLAN_ACTION_FT) {
ft_rx_action(wpa_s, payload, plen);
}
#endif /* CONFIG_INTERWORKING */
+ if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+ payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) {
+ wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, plen - 1);
+ return;
+ }
+
+ if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+ payload[0] == WLAN_RRM_LINK_MEASUREMENT_REQUEST) {
+ wpas_rrm_handle_link_measurement_request(wpa_s, mgmt->sa,
+ payload + 1, plen - 1,
+ rssi);
+ return;
+ }
+
wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid,
category, payload, plen, freq);
+ if (wpa_s->ifmsh)
+ mesh_mpm_action_rx(wpa_s, mgmt, len);
}
}
+static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Connection authorized by device, previous state %d",
+ wpa_s->wpa_state);
+ if (wpa_s->wpa_state == WPA_ASSOCIATED) {
+ wpa_supplicant_cancel_auth_timeout(wpa_s);
+ wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
+ eapol_sm_notify_portValid(wpa_s->eapol, TRUE);
+ eapol_sm_notify_eap_success(wpa_s->eapol, TRUE);
+ }
+ wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr);
+ wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck,
+ data->assoc_info.ptk_kek);
+}
+
+
void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data)
{
break;
case EVENT_ASSOC:
wpa_supplicant_event_assoc(wpa_s, data);
+ if (data && data->assoc_info.authorized)
+ wpa_supplicant_event_assoc_auth(wpa_s, data);
break;
case EVENT_DISASSOC:
wpas_event_disassoc(wpa_s,
wpa_s->own_scan_running = 1;
if (wpa_s->last_scan_req == MANUAL_SCAN_REQ &&
wpa_s->manual_scan_use_id) {
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED "id=%u",
- wpa_s->manual_scan_id);
+ wpa_msg_ctrl(wpa_s, MSG_INFO,
+ WPA_EVENT_SCAN_STARTED "id=%u",
+ wpa_s->manual_scan_id);
} else {
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+ wpa_msg_ctrl(wpa_s, MSG_INFO,
+ WPA_EVENT_SCAN_STARTED);
}
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
wpa_s->external_scan_running = 1;
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
+ wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
}
break;
case EVENT_SCAN_RESULTS:
}
break;
case EVENT_AUTH_TIMED_OUT:
+ /* It is possible to get this event from earlier connection */
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->mode == WPAS_MODE_MESH) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Ignore AUTH_TIMED_OUT in mesh configuration");
+ break;
+ }
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
sme_event_auth_timed_out(wpa_s, data);
break;
case EVENT_ASSOC_TIMED_OUT:
+ /* It is possible to get this event from earlier connection */
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->mode == WPAS_MODE_MESH) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Ignore ASSOC_TIMED_OUT in mesh configuration");
+ break;
+ }
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
sme_event_assoc_timed_out(wpa_s, data);
break;
}
#endif /* CONFIG_P2P */
#ifdef CONFIG_IBSS_RSN
- if (stype == WLAN_FC_STYPE_AUTH &&
+ if (wpa_s->current_ssid &&
+ wpa_s->current_ssid->mode == WPAS_MODE_IBSS &&
+ stype == WLAN_FC_STYPE_AUTH &&
data->rx_mgmt.frame_len >= 30) {
wpa_supplicant_event_ibss_auth(wpa_s, data);
break;
wpas_event_rx_mgmt_action(
wpa_s, data->rx_mgmt.frame,
data->rx_mgmt.frame_len,
- data->rx_mgmt.freq);
+ data->rx_mgmt.freq,
+ data->rx_mgmt.ssi_signal);
+ break;
+ }
+
+ if (wpa_s->ifmsh) {
+ mesh_mpm_mgmt_rx(wpa_s, &data->rx_mgmt);
break;
}
data->connect_failed_reason.code);
#endif /* CONFIG_AP */
break;
+ case EVENT_NEW_PEER_CANDIDATE:
+#ifdef CONFIG_MESH
+ if (!wpa_s->ifmsh || !data)
+ break;
+ wpa_mesh_notify_peer(wpa_s, data->mesh_peer.peer,
+ data->mesh_peer.ies,
+ data->mesh_peer.ie_len);
+#endif /* CONFIG_MESH */
+ break;
default:
wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
break;