1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54#include <linux/module.h>
55#include <linux/kernel.h>
56#include <linux/sched.h>
57#include <linux/types.h>
58#include <linux/skbuff.h>
59#include <linux/slab.h>
60#include <linux/wireless.h>
61#include <linux/netdevice.h>
62#include <linux/etherdevice.h>
63#include <linux/if_ether.h>
64#include <linux/byteorder/generic.h>
65
66#include <asm/byteorder.h>
67
68#include "p80211types.h"
69#include "p80211hdr.h"
70#include "p80211conv.h"
71#include "p80211mgmt.h"
72#include "p80211msg.h"
73#include "p80211netdev.h"
74#include "p80211ioctl.h"
75#include "p80211req.h"
76
77static u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 };
78static u8 oui_8021h[] = { 0x00, 0x00, 0xf8 };
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv,
106 struct sk_buff *skb, union p80211_hdr *p80211_hdr,
107 struct p80211_metawep *p80211_wep)
108{
109
110 u16 fc;
111 u16 proto;
112 struct wlan_ethhdr e_hdr;
113 struct wlan_llc *e_llc;
114 struct wlan_snap *e_snap;
115 int foo;
116
117 memcpy(&e_hdr, skb->data, sizeof(e_hdr));
118
119 if (skb->len <= 0) {
120 pr_debug("zero-length skb!\n");
121 return 1;
122 }
123
124 if (ethconv == WLAN_ETHCONV_ENCAP) {
125 pr_debug("ENCAP len: %d\n", skb->len);
126
127
128
129 } else {
130
131 proto = ntohs(e_hdr.type);
132 if (proto <= 1500) {
133 pr_debug("802.3 len: %d\n", skb->len);
134
135
136
137
138 skb_pull(skb, WLAN_ETHHDR_LEN);
139
140
141 skb_trim(skb, proto);
142 } else {
143 pr_debug("DIXII len: %d\n", skb->len);
144
145
146
147 skb_pull(skb, WLAN_ETHHDR_LEN);
148
149
150 e_snap =
151 (struct wlan_snap *) skb_push(skb,
152 sizeof(struct wlan_snap));
153 e_snap->type = htons(proto);
154 if (ethconv == WLAN_ETHCONV_8021h
155 && p80211_stt_findproto(proto)) {
156 memcpy(e_snap->oui, oui_8021h,
157 WLAN_IEEE_OUI_LEN);
158 } else {
159 memcpy(e_snap->oui, oui_rfc1042,
160 WLAN_IEEE_OUI_LEN);
161 }
162
163
164 e_llc =
165 (struct wlan_llc *) skb_push(skb,
166 sizeof(struct wlan_llc));
167 e_llc->dsap = 0xAA;
168 e_llc->ssap = 0xAA;
169 e_llc->ctl = 0x03;
170
171 }
172 }
173
174
175
176 fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
177 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY));
178
179 switch (wlandev->macmode) {
180 case WLAN_MACMODE_IBSS_STA:
181 memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
182 memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
183 memcpy(p80211_hdr->a3.a3, wlandev->bssid, ETH_ALEN);
184 break;
185 case WLAN_MACMODE_ESS_STA:
186 fc |= cpu_to_le16(WLAN_SET_FC_TODS(1));
187 memcpy(p80211_hdr->a3.a1, wlandev->bssid, ETH_ALEN);
188 memcpy(p80211_hdr->a3.a2, wlandev->netdev->dev_addr, ETH_ALEN);
189 memcpy(p80211_hdr->a3.a3, &e_hdr.daddr, ETH_ALEN);
190 break;
191 case WLAN_MACMODE_ESS_AP:
192 fc |= cpu_to_le16(WLAN_SET_FC_FROMDS(1));
193 memcpy(p80211_hdr->a3.a1, &e_hdr.daddr, ETH_ALEN);
194 memcpy(p80211_hdr->a3.a2, wlandev->bssid, ETH_ALEN);
195 memcpy(p80211_hdr->a3.a3, &e_hdr.saddr, ETH_ALEN);
196 break;
197 default:
198 printk(KERN_ERR
199 "Error: Converting eth to wlan in unknown mode.\n");
200 return 1;
201 break;
202 }
203
204 p80211_wep->data = NULL;
205
206 if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED)
207 && (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
208
209
210 p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
211 foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
212 skb->len,
213 (wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK),
214 p80211_wep->iv, p80211_wep->icv);
215 if (foo) {
216 printk(KERN_WARNING
217 "Host en-WEP failed, dropping frame (%d).\n",
218 foo);
219 return 2;
220 }
221 fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
222 }
223
224
225
226 p80211_hdr->a3.fc = fc;
227 p80211_hdr->a3.dur = 0;
228 p80211_hdr->a3.seq = 0;
229
230 return 0;
231}
232
233
234static void orinoco_spy_gather(wlandevice_t *wlandev, char *mac,
235 struct p80211_rxmeta *rxmeta)
236{
237 int i;
238
239
240
241
242 for (i = 0; i < wlandev->spy_number; i++) {
243
244 if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) {
245 memcpy(wlandev->spy_address[i], mac, ETH_ALEN);
246 wlandev->spy_stat[i].level = rxmeta->signal;
247 wlandev->spy_stat[i].noise = rxmeta->noise;
248 wlandev->spy_stat[i].qual =
249 (rxmeta->signal >
250 rxmeta->noise) ? (rxmeta->signal -
251 rxmeta->noise) : 0;
252 wlandev->spy_stat[i].updated = 0x7;
253 }
254 }
255}
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
277 struct sk_buff *skb)
278{
279 netdevice_t *netdev = wlandev->netdev;
280 u16 fc;
281 unsigned int payload_length;
282 unsigned int payload_offset;
283 u8 daddr[WLAN_ETHADDR_LEN];
284 u8 saddr[WLAN_ETHADDR_LEN];
285 union p80211_hdr *w_hdr;
286 struct wlan_ethhdr *e_hdr;
287 struct wlan_llc *e_llc;
288 struct wlan_snap *e_snap;
289
290 int foo;
291
292 payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
293 payload_offset = WLAN_HDR_A3_LEN;
294
295 w_hdr = (union p80211_hdr *) skb->data;
296
297
298 fc = le16_to_cpu(w_hdr->a3.fc);
299 if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) {
300 memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
301 memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
302 } else if ((WLAN_GET_FC_TODS(fc) == 0)
303 && (WLAN_GET_FC_FROMDS(fc) == 1)) {
304 memcpy(daddr, w_hdr->a3.a1, WLAN_ETHADDR_LEN);
305 memcpy(saddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
306 } else if ((WLAN_GET_FC_TODS(fc) == 1)
307 && (WLAN_GET_FC_FROMDS(fc) == 0)) {
308 memcpy(daddr, w_hdr->a3.a3, WLAN_ETHADDR_LEN);
309 memcpy(saddr, w_hdr->a3.a2, WLAN_ETHADDR_LEN);
310 } else {
311 payload_offset = WLAN_HDR_A4_LEN;
312 if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) {
313 printk(KERN_ERR "A4 frame too short!\n");
314 return 1;
315 }
316 payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
317 memcpy(daddr, w_hdr->a4.a3, WLAN_ETHADDR_LEN);
318 memcpy(saddr, w_hdr->a4.a4, WLAN_ETHADDR_LEN);
319 }
320
321
322 if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) && WLAN_GET_FC_ISWEP(fc)
323 && (wlandev->hostwep & HOSTWEP_DECRYPT)) {
324 if (payload_length <= 8) {
325 printk(KERN_ERR "WEP frame too short (%u).\n",
326 skb->len);
327 return 1;
328 }
329 foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
330 payload_length - 8, -1,
331 skb->data + payload_offset,
332 skb->data + payload_offset +
333 payload_length - 4);
334 if (foo) {
335
336 pr_debug("Host de-WEP failed, dropping frame (%d).\n",
337 foo);
338 wlandev->rx.decrypt_err++;
339 return 2;
340 }
341
342
343 payload_length -= 8;
344
345 skb_pull(skb, 4);
346
347 skb_trim(skb, skb->len - 4);
348
349 wlandev->rx.decrypt++;
350 }
351
352 e_hdr = (struct wlan_ethhdr *) (skb->data + payload_offset);
353
354 e_llc = (struct wlan_llc *) (skb->data + payload_offset);
355 e_snap =
356 (struct wlan_snap *) (skb->data + payload_offset +
357 sizeof(struct wlan_llc));
358
359
360 if ((payload_length >= sizeof(struct wlan_ethhdr)) &&
361 (e_llc->dsap != 0xaa || e_llc->ssap != 0xaa) &&
362 ((memcmp(daddr, e_hdr->daddr, WLAN_ETHADDR_LEN) == 0) ||
363 (memcmp(saddr, e_hdr->saddr, WLAN_ETHADDR_LEN) == 0))) {
364 pr_debug("802.3 ENCAP len: %d\n", payload_length);
365
366
367 if (payload_length > (netdev->mtu + WLAN_ETHHDR_LEN)) {
368
369
370 printk(KERN_ERR "ENCAP frame too large (%d > %d)\n",
371 payload_length, netdev->mtu + WLAN_ETHHDR_LEN);
372 return 1;
373 }
374
375
376 skb_pull(skb, payload_offset);
377
378 skb_trim(skb, skb->len - WLAN_CRC_LEN);
379
380 } else if ((payload_length >= sizeof(struct wlan_llc) +
381 sizeof(struct wlan_snap))
382 && (e_llc->dsap == 0xaa)
383 && (e_llc->ssap == 0xaa)
384 && (e_llc->ctl == 0x03)
385 &&
386 (((memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) == 0)
387 && (ethconv == WLAN_ETHCONV_8021h)
388 && (p80211_stt_findproto(le16_to_cpu(e_snap->type))))
389 || (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) !=
390 0))) {
391 pr_debug("SNAP+RFC1042 len: %d\n", payload_length);
392
393
394
395
396 if (payload_length > netdev->mtu) {
397
398
399 printk(KERN_ERR "SNAP frame too large (%d > %d)\n",
400 payload_length, netdev->mtu);
401 return 1;
402 }
403
404
405 skb_pull(skb, payload_offset);
406
407
408 e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
409 memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
410 memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
411 e_hdr->type = htons(payload_length);
412
413
414 skb_trim(skb, skb->len - WLAN_CRC_LEN);
415
416 } else if ((payload_length >= sizeof(struct wlan_llc) +
417 sizeof(struct wlan_snap))
418 && (e_llc->dsap == 0xaa)
419 && (e_llc->ssap == 0xaa)
420 && (e_llc->ctl == 0x03)) {
421 pr_debug("802.1h/RFC1042 len: %d\n", payload_length);
422
423
424
425
426 if ((payload_length - sizeof(struct wlan_llc) -
427 sizeof(struct wlan_snap))
428 > netdev->mtu) {
429
430
431 printk(KERN_ERR "DIXII frame too large (%ld > %d)\n",
432 (long int)(payload_length -
433 sizeof(struct wlan_llc) -
434 sizeof(struct wlan_snap)), netdev->mtu);
435 return 1;
436 }
437
438
439 skb_pull(skb, payload_offset);
440
441
442 skb_pull(skb, sizeof(struct wlan_llc));
443
444
445 skb_pull(skb, sizeof(struct wlan_snap));
446
447
448 e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
449 e_hdr->type = e_snap->type;
450 memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
451 memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
452
453
454 skb_trim(skb, skb->len - WLAN_CRC_LEN);
455 } else {
456 pr_debug("NON-ENCAP len: %d\n", payload_length);
457
458
459
460
461
462
463 if (payload_length > netdev->mtu) {
464
465
466 printk(KERN_ERR "OTHER frame too large (%d > %d)\n",
467 payload_length, netdev->mtu);
468 return 1;
469 }
470
471
472 skb_pull(skb, payload_offset);
473
474
475 e_hdr = (struct wlan_ethhdr *) skb_push(skb, WLAN_ETHHDR_LEN);
476 memcpy(e_hdr->daddr, daddr, WLAN_ETHADDR_LEN);
477 memcpy(e_hdr->saddr, saddr, WLAN_ETHADDR_LEN);
478 e_hdr->type = htons(payload_length);
479
480
481 skb_trim(skb, skb->len - WLAN_CRC_LEN);
482
483 }
484
485
486
487
488
489
490
491
492
493
494 skb->protocol = eth_type_trans(skb, netdev);
495
496
497
498 if (wlandev->spy_number)
499 orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source,
500 P80211SKB_RXMETA(skb));
501
502
503 p80211skb_rxmeta_detach(skb);
504
505 return 0;
506}
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524int p80211_stt_findproto(u16 proto)
525{
526
527
528
529
530
531
532
533 if (proto == 0x80f3)
534 return 1;
535
536 return 0;
537}
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554void p80211skb_rxmeta_detach(struct sk_buff *skb)
555{
556 struct p80211_rxmeta *rxmeta;
557 struct p80211_frmmeta *frmmeta;
558
559
560 if (skb == NULL) {
561 pr_debug("Called w/ null skb.\n");
562 goto exit;
563 }
564 frmmeta = P80211SKB_FRMMETA(skb);
565 if (frmmeta == NULL) {
566 pr_debug("Called w/ bad frmmeta magic.\n");
567 goto exit;
568 }
569 rxmeta = frmmeta->rx;
570 if (rxmeta == NULL) {
571 pr_debug("Called w/ bad rxmeta ptr.\n");
572 goto exit;
573 }
574
575
576 kfree(rxmeta);
577
578
579 memset(skb->cb, 0, sizeof(skb->cb));
580exit:
581 return;
582}
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb)
601{
602 int result = 0;
603 struct p80211_rxmeta *rxmeta;
604 struct p80211_frmmeta *frmmeta;
605
606
607 if (P80211SKB_RXMETA(skb) != NULL) {
608 printk(KERN_ERR "%s: RXmeta already attached!\n",
609 wlandev->name);
610 result = 0;
611 goto exit;
612 }
613
614
615 rxmeta = kzalloc(sizeof(struct p80211_rxmeta), GFP_ATOMIC);
616
617 if (rxmeta == NULL) {
618 printk(KERN_ERR "%s: Failed to allocate rxmeta.\n",
619 wlandev->name);
620 result = 1;
621 goto exit;
622 }
623
624
625 rxmeta->wlandev = wlandev;
626 rxmeta->hosttime = jiffies;
627
628
629 memset(skb->cb, 0, sizeof(struct p80211_frmmeta));
630 frmmeta = (struct p80211_frmmeta *) (skb->cb);
631 frmmeta->magic = P80211_FRMMETA_MAGIC;
632 frmmeta->rx = rxmeta;
633exit:
634 return result;
635}
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb)
654{
655 struct p80211_frmmeta *meta;
656
657 meta = P80211SKB_FRMMETA(skb);
658 if (meta && meta->rx)
659 p80211skb_rxmeta_detach(skb);
660 else
661 printk(KERN_ERR "Freeing an skb (%p) w/ no frmmeta.\n", skb);
662 dev_kfree_skb(skb);
663 return;
664}
665