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