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