1 /* 2 * Hotspot 2.0 AP ANQP processing 3 * Copyright (c) 2009, Atheros Communications, Inc. 4 * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. 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 "common/wpa_ctrl.h" 15 #include "hostapd.h" 16 #include "ap_config.h" 17 #include "ap_drv_ops.h" 18 #include "sta_info.h" 19 #include "hs20.h" 20 21 22 u8 * hostapd_eid_hs20_indication(struct hostapd_data *hapd, u8 *eid) 23 { 24 u8 conf; 25 if (!hapd->conf->hs20) 26 return eid; 27 *eid++ = WLAN_EID_VENDOR_SPECIFIC; 28 *eid++ = hapd->conf->hs20_release < 2 ? 5 : 7; 29 WPA_PUT_BE24(eid, OUI_WFA); 30 eid += 3; 31 *eid++ = HS20_INDICATION_OUI_TYPE; 32 conf = (hapd->conf->hs20_release - 1) << 4; /* Release Number */ 33 if (hapd->conf->hs20_release >= 2) 34 conf |= HS20_ANQP_DOMAIN_ID_PRESENT; 35 if (hapd->conf->disable_dgaf) 36 conf |= HS20_DGAF_DISABLED; 37 *eid++ = conf; 38 if (hapd->conf->hs20_release >= 2) { 39 WPA_PUT_LE16(eid, hapd->conf->anqp_domain_id); 40 eid += 2; 41 } 42 43 return eid; 44 } 45 46 47 u8 * hostapd_eid_osen(struct hostapd_data *hapd, u8 *eid) 48 { 49 u8 *len; 50 u16 capab; 51 52 if (!hapd->conf->osen) 53 return eid; 54 55 *eid++ = WLAN_EID_VENDOR_SPECIFIC; 56 len = eid++; /* to be filled */ 57 WPA_PUT_BE24(eid, OUI_WFA); 58 eid += 3; 59 *eid++ = HS20_OSEN_OUI_TYPE; 60 61 /* Group Data Cipher Suite */ 62 RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 63 eid += RSN_SELECTOR_LEN; 64 65 /* Pairwise Cipher Suite Count and List */ 66 WPA_PUT_LE16(eid, 1); 67 eid += 2; 68 RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP); 69 eid += RSN_SELECTOR_LEN; 70 71 /* AKM Suite Count and List */ 72 WPA_PUT_LE16(eid, 1); 73 eid += 2; 74 RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN); 75 eid += RSN_SELECTOR_LEN; 76 77 /* RSN Capabilities */ 78 capab = 0; 79 if (hapd->conf->wmm_enabled) { 80 /* 4 PTKSA replay counters when using WMM */ 81 capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); 82 } 83 #ifdef CONFIG_IEEE80211W 84 if (hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 85 capab |= WPA_CAPABILITY_MFPC; 86 if (hapd->conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) 87 capab |= WPA_CAPABILITY_MFPR; 88 } 89 #endif /* CONFIG_IEEE80211W */ 90 #ifdef CONFIG_OCV 91 if (hapd->conf->ocv) 92 capab |= WPA_CAPABILITY_OCVC; 93 #endif /* CONFIG_OCV */ 94 WPA_PUT_LE16(eid, capab); 95 eid += 2; 96 97 *len = eid - len - 1; 98 99 return eid; 100 } 101 102 103 int hs20_send_wnm_notification(struct hostapd_data *hapd, const u8 *addr, 104 u8 osu_method, const char *url) 105 { 106 struct wpabuf *buf; 107 size_t len = 0; 108 int ret; 109 110 /* TODO: should refuse to send notification if the STA is not associated 111 * or if the STA did not indicate support for WNM-Notification */ 112 113 if (url) { 114 len = 1 + os_strlen(url); 115 if (5 + len > 255) { 116 wpa_printf(MSG_INFO, "HS 2.0: Too long URL for " 117 "WNM-Notification: '%s'", url); 118 return -1; 119 } 120 } 121 122 buf = wpabuf_alloc(4 + 7 + len); 123 if (buf == NULL) 124 return -1; 125 126 wpabuf_put_u8(buf, WLAN_ACTION_WNM); 127 wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); 128 wpabuf_put_u8(buf, 1); /* Dialog token */ 129 wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ 130 131 /* Subscription Remediation subelement */ 132 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 133 wpabuf_put_u8(buf, 5 + len); 134 wpabuf_put_be24(buf, OUI_WFA); 135 wpabuf_put_u8(buf, HS20_WNM_SUB_REM_NEEDED); 136 if (url) { 137 wpabuf_put_u8(buf, len - 1); 138 wpabuf_put_data(buf, url, len - 1); 139 wpabuf_put_u8(buf, osu_method); 140 } else { 141 /* Server URL and Server Method fields not included */ 142 wpabuf_put_u8(buf, 0); 143 } 144 145 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 146 wpabuf_head(buf), wpabuf_len(buf)); 147 148 wpabuf_free(buf); 149 150 return ret; 151 } 152 153 154 int hs20_send_wnm_notification_deauth_req(struct hostapd_data *hapd, 155 const u8 *addr, 156 const struct wpabuf *payload) 157 { 158 struct wpabuf *buf; 159 int ret; 160 161 /* TODO: should refuse to send notification if the STA is not associated 162 * or if the STA did not indicate support for WNM-Notification */ 163 164 buf = wpabuf_alloc(4 + 6 + wpabuf_len(payload)); 165 if (buf == NULL) 166 return -1; 167 168 wpabuf_put_u8(buf, WLAN_ACTION_WNM); 169 wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); 170 wpabuf_put_u8(buf, 1); /* Dialog token */ 171 wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ 172 173 /* Deauthentication Imminent Notice subelement */ 174 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 175 wpabuf_put_u8(buf, 4 + wpabuf_len(payload)); 176 wpabuf_put_be24(buf, OUI_WFA); 177 wpabuf_put_u8(buf, HS20_WNM_DEAUTH_IMMINENT_NOTICE); 178 wpabuf_put_buf(buf, payload); 179 180 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 181 wpabuf_head(buf), wpabuf_len(buf)); 182 183 wpabuf_free(buf); 184 185 return ret; 186 } 187 188 189 int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd, 190 const u8 *addr, const char *url) 191 { 192 struct wpabuf *buf; 193 int ret; 194 size_t url_len; 195 196 if (!url) { 197 wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available"); 198 return -1; 199 } 200 201 url_len = os_strlen(url); 202 if (5 + url_len > 255) { 203 wpa_printf(MSG_INFO, 204 "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'", 205 url); 206 return -1; 207 } 208 209 buf = wpabuf_alloc(4 + 7 + url_len); 210 if (!buf) 211 return -1; 212 213 wpabuf_put_u8(buf, WLAN_ACTION_WNM); 214 wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); 215 wpabuf_put_u8(buf, 1); /* Dialog token */ 216 wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */ 217 218 /* Terms and Conditions Acceptance subelement */ 219 wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); 220 wpabuf_put_u8(buf, 4 + 1 + url_len); 221 wpabuf_put_be24(buf, OUI_WFA); 222 wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE); 223 wpabuf_put_u8(buf, url_len); 224 wpabuf_put_str(buf, url); 225 226 ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr, 227 wpabuf_head(buf), wpabuf_len(buf)); 228 229 wpabuf_free(buf); 230 231 return ret; 232 } 233 234 235 void hs20_t_c_filtering(struct hostapd_data *hapd, struct sta_info *sta, 236 int enabled) 237 { 238 if (enabled) { 239 wpa_printf(MSG_DEBUG, 240 "HS 2.0: Terms and Conditions filtering required for " 241 MACSTR, MAC2STR(sta->addr)); 242 sta->hs20_t_c_filtering = 1; 243 /* TODO: Enable firewall filtering for the STA */ 244 wpa_msg(hapd->msg_ctx, MSG_INFO, HS20_T_C_FILTERING_ADD MACSTR, 245 MAC2STR(sta->addr)); 246 } else { 247 wpa_printf(MSG_DEBUG, 248 "HS 2.0: Terms and Conditions filtering not required for " 249 MACSTR, MAC2STR(sta->addr)); 250 sta->hs20_t_c_filtering = 0; 251 /* TODO: Disable firewall filtering for the STA */ 252 wpa_msg(hapd->msg_ctx, MSG_INFO, 253 HS20_T_C_FILTERING_REMOVE MACSTR, MAC2STR(sta->addr)); 254 } 255 } 256