1 /*
2  * NAN unsynchronized service discovery (USD)
3  * Copyright (c) 2024, Qualcomm Innovation Center, Inc.
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/nan_de.h"
13 #include "wpa_supplicant_i.h"
14 #include "offchannel.h"
15 #include "driver_i.h"
16 #include "notify.h"
17 #include "p2p_supplicant.h"
18 #include "nan_usd.h"
19 
20 
21 static const char *
tx_status_result_txt(enum offchannel_send_action_result result)22 tx_status_result_txt(enum offchannel_send_action_result result)
23 {
24 	switch (result) {
25 	case OFFCHANNEL_SEND_ACTION_SUCCESS:
26 		return "success";
27 	case OFFCHANNEL_SEND_ACTION_NO_ACK:
28 		return "no-ack";
29 	case OFFCHANNEL_SEND_ACTION_FAILED:
30 		return "failed";
31 	}
32 
33 	return "?";
34 }
35 
36 
wpas_nan_de_tx_status(struct wpa_supplicant * wpa_s,unsigned int freq,const u8 * dst,const u8 * src,const u8 * bssid,const u8 * data,size_t data_len,enum offchannel_send_action_result result)37 static void wpas_nan_de_tx_status(struct wpa_supplicant *wpa_s,
38 				  unsigned int freq, const u8 *dst,
39 				  const u8 *src, const u8 *bssid,
40 				  const u8 *data, size_t data_len,
41 				  enum offchannel_send_action_result result)
42 {
43 	if (!wpa_s->nan_de)
44 		return;
45 
46 	wpa_printf(MSG_DEBUG, "NAN: TX status A1=" MACSTR " A2=" MACSTR
47 		   " A3=" MACSTR " freq=%d len=%zu result=%s",
48 		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
49 		   data_len, tx_status_result_txt(result));
50 
51 	nan_de_tx_status(wpa_s->nan_de, freq, dst);
52 }
53 
54 
55 struct wpas_nan_usd_tx_work {
56 	unsigned int freq;
57 	unsigned int wait_time;
58 	u8 dst[ETH_ALEN];
59 	u8 src[ETH_ALEN];
60 	u8 bssid[ETH_ALEN];
61 	struct wpabuf *buf;
62 };
63 
64 
wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work * twork)65 static void wpas_nan_usd_tx_work_free(struct wpas_nan_usd_tx_work *twork)
66 {
67 	if (!twork)
68 		return;
69 	wpabuf_free(twork->buf);
70 	os_free(twork);
71 }
72 
73 
wpas_nan_usd_tx_work_done(struct wpa_supplicant * wpa_s)74 static void wpas_nan_usd_tx_work_done(struct wpa_supplicant *wpa_s)
75 {
76 	struct wpas_nan_usd_tx_work *twork;
77 
78 	if (!wpa_s->nan_usd_tx_work)
79 		return;
80 
81 	twork = wpa_s->nan_usd_tx_work->ctx;
82 	wpas_nan_usd_tx_work_free(twork);
83 	radio_work_done(wpa_s->nan_usd_tx_work);
84 	wpa_s->nan_usd_tx_work = NULL;
85 }
86 
87 
wpas_nan_de_tx_send(struct wpa_supplicant * wpa_s,unsigned int freq,unsigned int wait_time,const u8 * dst,const u8 * src,const u8 * bssid,const struct wpabuf * buf)88 static int wpas_nan_de_tx_send(struct wpa_supplicant *wpa_s, unsigned int freq,
89 			       unsigned int wait_time, const u8 *dst,
90 			       const u8 *src, const u8 *bssid,
91 			       const struct wpabuf *buf)
92 {
93 	wpa_printf(MSG_DEBUG, "NAN: TX NAN SDF A1=" MACSTR " A2=" MACSTR
94 		   " A3=" MACSTR " freq=%d len=%zu",
95 		   MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), freq,
96 		   wpabuf_len(buf));
97 
98 	return offchannel_send_action(wpa_s, freq, dst, src, bssid,
99 				      wpabuf_head(buf), wpabuf_len(buf),
100 				      wait_time, wpas_nan_de_tx_status, 1);
101 }
102 
103 
wpas_nan_usd_start_tx_cb(struct wpa_radio_work * work,int deinit)104 static void wpas_nan_usd_start_tx_cb(struct wpa_radio_work *work, int deinit)
105 {
106 	struct wpa_supplicant *wpa_s = work->wpa_s;
107 	struct wpas_nan_usd_tx_work *twork = work->ctx;
108 
109 	if (deinit) {
110 		if (work->started) {
111 			wpa_s->nan_usd_tx_work = NULL;
112 			offchannel_send_action_done(wpa_s);
113 		}
114 		wpas_nan_usd_tx_work_free(twork);
115 		return;
116 	}
117 
118 	wpa_s->nan_usd_tx_work = work;
119 
120 	if (wpas_nan_de_tx_send(wpa_s, twork->freq, twork->wait_time,
121 				twork->dst, twork->src, twork->bssid,
122 				twork->buf) < 0)
123 		wpas_nan_usd_tx_work_done(wpa_s);
124 }
125 
126 
wpas_nan_de_tx(void * ctx,unsigned int freq,unsigned int wait_time,const u8 * dst,const u8 * src,const u8 * bssid,const struct wpabuf * buf)127 static int wpas_nan_de_tx(void *ctx, unsigned int freq, unsigned int wait_time,
128 			  const u8 *dst, const u8 *src, const u8 *bssid,
129 			  const struct wpabuf *buf)
130 {
131 	struct wpa_supplicant *wpa_s = ctx;
132 	struct wpas_nan_usd_tx_work *twork;
133 
134 	if (wpa_s->nan_usd_tx_work || wpa_s->nan_usd_listen_work) {
135 		/* Reuse ongoing radio work */
136 		return wpas_nan_de_tx_send(wpa_s, freq, wait_time, dst, src,
137 					   bssid, buf);
138 	}
139 
140 	twork = os_zalloc(sizeof(*twork));
141 	if (!twork)
142 		return -1;
143 	twork->freq = freq;
144 	twork->wait_time = wait_time;
145 	os_memcpy(twork->dst, dst, ETH_ALEN);
146 	os_memcpy(twork->src, src, ETH_ALEN);
147 	os_memcpy(twork->bssid, bssid, ETH_ALEN);
148 	twork->buf = wpabuf_dup(buf);
149 	if (!twork->buf) {
150 		wpas_nan_usd_tx_work_free(twork);
151 		return -1;
152 	}
153 
154 	if (radio_add_work(wpa_s, freq, "nan-usd-tx", 0,
155 			   wpas_nan_usd_start_tx_cb, twork) < 0) {
156 		wpas_nan_usd_tx_work_free(twork);
157 		return -1;
158 	}
159 
160 	return 0;
161 }
162 
163 
164 struct wpas_nan_usd_listen_work {
165 	unsigned int freq;
166 	unsigned int duration;
167 };
168 
169 
wpas_nan_usd_listen_work_done(struct wpa_supplicant * wpa_s)170 static void wpas_nan_usd_listen_work_done(struct wpa_supplicant *wpa_s)
171 {
172 	struct wpas_nan_usd_listen_work *lwork;
173 
174 	if (!wpa_s->nan_usd_listen_work)
175 		return;
176 
177 	lwork = wpa_s->nan_usd_listen_work->ctx;
178 	os_free(lwork);
179 	radio_work_done(wpa_s->nan_usd_listen_work);
180 	wpa_s->nan_usd_listen_work = NULL;
181 }
182 
183 
wpas_nan_usd_start_listen_cb(struct wpa_radio_work * work,int deinit)184 static void wpas_nan_usd_start_listen_cb(struct wpa_radio_work *work,
185 					 int deinit)
186 {
187 	struct wpa_supplicant *wpa_s = work->wpa_s;
188 	struct wpas_nan_usd_listen_work *lwork = work->ctx;
189 	unsigned int duration;
190 
191 	if (deinit) {
192 		if (work->started) {
193 			wpa_s->nan_usd_listen_work = NULL;
194 			wpa_drv_cancel_remain_on_channel(wpa_s);
195 		}
196 		os_free(lwork);
197 		return;
198 	}
199 
200 	wpa_s->nan_usd_listen_work = work;
201 
202 	duration = lwork->duration;
203 	if (duration > wpa_s->max_remain_on_chan)
204 		duration = wpa_s->max_remain_on_chan;
205 	wpa_printf(MSG_DEBUG, "NAN: Start listen on %u MHz for %u ms",
206 		   lwork->freq, duration);
207 	if (wpa_drv_remain_on_channel(wpa_s, lwork->freq, duration) < 0) {
208 		wpa_printf(MSG_DEBUG,
209 			   "NAN: Failed to request the driver to remain on channel (%u MHz) for listen",
210 			   lwork->freq);
211 		wpas_nan_usd_listen_work_done(wpa_s);
212 		return;
213 	}
214 }
215 
216 
wpas_nan_de_listen(void * ctx,unsigned int freq,unsigned int duration)217 static int wpas_nan_de_listen(void *ctx, unsigned int freq,
218 			      unsigned int duration)
219 {
220 	struct wpa_supplicant *wpa_s = ctx;
221 	struct wpas_nan_usd_listen_work *lwork;
222 
223 	lwork = os_zalloc(sizeof(*lwork));
224 	if (!lwork)
225 		return -1;
226 	lwork->freq = freq;
227 	lwork->duration = duration;
228 
229 	if (radio_add_work(wpa_s, freq, "nan-usd-listen", 0,
230 			   wpas_nan_usd_start_listen_cb, lwork) < 0) {
231 		os_free(lwork);
232 		return -1;
233 	}
234 
235 	return 0;
236 }
237 
238 
239 static void
wpas_nan_de_discovery_result(void * ctx,int subscribe_id,enum nan_service_protocol_type srv_proto_type,const u8 * ssi,size_t ssi_len,int peer_publish_id,const u8 * peer_addr,bool fsd,bool fsd_gas)240 wpas_nan_de_discovery_result(void *ctx, int subscribe_id,
241 			     enum nan_service_protocol_type srv_proto_type,
242 			     const u8 *ssi, size_t ssi_len, int peer_publish_id,
243 			     const u8 *peer_addr, bool fsd, bool fsd_gas)
244 {
245 	struct wpa_supplicant *wpa_s = ctx;
246 
247 	wpas_notify_nan_discovery_result(wpa_s, srv_proto_type, subscribe_id,
248 					 peer_publish_id, peer_addr, fsd,
249 					 fsd_gas, ssi, ssi_len);
250 }
251 
252 
wpas_nan_de_replied(void * ctx,int publish_id,const u8 * peer_addr,int peer_subscribe_id,enum nan_service_protocol_type srv_proto_type,const u8 * ssi,size_t ssi_len)253 static void wpas_nan_de_replied(void *ctx, int publish_id, const u8 *peer_addr,
254 				int peer_subscribe_id,
255 				enum nan_service_protocol_type srv_proto_type,
256 				const u8 *ssi, size_t ssi_len)
257 {
258 	struct wpa_supplicant *wpa_s = ctx;
259 
260 	wpas_notify_nan_replied(wpa_s, srv_proto_type, publish_id,
261 				peer_subscribe_id, peer_addr, ssi, ssi_len);
262 }
263 
264 
wpas_nan_de_publish_terminated(void * ctx,int publish_id,enum nan_de_reason reason)265 static void wpas_nan_de_publish_terminated(void *ctx, int publish_id,
266 					   enum nan_de_reason reason)
267 {
268 	struct wpa_supplicant *wpa_s = ctx;
269 
270 	wpas_notify_nan_publish_terminated(wpa_s, publish_id, reason);
271 }
272 
273 
wpas_nan_de_subscribe_terminated(void * ctx,int subscribe_id,enum nan_de_reason reason)274 static void wpas_nan_de_subscribe_terminated(void *ctx, int subscribe_id,
275 					     enum nan_de_reason reason)
276 {
277 	struct wpa_supplicant *wpa_s = ctx;
278 
279 	wpas_notify_nan_subscribe_terminated(wpa_s, subscribe_id, reason);
280 }
281 
282 
wpas_nan_de_receive(void * ctx,int id,int peer_instance_id,const u8 * ssi,size_t ssi_len,const u8 * peer_addr)283 static void wpas_nan_de_receive(void *ctx, int id, int peer_instance_id,
284 				const u8 *ssi, size_t ssi_len,
285 				const u8 *peer_addr)
286 {
287 	struct wpa_supplicant *wpa_s = ctx;
288 
289 	wpas_notify_nan_receive(wpa_s, id, peer_instance_id, peer_addr,
290 				ssi, ssi_len);
291 }
292 
293 
294 #ifdef CONFIG_P2P
wpas_nan_process_p2p_usd_elems(void * ctx,const u8 * buf,u16 buf_len,const u8 * peer_addr,unsigned int freq)295 static void wpas_nan_process_p2p_usd_elems(void *ctx, const u8 *buf,
296 					   u16 buf_len, const u8 *peer_addr,
297 					   unsigned int freq)
298 {
299 	struct wpa_supplicant *wpa_s = ctx;
300 
301 	wpas_p2p_process_usd_elems(wpa_s, buf, buf_len, peer_addr, freq);
302 }
303 #endif /* CONFIG_P2P */
304 
305 
wpas_nan_usd_init(struct wpa_supplicant * wpa_s)306 int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
307 {
308 	struct nan_callbacks cb;
309 	bool offload = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD;
310 
311 	os_memset(&cb, 0, sizeof(cb));
312 	cb.ctx = wpa_s;
313 	cb.tx = wpas_nan_de_tx;
314 	cb.listen = wpas_nan_de_listen;
315 	cb.discovery_result = wpas_nan_de_discovery_result;
316 	cb.replied = wpas_nan_de_replied;
317 	cb.publish_terminated = wpas_nan_de_publish_terminated;
318 	cb.subscribe_terminated = wpas_nan_de_subscribe_terminated;
319 	cb.receive = wpas_nan_de_receive;
320 #ifdef CONFIG_P2P
321 	cb.process_p2p_usd_elems = wpas_nan_process_p2p_usd_elems;
322 #endif /* CONFIG_P2P */
323 
324 	wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false,
325 				    wpa_s->max_remain_on_chan, &cb);
326 	if (!wpa_s->nan_de)
327 		return -1;
328 	return 0;
329 }
330 
331 
wpas_nan_usd_deinit(struct wpa_supplicant * wpa_s)332 void wpas_nan_usd_deinit(struct wpa_supplicant *wpa_s)
333 {
334 	nan_de_deinit(wpa_s->nan_de);
335 	wpa_s->nan_de = NULL;
336 }
337 
338 
wpas_nan_usd_rx_sdf(struct wpa_supplicant * wpa_s,const u8 * src,const u8 * a3,unsigned int freq,const u8 * buf,size_t len)339 void wpas_nan_usd_rx_sdf(struct wpa_supplicant *wpa_s, const u8 *src,
340 			 const u8 *a3,
341 			 unsigned int freq, const u8 *buf, size_t len)
342 {
343 	if (!wpa_s->nan_de)
344 		return;
345 	nan_de_rx_sdf(wpa_s->nan_de, src, a3, freq, buf, len);
346 }
347 
348 
wpas_nan_usd_flush(struct wpa_supplicant * wpa_s)349 void wpas_nan_usd_flush(struct wpa_supplicant *wpa_s)
350 {
351 	if (!wpa_s->nan_de)
352 		return;
353 	nan_de_flush(wpa_s->nan_de);
354 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
355 		wpas_drv_nan_flush(wpa_s);
356 }
357 
358 
wpas_nan_usd_publish(struct wpa_supplicant * wpa_s,const char * service_name,enum nan_service_protocol_type srv_proto_type,const struct wpabuf * ssi,struct nan_publish_params * params,bool p2p)359 int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
360 			 enum nan_service_protocol_type srv_proto_type,
361 			 const struct wpabuf *ssi,
362 			 struct nan_publish_params *params, bool p2p)
363 {
364 	int publish_id;
365 	struct wpabuf *elems = NULL;
366 	const u8 *addr;
367 
368 	if (!wpa_s->nan_de)
369 		return -1;
370 
371 	if (p2p) {
372 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
373 		addr = wpa_s->global->p2p_dev_addr;
374 	} else {
375 		addr = wpa_s->own_addr;
376 	}
377 
378 	publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
379 				    ssi, elems, params, p2p);
380 	if (publish_id >= 1 &&
381 	    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
382 	    wpas_drv_nan_publish(wpa_s, addr, publish_id, service_name,
383 				 nan_de_get_service_id(wpa_s->nan_de,
384 						       publish_id),
385 				 srv_proto_type, ssi, elems, params) < 0) {
386 		nan_de_cancel_publish(wpa_s->nan_de, publish_id);
387 		publish_id = -1;
388 	}
389 
390 	wpabuf_free(elems);
391 	return publish_id;
392 }
393 
394 
wpas_nan_usd_cancel_publish(struct wpa_supplicant * wpa_s,int publish_id)395 void wpas_nan_usd_cancel_publish(struct wpa_supplicant *wpa_s, int publish_id)
396 {
397 	if (!wpa_s->nan_de)
398 		return;
399 	nan_de_cancel_publish(wpa_s->nan_de, publish_id);
400 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
401 		wpas_drv_nan_cancel_publish(wpa_s, publish_id);
402 }
403 
404 
wpas_nan_usd_update_publish(struct wpa_supplicant * wpa_s,int publish_id,const struct wpabuf * ssi)405 int wpas_nan_usd_update_publish(struct wpa_supplicant *wpa_s, int publish_id,
406 				const struct wpabuf *ssi)
407 {
408 	int ret;
409 
410 	if (!wpa_s->nan_de)
411 		return -1;
412 	ret = nan_de_update_publish(wpa_s->nan_de, publish_id, ssi);
413 	if (ret == 0 && (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
414 	    wpas_drv_nan_update_publish(wpa_s, publish_id, ssi) < 0)
415 		return -1;
416 	return ret;
417 }
418 
419 
wpas_nan_usd_unpause_publish(struct wpa_supplicant * wpa_s,int publish_id,u8 peer_instance_id,const u8 * peer_addr)420 int wpas_nan_usd_unpause_publish(struct wpa_supplicant *wpa_s, int publish_id,
421 				 u8 peer_instance_id, const u8 *peer_addr)
422 {
423 	if (!wpa_s->nan_de)
424 		return -1;
425 	return nan_de_unpause_publish(wpa_s->nan_de, publish_id,
426 				      peer_instance_id, peer_addr);
427 }
428 
429 
wpas_nan_usd_subscribe(struct wpa_supplicant * wpa_s,const char * service_name,enum nan_service_protocol_type srv_proto_type,const struct wpabuf * ssi,struct nan_subscribe_params * params,bool p2p)430 int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
431 			   const char *service_name,
432 			   enum nan_service_protocol_type srv_proto_type,
433 			   const struct wpabuf *ssi,
434 			   struct nan_subscribe_params *params, bool p2p)
435 {
436 	int subscribe_id;
437 	struct wpabuf *elems = NULL;
438 	const u8 *addr;
439 
440 	if (!wpa_s->nan_de)
441 		return -1;
442 
443 	if (p2p) {
444 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
445 		addr = wpa_s->global->p2p_dev_addr;
446 	} else {
447 		addr = wpa_s->own_addr;
448 	}
449 
450 	subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
451 					srv_proto_type, ssi, elems, params,
452 					p2p);
453 	if (subscribe_id >= 1 &&
454 	    (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD) &&
455 	    wpas_drv_nan_subscribe(wpa_s, addr, subscribe_id, service_name,
456 				   nan_de_get_service_id(wpa_s->nan_de,
457 							 subscribe_id),
458 				   srv_proto_type, ssi, elems, params) < 0) {
459 		nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
460 		subscribe_id = -1;
461 	}
462 
463 	wpabuf_free(elems);
464 	return subscribe_id;
465 }
466 
467 
wpas_nan_usd_cancel_subscribe(struct wpa_supplicant * wpa_s,int subscribe_id)468 void wpas_nan_usd_cancel_subscribe(struct wpa_supplicant *wpa_s,
469 				   int subscribe_id)
470 {
471 	if (!wpa_s->nan_de)
472 		return;
473 	nan_de_cancel_subscribe(wpa_s->nan_de, subscribe_id);
474 	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_NAN_OFFLOAD)
475 		wpas_drv_nan_cancel_subscribe(wpa_s, subscribe_id);
476 }
477 
478 
wpas_nan_usd_transmit(struct wpa_supplicant * wpa_s,int handle,const struct wpabuf * ssi,const struct wpabuf * elems,const u8 * peer_addr,u8 req_instance_id)479 int wpas_nan_usd_transmit(struct wpa_supplicant *wpa_s, int handle,
480 			  const struct wpabuf *ssi, const struct wpabuf *elems,
481 			  const u8 *peer_addr, u8 req_instance_id)
482 {
483 	if (!wpa_s->nan_de)
484 		return -1;
485 	return nan_de_transmit(wpa_s->nan_de, handle, ssi, elems, peer_addr,
486 			       req_instance_id);
487 }
488 
489 
wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq,unsigned int duration)490 void wpas_nan_usd_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
491 				       unsigned int freq, unsigned int duration)
492 {
493 	wpas_nan_usd_listen_work_done(wpa_s);
494 
495 	if (wpa_s->nan_de)
496 		nan_de_listen_started(wpa_s->nan_de, freq, duration);
497 }
498 
499 
wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant * wpa_s,unsigned int freq)500 void wpas_nan_usd_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
501 					      unsigned int freq)
502 {
503 	if (wpa_s->nan_de)
504 		nan_de_listen_ended(wpa_s->nan_de, freq);
505 }
506 
507 
wpas_nan_usd_tx_wait_expire(struct wpa_supplicant * wpa_s)508 void wpas_nan_usd_tx_wait_expire(struct wpa_supplicant *wpa_s)
509 {
510 	wpas_nan_usd_tx_work_done(wpa_s);
511 
512 	if (wpa_s->nan_de)
513 		nan_de_tx_wait_ended(wpa_s->nan_de);
514 }
515 
516 
wpas_nan_usd_all_freqs(struct wpa_supplicant * wpa_s)517 int * wpas_nan_usd_all_freqs(struct wpa_supplicant *wpa_s)
518 {
519 	int i, j;
520 	int *freqs = NULL;
521 
522 	if (!wpa_s->hw.modes)
523 		return NULL;
524 
525 	for (i = 0; i < wpa_s->hw.num_modes; i++) {
526 		struct hostapd_hw_modes *mode = &wpa_s->hw.modes[i];
527 
528 		for (j = 0; j < mode->num_channels; j++) {
529 			struct hostapd_channel_data *chan = &mode->channels[j];
530 
531 			/* All 20 MHz channels on 2.4 and 5 GHz band */
532 			if (chan->freq < 2412 || chan->freq > 5900)
533 				continue;
534 
535 			/* that allow frames to be transmitted */
536 			if (chan->flag & (HOSTAPD_CHAN_DISABLED |
537 					  HOSTAPD_CHAN_NO_IR |
538 					  HOSTAPD_CHAN_RADAR))
539 				continue;
540 
541 			int_array_add_unique(&freqs, chan->freq);
542 		}
543 	}
544 
545 	return freqs;
546 }
547