1 /* SPDX-License-Identifier: GPL-2.0 */
3 * Copyright (C) 2018 - 2019 Intel Corporation
7 #include <net/cfg80211.h>
12 static int pmsr_parse_ftm(struct cfg80211_registered_device
*rdev
,
13 struct nlattr
*ftmreq
,
14 struct cfg80211_pmsr_request_peer
*out
,
15 struct genl_info
*info
)
17 const struct cfg80211_pmsr_capabilities
*capa
= rdev
->wiphy
.pmsr_capa
;
18 struct nlattr
*tb
[NL80211_PMSR_FTM_REQ_ATTR_MAX
+ 1];
19 u32 preamble
= NL80211_PREAMBLE_DMG
; /* only optional in DMG */
21 /* validate existing data */
22 if (!(rdev
->wiphy
.pmsr_capa
->ftm
.bandwidths
& BIT(out
->chandef
.width
))) {
23 NL_SET_ERR_MSG(info
->extack
, "FTM: unsupported bandwidth");
27 /* no validation needed - was already done via nested policy */
28 nla_parse_nested_deprecated(tb
, NL80211_PMSR_FTM_REQ_ATTR_MAX
, ftmreq
,
31 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE
])
32 preamble
= nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE
]);
34 /* set up values - struct is 0-initialized */
35 out
->ftm
.requested
= true;
37 switch (out
->chandef
.chan
->band
) {
38 case NL80211_BAND_60GHZ
:
42 if (!tb
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE
]) {
43 NL_SET_ERR_MSG(info
->extack
,
44 "FTM: must specify preamble");
49 if (!(capa
->ftm
.preambles
& BIT(preamble
))) {
50 NL_SET_ERR_MSG_ATTR(info
->extack
,
51 tb
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE
],
52 "FTM: invalid preamble");
56 out
->ftm
.preamble
= preamble
;
58 out
->ftm
.burst_period
= 0;
59 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD
])
60 out
->ftm
.burst_period
=
61 nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD
]);
63 out
->ftm
.asap
= !!tb
[NL80211_PMSR_FTM_REQ_ATTR_ASAP
];
64 if (out
->ftm
.asap
&& !capa
->ftm
.asap
) {
65 NL_SET_ERR_MSG_ATTR(info
->extack
,
66 tb
[NL80211_PMSR_FTM_REQ_ATTR_ASAP
],
67 "FTM: ASAP mode not supported");
71 if (!out
->ftm
.asap
&& !capa
->ftm
.non_asap
) {
72 NL_SET_ERR_MSG(info
->extack
,
73 "FTM: non-ASAP mode not supported");
77 out
->ftm
.num_bursts_exp
= 0;
78 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP
])
79 out
->ftm
.num_bursts_exp
=
80 nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP
]);
82 if (capa
->ftm
.max_bursts_exponent
>= 0 &&
83 out
->ftm
.num_bursts_exp
> capa
->ftm
.max_bursts_exponent
) {
84 NL_SET_ERR_MSG_ATTR(info
->extack
,
85 tb
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP
],
86 "FTM: max NUM_BURSTS_EXP must be set lower than the device limit");
90 out
->ftm
.burst_duration
= 15;
91 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION
])
92 out
->ftm
.burst_duration
=
93 nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION
]);
95 out
->ftm
.ftms_per_burst
= 0;
96 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST
])
97 out
->ftm
.ftms_per_burst
=
98 nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST
]);
100 if (capa
->ftm
.max_ftms_per_burst
&&
101 (out
->ftm
.ftms_per_burst
> capa
->ftm
.max_ftms_per_burst
||
102 out
->ftm
.ftms_per_burst
== 0)) {
103 NL_SET_ERR_MSG_ATTR(info
->extack
,
104 tb
[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST
],
105 "FTM: FTMs per burst must be set lower than the device limit but non-zero");
109 out
->ftm
.ftmr_retries
= 3;
110 if (tb
[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES
])
111 out
->ftm
.ftmr_retries
=
112 nla_get_u32(tb
[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES
]);
114 out
->ftm
.request_lci
= !!tb
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI
];
115 if (out
->ftm
.request_lci
&& !capa
->ftm
.request_lci
) {
116 NL_SET_ERR_MSG_ATTR(info
->extack
,
117 tb
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI
],
118 "FTM: LCI request not supported");
121 out
->ftm
.request_civicloc
=
122 !!tb
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC
];
123 if (out
->ftm
.request_civicloc
&& !capa
->ftm
.request_civicloc
) {
124 NL_SET_ERR_MSG_ATTR(info
->extack
,
125 tb
[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC
],
126 "FTM: civic location request not supported");
129 out
->ftm
.trigger_based
=
130 !!tb
[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED
];
131 if (out
->ftm
.trigger_based
&& !capa
->ftm
.trigger_based
) {
132 NL_SET_ERR_MSG_ATTR(info
->extack
,
133 tb
[NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED
],
134 "FTM: trigger based ranging is not supported");
138 out
->ftm
.non_trigger_based
=
139 !!tb
[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED
];
140 if (out
->ftm
.non_trigger_based
&& !capa
->ftm
.non_trigger_based
) {
141 NL_SET_ERR_MSG_ATTR(info
->extack
,
142 tb
[NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED
],
143 "FTM: trigger based ranging is not supported");
147 if (out
->ftm
.trigger_based
&& out
->ftm
.non_trigger_based
) {
148 NL_SET_ERR_MSG(info
->extack
,
149 "FTM: can't set both trigger based and non trigger based");
153 if ((out
->ftm
.trigger_based
|| out
->ftm
.non_trigger_based
) &&
154 out
->ftm
.preamble
!= NL80211_PREAMBLE_HE
) {
155 NL_SET_ERR_MSG_ATTR(info
->extack
,
156 tb
[NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE
],
157 "FTM: non EDCA based ranging must use HE preamble");
164 static int pmsr_parse_peer(struct cfg80211_registered_device
*rdev
,
166 struct cfg80211_pmsr_request_peer
*out
,
167 struct genl_info
*info
)
169 struct nlattr
*tb
[NL80211_PMSR_PEER_ATTR_MAX
+ 1];
170 struct nlattr
*req
[NL80211_PMSR_REQ_ATTR_MAX
+ 1];
174 /* no validation needed - was already done via nested policy */
175 nla_parse_nested_deprecated(tb
, NL80211_PMSR_PEER_ATTR_MAX
, peer
,
178 if (!tb
[NL80211_PMSR_PEER_ATTR_ADDR
] ||
179 !tb
[NL80211_PMSR_PEER_ATTR_CHAN
] ||
180 !tb
[NL80211_PMSR_PEER_ATTR_REQ
]) {
181 NL_SET_ERR_MSG_ATTR(info
->extack
, peer
,
182 "insufficient peer data");
186 memcpy(out
->addr
, nla_data(tb
[NL80211_PMSR_PEER_ATTR_ADDR
]), ETH_ALEN
);
188 /* reuse info->attrs */
189 memset(info
->attrs
, 0, sizeof(*info
->attrs
) * (NL80211_ATTR_MAX
+ 1));
190 err
= nla_parse_nested_deprecated(info
->attrs
, NL80211_ATTR_MAX
,
191 tb
[NL80211_PMSR_PEER_ATTR_CHAN
],
196 err
= nl80211_parse_chandef(rdev
, info
, &out
->chandef
);
200 /* no validation needed - was already done via nested policy */
201 nla_parse_nested_deprecated(req
, NL80211_PMSR_REQ_ATTR_MAX
,
202 tb
[NL80211_PMSR_PEER_ATTR_REQ
], NULL
,
205 if (!req
[NL80211_PMSR_REQ_ATTR_DATA
]) {
206 NL_SET_ERR_MSG_ATTR(info
->extack
,
207 tb
[NL80211_PMSR_PEER_ATTR_REQ
],
208 "missing request type/data");
212 if (req
[NL80211_PMSR_REQ_ATTR_GET_AP_TSF
])
213 out
->report_ap_tsf
= true;
215 if (out
->report_ap_tsf
&& !rdev
->wiphy
.pmsr_capa
->report_ap_tsf
) {
216 NL_SET_ERR_MSG_ATTR(info
->extack
,
217 req
[NL80211_PMSR_REQ_ATTR_GET_AP_TSF
],
218 "reporting AP TSF is not supported");
222 nla_for_each_nested(treq
, req
[NL80211_PMSR_REQ_ATTR_DATA
], rem
) {
223 switch (nla_type(treq
)) {
224 case NL80211_PMSR_TYPE_FTM
:
225 err
= pmsr_parse_ftm(rdev
, treq
, out
, info
);
228 NL_SET_ERR_MSG_ATTR(info
->extack
, treq
,
229 "unsupported measurement type");
240 int nl80211_pmsr_start(struct sk_buff
*skb
, struct genl_info
*info
)
242 struct nlattr
*reqattr
= info
->attrs
[NL80211_ATTR_PEER_MEASUREMENTS
];
243 struct cfg80211_registered_device
*rdev
= info
->user_ptr
[0];
244 struct wireless_dev
*wdev
= info
->user_ptr
[1];
245 struct cfg80211_pmsr_request
*req
;
246 struct nlattr
*peers
, *peer
;
247 int count
, rem
, err
, idx
;
249 if (!rdev
->wiphy
.pmsr_capa
)
255 peers
= nla_find(nla_data(reqattr
), nla_len(reqattr
),
256 NL80211_PMSR_ATTR_PEERS
);
261 nla_for_each_nested(peer
, peers
, rem
) {
264 if (count
> rdev
->wiphy
.pmsr_capa
->max_peers
) {
265 NL_SET_ERR_MSG_ATTR(info
->extack
, peer
,
266 "Too many peers used");
271 req
= kzalloc(struct_size(req
, peers
, count
), GFP_KERNEL
);
275 if (info
->attrs
[NL80211_ATTR_TIMEOUT
])
276 req
->timeout
= nla_get_u32(info
->attrs
[NL80211_ATTR_TIMEOUT
]);
278 if (info
->attrs
[NL80211_ATTR_MAC
]) {
279 if (!rdev
->wiphy
.pmsr_capa
->randomize_mac_addr
) {
280 NL_SET_ERR_MSG_ATTR(info
->extack
,
281 info
->attrs
[NL80211_ATTR_MAC
],
282 "device cannot randomize MAC address");
287 err
= nl80211_parse_random_mac(info
->attrs
, req
->mac_addr
,
292 memcpy(req
->mac_addr
, wdev_address(wdev
), ETH_ALEN
);
293 eth_broadcast_addr(req
->mac_addr_mask
);
297 nla_for_each_nested(peer
, peers
, rem
) {
298 /* NB: this reuses info->attrs, but we no longer need it */
299 err
= pmsr_parse_peer(rdev
, peer
, &req
->peers
[idx
], info
);
305 req
->n_peers
= count
;
306 req
->cookie
= cfg80211_assign_cookie(rdev
);
307 req
->nl_portid
= info
->snd_portid
;
309 err
= rdev_start_pmsr(rdev
, wdev
, req
);
313 list_add_tail(&req
->list
, &wdev
->pmsr_list
);
315 nl_set_extack_cookie_u64(info
->extack
, req
->cookie
);
322 void cfg80211_pmsr_complete(struct wireless_dev
*wdev
,
323 struct cfg80211_pmsr_request
*req
,
326 struct cfg80211_registered_device
*rdev
= wiphy_to_rdev(wdev
->wiphy
);
330 trace_cfg80211_pmsr_complete(wdev
->wiphy
, wdev
, req
->cookie
);
332 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, gfp
);
336 hdr
= nl80211hdr_put(msg
, 0, 0, 0,
337 NL80211_CMD_PEER_MEASUREMENT_COMPLETE
);
341 if (nla_put_u32(msg
, NL80211_ATTR_WIPHY
, rdev
->wiphy_idx
) ||
342 nla_put_u64_64bit(msg
, NL80211_ATTR_WDEV
, wdev_id(wdev
),
346 if (nla_put_u64_64bit(msg
, NL80211_ATTR_COOKIE
, req
->cookie
,
350 genlmsg_end(msg
, hdr
);
351 genlmsg_unicast(wiphy_net(wdev
->wiphy
), msg
, req
->nl_portid
);
356 spin_lock_bh(&wdev
->pmsr_lock
);
357 list_del(&req
->list
);
358 spin_unlock_bh(&wdev
->pmsr_lock
);
361 EXPORT_SYMBOL_GPL(cfg80211_pmsr_complete
);
363 static int nl80211_pmsr_send_ftm_res(struct sk_buff
*msg
,
364 struct cfg80211_pmsr_result
*res
)
366 if (res
->status
== NL80211_PMSR_STATUS_FAILURE
) {
367 if (nla_put_u32(msg
, NL80211_PMSR_FTM_RESP_ATTR_FAIL_REASON
,
368 res
->ftm
.failure_reason
))
371 if (res
->ftm
.failure_reason
==
372 NL80211_PMSR_FTM_FAILURE_PEER_BUSY
&&
373 res
->ftm
.busy_retry_time
&&
374 nla_put_u32(msg
, NL80211_PMSR_FTM_RESP_ATTR_BUSY_RETRY_TIME
,
375 res
->ftm
.busy_retry_time
))
381 #define PUT(tp, attr, val) \
383 if (nla_put_##tp(msg, \
384 NL80211_PMSR_FTM_RESP_ATTR_##attr, \
389 #define PUTOPT(tp, attr, val) \
391 if (res->ftm.val##_valid) \
392 PUT(tp, attr, val); \
395 #define PUT_U64(attr, val) \
397 if (nla_put_u64_64bit(msg, \
398 NL80211_PMSR_FTM_RESP_ATTR_##attr,\
400 NL80211_PMSR_FTM_RESP_ATTR_PAD)) \
404 #define PUTOPT_U64(attr, val) \
406 if (res->ftm.val##_valid) \
407 PUT_U64(attr, val); \
410 if (res
->ftm
.burst_index
>= 0)
411 PUT(u32
, BURST_INDEX
, burst_index
);
412 PUTOPT(u32
, NUM_FTMR_ATTEMPTS
, num_ftmr_attempts
);
413 PUTOPT(u32
, NUM_FTMR_SUCCESSES
, num_ftmr_successes
);
414 PUT(u8
, NUM_BURSTS_EXP
, num_bursts_exp
);
415 PUT(u8
, BURST_DURATION
, burst_duration
);
416 PUT(u8
, FTMS_PER_BURST
, ftms_per_burst
);
417 PUTOPT(s32
, RSSI_AVG
, rssi_avg
);
418 PUTOPT(s32
, RSSI_SPREAD
, rssi_spread
);
419 if (res
->ftm
.tx_rate_valid
&&
420 !nl80211_put_sta_rate(msg
, &res
->ftm
.tx_rate
,
421 NL80211_PMSR_FTM_RESP_ATTR_TX_RATE
))
423 if (res
->ftm
.rx_rate_valid
&&
424 !nl80211_put_sta_rate(msg
, &res
->ftm
.rx_rate
,
425 NL80211_PMSR_FTM_RESP_ATTR_RX_RATE
))
427 PUTOPT_U64(RTT_AVG
, rtt_avg
);
428 PUTOPT_U64(RTT_VARIANCE
, rtt_variance
);
429 PUTOPT_U64(RTT_SPREAD
, rtt_spread
);
430 PUTOPT_U64(DIST_AVG
, dist_avg
);
431 PUTOPT_U64(DIST_VARIANCE
, dist_variance
);
432 PUTOPT_U64(DIST_SPREAD
, dist_spread
);
433 if (res
->ftm
.lci
&& res
->ftm
.lci_len
&&
434 nla_put(msg
, NL80211_PMSR_FTM_RESP_ATTR_LCI
,
435 res
->ftm
.lci_len
, res
->ftm
.lci
))
437 if (res
->ftm
.civicloc
&& res
->ftm
.civicloc_len
&&
438 nla_put(msg
, NL80211_PMSR_FTM_RESP_ATTR_CIVICLOC
,
439 res
->ftm
.civicloc_len
, res
->ftm
.civicloc
))
451 static int nl80211_pmsr_send_result(struct sk_buff
*msg
,
452 struct cfg80211_pmsr_result
*res
)
454 struct nlattr
*pmsr
, *peers
, *peer
, *resp
, *data
, *typedata
;
456 pmsr
= nla_nest_start_noflag(msg
, NL80211_ATTR_PEER_MEASUREMENTS
);
460 peers
= nla_nest_start_noflag(msg
, NL80211_PMSR_ATTR_PEERS
);
464 peer
= nla_nest_start_noflag(msg
, 1);
468 if (nla_put(msg
, NL80211_PMSR_PEER_ATTR_ADDR
, ETH_ALEN
, res
->addr
))
471 resp
= nla_nest_start_noflag(msg
, NL80211_PMSR_PEER_ATTR_RESP
);
475 if (nla_put_u32(msg
, NL80211_PMSR_RESP_ATTR_STATUS
, res
->status
) ||
476 nla_put_u64_64bit(msg
, NL80211_PMSR_RESP_ATTR_HOST_TIME
,
477 res
->host_time
, NL80211_PMSR_RESP_ATTR_PAD
))
480 if (res
->ap_tsf_valid
&&
481 nla_put_u64_64bit(msg
, NL80211_PMSR_RESP_ATTR_AP_TSF
,
482 res
->ap_tsf
, NL80211_PMSR_RESP_ATTR_PAD
))
485 if (res
->final
&& nla_put_flag(msg
, NL80211_PMSR_RESP_ATTR_FINAL
))
488 data
= nla_nest_start_noflag(msg
, NL80211_PMSR_RESP_ATTR_DATA
);
492 typedata
= nla_nest_start_noflag(msg
, res
->type
);
497 case NL80211_PMSR_TYPE_FTM
:
498 if (nl80211_pmsr_send_ftm_res(msg
, res
))
505 nla_nest_end(msg
, typedata
);
506 nla_nest_end(msg
, data
);
507 nla_nest_end(msg
, resp
);
508 nla_nest_end(msg
, peer
);
509 nla_nest_end(msg
, peers
);
510 nla_nest_end(msg
, pmsr
);
517 void cfg80211_pmsr_report(struct wireless_dev
*wdev
,
518 struct cfg80211_pmsr_request
*req
,
519 struct cfg80211_pmsr_result
*result
,
522 struct cfg80211_registered_device
*rdev
= wiphy_to_rdev(wdev
->wiphy
);
527 trace_cfg80211_pmsr_report(wdev
->wiphy
, wdev
, req
->cookie
,
531 * Currently, only variable items are LCI and civic location,
532 * both of which are reasonably short so we don't need to
533 * worry about them here for the allocation.
535 msg
= nlmsg_new(NLMSG_DEFAULT_SIZE
, gfp
);
539 hdr
= nl80211hdr_put(msg
, 0, 0, 0, NL80211_CMD_PEER_MEASUREMENT_RESULT
);
543 if (nla_put_u32(msg
, NL80211_ATTR_WIPHY
, rdev
->wiphy_idx
) ||
544 nla_put_u64_64bit(msg
, NL80211_ATTR_WDEV
, wdev_id(wdev
),
548 if (nla_put_u64_64bit(msg
, NL80211_ATTR_COOKIE
, req
->cookie
,
552 err
= nl80211_pmsr_send_result(msg
, result
);
554 pr_err_ratelimited("peer measurement result: message didn't fit!");
558 genlmsg_end(msg
, hdr
);
559 genlmsg_unicast(wiphy_net(wdev
->wiphy
), msg
, req
->nl_portid
);
564 EXPORT_SYMBOL_GPL(cfg80211_pmsr_report
);
566 static void cfg80211_pmsr_process_abort(struct wireless_dev
*wdev
)
568 struct cfg80211_registered_device
*rdev
= wiphy_to_rdev(wdev
->wiphy
);
569 struct cfg80211_pmsr_request
*req
, *tmp
;
570 LIST_HEAD(free_list
);
572 lockdep_assert_held(&wdev
->mtx
);
574 spin_lock_bh(&wdev
->pmsr_lock
);
575 list_for_each_entry_safe(req
, tmp
, &wdev
->pmsr_list
, list
) {
578 list_move_tail(&req
->list
, &free_list
);
580 spin_unlock_bh(&wdev
->pmsr_lock
);
582 list_for_each_entry_safe(req
, tmp
, &free_list
, list
) {
583 rdev_abort_pmsr(rdev
, wdev
, req
);
589 void cfg80211_pmsr_free_wk(struct work_struct
*work
)
591 struct wireless_dev
*wdev
= container_of(work
, struct wireless_dev
,
595 cfg80211_pmsr_process_abort(wdev
);
599 void cfg80211_pmsr_wdev_down(struct wireless_dev
*wdev
)
601 struct cfg80211_pmsr_request
*req
;
604 spin_lock_bh(&wdev
->pmsr_lock
);
605 list_for_each_entry(req
, &wdev
->pmsr_list
, list
) {
609 spin_unlock_bh(&wdev
->pmsr_lock
);
612 cfg80211_pmsr_process_abort(wdev
);
614 WARN_ON(!list_empty(&wdev
->pmsr_list
));
617 void cfg80211_release_pmsr(struct wireless_dev
*wdev
, u32 portid
)
619 struct cfg80211_pmsr_request
*req
;
621 spin_lock_bh(&wdev
->pmsr_lock
);
622 list_for_each_entry(req
, &wdev
->pmsr_list
, list
) {
623 if (req
->nl_portid
== portid
) {
625 schedule_work(&wdev
->pmsr_free_wk
);
628 spin_unlock_bh(&wdev
->pmsr_lock
);
631 #endif /* __PMSR_H */