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