root/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ieee80211_monitor_rx
  2. ieee80211_frag_cache_find
  3. ieee80211_frag_cache_get
  4. ieee80211_frag_cache_invalidate
  5. ieee80211_rx_frame_mgmt
  6. ieee80211_is_eapol_frame
  7. ieee80211_rx_frame_decrypt
  8. ieee80211_rx_frame_decrypt_msdu
  9. is_duplicate_packet
  10. AddReorderEntry
  11. ieee80211_indicate_packets
  12. RxReorderIndicatePacket
  13. parse_subframe
  14. ieee80211_rx
  15. ieee80211_verify_qos_info
  16. ieee80211_read_qos_param_element
  17. ieee80211_read_qos_info_element
  18. ieee80211_qos_convert_ac_to_parameters
  19. ieee80211_parse_qos_info_param_IE
  20. get_info_element_string
  21. ieee80211_extract_country_ie
  22. ieee80211_parse_info_param
  23. ieee80211_SignalStrengthTranslate
  24. ieee80211_translate_todbm
  25. ieee80211_network_init
  26. is_same_network
  27. update_network
  28. is_beacon
  29. ieee80211_process_probe_response
  30. ieee80211_rx_mgt

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

/* [<][>][^][v][top][bottom][index][help] */