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 = { 0 }; 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 44 if (unlikely(len < sizeof(*sta_assoc))) { 45 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 46 mac->macid, vif->vifid, len, sizeof(*sta_assoc)); 47 return -EINVAL; 48 } 49 50 if (vif->wdev.iftype != NL80211_IFTYPE_AP) { 51 pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n", 52 mac->macid, vif->vifid); 53 return -EPROTO; 54 } 55 56 sta_addr = sta_assoc->sta_addr; 57 frame_control = le16_to_cpu(sta_assoc->frame_control); 58 59 pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr, 60 frame_control); 61 62 qtnf_sta_list_add(&vif->sta_list, sta_addr); 63 64 sinfo.assoc_req_ies = NULL; 65 sinfo.assoc_req_ies_len = 0; 66 67 payload_len = len - sizeof(*sta_assoc); 68 tlv = (struct qlink_tlv_hdr *)sta_assoc->ies; 69 70 while (payload_len >= sizeof(struct qlink_tlv_hdr)) { 71 tlv_type = le16_to_cpu(tlv->type); 72 tlv_value_len = le16_to_cpu(tlv->len); 73 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); 74 75 if (tlv_full_len > payload_len) { 76 pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", 77 mac->macid, vif->vifid, tlv_type, 78 tlv_value_len); 79 return -EINVAL; 80 } 81 82 if (tlv_type == QTN_TLV_ID_IE_SET) { 83 sinfo.assoc_req_ies = tlv->val; 84 sinfo.assoc_req_ies_len = tlv_value_len; 85 } 86 87 payload_len -= tlv_full_len; 88 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); 89 } 90 91 if (payload_len) { 92 pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", 93 mac->macid, vif->vifid, payload_len); 94 return -EINVAL; 95 } 96 97 cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, &sinfo, 98 GFP_KERNEL); 99 100 return 0; 101 } 102 103 static int 104 qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif, 105 const struct qlink_event_sta_deauth *sta_deauth, 106 u16 len) 107 { 108 const u8 *sta_addr; 109 u16 reason; 110 111 if (unlikely(len < sizeof(*sta_deauth))) { 112 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 113 mac->macid, vif->vifid, len, 114 sizeof(struct qlink_event_sta_deauth)); 115 return -EINVAL; 116 } 117 118 if (vif->wdev.iftype != NL80211_IFTYPE_AP) { 119 pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n", 120 mac->macid, vif->vifid); 121 return -EPROTO; 122 } 123 124 sta_addr = sta_deauth->sta_addr; 125 reason = le16_to_cpu(sta_deauth->reason); 126 127 pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid, 128 sta_addr, reason); 129 130 if (qtnf_sta_list_del(&vif->sta_list, sta_addr)) 131 cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr, 132 GFP_KERNEL); 133 134 return 0; 135 } 136 137 static int 138 qtnf_event_handle_bss_join(struct qtnf_vif *vif, 139 const struct qlink_event_bss_join *join_info, 140 u16 len) 141 { 142 if (unlikely(len < sizeof(*join_info))) { 143 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 144 vif->mac->macid, vif->vifid, len, 145 sizeof(struct qlink_event_bss_join)); 146 return -EINVAL; 147 } 148 149 if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { 150 pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n", 151 vif->mac->macid, vif->vifid); 152 return -EPROTO; 153 } 154 155 if (vif->sta_state != QTNF_STA_CONNECTING) { 156 pr_err("VIF%u.%u: BSS_JOIN event when STA is not connecting\n", 157 vif->mac->macid, vif->vifid); 158 return -EPROTO; 159 } 160 161 pr_debug("VIF%u.%u: BSSID:%pM\n", vif->mac->macid, vif->vifid, 162 join_info->bssid); 163 164 cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, NULL, 165 0, le16_to_cpu(join_info->status), GFP_KERNEL); 166 167 if (le16_to_cpu(join_info->status) == WLAN_STATUS_SUCCESS) { 168 vif->sta_state = QTNF_STA_CONNECTED; 169 netif_carrier_on(vif->netdev); 170 } else { 171 vif->sta_state = QTNF_STA_DISCONNECTED; 172 } 173 174 return 0; 175 } 176 177 static int 178 qtnf_event_handle_bss_leave(struct qtnf_vif *vif, 179 const struct qlink_event_bss_leave *leave_info, 180 u16 len) 181 { 182 if (unlikely(len < sizeof(*leave_info))) { 183 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 184 vif->mac->macid, vif->vifid, len, 185 sizeof(struct qlink_event_bss_leave)); 186 return -EINVAL; 187 } 188 189 if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { 190 pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n", 191 vif->mac->macid, vif->vifid); 192 return -EPROTO; 193 } 194 195 if (vif->sta_state != QTNF_STA_CONNECTED) { 196 pr_err("VIF%u.%u: BSS_LEAVE event when STA is not connected\n", 197 vif->mac->macid, vif->vifid); 198 return -EPROTO; 199 } 200 201 pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid); 202 203 cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason), 204 NULL, 0, 0, GFP_KERNEL); 205 206 vif->sta_state = QTNF_STA_DISCONNECTED; 207 netif_carrier_off(vif->netdev); 208 209 return 0; 210 } 211 212 static int 213 qtnf_event_handle_mgmt_received(struct qtnf_vif *vif, 214 const struct qlink_event_rxmgmt *rxmgmt, 215 u16 len) 216 { 217 const size_t min_len = sizeof(*rxmgmt) + 218 sizeof(struct ieee80211_hdr_3addr); 219 const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data; 220 const u16 frame_len = len - sizeof(*rxmgmt); 221 enum nl80211_rxmgmt_flags flags = 0; 222 223 if (unlikely(len < min_len)) { 224 pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", 225 vif->mac->macid, vif->vifid, len, min_len); 226 return -EINVAL; 227 } 228 229 if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED) 230 flags |= NL80211_RXMGMT_FLAG_ANSWERED; 231 232 pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len, 233 le16_to_cpu(frame->frame_control), frame->addr2); 234 235 cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), 236 le32_to_cpu(rxmgmt->sig_dbm), rxmgmt->frame_data, 237 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; 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 257 const u8 *ies = NULL; 258 size_t ies_len = 0; 259 260 if (len < sizeof(*sr)) { 261 pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid, 262 vif->vifid); 263 return -EINVAL; 264 } 265 266 channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq)); 267 if (!channel) { 268 pr_err("VIF%u.%u: channel at %u MHz not found\n", 269 vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq)); 270 return -EINVAL; 271 } 272 273 switch (sr->frame_type) { 274 case QLINK_BSS_FTYPE_BEACON: 275 frame_type = CFG80211_BSS_FTYPE_BEACON; 276 break; 277 case QLINK_BSS_FTYPE_PRESP: 278 frame_type = CFG80211_BSS_FTYPE_PRESP; 279 break; 280 default: 281 frame_type = CFG80211_BSS_FTYPE_UNKNOWN; 282 } 283 284 payload_len = len - sizeof(*sr); 285 tlv = (struct qlink_tlv_hdr *)sr->payload; 286 287 while (payload_len >= sizeof(struct qlink_tlv_hdr)) { 288 tlv_type = le16_to_cpu(tlv->type); 289 tlv_value_len = le16_to_cpu(tlv->len); 290 tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); 291 292 if (tlv_full_len > payload_len) { 293 pr_warn("VIF%u.%u: malformed TLV 0x%.2X; LEN: %u\n", 294 vif->mac->macid, vif->vifid, tlv_type, 295 tlv_value_len); 296 return -EINVAL; 297 } 298 299 if (tlv_type == QTN_TLV_ID_IE_SET) { 300 ies = tlv->val; 301 ies_len = tlv_value_len; 302 } 303 304 payload_len -= tlv_full_len; 305 tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); 306 } 307 308 if (payload_len) { 309 pr_warn("VIF%u.%u: malformed TLV buf; bytes left: %zu\n", 310 vif->mac->macid, vif->vifid, payload_len); 311 return -EINVAL; 312 } 313 314 bss = cfg80211_inform_bss(wiphy, channel, frame_type, 315 sr->bssid, get_unaligned_le64(&sr->tsf), 316 le16_to_cpu(sr->capab), 317 le16_to_cpu(sr->bintval), ies, ies_len, 318 sr->signal, GFP_KERNEL); 319 if (!bss) 320 return -ENOMEM; 321 322 cfg80211_put_bss(wiphy, bss); 323 324 return 0; 325 } 326 327 static int 328 qtnf_event_handle_scan_complete(struct qtnf_wmac *mac, 329 const struct qlink_event_scan_complete *status, 330 u16 len) 331 { 332 if (len < sizeof(*status)) { 333 pr_err("MAC%u: payload is too short\n", mac->macid); 334 return -EINVAL; 335 } 336 337 qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED); 338 339 return 0; 340 } 341 342 static int 343 qtnf_event_handle_freq_change(struct qtnf_wmac *mac, 344 const struct qlink_event_freq_change *data, 345 u16 len) 346 { 347 struct wiphy *wiphy = priv_to_wiphy(mac); 348 struct cfg80211_chan_def chandef; 349 struct qtnf_vif *vif; 350 int i; 351 352 if (len < sizeof(*data)) { 353 pr_err("MAC%u: payload is too short\n", mac->macid); 354 return -EINVAL; 355 } 356 357 if (!wiphy->registered) 358 return 0; 359 360 qlink_chandef_q2cfg(wiphy, &data->chan, &chandef); 361 362 if (!cfg80211_chandef_valid(&chandef)) { 363 pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n", mac->macid, 364 chandef.center_freq1, chandef.center_freq2, 365 chandef.width); 366 return -EINVAL; 367 } 368 369 pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n", 370 mac->macid, chandef.chan->hw_value, chandef.center_freq1, 371 chandef.center_freq2, chandef.width); 372 373 for (i = 0; i < QTNF_MAX_INTF; i++) { 374 vif = &mac->iflist[i]; 375 if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) 376 continue; 377 378 if (vif->netdev) { 379 mutex_lock(&vif->wdev.mtx); 380 cfg80211_ch_switch_notify(vif->netdev, &chandef); 381 mutex_unlock(&vif->wdev.mtx); 382 } 383 } 384 385 return 0; 386 } 387 388 static int qtnf_event_parse(struct qtnf_wmac *mac, 389 const struct sk_buff *event_skb) 390 { 391 const struct qlink_event *event; 392 struct qtnf_vif *vif = NULL; 393 int ret = -1; 394 u16 event_id; 395 u16 event_len; 396 397 event = (const struct qlink_event *)event_skb->data; 398 event_id = le16_to_cpu(event->event_id); 399 event_len = le16_to_cpu(event->mhdr.len); 400 401 if (likely(event->vifid < QTNF_MAX_INTF)) { 402 vif = &mac->iflist[event->vifid]; 403 } else { 404 pr_err("invalid vif(%u)\n", event->vifid); 405 return -EINVAL; 406 } 407 408 switch (event_id) { 409 case QLINK_EVENT_STA_ASSOCIATED: 410 ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event, 411 event_len); 412 break; 413 case QLINK_EVENT_STA_DEAUTH: 414 ret = qtnf_event_handle_sta_deauth(mac, vif, 415 (const void *)event, 416 event_len); 417 break; 418 case QLINK_EVENT_MGMT_RECEIVED: 419 ret = qtnf_event_handle_mgmt_received(vif, (const void *)event, 420 event_len); 421 break; 422 case QLINK_EVENT_SCAN_RESULTS: 423 ret = qtnf_event_handle_scan_results(vif, (const void *)event, 424 event_len); 425 break; 426 case QLINK_EVENT_SCAN_COMPLETE: 427 ret = qtnf_event_handle_scan_complete(mac, (const void *)event, 428 event_len); 429 break; 430 case QLINK_EVENT_BSS_JOIN: 431 ret = qtnf_event_handle_bss_join(vif, (const void *)event, 432 event_len); 433 break; 434 case QLINK_EVENT_BSS_LEAVE: 435 ret = qtnf_event_handle_bss_leave(vif, (const void *)event, 436 event_len); 437 break; 438 case QLINK_EVENT_FREQ_CHANGE: 439 ret = qtnf_event_handle_freq_change(mac, (const void *)event, 440 event_len); 441 break; 442 default: 443 pr_warn("unknown event type: %x\n", event_id); 444 break; 445 } 446 447 return ret; 448 } 449 450 static int qtnf_event_process_skb(struct qtnf_bus *bus, 451 const struct sk_buff *skb) 452 { 453 const struct qlink_event *event; 454 struct qtnf_wmac *mac; 455 int res; 456 457 if (unlikely(!skb || skb->len < sizeof(*event))) { 458 pr_err("invalid event buffer\n"); 459 return -EINVAL; 460 } 461 462 event = (struct qlink_event *)skb->data; 463 464 mac = qtnf_core_get_mac(bus, event->macid); 465 466 pr_debug("new event id:%x len:%u mac:%u vif:%u\n", 467 le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len), 468 event->macid, event->vifid); 469 470 if (unlikely(!mac)) 471 return -ENXIO; 472 473 qtnf_bus_lock(bus); 474 res = qtnf_event_parse(mac, skb); 475 qtnf_bus_unlock(bus); 476 477 return res; 478 } 479 480 void qtnf_event_work_handler(struct work_struct *work) 481 { 482 struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work); 483 struct sk_buff_head *event_queue = &bus->trans.event_queue; 484 struct sk_buff *current_event_skb = skb_dequeue(event_queue); 485 486 while (current_event_skb) { 487 qtnf_event_process_skb(bus, current_event_skb); 488 dev_kfree_skb_any(current_event_skb); 489 current_event_skb = skb_dequeue(event_queue); 490 } 491 } 492