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