From 7ff833674b5b6447361098dcd7b56e8c08c84a0b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 2 Sep 2012 21:05:54 +0300 Subject: [PATCH] Interworking: Fetch only the needed ANQP information Use configured credentials to figure out which ANQP information needs to be fetched and only fetch those when using Interworking network selection. The fetch_anqp command is still fetching all ANQP information. Signed-hostap: Jouni Malinen --- wpa_supplicant/interworking.c | 110 +++++++++++++++++++++++++----- wpa_supplicant/wpa_supplicant_i.h | 1 + 2 files changed, 95 insertions(+), 16 deletions(-) diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 987c79b5f..20c7731b3 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -108,27 +108,101 @@ static void interworking_anqp_resp_cb(void *ctx, const u8 *dst, } +static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->roaming_consortium_len) + return 1; + } + return 0; +} + + +static int cred_with_3gpp(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->pcsc || cred->imsi) + return 1; + } + return 0; +} + + +static int cred_with_nai_realm(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->pcsc || cred->imsi) + continue; + if (!cred->eap_method) + return 1; + if (cred->realm && cred->roaming_consortium_len == 0) + return 1; + } + return 0; +} + + +static int cred_with_domain(struct wpa_supplicant *wpa_s) +{ + struct wpa_cred *cred; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (cred->domain || cred->pcsc || cred->imsi) + return 1; + } + return 0; +} + + +static int additional_roaming_consortiums(struct wpa_bss *bss) +{ + const u8 *ie; + ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM); + if (ie == NULL || ie[1] == 0) + return 0; + return ie[2]; /* Number of ANQP OIs */ +} + + static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpabuf *buf; int ret = 0; int res; - u16 info_ids[] = { - ANQP_CAPABILITY_LIST, - ANQP_VENUE_NAME, - ANQP_NETWORK_AUTH_TYPE, - ANQP_ROAMING_CONSORTIUM, - ANQP_IP_ADDR_TYPE_AVAILABILITY, - ANQP_NAI_REALM, - ANQP_3GPP_CELLULAR_NETWORK, - ANQP_DOMAIN_NAME - }; + u16 info_ids[8]; + size_t num_info_ids = 0; struct wpabuf *extra = NULL; + int all = wpa_s->fetch_all_anqp; wpa_printf(MSG_DEBUG, "Interworking: ANQP Query Request to " MACSTR, MAC2STR(bss->bssid)); + info_ids[num_info_ids++] = ANQP_CAPABILITY_LIST; + if (all) { + info_ids[num_info_ids++] = ANQP_VENUE_NAME; + info_ids[num_info_ids++] = ANQP_NETWORK_AUTH_TYPE; + } + if (all || (cred_with_roaming_consortium(wpa_s) && + additional_roaming_consortiums(bss))) + info_ids[num_info_ids++] = ANQP_ROAMING_CONSORTIUM; + if (all) + info_ids[num_info_ids++] = ANQP_IP_ADDR_TYPE_AVAILABILITY; + if (all || cred_with_nai_realm(wpa_s)) + info_ids[num_info_ids++] = ANQP_NAI_REALM; + if (all || cred_with_3gpp(wpa_s)) + info_ids[num_info_ids++] = ANQP_3GPP_CELLULAR_NETWORK; + if (all || cred_with_domain(wpa_s)) + info_ids[num_info_ids++] = ANQP_DOMAIN_NAME; + wpa_hexdump(MSG_DEBUG, "Interworking: ANQP Query info", + (u8 *) info_ids, num_info_ids * 2); + #ifdef CONFIG_HS20 if (wpa_bss_get_vendor_ie(bss, HS20_IE_VENDOR_TYPE)) { u8 *len_pos; @@ -143,16 +217,18 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, wpabuf_put_u8(extra, HS20_STYPE_QUERY_LIST); wpabuf_put_u8(extra, 0); /* Reserved */ wpabuf_put_u8(extra, HS20_STYPE_CAPABILITY_LIST); - wpabuf_put_u8(extra, HS20_STYPE_OPERATOR_FRIENDLY_NAME); - wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); - wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); - wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); + if (all) { + wpabuf_put_u8(extra, + HS20_STYPE_OPERATOR_FRIENDLY_NAME); + wpabuf_put_u8(extra, HS20_STYPE_WAN_METRICS); + wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY); + wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS); + } gas_anqp_set_element_len(extra, len_pos); } #endif /* CONFIG_HS20 */ - buf = anqp_build_req(info_ids, sizeof(info_ids) / sizeof(info_ids[0]), - extra); + buf = anqp_build_req(info_ids, num_info_ids, extra); wpabuf_free(extra); if (buf == NULL) return -1; @@ -1532,6 +1608,7 @@ int interworking_fetch_anqp(struct wpa_supplicant *wpa_s) return 0; wpa_s->network_select = 0; + wpa_s->fetch_all_anqp = 1; interworking_start_fetch_anqp(wpa_s); @@ -1774,6 +1851,7 @@ int interworking_select(struct wpa_supplicant *wpa_s, int auto_select) wpa_s->network_select = 1; wpa_s->auto_network_select = 0; wpa_s->auto_select = !!auto_select; + wpa_s->fetch_all_anqp = 0; wpa_printf(MSG_DEBUG, "Interworking: Start scan for network " "selection"); wpa_s->scan_res_handler = interworking_scan_res_handler; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 4c520bacf..0bc288011 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -588,6 +588,7 @@ struct wpa_supplicant { unsigned int network_select:1; unsigned int auto_select:1; unsigned int auto_network_select:1; + unsigned int fetch_all_anqp:1; #endif /* CONFIG_INTERWORKING */ unsigned int drv_capa_known;