From f9cd147d6b4718b03d8f3110e5dcaa56fe57902b Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 2 Nov 2012 12:08:11 +0200 Subject: [PATCH] HS 2.0R2: Update Indication element to Release 2 The HS 2.0 Indication element from wpa_supplicant now includes the release number field and wpa_supplicant shows the release number of the AP in STATUS command (hs20=1 replaced with hs20=). The new update_identifier field in the cred block can now be used to configure the PPS MO ID so that wpa_supplicant adds it to the Indication element in Association Request frames. Signed-hostap: Jouni Malinen --- src/common/ieee802_11_defs.h | 5 +++++ wpa_supplicant/README-HS20 | 3 +++ wpa_supplicant/config.c | 5 +++++ wpa_supplicant/config.h | 2 ++ wpa_supplicant/config_file.c | 2 ++ wpa_supplicant/ctrl_iface.c | 13 +++++++++++-- wpa_supplicant/hs20_supplicant.c | 29 ++++++++++++++++++++++++++--- wpa_supplicant/hs20_supplicant.h | 3 ++- wpa_supplicant/scan.c | 2 +- wpa_supplicant/sme.c | 3 ++- wpa_supplicant/wpa_supplicant.c | 3 ++- wpa_supplicant/wpa_supplicant.conf | 3 +++ 12 files changed, 64 insertions(+), 9 deletions(-) diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 0e39caf56..df8c08b04 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -909,6 +909,11 @@ enum { #define HS20_STYPE_NAI_HOME_REALM_QUERY 6 #define HS20_STYPE_OPERATING_CLASS 7 +#define HS20_DGAF_DISABLED 0x01 +#define HS20_PPS_MO_ID_PRESENT 0x02 +#define HS20_ANQP_DOMAIN_ID_PRESENT 0x04 +#define HS20_VERSION 0x10 /* Release 2 */ + /* Wi-Fi Direct (P2P) */ #define P2P_OUI_TYPE 9 diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index 03d06d3be..33fbc21f9 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -220,6 +220,9 @@ Credentials can be pre-configured for automatic network selection: # (non-exact match means any subdomain matches the entry; priority is in # 0..255 range with 0 being the highest priority) # +# update_identifier: PPS MO ID +# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier) +# # for example: # #cred={ diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index f19c6615b..def3e838c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2440,6 +2440,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var, return 0; } + if (os_strcmp(var, "update_identifier") == 0) { + cred->update_identifier = atoi(value); + return 0; + } + val = wpa_config_parse_string(value, &len); if (val == NULL) { wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 8e6954453..b64f414bb 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -244,6 +244,8 @@ struct wpa_cred { char country[3]; } *roaming_partner; size_t num_roaming_partner; + + int update_identifier; }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index b9ec5ae5d..7ad3f9331 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -804,6 +804,8 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred) p->country); } } + if (cred->update_identifier) + fprintf(f, "\tupdate_identifier=%d\n", cred->update_identifier); } diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 7dce67922..0df37108e 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1554,6 +1554,9 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, { char *pos, *end, tmp[30]; int res, verbose, wps, ret; +#ifdef CONFIG_HS20 + const u8 *hs20; +#endif /* CONFIG_HS20 */ if (os_strcmp(params, "-DRIVER") == 0) return wpa_drv_status(wpa_s, buf, buflen); @@ -1692,10 +1695,16 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, #ifdef CONFIG_HS20 if (wpa_s->current_bss && - wpa_bss_get_vendor_ie(wpa_s->current_bss, HS20_IE_VENDOR_TYPE) && + (hs20 = wpa_bss_get_vendor_ie(wpa_s->current_bss, + HS20_IE_VENDOR_TYPE)) && wpa_s->wpa_proto == WPA_PROTO_RSN && wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { - ret = os_snprintf(pos, end - pos, "hs20=1\n"); + int release = 1; + if (hs20[1] >= 5) { + u8 rel_num = (hs20[6] & 0xf0) >> 4; + release = rel_num + 1; + } + ret = os_snprintf(pos, end - pos, "hs20=%d\n", release); if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 5f30313ba..004024482 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -23,13 +23,20 @@ #include "hs20_supplicant.h" -void wpas_hs20_add_indication(struct wpabuf *buf) +void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id) { + u8 conf; + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); - wpabuf_put_u8(buf, 5); + wpabuf_put_u8(buf, pps_mo_id >= 0 ? 7 : 5); wpabuf_put_be24(buf, OUI_WFA); wpabuf_put_u8(buf, HS20_INDICATION_OUI_TYPE); - wpabuf_put_u8(buf, 0x00); /* Hotspot Configuration */ + conf = HS20_VERSION; + if (pps_mo_id >= 0) + conf |= HS20_PPS_MO_ID_PRESENT; + wpabuf_put_u8(buf, conf); + if (pps_mo_id >= 0) + wpabuf_put_le16(buf, pps_mo_id); } @@ -62,6 +69,22 @@ int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, } +int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ + struct wpa_cred *cred; + + if (ssid == NULL || ssid->parent_cred == NULL) + return 0; + + for (cred = wpa_s->conf->cred; cred; cred = cred->next) { + if (ssid->parent_cred == cred) + return cred->update_identifier; + } + + return 0; +} + + struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload, size_t payload_len) { diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h index 1c8481bf8..7f62a1509 100644 --- a/wpa_supplicant/hs20_supplicant.h +++ b/wpa_supplicant/hs20_supplicant.h @@ -8,7 +8,7 @@ #ifndef HS20_SUPPLICANT_H #define HS20_SUPPLICANT_H -void wpas_hs20_add_indication(struct wpabuf *buf); +void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id); int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, const u8 *payload, size_t payload_len); @@ -18,5 +18,6 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *data, size_t slen); int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_bss *bss); +int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); #endif /* HS20_SUPPLICANT_H */ diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 6c742d6d2..6f586670a 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -425,7 +425,7 @@ static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) #ifdef CONFIG_HS20 if (wpa_s->conf->hs20 && wpabuf_resize(&extra_ie, 7) == 0) - wpas_hs20_add_indication(extra_ie); + wpas_hs20_add_indication(extra_ie, -1); #endif /* CONFIG_HS20 */ return extra_ie; diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 5ce9da710..297470dbc 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -360,7 +360,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { - wpas_hs20_add_indication(hs20); + int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); + wpas_hs20_add_indication(hs20, pps_mo_id); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 60e7a66a7..f67daeac6 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1586,7 +1586,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { - wpas_hs20_add_indication(hs20); + int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); + wpas_hs20_add_indication(hs20, pps_mo_id); os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_ie_len += wpabuf_len(hs20); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 1593c338a..99d86fe64 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -439,6 +439,9 @@ fast_reauth=1 # (non-exact match means any subdomain matches the entry; priority is in # 0..255 range with 0 being the highest priority) # +# update_identifier: PPS MO ID +# (Hotspot 2.0 PerProviderSubscription/UpdateIdentifier) +# # for example: # #cred={