linux/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
<<
>>
Prefs
   1/*
   2 * Original code based Host AP (software wireless LAN access point) driver
   3 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
   4 *
   5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
   6 * <jkmaline@cc.hut.fi>
   7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
   8 * Copyright (c) 2004, Intel Corporation
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation. See README and COPYING for
  13 * more details.
  14 ******************************************************************************
  15
  16  Few modifications for Realtek's Wi-Fi drivers by
  17  Andrea Merello <andreamrl@tiscali.it>
  18
  19  A special thanks goes to Realtek for their support !
  20
  21******************************************************************************/
  22
  23
  24#include <linux/compiler.h>
  25//#include <linux/config.h>
  26#include <linux/errno.h>
  27#include <linux/if_arp.h>
  28#include <linux/in6.h>
  29#include <linux/in.h>
  30#include <linux/ip.h>
  31#include <linux/kernel.h>
  32#include <linux/module.h>
  33#include <linux/netdevice.h>
  34#include <linux/pci.h>
  35#include <linux/proc_fs.h>
  36#include <linux/skbuff.h>
  37#include <linux/slab.h>
  38#include <linux/tcp.h>
  39#include <linux/types.h>
  40#include <linux/version.h>
  41#include <linux/wireless.h>
  42#include <linux/etherdevice.h>
  43#include <asm/uaccess.h>
  44#include <linux/ctype.h>
  45
  46#include "ieee80211.h"
  47#ifdef ENABLE_DOT11D
  48#include "dot11d.h"
  49#endif
  50static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
  51                                        struct sk_buff *skb,
  52                                        struct ieee80211_rx_stats *rx_stats)
  53{
  54        struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *)skb->data;
  55        u16 fc = le16_to_cpu(hdr->frame_ctl);
  56
  57        skb->dev = ieee->dev;
  58#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
  59        skb_reset_mac_header(skb);
  60#else
  61        skb->mac.raw = skb->data;
  62#endif
  63
  64        skb_pull(skb, ieee80211_get_hdrlen(fc));
  65        skb->pkt_type = PACKET_OTHERHOST;
  66        skb->protocol = __constant_htons(ETH_P_80211_RAW);
  67        memset(skb->cb, 0, sizeof(skb->cb));
  68        netif_rx(skb);
  69}
  70
  71
  72/* Called only as a tasklet (software IRQ) */
  73static struct ieee80211_frag_entry *
  74ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
  75                          unsigned int frag, u8 tid,u8 *src, u8 *dst)
  76{
  77        struct ieee80211_frag_entry *entry;
  78        int i;
  79
  80        for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
  81                entry = &ieee->frag_cache[tid][i];
  82                if (entry->skb != NULL &&
  83                    time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
  84                        IEEE80211_DEBUG_FRAG(
  85                                "expiring fragment cache entry "
  86                                "seq=%u last_frag=%u\n",
  87                                entry->seq, entry->last_frag);
  88                        dev_kfree_skb_any(entry->skb);
  89                        entry->skb = NULL;
  90                }
  91
  92                if (entry->skb != NULL && entry->seq == seq &&
  93                    (entry->last_frag + 1 == frag || frag == -1) &&
  94                    memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
  95                    memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
  96                        return entry;
  97        }
  98
  99        return NULL;
 100}
 101
 102/* Called only as a tasklet (software IRQ) */
 103static struct sk_buff *
 104ieee80211_frag_cache_get(struct ieee80211_device *ieee,
 105                         struct ieee80211_hdr_4addr *hdr)
 106{
 107        struct sk_buff *skb = NULL;
 108        u16 fc = le16_to_cpu(hdr->frame_ctl);
 109        u16 sc = le16_to_cpu(hdr->seq_ctl);
 110        unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
 111        unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
 112        struct ieee80211_frag_entry *entry;
 113        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 114        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 115        u8 tid;
 116
 117        if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 118          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
 119          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 120          tid = UP2AC(tid);
 121          tid ++;
 122        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
 123          hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
 124          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 125          tid = UP2AC(tid);
 126          tid ++;
 127        } else {
 128          tid = 0;
 129        }
 130
 131        if (frag == 0) {
 132                /* Reserve enough space to fit maximum frame length */
 133                skb = dev_alloc_skb(ieee->dev->mtu +
 134                                    sizeof(struct ieee80211_hdr_4addr) +
 135                                    8 /* LLC */ +
 136                                    2 /* alignment */ +
 137                                    8 /* WEP */ +
 138                                    ETH_ALEN /* WDS */ +
 139                                    (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
 140                if (skb == NULL)
 141                        return NULL;
 142
 143                entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
 144                ieee->frag_next_idx[tid]++;
 145                if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
 146                        ieee->frag_next_idx[tid] = 0;
 147
 148                if (entry->skb != NULL)
 149                        dev_kfree_skb_any(entry->skb);
 150
 151                entry->first_frag_time = jiffies;
 152                entry->seq = seq;
 153                entry->last_frag = frag;
 154                entry->skb = skb;
 155                memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
 156                memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
 157        } else {
 158                /* received a fragment of a frame for which the head fragment
 159                 * should have already been received */
 160                entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
 161                                                  hdr->addr1);
 162                if (entry != NULL) {
 163                        entry->last_frag = frag;
 164                        skb = entry->skb;
 165                }
 166        }
 167
 168        return skb;
 169}
 170
 171
 172/* Called only as a tasklet (software IRQ) */
 173static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
 174                                           struct ieee80211_hdr_4addr *hdr)
 175{
 176        u16 fc = le16_to_cpu(hdr->frame_ctl);
 177        u16 sc = le16_to_cpu(hdr->seq_ctl);
 178        unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
 179        struct ieee80211_frag_entry *entry;
 180        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 181        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 182        u8 tid;
 183
 184        if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 185          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
 186          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 187          tid = UP2AC(tid);
 188          tid ++;
 189        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
 190          hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
 191          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 192          tid = UP2AC(tid);
 193          tid ++;
 194        } else {
 195          tid = 0;
 196        }
 197
 198        entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
 199                                          hdr->addr1);
 200
 201        if (entry == NULL) {
 202                IEEE80211_DEBUG_FRAG(
 203                        "could not invalidate fragment cache "
 204                        "entry (seq=%u)\n", seq);
 205                return -1;
 206        }
 207
 208        entry->skb = NULL;
 209        return 0;
 210}
 211
 212
 213
 214/* ieee80211_rx_frame_mgtmt
 215 *
 216 * Responsible for handling management control frames
 217 *
 218 * Called by ieee80211_rx */
 219static inline int
 220ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 221                        struct ieee80211_rx_stats *rx_stats, u16 type,
 222                        u16 stype)
 223{
 224        /* On the struct stats definition there is written that
 225         * this is not mandatory.... but seems that the probe
 226         * response parser uses it
 227         */
 228        struct ieee80211_hdr_3addr * hdr = (struct ieee80211_hdr_3addr *)skb->data;
 229
 230        rx_stats->len = skb->len;
 231        ieee80211_rx_mgt(ieee,(struct ieee80211_hdr_4addr *)skb->data,rx_stats);
 232        //if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN)))
 233        if ((memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN)))//use ADDR1 to perform address matching for Management frames
 234        {
 235                dev_kfree_skb_any(skb);
 236                return 0;
 237        }
 238
 239        ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
 240
 241        dev_kfree_skb_any(skb);
 242
 243        return 0;
 244
 245        #ifdef NOT_YET
 246        if (ieee->iw_mode == IW_MODE_MASTER) {
 247                printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
 248                       ieee->dev->name);
 249                return 0;
 250/*
 251  hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
 252  skb->data);*/
 253        }
 254
 255        if (ieee->hostapd && type == IEEE80211_TYPE_MGMT) {
 256                if (stype == WLAN_FC_STYPE_BEACON &&
 257                    ieee->iw_mode == IW_MODE_MASTER) {
 258                        struct sk_buff *skb2;
 259                        /* Process beacon frames also in kernel driver to
 260                         * update STA(AP) table statistics */
 261                        skb2 = skb_clone(skb, GFP_ATOMIC);
 262                        if (skb2)
 263                                hostap_rx(skb2->dev, skb2, rx_stats);
 264                }
 265
 266                /* send management frames to the user space daemon for
 267                 * processing */
 268                ieee->apdevstats.rx_packets++;
 269                ieee->apdevstats.rx_bytes += skb->len;
 270                prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
 271                return 0;
 272        }
 273
 274            if (ieee->iw_mode == IW_MODE_MASTER) {
 275                if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
 276                        printk(KERN_DEBUG "%s: unknown management frame "
 277                               "(type=0x%02x, stype=0x%02x) dropped\n",
 278                               skb->dev->name, type, stype);
 279                        return -1;
 280                }
 281
 282                hostap_rx(skb->dev, skb, rx_stats);
 283                return 0;
 284        }
 285
 286        printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
 287               "received in non-Host AP mode\n", skb->dev->name);
 288        return -1;
 289        #endif
 290}
 291
 292
 293
 294/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
 295/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
 296static unsigned char rfc1042_header[] =
 297{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 298/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
 299static unsigned char bridge_tunnel_header[] =
 300{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 301/* No encapsulation header if EtherType < 0x600 (=length) */
 302
 303/* Called by ieee80211_rx_frame_decrypt */
 304static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 305                                    struct sk_buff *skb, size_t hdrlen)
 306{
 307        struct net_device *dev = ieee->dev;
 308        u16 fc, ethertype;
 309        struct ieee80211_hdr_4addr *hdr;
 310        u8 *pos;
 311
 312        if (skb->len < 24)
 313                return 0;
 314
 315        hdr = (struct ieee80211_hdr_4addr *) skb->data;
 316        fc = le16_to_cpu(hdr->frame_ctl);
 317
 318        /* check that the frame is unicast frame to us */
 319        if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 320            IEEE80211_FCTL_TODS &&
 321            memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
 322            memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
 323                /* ToDS frame with own addr BSSID and DA */
 324        } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 325                   IEEE80211_FCTL_FROMDS &&
 326                   memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
 327                /* FromDS frame with own addr as DA */
 328        } else
 329                return 0;
 330
 331        if (skb->len < 24 + 8)
 332                return 0;
 333
 334        /* check for port access entity Ethernet type */
 335//      pos = skb->data + 24;
 336        pos = skb->data + hdrlen;
 337        ethertype = (pos[6] << 8) | pos[7];
 338        if (ethertype == ETH_P_PAE)
 339                return 1;
 340
 341        return 0;
 342}
 343
 344/* Called only as a tasklet (software IRQ), by ieee80211_rx */
 345static inline int
 346ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
 347                           struct ieee80211_crypt_data *crypt)
 348{
 349        struct ieee80211_hdr_4addr *hdr;
 350        int res, hdrlen;
 351
 352        if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 353                return 0;
 354#if 1
 355        if (ieee->hwsec_active)
 356        {
 357                cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
 358                tcb_desc->bHwSec = 1;
 359        }
 360#endif
 361        hdr = (struct ieee80211_hdr_4addr *) skb->data;
 362        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 363
 364#ifdef CONFIG_IEEE80211_CRYPT_TKIP
 365        if (ieee->tkip_countermeasures &&
 366            strcmp(crypt->ops->name, "TKIP") == 0) {
 367                if (net_ratelimit()) {
 368                        printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
 369                               "received packet from " MAC_FMT "\n",
 370                               ieee->dev->name, MAC_ARG(hdr->addr2));
 371                }
 372                return -1;
 373        }
 374#endif
 375
 376        atomic_inc(&crypt->refcnt);
 377        res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 378        atomic_dec(&crypt->refcnt);
 379        if (res < 0) {
 380                IEEE80211_DEBUG_DROP(
 381                        "decryption failed (SA=" MAC_FMT
 382                        ") res=%d\n", MAC_ARG(hdr->addr2), res);
 383                if (res == -2)
 384                        IEEE80211_DEBUG_DROP("Decryption failed ICV "
 385                                             "mismatch (key %d)\n",
 386                                             skb->data[hdrlen + 3] >> 6);
 387                ieee->ieee_stats.rx_discards_undecryptable++;
 388                return -1;
 389        }
 390
 391        return res;
 392}
 393
 394
 395/* Called only as a tasklet (software IRQ), by ieee80211_rx */
 396static inline int
 397ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
 398                             int keyidx, struct ieee80211_crypt_data *crypt)
 399{
 400        struct ieee80211_hdr_4addr *hdr;
 401        int res, hdrlen;
 402
 403        if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 404                return 0;
 405        if (ieee->hwsec_active)
 406        {
 407                cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
 408                tcb_desc->bHwSec = 1;
 409        }
 410
 411        hdr = (struct ieee80211_hdr_4addr *) skb->data;
 412        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 413
 414        atomic_inc(&crypt->refcnt);
 415        res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
 416        atomic_dec(&crypt->refcnt);
 417        if (res < 0) {
 418                printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
 419                       " (SA=" MAC_FMT " keyidx=%d)\n",
 420                       ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
 421                return -1;
 422        }
 423
 424        return 0;
 425}
 426
 427
 428/* this function is stolen from ipw2200 driver*/
 429#define IEEE_PACKET_RETRY_TIME (5*HZ)
 430static int is_duplicate_packet(struct ieee80211_device *ieee,
 431                                      struct ieee80211_hdr_4addr *header)
 432{
 433        u16 fc = le16_to_cpu(header->frame_ctl);
 434        u16 sc = le16_to_cpu(header->seq_ctl);
 435        u16 seq = WLAN_GET_SEQ_SEQ(sc);
 436        u16 frag = WLAN_GET_SEQ_FRAG(sc);
 437        u16 *last_seq, *last_frag;
 438        unsigned long *last_time;
 439        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 440        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 441        u8 tid;
 442
 443
 444        //TO2DS and QoS
 445        if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 446          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
 447          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 448          tid = UP2AC(tid);
 449          tid ++;
 450        } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
 451          hdr_3addrqos = (struct ieee80211_hdr_3addrqos*)header;
 452          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QCTL_TID;
 453          tid = UP2AC(tid);
 454          tid ++;
 455        } else { // no QoS
 456          tid = 0;
 457        }
 458
 459        switch (ieee->iw_mode) {
 460        case IW_MODE_ADHOC:
 461        {
 462                struct list_head *p;
 463                struct ieee_ibss_seq *entry = NULL;
 464                u8 *mac = header->addr2;
 465                int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
 466                //for (pos = (head)->next; pos != (head); pos = pos->next)
 467                //__list_for_each(p, &ieee->ibss_mac_hash[index]) {
 468                list_for_each(p, &ieee->ibss_mac_hash[index]) {
 469                        entry = list_entry(p, struct ieee_ibss_seq, list);
 470                        if (!memcmp(entry->mac, mac, ETH_ALEN))
 471                                break;
 472                }
 473        //      if (memcmp(entry->mac, mac, ETH_ALEN)){
 474                if (p == &ieee->ibss_mac_hash[index]) {
 475                        entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
 476                        if (!entry) {
 477                                printk(KERN_WARNING "Cannot malloc new mac entry\n");
 478                                return 0;
 479                        }
 480                        memcpy(entry->mac, mac, ETH_ALEN);
 481                        entry->seq_num[tid] = seq;
 482                        entry->frag_num[tid] = frag;
 483                        entry->packet_time[tid] = jiffies;
 484                        list_add(&entry->list, &ieee->ibss_mac_hash[index]);
 485                        return 0;
 486                }
 487                last_seq = &entry->seq_num[tid];
 488                last_frag = &entry->frag_num[tid];
 489                last_time = &entry->packet_time[tid];
 490                break;
 491        }
 492
 493        case IW_MODE_INFRA:
 494                last_seq = &ieee->last_rxseq_num[tid];
 495                last_frag = &ieee->last_rxfrag_num[tid];
 496                last_time = &ieee->last_packet_time[tid];
 497
 498                break;
 499        default:
 500                return 0;
 501        }
 502
 503//      if(tid != 0) {
 504//              printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
 505//      }
 506        if ((*last_seq == seq) &&
 507            time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
 508                if (*last_frag == frag){
 509                        //printk(KERN_WARNING "[1] go drop!\n");
 510                        goto drop;
 511
 512                }
 513                if (*last_frag + 1 != frag)
 514                        /* out-of-order fragment */
 515                        //printk(KERN_WARNING "[2] go drop!\n");
 516                        goto drop;
 517        } else
 518                *last_seq = seq;
 519
 520        *last_frag = frag;
 521        *last_time = jiffies;
 522        return 0;
 523
 524drop:
 525//      BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
 526//      printk("DUP\n");
 527
 528        return 1;
 529}
 530bool
 531AddReorderEntry(
 532        PRX_TS_RECORD                   pTS,
 533        PRX_REORDER_ENTRY               pReorderEntry
 534        )
 535{
 536        struct list_head *pList = &pTS->RxPendingPktList;
 537#if  1
 538        while(pList->next != &pTS->RxPendingPktList)
 539        {
 540                if( SN_LESS(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
 541                {
 542                        pList = pList->next;
 543                }
 544                else if( SN_EQUAL(pReorderEntry->SeqNum, ((PRX_REORDER_ENTRY)list_entry(pList->next,RX_REORDER_ENTRY,List))->SeqNum) )
 545                {
 546                        return false;
 547                }
 548                else
 549                {
 550                        break;
 551                }
 552        }
 553#endif
 554        pReorderEntry->List.next = pList->next;
 555        pReorderEntry->List.next->prev = &pReorderEntry->List;
 556        pReorderEntry->List.prev = pList;
 557        pList->next = &pReorderEntry->List;
 558
 559        return true;
 560}
 561
 562void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8  index)
 563{
 564        u8 i = 0 , j=0;
 565        u16 ethertype;
 566//      if(index > 1)
 567//              IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): hahahahhhh, We indicate packet from reorder list, index is %u\n",__FUNCTION__,index);
 568        for(j = 0; j<index; j++)
 569        {
 570//added by amy for reorder
 571                struct ieee80211_rxb* prxb = prxbIndicateArray[j];
 572                for(i = 0; i<prxb->nr_subframes; i++) {
 573                        struct sk_buff *sub_skb = prxb->subframes[i];
 574
 575                /* convert hdr + possible LLC headers into Ethernet header */
 576                        ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
 577                        if (sub_skb->len >= 8 &&
 578                                ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
 579                                  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
 580                                 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
 581                        /* remove RFC1042 or Bridge-Tunnel encapsulation and
 582                         * replace EtherType */
 583                                skb_pull(sub_skb, SNAP_SIZE);
 584                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
 585                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
 586                        } else {
 587                                u16 len;
 588                        /* Leave Ethernet header part of hdr and full payload */
 589                                len = htons(sub_skb->len);
 590                                memcpy(skb_push(sub_skb, 2), &len, 2);
 591                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->src, ETH_ALEN);
 592                                memcpy(skb_push(sub_skb, ETH_ALEN), prxb->dst, ETH_ALEN);
 593                        }
 594                        //stats->rx_packets++;
 595                        //stats->rx_bytes += sub_skb->len;
 596
 597                /* Indicat the packets to upper layer */
 598                        if (sub_skb) {
 599                                //printk("0skb_len(%d)\n", skb->len);
 600                                sub_skb->protocol = eth_type_trans(sub_skb, ieee->dev);
 601                                memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
 602                                sub_skb->dev = ieee->dev;
 603                                sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
 604                                //skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */
 605                                ieee->last_rx_ps_time = jiffies;
 606                                //printk("1skb_len(%d)\n", skb->len);
 607                                netif_rx(sub_skb);
 608                        }
 609                }
 610                kfree(prxb);
 611                prxb = NULL;
 612        }
 613}
 614
 615
 616void RxReorderIndicatePacket( struct ieee80211_device *ieee,
 617                struct ieee80211_rxb* prxb,
 618                PRX_TS_RECORD           pTS,
 619                u16                     SeqNum)
 620{
 621        PRT_HIGH_THROUGHPUT     pHTInfo = ieee->pHTInfo;
 622        PRX_REORDER_ENTRY       pReorderEntry = NULL;
 623        struct ieee80211_rxb* prxbIndicateArray[REORDER_WIN_SIZE];
 624        u8                      WinSize = pHTInfo->RxReorderWinSize;
 625        u16                     WinEnd = (pTS->RxIndicateSeq + WinSize -1)%4096;
 626        u8                      index = 0;
 627        bool                    bMatchWinStart = false, bPktInBuf = false;
 628        IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__FUNCTION__,SeqNum,pTS->RxIndicateSeq,WinSize);
 629#if 0
 630        if(!list_empty(&ieee->RxReorder_Unused_List))
 631                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): ieee->RxReorder_Unused_List is nut NULL\n");
 632#endif
 633        /* Rx Reorder initialize condition.*/
 634        if(pTS->RxIndicateSeq == 0xffff) {
 635                pTS->RxIndicateSeq = SeqNum;
 636        }
 637
 638        /* Drop out the packet which SeqNum is smaller than WinStart */
 639        if(SN_LESS(SeqNum, pTS->RxIndicateSeq)) {
 640                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packet Drop! IndicateSeq: %d, NewSeq: %d\n",
 641                                 pTS->RxIndicateSeq, SeqNum);
 642                pHTInfo->RxReorderDropCounter++;
 643                {
 644                        int i;
 645                        for(i =0; i < prxb->nr_subframes; i++) {
 646                                dev_kfree_skb(prxb->subframes[i]);
 647                        }
 648                        kfree(prxb);
 649                        prxb = NULL;
 650                }
 651                return;
 652        }
 653
 654        /*
 655         * Sliding window manipulation. Conditions includes:
 656         * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
 657         * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
 658         */
 659        if(SN_EQUAL(SeqNum, pTS->RxIndicateSeq)) {
 660                pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
 661                bMatchWinStart = true;
 662        } else if(SN_LESS(WinEnd, SeqNum)) {
 663                if(SeqNum >= (WinSize - 1)) {
 664                        pTS->RxIndicateSeq = SeqNum + 1 -WinSize;
 665                } else {
 666                        pTS->RxIndicateSeq = 4095 - (WinSize - (SeqNum +1)) + 1;
 667                }
 668                IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Window Shift! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
 669        }
 670
 671        /*
 672         * Indication process.
 673         * After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
 674         * with the SeqNum smaller than latest WinStart and buffer other packets.
 675         */
 676        /* For Rx Reorder condition:
 677         * 1. All packets with SeqNum smaller than WinStart => Indicate
 678         * 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
 679         */
 680        if(bMatchWinStart) {
 681                /* Current packet is going to be indicated.*/
 682                IEEE80211_DEBUG(IEEE80211_DL_REORDER, "Packets indication!! IndicateSeq: %d, NewSeq: %d\n",\
 683                                pTS->RxIndicateSeq, SeqNum);
 684                prxbIndicateArray[0] = prxb;
 685//              printk("========================>%s(): SeqNum is %d\n",__FUNCTION__,SeqNum);
 686                index = 1;
 687        } else {
 688                /* Current packet is going to be inserted into pending list.*/
 689                //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): We RX no ordered packed, insert to orderd list\n",__FUNCTION__);
 690                if(!list_empty(&ieee->RxReorder_Unused_List)) {
 691                        pReorderEntry = (PRX_REORDER_ENTRY)list_entry(ieee->RxReorder_Unused_List.next,RX_REORDER_ENTRY,List);
 692                        list_del_init(&pReorderEntry->List);
 693
 694                        /* Make a reorder entry and insert into a the packet list.*/
 695                        pReorderEntry->SeqNum = SeqNum;
 696                        pReorderEntry->prxb = prxb;
 697        //              IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pREorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum);
 698
 699#if 1
 700                        if(!AddReorderEntry(pTS, pReorderEntry)) {
 701                                IEEE80211_DEBUG(IEEE80211_DL_REORDER, "%s(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n",
 702                                        __FUNCTION__, pTS->RxIndicateSeq, SeqNum);
 703                                list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
 704                                {
 705                                        int i;
 706                                        for(i =0; i < prxb->nr_subframes; i++) {
 707                                                dev_kfree_skb(prxb->subframes[i]);
 708                                        }
 709                                        kfree(prxb);
 710                                        prxb = NULL;
 711                                }
 712                        } else {
 713                                IEEE80211_DEBUG(IEEE80211_DL_REORDER,
 714                                         "Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
 715                        }
 716#endif
 717                }
 718                else {
 719                        /*
 720                         * Packets are dropped if there is not enough reorder entries.
 721                         * This part shall be modified!! We can just indicate all the
 722                         * packets in buffer and get reorder entries.
 723                         */
 724                        IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): There is no reorder entry!! Packet is dropped!!\n");
 725                        {
 726                                int i;
 727                                for(i =0; i < prxb->nr_subframes; i++) {
 728                                        dev_kfree_skb(prxb->subframes[i]);
 729                                }
 730                                kfree(prxb);
 731                                prxb = NULL;
 732                        }
 733                }
 734        }
 735
 736        /* Check if there is any packet need indicate.*/
 737        while(!list_empty(&pTS->RxPendingPktList)) {
 738                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): start RREORDER indicate\n",__FUNCTION__);
 739#if 1
 740                pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
 741                if( SN_LESS(pReorderEntry->SeqNum, pTS->RxIndicateSeq) ||
 742                                SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
 743                {
 744                        /* This protect buffer from overflow. */
 745                        if(index >= REORDER_WIN_SIZE) {
 746                                IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Buffer overflow!! \n");
 747                                bPktInBuf = true;
 748                                break;
 749                        }
 750
 751                        list_del_init(&pReorderEntry->List);
 752
 753                        if(SN_EQUAL(pReorderEntry->SeqNum, pTS->RxIndicateSeq))
 754                                pTS->RxIndicateSeq = (pTS->RxIndicateSeq + 1) % 4096;
 755
 756                        IEEE80211_DEBUG(IEEE80211_DL_REORDER,"Packets indication!! IndicateSeq: %d, NewSeq: %d\n",pTS->RxIndicateSeq, SeqNum);
 757                        prxbIndicateArray[index] = pReorderEntry->prxb;
 758                //      printk("========================>%s(): pReorderEntry->SeqNum is %d\n",__FUNCTION__,pReorderEntry->SeqNum);
 759                        index++;
 760
 761                        list_add_tail(&pReorderEntry->List,&ieee->RxReorder_Unused_List);
 762                } else {
 763                        bPktInBuf = true;
 764                        break;
 765                }
 766#endif
 767        }
 768
 769        /* Handling pending timer. Set this timer to prevent from long time Rx buffering.*/
 770        if(index>0) {
 771                // Cancel previous pending timer.
 772                if (timer_pending(&pTS->RxPktPendingTimer))
 773                        del_timer_sync(&pTS->RxPktPendingTimer);
 774                pTS->RxTimeoutIndicateSeq = 0xffff;
 775
 776                // Indicate packets
 777                if(index>REORDER_WIN_SIZE){
 778                        IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
 779                        return;
 780                }
 781                ieee80211_indicate_packets(ieee, prxbIndicateArray, index);
 782                bPktInBuf = false;
 783        }
 784
 785#if 1
 786        if(bPktInBuf && pTS->RxTimeoutIndicateSeq==0xffff) {
 787                // Set new pending timer.
 788                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): SET rx timeout timer\n", __FUNCTION__);
 789                pTS->RxTimeoutIndicateSeq = pTS->RxIndicateSeq;
 790#if 0
 791                if(timer_pending(&pTS->RxPktPendingTimer))
 792                        del_timer_sync(&pTS->RxPktPendingTimer);
 793                pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime);
 794                add_timer(&pTS->RxPktPendingTimer);
 795#else
 796                mod_timer(&pTS->RxPktPendingTimer,  jiffies + MSECS(pHTInfo->RxReorderPendingTime));
 797#endif
 798        }
 799#endif
 800}
 801
 802u8 parse_subframe(struct sk_buff *skb,
 803                  struct ieee80211_rx_stats *rx_stats,
 804                  struct ieee80211_rxb *rxb,u8* src,u8* dst)
 805{
 806        struct ieee80211_hdr_3addr  *hdr = (struct ieee80211_hdr_3addr* )skb->data;
 807        u16             fc = le16_to_cpu(hdr->frame_ctl);
 808
 809        u16             LLCOffset= sizeof(struct ieee80211_hdr_3addr);
 810        u16             ChkLength;
 811        bool            bIsAggregateFrame = false;
 812        u16             nSubframe_Length;
 813        u8              nPadding_Length = 0;
 814        u16             SeqNum=0;
 815
 816        struct sk_buff *sub_skb;
 817        u8             *data_ptr;
 818        /* just for debug purpose */
 819        SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
 820
 821        if((IEEE80211_QOS_HAS_SEQ(fc))&&\
 822                        (((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
 823                bIsAggregateFrame = true;
 824        }
 825
 826        if(IEEE80211_QOS_HAS_SEQ(fc)) {
 827                LLCOffset += 2;
 828        }
 829
 830        if(rx_stats->bContainHTC) {
 831                LLCOffset += sHTCLng;
 832        }
 833        //printk("ChkLength = %d\n", LLCOffset);
 834        // Null packet, don't indicate it to upper layer
 835        ChkLength = LLCOffset;/* + (Frame_WEP(frame)!=0 ?Adapter->MgntInfo.SecurityInfo.EncryptionHeadOverhead:0);*/
 836
 837        if( skb->len <= ChkLength ) {
 838                return 0;
 839        }
 840
 841        skb_pull(skb, LLCOffset);
 842
 843        if(!bIsAggregateFrame) {
 844                rxb->nr_subframes = 1;
 845#ifdef JOHN_NOCPY
 846                rxb->subframes[0] = skb;
 847#else
 848                rxb->subframes[0] = skb_copy(skb, GFP_ATOMIC);
 849#endif
 850
 851                memcpy(rxb->src,src,ETH_ALEN);
 852                memcpy(rxb->dst,dst,ETH_ALEN);
 853                //IEEE80211_DEBUG_DATA(IEEE80211_DL_RX,skb->data,skb->len);
 854                return 1;
 855        } else {
 856                rxb->nr_subframes = 0;
 857                memcpy(rxb->src,src,ETH_ALEN);
 858                memcpy(rxb->dst,dst,ETH_ALEN);
 859                while(skb->len > ETHERNET_HEADER_SIZE) {
 860                        /* Offset 12 denote 2 mac address */
 861                        nSubframe_Length = *((u16*)(skb->data + 12));
 862                        //==m==>change the length order
 863                        nSubframe_Length = (nSubframe_Length>>8) + (nSubframe_Length<<8);
 864
 865                        if(skb->len<(ETHERNET_HEADER_SIZE + nSubframe_Length)) {
 866#if 0//cosa
 867                                RT_ASSERT(
 868                                                (nRemain_Length>=(ETHERNET_HEADER_SIZE + nSubframe_Length)),
 869                                                ("ParseSubframe(): A-MSDU subframe parse error!! Subframe Length: %d\n", nSubframe_Length) );
 870#endif
 871                                printk("%s: A-MSDU parse error!! pRfd->nTotalSubframe : %d\n",\
 872                                                __FUNCTION__,rxb->nr_subframes);
 873                                printk("%s: A-MSDU parse error!! Subframe Length: %d\n",__FUNCTION__, nSubframe_Length);
 874                                printk("nRemain_Length is %d and nSubframe_Length is : %d\n",skb->len,nSubframe_Length);
 875                                printk("The Packet SeqNum is %d\n",SeqNum);
 876                                return 0;
 877                        }
 878
 879                        /* move the data point to data content */
 880                        skb_pull(skb, ETHERNET_HEADER_SIZE);
 881
 882#ifdef JOHN_NOCPY
 883                        sub_skb = skb_clone(skb, GFP_ATOMIC);
 884                        sub_skb->len = nSubframe_Length;
 885                        sub_skb->tail = sub_skb->data + nSubframe_Length;
 886#else
 887                        /* Allocate new skb for releasing to upper layer */
 888                        sub_skb = dev_alloc_skb(nSubframe_Length + 12);
 889                        skb_reserve(sub_skb, 12);
 890                        data_ptr = (u8 *)skb_put(sub_skb, nSubframe_Length);
 891                        memcpy(data_ptr,skb->data,nSubframe_Length);
 892#endif
 893                        rxb->subframes[rxb->nr_subframes++] = sub_skb;
 894                        if(rxb->nr_subframes >= MAX_SUBFRAME_COUNT) {
 895                                IEEE80211_DEBUG_RX("ParseSubframe(): Too many Subframes! Packets dropped!\n");
 896                                break;
 897                        }
 898                        skb_pull(skb,nSubframe_Length);
 899
 900                        if(skb->len != 0) {
 901                                nPadding_Length = 4 - ((nSubframe_Length + ETHERNET_HEADER_SIZE) % 4);
 902                                if(nPadding_Length == 4) {
 903                                        nPadding_Length = 0;
 904                                }
 905
 906                                if(skb->len < nPadding_Length) {
 907                                        return 0;
 908                                }
 909
 910                                skb_pull(skb,nPadding_Length);
 911                        }
 912                }
 913#ifdef JOHN_NOCPY
 914                dev_kfree_skb(skb);
 915#endif
 916                //{just for debug added by david
 917                //printk("AMSDU::rxb->nr_subframes = %d\n",rxb->nr_subframes);
 918                //}
 919                return rxb->nr_subframes;
 920        }
 921}
 922
 923/* All received frames are sent to this function. @skb contains the frame in
 924 * IEEE 802.11 format, i.e., in the format it was sent over air.
 925 * This function is called only as a tasklet (software IRQ). */
 926int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 927                 struct ieee80211_rx_stats *rx_stats)
 928{
 929        struct net_device *dev = ieee->dev;
 930        struct ieee80211_hdr_4addr *hdr;
 931        //struct ieee80211_hdr_3addrqos *hdr;
 932
 933        size_t hdrlen;
 934        u16 fc, type, stype, sc;
 935        struct net_device_stats *stats;
 936        unsigned int frag;
 937        u8 *payload;
 938        u16 ethertype;
 939        //added by amy for reorder
 940        u8      TID = 0;
 941        u16     SeqNum = 0;
 942        PRX_TS_RECORD pTS = NULL;
 943        //bool bIsAggregateFrame = false;
 944        //added by amy for reorder
 945#ifdef NOT_YET
 946        struct net_device *wds = NULL;
 947        struct sk_buff *skb2 = NULL;
 948        struct net_device *wds = NULL;
 949        int frame_authorized = 0;
 950        int from_assoc_ap = 0;
 951        void *sta = NULL;
 952#endif
 953//      u16 qos_ctl = 0;
 954        u8 dst[ETH_ALEN];
 955        u8 src[ETH_ALEN];
 956        u8 bssid[ETH_ALEN];
 957        struct ieee80211_crypt_data *crypt = NULL;
 958        int keyidx = 0;
 959
 960        int i;
 961        struct ieee80211_rxb* rxb = NULL;
 962        // cheat the the hdr type
 963        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 964        stats = &ieee->stats;
 965
 966        if (skb->len < 10) {
 967                printk(KERN_INFO "%s: SKB length < 10\n",
 968                       dev->name);
 969                goto rx_dropped;
 970        }
 971
 972        fc = le16_to_cpu(hdr->frame_ctl);
 973        type = WLAN_FC_GET_TYPE(fc);
 974        stype = WLAN_FC_GET_STYPE(fc);
 975        sc = le16_to_cpu(hdr->seq_ctl);
 976
 977        frag = WLAN_GET_SEQ_FRAG(sc);
 978        hdrlen = ieee80211_get_hdrlen(fc);
 979
 980        if(HTCCheck(ieee, skb->data))
 981        {
 982                if(net_ratelimit())
 983                printk("find HTCControl\n");
 984                hdrlen += 4;
 985                rx_stats->bContainHTC = 1;
 986        }
 987
 988        //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
 989#ifdef NOT_YET
 990#if WIRELESS_EXT > 15
 991        /* Put this code here so that we avoid duplicating it in all
 992         * Rx paths. - Jean II */
 993#ifdef IW_WIRELESS_SPY          /* defined in iw_handler.h */
 994        /* If spy monitoring on */
 995        if (iface->spy_data.spy_number > 0) {
 996                struct iw_quality wstats;
 997                wstats.level = rx_stats->rssi;
 998                wstats.noise = rx_stats->noise;
 999                wstats.updated = 6;     /* No qual value */
1000                /* Update spy records */
1001                wireless_spy_update(dev, hdr->addr2, &wstats);
1002        }
1003#endif /* IW_WIRELESS_SPY */
1004#endif /* WIRELESS_EXT > 15 */
1005        hostap_update_rx_stats(local->ap, hdr, rx_stats);
1006#endif
1007
1008#if WIRELESS_EXT > 15
1009        if (ieee->iw_mode == IW_MODE_MONITOR) {
1010                ieee80211_monitor_rx(ieee, skb, rx_stats);
1011                stats->rx_packets++;
1012                stats->rx_bytes += skb->len;
1013                return 1;
1014        }
1015#endif
1016        if (ieee->host_decrypt) {
1017                int idx = 0;
1018                if (skb->len >= hdrlen + 3)
1019                        idx = skb->data[hdrlen + 3] >> 6;
1020                crypt = ieee->crypt[idx];
1021#ifdef NOT_YET
1022                sta = NULL;
1023
1024                /* Use station specific key to override default keys if the
1025                 * receiver address is a unicast address ("individual RA"). If
1026                 * bcrx_sta_key parameter is set, station specific key is used
1027                 * even with broad/multicast targets (this is against IEEE
1028                 * 802.11, but makes it easier to use different keys with
1029                 * stations that do not support WEP key mapping). */
1030
1031                if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
1032                        (void) hostap_handle_sta_crypto(local, hdr, &crypt,
1033                                                        &sta);
1034#endif
1035
1036                /* allow NULL decrypt to indicate an station specific override
1037                 * for default encryption */
1038                if (crypt && (crypt->ops == NULL ||
1039                              crypt->ops->decrypt_mpdu == NULL))
1040                        crypt = NULL;
1041
1042                if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
1043                        /* This seems to be triggered by some (multicast?)
1044                         * frames from other than current BSS, so just drop the
1045                         * frames silently instead of filling system log with
1046                         * these reports. */
1047                        IEEE80211_DEBUG_DROP("Decryption failed (not set)"
1048                                             " (SA=" MAC_FMT ")\n",
1049                                             MAC_ARG(hdr->addr2));
1050                        ieee->ieee_stats.rx_discards_undecryptable++;
1051                        goto rx_dropped;
1052                }
1053        }
1054
1055        if (skb->len < IEEE80211_DATA_HDR3_LEN)
1056                goto rx_dropped;
1057
1058        // if QoS enabled, should check the sequence for each of the AC
1059        if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){
1060                if (is_duplicate_packet(ieee, hdr))
1061                goto rx_dropped;
1062
1063        }
1064        else
1065        {
1066                PRX_TS_RECORD pRxTS = NULL;
1067        #if 0
1068                struct ieee80211_hdr_3addr *hdr;
1069                u16 fc;
1070                hdr = (struct ieee80211_hdr_3addr *)skb->data;
1071                fc = le16_to_cpu(hdr->frame_ctl);
1072                u8 tmp = (fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS);
1073
1074                u8 tid = (*((u8*)skb->data + (((fc& IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS))?30:24)))&0xf;
1075                printk("====================>fc:%x, tid:%d, tmp:%d\n", fc, tid, tmp);
1076                //u8 tid =  (u8)((frameqos*)(buf + ((fc & IEEE80211_FCTL_TODS)&&(fc & IEEE80211_FCTL_FROMDS))? 30 : 24))->field.tid;
1077        #endif
1078                        //IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): QOS ENABLE AND RECEIVE QOS DATA , we will get Ts, tid:%d\n",__FUNCTION__, tid);
1079#if 1
1080                if(GetTs(
1081                                ieee,
1082                                (PTS_COMMON_INFO*) &pRxTS,
1083                                hdr->addr2,
1084                                (u8)Frame_QoSTID((u8*)(skb->data)),
1085                                RX_DIR,
1086                                true))
1087                {
1088
1089                //      IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): pRxTS->RxLastFragNum is %d,frag is %d,pRxTS->RxLastSeqNum is %d,seq is %d\n",__FUNCTION__,pRxTS->RxLastFragNum,frag,pRxTS->RxLastSeqNum,WLAN_GET_SEQ_SEQ(sc));
1090                        if(     (fc & (1<<11))  &&
1091                                        (frag == pRxTS->RxLastFragNum) &&
1092                                        (WLAN_GET_SEQ_SEQ(sc) == pRxTS->RxLastSeqNum)   )
1093                        {
1094                                goto rx_dropped;
1095                        }
1096                        else
1097                        {
1098                                pRxTS->RxLastFragNum = frag;
1099                                pRxTS->RxLastSeqNum = WLAN_GET_SEQ_SEQ(sc);
1100                        }
1101                }
1102                else
1103                {
1104                        IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s(): No TS!! Skip the check!!\n",__FUNCTION__);
1105                        goto rx_dropped;
1106                }
1107        }
1108#endif
1109        if (type == IEEE80211_FTYPE_MGMT) {
1110
1111        #if 0
1112                if ( stype == IEEE80211_STYPE_AUTH &&
1113                    fc & IEEE80211_FCTL_WEP && ieee->host_decrypt &&
1114                    (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
1115                {
1116                        printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
1117                               "from " MAC_FMT "\n", dev->name,
1118                               MAC_ARG(hdr->addr2));
1119                        /* TODO: could inform hostapd about this so that it
1120                         * could send auth failure report */
1121                        goto rx_dropped;
1122                }
1123        #endif
1124
1125        //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1126                if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
1127                        goto rx_dropped;
1128                else
1129                        goto rx_exit;
1130        }
1131
1132        /* Data frame - extract src/dst addresses */
1133        switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
1134        case IEEE80211_FCTL_FROMDS:
1135                memcpy(dst, hdr->addr1, ETH_ALEN);
1136                memcpy(src, hdr->addr3, ETH_ALEN);
1137                memcpy(bssid, hdr->addr2, ETH_ALEN);
1138                break;
1139        case IEEE80211_FCTL_TODS:
1140                memcpy(dst, hdr->addr3, ETH_ALEN);
1141                memcpy(src, hdr->addr2, ETH_ALEN);
1142                memcpy(bssid, hdr->addr1, ETH_ALEN);
1143                break;
1144        case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
1145                if (skb->len < IEEE80211_DATA_HDR4_LEN)
1146                        goto rx_dropped;
1147                memcpy(dst, hdr->addr3, ETH_ALEN);
1148                memcpy(src, hdr->addr4, ETH_ALEN);
1149                memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
1150                break;
1151        case 0:
1152                memcpy(dst, hdr->addr1, ETH_ALEN);
1153                memcpy(src, hdr->addr2, ETH_ALEN);
1154                memcpy(bssid, hdr->addr3, ETH_ALEN);
1155                break;
1156        }
1157
1158#ifdef NOT_YET
1159        if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
1160                goto rx_dropped;
1161        if (wds) {
1162                skb->dev = dev = wds;
1163                stats = hostap_get_stats(dev);
1164        }
1165
1166        if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
1167            (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS &&
1168            ieee->stadev &&
1169            memcmp(hdr->addr2, ieee->assoc_ap_addr, ETH_ALEN) == 0) {
1170                /* Frame from BSSID of the AP for which we are a client */
1171                skb->dev = dev = ieee->stadev;
1172                stats = hostap_get_stats(dev);
1173                from_assoc_ap = 1;
1174        }
1175#endif
1176
1177        dev->last_rx = jiffies;
1178
1179#ifdef NOT_YET
1180        if ((ieee->iw_mode == IW_MODE_MASTER ||
1181             ieee->iw_mode == IW_MODE_REPEAT) &&
1182            !from_assoc_ap) {
1183                switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
1184                                             wds != NULL)) {
1185                case AP_RX_CONTINUE_NOT_AUTHORIZED:
1186                        frame_authorized = 0;
1187                        break;
1188                case AP_RX_CONTINUE:
1189                        frame_authorized = 1;
1190                        break;
1191                case AP_RX_DROP:
1192                        goto rx_dropped;
1193                case AP_RX_EXIT:
1194                        goto rx_exit;
1195                }
1196        }
1197#endif
1198        //IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1199        /* Nullfunc frames may have PS-bit set, so they must be passed to
1200         * hostap_handle_sta_rx() before being dropped here. */
1201        if (stype != IEEE80211_STYPE_DATA &&
1202            stype != IEEE80211_STYPE_DATA_CFACK &&
1203            stype != IEEE80211_STYPE_DATA_CFPOLL &&
1204            stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
1205            stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
1206            ) {
1207                if (stype != IEEE80211_STYPE_NULLFUNC)
1208                        IEEE80211_DEBUG_DROP(
1209                                "RX: dropped data frame "
1210                                "with no data (type=0x%02x, "
1211                                "subtype=0x%02x, len=%d)\n",
1212                                type, stype, skb->len);
1213                goto rx_dropped;
1214        }
1215        if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
1216                goto rx_dropped;
1217
1218        /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
1219
1220        if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1221            (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
1222        {
1223                printk("decrypt frame error\n");
1224                goto rx_dropped;
1225        }
1226
1227
1228        hdr = (struct ieee80211_hdr_4addr *) skb->data;
1229
1230        /* skb: hdr + (possibly fragmented) plaintext payload */
1231        // PR: FIXME: hostap has additional conditions in the "if" below:
1232        // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1233        if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
1234                int flen;
1235                struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
1236                IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
1237
1238                if (!frag_skb) {
1239                        IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
1240                                        "Rx cannot get skb from fragment "
1241                                        "cache (morefrag=%d seq=%u frag=%u)\n",
1242                                        (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
1243                                        WLAN_GET_SEQ_SEQ(sc), frag);
1244                        goto rx_dropped;
1245                }
1246                flen = skb->len;
1247                if (frag != 0)
1248                        flen -= hdrlen;
1249
1250                if (frag_skb->tail + flen > frag_skb->end) {
1251                        printk(KERN_WARNING "%s: host decrypted and "
1252                               "reassembled frame did not fit skb\n",
1253                               dev->name);
1254                        ieee80211_frag_cache_invalidate(ieee, hdr);
1255                        goto rx_dropped;
1256                }
1257
1258                if (frag == 0) {
1259                        /* copy first fragment (including full headers) into
1260                         * beginning of the fragment cache skb */
1261                        memcpy(skb_put(frag_skb, flen), skb->data, flen);
1262                } else {
1263                        /* append frame payload to the end of the fragment
1264                         * cache skb */
1265                        memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
1266                               flen);
1267                }
1268                dev_kfree_skb_any(skb);
1269                skb = NULL;
1270
1271                if (fc & IEEE80211_FCTL_MOREFRAGS) {
1272                        /* more fragments expected - leave the skb in fragment
1273                         * cache for now; it will be delivered to upper layers
1274                         * after all fragments have been received */
1275                        goto rx_exit;
1276                }
1277
1278                /* this was the last fragment and the frame will be
1279                 * delivered, so remove skb from fragment cache */
1280                skb = frag_skb;
1281                hdr = (struct ieee80211_hdr_4addr *) skb->data;
1282                ieee80211_frag_cache_invalidate(ieee, hdr);
1283        }
1284
1285        /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
1286         * encrypted/authenticated */
1287        if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
1288            ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
1289        {
1290                printk("==>decrypt msdu error\n");
1291                goto rx_dropped;
1292        }
1293
1294        //added by amy for AP roaming
1295        ieee->LinkDetectInfo.NumRecvDataInPeriod++;
1296        ieee->LinkDetectInfo.NumRxOkInPeriod++;
1297
1298        hdr = (struct ieee80211_hdr_4addr *) skb->data;
1299        if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
1300                if (/*ieee->ieee802_1x &&*/
1301                    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1302
1303#ifdef CONFIG_IEEE80211_DEBUG
1304                        /* pass unencrypted EAPOL frames even if encryption is
1305                         * configured */
1306                        struct eapol *eap = (struct eapol *)(skb->data +
1307                                24);
1308                        IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1309                                                eap_get_type(eap->type));
1310#endif
1311                } else {
1312                        IEEE80211_DEBUG_DROP(
1313                                "encryption configured, but RX "
1314                                "frame not encrypted (SA=" MAC_FMT ")\n",
1315                                MAC_ARG(hdr->addr2));
1316                        goto rx_dropped;
1317                }
1318        }
1319
1320#ifdef CONFIG_IEEE80211_DEBUG
1321        if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
1322            ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1323                        struct eapol *eap = (struct eapol *)(skb->data +
1324                                24);
1325                        IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
1326                                                eap_get_type(eap->type));
1327        }
1328#endif
1329
1330        if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
1331            !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1332                IEEE80211_DEBUG_DROP(
1333                        "dropped unencrypted RX data "
1334                        "frame from " MAC_FMT
1335                        " (drop_unencrypted=1)\n",
1336                        MAC_ARG(hdr->addr2));
1337                goto rx_dropped;
1338        }
1339/*
1340        if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
1341                printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
1342        }
1343*/
1344//added by amy for reorder
1345#if 1
1346        if(ieee->current_network.qos_data.active && IsQoSDataFrame(skb->data)
1347                && !is_multicast_ether_addr(hdr->addr1) && !is_broadcast_ether_addr(hdr->addr1))
1348        {
1349                TID = Frame_QoSTID(skb->data);
1350                SeqNum = WLAN_GET_SEQ_SEQ(sc);
1351                GetTs(ieee,(PTS_COMMON_INFO*) &pTS,hdr->addr2,TID,RX_DIR,true);
1352                if(TID !=0 && TID !=3)
1353                {
1354                        ieee->bis_any_nonbepkts = true;
1355                }
1356        }
1357#endif
1358//added by amy for reorder
1359        /* skb: hdr + (possible reassembled) full plaintext payload */
1360        payload = skb->data + hdrlen;
1361        //ethertype = (payload[6] << 8) | payload[7];
1362        rxb = (struct ieee80211_rxb*)kmalloc(sizeof(struct ieee80211_rxb),GFP_ATOMIC);
1363        if(rxb == NULL)
1364        {
1365                IEEE80211_DEBUG(IEEE80211_DL_ERR,"%s(): kmalloc rxb error\n",__FUNCTION__);
1366                goto rx_dropped;
1367        }
1368        /* to parse amsdu packets */
1369        /* qos data packets & reserved bit is 1 */
1370        if(parse_subframe(skb,rx_stats,rxb,src,dst) == 0) {
1371                /* only to free rxb, and not submit the packets to upper layer */
1372                for(i =0; i < rxb->nr_subframes; i++) {
1373                        dev_kfree_skb(rxb->subframes[i]);
1374                }
1375                kfree(rxb);
1376                rxb = NULL;
1377                goto rx_dropped;
1378        }
1379
1380        ieee->last_rx_ps_time = jiffies;
1381//added by amy for reorder
1382        if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
1383//added by amy for reorder
1384                for(i = 0; i<rxb->nr_subframes; i++) {
1385                        struct sk_buff *sub_skb = rxb->subframes[i];
1386
1387                        if (sub_skb) {
1388                                /* convert hdr + possible LLC headers into Ethernet header */
1389                                ethertype = (sub_skb->data[6] << 8) | sub_skb->data[7];
1390                                if (sub_skb->len >= 8 &&
1391                                                ((memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) == 0 &&
1392                                                  ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1393                                                 memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE) == 0)) {
1394                                        /* remove RFC1042 or Bridge-Tunnel encapsulation and
1395                                         * replace EtherType */
1396                                        skb_pull(sub_skb, SNAP_SIZE);
1397                                        memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1398                                        memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1399                                } else {
1400                                        u16 len;
1401                                        /* Leave Ethernet header part of hdr and full payload */
1402                                        len = htons(sub_skb->len);
1403                                        memcpy(skb_push(sub_skb, 2), &len, 2);
1404                                        memcpy(skb_push(sub_skb, ETH_ALEN), src, ETH_ALEN);
1405                                        memcpy(skb_push(sub_skb, ETH_ALEN), dst, ETH_ALEN);
1406                                }
1407
1408                                stats->rx_packets++;
1409                                stats->rx_bytes += sub_skb->len;
1410                                if(is_multicast_ether_addr(dst)) {
1411                                        stats->multicast++;
1412                                }
1413
1414                                /* Indicat the packets to upper layer */
1415                                //printk("0skb_len(%d)\n", skb->len);
1416                                sub_skb->protocol = eth_type_trans(sub_skb, dev);
1417                                memset(sub_skb->cb, 0, sizeof(sub_skb->cb));
1418                                sub_skb->dev = dev;
1419                                sub_skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
1420                                //skb->ip_summed = CHECKSUM_UNNECESSARY; /* 802.11 crc not sufficient */
1421                                //printk("1skb_len(%d)\n", skb->len);
1422                                netif_rx(sub_skb);
1423                        }
1424                }
1425                kfree(rxb);
1426                rxb = NULL;
1427
1428        }
1429        else
1430        {
1431                IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): REORDER ENABLE AND PTS not NULL, and we will enter RxReorderIndicatePacket()\n",__FUNCTION__);
1432                RxReorderIndicatePacket(ieee, rxb, pTS, SeqNum);
1433        }
1434#ifndef JOHN_NOCPY
1435        dev_kfree_skb(skb);
1436#endif
1437
1438 rx_exit:
1439#ifdef NOT_YET
1440        if (sta)
1441                hostap_handle_sta_release(sta);
1442#endif
1443        return 1;
1444
1445 rx_dropped:
1446        if (rxb != NULL)
1447        {
1448                kfree(rxb);
1449                rxb = NULL;
1450        }
1451        stats->rx_dropped++;
1452
1453        /* Returning 0 indicates to caller that we have not handled the SKB--
1454         * so it is still allocated and can be used again by underlying
1455         * hardware as a DMA target */
1456        return 0;
1457}
1458
1459#define MGMT_FRAME_FIXED_PART_LENGTH            0x24
1460
1461static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
1462
1463/*
1464* Make ther structure we read from the beacon packet has
1465* the right values
1466*/
1467static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
1468                                     *info_element, int sub_type)
1469{
1470
1471        if (info_element->qui_subtype != sub_type)
1472                return -1;
1473        if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
1474                return -1;
1475        if (info_element->qui_type != QOS_OUI_TYPE)
1476                return -1;
1477        if (info_element->version != QOS_VERSION_1)
1478                return -1;
1479
1480        return 0;
1481}
1482
1483
1484/*
1485 * Parse a QoS parameter element
1486 */
1487static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
1488                                            *element_param, struct ieee80211_info_element
1489                                            *info_element)
1490{
1491        int ret = 0;
1492        u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
1493
1494        if ((info_element == NULL) || (element_param == NULL))
1495                return -1;
1496
1497        if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
1498                memcpy(element_param->info_element.qui, info_element->data,
1499                       info_element->len);
1500                element_param->info_element.elementID = info_element->id;
1501                element_param->info_element.length = info_element->len;
1502        } else
1503                ret = -1;
1504        if (ret == 0)
1505                ret = ieee80211_verify_qos_info(&element_param->info_element,
1506                                                QOS_OUI_PARAM_SUB_TYPE);
1507        return ret;
1508}
1509
1510/*
1511 * Parse a QoS information element
1512 */
1513static int ieee80211_read_qos_info_element(struct
1514                                           ieee80211_qos_information_element
1515                                           *element_info, struct ieee80211_info_element
1516                                           *info_element)
1517{
1518        int ret = 0;
1519        u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
1520
1521        if (element_info == NULL)
1522                return -1;
1523        if (info_element == NULL)
1524                return -1;
1525
1526        if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
1527                memcpy(element_info->qui, info_element->data,
1528                       info_element->len);
1529                element_info->elementID = info_element->id;
1530                element_info->length = info_element->len;
1531        } else
1532                ret = -1;
1533
1534        if (ret == 0)
1535                ret = ieee80211_verify_qos_info(element_info,
1536                                                QOS_OUI_INFO_SUB_TYPE);
1537        return ret;
1538}
1539
1540
1541/*
1542 * Write QoS parameters from the ac parameters.
1543 */
1544static int ieee80211_qos_convert_ac_to_parameters(struct
1545                                                  ieee80211_qos_parameter_info
1546                                                  *param_elm, struct
1547                                                  ieee80211_qos_parameters
1548                                                  *qos_param)
1549{
1550        int rc = 0;
1551        int i;
1552        struct ieee80211_qos_ac_parameter *ac_params;
1553        u8 aci;
1554        //u8 cw_min;
1555        //u8 cw_max;
1556
1557        for (i = 0; i < QOS_QUEUE_NUM; i++) {
1558                ac_params = &(param_elm->ac_params_record[i]);
1559
1560                aci = (ac_params->aci_aifsn & 0x60) >> 5;
1561
1562                if(aci >= QOS_QUEUE_NUM)
1563                        continue;
1564                qos_param->aifs[aci] = (ac_params->aci_aifsn) & 0x0f;
1565
1566                /* WMM spec P.11: The minimum value for AIFSN shall be 2 */
1567                qos_param->aifs[aci] = (qos_param->aifs[aci] < 2) ? 2:qos_param->aifs[aci];
1568
1569                qos_param->cw_min[aci] = ac_params->ecw_min_max & 0x0F;
1570
1571                qos_param->cw_max[aci] = (ac_params->ecw_min_max & 0xF0) >> 4;
1572
1573                qos_param->flag[aci] =
1574                    (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
1575                qos_param->tx_op_limit[aci] = le16_to_cpu(ac_params->tx_op_limit);
1576        }
1577        return rc;
1578}
1579
1580/*
1581 * we have a generic data element which it may contain QoS information or
1582 * parameters element. check the information element length to decide
1583 * which type to read
1584 */
1585static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
1586                                             *info_element,
1587                                             struct ieee80211_network *network)
1588{
1589        int rc = 0;
1590        struct ieee80211_qos_parameters *qos_param = NULL;
1591        struct ieee80211_qos_information_element qos_info_element;
1592
1593        rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
1594
1595        if (rc == 0) {
1596                network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
1597                network->flags |= NETWORK_HAS_QOS_INFORMATION;
1598        } else {
1599                struct ieee80211_qos_parameter_info param_element;
1600
1601                rc = ieee80211_read_qos_param_element(&param_element,
1602                                                      info_element);
1603                if (rc == 0) {
1604                        qos_param = &(network->qos_data.parameters);
1605                        ieee80211_qos_convert_ac_to_parameters(&param_element,
1606                                                               qos_param);
1607                        network->flags |= NETWORK_HAS_QOS_PARAMETERS;
1608                        network->qos_data.param_count =
1609                            param_element.info_element.ac_info & 0x0F;
1610                }
1611        }
1612
1613        if (rc == 0) {
1614                IEEE80211_DEBUG_QOS("QoS is supported\n");
1615                network->qos_data.supported = 1;
1616        }
1617        return rc;
1618}
1619
1620#ifdef CONFIG_IEEE80211_DEBUG
1621#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
1622
1623static const char *get_info_element_string(u16 id)
1624{
1625        switch (id) {
1626                MFIE_STRING(SSID);
1627                MFIE_STRING(RATES);
1628                MFIE_STRING(FH_SET);
1629                MFIE_STRING(DS_SET);
1630                MFIE_STRING(CF_SET);
1631                MFIE_STRING(TIM);
1632                MFIE_STRING(IBSS_SET);
1633                MFIE_STRING(COUNTRY);
1634                MFIE_STRING(HOP_PARAMS);
1635                MFIE_STRING(HOP_TABLE);
1636                MFIE_STRING(REQUEST);
1637                MFIE_STRING(CHALLENGE);
1638                MFIE_STRING(POWER_CONSTRAINT);
1639                MFIE_STRING(POWER_CAPABILITY);
1640                MFIE_STRING(TPC_REQUEST);
1641                MFIE_STRING(TPC_REPORT);
1642                MFIE_STRING(SUPP_CHANNELS);
1643                MFIE_STRING(CSA);
1644                MFIE_STRING(MEASURE_REQUEST);
1645                MFIE_STRING(MEASURE_REPORT);
1646                MFIE_STRING(QUIET);
1647                MFIE_STRING(IBSS_DFS);
1648               // MFIE_STRING(ERP_INFO);
1649                MFIE_STRING(RSN);
1650                MFIE_STRING(RATES_EX);
1651                MFIE_STRING(GENERIC);
1652                MFIE_STRING(QOS_PARAMETER);
1653        default:
1654                return "UNKNOWN";
1655        }
1656}
1657#endif
1658
1659#ifdef ENABLE_DOT11D
1660static inline void ieee80211_extract_country_ie(
1661        struct ieee80211_device *ieee,
1662        struct ieee80211_info_element *info_element,
1663        struct ieee80211_network *network,
1664        u8 * addr2
1665)
1666{
1667        if(IS_DOT11D_ENABLE(ieee))
1668        {
1669                if(info_element->len!= 0)
1670                {
1671                        memcpy(network->CountryIeBuf, info_element->data, info_element->len);
1672                        network->CountryIeLen = info_element->len;
1673
1674                        if(!IS_COUNTRY_IE_VALID(ieee))
1675                        {
1676                                Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
1677                        }
1678                }
1679
1680                //
1681                // 070305, rcnjko: I update country IE watch dog here because
1682                // some AP (e.g. Cisco 1242) don't include country IE in their
1683                // probe response frame.
1684                //
1685                if(IS_EQUAL_CIE_SRC(ieee, addr2) )
1686                {
1687                        UPDATE_CIE_WATCHDOG(ieee);
1688                }
1689        }
1690
1691}
1692#endif
1693
1694int ieee80211_parse_info_param(struct ieee80211_device *ieee,
1695                struct ieee80211_info_element *info_element,
1696                u16 length,
1697                struct ieee80211_network *network,
1698                struct ieee80211_rx_stats *stats)
1699{
1700        u8 i;
1701        short offset;
1702        u16     tmp_htcap_len=0;
1703        u16     tmp_htinfo_len=0;
1704        u16 ht_realtek_agg_len=0;
1705        u8  ht_realtek_agg_buf[MAX_IE_LEN];
1706//      u16 broadcom_len = 0;
1707#ifdef CONFIG_IEEE80211_DEBUG
1708        char rates_str[64];
1709        char *p;
1710#endif
1711
1712        while (length >= sizeof(*info_element)) {
1713                if (sizeof(*info_element) + info_element->len > length) {
1714                        IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
1715                                             "info_element->len + 2 > left : "
1716                                             "info_element->len+2=%zd left=%d, id=%d.\n",
1717                                             info_element->len +
1718                                             sizeof(*info_element),
1719                                             length, info_element->id);
1720                        /* We stop processing but don't return an error here
1721                         * because some misbehaviour APs break this rule. ie.
1722                         * Orinoco AP1000. */
1723                        break;
1724                }
1725
1726                switch (info_element->id) {
1727                case MFIE_TYPE_SSID:
1728                        if (ieee80211_is_empty_essid(info_element->data,
1729                                                     info_element->len)) {
1730                                network->flags |= NETWORK_EMPTY_ESSID;
1731                                break;
1732                        }
1733
1734                        network->ssid_len = min(info_element->len,
1735                                                (u8) IW_ESSID_MAX_SIZE);
1736                        memcpy(network->ssid, info_element->data, network->ssid_len);
1737                        if (network->ssid_len < IW_ESSID_MAX_SIZE)
1738                                memset(network->ssid + network->ssid_len, 0,
1739                                       IW_ESSID_MAX_SIZE - network->ssid_len);
1740
1741                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
1742                                             network->ssid, network->ssid_len);
1743                        break;
1744
1745                case MFIE_TYPE_RATES:
1746#ifdef CONFIG_IEEE80211_DEBUG
1747                        p = rates_str;
1748#endif
1749                        network->rates_len = min(info_element->len,
1750                                                 MAX_RATES_LENGTH);
1751                        for (i = 0; i < network->rates_len; i++) {
1752                                network->rates[i] = info_element->data[i];
1753#ifdef CONFIG_IEEE80211_DEBUG
1754                                p += snprintf(p, sizeof(rates_str) -
1755                                              (p - rates_str), "%02X ",
1756                                              network->rates[i]);
1757#endif
1758                                if (ieee80211_is_ofdm_rate
1759                                    (info_element->data[i])) {
1760                                        network->flags |= NETWORK_HAS_OFDM;
1761                                        if (info_element->data[i] &
1762                                            IEEE80211_BASIC_RATE_MASK)
1763                                                network->flags &=
1764                                                    ~NETWORK_HAS_CCK;
1765                                }
1766                        }
1767
1768                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
1769                                             rates_str, network->rates_len);
1770                        break;
1771
1772                case MFIE_TYPE_RATES_EX:
1773#ifdef CONFIG_IEEE80211_DEBUG
1774                        p = rates_str;
1775#endif
1776                        network->rates_ex_len = min(info_element->len,
1777                                                    MAX_RATES_EX_LENGTH);
1778                        for (i = 0; i < network->rates_ex_len; i++) {
1779                                network->rates_ex[i] = info_element->data[i];
1780#ifdef CONFIG_IEEE80211_DEBUG
1781                                p += snprintf(p, sizeof(rates_str) -
1782                                              (p - rates_str), "%02X ",
1783                                              network->rates[i]);
1784#endif
1785                                if (ieee80211_is_ofdm_rate
1786                                    (info_element->data[i])) {
1787                                        network->flags |= NETWORK_HAS_OFDM;
1788                                        if (info_element->data[i] &
1789                                            IEEE80211_BASIC_RATE_MASK)
1790                                                network->flags &=
1791                                                    ~NETWORK_HAS_CCK;
1792                                }
1793                        }
1794
1795                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1796                                             rates_str, network->rates_ex_len);
1797                        break;
1798
1799                case MFIE_TYPE_DS_SET:
1800                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
1801                                             info_element->data[0]);
1802                        network->channel = info_element->data[0];
1803                        break;
1804
1805                case MFIE_TYPE_FH_SET:
1806                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
1807                        break;
1808
1809                case MFIE_TYPE_CF_SET:
1810                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
1811                        break;
1812
1813                case MFIE_TYPE_TIM:
1814                        if(info_element->len < 4)
1815                                break;
1816
1817                        network->tim.tim_count = info_element->data[0];
1818                        network->tim.tim_period = info_element->data[1];
1819
1820                        network->dtim_period = info_element->data[1];
1821                        if(ieee->state != IEEE80211_LINKED)
1822                                break;
1823#if 0
1824                        network->last_dtim_sta_time[0] = stats->mac_time[0];
1825#else
1826                        //we use jiffies for legacy Power save
1827                        network->last_dtim_sta_time[0] = jiffies;
1828#endif
1829                        network->last_dtim_sta_time[1] = stats->mac_time[1];
1830
1831                        network->dtim_data = IEEE80211_DTIM_VALID;
1832
1833                        if(info_element->data[0] != 0)
1834                                break;
1835
1836                        if(info_element->data[2] & 1)
1837                                network->dtim_data |= IEEE80211_DTIM_MBCAST;
1838
1839                        offset = (info_element->data[2] >> 1)*2;
1840
1841                        //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
1842
1843                        if(ieee->assoc_id < 8*offset ||
1844                                ieee->assoc_id > 8*(offset + info_element->len -3))
1845
1846                                break;
1847
1848                        offset = (ieee->assoc_id / 8) - offset;// + ((aid % 8)? 0 : 1) ;
1849
1850                        if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8)))
1851                                network->dtim_data |= IEEE80211_DTIM_UCAST;
1852
1853                        //IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
1854                        break;
1855
1856                case MFIE_TYPE_ERP:
1857                        network->erp_value = info_element->data[0];
1858                        network->flags |= NETWORK_HAS_ERP_VALUE;
1859                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1860                                             network->erp_value);
1861                        break;
1862                case MFIE_TYPE_IBSS_SET:
1863                        network->atim_window = info_element->data[0];
1864                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1865                                             network->atim_window);
1866                        break;
1867
1868                case MFIE_TYPE_CHALLENGE:
1869                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
1870                        break;
1871
1872                case MFIE_TYPE_GENERIC:
1873                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
1874                                             info_element->len);
1875                        if (!ieee80211_parse_qos_info_param_IE(info_element,
1876                                                               network))
1877                                break;
1878
1879                        if (info_element->len >= 4 &&
1880                            info_element->data[0] == 0x00 &&
1881                            info_element->data[1] == 0x50 &&
1882                            info_element->data[2] == 0xf2 &&
1883                            info_element->data[3] == 0x01) {
1884                                network->wpa_ie_len = min(info_element->len + 2,
1885                                                          MAX_WPA_IE_LEN);
1886                                memcpy(network->wpa_ie, info_element,
1887                                       network->wpa_ie_len);
1888                                break;
1889                        }
1890
1891#ifdef THOMAS_TURBO
1892                        if (info_element->len == 7 &&
1893                            info_element->data[0] == 0x00 &&
1894                            info_element->data[1] == 0xe0 &&
1895                            info_element->data[2] == 0x4c &&
1896                            info_element->data[3] == 0x01 &&
1897                            info_element->data[4] == 0x02) {
1898                                network->Turbo_Enable = 1;
1899                        }
1900#endif
1901
1902                        //for HTcap and HTinfo parameters
1903                        if(tmp_htcap_len == 0){
1904                                if(info_element->len >= 4 &&
1905                                   info_element->data[0] == 0x00 &&
1906                                   info_element->data[1] == 0x90 &&
1907                                   info_element->data[2] == 0x4c &&
1908                                   info_element->data[3] == 0x033){
1909
1910                                                tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
1911                                                if(tmp_htcap_len != 0){
1912                                                        network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1913                                                        network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
1914                                                                sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
1915                                                        memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
1916                                                }
1917                                }
1918                                if(tmp_htcap_len != 0)
1919                                        network->bssht.bdSupportHT = true;
1920                                else
1921                                        network->bssht.bdSupportHT = false;
1922                        }
1923
1924
1925                        if(tmp_htinfo_len == 0){
1926                                if(info_element->len >= 4 &&
1927                                        info_element->data[0] == 0x00 &&
1928                                        info_element->data[1] == 0x90 &&
1929                                        info_element->data[2] == 0x4c &&
1930                                        info_element->data[3] == 0x034){
1931
1932                                                tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
1933                                                if(tmp_htinfo_len != 0){
1934                                                        network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
1935                                                        if(tmp_htinfo_len){
1936                                                                network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
1937                                                                        sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
1938                                                                memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
1939                                                        }
1940
1941                                                }
1942
1943                                }
1944                        }
1945
1946                        if(ieee->aggregation){
1947                                if(network->bssht.bdSupportHT){
1948                                        if(info_element->len >= 4 &&
1949                                                info_element->data[0] == 0x00 &&
1950                                                info_element->data[1] == 0xe0 &&
1951                                                info_element->data[2] == 0x4c &&
1952                                                info_element->data[3] == 0x02){
1953
1954                                                ht_realtek_agg_len = min(info_element->len,(u8)MAX_IE_LEN);
1955                                                memcpy(ht_realtek_agg_buf,info_element->data,info_element->len);
1956
1957                                        }
1958                                        if(ht_realtek_agg_len >= 5){
1959                                                network->bssht.bdRT2RTAggregation = true;
1960
1961                                                if((ht_realtek_agg_buf[4] == 1) && (ht_realtek_agg_buf[5] & 0x02))
1962                                                network->bssht.bdRT2RTLongSlotTime = true;
1963                                        }
1964                                }
1965
1966                        }
1967
1968                        //if(tmp_htcap_len !=0  ||  tmp_htinfo_len != 0)
1969                        {
1970                                if((info_element->len >= 3 &&
1971                                         info_element->data[0] == 0x00 &&
1972                                         info_element->data[1] == 0x05 &&
1973                                         info_element->data[2] == 0xb5) ||
1974                                         (info_element->len >= 3 &&
1975                                         info_element->data[0] == 0x00 &&
1976                                         info_element->data[1] == 0x0a &&
1977                                         info_element->data[2] == 0xf7) ||
1978                                         (info_element->len >= 3 &&
1979                                         info_element->data[0] == 0x00 &&
1980                                         info_element->data[1] == 0x10 &&
1981                                         info_element->data[2] == 0x18)){
1982
1983                                                network->broadcom_cap_exist = true;
1984
1985                                }
1986                        }
1987#if 0
1988                        if (tmp_htcap_len !=0)
1989                                {
1990                                        u16 cap_ext = ((PHT_CAPABILITY_ELE)&info_element->data[0])->ExtHTCapInfo;
1991                                        if ((cap_ext & 0x0c00) == 0x0c00)
1992                                                {
1993                                                        network->ralink_cap_exist = true;
1994                                                }
1995                                }
1996#endif
1997                        if(info_element->len >= 3 &&
1998                                info_element->data[0] == 0x00 &&
1999                                info_element->data[1] == 0x0c &&
2000                                info_element->data[2] == 0x43)
2001                        {
2002                                network->ralink_cap_exist = true;
2003                        }
2004                        else
2005                                network->ralink_cap_exist = false;
2006                        //added by amy for atheros AP
2007                        if((info_element->len >= 3 &&
2008                                info_element->data[0] == 0x00 &&
2009                                info_element->data[1] == 0x03 &&
2010                                info_element->data[2] == 0x7f) ||
2011                                (info_element->len >= 3 &&
2012                                info_element->data[0] == 0x00 &&
2013                                info_element->data[1] == 0x13 &&
2014                                info_element->data[2] == 0x74))
2015                        {
2016                                printk("========>%s(): athros AP is exist\n",__FUNCTION__);
2017                                network->atheros_cap_exist = true;
2018                        }
2019                        else
2020                                network->atheros_cap_exist = false;
2021
2022                        if(info_element->len >= 3 &&
2023                                info_element->data[0] == 0x00 &&
2024                                info_element->data[1] == 0x40 &&
2025                                info_element->data[2] == 0x96)
2026                        {
2027                                network->cisco_cap_exist = true;
2028                        }
2029                        else
2030                                network->cisco_cap_exist = false;
2031                        //added by amy for LEAP of cisco
2032                        if(info_element->len > 4 &&
2033                                info_element->data[0] == 0x00 &&
2034                                info_element->data[1] == 0x40 &&
2035                                info_element->data[2] == 0x96 &&
2036                                info_element->data[3] == 0x01)
2037                        {
2038                                if(info_element->len == 6)
2039                                {
2040                                        memcpy(network->CcxRmState, &info_element[4], 2);
2041                                        if(network->CcxRmState[0] != 0)
2042                                        {
2043                                                network->bCcxRmEnable = true;
2044                                        }
2045                                        else
2046                                                network->bCcxRmEnable = false;
2047                                        //
2048                                        // CCXv4 Table 59-1 MBSSID Masks.
2049                                        //
2050                                        network->MBssidMask = network->CcxRmState[1] & 0x07;
2051                                        if(network->MBssidMask != 0)
2052                                        {
2053                                                network->bMBssidValid = true;
2054                                                network->MBssidMask = 0xff << (network->MBssidMask);
2055                                                cpMacAddr(network->MBssid, network->bssid);
2056                                                network->MBssid[5] &= network->MBssidMask;
2057                                        }
2058                                        else
2059                                        {
2060                                                network->bMBssidValid = false;
2061                                        }
2062                                }
2063                                else
2064                                {
2065                                        network->bCcxRmEnable = false;
2066                                }
2067                        }
2068                        if(info_element->len > 4  &&
2069                                info_element->data[0] == 0x00 &&
2070                                info_element->data[1] == 0x40 &&
2071                                info_element->data[2] == 0x96 &&
2072                                info_element->data[3] == 0x03)
2073                        {
2074                                if(info_element->len == 5)
2075                                {
2076                                        network->bWithCcxVerNum = true;
2077                                        network->BssCcxVerNumber = info_element->data[4];
2078                                }
2079                                else
2080                                {
2081                                        network->bWithCcxVerNum = false;
2082                                        network->BssCcxVerNumber = 0;
2083                                }
2084                        }
2085                        break;
2086
2087                case MFIE_TYPE_RSN:
2088                        IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
2089                                             info_element->len);
2090                        network->rsn_ie_len = min(info_element->len + 2,
2091                                                  MAX_WPA_IE_LEN);
2092                        memcpy(network->rsn_ie, info_element,
2093                               network->rsn_ie_len);
2094                        break;
2095
2096                        //HT related element.
2097                case MFIE_TYPE_HT_CAP:
2098                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_CAP: %d bytes\n",
2099                                             info_element->len);
2100                        tmp_htcap_len = min(info_element->len,(u8)MAX_IE_LEN);
2101                        if(tmp_htcap_len != 0){
2102                                network->bssht.bdHTSpecVer = HT_SPEC_VER_EWC;
2103                                network->bssht.bdHTCapLen = tmp_htcap_len > sizeof(network->bssht.bdHTCapBuf)?\
2104                                        sizeof(network->bssht.bdHTCapBuf):tmp_htcap_len;
2105                                memcpy(network->bssht.bdHTCapBuf,info_element->data,network->bssht.bdHTCapLen);
2106
2107                                //If peer is HT, but not WMM, call QosSetLegacyWMMParamWithHT()
2108                                // windows driver will update WMM parameters each beacon received once connected
2109                                // Linux driver is a bit different.
2110                                network->bssht.bdSupportHT = true;
2111                        }
2112                        else
2113                                network->bssht.bdSupportHT = false;
2114                        break;
2115
2116
2117                case MFIE_TYPE_HT_INFO:
2118                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_HT_INFO: %d bytes\n",
2119                                             info_element->len);
2120                        tmp_htinfo_len = min(info_element->len,(u8)MAX_IE_LEN);
2121                        if(tmp_htinfo_len){
2122                                network->bssht.bdHTSpecVer = HT_SPEC_VER_IEEE;
2123                                network->bssht.bdHTInfoLen = tmp_htinfo_len > sizeof(network->bssht.bdHTInfoBuf)?\
2124                                        sizeof(network->bssht.bdHTInfoBuf):tmp_htinfo_len;
2125                                memcpy(network->bssht.bdHTInfoBuf,info_element->data,network->bssht.bdHTInfoLen);
2126                        }
2127                        break;
2128
2129                case MFIE_TYPE_AIRONET:
2130                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_AIRONET: %d bytes\n",
2131                                             info_element->len);
2132                        if(info_element->len >IE_CISCO_FLAG_POSITION)
2133                        {
2134                                network->bWithAironetIE = true;
2135
2136                                // CCX 1 spec v1.13, A01.1 CKIP Negotiation (page23):
2137                                // "A Cisco access point advertises support for CKIP in beacon and probe response packets,
2138                                //  by adding an Aironet element and setting one or both of the CKIP negotiation bits."
2139                                if(     (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_MIC)   ||
2140                                        (info_element->data[IE_CISCO_FLAG_POSITION]&SUPPORT_CKIP_PK)    )
2141                                {
2142                                        network->bCkipSupported = true;
2143                                }
2144                                else
2145                                {
2146                                        network->bCkipSupported = false;
2147                                }
2148                        }
2149                        else
2150                        {
2151                                network->bWithAironetIE = false;
2152                                network->bCkipSupported = false;
2153                        }
2154                        break;
2155                case MFIE_TYPE_QOS_PARAMETER:
2156                        printk(KERN_ERR
2157                               "QoS Error need to parse QOS_PARAMETER IE\n");
2158                        break;
2159
2160#ifdef ENABLE_DOT11D
2161                case MFIE_TYPE_COUNTRY:
2162                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
2163                                             info_element->len);
2164                        //printk("=====>Receive <%s> Country IE\n",network->ssid);
2165                        ieee80211_extract_country_ie(ieee, info_element, network, network->bssid);//addr2 is same as addr3 when from an AP
2166                        break;
2167#endif
2168/* TODO */
2169#if 0
2170                        /* 802.11h */
2171                case MFIE_TYPE_POWER_CONSTRAINT:
2172                        network->power_constraint = info_element->data[0];
2173                        network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
2174                        break;
2175
2176                case MFIE_TYPE_CSA:
2177                        network->power_constraint = info_element->data[0];
2178                        network->flags |= NETWORK_HAS_CSA;
2179                        break;
2180
2181                case MFIE_TYPE_QUIET:
2182                        network->quiet.count = info_element->data[0];
2183                        network->quiet.period = info_element->data[1];
2184                        network->quiet.duration = info_element->data[2];
2185                        network->quiet.offset = info_element->data[3];
2186                        network->flags |= NETWORK_HAS_QUIET;
2187                        break;
2188
2189                case MFIE_TYPE_IBSS_DFS:
2190                        if (network->ibss_dfs)
2191                                break;
2192                        network->ibss_dfs = kmemdup(info_element->data,
2193                                                    info_element->len,
2194                                                    GFP_ATOMIC);
2195                        if (!network->ibss_dfs)
2196                                return 1;
2197                        network->flags |= NETWORK_HAS_IBSS_DFS;
2198                        break;
2199
2200                case MFIE_TYPE_TPC_REPORT:
2201                        network->tpc_report.transmit_power =
2202                            info_element->data[0];
2203                        network->tpc_report.link_margin = info_element->data[1];
2204                        network->flags |= NETWORK_HAS_TPC_REPORT;
2205                        break;
2206#endif
2207                default:
2208                        IEEE80211_DEBUG_MGMT
2209                            ("Unsupported info element: %s (%d)\n",
2210                             get_info_element_string(info_element->id),
2211                             info_element->id);
2212                        break;
2213                }
2214
2215                length -= sizeof(*info_element) + info_element->len;
2216                info_element =
2217                    (struct ieee80211_info_element *)&info_element->
2218                    data[info_element->len];
2219        }
2220
2221        if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
2222                !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation)
2223        {
2224                network->unknown_cap_exist = true;
2225        }
2226        else
2227        {
2228                network->unknown_cap_exist = false;
2229        }
2230        return 0;
2231}
2232
2233static inline u8 ieee80211_SignalStrengthTranslate(
2234        u8  CurrSS
2235        )
2236{
2237        u8 RetSS;
2238
2239        // Step 1. Scale mapping.
2240        if(CurrSS >= 71 && CurrSS <= 100)
2241        {
2242                RetSS = 90 + ((CurrSS - 70) / 3);
2243        }
2244        else if(CurrSS >= 41 && CurrSS <= 70)
2245        {
2246                RetSS = 78 + ((CurrSS - 40) / 3);
2247        }
2248        else if(CurrSS >= 31 && CurrSS <= 40)
2249        {
2250                RetSS = 66 + (CurrSS - 30);
2251        }
2252        else if(CurrSS >= 21 && CurrSS <= 30)
2253        {
2254                RetSS = 54 + (CurrSS - 20);
2255        }
2256        else if(CurrSS >= 5 && CurrSS <= 20)
2257        {
2258                RetSS = 42 + (((CurrSS - 5) * 2) / 3);
2259        }
2260        else if(CurrSS == 4)
2261        {
2262                RetSS = 36;
2263        }
2264        else if(CurrSS == 3)
2265        {
2266                RetSS = 27;
2267        }
2268        else if(CurrSS == 2)
2269        {
2270                RetSS = 18;
2271        }
2272        else if(CurrSS == 1)
2273        {
2274                RetSS = 9;
2275        }
2276        else
2277        {
2278                RetSS = CurrSS;
2279        }
2280        //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
2281
2282        // Step 2. Smoothing.
2283
2284        //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
2285
2286        return RetSS;
2287}
2288
2289long ieee80211_translate_todbm(u8 signal_strength_index )// 0-100 index.
2290{
2291        long    signal_power; // in dBm.
2292
2293        // Translate to dBm (x=0.5y-95).
2294        signal_power = (long)((signal_strength_index + 1) >> 1);
2295        signal_power -= 95;
2296
2297        return signal_power;
2298}
2299
2300static inline int ieee80211_network_init(
2301        struct ieee80211_device *ieee,
2302        struct ieee80211_probe_response *beacon,
2303        struct ieee80211_network *network,
2304        struct ieee80211_rx_stats *stats)
2305{
2306#ifdef CONFIG_IEEE80211_DEBUG
2307        //char rates_str[64];
2308        //char *p;
2309#endif
2310
2311        network->qos_data.active = 0;
2312        network->qos_data.supported = 0;
2313        network->qos_data.param_count = 0;
2314        network->qos_data.old_param_count = 0;
2315
2316        /* Pull out fixed field data */
2317        memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
2318        network->capability = le16_to_cpu(beacon->capability);
2319        network->last_scanned = jiffies;
2320        network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
2321        network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
2322        network->beacon_interval = le32_to_cpu(beacon->beacon_interval);
2323        /* Where to pull this? beacon->listen_interval;*/
2324        network->listen_interval = 0x0A;
2325        network->rates_len = network->rates_ex_len = 0;
2326        network->last_associate = 0;
2327        network->ssid_len = 0;
2328        network->flags = 0;
2329        network->atim_window = 0;
2330        network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
2331            0x3 : 0x0;
2332        network->berp_info_valid = false;
2333        network->broadcom_cap_exist = false;
2334        network->ralink_cap_exist = false;
2335        network->atheros_cap_exist = false;
2336        network->cisco_cap_exist = false;
2337        network->unknown_cap_exist = false;
2338#ifdef THOMAS_TURBO
2339        network->Turbo_Enable = 0;
2340#endif
2341#ifdef ENABLE_DOT11D
2342        network->CountryIeLen = 0;
2343        memset(network->CountryIeBuf, 0, MAX_IE_LEN);
2344#endif
2345//Initialize HT parameters
2346        //ieee80211_ht_initialize(&network->bssht);
2347        HTInitializeBssDesc(&network->bssht);
2348        if (stats->freq == IEEE80211_52GHZ_BAND) {
2349                /* for A band (No DS info) */
2350                network->channel = stats->received_channel;
2351        } else
2352                network->flags |= NETWORK_HAS_CCK;
2353
2354        network->wpa_ie_len = 0;
2355        network->rsn_ie_len = 0;
2356
2357        if (ieee80211_parse_info_param
2358            (ieee,beacon->info_element, stats->len - sizeof(*beacon), network, stats))
2359                return 1;
2360
2361        network->mode = 0;
2362        if (stats->freq == IEEE80211_52GHZ_BAND)
2363                network->mode = IEEE_A;
2364        else {
2365                if (network->flags & NETWORK_HAS_OFDM)
2366                        network->mode |= IEEE_G;
2367                if (network->flags & NETWORK_HAS_CCK)
2368                        network->mode |= IEEE_B;
2369        }
2370
2371        if (network->mode == 0) {
2372                IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
2373                                     "network.\n",
2374                                     escape_essid(network->ssid,
2375                                                  network->ssid_len),
2376                                     MAC_ARG(network->bssid));
2377                return 1;
2378        }
2379
2380        if(network->bssht.bdSupportHT){
2381                if(network->mode == IEEE_A)
2382                        network->mode = IEEE_N_5G;
2383                else if(network->mode & (IEEE_G | IEEE_B))
2384                        network->mode = IEEE_N_24G;
2385        }
2386        if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
2387                network->flags |= NETWORK_EMPTY_ESSID;
2388
2389#if 1
2390        stats->signal = 30 + (stats->SignalStrength * 70) / 100;
2391        //stats->signal = ieee80211_SignalStrengthTranslate(stats->signal);
2392        stats->noise = ieee80211_translate_todbm((u8)(100-stats->signal)) -25;
2393#endif
2394
2395        memcpy(&network->stats, stats, sizeof(network->stats));
2396
2397        return 0;
2398}
2399
2400static inline int is_same_network(struct ieee80211_network *src,
2401                                  struct ieee80211_network *dst, struct ieee80211_device* ieee)
2402{
2403        /* A network is only a duplicate if the channel, BSSID, ESSID
2404         * and the capability field (in particular IBSS and BSS) all match.
2405         * We treat all <hidden> with the same BSSID and channel
2406         * as one network */
2407        return //((src->ssid_len == dst->ssid_len) &&
2408                (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2409                (src->channel == dst->channel) &&
2410                !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
2411                //!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
2412                (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&
2413                ((src->capability & WLAN_CAPABILITY_IBSS) ==
2414                (dst->capability & WLAN_CAPABILITY_IBSS)) &&
2415                ((src->capability & WLAN_CAPABILITY_BSS) ==
2416                (dst->capability & WLAN_CAPABILITY_BSS)));
2417}
2418
2419static inline void update_network(struct ieee80211_network *dst,
2420                                  struct ieee80211_network *src)
2421{
2422        int qos_active;
2423        u8 old_param;
2424
2425        memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
2426        dst->capability = src->capability;
2427        memcpy(dst->rates, src->rates, src->rates_len);
2428        dst->rates_len = src->rates_len;
2429        memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
2430        dst->rates_ex_len = src->rates_ex_len;
2431        if(src->ssid_len > 0)
2432        {
2433                memset(dst->ssid, 0, dst->ssid_len);
2434                dst->ssid_len = src->ssid_len;
2435                memcpy(dst->ssid, src->ssid, src->ssid_len);
2436        }
2437        dst->mode = src->mode;
2438        dst->flags = src->flags;
2439        dst->time_stamp[0] = src->time_stamp[0];
2440        dst->time_stamp[1] = src->time_stamp[1];
2441        if (src->flags & NETWORK_HAS_ERP_VALUE)
2442        {
2443                dst->erp_value = src->erp_value;
2444                dst->berp_info_valid = src->berp_info_valid = true;
2445        }
2446        dst->beacon_interval = src->beacon_interval;
2447        dst->listen_interval = src->listen_interval;
2448        dst->atim_window = src->atim_window;
2449        dst->dtim_period = src->dtim_period;
2450        dst->dtim_data = src->dtim_data;
2451        dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
2452        dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
2453        memcpy(&dst->tim, &src->tim, sizeof(struct ieee80211_tim_parameters));
2454
2455        dst->bssht.bdSupportHT = src->bssht.bdSupportHT;
2456        dst->bssht.bdRT2RTAggregation = src->bssht.bdRT2RTAggregation;
2457        dst->bssht.bdHTCapLen= src->bssht.bdHTCapLen;
2458        memcpy(dst->bssht.bdHTCapBuf,src->bssht.bdHTCapBuf,src->bssht.bdHTCapLen);
2459        dst->bssht.bdHTInfoLen= src->bssht.bdHTInfoLen;
2460        memcpy(dst->bssht.bdHTInfoBuf,src->bssht.bdHTInfoBuf,src->bssht.bdHTInfoLen);
2461        dst->bssht.bdHTSpecVer = src->bssht.bdHTSpecVer;
2462        dst->bssht.bdRT2RTLongSlotTime = src->bssht.bdRT2RTLongSlotTime;
2463        dst->broadcom_cap_exist = src->broadcom_cap_exist;
2464        dst->ralink_cap_exist = src->ralink_cap_exist;
2465        dst->atheros_cap_exist = src->atheros_cap_exist;
2466        dst->cisco_cap_exist = src->cisco_cap_exist;
2467        dst->unknown_cap_exist = src->unknown_cap_exist;
2468        memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
2469        dst->wpa_ie_len = src->wpa_ie_len;
2470        memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
2471        dst->rsn_ie_len = src->rsn_ie_len;
2472
2473        dst->last_scanned = jiffies;
2474        /* qos related parameters */
2475        //qos_active = src->qos_data.active;
2476        qos_active = dst->qos_data.active;
2477        //old_param = dst->qos_data.old_param_count;
2478        old_param = dst->qos_data.param_count;
2479        if(dst->flags & NETWORK_HAS_QOS_MASK){
2480        //not update QOS paramter in beacon, as most AP will set all these parameter to 0.//WB
2481        //      printk("====>%s(), aifs:%x, %x\n", __FUNCTION__, dst->qos_data.parameters.aifs[0], src->qos_data.parameters.aifs[0]);
2482        //      memcpy(&dst->qos_data, &src->qos_data,
2483        //              sizeof(struct ieee80211_qos_data));
2484        }
2485        else {
2486                dst->qos_data.supported = src->qos_data.supported;
2487                dst->qos_data.param_count = src->qos_data.param_count;
2488        }
2489
2490        if(dst->qos_data.supported == 1) {
2491                dst->QoS_Enable = 1;
2492                if(dst->ssid_len)
2493                        IEEE80211_DEBUG_QOS
2494                                ("QoS the network %s is QoS supported\n",
2495                                dst->ssid);
2496                else
2497                        IEEE80211_DEBUG_QOS
2498                                ("QoS the network is QoS supported\n");
2499        }
2500        dst->qos_data.active = qos_active;
2501        dst->qos_data.old_param_count = old_param;
2502
2503        /* dst->last_associate is not overwritten */
2504#if 1
2505        dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
2506        if(src->wmm_param[0].ac_aci_acm_aifsn|| \
2507           src->wmm_param[1].ac_aci_acm_aifsn|| \
2508           src->wmm_param[2].ac_aci_acm_aifsn|| \
2509           src->wmm_param[1].ac_aci_acm_aifsn) {
2510          memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
2511        }
2512        //dst->QoS_Enable = src->QoS_Enable;
2513#else
2514        dst->QoS_Enable = 1;//for Rtl8187 simulation
2515#endif
2516#ifdef THOMAS_TURBO
2517        dst->Turbo_Enable = src->Turbo_Enable;
2518#endif
2519
2520#ifdef ENABLE_DOT11D
2521        dst->CountryIeLen = src->CountryIeLen;
2522        memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
2523#endif
2524
2525        //added by amy for LEAP
2526        dst->bWithAironetIE = src->bWithAironetIE;
2527        dst->bCkipSupported = src->bCkipSupported;
2528        memcpy(dst->CcxRmState,src->CcxRmState,2);
2529        dst->bCcxRmEnable = src->bCcxRmEnable;
2530        dst->MBssidMask = src->MBssidMask;
2531        dst->bMBssidValid = src->bMBssidValid;
2532        memcpy(dst->MBssid,src->MBssid,6);
2533        dst->bWithCcxVerNum = src->bWithCcxVerNum;
2534        dst->BssCcxVerNumber = src->BssCcxVerNumber;
2535
2536}
2537
2538static inline int is_beacon(__le16 fc)
2539{
2540        return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
2541}
2542
2543static inline void ieee80211_process_probe_response(
2544        struct ieee80211_device *ieee,
2545        struct ieee80211_probe_response *beacon,
2546        struct ieee80211_rx_stats *stats)
2547{
2548        struct ieee80211_network network;
2549        struct ieee80211_network *target;
2550        struct ieee80211_network *oldest = NULL;
2551#ifdef CONFIG_IEEE80211_DEBUG
2552        struct ieee80211_info_element *info_element = &beacon->info_element[0];
2553#endif
2554        unsigned long flags;
2555        short renew;
2556        //u8 wmm_info;
2557
2558        memset(&network, 0, sizeof(struct ieee80211_network));
2559        IEEE80211_DEBUG_SCAN(
2560                "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
2561                escape_essid(info_element->data, info_element->len),
2562                MAC_ARG(beacon->header.addr3),
2563                (beacon->capability & (1<<0xf)) ? '1' : '0',
2564                (beacon->capability & (1<<0xe)) ? '1' : '0',
2565                (beacon->capability & (1<<0xd)) ? '1' : '0',
2566                (beacon->capability & (1<<0xc)) ? '1' : '0',
2567                (beacon->capability & (1<<0xb)) ? '1' : '0',
2568                (beacon->capability & (1<<0xa)) ? '1' : '0',
2569                (beacon->capability & (1<<0x9)) ? '1' : '0',
2570                (beacon->capability & (1<<0x8)) ? '1' : '0',
2571                (beacon->capability & (1<<0x7)) ? '1' : '0',
2572                (beacon->capability & (1<<0x6)) ? '1' : '0',
2573                (beacon->capability & (1<<0x5)) ? '1' : '0',
2574                (beacon->capability & (1<<0x4)) ? '1' : '0',
2575                (beacon->capability & (1<<0x3)) ? '1' : '0',
2576                (beacon->capability & (1<<0x2)) ? '1' : '0',
2577                (beacon->capability & (1<<0x1)) ? '1' : '0',
2578                (beacon->capability & (1<<0x0)) ? '1' : '0');
2579
2580        if (ieee80211_network_init(ieee, beacon, &network, stats)) {
2581                IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
2582                                     escape_essid(info_element->data,
2583                                                  info_element->len),
2584                                     MAC_ARG(beacon->header.addr3),
2585                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2586                                     IEEE80211_STYPE_PROBE_RESP ?
2587                                     "PROBE RESPONSE" : "BEACON");
2588                return;
2589        }
2590
2591#ifdef ENABLE_DOT11D
2592        // For Asus EeePc request,
2593        // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
2594        //         wireless adapter should follow the country code.
2595        // (2)  If there is no any country code in beacon,
2596        //       then wireless adapter should do active scan from ch1~11 and
2597        //       passive scan from ch12~14
2598
2599        if( !IsLegalChannel(ieee, network.channel) )
2600                return;
2601        if(ieee->bGlobalDomain)
2602        {
2603                if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
2604                {
2605                        // Case 1: Country code
2606                        if(IS_COUNTRY_IE_VALID(ieee) )
2607                        {
2608                                if( !IsLegalChannel(ieee, network.channel) )
2609                                {
2610                                        printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
2611                                        return;
2612                                }
2613                        }
2614                        // Case 2: No any country code.
2615                        else
2616                        {
2617                                // Filter over channel ch12~14
2618                                if(network.channel > 11)
2619                                {
2620                                        printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
2621                                        return;
2622                                }
2623                        }
2624                }
2625                else
2626                {
2627                        // Case 1: Country code
2628                        if(IS_COUNTRY_IE_VALID(ieee) )
2629                        {
2630                                if( !IsLegalChannel(ieee, network.channel) )
2631                                {
2632                                        printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
2633                                        return;
2634                                }
2635                        }
2636                        // Case 2: No any country code.
2637                        else
2638                        {
2639                                // Filter over channel ch12~14
2640                                if(network.channel > 14)
2641                                {
2642                                        printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
2643                                        return;
2644                                }
2645                        }
2646                }
2647        }
2648#endif
2649
2650        /* The network parsed correctly -- so now we scan our known networks
2651         * to see if we can find it in our list.
2652         *
2653         * NOTE:  This search is definitely not optimized.  Once its doing
2654         *        the "right thing" we'll optimize it for efficiency if
2655         *        necessary */
2656
2657        /* Search for this entry in the list and update it if it is
2658         * already there. */
2659
2660        spin_lock_irqsave(&ieee->lock, flags);
2661
2662        if(is_same_network(&ieee->current_network, &network, ieee)) {
2663                update_network(&ieee->current_network, &network);
2664                if((ieee->current_network.mode == IEEE_N_24G || ieee->current_network.mode == IEEE_G)
2665                && ieee->current_network.berp_info_valid){
2666                if(ieee->current_network.erp_value& ERP_UseProtection)
2667                        ieee->current_network.buseprotection = true;
2668                else
2669                        ieee->current_network.buseprotection = false;
2670                }
2671                if(is_beacon(beacon->header.frame_ctl))
2672                {
2673                        if(ieee->state == IEEE80211_LINKED)
2674                                ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
2675                }
2676                else //hidden AP
2677                        network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
2678        }
2679
2680        list_for_each_entry(target, &ieee->network_list, list) {
2681                if (is_same_network(target, &network, ieee))
2682                        break;
2683                if ((oldest == NULL) ||
2684                    (target->last_scanned < oldest->last_scanned))
2685                        oldest = target;
2686        }
2687
2688        /* If we didn't find a match, then get a new network slot to initialize
2689         * with this beacon's information */
2690        if (&target->list == &ieee->network_list) {
2691                if (list_empty(&ieee->network_free_list)) {
2692                        /* If there are no more slots, expire the oldest */
2693                        list_del(&oldest->list);
2694                        target = oldest;
2695                        IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
2696                                             "network list.\n",
2697                                             escape_essid(target->ssid,
2698                                                          target->ssid_len),
2699                                             MAC_ARG(target->bssid));
2700                } else {
2701                        /* Otherwise just pull from the free list */
2702                        target = list_entry(ieee->network_free_list.next,
2703                                            struct ieee80211_network, list);
2704                        list_del(ieee->network_free_list.next);
2705                }
2706
2707
2708#ifdef CONFIG_IEEE80211_DEBUG
2709                IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
2710                                     escape_essid(network.ssid,
2711                                                  network.ssid_len),
2712                                     MAC_ARG(network.bssid),
2713                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2714                                     IEEE80211_STYPE_PROBE_RESP ?
2715                                     "PROBE RESPONSE" : "BEACON");
2716#endif
2717                memcpy(target, &network, sizeof(*target));
2718                list_add_tail(&target->list, &ieee->network_list);
2719                if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
2720                        ieee80211_softmac_new_net(ieee,&network);
2721        } else {
2722                IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
2723                                     escape_essid(target->ssid,
2724                                                  target->ssid_len),
2725                                     MAC_ARG(target->bssid),
2726                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
2727                                     IEEE80211_STYPE_PROBE_RESP ?
2728                                     "PROBE RESPONSE" : "BEACON");
2729
2730                /* we have an entry and we are going to update it. But this entry may
2731                 * be already expired. In this case we do the same as we found a new
2732                 * net and call the new_net handler
2733                 */
2734                renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
2735                //YJ,add,080819,for hidden ap
2736                if(is_beacon(beacon->header.frame_ctl) == 0)
2737                        network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
2738                //if(strncmp(network.ssid, "linksys-c",9) == 0)
2739                //      printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
2740                if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
2741                    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
2742                    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
2743                        renew = 1;
2744                //YJ,add,080819,for hidden ap,end
2745
2746                update_network(target, &network);
2747                if(renew && (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE))
2748                        ieee80211_softmac_new_net(ieee,&network);
2749        }
2750
2751        spin_unlock_irqrestore(&ieee->lock, flags);
2752        if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
2753                (ieee->state == IEEE80211_LINKED)) {
2754                if(ieee->handle_beacon != NULL) {
2755                        ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
2756                }
2757        }
2758}
2759
2760void ieee80211_rx_mgt(struct ieee80211_device *ieee,
2761                      struct ieee80211_hdr_4addr *header,
2762                      struct ieee80211_rx_stats *stats)
2763{
2764        if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2765                                ieee->iw_mode == IW_MODE_INFRA &&
2766                                ieee->state == IEEE80211_LINKED))
2767        {
2768                tasklet_schedule(&ieee->ps_task);
2769        }
2770
2771        if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2772                WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2773                ieee->last_rx_ps_time = jiffies;
2774
2775        switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2776
2777        case IEEE80211_STYPE_BEACON:
2778                IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
2779                                     WLAN_FC_GET_STYPE(header->frame_ctl));
2780                IEEE80211_DEBUG_SCAN("Beacon\n");
2781                ieee80211_process_probe_response(
2782                        ieee, (struct ieee80211_probe_response *)header, stats);
2783                break;
2784
2785        case IEEE80211_STYPE_PROBE_RESP:
2786                IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
2787                                     WLAN_FC_GET_STYPE(header->frame_ctl));
2788                IEEE80211_DEBUG_SCAN("Probe response\n");
2789                ieee80211_process_probe_response(
2790                        ieee, (struct ieee80211_probe_response *)header, stats);
2791                break;
2792
2793        }
2794}
2795
2796#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
2797//EXPORT_SYMBOL(ieee80211_rx_mgt);
2798//EXPORT_SYMBOL(ieee80211_rx);
2799#else
2800EXPORT_SYMBOL_NOVERS(ieee80211_rx_mgt);
2801EXPORT_SYMBOL_NOVERS(ieee80211_rx);
2802#endif
2803