0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056 #include <linux/module.h>
0057 #include <linux/kernel.h>
0058 #include <linux/sched.h>
0059 #include <linux/types.h>
0060 #include <linux/skbuff.h>
0061 #include <linux/slab.h>
0062 #include <linux/wireless.h>
0063 #include <linux/netdevice.h>
0064 #include <linux/etherdevice.h>
0065 #include <linux/if_ether.h>
0066 #include <linux/byteorder/generic.h>
0067
0068 #include <asm/byteorder.h>
0069
0070 #include "p80211types.h"
0071 #include "p80211hdr.h"
0072 #include "p80211conv.h"
0073 #include "p80211mgmt.h"
0074 #include "p80211msg.h"
0075 #include "p80211netdev.h"
0076 #include "p80211ioctl.h"
0077 #include "p80211req.h"
0078
0079 static const u8 oui_rfc1042[] = { 0x00, 0x00, 0x00 };
0080 static const u8 oui_8021h[] = { 0x00, 0x00, 0xf8 };
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108 int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
0109 struct sk_buff *skb, struct p80211_hdr *p80211_hdr,
0110 struct p80211_metawep *p80211_wep)
0111 {
0112 __le16 fc;
0113 u16 proto;
0114 struct wlan_ethhdr e_hdr;
0115 struct wlan_llc *e_llc;
0116 struct wlan_snap *e_snap;
0117 int foo;
0118
0119 memcpy(&e_hdr, skb->data, sizeof(e_hdr));
0120
0121 if (skb->len <= 0) {
0122 pr_debug("zero-length skb!\n");
0123 return 1;
0124 }
0125
0126 if (ethconv == WLAN_ETHCONV_ENCAP) {
0127 pr_debug("ENCAP len: %d\n", skb->len);
0128
0129
0130
0131 } else {
0132
0133 proto = ntohs(e_hdr.type);
0134 if (proto <= ETH_DATA_LEN) {
0135 pr_debug("802.3 len: %d\n", skb->len);
0136
0137
0138
0139
0140 skb_pull(skb, ETH_HLEN);
0141
0142
0143 skb_trim(skb, proto);
0144 } else {
0145 pr_debug("DIXII len: %d\n", skb->len);
0146
0147
0148
0149 skb_pull(skb, ETH_HLEN);
0150
0151
0152 e_snap = skb_push(skb, sizeof(struct wlan_snap));
0153 e_snap->type = htons(proto);
0154 if (ethconv == WLAN_ETHCONV_8021h &&
0155 p80211_stt_findproto(proto)) {
0156 memcpy(e_snap->oui, oui_8021h,
0157 WLAN_IEEE_OUI_LEN);
0158 } else {
0159 memcpy(e_snap->oui, oui_rfc1042,
0160 WLAN_IEEE_OUI_LEN);
0161 }
0162
0163
0164 e_llc = skb_push(skb, sizeof(struct wlan_llc));
0165 e_llc->dsap = 0xAA;
0166 e_llc->ssap = 0xAA;
0167 e_llc->ctl = 0x03;
0168 }
0169 }
0170
0171
0172
0173 fc = cpu_to_le16(WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
0174 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY));
0175
0176 switch (wlandev->macmode) {
0177 case WLAN_MACMODE_IBSS_STA:
0178 memcpy(p80211_hdr->address1, &e_hdr.daddr, ETH_ALEN);
0179 memcpy(p80211_hdr->address2, wlandev->netdev->dev_addr, ETH_ALEN);
0180 memcpy(p80211_hdr->address3, wlandev->bssid, ETH_ALEN);
0181 break;
0182 case WLAN_MACMODE_ESS_STA:
0183 fc |= cpu_to_le16(WLAN_SET_FC_TODS(1));
0184 memcpy(p80211_hdr->address1, wlandev->bssid, ETH_ALEN);
0185 memcpy(p80211_hdr->address2, wlandev->netdev->dev_addr, ETH_ALEN);
0186 memcpy(p80211_hdr->address3, &e_hdr.daddr, ETH_ALEN);
0187 break;
0188 case WLAN_MACMODE_ESS_AP:
0189 fc |= cpu_to_le16(WLAN_SET_FC_FROMDS(1));
0190 memcpy(p80211_hdr->address1, &e_hdr.daddr, ETH_ALEN);
0191 memcpy(p80211_hdr->address2, wlandev->bssid, ETH_ALEN);
0192 memcpy(p80211_hdr->address3, &e_hdr.saddr, ETH_ALEN);
0193 break;
0194 default:
0195 netdev_err(wlandev->netdev,
0196 "Error: Converting eth to wlan in unknown mode.\n");
0197 return 1;
0198 }
0199
0200 p80211_wep->data = NULL;
0201
0202 if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) &&
0203 (wlandev->hostwep & HOSTWEP_ENCRYPT)) {
0204
0205
0206 p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
0207 if (!p80211_wep->data)
0208 return -ENOMEM;
0209 foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
0210 skb->len,
0211 wlandev->hostwep & HOSTWEP_DEFAULTKEY_MASK,
0212 p80211_wep->iv, p80211_wep->icv);
0213 if (foo) {
0214 netdev_warn(wlandev->netdev,
0215 "Host en-WEP failed, dropping frame (%d).\n",
0216 foo);
0217 kfree(p80211_wep->data);
0218 return 2;
0219 }
0220 fc |= cpu_to_le16(WLAN_SET_FC_ISWEP(1));
0221 }
0222
0223
0224
0225 p80211_hdr->frame_control = fc;
0226 p80211_hdr->duration_id = 0;
0227 p80211_hdr->sequence_control = 0;
0228
0229 return 0;
0230 }
0231
0232
0233 static void orinoco_spy_gather(struct wlandevice *wlandev, char *mac,
0234 struct p80211_rxmeta *rxmeta)
0235 {
0236 int i;
0237
0238
0239
0240
0241
0242 for (i = 0; i < wlandev->spy_number; i++) {
0243 if (!memcmp(wlandev->spy_address[i], mac, ETH_ALEN)) {
0244 wlandev->spy_stat[i].level = rxmeta->signal;
0245 wlandev->spy_stat[i].noise = rxmeta->noise;
0246 wlandev->spy_stat[i].qual =
0247 (rxmeta->signal >
0248 rxmeta->noise) ? (rxmeta->signal -
0249 rxmeta->noise) : 0;
0250 wlandev->spy_stat[i].updated = 0x7;
0251 }
0252 }
0253 }
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
0276 struct sk_buff *skb)
0277 {
0278 struct net_device *netdev = wlandev->netdev;
0279 u16 fc;
0280 unsigned int payload_length;
0281 unsigned int payload_offset;
0282 u8 daddr[ETH_ALEN];
0283 u8 saddr[ETH_ALEN];
0284 struct p80211_hdr *w_hdr;
0285 struct wlan_ethhdr *e_hdr;
0286 struct wlan_llc *e_llc;
0287 struct wlan_snap *e_snap;
0288
0289 int foo;
0290
0291 payload_length = skb->len - WLAN_HDR_A3_LEN - WLAN_CRC_LEN;
0292 payload_offset = WLAN_HDR_A3_LEN;
0293
0294 w_hdr = (struct p80211_hdr *)skb->data;
0295
0296
0297 fc = le16_to_cpu(w_hdr->frame_control);
0298 if ((WLAN_GET_FC_TODS(fc) == 0) && (WLAN_GET_FC_FROMDS(fc) == 0)) {
0299 ether_addr_copy(daddr, w_hdr->address1);
0300 ether_addr_copy(saddr, w_hdr->address2);
0301 } else if ((WLAN_GET_FC_TODS(fc) == 0) &&
0302 (WLAN_GET_FC_FROMDS(fc) == 1)) {
0303 ether_addr_copy(daddr, w_hdr->address1);
0304 ether_addr_copy(saddr, w_hdr->address3);
0305 } else if ((WLAN_GET_FC_TODS(fc) == 1) &&
0306 (WLAN_GET_FC_FROMDS(fc) == 0)) {
0307 ether_addr_copy(daddr, w_hdr->address3);
0308 ether_addr_copy(saddr, w_hdr->address2);
0309 } else {
0310 payload_offset = WLAN_HDR_A4_LEN;
0311 if (payload_length < WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN) {
0312 netdev_err(netdev, "A4 frame too short!\n");
0313 return 1;
0314 }
0315 payload_length -= (WLAN_HDR_A4_LEN - WLAN_HDR_A3_LEN);
0316 ether_addr_copy(daddr, w_hdr->address3);
0317 ether_addr_copy(saddr, w_hdr->address4);
0318 }
0319
0320
0321 if ((wlandev->hostwep & HOSTWEP_PRIVACYINVOKED) &&
0322 WLAN_GET_FC_ISWEP(fc) &&
0323 (wlandev->hostwep & HOSTWEP_DECRYPT)) {
0324 if (payload_length <= 8) {
0325 netdev_err(netdev,
0326 "WEP frame too short (%u).\n", skb->len);
0327 return 1;
0328 }
0329 foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
0330 payload_length - 8, -1,
0331 skb->data + payload_offset,
0332 skb->data + payload_offset +
0333 payload_length - 4);
0334 if (foo) {
0335
0336 pr_debug("Host de-WEP failed, dropping frame (%d).\n",
0337 foo);
0338 wlandev->rx.decrypt_err++;
0339 return 2;
0340 }
0341
0342
0343 payload_length -= 8;
0344
0345 skb_pull(skb, 4);
0346
0347 skb_trim(skb, skb->len - 4);
0348
0349 wlandev->rx.decrypt++;
0350 }
0351
0352 e_hdr = (struct wlan_ethhdr *)(skb->data + payload_offset);
0353
0354 e_llc = (struct wlan_llc *)(skb->data + payload_offset);
0355 e_snap =
0356 (struct wlan_snap *)(skb->data + payload_offset +
0357 sizeof(struct wlan_llc));
0358
0359
0360 if ((payload_length >= sizeof(struct wlan_ethhdr)) &&
0361 (e_llc->dsap != 0xaa || e_llc->ssap != 0xaa) &&
0362 ((!ether_addr_equal_unaligned(daddr, e_hdr->daddr)) ||
0363 (!ether_addr_equal_unaligned(saddr, e_hdr->saddr)))) {
0364 pr_debug("802.3 ENCAP len: %d\n", payload_length);
0365
0366
0367 if (payload_length > (netdev->mtu + ETH_HLEN)) {
0368
0369
0370 netdev_err(netdev, "ENCAP frame too large (%d > %d)\n",
0371 payload_length, netdev->mtu + ETH_HLEN);
0372 return 1;
0373 }
0374
0375
0376 skb_pull(skb, payload_offset);
0377
0378 skb_trim(skb, skb->len - WLAN_CRC_LEN);
0379
0380 } else if ((payload_length >= sizeof(struct wlan_llc) +
0381 sizeof(struct wlan_snap)) &&
0382 (e_llc->dsap == 0xaa) &&
0383 (e_llc->ssap == 0xaa) &&
0384 (e_llc->ctl == 0x03) &&
0385 (((memcmp(e_snap->oui, oui_rfc1042,
0386 WLAN_IEEE_OUI_LEN) == 0) &&
0387 (ethconv == WLAN_ETHCONV_8021h) &&
0388 (p80211_stt_findproto(be16_to_cpu(e_snap->type)))) ||
0389 (memcmp(e_snap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN) !=
0390 0))) {
0391 pr_debug("SNAP+RFC1042 len: %d\n", payload_length);
0392
0393
0394
0395
0396 if (payload_length > netdev->mtu) {
0397
0398
0399 netdev_err(netdev, "SNAP frame too large (%d > %d)\n",
0400 payload_length, netdev->mtu);
0401 return 1;
0402 }
0403
0404
0405 skb_pull(skb, payload_offset);
0406
0407
0408 e_hdr = skb_push(skb, ETH_HLEN);
0409 ether_addr_copy(e_hdr->daddr, daddr);
0410 ether_addr_copy(e_hdr->saddr, saddr);
0411 e_hdr->type = htons(payload_length);
0412
0413
0414 skb_trim(skb, skb->len - WLAN_CRC_LEN);
0415
0416 } else if ((payload_length >= sizeof(struct wlan_llc) +
0417 sizeof(struct wlan_snap)) &&
0418 (e_llc->dsap == 0xaa) &&
0419 (e_llc->ssap == 0xaa) &&
0420 (e_llc->ctl == 0x03)) {
0421 pr_debug("802.1h/RFC1042 len: %d\n", payload_length);
0422
0423
0424
0425
0426
0427 if ((payload_length - sizeof(struct wlan_llc) -
0428 sizeof(struct wlan_snap))
0429 > netdev->mtu) {
0430
0431
0432 netdev_err(netdev, "DIXII frame too large (%ld > %d)\n",
0433 (long)(payload_length -
0434 sizeof(struct wlan_llc) -
0435 sizeof(struct wlan_snap)), netdev->mtu);
0436 return 1;
0437 }
0438
0439
0440 skb_pull(skb, payload_offset);
0441
0442
0443 skb_pull(skb, sizeof(struct wlan_llc));
0444
0445
0446 skb_pull(skb, sizeof(struct wlan_snap));
0447
0448
0449 e_hdr = skb_push(skb, ETH_HLEN);
0450 e_hdr->type = e_snap->type;
0451 ether_addr_copy(e_hdr->daddr, daddr);
0452 ether_addr_copy(e_hdr->saddr, saddr);
0453
0454
0455 skb_trim(skb, skb->len - WLAN_CRC_LEN);
0456 } else {
0457 pr_debug("NON-ENCAP len: %d\n", payload_length);
0458
0459
0460
0461
0462
0463
0464 if (payload_length > netdev->mtu) {
0465
0466
0467 netdev_err(netdev, "OTHER frame too large (%d > %d)\n",
0468 payload_length, netdev->mtu);
0469 return 1;
0470 }
0471
0472
0473 skb_pull(skb, payload_offset);
0474
0475
0476 e_hdr = skb_push(skb, ETH_HLEN);
0477 ether_addr_copy(e_hdr->daddr, daddr);
0478 ether_addr_copy(e_hdr->saddr, saddr);
0479 e_hdr->type = htons(payload_length);
0480
0481
0482 skb_trim(skb, skb->len - WLAN_CRC_LEN);
0483 }
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 skb->protocol = eth_type_trans(skb, netdev);
0495
0496
0497
0498 if (wlandev->spy_number)
0499 orinoco_spy_gather(wlandev, eth_hdr(skb)->h_source,
0500 p80211skb_rxmeta(skb));
0501
0502
0503 p80211skb_rxmeta_detach(skb);
0504
0505 return 0;
0506 }
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525 int p80211_stt_findproto(u16 proto)
0526 {
0527
0528
0529
0530
0531
0532
0533
0534 if (proto == ETH_P_AARP)
0535 return 1;
0536
0537 return 0;
0538 }
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556 void p80211skb_rxmeta_detach(struct sk_buff *skb)
0557 {
0558 struct p80211_rxmeta *rxmeta;
0559 struct p80211_frmmeta *frmmeta;
0560
0561
0562 if (!skb) {
0563 pr_debug("Called w/ null skb.\n");
0564 return;
0565 }
0566 frmmeta = p80211skb_frmmeta(skb);
0567 if (!frmmeta) {
0568 pr_debug("Called w/ bad frmmeta magic.\n");
0569 return;
0570 }
0571 rxmeta = frmmeta->rx;
0572 if (!rxmeta) {
0573 pr_debug("Called w/ bad rxmeta ptr.\n");
0574 return;
0575 }
0576
0577
0578 kfree(rxmeta);
0579
0580
0581 memset(skb->cb, 0, sizeof(skb->cb));
0582 }
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601 int p80211skb_rxmeta_attach(struct wlandevice *wlandev, struct sk_buff *skb)
0602 {
0603 int result = 0;
0604 struct p80211_rxmeta *rxmeta;
0605 struct p80211_frmmeta *frmmeta;
0606
0607
0608 if (p80211skb_rxmeta(skb)) {
0609 netdev_err(wlandev->netdev,
0610 "%s: RXmeta already attached!\n", wlandev->name);
0611 result = 0;
0612 goto exit;
0613 }
0614
0615
0616 rxmeta = kzalloc(sizeof(*rxmeta), GFP_ATOMIC);
0617
0618 if (!rxmeta) {
0619 result = 1;
0620 goto exit;
0621 }
0622
0623
0624 rxmeta->wlandev = wlandev;
0625 rxmeta->hosttime = jiffies;
0626
0627
0628 memset(skb->cb, 0, sizeof(struct p80211_frmmeta));
0629 frmmeta = (struct p80211_frmmeta *)(skb->cb);
0630 frmmeta->magic = P80211_FRMMETA_MAGIC;
0631 frmmeta->rx = rxmeta;
0632 exit:
0633 return result;
0634 }
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653 void p80211skb_free(struct wlandevice *wlandev, struct sk_buff *skb)
0654 {
0655 struct p80211_frmmeta *meta;
0656
0657 meta = p80211skb_frmmeta(skb);
0658 if (meta && meta->rx)
0659 p80211skb_rxmeta_detach(skb);
0660 else
0661 netdev_err(wlandev->netdev,
0662 "Freeing an skb (%p) w/ no frmmeta.\n", skb);
0663 dev_kfree_skb(skb);
0664 }