xref: /openbmc/linux/net/wireless/pmsr.c (revision 6c71a0574249f5e5a45fe055ab5f837023d5eeca)
1  /* SPDX-License-Identifier: GPL-2.0 */
2  /*
3   * Copyright (C) 2018 - 2021, 2023 Intel Corporation
4   */
5  #include <net/cfg80211.h>
6  #include "core.h"
7  #include "nl80211.h"
8  #include "rdev-ops.h"
9  
pmsr_parse_ftm(struct cfg80211_registered_device * rdev,struct nlattr * ftmreq,struct cfg80211_pmsr_request_peer * out,struct genl_info * info)10  static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
11  			  struct nlattr *ftmreq,
12  			  struct cfg80211_pmsr_request_peer *out,
13  			  struct genl_info *info)
14  {
15  	const struct cfg80211_pmsr_capabilities *capa = rdev->wiphy.pmsr_capa;
16  	struct nlattr *tb[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1];
17  	u32 preamble = NL80211_PREAMBLE_DMG; /* only optional in DMG */
18  
19  	/* validate existing data */
20  	if (!(rdev->wiphy.pmsr_capa->ftm.bandwidths & BIT(out->chandef.width))) {
21  		NL_SET_ERR_MSG(info->extack, "FTM: unsupported bandwidth");
22  		return -EINVAL;
23  	}
24  
25  	/* no validation needed - was already done via nested policy */
26  	nla_parse_nested_deprecated(tb, NL80211_PMSR_FTM_REQ_ATTR_MAX, ftmreq,
27  				    NULL, NULL);
28  
29  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE])
30  		preamble = nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE]);
31  
32  	/* set up values - struct is 0-initialized */
33  	out->ftm.requested = true;
34  
35  	switch (out->chandef.chan->band) {
36  	case NL80211_BAND_60GHZ:
37  		/* optional */
38  		break;
39  	default:
40  		if (!tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE]) {
41  			NL_SET_ERR_MSG(info->extack,
42  				       "FTM: must specify preamble");
43  			return -EINVAL;
44  		}
45  	}
46  
47  	if (!(capa->ftm.preambles & BIT(preamble))) {
48  		NL_SET_ERR_MSG_ATTR(info->extack,
49  				    tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
50  				    "FTM: invalid preamble");
51  		return -EINVAL;
52  	}
53  
54  	out->ftm.preamble = preamble;
55  
56  	out->ftm.burst_period = 0;
57  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD])
58  		out->ftm.burst_period =
59  			nla_get_u16(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD]);
60  
61  	out->ftm.asap = !!tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP];
62  	if (out->ftm.asap && !capa->ftm.asap) {
63  		NL_SET_ERR_MSG_ATTR(info->extack,
64  				    tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP],
65  				    "FTM: ASAP mode not supported");
66  		return -EINVAL;
67  	}
68  
69  	if (!out->ftm.asap && !capa->ftm.non_asap) {
70  		NL_SET_ERR_MSG(info->extack,
71  			       "FTM: non-ASAP mode not supported");
72  		return -EINVAL;
73  	}
74  
75  	out->ftm.num_bursts_exp = 0;
76  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP])
77  		out->ftm.num_bursts_exp =
78  			nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP]);
79  
80  	if (capa->ftm.max_bursts_exponent >= 0 &&
81  	    out->ftm.num_bursts_exp > capa->ftm.max_bursts_exponent) {
82  		NL_SET_ERR_MSG_ATTR(info->extack,
83  				    tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP],
84  				    "FTM: max NUM_BURSTS_EXP must be set lower than the device limit");
85  		return -EINVAL;
86  	}
87  
88  	out->ftm.burst_duration = 15;
89  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION])
90  		out->ftm.burst_duration =
91  			nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION]);
92  
93  	out->ftm.ftms_per_burst = 0;
94  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST])
95  		out->ftm.ftms_per_burst =
96  			nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
97  
98  	if (capa->ftm.max_ftms_per_burst &&
99  	    (out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||
100  	     out->ftm.ftms_per_burst == 0)) {
101  		NL_SET_ERR_MSG_ATTR(info->extack,
102  				    tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST],
103  				    "FTM: FTMs per burst must be set lower than the device limit but non-zero");
104  		return -EINVAL;
105  	}
106  
107  	out->ftm.ftmr_retries = 3;
108  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES])
109  		out->ftm.ftmr_retries =
110  			nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES]);
111  
112  	out->ftm.request_lci = !!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI];
113  	if (out->ftm.request_lci && !capa->ftm.request_lci) {
114  		NL_SET_ERR_MSG_ATTR(info->extack,
115  				    tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI],
116  				    "FTM: LCI request not supported");
117  	}
118  
119  	out->ftm.request_civicloc =
120  		!!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC];
121  	if (out->ftm.request_civicloc && !capa->ftm.request_civicloc) {
122  		NL_SET_ERR_MSG_ATTR(info->extack,
123  				    tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC],
124  			    "FTM: civic location request not supported");
125  	}
126  
127  	out->ftm.trigger_based =
128  		!!tb[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED];
129  	if (out->ftm.trigger_based && !capa->ftm.trigger_based) {
130  		NL_SET_ERR_MSG_ATTR(info->extack,
131  				    tb[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED],
132  				    "FTM: trigger based ranging is not supported");
133  		return -EINVAL;
134  	}
135  
136  	out->ftm.non_trigger_based =
137  		!!tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED];
138  	if (out->ftm.non_trigger_based && !capa->ftm.non_trigger_based) {
139  		NL_SET_ERR_MSG_ATTR(info->extack,
140  				    tb[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED],
141  				    "FTM: trigger based ranging is not supported");
142  		return -EINVAL;
143  	}
144  
145  	if (out->ftm.trigger_based && out->ftm.non_trigger_based) {
146  		NL_SET_ERR_MSG(info->extack,
147  			       "FTM: can't set both trigger based and non trigger based");
148  		return -EINVAL;
149  	}
150  
151  	if ((out->ftm.trigger_based || out->ftm.non_trigger_based) &&
152  	    out->ftm.preamble != NL80211_PREAMBLE_HE) {
153  		NL_SET_ERR_MSG_ATTR(info->extack,
154  				    tb[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE],
155  				    "FTM: non EDCA based ranging must use HE preamble");
156  		return -EINVAL;
157  	}
158  
159  	out->ftm.lmr_feedback =
160  		!!tb[NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK];
161  	if (!out->ftm.trigger_based && !out->ftm.non_trigger_based &&
162  	    out->ftm.lmr_feedback) {
163  		NL_SET_ERR_MSG_ATTR(info->extack,
164  				    tb[NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK],
165  				    "FTM: LMR feedback set for EDCA based ranging");
166  		return -EINVAL;
167  	}
168  
169  	if (tb[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR]) {
170  		if (!out->ftm.non_trigger_based && !out->ftm.trigger_based) {
171  			NL_SET_ERR_MSG_ATTR(info->extack,
172  					    tb[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR],
173  					    "FTM: BSS color set for EDCA based ranging");
174  			return -EINVAL;
175  		}
176  
177  		out->ftm.bss_color =
178  			nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR]);
179  	}
180  
181  	return 0;
182  }
183  
pmsr_parse_peer(struct cfg80211_registered_device * rdev,struct nlattr * peer,struct cfg80211_pmsr_request_peer * out,struct genl_info * info)184  static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
185  			   struct nlattr *peer,
186  			   struct cfg80211_pmsr_request_peer *out,
187  			   struct genl_info *info)
188  {
189  	struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1];
190  	struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1];
191  	struct nlattr *treq;
192  	int err, rem;
193  
194  	/* no validation needed - was already done via nested policy */
195  	nla_parse_nested_deprecated(tb, NL80211_PMSR_PEER_ATTR_MAX, peer,
196  				    NULL, NULL);
197  
198  	if (!tb[NL80211_PMSR_PEER_ATTR_ADDR] ||
199  	    !tb[NL80211_PMSR_PEER_ATTR_CHAN] ||
200  	    !tb[NL80211_PMSR_PEER_ATTR_REQ]) {
201  		NL_SET_ERR_MSG_ATTR(info->extack, peer,
202  				    "insufficient peer data");
203  		return -EINVAL;
204  	}
205  
206  	memcpy(out->addr, nla_data(tb[NL80211_PMSR_PEER_ATTR_ADDR]), ETH_ALEN);
207  
208  	/* reuse info->attrs */
209  	memset(info->attrs, 0, sizeof(*info->attrs) * (NL80211_ATTR_MAX + 1));
210  	err = nla_parse_nested_deprecated(info->attrs, NL80211_ATTR_MAX,
211  					  tb[NL80211_PMSR_PEER_ATTR_CHAN],
212  					  NULL, info->extack);
213  	if (err)
214  		return err;
215  
216  	err = nl80211_parse_chandef(rdev, info, &out->chandef);
217  	if (err)
218  		return err;
219  
220  	/* no validation needed - was already done via nested policy */
221  	nla_parse_nested_deprecated(req, NL80211_PMSR_REQ_ATTR_MAX,
222  				    tb[NL80211_PMSR_PEER_ATTR_REQ], NULL,
223  				    NULL);
224  
225  	if (!req[NL80211_PMSR_REQ_ATTR_DATA]) {
226  		NL_SET_ERR_MSG_ATTR(info->extack,
227  				    tb[NL80211_PMSR_PEER_ATTR_REQ],
228  				    "missing request type/data");
229  		return -EINVAL;
230  	}
231  
232  	if (req[NL80211_PMSR_REQ_ATTR_GET_AP_TSF])
233  		out->report_ap_tsf = true;
234  
235  	if (out->report_ap_tsf && !rdev->wiphy.pmsr_capa->report_ap_tsf) {
236  		NL_SET_ERR_MSG_ATTR(info->extack,
237  				    req[NL80211_PMSR_REQ_ATTR_GET_AP_TSF],
238  				    "reporting AP TSF is not supported");
239  		return -EINVAL;
240  	}
241  
242  	nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) {
243  		switch (nla_type(treq)) {
244  		case NL80211_PMSR_TYPE_FTM:
245  			err = pmsr_parse_ftm(rdev, treq, out, info);
246  			break;
247  		default:
248  			NL_SET_ERR_MSG_ATTR(info->extack, treq,
249  					    "unsupported measurement type");
250  			err = -EINVAL;
251  		}
252  	}
253  
254  	if (err)
255  		return err;
256  
257  	return 0;
258  }
259  
nl80211_pmsr_start(struct sk_buff * skb,struct genl_info * info)260  int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
261  {
262  	struct nlattr *reqattr = info->attrs[NL80211_ATTR_PEER_MEASUREMENTS];
263  	struct cfg80211_registered_device *rdev = info->user_ptr[0];
264  	struct wireless_dev *wdev = info->user_ptr[1];
265  	struct cfg80211_pmsr_request *req;
266  	struct nlattr *peers, *peer;
267  	int count, rem, err, idx;
268  
269  	if (!rdev->wiphy.pmsr_capa)
270  		return -EOPNOTSUPP;
271  
272  	if (!reqattr)
273  		return -EINVAL;
274  
275  	peers = nla_find(nla_data(reqattr), nla_len(reqattr),
276  			 NL80211_PMSR_ATTR_PEERS);
277  	if (!peers)
278  		return -EINVAL;
279  
280  	count = 0;
281  	nla_for_each_nested(peer, peers, rem) {
282  		count++;
283  
284  		if (count > rdev->wiphy.pmsr_capa->max_peers) {
285  			NL_SET_ERR_MSG_ATTR(info->extack, peer,
286  					    "Too many peers used");
287  			return -EINVAL;
288  		}
289  	}
290  
291  	req = kzalloc(struct_size(req, peers, count), GFP_KERNEL);
292  	if (!req)
293  		return -ENOMEM;
294  	req->n_peers = count;
295  
296  	if (info->attrs[NL80211_ATTR_TIMEOUT])
297  		req->timeout = nla_get_u32(info->attrs[NL80211_ATTR_TIMEOUT]);
298  
299  	if (info->attrs[NL80211_ATTR_MAC]) {
300  		if (!rdev->wiphy.pmsr_capa->randomize_mac_addr) {
301  			NL_SET_ERR_MSG_ATTR(info->extack,
302  					    info->attrs[NL80211_ATTR_MAC],
303  					    "device cannot randomize MAC address");
304  			err = -EINVAL;
305  			goto out_err;
306  		}
307  
308  		err = nl80211_parse_random_mac(info->attrs, req->mac_addr,
309  					       req->mac_addr_mask);
310  		if (err)
311  			goto out_err;
312  	} else {
313  		memcpy(req->mac_addr, wdev_address(wdev), ETH_ALEN);
314  		eth_broadcast_addr(req->mac_addr_mask);
315  	}
316  
317  	idx = 0;
318  	nla_for_each_nested(peer, peers, rem) {
319  		/* NB: this reuses info->attrs, but we no longer need it */
320  		err = pmsr_parse_peer(rdev, peer, &req->peers[idx], info);
321  		if (err)
322  			goto out_err;
323  		idx++;
324  	}
325  	req->cookie = cfg80211_assign_cookie(rdev);
326  	req->nl_portid = info->snd_portid;
327  
328  	err = rdev_start_pmsr(rdev, wdev, req);
329  	if (err)
330  		goto out_err;
331  
332  	list_add_tail(&req->list, &wdev->pmsr_list);
333  
334  	nl_set_extack_cookie_u64(info->extack, req->cookie);
335  	return 0;
336  out_err:
337  	kfree(req);
338  	return err;
339  }
340  
cfg80211_pmsr_complete(struct wireless_dev * wdev,struct cfg80211_pmsr_request * req,gfp_t gfp)341  void cfg80211_pmsr_complete(struct wireless_dev *wdev,
342  			    struct cfg80211_pmsr_request *req,
343  			    gfp_t gfp)
344  {
345  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
346  	struct cfg80211_pmsr_request *tmp, *prev, *to_free = NULL;
347  	struct sk_buff *msg;
348  	void *hdr;
349  
350  	trace_cfg80211_pmsr_complete(wdev->wiphy, wdev, req->cookie);
351  
352  	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
353  	if (!msg)
354  		goto free_request;
355  
356  	hdr = nl80211hdr_put(msg, 0, 0, 0,
357  			     NL80211_CMD_PEER_MEASUREMENT_COMPLETE);
358  	if (!hdr)
359  		goto free_msg;
360  
361  	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
362  	    nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
363  			      NL80211_ATTR_PAD))
364  		goto free_msg;
365  
366  	if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->cookie,
367  			      NL80211_ATTR_PAD))
368  		goto free_msg;
369  
370  	genlmsg_end(msg, hdr);
371  	genlmsg_unicast(wiphy_net(wdev->wiphy), msg, req->nl_portid);
372  	goto free_request;
373  free_msg:
374  	nlmsg_free(msg);
375  free_request:
376  	spin_lock_bh(&wdev->pmsr_lock);
377  	/*
378  	 * cfg80211_pmsr_process_abort() may have already moved this request
379  	 * to the free list, and will free it later. In this case, don't free
380  	 * it here.
381  	 */
382  	list_for_each_entry_safe(tmp, prev, &wdev->pmsr_list, list) {
383  		if (tmp == req) {
384  			list_del(&req->list);
385  			to_free = req;
386  			break;
387  		}
388  	}
389  	spin_unlock_bh(&wdev->pmsr_lock);
390  	kfree(to_free);
391  }
392  EXPORT_SYMBOL_GPL(cfg80211_pmsr_complete);
393  
nl80211_pmsr_send_ftm_res(struct sk_buff * msg,struct cfg80211_pmsr_result * res)394  static int nl80211_pmsr_send_ftm_res(struct sk_buff *msg,
395  				     struct cfg80211_pmsr_result *res)
396  {
397  	if (res->status == NL80211_PMSR_STATUS_FAILURE) {
398  		if (nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON,
399  				res->ftm.failure_reason))
400  			goto error;
401  
402  		if (res->ftm.failure_reason ==
403  			NL80211_PMSR_FTM_FAILURE_PEER_BUSY &&
404  		    res->ftm.busy_retry_time &&
405  		    nla_put_u32(msg, NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME,
406  				res->ftm.busy_retry_time))
407  			goto error;
408  
409  		return 0;
410  	}
411  
412  #define PUT(tp, attr, val)						\
413  	do {								\
414  		if (nla_put_##tp(msg,					\
415  				 NL80211_PMSR_FTM_RESP_ATTR_##attr,	\
416  				 res->ftm.val))				\
417  			goto error;					\
418  	} while (0)
419  
420  #define PUTOPT(tp, attr, val)						\
421  	do {								\
422  		if (res->ftm.val##_valid)				\
423  			PUT(tp, attr, val);				\
424  	} while (0)
425  
426  #define PUT_U64(attr, val)						\
427  	do {								\
428  		if (nla_put_u64_64bit(msg,				\
429  				      NL80211_PMSR_FTM_RESP_ATTR_##attr,\
430  				      res->ftm.val,			\
431  				      NL80211_PMSR_FTM_RESP_ATTR_PAD))	\
432  			goto error;					\
433  	} while (0)
434  
435  #define PUTOPT_U64(attr, val)						\
436  	do {								\
437  		if (res->ftm.val##_valid)				\
438  			PUT_U64(attr, val);				\
439  	} while (0)
440  
441  	if (res->ftm.burst_index >= 0)
442  		PUT(u32, BURST_INDEX, burst_index);
443  	PUTOPT(u32, NUM_FTMR_ATTEMPTS, num_ftmr_attempts);
444  	PUTOPT(u32, NUM_FTMR_SUCCESSES, num_ftmr_successes);
445  	PUT(u8, NUM_BURSTS_EXP, num_bursts_exp);
446  	PUT(u8, BURST_DURATION, burst_duration);
447  	PUT(u8, FTMS_PER_BURST, ftms_per_burst);
448  	PUTOPT(s32, RSSI_AVG, rssi_avg);
449  	PUTOPT(s32, RSSI_SPREAD, rssi_spread);
450  	if (res->ftm.tx_rate_valid &&
451  	    !nl80211_put_sta_rate(msg, &res->ftm.tx_rate,
452  				  NL80211_PMSR_FTM_RESP_ATTR_TX_RATE))
453  		goto error;
454  	if (res->ftm.rx_rate_valid &&
455  	    !nl80211_put_sta_rate(msg, &res->ftm.rx_rate,
456  				  NL80211_PMSR_FTM_RESP_ATTR_RX_RATE))
457  		goto error;
458  	PUTOPT_U64(RTT_AVG, rtt_avg);
459  	PUTOPT_U64(RTT_VARIANCE, rtt_variance);
460  	PUTOPT_U64(RTT_SPREAD, rtt_spread);
461  	PUTOPT_U64(DIST_AVG, dist_avg);
462  	PUTOPT_U64(DIST_VARIANCE, dist_variance);
463  	PUTOPT_U64(DIST_SPREAD, dist_spread);
464  	if (res->ftm.lci && res->ftm.lci_len &&
465  	    nla_put(msg, NL80211_PMSR_FTM_RESP_ATTR_LCI,
466  		    res->ftm.lci_len, res->ftm.lci))
467  		goto error;
468  	if (res->ftm.civicloc && res->ftm.civicloc_len &&
469  	    nla_put(msg, NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC,
470  		    res->ftm.civicloc_len, res->ftm.civicloc))
471  		goto error;
472  #undef PUT
473  #undef PUTOPT
474  #undef PUT_U64
475  #undef PUTOPT_U64
476  
477  	return 0;
478  error:
479  	return -ENOSPC;
480  }
481  
nl80211_pmsr_send_result(struct sk_buff * msg,struct cfg80211_pmsr_result * res)482  static int nl80211_pmsr_send_result(struct sk_buff *msg,
483  				    struct cfg80211_pmsr_result *res)
484  {
485  	struct nlattr *pmsr, *peers, *peer, *resp, *data, *typedata;
486  
487  	pmsr = nla_nest_start_noflag(msg, NL80211_ATTR_PEER_MEASUREMENTS);
488  	if (!pmsr)
489  		goto error;
490  
491  	peers = nla_nest_start_noflag(msg, NL80211_PMSR_ATTR_PEERS);
492  	if (!peers)
493  		goto error;
494  
495  	peer = nla_nest_start_noflag(msg, 1);
496  	if (!peer)
497  		goto error;
498  
499  	if (nla_put(msg, NL80211_PMSR_PEER_ATTR_ADDR, ETH_ALEN, res->addr))
500  		goto error;
501  
502  	resp = nla_nest_start_noflag(msg, NL80211_PMSR_PEER_ATTR_RESP);
503  	if (!resp)
504  		goto error;
505  
506  	if (nla_put_u32(msg, NL80211_PMSR_RESP_ATTR_STATUS, res->status) ||
507  	    nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_HOST_TIME,
508  			      res->host_time, NL80211_PMSR_RESP_ATTR_PAD))
509  		goto error;
510  
511  	if (res->ap_tsf_valid &&
512  	    nla_put_u64_64bit(msg, NL80211_PMSR_RESP_ATTR_AP_TSF,
513  			      res->ap_tsf, NL80211_PMSR_RESP_ATTR_PAD))
514  		goto error;
515  
516  	if (res->final && nla_put_flag(msg, NL80211_PMSR_RESP_ATTR_FINAL))
517  		goto error;
518  
519  	data = nla_nest_start_noflag(msg, NL80211_PMSR_RESP_ATTR_DATA);
520  	if (!data)
521  		goto error;
522  
523  	typedata = nla_nest_start_noflag(msg, res->type);
524  	if (!typedata)
525  		goto error;
526  
527  	switch (res->type) {
528  	case NL80211_PMSR_TYPE_FTM:
529  		if (nl80211_pmsr_send_ftm_res(msg, res))
530  			goto error;
531  		break;
532  	default:
533  		WARN_ON(1);
534  	}
535  
536  	nla_nest_end(msg, typedata);
537  	nla_nest_end(msg, data);
538  	nla_nest_end(msg, resp);
539  	nla_nest_end(msg, peer);
540  	nla_nest_end(msg, peers);
541  	nla_nest_end(msg, pmsr);
542  
543  	return 0;
544  error:
545  	return -ENOSPC;
546  }
547  
cfg80211_pmsr_report(struct wireless_dev * wdev,struct cfg80211_pmsr_request * req,struct cfg80211_pmsr_result * result,gfp_t gfp)548  void cfg80211_pmsr_report(struct wireless_dev *wdev,
549  			  struct cfg80211_pmsr_request *req,
550  			  struct cfg80211_pmsr_result *result,
551  			  gfp_t gfp)
552  {
553  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
554  	struct sk_buff *msg;
555  	void *hdr;
556  	int err;
557  
558  	trace_cfg80211_pmsr_report(wdev->wiphy, wdev, req->cookie,
559  				   result->addr);
560  
561  	/*
562  	 * Currently, only variable items are LCI and civic location,
563  	 * both of which are reasonably short so we don't need to
564  	 * worry about them here for the allocation.
565  	 */
566  	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
567  	if (!msg)
568  		return;
569  
570  	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_PEER_MEASUREMENT_RESULT);
571  	if (!hdr)
572  		goto free;
573  
574  	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
575  	    nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev),
576  			      NL80211_ATTR_PAD))
577  		goto free;
578  
579  	if (nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->cookie,
580  			      NL80211_ATTR_PAD))
581  		goto free;
582  
583  	err = nl80211_pmsr_send_result(msg, result);
584  	if (err) {
585  		pr_err_ratelimited("peer measurement result: message didn't fit!");
586  		goto free;
587  	}
588  
589  	genlmsg_end(msg, hdr);
590  	genlmsg_unicast(wiphy_net(wdev->wiphy), msg, req->nl_portid);
591  	return;
592  free:
593  	nlmsg_free(msg);
594  }
595  EXPORT_SYMBOL_GPL(cfg80211_pmsr_report);
596  
cfg80211_pmsr_process_abort(struct wireless_dev * wdev)597  static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev)
598  {
599  	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
600  	struct cfg80211_pmsr_request *req, *tmp;
601  	LIST_HEAD(free_list);
602  
603  	lockdep_assert_held(&wdev->mtx);
604  
605  	spin_lock_bh(&wdev->pmsr_lock);
606  	list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) {
607  		if (req->nl_portid)
608  			continue;
609  		list_move_tail(&req->list, &free_list);
610  	}
611  	spin_unlock_bh(&wdev->pmsr_lock);
612  
613  	list_for_each_entry_safe(req, tmp, &free_list, list) {
614  		rdev_abort_pmsr(rdev, wdev, req);
615  
616  		kfree(req);
617  	}
618  }
619  
cfg80211_pmsr_free_wk(struct work_struct * work)620  void cfg80211_pmsr_free_wk(struct work_struct *work)
621  {
622  	struct wireless_dev *wdev = container_of(work, struct wireless_dev,
623  						 pmsr_free_wk);
624  
625  	wiphy_lock(wdev->wiphy);
626  	wdev_lock(wdev);
627  	cfg80211_pmsr_process_abort(wdev);
628  	wdev_unlock(wdev);
629  	wiphy_unlock(wdev->wiphy);
630  }
631  
cfg80211_pmsr_wdev_down(struct wireless_dev * wdev)632  void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
633  {
634  	struct cfg80211_pmsr_request *req;
635  	bool found = false;
636  
637  	spin_lock_bh(&wdev->pmsr_lock);
638  	list_for_each_entry(req, &wdev->pmsr_list, list) {
639  		found = true;
640  		req->nl_portid = 0;
641  	}
642  	spin_unlock_bh(&wdev->pmsr_lock);
643  
644  	if (found)
645  		cfg80211_pmsr_process_abort(wdev);
646  
647  	WARN_ON(!list_empty(&wdev->pmsr_list));
648  }
649  
cfg80211_release_pmsr(struct wireless_dev * wdev,u32 portid)650  void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid)
651  {
652  	struct cfg80211_pmsr_request *req;
653  
654  	spin_lock_bh(&wdev->pmsr_lock);
655  	list_for_each_entry(req, &wdev->pmsr_list, list) {
656  		if (req->nl_portid == portid) {
657  			req->nl_portid = 0;
658  			schedule_work(&wdev->pmsr_free_wk);
659  		}
660  	}
661  	spin_unlock_bh(&wdev->pmsr_lock);
662  }
663