Interworking: Add support for using eap_proxy offload
[mech_eap.git] / wpa_supplicant / interworking.c
index 3602b07..2f35240 100644 (file)
@@ -187,6 +187,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
 
        wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR,
                   MAC2STR(bss->bssid));
+       wpa_s->interworking_gas_bss = bss;
 
        info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST;
        if (all) {
@@ -407,11 +408,9 @@ static const u8 * nai_realm_parse_realm(struct nai_realm *r, const u8 *pos,
                return NULL;
        }
        wpa_hexdump_ascii(MSG_DEBUG, "NAI Realm", pos, realm_len);
-       r->realm = os_malloc(realm_len + 1);
+       r->realm = dup_binstr(pos, realm_len);
        if (r->realm == NULL)
                return NULL;
-       os_memcpy(r->realm, pos, realm_len);
-       r->realm[realm_len] = '\0';
        pos += realm_len;
 
        if (pos + 1 > f_end) {
@@ -1326,10 +1325,11 @@ fail:
 static struct wpa_cred * interworking_credentials_available_3gpp(
        struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
 {
-       struct wpa_cred *cred, *selected = NULL;
+       struct wpa_cred *selected = NULL;
+#ifdef INTERWORKING_3GPP
+       struct wpa_cred *cred;
        int ret;
 
-#ifdef INTERWORKING_3GPP
        if (bss->anqp == NULL || bss->anqp->anqp_3gpp == NULL)
                return NULL;
 
@@ -1346,6 +1346,13 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
                        goto compare;
                }
 #endif /* PCSC_FUNCS */
+#ifdef CONFIG_EAP_PROXY
+               if (cred->pcsc && wpa_s->mnc_len > 0 && wpa_s->imsi[0]) {
+                       imsi = wpa_s->imsi;
+                       mnc_len = wpa_s->mnc_len;
+                       goto compare;
+               }
+#endif /* CONFIG_EAP_PROXY */
 
                if (cred->imsi == NULL || !cred->imsi[0] ||
                    cred->milenage == NULL || !cred->milenage[0])
@@ -1358,9 +1365,9 @@ static struct wpa_cred * interworking_credentials_available_3gpp(
                mnc_len = sep - cred->imsi - 3;
                imsi = cred->imsi;
 
-#ifdef PCSC_FUNCS
+#if defined(PCSC_FUNCS) || defined(CONFIG_EAP_PROXY)
        compare:
-#endif /* PCSC_FUNCS */
+#endif /* PCSC_FUNCS || CONFIG_EAP_PROXY */
                wpa_printf(MSG_DEBUG, "Interworking: Parsing 3GPP info from "
                           MACSTR, MAC2STR(bss->bssid));
                ret = plmn_id_match(bss->anqp->anqp_3gpp, imsi, mnc_len);
@@ -1808,11 +1815,11 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst,
 
 
 static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
-                                           const u8 *sa, u16 info_id,
+                                           struct wpa_bss *bss, const u8 *sa,
+                                           u16 info_id,
                                            const u8 *data, size_t slen)
 {
        const u8 *pos = data;
-       struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa);
        struct wpa_bss_anqp *anqp = NULL;
 #ifdef CONFIG_HS20
        u8 type;
@@ -1948,6 +1955,7 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
        const u8 *end;
        u16 info_id;
        u16 slen;
+       struct wpa_bss *bss = NULL, *tmp;
 
        if (result != GAS_QUERY_SUCCESS)
                return;
@@ -1960,6 +1968,21 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
                return;
        }
 
+       /*
+        * If possible, select the BSS entry based on which BSS entry was used
+        * for the request. This can help in cases where multiple BSS entries
+        * may exist for the same AP.
+        */
+       dl_list_for_each_reverse(tmp, &wpa_s->bss, struct wpa_bss, list) {
+               if (tmp == wpa_s->interworking_gas_bss &&
+                   os_memcmp(tmp->bssid, dst, ETH_ALEN) == 0) {
+                       bss = tmp;
+                       break;
+               }
+       }
+       if (bss == NULL)
+               bss = wpa_bss_get_bssid(wpa_s, dst);
+
        pos = wpabuf_head(resp);
        end = pos + wpabuf_len(resp);
 
@@ -1977,7 +2000,7 @@ void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token,
                                   "for Info ID %u", info_id);
                        break;
                }
-               interworking_parse_rx_anqp_resp(wpa_s, dst, info_id, pos,
+               interworking_parse_rx_anqp_resp(wpa_s, bss, dst, info_id, pos,
                                                slen);
                pos += slen;
        }