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