xref: /openbmc/linux/drivers/net/wireless/quantenna/qtnfmac/event.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1  // SPDX-License-Identifier: GPL-2.0+
2  /* Copyright (c) 2015-2016 Quantenna Communications. All rights reserved. */
3  
4  #include <linux/kernel.h>
5  #include <linux/module.h>
6  #include <linux/slab.h>
7  #include <linux/nospec.h>
8  
9  #include "cfg80211.h"
10  #include "core.h"
11  #include "qlink.h"
12  #include "bus.h"
13  #include "trans.h"
14  #include "util.h"
15  #include "event.h"
16  #include "qlink_util.h"
17  
18  static int
qtnf_event_handle_sta_assoc(struct qtnf_wmac * mac,struct qtnf_vif * vif,const struct qlink_event_sta_assoc * sta_assoc,u16 len)19  qtnf_event_handle_sta_assoc(struct qtnf_wmac *mac, struct qtnf_vif *vif,
20  			    const struct qlink_event_sta_assoc *sta_assoc,
21  			    u16 len)
22  {
23  	const u8 *sta_addr;
24  	u16 frame_control;
25  	struct station_info *sinfo;
26  	size_t payload_len;
27  	u16 tlv_type;
28  	u16 tlv_value_len;
29  	const struct qlink_tlv_hdr *tlv;
30  	int ret = 0;
31  
32  	if (unlikely(len < sizeof(*sta_assoc))) {
33  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
34  		       mac->macid, vif->vifid, len, sizeof(*sta_assoc));
35  		return -EINVAL;
36  	}
37  
38  	if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
39  		pr_err("VIF%u.%u: STA_ASSOC event when not in AP mode\n",
40  		       mac->macid, vif->vifid);
41  		return -EPROTO;
42  	}
43  
44  	sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
45  	if (!sinfo)
46  		return -ENOMEM;
47  
48  	sta_addr = sta_assoc->sta_addr;
49  	frame_control = le16_to_cpu(sta_assoc->frame_control);
50  
51  	pr_debug("VIF%u.%u: MAC:%pM FC:%x\n", mac->macid, vif->vifid, sta_addr,
52  		 frame_control);
53  
54  	qtnf_sta_list_add(vif, sta_addr);
55  
56  	sinfo->assoc_req_ies = NULL;
57  	sinfo->assoc_req_ies_len = 0;
58  	sinfo->generation = vif->generation;
59  
60  	payload_len = len - sizeof(*sta_assoc);
61  
62  	qlink_for_each_tlv(tlv, sta_assoc->ies, payload_len) {
63  		tlv_type = le16_to_cpu(tlv->type);
64  		tlv_value_len = le16_to_cpu(tlv->len);
65  
66  		if (tlv_type == QTN_TLV_ID_IE_SET) {
67  			const struct qlink_tlv_ie_set *ie_set;
68  			unsigned int ie_len;
69  
70  			if (tlv_value_len <
71  			    (sizeof(*ie_set) - sizeof(ie_set->hdr))) {
72  				ret = -EINVAL;
73  				goto out;
74  			}
75  
76  			ie_set = (const struct qlink_tlv_ie_set *)tlv;
77  			ie_len = tlv_value_len -
78  				(sizeof(*ie_set) - sizeof(ie_set->hdr));
79  
80  			if (ie_set->type == QLINK_IE_SET_ASSOC_REQ && ie_len) {
81  				sinfo->assoc_req_ies = ie_set->ie_data;
82  				sinfo->assoc_req_ies_len = ie_len;
83  			}
84  		}
85  	}
86  
87  	if (!qlink_tlv_parsing_ok(tlv, sta_assoc->ies, payload_len)) {
88  		pr_err("Malformed TLV buffer\n");
89  		ret = -EINVAL;
90  		goto out;
91  	}
92  
93  	cfg80211_new_sta(vif->netdev, sta_assoc->sta_addr, sinfo,
94  			 GFP_KERNEL);
95  
96  out:
97  	kfree(sinfo);
98  	return ret;
99  }
100  
101  static int
qtnf_event_handle_sta_deauth(struct qtnf_wmac * mac,struct qtnf_vif * vif,const struct qlink_event_sta_deauth * sta_deauth,u16 len)102  qtnf_event_handle_sta_deauth(struct qtnf_wmac *mac, struct qtnf_vif *vif,
103  			     const struct qlink_event_sta_deauth *sta_deauth,
104  			     u16 len)
105  {
106  	const u8 *sta_addr;
107  	u16 reason;
108  
109  	if (unlikely(len < sizeof(*sta_deauth))) {
110  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
111  		       mac->macid, vif->vifid, len,
112  		       sizeof(struct qlink_event_sta_deauth));
113  		return -EINVAL;
114  	}
115  
116  	if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
117  		pr_err("VIF%u.%u: STA_DEAUTH event when not in AP mode\n",
118  		       mac->macid, vif->vifid);
119  		return -EPROTO;
120  	}
121  
122  	sta_addr = sta_deauth->sta_addr;
123  	reason = le16_to_cpu(sta_deauth->reason);
124  
125  	pr_debug("VIF%u.%u: MAC:%pM reason:%x\n", mac->macid, vif->vifid,
126  		 sta_addr, reason);
127  
128  	if (qtnf_sta_list_del(vif, sta_addr))
129  		cfg80211_del_sta(vif->netdev, sta_deauth->sta_addr,
130  				 GFP_KERNEL);
131  
132  	return 0;
133  }
134  
135  static int
qtnf_event_handle_bss_join(struct qtnf_vif * vif,const struct qlink_event_bss_join * join_info,u16 len)136  qtnf_event_handle_bss_join(struct qtnf_vif *vif,
137  			   const struct qlink_event_bss_join *join_info,
138  			   u16 len)
139  {
140  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
141  	enum ieee80211_statuscode status = le16_to_cpu(join_info->status);
142  	struct cfg80211_chan_def chandef;
143  	struct cfg80211_bss *bss = NULL;
144  	u8 *ie = NULL;
145  	size_t payload_len;
146  	u16 tlv_type;
147  	u16 tlv_value_len;
148  	const struct qlink_tlv_hdr *tlv;
149  	const u8 *rsp_ies = NULL;
150  	size_t rsp_ies_len = 0;
151  
152  	if (unlikely(len < sizeof(*join_info))) {
153  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
154  		       vif->mac->macid, vif->vifid, len,
155  		       sizeof(struct qlink_event_bss_join));
156  		return -EINVAL;
157  	}
158  
159  	if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
160  		pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n",
161  		       vif->mac->macid, vif->vifid);
162  		return -EPROTO;
163  	}
164  
165  	pr_debug("VIF%u.%u: BSSID:%pM chan:%u status:%u\n",
166  		 vif->mac->macid, vif->vifid, join_info->bssid,
167  		 le16_to_cpu(join_info->chan.chan.center_freq), status);
168  
169  	if (status != WLAN_STATUS_SUCCESS)
170  		goto done;
171  
172  	qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef);
173  	if (!cfg80211_chandef_valid(&chandef)) {
174  		pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
175  			vif->mac->macid, vif->vifid,
176  			chandef.chan ? chandef.chan->center_freq : 0,
177  			chandef.center_freq1,
178  			chandef.center_freq2,
179  			chandef.width);
180  		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
181  		goto done;
182  	}
183  
184  	bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid,
185  			       NULL, 0, IEEE80211_BSS_TYPE_ESS,
186  			       IEEE80211_PRIVACY_ANY);
187  	if (!bss) {
188  		pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n",
189  			vif->mac->macid, vif->vifid,
190  			join_info->bssid, chandef.chan->hw_value);
191  
192  		if (!vif->wdev.u.client.ssid_len) {
193  			pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n",
194  				vif->mac->macid, vif->vifid,
195  				join_info->bssid);
196  			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
197  			goto done;
198  		}
199  
200  		ie = kzalloc(2 + vif->wdev.u.client.ssid_len, GFP_KERNEL);
201  		if (!ie) {
202  			pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n",
203  				vif->mac->macid, vif->vifid,
204  				join_info->bssid);
205  			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
206  			goto done;
207  		}
208  
209  		ie[0] = WLAN_EID_SSID;
210  		ie[1] = vif->wdev.u.client.ssid_len;
211  		memcpy(ie + 2, vif->wdev.u.client.ssid,
212  		       vif->wdev.u.client.ssid_len);
213  
214  		bss = cfg80211_inform_bss(wiphy, chandef.chan,
215  					  CFG80211_BSS_FTYPE_UNKNOWN,
216  					  join_info->bssid, 0,
217  					  WLAN_CAPABILITY_ESS, 100,
218  					  ie, 2 + vif->wdev.u.client.ssid_len,
219  					  0, GFP_KERNEL);
220  		if (!bss) {
221  			pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n",
222  				vif->mac->macid, vif->vifid,
223  				join_info->bssid);
224  			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
225  			goto done;
226  		}
227  	}
228  
229  	payload_len = len - sizeof(*join_info);
230  
231  	qlink_for_each_tlv(tlv, join_info->ies, payload_len) {
232  		tlv_type = le16_to_cpu(tlv->type);
233  		tlv_value_len = le16_to_cpu(tlv->len);
234  
235  		if (tlv_type == QTN_TLV_ID_IE_SET) {
236  			const struct qlink_tlv_ie_set *ie_set;
237  			unsigned int ie_len;
238  
239  			if (tlv_value_len <
240  			    (sizeof(*ie_set) - sizeof(ie_set->hdr))) {
241  				pr_warn("invalid IE_SET TLV\n");
242  				status = WLAN_STATUS_UNSPECIFIED_FAILURE;
243  				goto done;
244  			}
245  
246  			ie_set = (const struct qlink_tlv_ie_set *)tlv;
247  			ie_len = tlv_value_len -
248  				(sizeof(*ie_set) - sizeof(ie_set->hdr));
249  
250  			switch (ie_set->type) {
251  			case QLINK_IE_SET_ASSOC_RESP:
252  				if (ie_len) {
253  					rsp_ies = ie_set->ie_data;
254  					rsp_ies_len = ie_len;
255  				}
256  				break;
257  			default:
258  				pr_warn("unexpected IE type: %u\n",
259  					ie_set->type);
260  				break;
261  			}
262  		}
263  	}
264  
265  	if (!qlink_tlv_parsing_ok(tlv, join_info->ies, payload_len))
266  		pr_warn("Malformed TLV buffer\n");
267  done:
268  	cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies,
269  				rsp_ies_len, status, GFP_KERNEL);
270  	if (bss) {
271  		if (!ether_addr_equal(vif->bssid, join_info->bssid))
272  			ether_addr_copy(vif->bssid, join_info->bssid);
273  		cfg80211_put_bss(wiphy, bss);
274  	}
275  
276  	if (status == WLAN_STATUS_SUCCESS)
277  		netif_carrier_on(vif->netdev);
278  
279  	kfree(ie);
280  	return 0;
281  }
282  
283  static int
qtnf_event_handle_bss_leave(struct qtnf_vif * vif,const struct qlink_event_bss_leave * leave_info,u16 len)284  qtnf_event_handle_bss_leave(struct qtnf_vif *vif,
285  			    const struct qlink_event_bss_leave *leave_info,
286  			    u16 len)
287  {
288  	if (unlikely(len < sizeof(*leave_info))) {
289  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
290  		       vif->mac->macid, vif->vifid, len,
291  		       sizeof(struct qlink_event_bss_leave));
292  		return -EINVAL;
293  	}
294  
295  	if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
296  		pr_err("VIF%u.%u: BSS_LEAVE event when not in STA mode\n",
297  		       vif->mac->macid, vif->vifid);
298  		return -EPROTO;
299  	}
300  
301  	pr_debug("VIF%u.%u: disconnected\n", vif->mac->macid, vif->vifid);
302  
303  	cfg80211_disconnected(vif->netdev, le16_to_cpu(leave_info->reason),
304  			      NULL, 0, 0, GFP_KERNEL);
305  	netif_carrier_off(vif->netdev);
306  
307  	return 0;
308  }
309  
310  static int
qtnf_event_handle_mgmt_received(struct qtnf_vif * vif,const struct qlink_event_rxmgmt * rxmgmt,u16 len)311  qtnf_event_handle_mgmt_received(struct qtnf_vif *vif,
312  				const struct qlink_event_rxmgmt *rxmgmt,
313  				u16 len)
314  {
315  	const size_t min_len = sizeof(*rxmgmt) +
316  			       sizeof(struct ieee80211_hdr_3addr);
317  	const struct ieee80211_hdr_3addr *frame = (void *)rxmgmt->frame_data;
318  	const u16 frame_len = len - sizeof(*rxmgmt);
319  	enum nl80211_rxmgmt_flags flags = 0;
320  
321  	if (unlikely(len < min_len)) {
322  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
323  		       vif->mac->macid, vif->vifid, len, min_len);
324  		return -EINVAL;
325  	}
326  
327  	if (le32_to_cpu(rxmgmt->flags) & QLINK_RXMGMT_FLAG_ANSWERED)
328  		flags |= NL80211_RXMGMT_FLAG_ANSWERED;
329  
330  	pr_debug("%s LEN:%u FC:%.4X SA:%pM\n", vif->netdev->name, frame_len,
331  		 le16_to_cpu(frame->frame_control), frame->addr2);
332  
333  	cfg80211_rx_mgmt(&vif->wdev, le32_to_cpu(rxmgmt->freq), rxmgmt->sig_dbm,
334  			 rxmgmt->frame_data, frame_len, flags);
335  
336  	return 0;
337  }
338  
339  static int
qtnf_event_handle_scan_results(struct qtnf_vif * vif,const struct qlink_event_scan_result * sr,u16 len)340  qtnf_event_handle_scan_results(struct qtnf_vif *vif,
341  			       const struct qlink_event_scan_result *sr,
342  			       u16 len)
343  {
344  	struct cfg80211_bss *bss;
345  	struct ieee80211_channel *channel;
346  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
347  	enum cfg80211_bss_frame_type frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
348  	size_t payload_len;
349  	u16 tlv_type;
350  	u16 tlv_value_len;
351  	const struct qlink_tlv_hdr *tlv;
352  	const u8 *ies = NULL;
353  	size_t ies_len = 0;
354  
355  	if (len < sizeof(*sr)) {
356  		pr_err("VIF%u.%u: payload is too short\n", vif->mac->macid,
357  		       vif->vifid);
358  		return -EINVAL;
359  	}
360  
361  	channel = ieee80211_get_channel(wiphy, le16_to_cpu(sr->freq));
362  	if (!channel) {
363  		pr_err("VIF%u.%u: channel at %u MHz not found\n",
364  		       vif->mac->macid, vif->vifid, le16_to_cpu(sr->freq));
365  		return -EINVAL;
366  	}
367  
368  	payload_len = len - sizeof(*sr);
369  
370  	qlink_for_each_tlv(tlv, sr->payload, payload_len) {
371  		tlv_type = le16_to_cpu(tlv->type);
372  		tlv_value_len = le16_to_cpu(tlv->len);
373  
374  		if (tlv_type == QTN_TLV_ID_IE_SET) {
375  			const struct qlink_tlv_ie_set *ie_set;
376  			unsigned int ie_len;
377  
378  			if (tlv_value_len <
379  			    (sizeof(*ie_set) - sizeof(ie_set->hdr)))
380  				return -EINVAL;
381  
382  			ie_set = (const struct qlink_tlv_ie_set *)tlv;
383  			ie_len = tlv_value_len -
384  				(sizeof(*ie_set) - sizeof(ie_set->hdr));
385  
386  			switch (ie_set->type) {
387  			case QLINK_IE_SET_BEACON_IES:
388  				frame_type = CFG80211_BSS_FTYPE_BEACON;
389  				break;
390  			case QLINK_IE_SET_PROBE_RESP_IES:
391  				frame_type = CFG80211_BSS_FTYPE_PRESP;
392  				break;
393  			default:
394  				frame_type = CFG80211_BSS_FTYPE_UNKNOWN;
395  			}
396  
397  			if (ie_len) {
398  				ies = ie_set->ie_data;
399  				ies_len = ie_len;
400  			}
401  		}
402  	}
403  
404  	if (!qlink_tlv_parsing_ok(tlv, sr->payload, payload_len))
405  		return -EINVAL;
406  
407  	bss = cfg80211_inform_bss(wiphy, channel, frame_type,
408  				  sr->bssid, get_unaligned_le64(&sr->tsf),
409  				  le16_to_cpu(sr->capab),
410  				  le16_to_cpu(sr->bintval), ies, ies_len,
411  				  DBM_TO_MBM(sr->sig_dbm), GFP_KERNEL);
412  	if (!bss)
413  		return -ENOMEM;
414  
415  	cfg80211_put_bss(wiphy, bss);
416  
417  	return 0;
418  }
419  
420  static int
qtnf_event_handle_scan_complete(struct qtnf_wmac * mac,const struct qlink_event_scan_complete * status,u16 len)421  qtnf_event_handle_scan_complete(struct qtnf_wmac *mac,
422  				const struct qlink_event_scan_complete *status,
423  				u16 len)
424  {
425  	if (len < sizeof(*status)) {
426  		pr_err("MAC%u: payload is too short\n", mac->macid);
427  		return -EINVAL;
428  	}
429  
430  	qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED);
431  
432  	return 0;
433  }
434  
435  static int
qtnf_event_handle_freq_change(struct qtnf_wmac * mac,const struct qlink_event_freq_change * data,u16 len)436  qtnf_event_handle_freq_change(struct qtnf_wmac *mac,
437  			      const struct qlink_event_freq_change *data,
438  			      u16 len)
439  {
440  	struct wiphy *wiphy = priv_to_wiphy(mac);
441  	struct cfg80211_chan_def chandef;
442  	struct qtnf_vif *vif;
443  	int i;
444  
445  	if (len < sizeof(*data)) {
446  		pr_err("MAC%u: payload is too short\n", mac->macid);
447  		return -EINVAL;
448  	}
449  
450  	if (!wiphy->registered)
451  		return 0;
452  
453  	qlink_chandef_q2cfg(wiphy, &data->chan, &chandef);
454  
455  	if (!cfg80211_chandef_valid(&chandef)) {
456  		pr_err("MAC%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n",
457  		       mac->macid, chandef.chan->center_freq,
458  		       chandef.center_freq1, chandef.center_freq2,
459  		       chandef.width);
460  		return -EINVAL;
461  	}
462  
463  	pr_debug("MAC%d: new channel ieee=%u freq1=%u freq2=%u bw=%u\n",
464  		 mac->macid, chandef.chan->hw_value, chandef.center_freq1,
465  		 chandef.center_freq2, chandef.width);
466  
467  	for (i = 0; i < QTNF_MAX_INTF; i++) {
468  		vif = &mac->iflist[i];
469  
470  		if (vif->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED)
471  			continue;
472  
473  		if (vif->wdev.iftype == NL80211_IFTYPE_STATION &&
474  		    !vif->wdev.connected)
475  			continue;
476  
477  		if (!vif->netdev)
478  			continue;
479  
480  		mutex_lock(&vif->wdev.mtx);
481  		cfg80211_ch_switch_notify(vif->netdev, &chandef, 0, 0);
482  		mutex_unlock(&vif->wdev.mtx);
483  	}
484  
485  	return 0;
486  }
487  
qtnf_event_handle_radar(struct qtnf_vif * vif,const struct qlink_event_radar * ev,u16 len)488  static int qtnf_event_handle_radar(struct qtnf_vif *vif,
489  				   const struct qlink_event_radar *ev,
490  				   u16 len)
491  {
492  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
493  	struct cfg80211_chan_def chandef;
494  
495  	if (len < sizeof(*ev)) {
496  		pr_err("MAC%u: payload is too short\n", vif->mac->macid);
497  		return -EINVAL;
498  	}
499  
500  	if (!wiphy->registered || !vif->netdev)
501  		return 0;
502  
503  	qlink_chandef_q2cfg(wiphy, &ev->chan, &chandef);
504  
505  	if (!cfg80211_chandef_valid(&chandef)) {
506  		pr_err("MAC%u: bad channel f1=%u f2=%u bw=%u\n",
507  		       vif->mac->macid,
508  		       chandef.center_freq1, chandef.center_freq2,
509  		       chandef.width);
510  		return -EINVAL;
511  	}
512  
513  	pr_info("%s: radar event=%u f1=%u f2=%u bw=%u\n",
514  		vif->netdev->name, ev->event,
515  		chandef.center_freq1, chandef.center_freq2,
516  		chandef.width);
517  
518  	switch (ev->event) {
519  	case QLINK_RADAR_DETECTED:
520  		cfg80211_radar_event(wiphy, &chandef, GFP_KERNEL);
521  		break;
522  	case QLINK_RADAR_CAC_FINISHED:
523  		if (!vif->wdev.cac_started)
524  			break;
525  
526  		cfg80211_cac_event(vif->netdev, &chandef,
527  				   NL80211_RADAR_CAC_FINISHED, GFP_KERNEL);
528  		break;
529  	case QLINK_RADAR_CAC_ABORTED:
530  		if (!vif->wdev.cac_started)
531  			break;
532  
533  		cfg80211_cac_event(vif->netdev, &chandef,
534  				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
535  		break;
536  	case QLINK_RADAR_CAC_STARTED:
537  		if (vif->wdev.cac_started)
538  			break;
539  
540  		if (!wiphy_ext_feature_isset(wiphy,
541  					     NL80211_EXT_FEATURE_DFS_OFFLOAD))
542  			break;
543  
544  		cfg80211_cac_event(vif->netdev, &chandef,
545  				   NL80211_RADAR_CAC_STARTED, GFP_KERNEL);
546  		break;
547  	default:
548  		pr_warn("%s: unhandled radar event %u\n",
549  			vif->netdev->name, ev->event);
550  		break;
551  	}
552  
553  	return 0;
554  }
555  
556  static int
qtnf_event_handle_external_auth(struct qtnf_vif * vif,const struct qlink_event_external_auth * ev,u16 len)557  qtnf_event_handle_external_auth(struct qtnf_vif *vif,
558  				const struct qlink_event_external_auth *ev,
559  				u16 len)
560  {
561  	struct cfg80211_external_auth_params auth = {0};
562  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
563  	int ret;
564  
565  	if (len < sizeof(*ev)) {
566  		pr_err("MAC%u: payload is too short\n", vif->mac->macid);
567  		return -EINVAL;
568  	}
569  
570  	if (!wiphy->registered || !vif->netdev)
571  		return 0;
572  
573  	if (ev->ssid_len) {
574  		int len = clamp_val(ev->ssid_len, 0, IEEE80211_MAX_SSID_LEN);
575  
576  		memcpy(auth.ssid.ssid, ev->ssid, len);
577  		auth.ssid.ssid_len = len;
578  	}
579  
580  	auth.key_mgmt_suite = le32_to_cpu(ev->akm_suite);
581  	ether_addr_copy(auth.bssid, ev->bssid);
582  	auth.action = ev->action;
583  
584  	pr_debug("%s: external SAE processing: bss=%pM action=%u akm=%u\n",
585  		 vif->netdev->name, auth.bssid, auth.action,
586  		 auth.key_mgmt_suite);
587  
588  	ret = cfg80211_external_auth_request(vif->netdev, &auth, GFP_KERNEL);
589  	if (ret)
590  		pr_warn("failed to offload external auth request\n");
591  
592  	return ret;
593  }
594  
595  static int
qtnf_event_handle_mic_failure(struct qtnf_vif * vif,const struct qlink_event_mic_failure * mic_ev,u16 len)596  qtnf_event_handle_mic_failure(struct qtnf_vif *vif,
597  			      const struct qlink_event_mic_failure *mic_ev,
598  			      u16 len)
599  {
600  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
601  	u8 pairwise;
602  
603  	if (len < sizeof(*mic_ev)) {
604  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
605  		       vif->mac->macid, vif->vifid, len,
606  		       sizeof(struct qlink_event_mic_failure));
607  		return -EINVAL;
608  	}
609  
610  	if (!wiphy->registered || !vif->netdev)
611  		return 0;
612  
613  	if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
614  		pr_err("VIF%u.%u: MIC_FAILURE event when not in STA mode\n",
615  		       vif->mac->macid, vif->vifid);
616  		return -EPROTO;
617  	}
618  
619  	pairwise = mic_ev->pairwise ?
620  		NL80211_KEYTYPE_PAIRWISE : NL80211_KEYTYPE_GROUP;
621  
622  	pr_info("%s: MIC error: src=%pM key_index=%u pairwise=%u\n",
623  		vif->netdev->name, mic_ev->src, mic_ev->key_index, pairwise);
624  
625  	cfg80211_michael_mic_failure(vif->netdev, mic_ev->src, pairwise,
626  				     mic_ev->key_index, NULL, GFP_KERNEL);
627  
628  	return 0;
629  }
630  
631  static int
qtnf_event_handle_update_owe(struct qtnf_vif * vif,const struct qlink_event_update_owe * owe_ev,u16 len)632  qtnf_event_handle_update_owe(struct qtnf_vif *vif,
633  			     const struct qlink_event_update_owe *owe_ev,
634  			     u16 len)
635  {
636  	struct wiphy *wiphy = priv_to_wiphy(vif->mac);
637  	struct cfg80211_update_owe_info owe_info = {};
638  	const u16 ie_len = len - sizeof(*owe_ev);
639  	u8 *ie;
640  
641  	if (len < sizeof(*owe_ev)) {
642  		pr_err("VIF%u.%u: payload is too short (%u < %zu)\n",
643  		       vif->mac->macid, vif->vifid, len,
644  		       sizeof(struct qlink_event_update_owe));
645  		return -EINVAL;
646  	}
647  
648  	if (!wiphy->registered || !vif->netdev)
649  		return 0;
650  
651  	if (vif->wdev.iftype != NL80211_IFTYPE_AP) {
652  		pr_err("VIF%u.%u: UPDATE_OWE event when not in AP mode\n",
653  		       vif->mac->macid, vif->vifid);
654  		return -EPROTO;
655  	}
656  
657  	ie = kzalloc(ie_len, GFP_KERNEL);
658  	if (!ie)
659  		return -ENOMEM;
660  
661  	memcpy(owe_info.peer, owe_ev->peer, ETH_ALEN);
662  	memcpy(ie, owe_ev->ies, ie_len);
663  	owe_info.ie_len = ie_len;
664  	owe_info.ie = ie;
665  	owe_info.assoc_link_id = -1;
666  
667  	pr_info("%s: external OWE processing: peer=%pM\n",
668  		vif->netdev->name, owe_ev->peer);
669  
670  	cfg80211_update_owe_info_event(vif->netdev, &owe_info, GFP_KERNEL);
671  	kfree(ie);
672  
673  	return 0;
674  }
675  
qtnf_event_parse(struct qtnf_wmac * mac,const struct sk_buff * event_skb)676  static int qtnf_event_parse(struct qtnf_wmac *mac,
677  			    const struct sk_buff *event_skb)
678  {
679  	const struct qlink_event *event;
680  	struct qtnf_vif *vif = NULL;
681  	int ret = -1;
682  	u16 event_id;
683  	u16 event_len;
684  	u8 vifid;
685  
686  	event = (const struct qlink_event *)event_skb->data;
687  	event_id = le16_to_cpu(event->event_id);
688  	event_len = le16_to_cpu(event->mhdr.len);
689  
690  	if (event->vifid >= QTNF_MAX_INTF) {
691  		pr_err("invalid vif(%u)\n", event->vifid);
692  		return -EINVAL;
693  	}
694  
695  	vifid = array_index_nospec(event->vifid, QTNF_MAX_INTF);
696  	vif = &mac->iflist[vifid];
697  
698  	switch (event_id) {
699  	case QLINK_EVENT_STA_ASSOCIATED:
700  		ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event,
701  						  event_len);
702  		break;
703  	case QLINK_EVENT_STA_DEAUTH:
704  		ret = qtnf_event_handle_sta_deauth(mac, vif,
705  						   (const void *)event,
706  						   event_len);
707  		break;
708  	case QLINK_EVENT_MGMT_RECEIVED:
709  		ret = qtnf_event_handle_mgmt_received(vif, (const void *)event,
710  						      event_len);
711  		break;
712  	case QLINK_EVENT_SCAN_RESULTS:
713  		ret = qtnf_event_handle_scan_results(vif, (const void *)event,
714  						     event_len);
715  		break;
716  	case QLINK_EVENT_SCAN_COMPLETE:
717  		ret = qtnf_event_handle_scan_complete(mac, (const void *)event,
718  						      event_len);
719  		break;
720  	case QLINK_EVENT_BSS_JOIN:
721  		ret = qtnf_event_handle_bss_join(vif, (const void *)event,
722  						 event_len);
723  		break;
724  	case QLINK_EVENT_BSS_LEAVE:
725  		ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
726  						  event_len);
727  		break;
728  	case QLINK_EVENT_FREQ_CHANGE:
729  		ret = qtnf_event_handle_freq_change(mac, (const void *)event,
730  						    event_len);
731  		break;
732  	case QLINK_EVENT_RADAR:
733  		ret = qtnf_event_handle_radar(vif, (const void *)event,
734  					      event_len);
735  		break;
736  	case QLINK_EVENT_EXTERNAL_AUTH:
737  		ret = qtnf_event_handle_external_auth(vif, (const void *)event,
738  						      event_len);
739  		break;
740  	case QLINK_EVENT_MIC_FAILURE:
741  		ret = qtnf_event_handle_mic_failure(vif, (const void *)event,
742  						    event_len);
743  		break;
744  	case QLINK_EVENT_UPDATE_OWE:
745  		ret = qtnf_event_handle_update_owe(vif, (const void *)event,
746  						   event_len);
747  		break;
748  	default:
749  		pr_warn("unknown event type: %x\n", event_id);
750  		break;
751  	}
752  
753  	return ret;
754  }
755  
qtnf_event_process_skb(struct qtnf_bus * bus,const struct sk_buff * skb)756  static int qtnf_event_process_skb(struct qtnf_bus *bus,
757  				  const struct sk_buff *skb)
758  {
759  	const struct qlink_event *event;
760  	struct qtnf_wmac *mac;
761  	int res;
762  
763  	if (unlikely(!skb || skb->len < sizeof(*event))) {
764  		pr_err("invalid event buffer\n");
765  		return -EINVAL;
766  	}
767  
768  	event = (struct qlink_event *)skb->data;
769  
770  	mac = qtnf_core_get_mac(bus, event->macid);
771  
772  	pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
773  		 le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len),
774  		 event->macid, event->vifid);
775  
776  	if (unlikely(!mac))
777  		return -ENXIO;
778  
779  	rtnl_lock();
780  	res = qtnf_event_parse(mac, skb);
781  	rtnl_unlock();
782  
783  	return res;
784  }
785  
qtnf_event_work_handler(struct work_struct * work)786  void qtnf_event_work_handler(struct work_struct *work)
787  {
788  	struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work);
789  	struct sk_buff_head *event_queue = &bus->trans.event_queue;
790  	struct sk_buff *current_event_skb = skb_dequeue(event_queue);
791  
792  	while (current_event_skb) {
793  		qtnf_event_process_skb(bus, current_event_skb);
794  		dev_kfree_skb_any(current_event_skb);
795  		current_event_skb = skb_dequeue(event_queue);
796  	}
797  }
798