1ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines/* 2ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * Hotspot 2.0 AP ANQP processing 3ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * Copyright (c) 2009, Atheros Communications, Inc. 4ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. 5ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * 6ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * This software may be distributed under the terms of the BSD license. 7ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines * See README for more details. 8ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines */ 9ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 10ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "includes.h" 11ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 126948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include "common.h" 136948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar#include "common/ieee802_11_defs.h" 14ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "hostapd.h" 15ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "ap_config.h" 16cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "ap_drv_ops.h" 17cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#include "hs20.h" 18ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 19ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 20cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainaru8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid) 21cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar{ 22cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar u8 conf; 23cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (!hapd->conf->hs20) 24cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return eid; 25cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *eid++ = WLAN_EID_VENDOR_SPECIFIC; 26cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *eid++ = 7; 27cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar WPA_PUT_BE24(eid, OUI_WFA); 28cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += 3; 29cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *eid++ = HS20_INDICATION_OUI_TYPE; 30cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar conf = HS20_VERSION; /* Release Number */ 31cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar conf |= HS20_ANQP_DOMAIN_ID_PRESENT; 32cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (hapd->conf->disable_dgaf) 33cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar conf |= HS20_DGAF_DISABLED; 34cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *eid++ = conf; 35cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id); 36cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += 2; 37cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 38cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return eid; 39cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar} 40cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 41cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 42cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainaru8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid) 43cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar{ 44cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar u8 *len; 45cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar u16 capab; 46cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 47cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (!hapd->conf->osen) 48cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return eid; 49cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 50cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *eid++ = WLAN_EID_VENDOR_SPECIFIC; 51cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar len = eid++; /* to be filled */ 52ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines WPA_PUT_BE24(eid, OUI_WFA); 53ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines eid += 3; 54ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines *eid++ = HS20_OSEN_OUI_TYPE; 55ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 56ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines /* Group Data Cipher Suite */ 57ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 58ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines eid += RSN_SELECTOR_LEN; 59ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines 60ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines /* Pairwise Cipher Suite Count and List */ 61ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines WPA_PUT_LE16(eid, 1); 62cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += 2; 63cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP); 64ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines eid += RSN_SELECTOR_LEN; 65cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 66cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* AKM Suite Count and List */ 67cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar WPA_PUT_LE16(eid, 1); 68cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += 2; 69cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN); 70cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += RSN_SELECTOR_LEN; 71cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 72cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* RSN Capabilities */ 73cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar capab = 0; 74cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (hapd->conf->wmm_enabled) { 75cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* 4 PTKSA replay counters when using WMM */ 76cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 77cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 78cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#ifdef CONFIG_IEEE80211W 79cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 80cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar capab |= WPA_CAPABILITY_MFPC; 81cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 82cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar capab |= WPA_CAPABILITY_MFPR; 83cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 84cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar#endif /* CONFIG_IEEE80211W */ 85cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar WPA_PUT_LE16(eid, capab); 86cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar eid += 2; 87cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 88cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar *len = eid - len - 1; 89cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 90cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return eid; 91cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar} 92cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 93cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 94cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarint hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr, 95cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar u8 osu_method, const char *url) 96cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar{ 97cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar struct wpabuf *buf; 98cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar size_t len = 0; 99cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar int ret; 100cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 101cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* TODO: should refuse to send notification if the STA is not associated 102cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar * or if the STA did not indicate support for WNM-Notification */ 103cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 104cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (url) { 105cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar len = 1 + os_strlen(url); 106cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (5 + len > 255) { 107cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpa_printf(MSG_INFO, "HS 2.0: Too long URL for " 108cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar "WNM-Notification: '%s'", url); 109cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return -1; 110cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 111cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 112cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 113cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar buf = wpabuf_alloc(4 + 7 + len); 114cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (buf == NULL) 115cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return -1; 116cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 117cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WLAN_ACTION_WNM); 118cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); 119cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 1); /* Dialog token */ 120cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ 121cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 122cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* Subscription Remediation subelement */ 123cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 124cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 5 + len); 125cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_be24(buf, OUI_WFA); 126cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED); 127cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (url) { 128cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, len - 1); 129cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_data(buf, url, len - 1); 130cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, osu_method); 131cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } else { 132cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* Server URL and Server Method fields not included */ 133cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 0); 134cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar } 135cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 136cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 137cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_head(buf), wpabuf_len(buf)); 138cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 139cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_free(buf); 140cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 141cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return ret; 142cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar} 143cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 144cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 145cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainarint hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd, 146cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar const u8 *addr, 147cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar const struct wpabuf *payload) 148cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar{ 149cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar struct wpabuf *buf; 150cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar int ret; 151cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 152cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* TODO: should refuse to send notification if the STA is not associated 153cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar * or if the STA did not indicate support for WNM-Notification */ 154cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 155cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload)); 156cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar if (buf == NULL) 157cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return -1; 158cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 159cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WLAN_ACTION_WNM); 160cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); 161cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 1); /* Dialog token */ 162cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ 163cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 164cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar /* Deauthentication Imminent Notice subelement */ 165cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 166cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, 4 + wpabuf_len(payload)); 167cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_be24(buf, OUI_WFA); 168cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE); 169cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_put_buf(buf, payload); 170cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 171cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 172cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_head(buf), wpabuf_len(buf)); 173cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 174cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar wpabuf_free(buf); 175cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar 176cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar return ret; 177cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar} 178cddc3e03e4ec99c0268c03a126195173e519ed58Pirama Arumuga Nainar