EAP peer: Add framework for external SIM/USIM processing
[mech_eap.git] / wpa_supplicant / events.c
index 3ecb0ce..2e99af2 100644 (file)
@@ -187,6 +187,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
                eapol_sm_notify_eap_success(wpa_s->eapol, FALSE);
        wpa_s->ap_ies_from_associnfo = 0;
        wpa_s->current_ssid = NULL;
+       eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
        wpa_s->key_mgmt = 0;
 }
 
@@ -272,9 +273,10 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 {
 #ifdef IEEE8021X_EAPOL
 #ifdef PCSC_FUNCS
-       int aka = 0, sim = 0, type;
+       int aka = 0, sim = 0;
 
-       if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL)
+       if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL ||
+           wpa_s->conf->external_sim)
                return 0;
 
        if (ssid->eap.eap_methods == NULL) {
@@ -311,14 +313,9 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s,
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is configured to use SIM "
                "(sim=%d aka=%d) - initialize PCSC", sim, aka);
-       if (sim && aka)
-               type = SCARD_TRY_BOTH;
-       else if (aka)
-               type = SCARD_USIM_ONLY;
-       else
-               type = SCARD_GSM_SIM_ONLY;
 
-       wpa_s->scard = scard_init(type, NULL);
+       wpa_s->scard = scard_init((!sim && aka) ? SCARD_USIM_ONLY :
+                                 SCARD_TRY_BOTH, NULL);
        if (wpa_s->scard == NULL) {
                wpa_msg(wpa_s, MSG_WARNING, "Failed to initialize SIM "
                        "(pcsc-lite)");
@@ -719,10 +716,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
        rsn_ie_len = ie ? ie[1] : 0;
 
        wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' "
-               "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s",
+               "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d%s%s",
                i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len),
                wpa_ie_len, rsn_ie_len, bss->caps, bss->level,
-               wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "");
+               wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "",
+               (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) ||
+                wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ?
+               " p2p" : "");
 
        e = wpa_blacklist_get(wpa_s, bss->bssid);
        if (e) {
@@ -859,6 +859,13 @@ static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
                }
 
 #ifdef CONFIG_P2P
+               if (ssid->p2p_group &&
+                   !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) &&
+                   !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "   skip - no P2P IE seen");
+                       continue;
+               }
+
                /*
                 * TODO: skip the AP if its P2P IE has Group Formation
                 * bit set in the P2P Group Capability Bitmap and we
@@ -1497,6 +1504,43 @@ void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s)
 }
 
 
+#ifdef CONFIG_INTERWORKING
+
+static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
+                           size_t len)
+{
+       int res;
+
+       wpa_hexdump(MSG_DEBUG, "Interworking: QoS Map Set", qos_map, len);
+       res = wpa_drv_set_qos_map(wpa_s, qos_map, len);
+       if (res) {
+               wpa_printf(MSG_DEBUG, "Interworking: Failed to configure QoS Map Set to the driver");
+       }
+
+       return res;
+}
+
+
+static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s,
+                                           const u8 *ies, size_t ies_len)
+{
+       struct ieee802_11_elems elems;
+
+       if (ies == NULL)
+               return;
+
+       if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed)
+               return;
+
+       if (elems.qos_map_set) {
+               wpas_qos_map_set(wpa_s, elems.qos_map_set,
+                                elems.qos_map_set_len);
+       }
+}
+
+#endif /* CONFIG_INTERWORKING */
+
+
 static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                                          union wpa_event_data *data)
 {
@@ -1521,6 +1565,10 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
                                       data->assoc_info.resp_ies_len);
 #endif /* CONFIG_WNM */
+#ifdef CONFIG_INTERWORKING
+               interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
+                                               data->assoc_info.resp_ies_len);
+#endif /* CONFIG_INTERWORKING */
        }
        if (data->assoc_info.beacon_ies)
                wpa_hexdump(MSG_DEBUG, "beacon_ies",
@@ -2021,6 +2069,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *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 (wpas_p2p_4way_hs_failed(wpa_s) > 0)
+                       return; /* P2P group removed */
                wpas_auth_failed(wpa_s);
        }
        if (!wpa_s->disconnected &&
@@ -2283,8 +2333,12 @@ static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
                        wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, data->tdls.peer);
                break;
        case TDLS_REQUEST_TEARDOWN:
-               wpa_tdls_teardown_link(wpa_s->wpa, data->tdls.peer,
-                                      data->tdls.reason_code);
+               if (wpa_tdls_is_external_setup(wpa_s->wpa))
+                       wpa_tdls_teardown_link(wpa_s->wpa, data->tdls.peer,
+                                              data->tdls.reason_code);
+               else
+                       wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN,
+                                         data->tdls.peer);
                break;
        }
 }
@@ -2472,7 +2526,7 @@ static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr,
                wpas_auth_failed(wpa_s);
 
 #ifdef CONFIG_P2P
-       if (deauth && ie && ie_len > 0) {
+       if (deauth && reason_code > 0) {
                if (wpas_p2p_deauth_notif(wpa_s, addr, reason_code, ie, ie_len,
                                          locally_generated) > 0) {
                        /*
@@ -2894,6 +2948,19 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                        break;
                }
 #endif /* CONFIG_TDLS */
+#ifdef CONFIG_INTERWORKING
+               if (data->rx_action.category == WLAN_ACTION_QOS &&
+                   data->rx_action.len >= 1 &&
+                   data->rx_action.data[0] == QOS_QOS_MAP_CONFIG) {
+                       wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from "
+                               MACSTR, MAC2STR(data->rx_action.sa));
+                       if (os_memcmp(data->rx_action.sa, wpa_s->bssid, ETH_ALEN)
+                           == 0)
+                               wpas_qos_map_set(wpa_s, data->rx_action.data + 1,
+                                                data->rx_action.len - 1);
+                       break;
+               }
+#endif /* CONFIG_INTERWORKING */
 #ifdef CONFIG_P2P
                wpas_p2p_rx_action(wpa_s, data->rx_action.da,
                                   data->rx_action.sa,