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