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