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