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 pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid, 175 join_info->bssid); 176 177 cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, 178 0, le16_to_cpu(join_info->status), GFP_KERNEL); 179 180 if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) 181 netif_carrier_on(vif->netdev); 182 183 return 0; 184 } 185 186 static int 187 qtnf_event_handle_bss_leave(struct qtnf_vif *vif, 188 const struct qlink_event_bss_leave *leave_info, 189 u16 len) 190 { 191 if (unlikely(len < sizeof(*leave_info))) { 192 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 193 vif->mac->macid, vif->vifid, len, 194 sizeof(struct qlink_event_bss_leave)); 195 return -EINVAL; 196 } 197 198 if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { 199 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n", 200 vif->mac->macid, vif->vifid); 201 return -EPROTO; 202 } 203 204 pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid); 205 206 cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason), 207 NULL, 0, 0, GFP_KERNEL); 208 netif_carrier_off(vif->netdev); 209 210 return 0; 211 } 212 213 static int 214 qtnf_event_handle_mgmt_received(struct qtnf_vif *vif, 215 const struct qlink_event_rxmgmt *rxmgmt, 216 u16 len) 217 { 218 const size_t min_len = sizeof(*rxmgmt) + 219 sizeof(struct ieee80211_hdr_3addr); 220 const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data; 221 const u16 frame_len = len - sizeof(*rxmgmt); 222 enum nl80211_rxmgmt_flags flags = 0; 223 224 if (unlikely(len < min_len)) { 225 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 226 vif->mac->macid, vif->vifid, len, min_len); 227 return -EINVAL; 228 } 229 230 if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED) 231 flags |= NL80211_RXMGMT_FLAG_ANSWERED; 232 233 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len, 234 le16_to_cpu(frame->frame_control), frame->addr2); 235 236 cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), rxmgmt->sig_dbm, 237 rxmgmt->frame_data, frame_len, flags); 238 239 return 0; 240 } 241 242 static int 243 qtnf_event_handle_scan_results(struct qtnf_vif *vif, 244 const struct qlink_event_scan_result *sr, 245 u16 len) 246 { 247 struct cfg80211_bss *bss; 248 struct ieee80211_channel *channel; 249 struct wiphy *wiphy = priv_to_wiphy(vif->mac); 250 enum cfg80211_bss_frame_type frame_type = CFG80211_BSS_FTYPE_UNKNOWN; 251 size_t payload_len; 252 u16 tlv_type; 253 u16 tlv_value_len; 254 size_t tlv_full_len; 255 const struct qlink_tlv_hdr *tlv; 256 const u8 *ies = NULL; 257 size_t ies_len = 0; 258 259 if (len < sizeof(*sr)) { 260 pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid, 261 vif->vifid); 262 return -EINVAL; 263 } 264 265 channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq)); 266 if (!channel) { 267 pr_err("VIF%u.%u: channel at %u MHz not found\n", 268 vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq)); 269 return -EINVAL; 270 } 271 272 payload_len = len - sizeof(*sr); 273 tlv = (struct qlink_tlv_hdr *)sr->payload; 274 275 while (payload_len >= sizeof(struct qlink_tlv_hdr)) { 276 tlv_type = le16_to_cpu(tlv->type); 277 tlv_value_len = le16_to_cpu(tlv->len); 278 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); 279 280 if (tlv_full_len > payload_len) 281 return -EINVAL; 282 283 if (tlv_type == QTN_TLV_ID_IE_SET) { 284 const struct qlink_tlv_ie_set *ie_set; 285 unsigned int ie_len; 286 287 if (payload_len < sizeof(*ie_set)) 288 return -EINVAL; 289 290 ie_set = (const struct qlink_tlv_ie_set *)tlv; 291 ie_len = tlv_value_len - 292 (sizeof(*ie_set) - sizeof(ie_set->hdr)); 293 294 switch (ie_set->type) { 295 case QLINK_IE_SET_BEACON_IES: 296 frame_type = CFG80211_BSS_FTYPE_BEACON; 297 break; 298 case QLINK_IE_SET_PROBE_RESP_IES: 299 frame_type = CFG80211_BSS_FTYPE_PRESP; 300 break; 301 default: 302 frame_type = CFG80211_BSS_FTYPE_UNKNOWN; 303 } 304 305 if (ie_len) { 306 ies = ie_set->ie_data; 307 ies_len = ie_len; 308 } 309 } 310 311 payload_len -= tlv_full_len; 312 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); 313 } 314 315 if (payload_len) 316 return -EINVAL; 317 318 bss = cfg80211_inform_bss(wiphy, channel, frame_type, 319 sr->bssid, get_unaligned_le64(&sr->tsf), 320 le16_to_cpu(sr->capab), 321 le16_to_cpu(sr->bintval), ies, ies_len, 322 DBM_TO_MBM(sr->sig_dbm), GFP_KERNEL); 323 if (!bss) 324 return -ENOMEM; 325 326 cfg80211_put_bss(wiphy, bss); 327 328 return 0; 329 } 330 331 static int 332 qtnf_event_handle_scan_complete(struct qtnf_wmac *mac, 333 const struct qlink_event_scan_complete *status, 334 u16 len) 335 { 336 if (len < sizeof(*status)) { 337 pr_err("MAC%u: payload is too short\n", mac->macid); 338 return -EINVAL; 339 } 340 341 qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED); 342 343 return 0; 344 } 345 346 static int 347 qtnf_event_handle_freq_change(struct qtnf_wmac *mac, 348 const struct qlink_event_freq_change *data, 349 u16 len) 350 { 351 struct wiphy *wiphy = priv_to_wiphy(mac); 352 struct cfg80211_chan_def chandef; 353 struct qtnf_vif *vif; 354 int i; 355 356 if (len < sizeof(*data)) { 357 pr_err("MAC%u: payload is too short\n", mac->macid); 358 return -EINVAL; 359 } 360 361 if (!wiphy->registered) 362 return 0; 363 364 qlink_chandef_q2cfg(wiphy, &data->chan, &chandef); 365 366 if (!cfg80211_chandef_valid(&chandef)) { 367 pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", 368 mac->macid, chandef.chan->center_freq, 369 chandef.center_freq1, chandef.center_freq2, 370 chandef.width); 371 return -EINVAL; 372 } 373 374 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n", 375 mac->macid, chandef.chan->hw_value, chandef.center_freq1, 376 chandef.center_freq2, chandef.width); 377 378 for (i = 0; i < QTNF_MAX_INTF; i++) { 379 vif = &mac->iflist[i]; 380 if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) 381 continue; 382 383 if (vif->netdev) { 384 mutex_lock(&vif->wdev.mtx); 385 cfg80211_ch_switch_notify(vif->netdev, &chandef); 386 mutex_unlock(&vif->wdev.mtx); 387 } 388 } 389 390 return 0; 391 } 392 393 static int qtnf_event_handle_radar(struct qtnf_vif *vif, 394 const struct qlink_event_radar *ev, 395 u16 len) 396 { 397 struct wiphy *wiphy = priv_to_wiphy(vif->mac); 398 struct cfg80211_chan_def chandef; 399 400 if (len < sizeof(*ev)) { 401 pr_err("MAC%u: payload is too short\n", vif->mac->macid); 402 return -EINVAL; 403 } 404 405 if (!wiphy->registered || !vif->netdev) 406 return 0; 407 408 qlink_chandef_q2cfg(wiphy, &ev->chan, &chandef); 409 410 if (!cfg80211_chandef_valid(&chandef)) { 411 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", 412 vif->mac->macid, 413 chandef.center_freq1, chandef.center_freq2, 414 chandef.width); 415 return -EINVAL; 416 } 417 418 pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n", 419 vif->netdev->name, ev->event, 420 chandef.center_freq1, chandef.center_freq2, 421 chandef.width); 422 423 switch (ev->event) { 424 case QLINK_RADAR_DETECTED: 425 cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL); 426 break; 427 case QLINK_RADAR_CAC_FINISHED: 428 if (!vif->wdev.cac_started) 429 break; 430 431 cfg80211_cac_event(vif->netdev, &chandef, 432 NL80211_RADAR_CAC_FINISHED, GFP_KERNEL); 433 break; 434 case QLINK_RADAR_CAC_ABORTED: 435 if (!vif->wdev.cac_started) 436 break; 437 438 cfg80211_cac_event(vif->netdev, &chandef, 439 NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); 440 break; 441 case QLINK_RADAR_CAC_STARTED: 442 if (vif->wdev.cac_started) 443 break; 444 445 if (!wiphy_ext_feature_isset(wiphy, 446 NL80211_EXT_FEATURE_DFS_OFFLOAD)) 447 break; 448 449 cfg80211_cac_event(vif->netdev, &chandef, 450 NL80211_RADAR_CAC_STARTED, GFP_KERNEL); 451 break; 452 default: 453 pr_warn("%s: unhandled radar event %u\n", 454 vif->netdev->name, ev->event); 455 break; 456 } 457 458 return 0; 459 } 460 461 static int qtnf_event_parse(struct qtnf_wmac *mac, 462 const struct sk_buff *event_skb) 463 { 464 const struct qlink_event *event; 465 struct qtnf_vif *vif = NULL; 466 int ret = -1; 467 u16 event_id; 468 u16 event_len; 469 470 event = (const struct qlink_event *)event_skb->data; 471 event_id = le16_to_cpu(event->event_id); 472 event_len = le16_to_cpu(event->mhdr.len); 473 474 if (likely(event->vifid < QTNF_MAX_INTF)) { 475 vif = &mac->iflist[event->vifid]; 476 } else { 477 pr_err("invalid vif(%u)\n", event->vifid); 478 return -EINVAL; 479 } 480 481 switch (event_id) { 482 case QLINK_EVENT_STA_ASSOCIATED: 483 ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event, 484 event_len); 485 break; 486 case QLINK_EVENT_STA_DEAUTH: 487 ret = qtnf_event_handle_sta_deauth(mac, vif, 488 (const void *)event, 489 event_len); 490 break; 491 case QLINK_EVENT_MGMT_RECEIVED: 492 ret = qtnf_event_handle_mgmt_received(vif, (const void *)event, 493 event_len); 494 break; 495 case QLINK_EVENT_SCAN_RESULTS: 496 ret = qtnf_event_handle_scan_results(vif, (const void *)event, 497 event_len); 498 break; 499 case QLINK_EVENT_SCAN_COMPLETE: 500 ret = qtnf_event_handle_scan_complete(mac, (const void *)event, 501 event_len); 502 break; 503 case QLINK_EVENT_BSS_JOIN: 504 ret = qtnf_event_handle_bss_join(vif, (const void *)event, 505 event_len); 506 break; 507 case QLINK_EVENT_BSS_LEAVE: 508 ret = qtnf_event_handle_bss_leave(vif, (const void *)event, 509 event_len); 510 break; 511 case QLINK_EVENT_FREQ_CHANGE: 512 ret = qtnf_event_handle_freq_change(mac, (const void *)event, 513 event_len); 514 break; 515 case QLINK_EVENT_RADAR: 516 ret = qtnf_event_handle_radar(vif, (const void *)event, 517 event_len); 518 break; 519 default: 520 pr_warn("unknown event type: %x\n", event_id); 521 break; 522 } 523 524 return ret; 525 } 526 527 static int qtnf_event_process_skb(struct qtnf_bus *bus, 528 const struct sk_buff *skb) 529 { 530 const struct qlink_event *event; 531 struct qtnf_wmac *mac; 532 int res; 533 534 if (unlikely(!skb || skb->len < sizeof(*event))) { 535 pr_err("invalid event buffer\n"); 536 return -EINVAL; 537 } 538 539 event = (struct qlink_event *)skb->data; 540 541 mac = qtnf_core_get_mac(bus, event->macid); 542 543 pr_debug("new event id:%x len:%u mac:%u vif:%u\n", 544 le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len), 545 event->macid, event->vifid); 546 547 if (unlikely(!mac)) 548 return -ENXIO; 549 550 rtnl_lock(); 551 res = qtnf_event_parse(mac, skb); 552 rtnl_unlock(); 553 554 return res; 555 } 556 557 void qtnf_event_work_handler(struct work_struct *work) 558 { 559 struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work); 560 struct sk_buff_head *event_queue = &bus->trans.event_queue; 561 struct sk_buff *current_event_skb = skb_dequeue(event_queue); 562 563 while (current_event_skb) { 564 qtnf_event_process_skb(bus, current_event_skb); 565 dev_kfree_skb_any(current_event_skb); 566 current_event_skb = skb_dequeue(event_queue); 567 } 568 } 569