• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * hostapd / IEEE 802.11 Management
3  * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "common/ocv.h"
14 #include "hostapd.h"
15 #include "sta_info.h"
16 #include "ap_config.h"
17 #include "ap_drv_ops.h"
18 #include "wpa_auth.h"
19 #include "ieee802_11.h"
20 
21 
hostapd_eid_assoc_comeback_time(struct hostapd_data * hapd,struct sta_info * sta,u8 * eid)22 u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd,
23 				     struct sta_info *sta, u8 *eid)
24 {
25 	u8 *pos = eid;
26 	u32 timeout, tu;
27 	struct os_reltime now, passed;
28 
29 	*pos++ = WLAN_EID_TIMEOUT_INTERVAL;
30 	*pos++ = 5;
31 	*pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK;
32 	os_get_reltime(&now);
33 	os_reltime_sub(&now, &sta->sa_query_start, &passed);
34 	tu = (passed.sec * 1000000 + passed.usec) / 1024;
35 	if (hapd->conf->assoc_sa_query_max_timeout > tu)
36 		timeout = hapd->conf->assoc_sa_query_max_timeout - tu;
37 	else
38 		timeout = 0;
39 	if (timeout < hapd->conf->assoc_sa_query_max_timeout)
40 		timeout++; /* add some extra time for local timers */
41 	WPA_PUT_LE32(pos, timeout);
42 	pos += 4;
43 
44 	return pos;
45 }
46 
47 
48 /* MLME-SAQuery.request */
ieee802_11_send_sa_query_req(struct hostapd_data * hapd,const u8 * addr,const u8 * trans_id)49 void ieee802_11_send_sa_query_req(struct hostapd_data *hapd,
50 				  const u8 *addr, const u8 *trans_id)
51 {
52 #ifdef CONFIG_OCV
53 	struct sta_info *sta;
54 #endif /* CONFIG_OCV */
55 	struct ieee80211_mgmt *mgmt;
56 	u8 *oci_ie = NULL;
57 	u8 oci_ie_len = 0;
58 	u8 *end;
59 
60 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to "
61 		   MACSTR, MAC2STR(addr));
62 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
63 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
64 
65 #ifdef CONFIG_OCV
66 	sta = ap_get_sta(hapd, addr);
67 	if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
68 		struct wpa_channel_info ci;
69 
70 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
71 			wpa_printf(MSG_WARNING,
72 				   "Failed to get channel info for OCI element in SA Query Request");
73 			return;
74 		}
75 
76 		oci_ie_len = OCV_OCI_EXTENDED_LEN;
77 		oci_ie = os_zalloc(oci_ie_len);
78 		if (!oci_ie) {
79 			wpa_printf(MSG_WARNING,
80 				   "Failed to allocate buffer for OCI element in SA Query Request");
81 			return;
82 		}
83 
84 		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
85 			os_free(oci_ie);
86 			return;
87 		}
88 	}
89 #endif /* CONFIG_OCV */
90 
91 	mgmt = os_zalloc(sizeof(*mgmt) + oci_ie_len);
92 	if (!mgmt) {
93 		wpa_printf(MSG_DEBUG,
94 			   "Failed to allocate buffer for SA Query Response frame");
95 		os_free(oci_ie);
96 		return;
97 	}
98 
99 	mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
100 					   WLAN_FC_STYPE_ACTION);
101 	os_memcpy(mgmt->da, addr, ETH_ALEN);
102 	os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
103 	os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
104 	mgmt->u.action.category = WLAN_ACTION_SA_QUERY;
105 	mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST;
106 	os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id,
107 		  WLAN_SA_QUERY_TR_ID_LEN);
108 	end = mgmt->u.action.u.sa_query_req.variable;
109 #ifdef CONFIG_OCV
110 	if (oci_ie_len > 0) {
111 		os_memcpy(end, oci_ie, oci_ie_len);
112 		end += oci_ie_len;
113 	}
114 #endif /* CONFIG_OCV */
115 	if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0, NULL, 0, 0)
116 	    < 0)
117 		wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed");
118 
119 	os_free(mgmt);
120 	os_free(oci_ie);
121 }
122 
123 
ieee802_11_send_sa_query_resp(struct hostapd_data * hapd,const u8 * sa,const u8 * trans_id)124 static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd,
125 					  const u8 *sa, const u8 *trans_id)
126 {
127 	struct sta_info *sta;
128 	struct ieee80211_mgmt *resp;
129 	u8 *oci_ie = NULL;
130 	u8 oci_ie_len = 0;
131 	u8 *end;
132 
133 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from "
134 		   MACSTR, MAC2STR(sa));
135 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
136 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
137 
138 	sta = ap_get_sta(hapd, sa);
139 	if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
140 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request "
141 			   "from unassociated STA " MACSTR, MAC2STR(sa));
142 		return;
143 	}
144 
145 #ifdef CONFIG_OCV
146 	if (wpa_auth_uses_ocv(sta->wpa_sm)) {
147 		struct wpa_channel_info ci;
148 
149 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
150 			wpa_printf(MSG_WARNING,
151 				   "Failed to get channel info for OCI element in SA Query Response");
152 			return;
153 		}
154 
155 		oci_ie_len = OCV_OCI_EXTENDED_LEN;
156 		oci_ie = os_zalloc(oci_ie_len);
157 		if (!oci_ie) {
158 			wpa_printf(MSG_WARNING,
159 				   "Failed to allocate buffer for for OCI element in SA Query Response");
160 			return;
161 		}
162 
163 		if (ocv_insert_extended_oci(&ci, oci_ie) < 0) {
164 			os_free(oci_ie);
165 			return;
166 		}
167 	}
168 #endif /* CONFIG_OCV */
169 
170 	resp = os_zalloc(sizeof(*resp) + oci_ie_len);
171 	if (!resp) {
172 		wpa_printf(MSG_DEBUG,
173 			   "Failed to allocate buffer for SA Query Response frame");
174 		os_free(oci_ie);
175 		return;
176 	}
177 
178 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to "
179 		   MACSTR, MAC2STR(sa));
180 
181 	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
182 					   WLAN_FC_STYPE_ACTION);
183 	os_memcpy(resp->da, sa, ETH_ALEN);
184 	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
185 	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
186 	resp->u.action.category = WLAN_ACTION_SA_QUERY;
187 	resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE;
188 	os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id,
189 		  WLAN_SA_QUERY_TR_ID_LEN);
190 	end = resp->u.action.u.sa_query_req.variable;
191 #ifdef CONFIG_OCV
192 	if (oci_ie_len > 0) {
193 		os_memcpy(end, oci_ie, oci_ie_len);
194 		end += oci_ie_len;
195 	}
196 #endif /* CONFIG_OCV */
197 	if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0, NULL, 0, 0)
198 	    < 0)
199 		wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed");
200 
201 	os_free(resp);
202 	os_free(oci_ie);
203 }
204 
205 
ieee802_11_sa_query_action(struct hostapd_data * hapd,const struct ieee80211_mgmt * mgmt,size_t len)206 void ieee802_11_sa_query_action(struct hostapd_data *hapd,
207 				const struct ieee80211_mgmt *mgmt,
208 				size_t len)
209 {
210 	struct sta_info *sta;
211 	int i;
212 	const u8 *sa = mgmt->sa;
213 	const u8 action_type = mgmt->u.action.u.sa_query_resp.action;
214 	const u8 *trans_id = mgmt->u.action.u.sa_query_resp.trans_id;
215 
216 	if (((const u8 *) mgmt) + len <
217 	    mgmt->u.action.u.sa_query_resp.variable) {
218 		wpa_printf(MSG_DEBUG,
219 			   "IEEE 802.11: Too short SA Query Action frame (len=%lu)",
220 			   (unsigned long) len);
221 		return;
222 	}
223 
224 	sta = ap_get_sta(hapd, sa);
225 
226 #ifdef CONFIG_OCV
227 	if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) {
228 		struct ieee802_11_elems elems;
229 		struct wpa_channel_info ci;
230 		int tx_chanwidth;
231 		int tx_seg1_idx;
232 		size_t ies_len;
233 		const u8 *ies;
234 
235 		ies = mgmt->u.action.u.sa_query_resp.variable;
236 		ies_len = len - (ies - (u8 *) mgmt);
237 		if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) ==
238 		    ParseFailed) {
239 			wpa_printf(MSG_DEBUG,
240 				   "SA Query: Failed to parse elements");
241 			return;
242 		}
243 
244 		if (hostapd_drv_channel_info(hapd, &ci) != 0) {
245 			wpa_printf(MSG_WARNING,
246 				   "Failed to get channel info to validate received OCI in SA Query Action frame");
247 			return;
248 		}
249 
250 		if (get_sta_tx_parameters(sta->wpa_sm,
251 					  channel_width_to_int(ci.chanwidth),
252 					  ci.seg1_idx, &tx_chanwidth,
253 					  &tx_seg1_idx) < 0)
254 			return;
255 
256 		if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
257 					 tx_chanwidth, tx_seg1_idx) != 0) {
258 			wpa_printf(MSG_WARNING, "%s", ocv_errorstr);
259 			return;
260 		}
261 	}
262 #endif /* CONFIG_OCV */
263 
264 	if (action_type == WLAN_SA_QUERY_REQUEST) {
265 		ieee802_11_send_sa_query_resp(hapd, sa, trans_id);
266 		return;
267 	}
268 
269 	if (action_type != WLAN_SA_QUERY_RESPONSE) {
270 		wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query "
271 			   "Action %d", action_type);
272 		return;
273 	}
274 
275 	wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from "
276 		   MACSTR, MAC2STR(sa));
277 	wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID",
278 		    trans_id, WLAN_SA_QUERY_TR_ID_LEN);
279 
280 	/* MLME-SAQuery.confirm */
281 
282 	if (sta == NULL || sta->sa_query_trans_id == NULL) {
283 		wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with "
284 			   "pending SA Query request found");
285 		return;
286 	}
287 
288 	for (i = 0; i < sta->sa_query_count; i++) {
289 		if (os_memcmp(sta->sa_query_trans_id +
290 			      i * WLAN_SA_QUERY_TR_ID_LEN,
291 			      trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0)
292 			break;
293 	}
294 
295 	if (i >= sta->sa_query_count) {
296 		wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query "
297 			   "transaction identifier found");
298 		return;
299 	}
300 
301 	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
302 		       HOSTAPD_LEVEL_DEBUG,
303 		       "Reply to pending SA Query received");
304 	ap_sta_stop_sa_query(hapd, sta);
305 }
306 
307 
hostapd_ext_capab_byte(struct hostapd_data * hapd,u8 * pos,int idx)308 static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
309 {
310 	*pos = 0x00;
311 
312 	switch (idx) {
313 	case 0: /* Bits 0-7 */
314 		if (hapd->iconf->obss_interval)
315 			*pos |= 0x01; /* Bit 0 - Coexistence management */
316 		if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)
317 			*pos |= 0x04; /* Bit 2 - Extended Channel Switching */
318 		break;
319 	case 1: /* Bits 8-15 */
320 		if (hapd->conf->proxy_arp)
321 			*pos |= 0x10; /* Bit 12 - Proxy ARP */
322 		if (hapd->conf->coloc_intf_reporting) {
323 			/* Bit 13 - Collocated Interference Reporting */
324 			*pos |= 0x20;
325 		}
326 		break;
327 	case 2: /* Bits 16-23 */
328 		if (hapd->conf->wnm_sleep_mode)
329 			*pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */
330 		if (hapd->conf->bss_transition)
331 			*pos |= 0x08; /* Bit 19 - BSS Transition */
332 		break;
333 	case 3: /* Bits 24-31 */
334 #ifdef CONFIG_WNM_AP
335 		*pos |= 0x02; /* Bit 25 - SSID List */
336 #endif /* CONFIG_WNM_AP */
337 		if (hapd->conf->time_advertisement == 2)
338 			*pos |= 0x08; /* Bit 27 - UTC TSF Offset */
339 		if (hapd->conf->interworking)
340 			*pos |= 0x80; /* Bit 31 - Interworking */
341 		break;
342 	case 4: /* Bits 32-39 */
343 		if (hapd->conf->qos_map_set_len)
344 			*pos |= 0x01; /* Bit 32 - QoS Map */
345 		if (hapd->conf->tdls & TDLS_PROHIBIT)
346 			*pos |= 0x40; /* Bit 38 - TDLS Prohibited */
347 		if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) {
348 			/* Bit 39 - TDLS Channel Switching Prohibited */
349 			*pos |= 0x80;
350 		}
351 		break;
352 	case 5: /* Bits 40-47 */
353 #ifdef CONFIG_HS20
354 		if (hapd->conf->hs20)
355 			*pos |= 0x40; /* Bit 46 - WNM-Notification */
356 #endif /* CONFIG_HS20 */
357 #ifdef CONFIG_MBO
358 		if (hapd->conf->mbo_enabled)
359 			*pos |= 0x40; /* Bit 46 - WNM-Notification */
360 #endif /* CONFIG_MBO */
361 		break;
362 	case 6: /* Bits 48-55 */
363 		if (hapd->conf->ssid.utf8_ssid)
364 			*pos |= 0x01; /* Bit 48 - UTF-8 SSID */
365 		break;
366 	case 7: /* Bits 56-63 */
367 		break;
368 	case 8: /* Bits 64-71 */
369 		if (hapd->conf->ftm_responder)
370 			*pos |= 0x40; /* Bit 70 - FTM responder */
371 		if (hapd->conf->ftm_initiator)
372 			*pos |= 0x80; /* Bit 71 - FTM initiator */
373 		break;
374 	case 9: /* Bits 72-79 */
375 #ifdef CONFIG_FILS
376 		if ((hapd->conf->wpa & WPA_PROTO_RSN) &&
377 		    wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
378 			*pos |= 0x01;
379 #endif /* CONFIG_FILS */
380 #ifdef CONFIG_IEEE80211AX
381 		if (hapd->iconf->ieee80211ax &&
382 		    hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
383 			*pos |= 0x40; /* Bit 78 - TWT responder */
384 #endif /* CONFIG_IEEE80211AX */
385 		break;
386 	case 10: /* Bits 80-87 */
387 #ifdef CONFIG_SAE
388 		if (hapd->conf->wpa &&
389 		    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
390 			int in_use = hostapd_sae_pw_id_in_use(hapd->conf);
391 
392 			if (in_use)
393 				*pos |= 0x02; /* Bit 81 - SAE Password
394 					       * Identifiers In Use */
395 			if (in_use == 2)
396 				*pos |= 0x04; /* Bit 82 - SAE Password
397 					       * Identifiers Used Exclusively */
398 		}
399 #endif /* CONFIG_SAE */
400 		if (hapd->conf->beacon_prot)
401 			*pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */
402 		break;
403 	}
404 }
405 
406 
hostapd_eid_ext_capab(struct hostapd_data * hapd,u8 * eid)407 u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
408 {
409 	u8 *pos = eid;
410 	u8 len = 0, i;
411 
412 	if (hapd->conf->qos_map_set_len ||
413 	    (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)))
414 		len = 5;
415 	if (len < 4 &&
416 	    (hapd->conf->time_advertisement == 2 || hapd->conf->interworking))
417 		len = 4;
418 	if (len < 3 &&
419 	    (hapd->conf->wnm_sleep_mode || hapd->conf->bss_transition))
420 		len = 3;
421 	if (len < 1 &&
422 	    (hapd->iconf->obss_interval ||
423 	     (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)))
424 		len = 1;
425 	if (len < 2 &&
426 	    (hapd->conf->proxy_arp || hapd->conf->coloc_intf_reporting))
427 		len = 2;
428 	if (len < 7 && hapd->conf->ssid.utf8_ssid)
429 		len = 7;
430 	if (len < 9 &&
431 	    (hapd->conf->ftm_initiator || hapd->conf->ftm_responder))
432 		len = 9;
433 #ifdef CONFIG_WNM_AP
434 	if (len < 4)
435 		len = 4;
436 #endif /* CONFIG_WNM_AP */
437 #ifdef CONFIG_HS20
438 	if (hapd->conf->hs20 && len < 6)
439 		len = 6;
440 #endif /* CONFIG_HS20 */
441 #ifdef CONFIG_MBO
442 	if (hapd->conf->mbo_enabled && len < 6)
443 		len = 6;
444 #endif /* CONFIG_MBO */
445 #ifdef CONFIG_FILS
446 	if ((!(hapd->conf->wpa & WPA_PROTO_RSN) ||
447 	     !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10)
448 		len = 10;
449 #endif /* CONFIG_FILS */
450 #ifdef CONFIG_IEEE80211AX
451 	if (len < 10 && hapd->iconf->ieee80211ax &&
452 	    hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP))
453 		len = 10;
454 #endif /* CONFIG_IEEE80211AX */
455 #ifdef CONFIG_SAE
456 	if (len < 11 && hapd->conf->wpa &&
457 	    wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
458 	    hostapd_sae_pw_id_in_use(hapd->conf))
459 		len = 11;
460 #endif /* CONFIG_SAE */
461 	if (len < 11 && hapd->conf->beacon_prot)
462 		len = 11;
463 	if (len < hapd->iface->extended_capa_len)
464 		len = hapd->iface->extended_capa_len;
465 	if (len == 0)
466 		return eid;
467 
468 	*pos++ = WLAN_EID_EXT_CAPAB;
469 	*pos++ = len;
470 	for (i = 0; i < len; i++, pos++) {
471 		hostapd_ext_capab_byte(hapd, pos, i);
472 
473 		if (i < hapd->iface->extended_capa_len) {
474 			*pos &= ~hapd->iface->extended_capa_mask[i];
475 			*pos |= hapd->iface->extended_capa[i];
476 		}
477 	}
478 
479 	while (len > 0 && eid[1 + len] == 0) {
480 		len--;
481 		eid[1] = len;
482 	}
483 	if (len == 0)
484 		return eid;
485 
486 	return eid + 2 + len;
487 }
488 
489 
hostapd_eid_qos_map_set(struct hostapd_data * hapd,u8 * eid)490 u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid)
491 {
492 	u8 *pos = eid;
493 	u8 len = hapd->conf->qos_map_set_len;
494 
495 	if (!len)
496 		return eid;
497 
498 	*pos++ = WLAN_EID_QOS_MAP_SET;
499 	*pos++ = len;
500 	os_memcpy(pos, hapd->conf->qos_map_set, len);
501 	pos += len;
502 
503 	return pos;
504 }
505 
506 
hostapd_eid_interworking(struct hostapd_data * hapd,u8 * eid)507 u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid)
508 {
509 	u8 *pos = eid;
510 #ifdef CONFIG_INTERWORKING
511 	u8 *len;
512 
513 	if (!hapd->conf->interworking)
514 		return eid;
515 
516 	*pos++ = WLAN_EID_INTERWORKING;
517 	len = pos++;
518 
519 	*pos = hapd->conf->access_network_type;
520 	if (hapd->conf->internet)
521 		*pos |= INTERWORKING_ANO_INTERNET;
522 	if (hapd->conf->asra)
523 		*pos |= INTERWORKING_ANO_ASRA;
524 	if (hapd->conf->esr)
525 		*pos |= INTERWORKING_ANO_ESR;
526 	if (hapd->conf->uesa)
527 		*pos |= INTERWORKING_ANO_UESA;
528 	pos++;
529 
530 	if (hapd->conf->venue_info_set) {
531 		*pos++ = hapd->conf->venue_group;
532 		*pos++ = hapd->conf->venue_type;
533 	}
534 
535 	if (!is_zero_ether_addr(hapd->conf->hessid)) {
536 		os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
537 		pos += ETH_ALEN;
538 	}
539 
540 	*len = pos - len - 1;
541 #endif /* CONFIG_INTERWORKING */
542 
543 	return pos;
544 }
545 
546 
hostapd_eid_adv_proto(struct hostapd_data * hapd,u8 * eid)547 u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid)
548 {
549 	u8 *pos = eid;
550 #ifdef CONFIG_INTERWORKING
551 
552 	/* TODO: Separate configuration for ANQP? */
553 	if (!hapd->conf->interworking)
554 		return eid;
555 
556 	*pos++ = WLAN_EID_ADV_PROTO;
557 	*pos++ = 2;
558 	*pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */
559 	*pos++ = ACCESS_NETWORK_QUERY_PROTOCOL;
560 #endif /* CONFIG_INTERWORKING */
561 
562 	return pos;
563 }
564 
565 
hostapd_eid_roaming_consortium(struct hostapd_data * hapd,u8 * eid)566 u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid)
567 {
568 	u8 *pos = eid;
569 #ifdef CONFIG_INTERWORKING
570 	u8 *len;
571 	unsigned int i, count;
572 
573 	if (!hapd->conf->interworking ||
574 	    hapd->conf->roaming_consortium == NULL ||
575 	    hapd->conf->roaming_consortium_count == 0)
576 		return eid;
577 
578 	*pos++ = WLAN_EID_ROAMING_CONSORTIUM;
579 	len = pos++;
580 
581 	/* Number of ANQP OIs (in addition to the max 3 listed here) */
582 	if (hapd->conf->roaming_consortium_count > 3 + 255)
583 		*pos++ = 255;
584 	else if (hapd->conf->roaming_consortium_count > 3)
585 		*pos++ = hapd->conf->roaming_consortium_count - 3;
586 	else
587 		*pos++ = 0;
588 
589 	/* OU #1 and #2 Lengths */
590 	*pos = hapd->conf->roaming_consortium[0].len;
591 	if (hapd->conf->roaming_consortium_count > 1)
592 		*pos |= hapd->conf->roaming_consortium[1].len << 4;
593 	pos++;
594 
595 	if (hapd->conf->roaming_consortium_count > 3)
596 		count = 3;
597 	else
598 		count = hapd->conf->roaming_consortium_count;
599 
600 	for (i = 0; i < count; i++) {
601 		os_memcpy(pos, hapd->conf->roaming_consortium[i].oi,
602 			  hapd->conf->roaming_consortium[i].len);
603 		pos += hapd->conf->roaming_consortium[i].len;
604 	}
605 
606 	*len = pos - len - 1;
607 #endif /* CONFIG_INTERWORKING */
608 
609 	return pos;
610 }
611 
612 
hostapd_eid_time_adv(struct hostapd_data * hapd,u8 * eid)613 u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid)
614 {
615 	if (hapd->conf->time_advertisement != 2)
616 		return eid;
617 
618 	if (hapd->time_adv == NULL &&
619 	    hostapd_update_time_adv(hapd) < 0)
620 		return eid;
621 
622 	if (hapd->time_adv == NULL)
623 		return eid;
624 
625 	os_memcpy(eid, wpabuf_head(hapd->time_adv),
626 		  wpabuf_len(hapd->time_adv));
627 	eid += wpabuf_len(hapd->time_adv);
628 
629 	return eid;
630 }
631 
632 
hostapd_eid_time_zone(struct hostapd_data * hapd,u8 * eid)633 u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid)
634 {
635 	size_t len;
636 
637 	if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone)
638 		return eid;
639 
640 	len = os_strlen(hapd->conf->time_zone);
641 
642 	*eid++ = WLAN_EID_TIME_ZONE;
643 	*eid++ = len;
644 	os_memcpy(eid, hapd->conf->time_zone, len);
645 	eid += len;
646 
647 	return eid;
648 }
649 
650 
hostapd_update_time_adv(struct hostapd_data * hapd)651 int hostapd_update_time_adv(struct hostapd_data *hapd)
652 {
653 	const int elen = 2 + 1 + 10 + 5 + 1;
654 	struct os_time t;
655 	struct os_tm tm;
656 	u8 *pos;
657 
658 	if (hapd->conf->time_advertisement != 2)
659 		return 0;
660 
661 	if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0)
662 		return -1;
663 
664 	if (!hapd->time_adv) {
665 		hapd->time_adv = wpabuf_alloc(elen);
666 		if (hapd->time_adv == NULL)
667 			return -1;
668 		pos = wpabuf_put(hapd->time_adv, elen);
669 	} else
670 		pos = wpabuf_mhead_u8(hapd->time_adv);
671 
672 	*pos++ = WLAN_EID_TIME_ADVERTISEMENT;
673 	*pos++ = 1 + 10 + 5 + 1;
674 
675 	*pos++ = 2; /* UTC time at which the TSF timer is 0 */
676 
677 	/* Time Value at TSF 0 */
678 	/* FIX: need to calculate this based on the current TSF value */
679 	WPA_PUT_LE16(pos, tm.year); /* Year */
680 	pos += 2;
681 	*pos++ = tm.month; /* Month */
682 	*pos++ = tm.day; /* Day of month */
683 	*pos++ = tm.hour; /* Hours */
684 	*pos++ = tm.min; /* Minutes */
685 	*pos++ = tm.sec; /* Seconds */
686 	WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */
687 	pos += 2;
688 	*pos++ = 0; /* Reserved */
689 
690 	/* Time Error */
691 	/* TODO: fill in an estimate on the error */
692 	*pos++ = 0;
693 	*pos++ = 0;
694 	*pos++ = 0;
695 	*pos++ = 0;
696 	*pos++ = 0;
697 
698 	*pos++ = hapd->time_update_counter++;
699 
700 	return 0;
701 }
702 
703 
hostapd_eid_bss_max_idle_period(struct hostapd_data * hapd,u8 * eid)704 u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid)
705 {
706 	u8 *pos = eid;
707 
708 #ifdef CONFIG_WNM_AP
709 	if (hapd->conf->ap_max_inactivity > 0) {
710 		unsigned int val;
711 		*pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD;
712 		*pos++ = 3;
713 		val = hapd->conf->ap_max_inactivity;
714 		if (val > 68000)
715 			val = 68000;
716 		val *= 1000;
717 		val /= 1024;
718 		if (val == 0)
719 			val = 1;
720 		if (val > 65535)
721 			val = 65535;
722 		WPA_PUT_LE16(pos, val);
723 		pos += 2;
724 		*pos++ = 0x00; /* TODO: Protected Keep-Alive Required */
725 	}
726 #endif /* CONFIG_WNM_AP */
727 
728 	return pos;
729 }
730 
731 
732 #ifdef CONFIG_MBO
733 
hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data * hapd,u8 * eid,size_t len,int delta)734 u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid,
735 				    size_t len, int delta)
736 {
737 	u8 mbo[4];
738 
739 	mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT;
740 	mbo[1] = 2;
741 	/* Delta RSSI */
742 	mbo[2] = delta;
743 	/* Retry delay */
744 	mbo[3] = hapd->iconf->rssi_reject_assoc_timeout;
745 
746 	return eid + mbo_add_ie(eid, len, mbo, 4);
747 }
748 
749 
hostapd_eid_mbo(struct hostapd_data * hapd,u8 * eid,size_t len)750 u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
751 {
752 	u8 mbo[9], *mbo_pos = mbo;
753 	u8 *pos = eid;
754 
755 	if (!hapd->conf->mbo_enabled &&
756 	    !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
757 		return eid;
758 
759 	if (hapd->conf->mbo_enabled) {
760 		*mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND;
761 		*mbo_pos++ = 1;
762 		/* Not Cellular aware */
763 		*mbo_pos++ = 0;
764 	}
765 
766 	if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
767 		*mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW;
768 		*mbo_pos++ = 1;
769 		*mbo_pos++ = hapd->mbo_assoc_disallow;
770 	}
771 
772 	if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
773 		u8 ctrl;
774 
775 		ctrl = OCE_RELEASE;
776 		if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
777 			ctrl |= OCE_IS_STA_CFON;
778 
779 		*mbo_pos++ = OCE_ATTR_ID_CAPA_IND;
780 		*mbo_pos++ = 1;
781 		*mbo_pos++ = ctrl;
782 	}
783 
784 	pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo);
785 
786 	return pos;
787 }
788 
789 
hostapd_mbo_ie_len(struct hostapd_data * hapd)790 u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
791 {
792 	u8 len;
793 
794 	if (!hapd->conf->mbo_enabled &&
795 	    !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
796 		return 0;
797 
798 	/*
799 	 * MBO IE header (6) + Capability Indication attribute (3) +
800 	 * Association Disallowed attribute (3) = 12
801 	 */
802 	len = 6;
803 	if (hapd->conf->mbo_enabled)
804 		len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
805 
806 	/* OCE capability indication attribute (3) */
807 	if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd))
808 		len += 3;
809 
810 	return len;
811 }
812 
813 #endif /* CONFIG_MBO */
814 
815 
816 #ifdef CONFIG_OWE
hostapd_eid_owe_trans_enabled(struct hostapd_data * hapd)817 static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd)
818 {
819 	return hapd->conf->owe_transition_ssid_len > 0 &&
820 		!is_zero_ether_addr(hapd->conf->owe_transition_bssid);
821 }
822 #endif /* CONFIG_OWE */
823 
824 
hostapd_eid_owe_trans_len(struct hostapd_data * hapd)825 size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd)
826 {
827 #ifdef CONFIG_OWE
828 	if (!hostapd_eid_owe_trans_enabled(hapd))
829 		return 0;
830 	return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len;
831 #else /* CONFIG_OWE */
832 	return 0;
833 #endif /* CONFIG_OWE */
834 }
835 
836 
hostapd_eid_owe_trans(struct hostapd_data * hapd,u8 * eid,size_t len)837 u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid,
838 				  size_t len)
839 {
840 #ifdef CONFIG_OWE
841 	u8 *pos = eid;
842 	size_t elen;
843 
844 	if (hapd->conf->owe_transition_ifname[0] &&
845 	    !hostapd_eid_owe_trans_enabled(hapd))
846 		hostapd_owe_trans_get_info(hapd);
847 
848 	if (!hostapd_eid_owe_trans_enabled(hapd))
849 		return pos;
850 
851 	elen = hostapd_eid_owe_trans_len(hapd);
852 	if (len < elen) {
853 		wpa_printf(MSG_DEBUG,
854 			   "OWE: Not enough room in the buffer for OWE IE");
855 		return pos;
856 	}
857 
858 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
859 	*pos++ = elen - 2;
860 	WPA_PUT_BE24(pos, OUI_WFA);
861 	pos += 3;
862 	*pos++ = OWE_OUI_TYPE;
863 	os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN);
864 	pos += ETH_ALEN;
865 	*pos++ = hapd->conf->owe_transition_ssid_len;
866 	os_memcpy(pos, hapd->conf->owe_transition_ssid,
867 		  hapd->conf->owe_transition_ssid_len);
868 	pos += hapd->conf->owe_transition_ssid_len;
869 
870 	return pos;
871 #else /* CONFIG_OWE */
872 	return eid;
873 #endif /* CONFIG_OWE */
874 }
875 
876 
hostapd_eid_dpp_cc_len(struct hostapd_data * hapd)877 size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd)
878 {
879 #ifdef CONFIG_DPP2
880 	if (hapd->conf->dpp_configurator_connectivity)
881 		return 6;
882 #endif /* CONFIG_DPP2 */
883 	return 0;
884 }
885 
886 
hostapd_eid_dpp_cc(struct hostapd_data * hapd,u8 * eid,size_t len)887 u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len)
888 {
889 	u8 *pos = eid;
890 
891 #ifdef CONFIG_DPP2
892 	if (!hapd->conf->dpp_configurator_connectivity || len < 6)
893 		return pos;
894 
895 	*pos++ = WLAN_EID_VENDOR_SPECIFIC;
896 	*pos++ = 4;
897 	WPA_PUT_BE24(pos, OUI_WFA);
898 	pos += 3;
899 	*pos++ = DPP_CC_OUI_TYPE;
900 #endif /* CONFIG_DPP2 */
901 
902 	return pos;
903 }
904 
905 
ap_copy_sta_supp_op_classes(struct sta_info * sta,const u8 * supp_op_classes,size_t supp_op_classes_len)906 void ap_copy_sta_supp_op_classes(struct sta_info *sta,
907 				 const u8 *supp_op_classes,
908 				 size_t supp_op_classes_len)
909 {
910 	if (!supp_op_classes)
911 		return;
912 	os_free(sta->supp_op_classes);
913 	sta->supp_op_classes = os_malloc(1 + supp_op_classes_len);
914 	if (!sta->supp_op_classes)
915 		return;
916 
917 	sta->supp_op_classes[0] = supp_op_classes_len;
918 	os_memcpy(sta->supp_op_classes + 1, supp_op_classes,
919 		  supp_op_classes_len);
920 }
921 
922 
hostapd_eid_fils_indic(struct hostapd_data * hapd,u8 * eid,int hessid)923 u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid)
924 {
925 	u8 *pos = eid;
926 #ifdef CONFIG_FILS
927 	u8 *len;
928 	u16 fils_info = 0;
929 	size_t realms;
930 	struct fils_realm *realm;
931 
932 	if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
933 	    !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt))
934 		return pos;
935 
936 	realms = dl_list_len(&hapd->conf->fils_realms);
937 	if (realms > 7)
938 		realms = 7; /* 3 bit count field limits this to max 7 */
939 
940 	*pos++ = WLAN_EID_FILS_INDICATION;
941 	len = pos++;
942 	/* TODO: B0..B2: Number of Public Key Identifiers */
943 	if (hapd->conf->erp_domain) {
944 		/* B3..B5: Number of Realm Identifiers */
945 		fils_info |= realms << 3;
946 	}
947 	/* TODO: B6: FILS IP Address Configuration */
948 	if (hapd->conf->fils_cache_id_set)
949 		fils_info |= BIT(7);
950 	if (hessid && !is_zero_ether_addr(hapd->conf->hessid))
951 		fils_info |= BIT(8); /* HESSID Included */
952 	/* FILS Shared Key Authentication without PFS Supported */
953 	fils_info |= BIT(9);
954 	if (hapd->conf->fils_dh_group) {
955 		/* FILS Shared Key Authentication with PFS Supported */
956 		fils_info |= BIT(10);
957 	}
958 	/* TODO: B11: FILS Public Key Authentication Supported */
959 	/* B12..B15: Reserved */
960 	WPA_PUT_LE16(pos, fils_info);
961 	pos += 2;
962 	if (hapd->conf->fils_cache_id_set) {
963 		os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN);
964 		pos += FILS_CACHE_ID_LEN;
965 	}
966 	if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) {
967 		os_memcpy(pos, hapd->conf->hessid, ETH_ALEN);
968 		pos += ETH_ALEN;
969 	}
970 
971 	dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm,
972 			 list) {
973 		if (realms == 0)
974 			break;
975 		realms--;
976 		os_memcpy(pos, realm->hash, 2);
977 		pos += 2;
978 	}
979 	*len = pos - len - 1;
980 #endif /* CONFIG_FILS */
981 
982 	return pos;
983 }
984 
985 
986 #ifdef CONFIG_OCV
get_tx_parameters(struct sta_info * sta,int ap_max_chanwidth,int ap_seg1_idx,int * bandwidth,int * seg1_idx)987 int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth,
988 		      int ap_seg1_idx, int *bandwidth, int *seg1_idx)
989 {
990 	int ht_40mhz = 0;
991 	int vht_80p80 = 0;
992 	int requested_bw;
993 
994 	if (sta->ht_capabilities)
995 		ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info &
996 			      HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET);
997 
998 	if (sta->vht_operation) {
999 		struct ieee80211_vht_operation *oper = sta->vht_operation;
1000 
1001 		/*
1002 		 * If a VHT Operation element was present, use it to determine
1003 		 * the supported channel bandwidth.
1004 		 */
1005 		if (oper->vht_op_info_chwidth == 0) {
1006 			requested_bw = ht_40mhz ? 40 : 20;
1007 		} else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) {
1008 			requested_bw = 80;
1009 		} else {
1010 			int diff;
1011 
1012 			requested_bw = 160;
1013 			diff = abs((int)
1014 				   oper->vht_op_info_chan_center_freq_seg0_idx -
1015 				   (int)
1016 				   oper->vht_op_info_chan_center_freq_seg1_idx);
1017 			vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx
1018 				!= 0 &&	diff > 16;
1019 		}
1020 	} else if (sta->vht_capabilities) {
1021 		struct ieee80211_vht_capabilities *capab;
1022 		int vht_chanwidth;
1023 
1024 		capab = sta->vht_capabilities;
1025 
1026 		/*
1027 		 * If only the VHT Capabilities element is present (e.g., for
1028 		 * normal clients), use it to determine the supported channel
1029 		 * bandwidth.
1030 		 */
1031 		vht_chanwidth = capab->vht_capabilities_info &
1032 			VHT_CAP_SUPP_CHAN_WIDTH_MASK;
1033 		vht_80p80 = capab->vht_capabilities_info &
1034 			VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
1035 
1036 		/* TODO: Also take into account Extended NSS BW Support field */
1037 		requested_bw = vht_chanwidth ? 160 : 80;
1038 	} else {
1039 		requested_bw = ht_40mhz ? 40 : 20;
1040 	}
1041 
1042 	*bandwidth = requested_bw < ap_max_chanwidth ?
1043 		requested_bw : ap_max_chanwidth;
1044 
1045 	*seg1_idx = 0;
1046 	if (ap_seg1_idx && vht_80p80)
1047 		*seg1_idx = ap_seg1_idx;
1048 
1049 	return 0;
1050 }
1051 #endif /* CONFIG_OCV */
1052 
1053 
hostapd_eid_rsnxe(struct hostapd_data * hapd,u8 * eid,size_t len)1054 u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len)
1055 {
1056 	u8 *pos = eid;
1057 
1058 	if (!(hapd->conf->wpa & WPA_PROTO_RSN) ||
1059 	    !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) ||
1060 	    (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 &&
1061 	     !hostapd_sae_pw_id_in_use(hapd->conf)) ||
1062 	    hapd->conf->sae_pwe == 3 ||
1063 	    len < 3)
1064 		return pos;
1065 
1066 	*pos++ = WLAN_EID_RSNX;
1067 	*pos++ = 1;
1068 	/* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is
1069 	 * used for now */
1070 	*pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E);
1071 
1072 	return pos;
1073 }
1074