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, leave_info->reason, NULL, 0, 0,
215 			      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 qtnf_event_parse(struct qtnf_wmac *mac,
354 			    const struct sk_buff *event_skb)
355 {
356 	const struct qlink_event *event;
357 	struct qtnf_vif *vif = NULL;
358 	int ret = -1;
359 	u16 event_id;
360 	u16 event_len;
361 
362 	event = (const struct qlink_event *)event_skb->data;
363 	event_id = le16_to_cpu(event->event_id);
364 	event_len = le16_to_cpu(event->mhdr.len);
365 
366 	if (likely(event->vifid < QTNF_MAX_INTF)) {
367 		vif = &mac->iflist[event->vifid];
368 	} else {
369 		pr_err("invalid vif(%u)\n", event->vifid);
370 		return -EINVAL;
371 	}
372 
373 	switch (event_id) {
374 	case QLINK_EVENT_STA_ASSOCIATED:
375 		ret = qtnf_event_handle_sta_assoc(mac, vif, (const void *)event,
376 						  event_len);
377 		break;
378 	case QLINK_EVENT_STA_DEAUTH:
379 		ret = qtnf_event_handle_sta_deauth(mac, vif,
380 						   (const void *)event,
381 						   event_len);
382 		break;
383 	case QLINK_EVENT_MGMT_RECEIVED:
384 		ret = qtnf_event_handle_mgmt_received(vif, (const void *)event,
385 						      event_len);
386 		break;
387 	case QLINK_EVENT_SCAN_RESULTS:
388 		ret = qtnf_event_handle_scan_results(vif, (const void *)event,
389 						     event_len);
390 		break;
391 	case QLINK_EVENT_SCAN_COMPLETE:
392 		ret = qtnf_event_handle_scan_complete(mac, (const void *)event,
393 						      event_len);
394 		break;
395 	case QLINK_EVENT_BSS_JOIN:
396 		ret = qtnf_event_handle_bss_join(vif, (const void *)event,
397 						 event_len);
398 		break;
399 	case QLINK_EVENT_BSS_LEAVE:
400 		ret = qtnf_event_handle_bss_leave(vif, (const void *)event,
401 						  event_len);
402 		break;
403 	default:
404 		pr_warn("unknown event type: %x\n", event_id);
405 		break;
406 	}
407 
408 	return ret;
409 }
410 
411 static int qtnf_event_process_skb(struct qtnf_bus *bus,
412 				  const struct sk_buff *skb)
413 {
414 	const struct qlink_event *event;
415 	struct qtnf_wmac *mac;
416 	int res;
417 
418 	if (unlikely(!skb || skb->len < sizeof(*event))) {
419 		pr_err("invalid event buffer\n");
420 		return -EINVAL;
421 	}
422 
423 	event = (struct qlink_event *)skb->data;
424 
425 	mac = qtnf_core_get_mac(bus, event->macid);
426 
427 	pr_debug("new event id:%x len:%u mac:%u vif:%u\n",
428 		 le16_to_cpu(event->event_id), le16_to_cpu(event->mhdr.len),
429 		 event->macid, event->vifid);
430 
431 	if (unlikely(!mac))
432 		return -ENXIO;
433 
434 	qtnf_bus_lock(bus);
435 	res = qtnf_event_parse(mac, skb);
436 	qtnf_bus_unlock(bus);
437 
438 	return res;
439 }
440 
441 void qtnf_event_work_handler(struct work_struct *work)
442 {
443 	struct qtnf_bus *bus = container_of(work, struct qtnf_bus, event_work);
444 	struct sk_buff_head *event_queue = &bus->trans.event_queue;
445 	struct sk_buff *current_event_skb = skb_dequeue(event_queue);
446 
447 	while (current_event_skb) {
448 		qtnf_event_process_skb(bus, current_event_skb);
449 		dev_kfree_skb_any(current_event_skb);
450 		current_event_skb = skb_dequeue(event_queue);
451 	}
452 }
453