1 /* 2 * Copyright (c) 2015-2016 Quantenna Communications, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 2 8 * of the License, or (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 */ 16 17 #include <linux/kernel.h> 18 #include <linux/module.h> 19 #include <linux/slab.h> 20 21 #include "cfg80211.h" 22 #include "core.h" 23 #include "qlink.h" 24 #include "bus.h" 25 #include "trans.h" 26 #include "util.h" 27 #include "event.h" 28 #include "qlink_util.h" 29 30 static int 31 qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif, 32 const struct qlink_event_sta_assoc *sta_assoc, 33 u16 len) 34 { 35 const u8 *sta_addr; 36 u16 frame_control; 37 struct station_info *sinfo; 38 size_t payload_len; 39 u16 tlv_type; 40 u16 tlv_value_len; 41 size_t tlv_full_len; 42 const struct qlink_tlv_hdr *tlv; 43 int ret = 0; 44 45 if (unlikely(len < sizeof(*sta_assoc))) { 46 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 47 mac->macid, vif->vifid, len, sizeof(*sta_assoc)); 48 return -EINVAL; 49 } 50 51 if (vif->wdev.iftype != NL80211_IFTYPE_AP) { 52 pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n", 53 mac->macid, vif->vifid); 54 return -EPROTO; 55 } 56 57 sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL); 58 if (!sinfo) 59 return -ENOMEM; 60 61 sta_addr = sta_assoc->sta_addr; 62 frame_control = le16_to_cpu(sta_assoc->frame_control); 63 64 pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr, 65 frame_control); 66 67 qtnf_sta_list_add(vif, sta_addr); 68 69 sinfo->assoc_req_ies = NULL; 70 sinfo->assoc_req_ies_len = 0; 71 sinfo->generation = vif->generation; 72 73 payload_len = len - sizeof(*sta_assoc); 74 tlv = (const struct qlink_tlv_hdr *)sta_assoc->ies; 75 76 while (payload_len >= sizeof(*tlv)) { 77 tlv_type = le16_to_cpu(tlv->type); 78 tlv_value_len = le16_to_cpu(tlv->len); 79 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); 80 81 if (tlv_full_len > payload_len) { 82 ret = -EINVAL; 83 goto out; 84 } 85 86 if (tlv_type == QTN_TLV_ID_IE_SET) { 87 const struct qlink_tlv_ie_set *ie_set; 88 unsigned int ie_len; 89 90 if (payload_len < sizeof(*ie_set)) { 91 ret = -EINVAL; 92 goto out; 93 } 94 95 ie_set = (const struct qlink_tlv_ie_set *)tlv; 96 ie_len = tlv_value_len - 97 (sizeof(*ie_set) - sizeof(ie_set->hdr)); 98 99 if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) { 100 sinfo->assoc_req_ies = ie_set->ie_data; 101 sinfo->assoc_req_ies_len = ie_len; 102 } 103 } 104 105 payload_len -= tlv_full_len; 106 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); 107 } 108 109 if (payload_len) { 110 ret = -EINVAL; 111 goto out; 112 } 113 114 cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, sinfo, 115 GFP_KERNEL); 116 117 out: 118 kfree(sinfo); 119 return ret; 120 } 121 122 static int 123 qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif, 124 const struct qlink_event_sta_deauth *sta_deauth, 125 u16 len) 126 { 127 const u8 *sta_addr; 128 u16 reason; 129 130 if (unlikely(len < sizeof(*sta_deauth))) { 131 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 132 mac->macid, vif->vifid, len, 133 sizeof(struct qlink_event_sta_deauth)); 134 return -EINVAL; 135 } 136 137 if (vif->wdev.iftype != NL80211_IFTYPE_AP) { 138 pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n", 139 mac->macid, vif->vifid); 140 return -EPROTO; 141 } 142 143 sta_addr = sta_deauth->sta_addr; 144 reason = le16_to_cpu(sta_deauth->reason); 145 146 pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid, 147 sta_addr, reason); 148 149 if (qtnf_sta_list_del(vif, sta_addr)) 150 cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr, 151 GFP_KERNEL); 152 153 return 0; 154 } 155 156 static int 157 qtnf_event_handle_bss_join(struct qtnf_vif *vif, 158 const struct qlink_event_bss_join *join_info, 159 u16 len) 160 { 161 if (unlikely(len < sizeof(*join_info))) { 162 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 163 vif->mac->macid, vif->vifid, len, 164 sizeof(struct qlink_event_bss_join)); 165 return -EINVAL; 166 } 167 168 if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { 169 pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n", 170 vif->mac->macid, vif->vifid); 171 return -EPROTO; 172 } 173 174 if (vif->sta_state != QTNF_STA_CONNECTING) { 175 pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n", 176 vif->mac->macid, vif->vifid); 177 return -EPROTO; 178 } 179 180 pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid, 181 join_info->bssid); 182 183 cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, 184 0, le16_to_cpu(join_info->status), GFP_KERNEL); 185 186 if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) { 187 vif->sta_state = QTNF_STA_CONNECTED; 188 netif_carrier_on(vif->netdev); 189 } else { 190 vif->sta_state = QTNF_STA_DISCONNECTED; 191 } 192 193 return 0; 194 } 195 196 static int 197 qtnf_event_handle_bss_leave(struct qtnf_vif *vif, 198 const struct qlink_event_bss_leave *leave_info, 199 u16 len) 200 { 201 if (unlikely(len < sizeof(*leave_info))) { 202 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 203 vif->mac->macid, vif->vifid, len, 204 sizeof(struct qlink_event_bss_leave)); 205 return -EINVAL; 206 } 207 208 if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { 209 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n", 210 vif->mac->macid, vif->vifid); 211 return -EPROTO; 212 } 213 214 if (vif->sta_state != QTNF_STA_CONNECTED) 215 pr_warn("VIF%u.%u: BSS_LEAVE event when STA is not connected\n", 216 vif->mac->macid, vif->vifid); 217 218 pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid); 219 220 cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason), 221 NULL, 0, 0, GFP_KERNEL); 222 223 vif->sta_state = QTNF_STA_DISCONNECTED; 224 netif_carrier_off(vif->netdev); 225 226 return 0; 227 } 228 229 static int 230 qtnf_event_handle_mgmt_received(struct qtnf_vif *vif, 231 const struct qlink_event_rxmgmt *rxmgmt, 232 u16 len) 233 { 234 const size_t min_len = sizeof(*rxmgmt) + 235 sizeof(struct ieee80211_hdr_3addr); 236 const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data; 237 const u16 frame_len = len - sizeof(*rxmgmt); 238 enum nl80211_rxmgmt_flags flags = 0; 239 240 if (unlikely(len < min_len)) { 241 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 242 vif->mac->macid, vif->vifid, len, min_len); 243 return -EINVAL; 244 } 245 246 if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED) 247 flags |= NL80211_RXMGMT_FLAG_ANSWERED; 248 249 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len, 250 le16_to_cpu(frame->frame_control), frame->addr2); 251 252 cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), rxmgmt->sig_dbm, 253 rxmgmt->frame_data, frame_len, flags); 254 255 return 0; 256 } 257 258 static int 259 qtnf_event_handle_scan_results(struct qtnf_vif *vif, 260 const struct qlink_event_scan_result *sr, 261 u16 len) 262 { 263 struct cfg80211_bss *bss; 264 struct ieee80211_channel *channel; 265 struct wiphy *wiphy = priv_to_wiphy(vif->mac); 266 enum cfg80211_bss_frame_type frame_type = CFG80211_BSS_FTYPE_UNKNOWN; 267 size_t payload_len; 268 u16 tlv_type; 269 u16 tlv_value_len; 270 size_t tlv_full_len; 271 const struct qlink_tlv_hdr *tlv; 272 const u8 *ies = NULL; 273 size_t ies_len = 0; 274 275 if (len < sizeof(*sr)) { 276 pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid, 277 vif->vifid); 278 return -EINVAL; 279 } 280 281 channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq)); 282 if (!channel) { 283 pr_err("VIF%u.%u: channel at %u MHz not found\n", 284 vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq)); 285 return -EINVAL; 286 } 287 288 payload_len = len - sizeof(*sr); 289 tlv = (struct qlink_tlv_hdr *)sr->payload; 290 291 while (payload_len >= sizeof(struct qlink_tlv_hdr)) { 292 tlv_type = le16_to_cpu(tlv->type); 293 tlv_value_len = le16_to_cpu(tlv->len); 294 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); 295 296 if (tlv_full_len > payload_len) 297 return -EINVAL; 298 299 if (tlv_type == QTN_TLV_ID_IE_SET) { 300 const struct qlink_tlv_ie_set *ie_set; 301 unsigned int ie_len; 302 303 if (payload_len < sizeof(*ie_set)) 304 return -EINVAL; 305 306 ie_set = (const struct qlink_tlv_ie_set *)tlv; 307 ie_len = tlv_value_len - 308 (sizeof(*ie_set) - sizeof(ie_set->hdr)); 309 310 switch (ie_set->type) { 311 case QLINK_IE_SET_BEACON_IES: 312 frame_type = CFG80211_BSS_FTYPE_BEACON; 313 break; 314 case QLINK_IE_SET_PROBE_RESP_IES: 315 frame_type = CFG80211_BSS_FTYPE_PRESP; 316 break; 317 default: 318 frame_type = CFG80211_BSS_FTYPE_UNKNOWN; 319 } 320 321 if (ie_len) { 322 ies = ie_set->ie_data; 323 ies_len = ie_len; 324 } 325 } 326 327 payload_len -= tlv_full_len; 328 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); 329 } 330 331 if (payload_len) 332 return -EINVAL; 333 334 bss = cfg80211_inform_bss(wiphy, channel, frame_type, 335 sr->bssid, get_unaligned_le64(&sr->tsf), 336 le16_to_cpu(sr->capab), 337 le16_to_cpu(sr->bintval), ies, ies_len, 338 DBM_TO_MBM(sr->sig_dbm), GFP_KERNEL); 339 if (!bss) 340 return -ENOMEM; 341 342 cfg80211_put_bss(wiphy, bss); 343 344 return 0; 345 } 346 347 static int 348 qtnf_event_handle_scan_complete(struct qtnf_wmac *mac, 349 const struct qlink_event_scan_complete *status, 350 u16 len) 351 { 352 if (len < sizeof(*status)) { 353 pr_err("MAC%u: payload is too short\n", mac->macid); 354 return -EINVAL; 355 } 356 357 qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED); 358 359 return 0; 360 } 361 362 static int 363 qtnf_event_handle_freq_change(struct qtnf_wmac *mac, 364 const struct qlink_event_freq_change *data, 365 u16 len) 366 { 367 struct wiphy *wiphy = priv_to_wiphy(mac); 368 struct cfg80211_chan_def chandef; 369 struct qtnf_vif *vif; 370 int i; 371 372 if (len < sizeof(*data)) { 373 pr_err("MAC%u: payload is too short\n", mac->macid); 374 return -EINVAL; 375 } 376 377 if (!wiphy->registered) 378 return 0; 379 380 qlink_chandef_q2cfg(wiphy, &data->chan, &chandef); 381 382 if (!cfg80211_chandef_valid(&chandef)) { 383 pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", 384 mac->macid, chandef.chan->center_freq, 385 chandef.center_freq1, chandef.center_freq2, 386 chandef.width); 387 return -EINVAL; 388 } 389 390 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n", 391 mac->macid, chandef.chan->hw_value, chandef.center_freq1, 392 chandef.center_freq2, chandef.width); 393 394 for (i = 0; i < QTNF_MAX_INTF; i++) { 395 vif = &mac->iflist[i]; 396 if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) 397 continue; 398 399 if (vif->netdev) { 400 mutex_lock(&vif->wdev.mtx); 401 cfg80211_ch_switch_notify(vif->netdev, &chandef); 402 mutex_unlock(&vif->wdev.mtx); 403 } 404 } 405 406 return 0; 407 } 408 409 static int qtnf_event_handle_radar(struct qtnf_vif *vif, 410 const struct qlink_event_radar *ev, 411 u16 len) 412 { 413 struct wiphy *wiphy = priv_to_wiphy(vif->mac); 414 struct cfg80211_chan_def chandef; 415 416 if (len < sizeof(*ev)) { 417 pr_err("MAC%u: payload is too short\n", vif->mac->macid); 418 return -EINVAL; 419 } 420 421 if (!wiphy->registered || !vif->netdev) 422 return 0; 423 424 qlink_chandef_q2cfg(wiphy, &ev->chan, &chandef); 425 426 if (!cfg80211_chandef_valid(&chandef)) { 427 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", 428 vif->mac->macid, 429 chandef.center_freq1, chandef.center_freq2, 430 chandef.width); 431 return -EINVAL; 432 } 433 434 pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n", 435 vif->netdev->name, ev->event, 436 chandef.center_freq1, chandef.center_freq2, 437 chandef.width); 438 439 switch (ev->event) { 440 case QLINK_RADAR_DETECTED: 441 cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL); 442 break; 443 case QLINK_RADAR_CAC_FINISHED: 444 if (!vif->wdev.cac_started) 445 break; 446 447 cfg80211_cac_event(vif->netdev, &chandef, 448 NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); 449 break; 450 case QLINK_RADAR_CAC_ABORTED: 451 if (!vif->wdev.cac_started) 452 break; 453 454 cfg80211_cac_event(vif->netdev, &chandef, 455 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); 456 break; 457 case QLINK_RADAR_CAC_STARTED: 458 if (vif->wdev.cac_started) 459 break; 460 461 if (!wiphy_ext_feature_isset(wiphy, 462 NL80211_EXT_FEATURE_DFS_OFFLOAD)) 463 break; 464 465 cfg80211_cac_event(vif->netdev, &chandef, 466 NL80211_RADAR_CAC_STARTED, GFP_KERNEL); 467 break; 468 default: 469 pr_warn("%s: unhandled radar event %u\n", 470 vif->netdev->name, ev->event); 471 break; 472 } 473 474 return 0; 475 } 476 477 static int qtnf_event_parse(struct qtnf_wmac *mac, 478 const struct sk_buff *event_skb) 479 { 480 const struct qlink_event *event; 481 struct qtnf_vif *vif = NULL; 482 int ret = -1; 483 u16 event_id; 484 u16 event_len; 485 486 event = (const struct qlink_event *)event_skb->data; 487 event_id = le16_to_cpu(event->event_id); 488 event_len = le16_to_cpu(event->mhdr.len); 489 490 if (likely(event->vifid < QTNF_MAX_INTF)) { 491 vif = &mac->iflist[event->vifid]; 492 } else { 493 pr_err("invalid vif(%u)\n", event->vifid); 494 return -EINVAL; 495 } 496 497 switch (event_id) { 498 case QLINK_EVENT_STA_ASSOCIATED: 499 ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event, 500 event_len); 501 break; 502 case QLINK_EVENT_STA_DEAUTH: 503 ret = qtnf_event_handle_sta_deauth(mac, vif, 504 (const void *)event, 505 event_len); 506 break; 507 case QLINK_EVENT_MGMT_RECEIVED: 508 ret = qtnf_event_handle_mgmt_received(vif, (const void *)event, 509 event_len); 510 break; 511 case QLINK_EVENT_SCAN_RESULTS: 512 ret = qtnf_event_handle_scan_results(vif, (const void *)event, 513 event_len); 514 break; 515 case QLINK_EVENT_SCAN_COMPLETE: 516 ret = qtnf_event_handle_scan_complete(mac, (const void *)event, 517 event_len); 518 break; 519 case QLINK_EVENT_BSS_JOIN: 520 ret = qtnf_event_handle_bss_join(vif, (const void *)event, 521 event_len); 522 break; 523 case QLINK_EVENT_BSS_LEAVE: 524 ret = qtnf_event_handle_bss_leave(vif, (const void *)event, 525 event_len); 526 break; 527 case QLINK_EVENT_FREQ_CHANGE: 528 ret = qtnf_event_handle_freq_change(mac, (const void *)event, 529 event_len); 530 break; 531 case QLINK_EVENT_RADAR: 532 ret = qtnf_event_handle_radar(vif, (const void *)event, 533 event_len); 534 break; 535 default: 536 pr_warn("unknown event type: %x\n", event_id); 537 break; 538 } 539 540 return ret; 541 } 542 543 static int qtnf_event_process_skb(struct qtnf_bus *bus, 544 const struct sk_buff *skb) 545 { 546 const struct qlink_event *event; 547 struct qtnf_wmac *mac; 548 int res; 549 550 if (unlikely(!skb || skb->len < sizeof(*event))) { 551 pr_err("invalid event buffer\n"); 552 return -EINVAL; 553 } 554 555 event = (struct qlink_event *)skb->data; 556 557 mac = qtnf_core_get_mac(bus, event->macid); 558 559 pr_debug("new event id:%x len:%u mac:%u vif:%u\n", 560 le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len), 561 event->macid, event->vifid); 562 563 if (unlikely(!mac)) 564 return -ENXIO; 565 566 rtnl_lock(); 567 res = qtnf_event_parse(mac, skb); 568 rtnl_unlock(); 569 570 return res; 571 } 572 573 void qtnf_event_work_handler(struct work_struct *work) 574 { 575 struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work); 576 struct sk_buff_head *event_queue = &bus->trans.event_queue; 577 struct sk_buff *current_event_skb = skb_dequeue(event_queue); 578 579 while (current_event_skb) { 580 qtnf_event_process_skb(bus, current_event_skb); 581 dev_kfree_skb_any(current_event_skb); 582 current_event_skb = skb_dequeue(event_queue); 583 } 584 } 585