wpa_supplicant_ap_deinit(wpa_s);
#endif /* CONFIG_AP */
+#ifdef CONFIG_HS20
+ /* Clear possibly configured frame filters */
+ wpa_drv_configure_frame_filters(wpa_s, 0);
+#endif /* CONFIG_HS20 */
+
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
return;
return 1;
}
+#ifdef CONFIG_IEEE80211W
+ if (wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip - MFP Required but network not MFP Capable");
+ return 0;
+ }
+#endif /* CONFIG_IEEE80211W */
+
wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) {
proto_match++;
continue;
}
- if (ssid->pbss != bss_is_pbss(bss)) {
+ if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) {
wpa_dbg(wpa_s, MSG_DEBUG, " skip - PBSS mismatch (ssid %d bss %d)",
ssid->pbss, bss_is_pbss(bss));
continue;
struct wpa_bss *current_bss = NULL;
#ifndef CONFIG_NO_ROAMING
int min_diff;
+ int to_5ghz;
#endif /* CONFIG_NO_ROAMING */
if (wpa_s->reassociate)
return 1;
}
- if (current_bss->level < 0 && current_bss->level > selected->level) {
+ to_5ghz = selected->freq > 4000 && current_bss->freq < 4000;
+
+ if (current_bss->level < 0 &&
+ current_bss->level > selected->level + to_5ghz * 2) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better "
"signal level");
return 0;
else
min_diff = 5;
}
+ if (to_5ghz) {
+ /* Make it easier to move to 5 GHz band */
+ if (min_diff > 2)
+ min_diff -= 2;
+ else
+ min_diff = 0;
+ }
if (abs(current_bss->level - selected->level) < min_diff) {
wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference "
"in signal level");
}
if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
(os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+ (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+ (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
(p[0] == WLAN_EID_RSN && p[1] >= 2)) {
if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len))
break;
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_MATCH_IFACE
+ if (wpa_s->matched) {
+ wpa_supplicant_remove_iface(wpa_s->global, wpa_s, 0);
+ break;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
#ifdef CONFIG_TERMINATE_ONLASTIF
/* check if last interface */
if (!any_interfaces(wpa_s->global->ifaces))
{
struct wpa_supplicant *ifs;
- wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+ /*
+ * To allow backwards compatibility with higher level layers that
+ * assumed the REGDOM_CHANGE event is sent over the initially added
+ * interface. Find the highest parent of this interface and use it to
+ * send the event.
+ */
+ for (ifs = wpa_s; ifs->parent && ifs != ifs->parent; ifs = ifs->parent)
+ ;
+
+ wpa_msg(ifs, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
reg_init_str(info->initiator), reg_type_str(info->type),
info->alpha2[0] ? " alpha2=" : "",
info->alpha2[0] ? info->alpha2 : "");
#endif /* CONFIG_INTERWORKING */
if (category == WLAN_ACTION_RADIO_MEASUREMENT &&
+ payload[0] == WLAN_RRM_RADIO_MEASUREMENT_REQUEST) {
+ wpas_rrm_handle_radio_measurement_request(wpa_s, mgmt->sa,
+ payload + 1,
+ plen - 1);
+ return;
+ }
+
+ 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;
case EVENT_ASSOC_REJECT:
if (data->assoc_reject.bssid)
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "bssid=" MACSTR " status_code=%u",
+ "bssid=" MACSTR " status_code=%u%s",
MAC2STR(data->assoc_reject.bssid),
- data->assoc_reject.status_code);
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
else
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT
- "status_code=%u",
- data->assoc_reject.status_code);
+ "status_code=%u%s",
+ data->assoc_reject.status_code,
+ data->assoc_reject.timed_out ? " timeout" : "");
wpa_s->assoc_status_code = data->assoc_reject.status_code;
wpas_notify_assoc_status_code(wpa_s);
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
#endif /* CONFIG_AP */
#ifdef CONFIG_OFFCHANNEL
wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS pending_dst="
- MACSTR, MAC2STR(wpa_s->parent->pending_action_dst));
+ MACSTR, MAC2STR(wpa_s->p2pdev->pending_action_dst));
/*
* Catch TX status events for Action frames we sent via group
- * interface in GO mode.
+ * interface in GO mode, or via standalone AP interface.
+ * Note, wpa_s->p2pdev will be the same as wpa_s->parent,
+ * except when the primary interface is used as a GO interface
+ * (for drivers which do not have group interface concurrency)
*/
if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
data->tx_status.stype == WLAN_FC_STYPE_ACTION &&
- os_memcmp(wpa_s->parent->pending_action_dst,
+ os_memcmp(wpa_s->p2pdev->pending_action_dst,
data->tx_status.dst, ETH_ALEN) == 0) {
offchannel_send_action_tx_status(
- wpa_s->parent, data->tx_status.dst,
+ wpa_s->p2pdev, data->tx_status.dst,
data->tx_status.data,
data->tx_status.data_len,
data->tx_status.ack ?
if (!data || !wpa_s->current_ssid)
break;
+ wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CHANNEL_SWITCH
+ "freq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d",
+ data->ch_switch.freq,
+ data->ch_switch.ht_enabled,
+ data->ch_switch.ch_offset,
+ channel_width_to_string(data->ch_switch.ch_width),
+ data->ch_switch.cf1,
+ data->ch_switch.cf2);
+
wpa_s->assoc_freq = data->ch_switch.freq;
wpa_s->current_ssid->frequency = data->ch_switch.freq;
#endif /* CONFIG_AP */
#ifdef CONFIG_P2P
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
const u8 *src = mgmt->sa;
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len -
+ IEEE80211_HDRLEN;
wpas_p2p_probe_req_rx(
wpa_s, src, mgmt->da,
mgmt->bssid, ie, ie_len,
}
if (stype == WLAN_FC_STYPE_PROBE_REQ &&
- data->rx_mgmt.frame_len > 24) {
- const u8 *ie = mgmt->u.probe_req.variable;
- size_t ie_len = data->rx_mgmt.frame_len -
- (mgmt->u.probe_req.variable -
- data->rx_mgmt.frame);
+ data->rx_mgmt.frame_len > IEEE80211_HDRLEN) {
+ const u8 *ie;
+ size_t ie_len;
+
+ ie = data->rx_mgmt.frame + IEEE80211_HDRLEN;
+ ie_len = data->rx_mgmt.frame_len - IEEE80211_HDRLEN;
wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da,
mgmt->bssid, ie, ie_len,
data->driver_gtk_rekey.replay_ctr);
break;
case EVENT_SCHED_SCAN_STOPPED:
- wpa_s->pno = 0;
wpa_s->sched_scanning = 0;
resched = wpa_s->scanning && wpas_scan_scheduled(wpa_s);
wpa_supplicant_notify_scanning(wpa_s, 0);
break;
}
}
+
+
+void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
+ union wpa_event_data *data)
+{
+ struct wpa_supplicant *wpa_s;
+
+ if (event != EVENT_INTERFACE_STATUS)
+ return;
+
+ wpa_s = wpa_supplicant_get_iface(ctx, data->interface_status.ifname);
+ if (wpa_s && wpa_s->driver->get_ifindex) {
+ unsigned int ifindex;
+
+ ifindex = wpa_s->driver->get_ifindex(wpa_s->drv_priv);
+ if (ifindex != data->interface_status.ifindex) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "interface status ifindex %d mismatch (%d)",
+ ifindex, data->interface_status.ifindex);
+ return;
+ }
+ }
+#ifdef CONFIG_MATCH_IFACE
+ else if (data->interface_status.ievent == EVENT_INTERFACE_ADDED) {
+ struct wpa_interface *wpa_i;
+
+ wpa_i = wpa_supplicant_match_iface(
+ ctx, data->interface_status.ifname);
+ if (!wpa_i)
+ return;
+ wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL);
+ os_free(wpa_i);
+ if (wpa_s)
+ wpa_s->matched = 1;
+ }
+#endif /* CONFIG_MATCH_IFACE */
+
+ if (wpa_s)
+ wpa_supplicant_event(wpa_s, event, data);
+}