00001 #include <linux/etherdevice.h>
00002
00003 #include "hostap_80211.h"
00004 #include "hostap.h"
00005
00006 void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
00007 struct hostap_80211_rx_status *rx_stats)
00008 {
00009 struct hostap_ieee80211_hdr *hdr;
00010 u16 fc;
00011
00012 hdr = (struct hostap_ieee80211_hdr *) skb->data;
00013
00014 printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d "
00015 "jiffies=%ld\n",
00016 name, rx_stats->signal, rx_stats->noise, rx_stats->rate,
00017 skb->len, jiffies);
00018
00019 if (skb->len < 2)
00020 return;
00021
00022 fc = le16_to_cpu(hdr->frame_control);
00023 printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s",
00024 fc, WLAN_FC_GET_TYPE(fc), WLAN_FC_GET_STYPE(fc),
00025 fc & WLAN_FC_TODS ? " [ToDS]" : "",
00026 fc & WLAN_FC_FROMDS ? " [FromDS]" : "");
00027
00028 if (skb->len < IEEE80211_DATA_HDR3_LEN) {
00029 printk("\n");
00030 return;
00031 }
00032
00033 printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
00034 le16_to_cpu(hdr->seq_ctrl));
00035
00036 printk(KERN_DEBUG " A1=" MACSTR " A2=" MACSTR " A3=" MACSTR,
00037 MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3));
00038 if (skb->len >= 30)
00039 printk(" A4=" MACSTR, MAC2STR(hdr->addr4));
00040 printk("\n");
00041 }
00042
00043
00044
00045
00046 int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
00047 struct hostap_80211_rx_status *rx_stats, int type)
00048 {
00049 struct hostap_interface *iface = dev->priv;
00050 local_info_t *local = iface->local;
00051 int hdrlen, phdrlen, head_need, tail_need;
00052 u16 fc;
00053 int prism_header, ret;
00054 struct hostap_ieee80211_hdr *hdr;
00055
00056 dev->last_rx = jiffies;
00057
00058 if (dev->type == ARPHRD_IEEE80211_PRISM) {
00059 if (local->monitor_type == PRISM2_MONITOR_PRISM) {
00060 prism_header = 1;
00061 phdrlen = sizeof(struct linux_wlan_ng_prism_hdr);
00062 } else {
00063 prism_header = 2;
00064 phdrlen = sizeof(struct linux_wlan_ng_cap_hdr);
00065 }
00066 } else {
00067 prism_header = 0;
00068 phdrlen = 0;
00069 }
00070
00071 hdr = (struct hostap_ieee80211_hdr *) skb->data;
00072 fc = le16_to_cpu(hdr->frame_control);
00073
00074 if (type == PRISM2_RX_MGMT && (fc & WLAN_FC_PVER)) {
00075 printk(KERN_DEBUG "%s: dropped management frame with header "
00076 "version %d\n", dev->name, fc & WLAN_FC_PVER);
00077 dev_kfree_skb_any(skb);
00078 return 0;
00079 }
00080
00081 hdrlen = hostap_80211_get_hdrlen(fc);
00082
00083
00084
00085 head_need = phdrlen;
00086 tail_need = 0;
00087 #ifdef PRISM2_ADD_BOGUS_CRC
00088 tail_need += 4;
00089 #endif
00090
00091 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
00092 if (head_need > skb_headroom(skb) || tail_need > skb_tailroom(skb)) {
00093 struct sk_buff *nskb;
00094
00095 nskb = dev_alloc_skb(skb->len + head_need + tail_need);
00096 if (nskb == NULL) {
00097 dev_kfree_skb_any(skb);
00098 return 0;
00099 }
00100
00101 skb_reserve(nskb, head_need);
00102 memcpy(skb_put(nskb, skb->len), skb->data, skb->len);
00103 dev_kfree_skb_any(skb);
00104 skb = nskb;
00105 }
00106 #else
00107 head_need -= skb_headroom(skb);
00108 tail_need -= skb_tailroom(skb);
00109
00110 if (head_need > 0 || tail_need > 0) {
00111 if (pskb_expand_head(skb, head_need > 0 ? head_need : 0,
00112 tail_need > 0 ? tail_need : 0,
00113 GFP_ATOMIC)) {
00114 printk(KERN_DEBUG "%s: prism2_rx_80211 failed to "
00115 "reallocate skb buffer\n", dev->name);
00116 dev_kfree_skb_any(skb);
00117 return 0;
00118 }
00119 }
00120 #endif
00121
00122
00123
00124
00125 #ifdef PRISM2_ADD_BOGUS_CRC
00126 memset(skb_put(skb, 4), 0xff, 4);
00127 #endif
00128
00129 if (prism_header == 1) {
00130 struct linux_wlan_ng_prism_hdr *hdr;
00131 hdr = (struct linux_wlan_ng_prism_hdr *)
00132 skb_push(skb, phdrlen);
00133 memset(hdr, 0, phdrlen);
00134 hdr->msgcode = LWNG_CAP_DID_BASE;
00135 hdr->msglen = sizeof(*hdr);
00136 memcpy(hdr->devname, dev->name, sizeof(hdr->devname));
00137 #define LWNG_SETVAL(f,i,s,l,d) \
00138 hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \
00139 hdr->f.status = s; hdr->f.len = l; hdr->f.data = d
00140 LWNG_SETVAL(hosttime, 1, 0, 4, jiffies);
00141 LWNG_SETVAL(mactime, 2, 0, 0, rx_stats->mac_time);
00142 LWNG_SETVAL(channel, 3, 1 , 4, 0);
00143 LWNG_SETVAL(rssi, 4, 1 , 4, 0);
00144 LWNG_SETVAL(sq, 5, 1 , 4, 0);
00145 LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal);
00146 LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise);
00147 LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5);
00148 LWNG_SETVAL(istx, 9, 0, 4, 0);
00149 LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen);
00150 #undef LWNG_SETVAL
00151 } else if (prism_header == 2) {
00152 struct linux_wlan_ng_cap_hdr *hdr;
00153 hdr = (struct linux_wlan_ng_cap_hdr *)
00154 skb_push(skb, phdrlen);
00155 memset(hdr, 0, phdrlen);
00156 hdr->version = htonl(LWNG_CAPHDR_VERSION);
00157 hdr->length = htonl(phdrlen);
00158 hdr->mactime = __cpu_to_be64(rx_stats->mac_time);
00159 hdr->hosttime = __cpu_to_be64(jiffies);
00160 hdr->phytype = htonl(4);
00161 hdr->channel = htonl(local->channel);
00162 hdr->datarate = htonl(rx_stats->rate);
00163 hdr->antenna = htonl(0);
00164 hdr->priority = htonl(0);
00165 hdr->ssi_type = htonl(3);
00166 hdr->ssi_signal = htonl(rx_stats->signal);
00167 hdr->ssi_noise = htonl(rx_stats->noise);
00168 hdr->preamble = htonl(0);
00169 hdr->encoding = htonl(1);
00170 }
00171
00172 ret = skb->len - phdrlen;
00173 skb->dev = dev;
00174 skb->mac.raw = skb->data;
00175 skb_pull(skb, hdrlen);
00176 if (prism_header)
00177 skb_pull(skb, phdrlen);
00178 skb->pkt_type = PACKET_OTHERHOST;
00179 skb->protocol = __constant_htons(ETH_P_802_2);
00180
00181
00182
00183 netif_rx(skb);
00184
00185 return ret;
00186 }
00187
00188
00189
00190 static void monitor_rx(struct net_device *dev, struct sk_buff *skb,
00191 struct hostap_80211_rx_status *rx_stats)
00192 {
00193 struct net_device_stats *stats;
00194 int len;
00195
00196 len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR);
00197 stats = hostap_get_stats(dev);
00198 stats->rx_packets++;
00199 stats->rx_bytes += len;
00200 }
00201
00202
00203
00204 static struct prism2_frag_entry *
00205 prism2_frag_cache_find(local_info_t *local, unsigned int seq,
00206 unsigned int frag, u8 *src, u8 *dst)
00207 {
00208 struct prism2_frag_entry *entry;
00209 int i;
00210
00211 for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) {
00212 entry = &local->frag_cache[i];
00213 if (entry->skb != NULL &&
00214 time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
00215 printk(KERN_DEBUG "%s: expiring fragment cache entry "
00216 "seq=%u last_frag=%u\n",
00217 local->dev->name, entry->seq, entry->last_frag);
00218 dev_kfree_skb(entry->skb);
00219 entry->skb = NULL;
00220 }
00221
00222 if (entry->skb != NULL && entry->seq == seq &&
00223 (entry->last_frag + 1 == frag || frag == -1) &&
00224 memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
00225 memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
00226 return entry;
00227 }
00228
00229 return NULL;
00230 }
00231
00232
00233
00234 static struct sk_buff *
00235 prism2_frag_cache_get(local_info_t *local, struct hostap_ieee80211_hdr *hdr)
00236 {
00237 struct sk_buff *skb = NULL;
00238 u16 sc;
00239 unsigned int frag, seq;
00240 struct prism2_frag_entry *entry;
00241
00242 sc = le16_to_cpu(hdr->seq_ctrl);
00243 frag = WLAN_GET_SEQ_FRAG(sc);
00244 seq = WLAN_GET_SEQ_SEQ(sc);
00245
00246 if (frag == 0) {
00247
00248 skb = dev_alloc_skb(local->dev->mtu +
00249 sizeof(struct hostap_ieee80211_hdr) +
00250 8 +
00251 2 +
00252 8 + ETH_ALEN );
00253 if (skb == NULL)
00254 return NULL;
00255
00256 entry = &local->frag_cache[local->frag_next_idx];
00257 local->frag_next_idx++;
00258 if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN)
00259 local->frag_next_idx = 0;
00260
00261 if (entry->skb != NULL)
00262 dev_kfree_skb(entry->skb);
00263
00264 entry->first_frag_time = jiffies;
00265 entry->seq = seq;
00266 entry->last_frag = frag;
00267 entry->skb = skb;
00268 memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
00269 memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
00270 } else {
00271
00272
00273 entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2,
00274 hdr->addr1);
00275 if (entry != NULL) {
00276 entry->last_frag = frag;
00277 skb = entry->skb;
00278 }
00279 }
00280
00281 return skb;
00282 }
00283
00284
00285
00286 static int prism2_frag_cache_invalidate(local_info_t *local,
00287 struct hostap_ieee80211_hdr *hdr)
00288 {
00289 u16 sc;
00290 unsigned int seq;
00291 struct prism2_frag_entry *entry;
00292
00293 sc = le16_to_cpu(hdr->seq_ctrl);
00294 seq = WLAN_GET_SEQ_SEQ(sc);
00295
00296 entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1);
00297
00298 if (entry == NULL) {
00299 printk(KERN_DEBUG "%s: could not invalidate fragment cache "
00300 "entry (seq=%u)\n",
00301 local->dev->name, seq);
00302 return -1;
00303 }
00304
00305 entry->skb = NULL;
00306 return 0;
00307 }
00308
00309
00310 static inline int
00311 hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb,
00312 struct hostap_80211_rx_status *rx_stats, u16 type,
00313 u16 stype)
00314 {
00315 if (local->iw_mode == IW_MODE_MASTER) {
00316 hostap_update_sta_ps(local, (struct hostap_ieee80211_hdr *)
00317 skb->data);
00318 }
00319
00320 if (local->hostapd && type == WLAN_FC_TYPE_MGMT) {
00321 if (stype == WLAN_FC_STYPE_BEACON &&
00322 local->iw_mode == IW_MODE_MASTER) {
00323 struct sk_buff *skb2;
00324
00325
00326 skb2 = skb_clone(skb, GFP_ATOMIC);
00327 if (skb2)
00328 hostap_rx(skb2->dev, skb2, rx_stats);
00329 }
00330
00331
00332
00333 local->apdevstats.rx_packets++;
00334 local->apdevstats.rx_bytes += skb->len;
00335 prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT);
00336 return 0;
00337 }
00338
00339 if (local->iw_mode == IW_MODE_MASTER) {
00340 if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
00341 printk(KERN_DEBUG "%s: unknown management frame "
00342 "(type=0x%02x, stype=0x%02x) dropped\n",
00343 skb->dev->name, type, stype);
00344 return -1;
00345 }
00346
00347 hostap_rx(skb->dev, skb, rx_stats);
00348 return 0;
00349 } else {
00350 printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
00351 "received in non-Host AP mode\n", skb->dev->name);
00352 return -1;
00353 }
00354 }
00355
00356
00357
00358 static inline struct net_device *prism2_rx_get_wds(local_info_t *local,
00359 u8 *addr)
00360 {
00361 struct hostap_interface *iface = NULL;
00362 struct list_head *ptr;
00363 unsigned long flags;
00364
00365 read_lock_irqsave(&local->iface_lock, flags);
00366 list_for_each(ptr, &local->hostap_interfaces) {
00367 iface = list_entry(ptr, struct hostap_interface, list);
00368 if (iface->type == HOSTAP_INTERFACE_WDS &&
00369 memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0)
00370 break;
00371 iface = NULL;
00372 }
00373 read_unlock_irqrestore(&local->iface_lock, flags);
00374
00375 return iface ? iface->dev : NULL;
00376 }
00377
00378
00379 static inline int
00380 hostap_rx_frame_wds(local_info_t *local, struct hostap_ieee80211_hdr *hdr,
00381 u16 fc, struct net_device **wds)
00382 {
00383
00384
00385 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) !=
00386 (WLAN_FC_TODS | WLAN_FC_FROMDS) &&
00387 (local->iw_mode != IW_MODE_MASTER || !(fc & WLAN_FC_TODS)))
00388 return 0;
00389
00390
00391
00392 if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 &&
00393 (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff ||
00394 hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff ||
00395 hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
00396
00397 PDEBUG(DEBUG_EXTRA, "%s: received WDS frame with "
00398 "not own or broadcast %s=" MACSTR "\n",
00399 local->dev->name, fc & WLAN_FC_FROMDS ? "RA" : "BSSID",
00400 MAC2STR(hdr->addr1));
00401 return -1;
00402 }
00403
00404
00405 *wds = prism2_rx_get_wds(local, hdr->addr2);
00406 if (*wds == NULL && fc & WLAN_FC_FROMDS &&
00407 (local->iw_mode != IW_MODE_INFRA ||
00408 !(local->wds_type & HOSTAP_WDS_AP_CLIENT) ||
00409 memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) {
00410
00411
00412 PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
00413 "from unknown TA=" MACSTR "\n",
00414 local->dev->name, MAC2STR(hdr->addr2));
00415 if (local->ap && local->ap->autom_ap_wds)
00416 hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
00417 return -1;
00418 }
00419
00420 if (*wds && !(fc & WLAN_FC_FROMDS) && local->ap &&
00421 hostap_is_sta_assoc(local->ap, hdr->addr2)) {
00422
00423
00424
00425
00426
00427 *wds = NULL;
00428 }
00429
00430 return 0;
00431 }
00432
00433
00434 static int hostap_is_eapol_frame(local_info_t *local,
00435 struct hostap_ieee80211_hdr *hdr, u8 *buf,
00436 int len)
00437 {
00438 struct net_device *dev = local->dev;
00439 u16 fc, ethertype;
00440
00441 fc = le16_to_cpu(hdr->frame_control);
00442
00443
00444 if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_TODS &&
00445 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
00446 memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
00447
00448 } else if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_FROMDS &&
00449 memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
00450
00451 } else
00452 return 0;
00453
00454 if (len < 8)
00455 return 0;
00456
00457
00458 ethertype = (buf[6] << 8) | buf[7];
00459 if (ethertype == ETH_P_PAE)
00460 return 1;
00461
00462 return 0;
00463 }
00464
00465
00466
00467 static inline int
00468 hostap_rx_frame_decrypt(local_info_t *local, int iswep, struct sk_buff *skb)
00469 {
00470 struct hostap_ieee80211_hdr *hdr;
00471 struct prism2_crypt_data *crypt;
00472 void *sta = NULL;
00473 int ret = 0, olen, len, hdrlen;
00474 char *payload;
00475
00476 hdr = (struct hostap_ieee80211_hdr *) skb->data;
00477 hdrlen = hostap_80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
00478
00479 len = skb->len - hdrlen;
00480 payload = ((char *) (hdr)) + hdrlen;
00481 crypt = local->crypt;
00482 sta = NULL;
00483
00484
00485
00486
00487
00488
00489
00490 if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
00491 (void) hostap_handle_sta_crypto(local, hdr, &crypt, &sta);
00492
00493
00494
00495 if (crypt && (crypt->ops == NULL || crypt->ops->decrypt == NULL))
00496 crypt = NULL;
00497
00498 if (!crypt && iswep) {
00499 printk(KERN_DEBUG "%s: WEP decryption failed (not set) (SA="
00500 MACSTR ")\n", local->dev->name, MAC2STR(hdr->addr2));
00501 local->comm_tallies.rx_discards_wep_undecryptable++;
00502 ret = -1;
00503 goto done;
00504 }
00505
00506 if (!crypt)
00507 goto done;
00508
00509 if (!iswep && !local->open_wep) {
00510 if (local->ieee_802_1x &&
00511 hostap_is_eapol_frame(local, hdr, payload, len)) {
00512
00513
00514 printk(KERN_DEBUG "%s: RX: IEEE 802.1X - passing "
00515 "unencrypted EAPOL frame\n", local->dev->name);
00516 goto done;
00517 }
00518 printk(KERN_DEBUG "%s: encryption configured, but RX frame "
00519 "not encrypted (SA=" MACSTR ")\n",
00520 local->dev->name, MAC2STR(hdr->addr2));
00521 ret = -1;
00522 goto done;
00523 }
00524
00525
00526
00527 atomic_inc(&crypt->refcnt);
00528 olen = crypt->ops->decrypt(payload, len, crypt->priv);
00529 atomic_dec(&crypt->refcnt);
00530 if (olen < 0) {
00531 printk(KERN_DEBUG "%s: WEP decryption failed (SA=" MACSTR
00532 ")\n", local->dev->name, MAC2STR(hdr->addr2));
00533 local->comm_tallies.rx_discards_wep_undecryptable++;
00534 ret = -1;
00535 goto done;
00536 }
00537
00538 skb_trim(skb, skb->len - (len - olen));
00539
00540 done:
00541 if (sta)
00542 hostap_handle_sta_release(sta);
00543
00544 return ret;
00545 }
00546
00547
00548
00549
00550
00551 void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
00552 struct hostap_80211_rx_status *rx_stats)
00553 {
00554 struct hostap_interface *iface = dev->priv;
00555 local_info_t *local = iface->local;
00556 struct hostap_ieee80211_hdr *hdr;
00557 size_t hdrlen;
00558 u16 fc, type, stype, sc;
00559 struct net_device *wds = NULL;
00560 struct net_device_stats *stats;
00561 unsigned int frag;
00562 u8 *payload;
00563 struct sk_buff *skb2 = NULL;
00564 u16 ethertype;
00565 int frame_authorized = 0;
00566 int from_assoc_ap = 0;
00567 u8 dst[ETH_ALEN];
00568 u8 src[ETH_ALEN];
00569
00570 hdr = (struct hostap_ieee80211_hdr *) skb->data;
00571 stats = hostap_get_stats(dev);
00572
00573 if (skb->len < 10)
00574 goto rx_dropped;
00575
00576 fc = le16_to_cpu(hdr->frame_control);
00577 type = WLAN_FC_GET_TYPE(fc);
00578 stype = WLAN_FC_GET_STYPE(fc);
00579 sc = le16_to_cpu(hdr->seq_ctrl);
00580 frag = WLAN_GET_SEQ_FRAG(sc);
00581 hdrlen = hostap_80211_get_hdrlen(fc);
00582
00583 #if WIRELESS_EXT > 15
00584
00585
00586 #ifdef IW_WIRELESS_SPY
00587
00588 if (iface->spy_data.spy_number > 0) {
00589 struct iw_quality wstats;
00590 wstats.level = rx_stats->signal;
00591 wstats.noise = rx_stats->noise;
00592 wstats.updated = 6;
00593
00594 wireless_spy_update(dev, hdr->addr2, &wstats);
00595 }
00596 #endif
00597 #endif
00598
00599 if (local->iw_mode == IW_MODE_MONITOR) {
00600 monitor_rx(dev, skb, rx_stats);
00601 return;
00602 }
00603
00604 if (type != WLAN_FC_TYPE_DATA) {
00605 if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
00606 fc & WLAN_FC_ISWEP && local->host_decrypt &&
00607 hostap_rx_frame_decrypt(local, fc & WLAN_FC_ISWEP, skb)) {
00608 printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
00609 "from " MACSTR "\n", dev->name,
00610 MAC2STR(hdr->addr2));
00611
00612
00613 goto rx_dropped;
00614 }
00615
00616 if (hostap_rx_frame_mgmt(local, skb, rx_stats, type, stype))
00617 goto rx_dropped;
00618 else
00619 goto rx_exit;
00620 }
00621
00622
00623 if (skb->len < IEEE80211_DATA_HDR3_LEN)
00624 goto rx_dropped;
00625
00626 switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) {
00627 case WLAN_FC_FROMDS:
00628 memcpy(dst, hdr->addr1, ETH_ALEN);
00629 memcpy(src, hdr->addr3, ETH_ALEN);
00630 break;
00631 case WLAN_FC_TODS:
00632 memcpy(dst, hdr->addr3, ETH_ALEN);
00633 memcpy(src, hdr->addr2, ETH_ALEN);
00634 break;
00635 case WLAN_FC_FROMDS | WLAN_FC_TODS:
00636 if (skb->len < IEEE80211_DATA_HDR4_LEN)
00637 goto rx_dropped;
00638 memcpy(dst, hdr->addr3, ETH_ALEN);
00639 memcpy(src, hdr->addr4, ETH_ALEN);
00640 break;
00641 case 0:
00642 memcpy(dst, hdr->addr1, ETH_ALEN);
00643 memcpy(src, hdr->addr2, ETH_ALEN);
00644 break;
00645 }
00646
00647 if (hostap_rx_frame_wds(local, hdr, fc, &wds))
00648 goto rx_dropped;
00649 if (wds) {
00650 skb->dev = dev = wds;
00651 stats = hostap_get_stats(dev);
00652 }
00653
00654 if (local->iw_mode == IW_MODE_MASTER && !wds &&
00655 (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_FROMDS &&
00656 local->stadev &&
00657 memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) {
00658
00659 skb->dev = dev = local->stadev;
00660 stats = hostap_get_stats(dev);
00661 from_assoc_ap = 1;
00662 }
00663
00664 dev->last_rx = jiffies;
00665
00666 if ((local->iw_mode == IW_MODE_MASTER ||
00667 local->iw_mode == IW_MODE_REPEAT) &&
00668 !from_assoc_ap) {
00669 switch (hostap_handle_sta_rx(local, dev, skb, rx_stats,
00670 wds != NULL)) {
00671 case AP_RX_CONTINUE_NOT_AUTHORIZED:
00672 frame_authorized = 0;
00673 break;
00674 case AP_RX_CONTINUE:
00675 frame_authorized = 1;
00676 break;
00677 case AP_RX_DROP:
00678 goto rx_dropped;
00679 case AP_RX_EXIT:
00680 goto rx_exit;
00681 }
00682 } else if (local->iw_mode == IW_MODE_REPEAT ||
00683 local->wds_type & HOSTAP_WDS_AP_CLIENT)
00684 hostap_update_rx_stats(local->ap, hdr, rx_stats);
00685
00686
00687
00688 if (stype != WLAN_FC_STYPE_DATA &&
00689 stype != WLAN_FC_STYPE_DATA_CFACK &&
00690 stype != WLAN_FC_STYPE_DATA_CFPOLL &&
00691 stype != WLAN_FC_STYPE_DATA_CFACKPOLL) {
00692 if (stype != WLAN_FC_STYPE_NULLFUNC)
00693 printk(KERN_DEBUG "%s: RX: dropped data frame "
00694 "with no data (type=0x%02x, subtype=0x%02x)\n",
00695 dev->name, type, stype);
00696 goto rx_dropped;
00697 }
00698
00699
00700
00701 if (local->host_decrypt &&
00702 hostap_rx_frame_decrypt(local, fc & WLAN_FC_ISWEP, skb))
00703 goto rx_dropped;
00704
00705
00706
00707 if (local->host_decrypt && (fc & WLAN_FC_ISWEP) &&
00708 (frag != 0 || (fc & WLAN_FC_MOREFRAG))) {
00709 int flen;
00710 struct sk_buff *frag_skb =
00711 prism2_frag_cache_get(local, hdr);
00712 if (!frag_skb) {
00713 printk(KERN_DEBUG "%s: Rx cannot get skb from "
00714 "fragment cache (morefrag=%d seq=%u frag=%u)\n",
00715 dev->name, (fc & WLAN_FC_MOREFRAG) != 0,
00716 WLAN_GET_SEQ_SEQ(sc), frag);
00717 goto rx_dropped;
00718 }
00719
00720 flen = skb->len;
00721 if (frag != 0)
00722 flen -= hdrlen;
00723
00724 if (frag_skb->tail + flen > frag_skb->end) {
00725 printk(KERN_WARNING "%s: host decrypted and "
00726 "reassembled frame did not fit skb\n",
00727 dev->name);
00728 prism2_frag_cache_invalidate(local, hdr);
00729 goto rx_dropped;
00730 }
00731
00732 if (frag == 0) {
00733
00734
00735 memcpy(skb_put(frag_skb, flen), skb->data, flen);
00736 } else {
00737
00738
00739 memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
00740 flen);
00741 }
00742 dev_kfree_skb(skb);
00743 skb = NULL;
00744
00745 if (fc & WLAN_FC_MOREFRAG) {
00746
00747
00748
00749 goto rx_exit;
00750 }
00751
00752
00753
00754 skb = frag_skb;
00755 hdr = (struct hostap_ieee80211_hdr *) skb->data;
00756 prism2_frag_cache_invalidate(local, hdr);
00757 }
00758
00759
00760
00761 payload = skb->data + hdrlen;
00762 ethertype = (payload[6] << 8) | payload[7];
00763
00764
00765
00766 if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) {
00767 if (ethertype == ETH_P_PAE) {
00768 printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
00769 dev->name);
00770 if (local->hostapd && local->apdev) {
00771
00772
00773 prism2_rx_80211(local->apdev, skb, rx_stats,
00774 PRISM2_RX_MGMT);
00775 local->apdevstats.rx_packets++;
00776 local->apdevstats.rx_bytes += skb->len;
00777 goto rx_exit;
00778 }
00779 } else if (!frame_authorized) {
00780 printk(KERN_DEBUG "%s: dropped frame from "
00781 "unauthorized port (IEEE 802.1X): "
00782 "ethertype=0x%04x\n",
00783 dev->name, ethertype);
00784 goto rx_dropped;
00785 }
00786 }
00787
00788
00789 if (skb->len - hdrlen >= 8 &&
00790 ((memcmp(payload, rfc1042_header, 6) == 0 &&
00791 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
00792 memcmp(payload, bridge_tunnel_header, 6) == 0)) {
00793
00794
00795 skb_pull(skb, hdrlen + 6);
00796 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
00797 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
00798 } else {
00799 u16 len;
00800
00801 skb_pull(skb, hdrlen);
00802 len = htons(skb->len);
00803 memcpy(skb_push(skb, 2), &len, 2);
00804 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
00805 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
00806 }
00807
00808 if (wds && ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == WLAN_FC_TODS) &&
00809 skb->len >= ETH_HLEN + ETH_ALEN) {
00810
00811
00812 memcpy(skb->data + ETH_ALEN,
00813 skb->data + skb->len - ETH_ALEN, ETH_ALEN);
00814 skb_trim(skb, skb->len - ETH_ALEN);
00815 }
00816
00817 stats->rx_packets++;
00818 stats->rx_bytes += skb->len;
00819
00820 if (local->iw_mode == IW_MODE_MASTER && !wds &&
00821 local->ap->bridge_packets) {
00822 if (dst[0] & 0x01) {
00823
00824
00825 local->ap->bridged_multicast++;
00826 skb2 = skb_clone(skb, GFP_ATOMIC);
00827 if (skb2 == NULL)
00828 printk(KERN_DEBUG "%s: skb_clone failed for "
00829 "multicast frame\n", dev->name);
00830 } else if (hostap_is_sta_assoc(local->ap, dst)) {
00831
00832
00833 local->ap->bridged_unicast++;
00834 skb2 = skb;
00835 skb = NULL;
00836 }
00837 }
00838
00839 if (skb2 != NULL) {
00840
00841 skb2->protocol = __constant_htons(ETH_P_802_3);
00842 skb2->mac.raw = skb2->nh.raw = skb2->data;
00843
00844 skb2->dev = dev;
00845 dev_queue_xmit(skb2);
00846 }
00847
00848 if (skb) {
00849 skb->protocol = eth_type_trans(skb, dev);
00850
00851
00852
00853 skb->dev = dev;
00854 netif_rx(skb);
00855 }
00856
00857 rx_exit:
00858 return;
00859
00860 rx_dropped:
00861 dev_kfree_skb(skb);
00862
00863 stats->rx_dropped++;
00864 goto rx_exit;
00865 }
00866
00867
00868 EXPORT_SYMBOL(hostap_80211_rx);