linux/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
<<
>>
Prefs
   1/*
   2 * Original code based Host AP (software wireless LAN access point) driver
   3 * for Intersil Prism2/2.5/3 - hostap.o module, common routines
   4 *
   5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
   6 * <jkmaline@cc.hut.fi>
   7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
   8 * Copyright (c) 2004, Intel Corporation
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation. See README and COPYING for
  13 * more details.
  14 ******************************************************************************
  15
  16  Few modifications for Realtek's Wi-Fi drivers by
  17  Andrea Merello <andreamrl@tiscali.it>
  18
  19  A special thanks goes to Realtek for their support !
  20
  21******************************************************************************/
  22
  23
  24#include <linux/compiler.h>
  25//#include <linux/config.h>
  26#include <linux/errno.h>
  27#include <linux/if_arp.h>
  28#include <linux/in6.h>
  29#include <linux/in.h>
  30#include <linux/ip.h>
  31#include <linux/kernel.h>
  32#include <linux/module.h>
  33#include <linux/netdevice.h>
  34#include <linux/pci.h>
  35#include <linux/proc_fs.h>
  36#include <linux/skbuff.h>
  37#include <linux/slab.h>
  38#include <linux/tcp.h>
  39#include <linux/types.h>
  40#include <linux/wireless.h>
  41#include <linux/etherdevice.h>
  42#include <asm/uaccess.h>
  43#include <linux/ctype.h>
  44
  45#include "ieee80211.h"
  46#include "dot11d.h"
  47static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee,
  48                                        struct sk_buff *skb,
  49                                        struct ieee80211_rx_stats *rx_stats)
  50{
  51        struct ieee80211_hdr_4addr *hdr =
  52                (struct ieee80211_hdr_4addr *)skb->data;
  53        u16 fc = le16_to_cpu(hdr->frame_ctl);
  54
  55        skb->dev = ieee->dev;
  56        skb_reset_mac_header(skb);
  57        skb_pull(skb, ieee80211_get_hdrlen(fc));
  58        skb->pkt_type = PACKET_OTHERHOST;
  59        skb->protocol = __constant_htons(ETH_P_80211_RAW);
  60        memset(skb->cb, 0, sizeof(skb->cb));
  61        netif_rx(skb);
  62}
  63
  64
  65/* Called only as a tasklet (software IRQ) */
  66static struct ieee80211_frag_entry *
  67ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq,
  68                          unsigned int frag, u8 tid,u8 *src, u8 *dst)
  69{
  70        struct ieee80211_frag_entry *entry;
  71        int i;
  72
  73        for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
  74                entry = &ieee->frag_cache[tid][i];
  75                if (entry->skb != NULL &&
  76                    time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
  77                        IEEE80211_DEBUG_FRAG(
  78                                "expiring fragment cache entry "
  79                                "seq=%u last_frag=%u\n",
  80                                entry->seq, entry->last_frag);
  81                        dev_kfree_skb_any(entry->skb);
  82                        entry->skb = NULL;
  83                }
  84
  85                if (entry->skb != NULL && entry->seq == seq &&
  86                    (entry->last_frag + 1 == frag || frag == -1) &&
  87                    memcmp(entry->src_addr, src, ETH_ALEN) == 0 &&
  88                    memcmp(entry->dst_addr, dst, ETH_ALEN) == 0)
  89                        return entry;
  90        }
  91
  92        return NULL;
  93}
  94
  95/* Called only as a tasklet (software IRQ) */
  96static struct sk_buff *
  97ieee80211_frag_cache_get(struct ieee80211_device *ieee,
  98                         struct ieee80211_hdr_4addr *hdr)
  99{
 100        struct sk_buff *skb = NULL;
 101        u16 fc = le16_to_cpu(hdr->frame_ctl);
 102        u16 sc = le16_to_cpu(hdr->seq_ctl);
 103        unsigned int frag = WLAN_GET_SEQ_FRAG(sc);
 104        unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
 105        struct ieee80211_frag_entry *entry;
 106        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 107        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 108        u8 tid;
 109
 110        if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 111          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
 112          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
 113          tid = UP2AC(tid);
 114          tid ++;
 115        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
 116          hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
 117          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
 118          tid = UP2AC(tid);
 119          tid ++;
 120        } else {
 121          tid = 0;
 122        }
 123
 124        if (frag == 0) {
 125                /* Reserve enough space to fit maximum frame length */
 126                skb = dev_alloc_skb(ieee->dev->mtu +
 127                                    sizeof(struct ieee80211_hdr_4addr) +
 128                                    8 /* LLC */ +
 129                                    2 /* alignment */ +
 130                                    8 /* WEP */ +
 131                                    ETH_ALEN /* WDS */ +
 132                                    (IEEE80211_QOS_HAS_SEQ(fc)?2:0) /* QOS Control */);
 133                if (skb == NULL)
 134                        return NULL;
 135
 136                entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]];
 137                ieee->frag_next_idx[tid]++;
 138                if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN)
 139                        ieee->frag_next_idx[tid] = 0;
 140
 141                if (entry->skb != NULL)
 142                        dev_kfree_skb_any(entry->skb);
 143
 144                entry->first_frag_time = jiffies;
 145                entry->seq = seq;
 146                entry->last_frag = frag;
 147                entry->skb = skb;
 148                memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
 149                memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
 150        } else {
 151                /* received a fragment of a frame for which the head fragment
 152                 * should have already been received */
 153                entry = ieee80211_frag_cache_find(ieee, seq, frag, tid,hdr->addr2,
 154                                                  hdr->addr1);
 155                if (entry != NULL) {
 156                        entry->last_frag = frag;
 157                        skb = entry->skb;
 158                }
 159        }
 160
 161        return skb;
 162}
 163
 164
 165/* Called only as a tasklet (software IRQ) */
 166static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
 167                                           struct ieee80211_hdr_4addr *hdr)
 168{
 169        u16 fc = le16_to_cpu(hdr->frame_ctl);
 170        u16 sc = le16_to_cpu(hdr->seq_ctl);
 171        unsigned int seq = WLAN_GET_SEQ_SEQ(sc);
 172        struct ieee80211_frag_entry *entry;
 173        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 174        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 175        u8 tid;
 176
 177        if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 178          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr;
 179          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
 180          tid = UP2AC(tid);
 181          tid ++;
 182        } else if (IEEE80211_QOS_HAS_SEQ(fc)) {
 183          hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr;
 184          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
 185          tid = UP2AC(tid);
 186          tid ++;
 187        } else {
 188          tid = 0;
 189        }
 190
 191        entry = ieee80211_frag_cache_find(ieee, seq, -1, tid,hdr->addr2,
 192                                          hdr->addr1);
 193
 194        if (entry == NULL) {
 195                IEEE80211_DEBUG_FRAG(
 196                        "could not invalidate fragment cache "
 197                        "entry (seq=%u)\n", seq);
 198                return -1;
 199        }
 200
 201        entry->skb = NULL;
 202        return 0;
 203}
 204
 205
 206
 207/* ieee80211_rx_frame_mgtmt
 208 *
 209 * Responsible for handling management control frames
 210 *
 211 * Called by ieee80211_rx */
 212static inline int
 213ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
 214                        struct ieee80211_rx_stats *rx_stats, u16 type,
 215                        u16 stype)
 216{
 217        struct ieee80211_hdr_4addr *hdr;
 218
 219        // cheat the the hdr type
 220        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 221
 222        /* On the struct stats definition there is written that
 223         * this is not mandatory.... but seems that the probe
 224         * response parser uses it
 225         */
 226        rx_stats->len = skb->len;
 227        ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data,
 228                         rx_stats);
 229
 230        if((ieee->state == IEEE80211_LINKED)&&(memcmp(hdr->addr3,ieee->current_network.bssid,ETH_ALEN))) {
 231                dev_kfree_skb_any(skb);
 232                return 0;
 233        }
 234
 235        ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype);
 236
 237        dev_kfree_skb_any(skb);
 238
 239        return 0;
 240
 241}
 242
 243
 244
 245/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
 246/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
 247static unsigned char rfc1042_header[] =
 248{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
 249/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
 250static unsigned char bridge_tunnel_header[] =
 251{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
 252/* No encapsulation header if EtherType < 0x600 (=length) */
 253
 254/* Called by ieee80211_rx_frame_decrypt */
 255static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
 256                                    struct sk_buff *skb, size_t hdrlen)
 257{
 258        struct net_device *dev = ieee->dev;
 259        u16 fc, ethertype;
 260        struct ieee80211_hdr_4addr *hdr;
 261        u8 *pos;
 262
 263        if (skb->len < 24)
 264                return 0;
 265
 266        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 267        fc = le16_to_cpu(hdr->frame_ctl);
 268
 269        /* check that the frame is unicast frame to us */
 270        if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 271            IEEE80211_FCTL_TODS &&
 272            memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 &&
 273            memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
 274                /* ToDS frame with own addr BSSID and DA */
 275        } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
 276                   IEEE80211_FCTL_FROMDS &&
 277                   memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) {
 278                /* FromDS frame with own addr as DA */
 279        } else
 280                return 0;
 281
 282        if (skb->len < 24 + 8)
 283                return 0;
 284
 285        /* check for port access entity Ethernet type */
 286//      pos = skb->data + 24;
 287        pos = skb->data + hdrlen;
 288        ethertype = (pos[6] << 8) | pos[7];
 289        if (ethertype == ETH_P_PAE)
 290                return 1;
 291
 292        return 0;
 293}
 294
 295/* Called only as a tasklet (software IRQ), by ieee80211_rx */
 296static inline int
 297ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
 298                           struct ieee80211_crypt_data *crypt)
 299{
 300        struct ieee80211_hdr_4addr *hdr;
 301        int res, hdrlen;
 302
 303        if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
 304                return 0;
 305
 306        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 307        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 308
 309#ifdef CONFIG_IEEE80211_CRYPT_TKIP
 310        if (ieee->tkip_countermeasures &&
 311            strcmp(crypt->ops->name, "TKIP") == 0) {
 312                if (net_ratelimit()) {
 313                        printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
 314                               "received packet from %pM\n",
 315                               ieee->dev->name, hdr->addr2);
 316                }
 317                return -1;
 318        }
 319#endif
 320
 321        atomic_inc(&crypt->refcnt);
 322        res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
 323        atomic_dec(&crypt->refcnt);
 324        if (res < 0) {
 325                IEEE80211_DEBUG_DROP(
 326                        "decryption failed (SA=%pM"
 327                        ") res=%d\n", hdr->addr2, res);
 328                if (res == -2)
 329                        IEEE80211_DEBUG_DROP("Decryption failed ICV "
 330                                             "mismatch (key %d)\n",
 331                                             skb->data[hdrlen + 3] >> 6);
 332                ieee->ieee_stats.rx_discards_undecryptable++;
 333                return -1;
 334        }
 335
 336        return res;
 337}
 338
 339
 340/* Called only as a tasklet (software IRQ), by ieee80211_rx */
 341static inline int
 342ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *skb,
 343                             int keyidx, struct ieee80211_crypt_data *crypt)
 344{
 345        struct ieee80211_hdr_4addr *hdr;
 346        int res, hdrlen;
 347
 348        if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
 349                return 0;
 350
 351        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 352        hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
 353
 354        atomic_inc(&crypt->refcnt);
 355        res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
 356        atomic_dec(&crypt->refcnt);
 357        if (res < 0) {
 358                printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
 359                       " (SA=%pM keyidx=%d)\n",
 360                       ieee->dev->name, hdr->addr2, keyidx);
 361                return -1;
 362        }
 363
 364        return 0;
 365}
 366
 367
 368/* this function is stolen from ipw2200 driver*/
 369#define IEEE_PACKET_RETRY_TIME (5*HZ)
 370static int is_duplicate_packet(struct ieee80211_device *ieee,
 371                                      struct ieee80211_hdr_4addr *header)
 372{
 373        u16 fc = le16_to_cpu(header->frame_ctl);
 374        u16 sc = le16_to_cpu(header->seq_ctl);
 375        u16 seq = WLAN_GET_SEQ_SEQ(sc);
 376        u16 frag = WLAN_GET_SEQ_FRAG(sc);
 377        u16 *last_seq, *last_frag;
 378        unsigned long *last_time;
 379        struct ieee80211_hdr_3addrqos *hdr_3addrqos;
 380        struct ieee80211_hdr_4addrqos *hdr_4addrqos;
 381        u8 tid;
 382
 383        //TO2DS and QoS
 384        if(((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS)&&IEEE80211_QOS_HAS_SEQ(fc)) {
 385          hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header;
 386          tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID;
 387          tid = UP2AC(tid);
 388          tid ++;
 389        } else if(IEEE80211_QOS_HAS_SEQ(fc)) { //QoS
 390          hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header;
 391          tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID;
 392          tid = UP2AC(tid);
 393          tid ++;
 394        } else { // no QoS
 395          tid = 0;
 396        }
 397        switch (ieee->iw_mode) {
 398        case IW_MODE_ADHOC:
 399        {
 400                struct list_head *p;
 401                struct ieee_ibss_seq *entry = NULL;
 402                u8 *mac = header->addr2;
 403                int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE;
 404                //for (pos = (head)->next; pos != (head); pos = pos->next)
 405                __list_for_each(p, &ieee->ibss_mac_hash[index]) {
 406                        entry = list_entry(p, struct ieee_ibss_seq, list);
 407                        if (!memcmp(entry->mac, mac, ETH_ALEN))
 408                                break;
 409                }
 410        //      if (memcmp(entry->mac, mac, ETH_ALEN)){
 411                if (p == &ieee->ibss_mac_hash[index]) {
 412                        entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC);
 413                        if (!entry) {
 414                                printk(KERN_WARNING "Cannot malloc new mac entry\n");
 415                                return 0;
 416                        }
 417                        memcpy(entry->mac, mac, ETH_ALEN);
 418                        entry->seq_num[tid] = seq;
 419                        entry->frag_num[tid] = frag;
 420                        entry->packet_time[tid] = jiffies;
 421                        list_add(&entry->list, &ieee->ibss_mac_hash[index]);
 422                        return 0;
 423                }
 424                last_seq = &entry->seq_num[tid];
 425                last_frag = &entry->frag_num[tid];
 426                last_time = &entry->packet_time[tid];
 427                break;
 428        }
 429
 430        case IW_MODE_INFRA:
 431                last_seq = &ieee->last_rxseq_num[tid];
 432                last_frag = &ieee->last_rxfrag_num[tid];
 433                last_time = &ieee->last_packet_time[tid];
 434
 435                break;
 436        default:
 437                return 0;
 438        }
 439
 440//      if(tid != 0) {
 441//              printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl);
 442//      }
 443        if ((*last_seq == seq) &&
 444            time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) {
 445                if (*last_frag == frag){
 446                        //printk(KERN_WARNING "[1] go drop!\n");
 447                        goto drop;
 448
 449                }
 450                if (*last_frag + 1 != frag)
 451                        /* out-of-order fragment */
 452                        //printk(KERN_WARNING "[2] go drop!\n");
 453                        goto drop;
 454        } else
 455                *last_seq = seq;
 456
 457        *last_frag = frag;
 458        *last_time = jiffies;
 459        return 0;
 460
 461drop:
 462//      BUG_ON(!(fc & IEEE80211_FCTL_RETRY));
 463//      printk("DUP\n");
 464
 465        return 1;
 466}
 467
 468
 469/* All received frames are sent to this function. @skb contains the frame in
 470 * IEEE 802.11 format, i.e., in the format it was sent over air.
 471 * This function is called only as a tasklet (software IRQ). */
 472int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
 473                 struct ieee80211_rx_stats *rx_stats)
 474{
 475        struct net_device *dev = ieee->dev;
 476        //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
 477        struct ieee80211_hdr_4addr *hdr;
 478
 479        size_t hdrlen;
 480        u16 fc, type, stype, sc;
 481        struct net_device_stats *stats;
 482        unsigned int frag;
 483        u8 *payload;
 484        u16 ethertype;
 485        u8 dst[ETH_ALEN];
 486        u8 src[ETH_ALEN];
 487        u8 bssid[ETH_ALEN];
 488        struct ieee80211_crypt_data *crypt = NULL;
 489        int keyidx = 0;
 490
 491        // cheat the the hdr type
 492        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 493        stats = &ieee->stats;
 494
 495        if (skb->len < 10) {
 496                printk(KERN_INFO "%s: SKB length < 10\n",
 497                       dev->name);
 498                goto rx_dropped;
 499        }
 500
 501        fc = le16_to_cpu(hdr->frame_ctl);
 502        type = WLAN_FC_GET_TYPE(fc);
 503        stype = WLAN_FC_GET_STYPE(fc);
 504        sc = le16_to_cpu(hdr->seq_ctl);
 505
 506        frag = WLAN_GET_SEQ_FRAG(sc);
 507
 508//YJ,add,080828,for keep alive
 509        if((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS)
 510        {
 511                if(!memcmp(hdr->addr1,dev->dev_addr, ETH_ALEN))
 512                {
 513                        ieee->NumRxUnicast++;
 514                }
 515        }
 516        else
 517        {
 518                if(!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN))
 519                {
 520                        ieee->NumRxUnicast++;
 521                }
 522        }
 523//YJ,add,080828,for keep alive,end
 524
 525        hdrlen = ieee80211_get_hdrlen(fc);
 526
 527
 528        if (ieee->iw_mode == IW_MODE_MONITOR) {
 529                ieee80211_monitor_rx(ieee, skb, rx_stats);
 530                stats->rx_packets++;
 531                stats->rx_bytes += skb->len;
 532                return 1;
 533        }
 534
 535        if (ieee->host_decrypt) {
 536                int idx = 0;
 537                if (skb->len >= hdrlen + 3)
 538                        idx = skb->data[hdrlen + 3] >> 6;
 539                crypt = ieee->crypt[idx];
 540
 541                /* allow NULL decrypt to indicate an station specific override
 542                 * for default encryption */
 543                if (crypt && (crypt->ops == NULL ||
 544                              crypt->ops->decrypt_mpdu == NULL))
 545                        crypt = NULL;
 546
 547                if (!crypt && (fc & IEEE80211_FCTL_WEP)) {
 548                        /* This seems to be triggered by some (multicast?)
 549                         * frames from other than current BSS, so just drop the
 550                         * frames silently instead of filling system log with
 551                         * these reports. */
 552                        IEEE80211_DEBUG_DROP("Decryption failed (not set)"
 553                                             " (SA=%pM)\n",
 554                                             hdr->addr2);
 555                        ieee->ieee_stats.rx_discards_undecryptable++;
 556                        goto rx_dropped;
 557                }
 558        }
 559
 560        if (skb->len < IEEE80211_DATA_HDR3_LEN)
 561                goto rx_dropped;
 562
 563        // if QoS enabled, should check the sequence for each of the AC
 564        if (is_duplicate_packet(ieee, hdr))
 565                goto rx_dropped;
 566
 567
 568        if (type == IEEE80211_FTYPE_MGMT) {
 569                if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
 570                        goto rx_dropped;
 571                else
 572                        goto rx_exit;
 573        }
 574
 575        /* Data frame - extract src/dst addresses */
 576        switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
 577        case IEEE80211_FCTL_FROMDS:
 578                memcpy(dst, hdr->addr1, ETH_ALEN);
 579                memcpy(src, hdr->addr3, ETH_ALEN);
 580                memcpy(bssid,hdr->addr2,ETH_ALEN);
 581                break;
 582        case IEEE80211_FCTL_TODS:
 583                memcpy(dst, hdr->addr3, ETH_ALEN);
 584                memcpy(src, hdr->addr2, ETH_ALEN);
 585                memcpy(bssid,hdr->addr1,ETH_ALEN);
 586                break;
 587        case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
 588                if (skb->len < IEEE80211_DATA_HDR4_LEN)
 589                        goto rx_dropped;
 590                memcpy(dst, hdr->addr3, ETH_ALEN);
 591                memcpy(src, hdr->addr4, ETH_ALEN);
 592                memcpy(bssid, ieee->current_network.bssid, ETH_ALEN);
 593                break;
 594        case 0:
 595                memcpy(dst, hdr->addr1, ETH_ALEN);
 596                memcpy(src, hdr->addr2, ETH_ALEN);
 597                memcpy(bssid,hdr->addr3,ETH_ALEN);
 598                break;
 599        }
 600
 601
 602        dev->last_rx = jiffies;
 603
 604
 605        /* Nullfunc frames may have PS-bit set, so they must be passed to
 606         * hostap_handle_sta_rx() before being dropped here. */
 607        if (stype != IEEE80211_STYPE_DATA &&
 608            stype != IEEE80211_STYPE_DATA_CFACK &&
 609            stype != IEEE80211_STYPE_DATA_CFPOLL &&
 610            stype != IEEE80211_STYPE_DATA_CFACKPOLL&&
 611            stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4
 612            ) {
 613                if (stype != IEEE80211_STYPE_NULLFUNC)
 614                        IEEE80211_DEBUG_DROP(
 615                                "RX: dropped data frame "
 616                                "with no data (type=0x%02x, "
 617                                "subtype=0x%02x, len=%d)\n",
 618                                type, stype, skb->len);
 619                goto rx_dropped;
 620        }
 621        if(memcmp(bssid,ieee->current_network.bssid,ETH_ALEN)) {
 622                goto rx_dropped;
 623        }
 624
 625        ieee->NumRxDataInPeriod++;
 626        ieee->NumRxOkTotal++;
 627        /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
 628
 629        if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
 630            (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
 631                goto rx_dropped;
 632
 633        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 634
 635        /* skb: hdr + (possibly fragmented) plaintext payload */
 636        // PR: FIXME: hostap has additional conditions in the "if" below:
 637        // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
 638        if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) {
 639                int flen;
 640                struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
 641                IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
 642
 643                if (!frag_skb) {
 644                        IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
 645                                        "Rx cannot get skb from fragment "
 646                                        "cache (morefrag=%d seq=%u frag=%u)\n",
 647                                        (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
 648                                        WLAN_GET_SEQ_SEQ(sc), frag);
 649                        goto rx_dropped;
 650                }
 651                flen = skb->len;
 652                if (frag != 0)
 653                        flen -= hdrlen;
 654
 655                if (frag_skb->tail + flen > frag_skb->end) {
 656                        printk(KERN_WARNING "%s: host decrypted and "
 657                               "reassembled frame did not fit skb\n",
 658                               dev->name);
 659                        ieee80211_frag_cache_invalidate(ieee, hdr);
 660                        goto rx_dropped;
 661                }
 662
 663                if (frag == 0) {
 664                        /* copy first fragment (including full headers) into
 665                         * beginning of the fragment cache skb */
 666                        memcpy(skb_put(frag_skb, flen), skb->data, flen);
 667                } else {
 668                        /* append frame payload to the end of the fragment
 669                         * cache skb */
 670                        memcpy(skb_put(frag_skb, flen), skb->data + hdrlen,
 671                               flen);
 672                }
 673                dev_kfree_skb_any(skb);
 674                skb = NULL;
 675
 676                if (fc & IEEE80211_FCTL_MOREFRAGS) {
 677                        /* more fragments expected - leave the skb in fragment
 678                         * cache for now; it will be delivered to upper layers
 679                         * after all fragments have been received */
 680                        goto rx_exit;
 681                }
 682
 683                /* this was the last fragment and the frame will be
 684                 * delivered, so remove skb from fragment cache */
 685                skb = frag_skb;
 686                hdr = (struct ieee80211_hdr_4addr *)skb->data;
 687                ieee80211_frag_cache_invalidate(ieee, hdr);
 688        }
 689
 690        /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
 691         * encrypted/authenticated */
 692        if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
 693            ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
 694                goto rx_dropped;
 695
 696        hdr = (struct ieee80211_hdr_4addr *)skb->data;
 697        if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
 698                if (/*ieee->ieee802_1x &&*/
 699                    ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 700
 701#ifdef CONFIG_IEEE80211_DEBUG
 702                        /* pass unencrypted EAPOL frames even if encryption is
 703                         * configured */
 704                        struct eapol *eap = (struct eapol *)(skb->data +
 705                                24);
 706                        IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
 707                                                eap_get_type(eap->type));
 708#endif
 709                } else {
 710                        IEEE80211_DEBUG_DROP(
 711                                "encryption configured, but RX "
 712                                "frame not encrypted (SA=%pM)\n",
 713                                hdr->addr2);
 714                        goto rx_dropped;
 715                }
 716        }
 717
 718#ifdef CONFIG_IEEE80211_DEBUG
 719        if (crypt && !(fc & IEEE80211_FCTL_WEP) &&
 720            ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 721                        struct eapol *eap = (struct eapol *)(skb->data +
 722                                24);
 723                        IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n",
 724                                                eap_get_type(eap->type));
 725        }
 726#endif
 727
 728        if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep &&
 729            !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 730                IEEE80211_DEBUG_DROP(
 731                        "dropped unencrypted RX data "
 732                        "frame from %pM"
 733                        " (drop_unencrypted=1)\n",
 734                        hdr->addr2);
 735                goto rx_dropped;
 736        }
 737/*
 738        if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
 739                printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n");
 740        }
 741*/
 742        /* skb: hdr + (possible reassembled) full plaintext payload */
 743        payload = skb->data + hdrlen;
 744        ethertype = (payload[6] << 8) | payload[7];
 745
 746
 747        /* convert hdr + possible LLC headers into Ethernet header */
 748        if (skb->len - hdrlen >= 8 &&
 749            ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
 750              ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
 751             memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
 752                /* remove RFC1042 or Bridge-Tunnel encapsulation and
 753                 * replace EtherType */
 754                skb_pull(skb, hdrlen + SNAP_SIZE);
 755                memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
 756                memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
 757        } else {
 758                u16 len;
 759                /* Leave Ethernet header part of hdr and full payload */
 760                skb_pull(skb, hdrlen);
 761                len = htons(skb->len);
 762                memcpy(skb_push(skb, 2), &len, 2);
 763                memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
 764                memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
 765        }
 766
 767
 768        stats->rx_packets++;
 769        stats->rx_bytes += skb->len;
 770
 771        if (skb) {
 772                skb->protocol = eth_type_trans(skb, dev);
 773                memset(skb->cb, 0, sizeof(skb->cb));
 774                skb->dev = dev;
 775                skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
 776                ieee->last_rx_ps_time = jiffies;
 777                netif_rx(skb);
 778        }
 779
 780 rx_exit:
 781        return 1;
 782
 783 rx_dropped:
 784        stats->rx_dropped++;
 785
 786        /* Returning 0 indicates to caller that we have not handled the SKB--
 787         * so it is still allocated and can be used again by underlying
 788         * hardware as a DMA target */
 789        return 0;
 790}
 791
 792#define MGMT_FRAME_FIXED_PART_LENGTH            0x24
 793
 794static inline int ieee80211_is_ofdm_rate(u8 rate)
 795{
 796        switch (rate & ~IEEE80211_BASIC_RATE_MASK) {
 797        case IEEE80211_OFDM_RATE_6MB:
 798        case IEEE80211_OFDM_RATE_9MB:
 799        case IEEE80211_OFDM_RATE_12MB:
 800        case IEEE80211_OFDM_RATE_18MB:
 801        case IEEE80211_OFDM_RATE_24MB:
 802        case IEEE80211_OFDM_RATE_36MB:
 803        case IEEE80211_OFDM_RATE_48MB:
 804        case IEEE80211_OFDM_RATE_54MB:
 805                return 1;
 806        }
 807        return 0;
 808}
 809
 810static inline int ieee80211_SignalStrengthTranslate(
 811        int  CurrSS
 812        )
 813{
 814        int RetSS;
 815
 816        // Step 1. Scale mapping.
 817        if(CurrSS >= 71 && CurrSS <= 100)
 818        {
 819                RetSS = 90 + ((CurrSS - 70) / 3);
 820        }
 821        else if(CurrSS >= 41 && CurrSS <= 70)
 822        {
 823                RetSS = 78 + ((CurrSS - 40) / 3);
 824        }
 825        else if(CurrSS >= 31 && CurrSS <= 40)
 826        {
 827                RetSS = 66 + (CurrSS - 30);
 828        }
 829        else if(CurrSS >= 21 && CurrSS <= 30)
 830        {
 831                RetSS = 54 + (CurrSS - 20);
 832        }
 833        else if(CurrSS >= 5 && CurrSS <= 20)
 834        {
 835                RetSS = 42 + (((CurrSS - 5) * 2) / 3);
 836        }
 837        else if(CurrSS == 4)
 838        {
 839                RetSS = 36;
 840        }
 841        else if(CurrSS == 3)
 842        {
 843                RetSS = 27;
 844        }
 845        else if(CurrSS == 2)
 846        {
 847                RetSS = 18;
 848        }
 849        else if(CurrSS == 1)
 850        {
 851                RetSS = 9;
 852        }
 853        else
 854        {
 855                RetSS = CurrSS;
 856        }
 857        //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
 858
 859        // Step 2. Smoothing.
 860
 861        //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing:  LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS));
 862
 863        return RetSS;
 864}
 865
 866static inline void ieee80211_extract_country_ie(
 867        struct ieee80211_device *ieee,
 868        struct ieee80211_info_element *info_element,
 869        struct ieee80211_network *network,
 870        u8 * addr2
 871)
 872{
 873        if(IS_DOT11D_ENABLE(ieee))
 874        {
 875                if(info_element->len!= 0)
 876                {
 877                        memcpy(network->CountryIeBuf, info_element->data, info_element->len);
 878                        network->CountryIeLen = info_element->len;
 879
 880                        if(!IS_COUNTRY_IE_VALID(ieee))
 881                        {
 882                                Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data);
 883                        }
 884                }
 885
 886                //
 887                // 070305, rcnjko: I update country IE watch dog here because
 888                // some AP (e.g. Cisco 1242) don't include country IE in their
 889                // probe response frame.
 890                //
 891                if(IS_EQUAL_CIE_SRC(ieee, addr2) )
 892                {
 893                        UPDATE_CIE_WATCHDOG(ieee);
 894                }
 895        }
 896
 897}
 898
 899int
 900ieee80211_TranslateToDbm(
 901        unsigned char SignalStrengthIndex       // 0-100 index.
 902        )
 903{
 904        unsigned char SignalPower; // in dBm.
 905
 906        // Translate to dBm (x=0.5y-95).
 907        SignalPower = (int)SignalStrengthIndex * 7 / 10;
 908        SignalPower -= 95;
 909
 910        return SignalPower;
 911}
 912inline int ieee80211_network_init(
 913        struct ieee80211_device *ieee,
 914        struct ieee80211_probe_response *beacon,
 915        struct ieee80211_network *network,
 916        struct ieee80211_rx_stats *stats)
 917{
 918#ifdef CONFIG_IEEE80211_DEBUG
 919        char rates_str[64];
 920        char *p;
 921#endif
 922        struct ieee80211_info_element *info_element;
 923        u16 left;
 924        u8 i;
 925        short offset;
 926        u8 curRate = 0,hOpRate = 0,curRate_ex = 0;
 927
 928        /* Pull out fixed field data */
 929        memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
 930        network->capability = beacon->capability;
 931        network->last_scanned = jiffies;
 932        network->time_stamp[0] = beacon->time_stamp[0];
 933        network->time_stamp[1] = beacon->time_stamp[1];
 934        network->beacon_interval = beacon->beacon_interval;
 935        /* Where to pull this? beacon->listen_interval;*/
 936        network->listen_interval = 0x0A;
 937        network->rates_len = network->rates_ex_len = 0;
 938        network->last_associate = 0;
 939        network->ssid_len = 0;
 940        network->flags = 0;
 941        network->atim_window = 0;
 942        network->QoS_Enable = 0;
 943//by amy 080312
 944        network->HighestOperaRate = 0;
 945//by amy 080312
 946        network->Turbo_Enable = 0;
 947        network->CountryIeLen = 0;
 948        memset(network->CountryIeBuf, 0, MAX_IE_LEN);
 949
 950        if (stats->freq == IEEE80211_52GHZ_BAND) {
 951                /* for A band (No DS info) */
 952                network->channel = stats->received_channel;
 953        } else
 954                network->flags |= NETWORK_HAS_CCK;
 955
 956        network->wpa_ie_len = 0;
 957        network->rsn_ie_len = 0;
 958
 959        info_element = &beacon->info_element;
 960        left = stats->len - ((void *)info_element - (void *)beacon);
 961        while (left >= sizeof(struct ieee80211_info_element_hdr)) {
 962                if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) {
 963                        IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n",
 964                                             info_element->len + sizeof(struct ieee80211_info_element),
 965                                             left);
 966                        return 1;
 967                }
 968
 969                switch (info_element->id) {
 970                case MFIE_TYPE_SSID:
 971                        if (ieee80211_is_empty_essid(info_element->data,
 972                                                     info_element->len)) {
 973                                network->flags |= NETWORK_EMPTY_ESSID;
 974                                break;
 975                        }
 976
 977                        network->ssid_len = min(info_element->len,
 978                                                (u8)IW_ESSID_MAX_SIZE);
 979                        memcpy(network->ssid, info_element->data, network->ssid_len);
 980                        if (network->ssid_len < IW_ESSID_MAX_SIZE)
 981                                memset(network->ssid + network->ssid_len, 0,
 982                                       IW_ESSID_MAX_SIZE - network->ssid_len);
 983
 984                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n",
 985                                             network->ssid, network->ssid_len);
 986                        break;
 987
 988                case MFIE_TYPE_RATES:
 989#ifdef CONFIG_IEEE80211_DEBUG
 990                        p = rates_str;
 991#endif
 992                        network->rates_len = min(info_element->len, MAX_RATES_LENGTH);
 993                        for (i = 0; i < network->rates_len; i++) {
 994                                network->rates[i] = info_element->data[i];
 995                                curRate = network->rates[i] & 0x7f;
 996                                if( hOpRate < curRate )
 997                                        hOpRate = curRate;
 998#ifdef CONFIG_IEEE80211_DEBUG
 999                                p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
1000#endif
1001                                if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1002                                        network->flags |= NETWORK_HAS_OFDM;
1003                                        if (info_element->data[i] &
1004                                            IEEE80211_BASIC_RATE_MASK)
1005                                                network->flags &=
1006                                                        ~NETWORK_HAS_CCK;
1007                                }
1008                        }
1009
1010                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n",
1011                                             rates_str, network->rates_len);
1012                        break;
1013
1014                case MFIE_TYPE_RATES_EX:
1015#ifdef CONFIG_IEEE80211_DEBUG
1016                        p = rates_str;
1017#endif
1018                        network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH);
1019                        for (i = 0; i < network->rates_ex_len; i++) {
1020                                network->rates_ex[i] = info_element->data[i];
1021                                curRate_ex = network->rates_ex[i] & 0x7f;
1022                                if( hOpRate < curRate_ex )
1023                                        hOpRate = curRate_ex;
1024#ifdef CONFIG_IEEE80211_DEBUG
1025                                p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]);
1026#endif
1027                                if (ieee80211_is_ofdm_rate(info_element->data[i])) {
1028                                        network->flags |= NETWORK_HAS_OFDM;
1029                                        if (info_element->data[i] &
1030                                            IEEE80211_BASIC_RATE_MASK)
1031                                                network->flags &=
1032                                                        ~NETWORK_HAS_CCK;
1033                                }
1034                        }
1035
1036                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
1037                                             rates_str, network->rates_ex_len);
1038                        break;
1039
1040                case MFIE_TYPE_DS_SET:
1041                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n",
1042                                             info_element->data[0]);
1043                        if (stats->freq == IEEE80211_24GHZ_BAND)
1044                                network->channel = info_element->data[0];
1045                        break;
1046
1047                case MFIE_TYPE_FH_SET:
1048                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n");
1049                        break;
1050
1051                case MFIE_TYPE_CF_SET:
1052                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n");
1053                        break;
1054
1055                case MFIE_TYPE_TIM:
1056
1057                        if(info_element->len < 4)
1058                                break;
1059
1060                        network->dtim_period = info_element->data[1];
1061
1062                        if(ieee->state != IEEE80211_LINKED)
1063                                break;
1064
1065                        network->last_dtim_sta_time[0] = jiffies;
1066                        network->last_dtim_sta_time[1] = stats->mac_time[1];
1067
1068                        network->dtim_data = IEEE80211_DTIM_VALID;
1069
1070                        if(info_element->data[0] != 0)
1071                                break;
1072
1073                        if(info_element->data[2] & 1)
1074                                network->dtim_data |= IEEE80211_DTIM_MBCAST;
1075
1076                        offset = (info_element->data[2] >> 1)*2;
1077
1078                        //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id);
1079
1080                        /* add and modified for ps 2008.1.22 */
1081                        if(ieee->assoc_id < 8*offset ||
1082                                ieee->assoc_id > 8*(offset + info_element->len -3)) {
1083                                break;
1084                        }
1085
1086                        offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ;
1087
1088                //      printk("offset:%x data:%x, ucast:%d\n", offset,
1089                        //      info_element->data[3+offset] ,
1090                        //      info_element->data[3+offset] & (1<<(ieee->assoc_id%8)));
1091
1092                        if(info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) {
1093                                network->dtim_data |= IEEE80211_DTIM_UCAST;
1094                        }
1095                        break;
1096
1097                case MFIE_TYPE_IBSS_SET:
1098                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n");
1099                        break;
1100
1101                case MFIE_TYPE_CHALLENGE:
1102                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n");
1103                        break;
1104
1105                case MFIE_TYPE_GENERIC:
1106                        //nic is 87B
1107                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n",
1108                                             info_element->len);
1109                        if (info_element->len >= 4  &&
1110                            info_element->data[0] == 0x00 &&
1111                            info_element->data[1] == 0x50 &&
1112                            info_element->data[2] == 0xf2 &&
1113                            info_element->data[3] == 0x01) {
1114                                network->wpa_ie_len = min(info_element->len + 2,
1115                                                         MAX_WPA_IE_LEN);
1116                                memcpy(network->wpa_ie, info_element,
1117                                       network->wpa_ie_len);
1118                        }
1119
1120                        if (info_element->len == 7 &&
1121                            info_element->data[0] == 0x00 &&
1122                            info_element->data[1] == 0xe0 &&
1123                            info_element->data[2] == 0x4c &&
1124                            info_element->data[3] == 0x01 &&
1125                            info_element->data[4] == 0x02) {
1126                                network->Turbo_Enable = 1;
1127                        }
1128                        if (1 == stats->nic_type) {//nic 87
1129                                break;
1130                        }
1131
1132                        if (info_element->len >= 5  &&
1133                            info_element->data[0] == 0x00 &&
1134                            info_element->data[1] == 0x50 &&
1135                            info_element->data[2] == 0xf2 &&
1136                            info_element->data[3] == 0x02 &&
1137                            info_element->data[4] == 0x00) {
1138                                //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]);
1139                                //WMM Information Element
1140                                network->wmm_info = info_element->data[6];
1141                                network->QoS_Enable = 1;
1142                        }
1143
1144                        if (info_element->len >= 8  &&
1145                            info_element->data[0] == 0x00 &&
1146                            info_element->data[1] == 0x50 &&
1147                            info_element->data[2] == 0xf2 &&
1148                            info_element->data[3] == 0x02 &&
1149                            info_element->data[4] == 0x01) {
1150                                // Not care about version at present.
1151                                //WMM Information Element
1152                                //printk(KERN_WARNING "wmm info&param updated: %x\n", info_element->data[6]);
1153                                network->wmm_info = info_element->data[6];
1154                                //WMM Parameter Element
1155                                memcpy(network->wmm_param, (u8 *)(info_element->data + 8),(info_element->len - 8));
1156                                network->QoS_Enable = 1;
1157                        }
1158                        break;
1159
1160                case MFIE_TYPE_RSN:
1161                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n",
1162                                             info_element->len);
1163                        network->rsn_ie_len = min(info_element->len + 2,
1164                                                 MAX_WPA_IE_LEN);
1165                        memcpy(network->rsn_ie, info_element,
1166                               network->rsn_ie_len);
1167                        break;
1168                case MFIE_TYPE_COUNTRY:
1169                        IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n",
1170                                             info_element->len);
1171//                      printk("=====>Receive <%s> Country IE\n",network->ssid);
1172                        ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2);
1173                        break;
1174                default:
1175                        IEEE80211_DEBUG_SCAN("unsupported IE %d\n",
1176                                             info_element->id);
1177                        break;
1178                }
1179
1180                left -= sizeof(struct ieee80211_info_element_hdr) +
1181                        info_element->len;
1182                info_element = (struct ieee80211_info_element *)
1183                        &info_element->data[info_element->len];
1184        }
1185//by amy 080312
1186        network->HighestOperaRate = hOpRate;
1187//by amy 080312
1188        network->mode = 0;
1189        if (stats->freq == IEEE80211_52GHZ_BAND)
1190                network->mode = IEEE_A;
1191        else {
1192                if (network->flags & NETWORK_HAS_OFDM)
1193                        network->mode |= IEEE_G;
1194                if (network->flags & NETWORK_HAS_CCK)
1195                        network->mode |= IEEE_B;
1196        }
1197
1198        if (network->mode == 0) {
1199                IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
1200                                     "network.\n",
1201                                     escape_essid(network->ssid,
1202                                                  network->ssid_len),
1203                                     network->bssid);
1204                return 1;
1205        }
1206
1207        if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1208                network->flags |= NETWORK_EMPTY_ESSID;
1209
1210        stats->signal = ieee80211_TranslateToDbm(stats->signalstrength);
1211        //stats->noise = stats->signal - stats->noise;
1212        stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25;
1213        memcpy(&network->stats, stats, sizeof(network->stats));
1214
1215        return 0;
1216}
1217
1218static inline int is_same_network(struct ieee80211_network *src,
1219                                  struct ieee80211_network *dst,
1220                                  struct ieee80211_device * ieee)
1221{
1222        /* A network is only a duplicate if the channel, BSSID, ESSID
1223         * and the capability field (in particular IBSS and BSS) all match.
1224         * We treat all <hidden> with the same BSSID and channel
1225         * as one network */
1226        return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&  //YJ,mod,080819,for hidden ap
1227                //((src->ssid_len == dst->ssid_len) &&
1228                (src->channel == dst->channel) &&
1229                !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1230                (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap
1231                //!memcmp(src->ssid, dst->ssid, src->ssid_len) &&
1232                ((src->capability & WLAN_CAPABILITY_IBSS) ==
1233                (dst->capability & WLAN_CAPABILITY_IBSS)) &&
1234                ((src->capability & WLAN_CAPABILITY_BSS) ==
1235                (dst->capability & WLAN_CAPABILITY_BSS)));
1236}
1237
1238inline void update_network(struct ieee80211_network *dst,
1239                                  struct ieee80211_network *src)
1240{
1241        unsigned char quality = src->stats.signalstrength;
1242        unsigned char signal = 0;
1243        unsigned char noise = 0;
1244        if(dst->stats.signalstrength > 0) {
1245                quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6;
1246        }
1247        signal = ieee80211_TranslateToDbm(quality);
1248        //noise = signal - src->stats.noise;
1249        if(dst->stats.noise > 0)
1250                noise = (dst->stats.noise * 5 + src->stats.noise)/6;
1251        //if(strcmp(dst->ssid, "linksys_lzm000") == 0)
1252//      printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal);
1253        memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1254        dst->stats.signalstrength = quality;
1255        dst->stats.signal = signal;
1256//      printk("==================>stats.signal is %d\n",dst->stats.signal);
1257        dst->stats.noise = noise;
1258
1259
1260        dst->capability = src->capability;
1261        memcpy(dst->rates, src->rates, src->rates_len);
1262        dst->rates_len = src->rates_len;
1263        memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
1264        dst->rates_ex_len = src->rates_ex_len;
1265        dst->HighestOperaRate= src->HighestOperaRate;
1266        //printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel);
1267
1268        //YJ,add,080819,for hidden ap
1269        if(src->ssid_len > 0)
1270        {
1271                //if(src->ssid_len == 13)
1272                //      printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid);
1273                memset(dst->ssid, 0, dst->ssid_len);
1274                dst->ssid_len = src->ssid_len;
1275                memcpy(dst->ssid, src->ssid, src->ssid_len);
1276        }
1277        //YJ,add,080819,for hidden ap,end
1278
1279        dst->channel = src->channel;
1280        dst->mode = src->mode;
1281        dst->flags = src->flags;
1282        dst->time_stamp[0] = src->time_stamp[0];
1283        dst->time_stamp[1] = src->time_stamp[1];
1284
1285        dst->beacon_interval = src->beacon_interval;
1286        dst->listen_interval = src->listen_interval;
1287        dst->atim_window = src->atim_window;
1288        dst->dtim_period = src->dtim_period;
1289        dst->dtim_data = src->dtim_data;
1290        dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0];
1291        dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1];
1292//      printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data);
1293        memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1294        dst->wpa_ie_len = src->wpa_ie_len;
1295        memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
1296        dst->rsn_ie_len = src->rsn_ie_len;
1297
1298        dst->last_scanned = jiffies;
1299        /* dst->last_associate is not overwritten */
1300// disable QoS process now, added by David 2006/7/25
1301#if 1
1302        dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame.
1303/*
1304        if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter
1305          memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN);
1306        }
1307*/
1308        if(src->wmm_param[0].ac_aci_acm_aifsn|| \
1309           src->wmm_param[1].ac_aci_acm_aifsn|| \
1310           src->wmm_param[2].ac_aci_acm_aifsn|| \
1311           src->wmm_param[3].ac_aci_acm_aifsn) {
1312          memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN);
1313        }
1314        dst->QoS_Enable = src->QoS_Enable;
1315#else
1316        dst->QoS_Enable = 1;//for Rtl8187 simulation
1317#endif
1318        dst->SignalStrength = src->SignalStrength;
1319        dst->Turbo_Enable = src->Turbo_Enable;
1320        dst->CountryIeLen = src->CountryIeLen;
1321        memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen);
1322}
1323
1324
1325inline void ieee80211_process_probe_response(
1326        struct ieee80211_device *ieee,
1327        struct ieee80211_probe_response *beacon,
1328        struct ieee80211_rx_stats *stats)
1329{
1330        struct ieee80211_network network;
1331        struct ieee80211_network *target;
1332        struct ieee80211_network *oldest = NULL;
1333#ifdef CONFIG_IEEE80211_DEBUG
1334        struct ieee80211_info_element *info_element = &beacon->info_element;
1335#endif
1336        unsigned long flags;
1337        short renew;
1338        u8 wmm_info;
1339        u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON)? 1:0;  //YJ,add,080819,for hidden ap
1340
1341        memset(&network, 0, sizeof(struct ieee80211_network));
1342
1343        IEEE80211_DEBUG_SCAN(
1344                "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
1345                escape_essid(info_element->data, info_element->len),
1346                beacon->header.addr3,
1347                (beacon->capability & (1<<0xf)) ? '1' : '0',
1348                (beacon->capability & (1<<0xe)) ? '1' : '0',
1349                (beacon->capability & (1<<0xd)) ? '1' : '0',
1350                (beacon->capability & (1<<0xc)) ? '1' : '0',
1351                (beacon->capability & (1<<0xb)) ? '1' : '0',
1352                (beacon->capability & (1<<0xa)) ? '1' : '0',
1353                (beacon->capability & (1<<0x9)) ? '1' : '0',
1354                (beacon->capability & (1<<0x8)) ? '1' : '0',
1355                (beacon->capability & (1<<0x7)) ? '1' : '0',
1356                (beacon->capability & (1<<0x6)) ? '1' : '0',
1357                (beacon->capability & (1<<0x5)) ? '1' : '0',
1358                (beacon->capability & (1<<0x4)) ? '1' : '0',
1359                (beacon->capability & (1<<0x3)) ? '1' : '0',
1360                (beacon->capability & (1<<0x2)) ? '1' : '0',
1361                (beacon->capability & (1<<0x1)) ? '1' : '0',
1362                (beacon->capability & (1<<0x0)) ? '1' : '0');
1363
1364        if (ieee80211_network_init(ieee, beacon, &network, stats)) {
1365                IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
1366                                     escape_essid(info_element->data,
1367                                                  info_element->len),
1368                                     beacon->header.addr3,
1369                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1370                                     IEEE80211_STYPE_PROBE_RESP ?
1371                                     "PROBE RESPONSE" : "BEACON");
1372                return;
1373        }
1374
1375        // For Asus EeePc request,
1376        // (1) if wireless adapter receive get any 802.11d country code in AP beacon,
1377        //         wireless adapter should follow the country code.
1378        // (2)  If there is no any country code in beacon,
1379        //       then wireless adapter should do active scan from ch1~11 and
1380        //       passive scan from ch12~14
1381        if(ieee->bGlobalDomain)
1382        {
1383                if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
1384                {
1385                        // Case 1: Country code
1386                        if(IS_COUNTRY_IE_VALID(ieee) )
1387                        {
1388                                if( !IsLegalChannel(ieee, network.channel) )
1389                                {
1390                                        printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel);
1391                                        return;
1392                                }
1393                        }
1394                        // Case 2: No any country code.
1395                        else
1396                        {
1397                                // Filter over channel ch12~14
1398                                if(network.channel > 11)
1399                                {
1400                                        printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel);
1401                                        return;
1402                                }
1403                        }
1404                }
1405                else
1406                {
1407                        // Case 1: Country code
1408                        if(IS_COUNTRY_IE_VALID(ieee) )
1409                        {
1410                                if( !IsLegalChannel(ieee, network.channel) )
1411                                {
1412                                        printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n",network.channel);
1413                                        return;
1414                                }
1415                        }
1416                        // Case 2: No any country code.
1417                        else
1418                        {
1419                                // Filter over channel ch12~14
1420                                if(network.channel > 14)
1421                                {
1422                                        printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n",network.channel);
1423                                        return;
1424                                }
1425                        }
1426                }
1427        }
1428        /* The network parsed correctly -- so now we scan our known networks
1429         * to see if we can find it in our list.
1430         *
1431         * NOTE:  This search is definitely not optimized.  Once its doing
1432         *        the "right thing" we'll optimize it for efficiency if
1433         *        necessary */
1434
1435        /* Search for this entry in the list and update it if it is
1436         * already there. */
1437
1438        spin_lock_irqsave(&ieee->lock, flags);
1439
1440        if(is_same_network(&ieee->current_network, &network, ieee)) {
1441                wmm_info = ieee->current_network.wmm_info;
1442                //YJ,add,080819,for hidden ap
1443                if(is_beacon == 0)
1444                        network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags);
1445                else if(ieee->state == IEEE80211_LINKED)
1446                        ieee->NumRxBcnInPeriod++;
1447                //YJ,add,080819,for hidden ap,end
1448                //printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid);
1449                update_network(&ieee->current_network, &network);
1450        }
1451
1452        list_for_each_entry(target, &ieee->network_list, list) {
1453                if (is_same_network(target, &network, ieee))
1454                        break;
1455                if ((oldest == NULL) ||
1456                    (target->last_scanned < oldest->last_scanned))
1457                        oldest = target;
1458        }
1459
1460        /* If we didn't find a match, then get a new network slot to initialize
1461         * with this beacon's information */
1462        if (&target->list == &ieee->network_list) {
1463                if (list_empty(&ieee->network_free_list)) {
1464                        /* If there are no more slots, expire the oldest */
1465                        list_del(&oldest->list);
1466                        target = oldest;
1467                        IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
1468                                             "network list.\n",
1469                                             escape_essid(target->ssid,
1470                                                          target->ssid_len),
1471                                             target->bssid);
1472                } else {
1473                        /* Otherwise just pull from the free list */
1474                        target = list_entry(ieee->network_free_list.next,
1475                                            struct ieee80211_network, list);
1476                        list_del(ieee->network_free_list.next);
1477                }
1478
1479
1480#ifdef CONFIG_IEEE80211_DEBUG
1481                IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
1482                                     escape_essid(network.ssid,
1483                                                  network.ssid_len),
1484                                     network.bssid,
1485                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1486                                     IEEE80211_STYPE_PROBE_RESP ?
1487                                     "PROBE RESPONSE" : "BEACON");
1488#endif
1489
1490                memcpy(target, &network, sizeof(*target));
1491                list_add_tail(&target->list, &ieee->network_list);
1492        } else {
1493                IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
1494                                     escape_essid(target->ssid,
1495                                                  target->ssid_len),
1496                                     target->bssid,
1497                                     WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
1498                                     IEEE80211_STYPE_PROBE_RESP ?
1499                                     "PROBE RESPONSE" : "BEACON");
1500
1501                /* we have an entry and we are going to update it. But this entry may
1502                 * be already expired. In this case we do the same as we found a new
1503                 * net and call the new_net handler
1504                 */
1505                renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
1506                //YJ,add,080819,for hidden ap
1507                if(is_beacon == 0)
1508                        network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
1509                //if(strncmp(network.ssid, "linksys-c",9) == 0)
1510                //      printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
1511                if(((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \
1512                    && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\
1513                    ||((ieee->current_network.ssid_len == network.ssid_len)&&(strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0)&&(ieee->state == IEEE80211_NOLINK))))
1514                        renew = 1;
1515                //YJ,add,080819,for hidden ap,end
1516                update_network(target, &network);
1517        }
1518
1519        spin_unlock_irqrestore(&ieee->lock, flags);
1520}
1521
1522void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1523                      struct ieee80211_hdr_4addr *header,
1524                      struct ieee80211_rx_stats *stats)
1525{
1526        switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1527
1528        case IEEE80211_STYPE_BEACON:
1529                IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1530                                     WLAN_FC_GET_STYPE(header->frame_ctl));
1531                IEEE80211_DEBUG_SCAN("Beacon\n");
1532                ieee80211_process_probe_response(
1533                        ieee, (struct ieee80211_probe_response *)header, stats);
1534                break;
1535
1536        case IEEE80211_STYPE_PROBE_RESP:
1537                IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1538                                     WLAN_FC_GET_STYPE(header->frame_ctl));
1539                IEEE80211_DEBUG_SCAN("Probe response\n");
1540                ieee80211_process_probe_response(
1541                        ieee, (struct ieee80211_probe_response *)header, stats);
1542                break;
1543        }
1544}
1545