aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/ieee80211_rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211/ieee80211_rx.c')
-rw-r--r--net/ieee80211/ieee80211_rx.c610
1 files changed, 464 insertions, 146 deletions
diff --git a/net/ieee80211/ieee80211_rx.c b/net/ieee80211/ieee80211_rx.c
index f7dcd854139e..ce694cf5c160 100644
--- a/net/ieee80211/ieee80211_rx.c
+++ b/net/ieee80211/ieee80211_rx.c
@@ -5,7 +5,7 @@
5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen 5 * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
6 * <jkmaline@cc.hut.fi> 6 * <jkmaline@cc.hut.fi>
7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi> 7 * Copyright (c) 2002-2003, Jouni Malinen <jkmaline@cc.hut.fi>
8 * Copyright (c) 2004, Intel Corporation 8 * Copyright (c) 2004-2005, Intel Corporation
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as 11 * it under the terms of the GNU General Public License version 2 as
@@ -87,7 +87,7 @@ static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
87 87
88/* Called only as a tasklet (software IRQ) */ 88/* Called only as a tasklet (software IRQ) */
89static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee, 89static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
90 struct ieee80211_hdr *hdr) 90 struct ieee80211_hdr_4addr *hdr)
91{ 91{
92 struct sk_buff *skb = NULL; 92 struct sk_buff *skb = NULL;
93 u16 sc; 93 u16 sc;
@@ -101,7 +101,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
101 if (frag == 0) { 101 if (frag == 0) {
102 /* Reserve enough space to fit maximum frame length */ 102 /* Reserve enough space to fit maximum frame length */
103 skb = dev_alloc_skb(ieee->dev->mtu + 103 skb = dev_alloc_skb(ieee->dev->mtu +
104 sizeof(struct ieee80211_hdr) + 104 sizeof(struct ieee80211_hdr_4addr) +
105 8 /* LLC */ + 105 8 /* LLC */ +
106 2 /* alignment */ + 106 2 /* alignment */ +
107 8 /* WEP */ + ETH_ALEN /* WDS */ ); 107 8 /* WEP */ + ETH_ALEN /* WDS */ );
@@ -138,7 +138,7 @@ static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
138 138
139/* Called only as a tasklet (software IRQ) */ 139/* Called only as a tasklet (software IRQ) */
140static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, 140static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
141 struct ieee80211_hdr *hdr) 141 struct ieee80211_hdr_4addr *hdr)
142{ 142{
143 u16 sc; 143 u16 sc;
144 unsigned int seq; 144 unsigned int seq;
@@ -176,7 +176,7 @@ ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
176 ieee->dev->name); 176 ieee->dev->name);
177 return 0; 177 return 0;
178/* 178/*
179 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr *) 179 hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
180 skb->data);*/ 180 skb->data);*/
181 } 181 }
182 182
@@ -232,13 +232,13 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
232{ 232{
233 struct net_device *dev = ieee->dev; 233 struct net_device *dev = ieee->dev;
234 u16 fc, ethertype; 234 u16 fc, ethertype;
235 struct ieee80211_hdr *hdr; 235 struct ieee80211_hdr_3addr *hdr;
236 u8 *pos; 236 u8 *pos;
237 237
238 if (skb->len < 24) 238 if (skb->len < 24)
239 return 0; 239 return 0;
240 240
241 hdr = (struct ieee80211_hdr *)skb->data; 241 hdr = (struct ieee80211_hdr_3addr *)skb->data;
242 fc = le16_to_cpu(hdr->frame_ctl); 242 fc = le16_to_cpu(hdr->frame_ctl);
243 243
244 /* check that the frame is unicast frame to us */ 244 /* check that the frame is unicast frame to us */
@@ -271,26 +271,15 @@ static inline int
271ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, 271ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
272 struct ieee80211_crypt_data *crypt) 272 struct ieee80211_crypt_data *crypt)
273{ 273{
274 struct ieee80211_hdr *hdr; 274 struct ieee80211_hdr_3addr *hdr;
275 int res, hdrlen; 275 int res, hdrlen;
276 276
277 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) 277 if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
278 return 0; 278 return 0;
279 279
280 hdr = (struct ieee80211_hdr *)skb->data; 280 hdr = (struct ieee80211_hdr_3addr *)skb->data;
281 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); 281 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
282 282
283#ifdef CONFIG_IEEE80211_CRYPT_TKIP
284 if (ieee->tkip_countermeasures && strcmp(crypt->ops->name, "TKIP") == 0) {
285 if (net_ratelimit()) {
286 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
287 "received packet from " MAC_FMT "\n",
288 ieee->dev->name, MAC_ARG(hdr->addr2));
289 }
290 return -1;
291 }
292#endif
293
294 atomic_inc(&crypt->refcnt); 283 atomic_inc(&crypt->refcnt);
295 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); 284 res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
296 atomic_dec(&crypt->refcnt); 285 atomic_dec(&crypt->refcnt);
@@ -314,13 +303,13 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
314 struct sk_buff *skb, int keyidx, 303 struct sk_buff *skb, int keyidx,
315 struct ieee80211_crypt_data *crypt) 304 struct ieee80211_crypt_data *crypt)
316{ 305{
317 struct ieee80211_hdr *hdr; 306 struct ieee80211_hdr_3addr *hdr;
318 int res, hdrlen; 307 int res, hdrlen;
319 308
320 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) 309 if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
321 return 0; 310 return 0;
322 311
323 hdr = (struct ieee80211_hdr *)skb->data; 312 hdr = (struct ieee80211_hdr_3addr *)skb->data;
324 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); 313 hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
325 314
326 atomic_inc(&crypt->refcnt); 315 atomic_inc(&crypt->refcnt);
@@ -343,7 +332,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
343 struct ieee80211_rx_stats *rx_stats) 332 struct ieee80211_rx_stats *rx_stats)
344{ 333{
345 struct net_device *dev = ieee->dev; 334 struct net_device *dev = ieee->dev;
346 struct ieee80211_hdr *hdr; 335 struct ieee80211_hdr_4addr *hdr;
347 size_t hdrlen; 336 size_t hdrlen;
348 u16 fc, type, stype, sc; 337 u16 fc, type, stype, sc;
349 struct net_device_stats *stats; 338 struct net_device_stats *stats;
@@ -363,7 +352,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
363 struct ieee80211_crypt_data *crypt = NULL; 352 struct ieee80211_crypt_data *crypt = NULL;
364 int keyidx = 0; 353 int keyidx = 0;
365 354
366 hdr = (struct ieee80211_hdr *)skb->data; 355 hdr = (struct ieee80211_hdr_4addr *)skb->data;
367 stats = &ieee->stats; 356 stats = &ieee->stats;
368 357
369 if (skb->len < 10) { 358 if (skb->len < 10) {
@@ -378,35 +367,51 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
378 frag = WLAN_GET_SEQ_FRAG(sc); 367 frag = WLAN_GET_SEQ_FRAG(sc);
379 hdrlen = ieee80211_get_hdrlen(fc); 368 hdrlen = ieee80211_get_hdrlen(fc);
380 369
381#ifdef NOT_YET
382#if WIRELESS_EXT > 15
383 /* Put this code here so that we avoid duplicating it in all 370 /* Put this code here so that we avoid duplicating it in all
384 * Rx paths. - Jean II */ 371 * Rx paths. - Jean II */
385#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ 372#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
386 /* If spy monitoring on */ 373 /* If spy monitoring on */
387 if (iface->spy_data.spy_number > 0) { 374 if (ieee->spy_data.spy_number > 0) {
388 struct iw_quality wstats; 375 struct iw_quality wstats;
389 wstats.level = rx_stats->signal; 376
390 wstats.noise = rx_stats->noise; 377 wstats.updated = 0;
391 wstats.updated = 6; /* No qual value */ 378 if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
379 wstats.level = rx_stats->rssi;
380 wstats.updated |= IW_QUAL_LEVEL_UPDATED;
381 } else
382 wstats.updated |= IW_QUAL_LEVEL_INVALID;
383
384 if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
385 wstats.noise = rx_stats->noise;
386 wstats.updated |= IW_QUAL_NOISE_UPDATED;
387 } else
388 wstats.updated |= IW_QUAL_NOISE_INVALID;
389
390 if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
391 wstats.qual = rx_stats->signal;
392 wstats.updated |= IW_QUAL_QUAL_UPDATED;
393 } else
394 wstats.updated |= IW_QUAL_QUAL_INVALID;
395
392 /* Update spy records */ 396 /* Update spy records */
393 wireless_spy_update(dev, hdr->addr2, &wstats); 397 wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
394 } 398 }
395#endif /* IW_WIRELESS_SPY */ 399#endif /* IW_WIRELESS_SPY */
396#endif /* WIRELESS_EXT > 15 */ 400
401#ifdef NOT_YET
397 hostap_update_rx_stats(local->ap, hdr, rx_stats); 402 hostap_update_rx_stats(local->ap, hdr, rx_stats);
398#endif 403#endif
399 404
400#if WIRELESS_EXT > 15
401 if (ieee->iw_mode == IW_MODE_MONITOR) { 405 if (ieee->iw_mode == IW_MODE_MONITOR) {
402 ieee80211_monitor_rx(ieee, skb, rx_stats); 406 ieee80211_monitor_rx(ieee, skb, rx_stats);
403 stats->rx_packets++; 407 stats->rx_packets++;
404 stats->rx_bytes += skb->len; 408 stats->rx_bytes += skb->len;
405 return 1; 409 return 1;
406 } 410 }
407#endif
408 411
409 if (ieee->host_decrypt) { 412 if ((is_multicast_ether_addr(hdr->addr1) ||
413 is_broadcast_ether_addr(hdr->addr2)) ? ieee->host_mc_decrypt :
414 ieee->host_decrypt) {
410 int idx = 0; 415 int idx = 0;
411 if (skb->len >= hdrlen + 3) 416 if (skb->len >= hdrlen + 3)
412 idx = skb->data[hdrlen + 3] >> 6; 417 idx = skb->data[hdrlen + 3] >> 6;
@@ -531,6 +536,9 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
531 536
532 /* Nullfunc frames may have PS-bit set, so they must be passed to 537 /* Nullfunc frames may have PS-bit set, so they must be passed to
533 * hostap_handle_sta_rx() before being dropped here. */ 538 * hostap_handle_sta_rx() before being dropped here. */
539
540 stype &= ~IEEE80211_STYPE_QOS_DATA;
541
534 if (stype != IEEE80211_STYPE_DATA && 542 if (stype != IEEE80211_STYPE_DATA &&
535 stype != IEEE80211_STYPE_DATA_CFACK && 543 stype != IEEE80211_STYPE_DATA_CFACK &&
536 stype != IEEE80211_STYPE_DATA_CFPOLL && 544 stype != IEEE80211_STYPE_DATA_CFPOLL &&
@@ -549,7 +557,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
549 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) 557 (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
550 goto rx_dropped; 558 goto rx_dropped;
551 559
552 hdr = (struct ieee80211_hdr *)skb->data; 560 hdr = (struct ieee80211_hdr_4addr *)skb->data;
553 561
554 /* skb: hdr + (possibly fragmented) plaintext payload */ 562 /* skb: hdr + (possibly fragmented) plaintext payload */
555 // PR: FIXME: hostap has additional conditions in the "if" below: 563 // PR: FIXME: hostap has additional conditions in the "if" below:
@@ -603,7 +611,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
603 /* this was the last fragment and the frame will be 611 /* this was the last fragment and the frame will be
604 * delivered, so remove skb from fragment cache */ 612 * delivered, so remove skb from fragment cache */
605 skb = frag_skb; 613 skb = frag_skb;
606 hdr = (struct ieee80211_hdr *)skb->data; 614 hdr = (struct ieee80211_hdr_4addr *)skb->data;
607 ieee80211_frag_cache_invalidate(ieee, hdr); 615 ieee80211_frag_cache_invalidate(ieee, hdr);
608 } 616 }
609 617
@@ -613,7 +621,7 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
613 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) 621 ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
614 goto rx_dropped; 622 goto rx_dropped;
615 623
616 hdr = (struct ieee80211_hdr *)skb->data; 624 hdr = (struct ieee80211_hdr_4addr *)skb->data;
617 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) { 625 if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
618 if ( /*ieee->ieee802_1x && */ 626 if ( /*ieee->ieee802_1x && */
619 ieee80211_is_eapol_frame(ieee, skb)) { 627 ieee80211_is_eapol_frame(ieee, skb)) {
@@ -755,69 +763,179 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
755 763
756#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 764#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
757 765
758static inline int ieee80211_is_ofdm_rate(u8 rate) 766static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
767
768/*
769* Make ther structure we read from the beacon packet has
770* the right values
771*/
772static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
773 *info_element, int sub_type)
759{ 774{
760 switch (rate & ~IEEE80211_BASIC_RATE_MASK) { 775
761 case IEEE80211_OFDM_RATE_6MB: 776 if (info_element->qui_subtype != sub_type)
762 case IEEE80211_OFDM_RATE_9MB: 777 return -1;
763 case IEEE80211_OFDM_RATE_12MB: 778 if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
764 case IEEE80211_OFDM_RATE_18MB: 779 return -1;
765 case IEEE80211_OFDM_RATE_24MB: 780 if (info_element->qui_type != QOS_OUI_TYPE)
766 case IEEE80211_OFDM_RATE_36MB: 781 return -1;
767 case IEEE80211_OFDM_RATE_48MB: 782 if (info_element->version != QOS_VERSION_1)
768 case IEEE80211_OFDM_RATE_54MB: 783 return -1;
769 return 1; 784
770 }
771 return 0; 785 return 0;
772} 786}
773 787
774static inline int ieee80211_network_init(struct ieee80211_device *ieee, 788/*
775 struct ieee80211_probe_response 789 * Parse a QoS parameter element
776 *beacon, 790 */
777 struct ieee80211_network *network, 791static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
778 struct ieee80211_rx_stats *stats) 792 *element_param, struct ieee80211_info_element
793 *info_element)
779{ 794{
780#ifdef CONFIG_IEEE80211_DEBUG 795 int ret = 0;
781 char rates_str[64]; 796 u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
782 char *p;
783#endif
784 struct ieee80211_info_element *info_element;
785 u16 left;
786 u8 i;
787 797
788 /* Pull out fixed field data */ 798 if ((info_element == NULL) || (element_param == NULL))
789 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); 799 return -1;
790 network->capability = beacon->capability;
791 network->last_scanned = jiffies;
792 network->time_stamp[0] = beacon->time_stamp[0];
793 network->time_stamp[1] = beacon->time_stamp[1];
794 network->beacon_interval = beacon->beacon_interval;
795 /* Where to pull this? beacon->listen_interval; */
796 network->listen_interval = 0x0A;
797 network->rates_len = network->rates_ex_len = 0;
798 network->last_associate = 0;
799 network->ssid_len = 0;
800 network->flags = 0;
801 network->atim_window = 0;
802 800
803 if (stats->freq == IEEE80211_52GHZ_BAND) { 801 if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
804 /* for A band (No DS info) */ 802 memcpy(element_param->info_element.qui, info_element->data,
805 network->channel = stats->received_channel; 803 info_element->len);
804 element_param->info_element.elementID = info_element->id;
805 element_param->info_element.length = info_element->len;
806 } else 806 } else
807 network->flags |= NETWORK_HAS_CCK; 807 ret = -1;
808 if (ret == 0)
809 ret = ieee80211_verify_qos_info(&element_param->info_element,
810 QOS_OUI_PARAM_SUB_TYPE);
811 return ret;
812}
808 813
809 network->wpa_ie_len = 0; 814/*
810 network->rsn_ie_len = 0; 815 * Parse a QoS information element
816 */
817static int ieee80211_read_qos_info_element(struct
818 ieee80211_qos_information_element
819 *element_info, struct ieee80211_info_element
820 *info_element)
821{
822 int ret = 0;
823 u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
824
825 if (element_info == NULL)
826 return -1;
827 if (info_element == NULL)
828 return -1;
829
830 if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
831 memcpy(element_info->qui, info_element->data,
832 info_element->len);
833 element_info->elementID = info_element->id;
834 element_info->length = info_element->len;
835 } else
836 ret = -1;
837
838 if (ret == 0)
839 ret = ieee80211_verify_qos_info(element_info,
840 QOS_OUI_INFO_SUB_TYPE);
841 return ret;
842}
843
844/*
845 * Write QoS parameters from the ac parameters.
846 */
847static int ieee80211_qos_convert_ac_to_parameters(struct
848 ieee80211_qos_parameter_info
849 *param_elm, struct
850 ieee80211_qos_parameters
851 *qos_param)
852{
853 int rc = 0;
854 int i;
855 struct ieee80211_qos_ac_parameter *ac_params;
856 u32 txop;
857 u8 cw_min;
858 u8 cw_max;
859
860 for (i = 0; i < QOS_QUEUE_NUM; i++) {
861 ac_params = &(param_elm->ac_params_record[i]);
862
863 qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
864 qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
865
866 cw_min = ac_params->ecw_min_max & 0x0F;
867 qos_param->cw_min[i] = (u16) ((1 << cw_min) - 1);
868
869 cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
870 qos_param->cw_max[i] = (u16) ((1 << cw_max) - 1);
871
872 qos_param->flag[i] =
873 (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
874
875 txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
876 qos_param->tx_op_limit[i] = (u16) txop;
877 }
878 return rc;
879}
880
881/*
882 * we have a generic data element which it may contain QoS information or
883 * parameters element. check the information element length to decide
884 * which type to read
885 */
886static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
887 *info_element,
888 struct ieee80211_network *network)
889{
890 int rc = 0;
891 struct ieee80211_qos_parameters *qos_param = NULL;
892 struct ieee80211_qos_information_element qos_info_element;
893
894 rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
895
896 if (rc == 0) {
897 network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
898 network->flags |= NETWORK_HAS_QOS_INFORMATION;
899 } else {
900 struct ieee80211_qos_parameter_info param_element;
901
902 rc = ieee80211_read_qos_param_element(&param_element,
903 info_element);
904 if (rc == 0) {
905 qos_param = &(network->qos_data.parameters);
906 ieee80211_qos_convert_ac_to_parameters(&param_element,
907 qos_param);
908 network->flags |= NETWORK_HAS_QOS_PARAMETERS;
909 network->qos_data.param_count =
910 param_element.info_element.ac_info & 0x0F;
911 }
912 }
913
914 if (rc == 0) {
915 IEEE80211_DEBUG_QOS("QoS is supported\n");
916 network->qos_data.supported = 1;
917 }
918 return rc;
919}
920
921static int ieee80211_parse_info_param(struct ieee80211_info_element
922 *info_element, u16 length,
923 struct ieee80211_network *network)
924{
925 u8 i;
926#ifdef CONFIG_IEEE80211_DEBUG
927 char rates_str[64];
928 char *p;
929#endif
811 930
812 info_element = &beacon->info_element; 931 while (length >= sizeof(*info_element)) {
813 left = stats->len - ((void *)info_element - (void *)beacon); 932 if (sizeof(*info_element) + info_element->len > length) {
814 while (left >= sizeof(struct ieee80211_info_element_hdr)) { 933 IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
815 if (sizeof(struct ieee80211_info_element_hdr) + 934 "info_element->len + 2 > left : "
816 info_element->len > left) { 935 "info_element->len+2=%zd left=%d, id=%d.\n",
817 IEEE80211_DEBUG_SCAN 936 info_element->len +
818 ("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%Zd left=%d.\n", 937 sizeof(*info_element),
819 info_element->len + 938 length, info_element->id);
820 sizeof(struct ieee80211_info_element), left);
821 return 1; 939 return 1;
822 } 940 }
823 941
@@ -837,7 +955,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
837 memset(network->ssid + network->ssid_len, 0, 955 memset(network->ssid + network->ssid_len, 0,
838 IW_ESSID_MAX_SIZE - network->ssid_len); 956 IW_ESSID_MAX_SIZE - network->ssid_len);
839 957
840 IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", 958 IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
841 network->ssid, network->ssid_len); 959 network->ssid, network->ssid_len);
842 break; 960 break;
843 961
@@ -845,15 +963,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
845#ifdef CONFIG_IEEE80211_DEBUG 963#ifdef CONFIG_IEEE80211_DEBUG
846 p = rates_str; 964 p = rates_str;
847#endif 965#endif
848 network->rates_len = 966 network->rates_len = min(info_element->len,
849 min(info_element->len, MAX_RATES_LENGTH); 967 MAX_RATES_LENGTH);
850 for (i = 0; i < network->rates_len; i++) { 968 for (i = 0; i < network->rates_len; i++) {
851 network->rates[i] = info_element->data[i]; 969 network->rates[i] = info_element->data[i];
852#ifdef CONFIG_IEEE80211_DEBUG 970#ifdef CONFIG_IEEE80211_DEBUG
853 p += snprintf(p, 971 p += snprintf(p, sizeof(rates_str) -
854 sizeof(rates_str) - (p - 972 (p - rates_str), "%02X ",
855 rates_str), 973 network->rates[i]);
856 "%02X ", network->rates[i]);
857#endif 974#endif
858 if (ieee80211_is_ofdm_rate 975 if (ieee80211_is_ofdm_rate
859 (info_element->data[i])) { 976 (info_element->data[i])) {
@@ -865,7 +982,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
865 } 982 }
866 } 983 }
867 984
868 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", 985 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
869 rates_str, network->rates_len); 986 rates_str, network->rates_len);
870 break; 987 break;
871 988
@@ -873,15 +990,14 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
873#ifdef CONFIG_IEEE80211_DEBUG 990#ifdef CONFIG_IEEE80211_DEBUG
874 p = rates_str; 991 p = rates_str;
875#endif 992#endif
876 network->rates_ex_len = 993 network->rates_ex_len = min(info_element->len,
877 min(info_element->len, MAX_RATES_EX_LENGTH); 994 MAX_RATES_EX_LENGTH);
878 for (i = 0; i < network->rates_ex_len; i++) { 995 for (i = 0; i < network->rates_ex_len; i++) {
879 network->rates_ex[i] = info_element->data[i]; 996 network->rates_ex[i] = info_element->data[i];
880#ifdef CONFIG_IEEE80211_DEBUG 997#ifdef CONFIG_IEEE80211_DEBUG
881 p += snprintf(p, 998 p += snprintf(p, sizeof(rates_str) -
882 sizeof(rates_str) - (p - 999 (p - rates_str), "%02X ",
883 rates_str), 1000 network->rates[i]);
884 "%02X ", network->rates[i]);
885#endif 1001#endif
886 if (ieee80211_is_ofdm_rate 1002 if (ieee80211_is_ofdm_rate
887 (info_element->data[i])) { 1003 (info_element->data[i])) {
@@ -893,40 +1009,51 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
893 } 1009 }
894 } 1010 }
895 1011
896 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", 1012 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
897 rates_str, network->rates_ex_len); 1013 rates_str, network->rates_ex_len);
898 break; 1014 break;
899 1015
900 case MFIE_TYPE_DS_SET: 1016 case MFIE_TYPE_DS_SET:
901 IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", 1017 IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
902 info_element->data[0]); 1018 info_element->data[0]);
903 if (stats->freq == IEEE80211_24GHZ_BAND) 1019 network->channel = info_element->data[0];
904 network->channel = info_element->data[0];
905 break; 1020 break;
906 1021
907 case MFIE_TYPE_FH_SET: 1022 case MFIE_TYPE_FH_SET:
908 IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); 1023 IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
909 break; 1024 break;
910 1025
911 case MFIE_TYPE_CF_SET: 1026 case MFIE_TYPE_CF_SET:
912 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); 1027 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
913 break; 1028 break;
914 1029
915 case MFIE_TYPE_TIM: 1030 case MFIE_TYPE_TIM:
916 IEEE80211_DEBUG_SCAN("MFIE_TYPE_TIM: ignored\n"); 1031 IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: ignored\n");
1032 break;
1033
1034 case MFIE_TYPE_ERP_INFO:
1035 network->erp_value = info_element->data[0];
1036 IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
1037 network->erp_value);
917 break; 1038 break;
918 1039
919 case MFIE_TYPE_IBSS_SET: 1040 case MFIE_TYPE_IBSS_SET:
920 IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n"); 1041 network->atim_window = info_element->data[0];
1042 IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
1043 network->atim_window);
921 break; 1044 break;
922 1045
923 case MFIE_TYPE_CHALLENGE: 1046 case MFIE_TYPE_CHALLENGE:
924 IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); 1047 IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
925 break; 1048 break;
926 1049
927 case MFIE_TYPE_GENERIC: 1050 case MFIE_TYPE_GENERIC:
928 IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", 1051 IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
929 info_element->len); 1052 info_element->len);
1053 if (!ieee80211_parse_qos_info_param_IE(info_element,
1054 network))
1055 break;
1056
930 if (info_element->len >= 4 && 1057 if (info_element->len >= 4 &&
931 info_element->data[0] == 0x00 && 1058 info_element->data[0] == 0x00 &&
932 info_element->data[1] == 0x50 && 1059 info_element->data[1] == 0x50 &&
@@ -940,7 +1067,7 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
940 break; 1067 break;
941 1068
942 case MFIE_TYPE_RSN: 1069 case MFIE_TYPE_RSN:
943 IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", 1070 IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
944 info_element->len); 1071 info_element->len);
945 network->rsn_ie_len = min(info_element->len + 2, 1072 network->rsn_ie_len = min(info_element->len + 2,
946 MAX_WPA_IE_LEN); 1073 MAX_WPA_IE_LEN);
@@ -948,18 +1075,127 @@ static inline int ieee80211_network_init(struct ieee80211_device *ieee,
948 network->rsn_ie_len); 1075 network->rsn_ie_len);
949 break; 1076 break;
950 1077
1078 case MFIE_TYPE_QOS_PARAMETER:
1079 printk(KERN_ERR
1080 "QoS Error need to parse QOS_PARAMETER IE\n");
1081 break;
1082
951 default: 1083 default:
952 IEEE80211_DEBUG_SCAN("unsupported IE %d\n", 1084 IEEE80211_DEBUG_MGMT("unsupported IE %d\n",
953 info_element->id); 1085 info_element->id);
954 break; 1086 break;
955 } 1087 }
956 1088
957 left -= sizeof(struct ieee80211_info_element_hdr) + 1089 length -= sizeof(*info_element) + info_element->len;
958 info_element->len; 1090 info_element =
959 info_element = (struct ieee80211_info_element *) 1091 (struct ieee80211_info_element *)&info_element->
960 &info_element->data[info_element->len]; 1092 data[info_element->len];
1093 }
1094
1095 return 0;
1096}
1097
1098static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
1099 *frame, struct ieee80211_rx_stats *stats)
1100{
1101 struct ieee80211_network network_resp;
1102 struct ieee80211_network *network = &network_resp;
1103 struct net_device *dev = ieee->dev;
1104
1105 network->flags = 0;
1106 network->qos_data.active = 0;
1107 network->qos_data.supported = 0;
1108 network->qos_data.param_count = 0;
1109 network->qos_data.old_param_count = 0;
1110
1111 //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
1112 network->atim_window = le16_to_cpu(frame->aid);
1113 network->listen_interval = le16_to_cpu(frame->status);
1114 memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
1115 network->capability = le16_to_cpu(frame->capability);
1116 network->last_scanned = jiffies;
1117 network->rates_len = network->rates_ex_len = 0;
1118 network->last_associate = 0;
1119 network->ssid_len = 0;
1120 network->erp_value =
1121 (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
1122
1123 if (stats->freq == IEEE80211_52GHZ_BAND) {
1124 /* for A band (No DS info) */
1125 network->channel = stats->received_channel;
1126 } else
1127 network->flags |= NETWORK_HAS_CCK;
1128
1129 network->wpa_ie_len = 0;
1130 network->rsn_ie_len = 0;
1131
1132 if (ieee80211_parse_info_param
1133 (frame->info_element, stats->len - sizeof(*frame), network))
1134 return 1;
1135
1136 network->mode = 0;
1137 if (stats->freq == IEEE80211_52GHZ_BAND)
1138 network->mode = IEEE_A;
1139 else {
1140 if (network->flags & NETWORK_HAS_OFDM)
1141 network->mode |= IEEE_G;
1142 if (network->flags & NETWORK_HAS_CCK)
1143 network->mode |= IEEE_B;
961 } 1144 }
962 1145
1146 if (ieee80211_is_empty_essid(network->ssid, network->ssid_len))
1147 network->flags |= NETWORK_EMPTY_ESSID;
1148
1149 memcpy(&network->stats, stats, sizeof(network->stats));
1150
1151 if (ieee->handle_assoc_response != NULL)
1152 ieee->handle_assoc_response(dev, frame, network);
1153
1154 return 0;
1155}
1156
1157/***************************************************/
1158
1159static inline int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
1160 *beacon,
1161 struct ieee80211_network *network,
1162 struct ieee80211_rx_stats *stats)
1163{
1164 network->qos_data.active = 0;
1165 network->qos_data.supported = 0;
1166 network->qos_data.param_count = 0;
1167 network->qos_data.old_param_count = 0;
1168
1169 /* Pull out fixed field data */
1170 memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
1171 network->capability = le16_to_cpu(beacon->capability);
1172 network->last_scanned = jiffies;
1173 network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
1174 network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
1175 network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
1176 /* Where to pull this? beacon->listen_interval; */
1177 network->listen_interval = 0x0A;
1178 network->rates_len = network->rates_ex_len = 0;
1179 network->last_associate = 0;
1180 network->ssid_len = 0;
1181 network->flags = 0;
1182 network->atim_window = 0;
1183 network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
1184 0x3 : 0x0;
1185
1186 if (stats->freq == IEEE80211_52GHZ_BAND) {
1187 /* for A band (No DS info) */
1188 network->channel = stats->received_channel;
1189 } else
1190 network->flags |= NETWORK_HAS_CCK;
1191
1192 network->wpa_ie_len = 0;
1193 network->rsn_ie_len = 0;
1194
1195 if (ieee80211_parse_info_param
1196 (beacon->info_element, stats->len - sizeof(*beacon), network))
1197 return 1;
1198
963 network->mode = 0; 1199 network->mode = 0;
964 if (stats->freq == IEEE80211_52GHZ_BAND) 1200 if (stats->freq == IEEE80211_52GHZ_BAND)
965 network->mode = IEEE_A; 1201 network->mode = IEEE_A;
@@ -1002,6 +1238,9 @@ static inline int is_same_network(struct ieee80211_network *src,
1002static inline void update_network(struct ieee80211_network *dst, 1238static inline void update_network(struct ieee80211_network *dst,
1003 struct ieee80211_network *src) 1239 struct ieee80211_network *src)
1004{ 1240{
1241 int qos_active;
1242 u8 old_param;
1243
1005 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); 1244 memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats));
1006 dst->capability = src->capability; 1245 dst->capability = src->capability;
1007 memcpy(dst->rates, src->rates, src->rates_len); 1246 memcpy(dst->rates, src->rates, src->rates_len);
@@ -1017,6 +1256,7 @@ static inline void update_network(struct ieee80211_network *dst,
1017 dst->beacon_interval = src->beacon_interval; 1256 dst->beacon_interval = src->beacon_interval;
1018 dst->listen_interval = src->listen_interval; 1257 dst->listen_interval = src->listen_interval;
1019 dst->atim_window = src->atim_window; 1258 dst->atim_window = src->atim_window;
1259 dst->erp_value = src->erp_value;
1020 1260
1021 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); 1261 memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
1022 dst->wpa_ie_len = src->wpa_ie_len; 1262 dst->wpa_ie_len = src->wpa_ie_len;
@@ -1024,22 +1264,48 @@ static inline void update_network(struct ieee80211_network *dst,
1024 dst->rsn_ie_len = src->rsn_ie_len; 1264 dst->rsn_ie_len = src->rsn_ie_len;
1025 1265
1026 dst->last_scanned = jiffies; 1266 dst->last_scanned = jiffies;
1267 qos_active = src->qos_data.active;
1268 old_param = dst->qos_data.old_param_count;
1269 if (dst->flags & NETWORK_HAS_QOS_MASK)
1270 memcpy(&dst->qos_data, &src->qos_data,
1271 sizeof(struct ieee80211_qos_data));
1272 else {
1273 dst->qos_data.supported = src->qos_data.supported;
1274 dst->qos_data.param_count = src->qos_data.param_count;
1275 }
1276
1277 if (dst->qos_data.supported == 1) {
1278 if (dst->ssid_len)
1279 IEEE80211_DEBUG_QOS
1280 ("QoS the network %s is QoS supported\n",
1281 dst->ssid);
1282 else
1283 IEEE80211_DEBUG_QOS
1284 ("QoS the network is QoS supported\n");
1285 }
1286 dst->qos_data.active = qos_active;
1287 dst->qos_data.old_param_count = old_param;
1288
1027 /* dst->last_associate is not overwritten */ 1289 /* dst->last_associate is not overwritten */
1028} 1290}
1029 1291
1292static inline int is_beacon(int fc)
1293{
1294 return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
1295}
1296
1030static inline void ieee80211_process_probe_response(struct ieee80211_device 1297static inline void ieee80211_process_probe_response(struct ieee80211_device
1031 *ieee, 1298 *ieee, struct
1032 struct
1033 ieee80211_probe_response 1299 ieee80211_probe_response
1034 *beacon, 1300 *beacon, struct ieee80211_rx_stats
1035 struct ieee80211_rx_stats
1036 *stats) 1301 *stats)
1037{ 1302{
1303 struct net_device *dev = ieee->dev;
1038 struct ieee80211_network network; 1304 struct ieee80211_network network;
1039 struct ieee80211_network *target; 1305 struct ieee80211_network *target;
1040 struct ieee80211_network *oldest = NULL; 1306 struct ieee80211_network *oldest = NULL;
1041#ifdef CONFIG_IEEE80211_DEBUG 1307#ifdef CONFIG_IEEE80211_DEBUG
1042 struct ieee80211_info_element *info_element = &beacon->info_element; 1308 struct ieee80211_info_element *info_element = beacon->info_element;
1043#endif 1309#endif
1044 unsigned long flags; 1310 unsigned long flags;
1045 1311
@@ -1070,10 +1336,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1070 escape_essid(info_element->data, 1336 escape_essid(info_element->data,
1071 info_element->len), 1337 info_element->len),
1072 MAC_ARG(beacon->header.addr3), 1338 MAC_ARG(beacon->header.addr3),
1073 WLAN_FC_GET_STYPE(beacon->header. 1339 is_beacon(le16_to_cpu
1074 frame_ctl) == 1340 (beacon->header.
1075 IEEE80211_STYPE_PROBE_RESP ? 1341 frame_ctl)) ?
1076 "PROBE RESPONSE" : "BEACON"); 1342 "BEACON" : "PROBE RESPONSE");
1077 return; 1343 return;
1078 } 1344 }
1079 1345
@@ -1122,10 +1388,10 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1122 escape_essid(network.ssid, 1388 escape_essid(network.ssid,
1123 network.ssid_len), 1389 network.ssid_len),
1124 MAC_ARG(network.bssid), 1390 MAC_ARG(network.bssid),
1125 WLAN_FC_GET_STYPE(beacon->header. 1391 is_beacon(le16_to_cpu
1126 frame_ctl) == 1392 (beacon->header.
1127 IEEE80211_STYPE_PROBE_RESP ? 1393 frame_ctl)) ?
1128 "PROBE RESPONSE" : "BEACON"); 1394 "BEACON" : "PROBE RESPONSE");
1129#endif 1395#endif
1130 memcpy(target, &network, sizeof(*target)); 1396 memcpy(target, &network, sizeof(*target));
1131 list_add_tail(&target->list, &ieee->network_list); 1397 list_add_tail(&target->list, &ieee->network_list);
@@ -1134,34 +1400,60 @@ static inline void ieee80211_process_probe_response(struct ieee80211_device
1134 escape_essid(target->ssid, 1400 escape_essid(target->ssid,
1135 target->ssid_len), 1401 target->ssid_len),
1136 MAC_ARG(target->bssid), 1402 MAC_ARG(target->bssid),
1137 WLAN_FC_GET_STYPE(beacon->header. 1403 is_beacon(le16_to_cpu
1138 frame_ctl) == 1404 (beacon->header.
1139 IEEE80211_STYPE_PROBE_RESP ? 1405 frame_ctl)) ?
1140 "PROBE RESPONSE" : "BEACON"); 1406 "BEACON" : "PROBE RESPONSE");
1141 update_network(target, &network); 1407 update_network(target, &network);
1142 } 1408 }
1143 1409
1144 spin_unlock_irqrestore(&ieee->lock, flags); 1410 spin_unlock_irqrestore(&ieee->lock, flags);
1411
1412 if (is_beacon(le16_to_cpu(beacon->header.frame_ctl))) {
1413 if (ieee->handle_beacon != NULL)
1414 ieee->handle_beacon(dev, beacon, &network);
1415 } else {
1416 if (ieee->handle_probe_response != NULL)
1417 ieee->handle_probe_response(dev, beacon, &network);
1418 }
1145} 1419}
1146 1420
1147void ieee80211_rx_mgt(struct ieee80211_device *ieee, 1421void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1148 struct ieee80211_hdr *header, 1422 struct ieee80211_hdr_4addr *header,
1149 struct ieee80211_rx_stats *stats) 1423 struct ieee80211_rx_stats *stats)
1150{ 1424{
1151 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { 1425 switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
1152 case IEEE80211_STYPE_ASSOC_RESP: 1426 case IEEE80211_STYPE_ASSOC_RESP:
1153 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", 1427 IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
1154 WLAN_FC_GET_STYPE(header->frame_ctl)); 1428 WLAN_FC_GET_STYPE(le16_to_cpu
1429 (header->frame_ctl)));
1430 ieee80211_handle_assoc_resp(ieee,
1431 (struct ieee80211_assoc_response *)
1432 header, stats);
1155 break; 1433 break;
1156 1434
1157 case IEEE80211_STYPE_REASSOC_RESP: 1435 case IEEE80211_STYPE_REASSOC_RESP:
1158 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n", 1436 IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
1159 WLAN_FC_GET_STYPE(header->frame_ctl)); 1437 WLAN_FC_GET_STYPE(le16_to_cpu
1438 (header->frame_ctl)));
1439 break;
1440
1441 case IEEE80211_STYPE_PROBE_REQ:
1442 IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
1443 WLAN_FC_GET_STYPE(le16_to_cpu
1444 (header->frame_ctl)));
1445
1446 if (ieee->handle_probe_request != NULL)
1447 ieee->handle_probe_request(ieee->dev,
1448 (struct
1449 ieee80211_probe_request *)
1450 header, stats);
1160 break; 1451 break;
1161 1452
1162 case IEEE80211_STYPE_PROBE_RESP: 1453 case IEEE80211_STYPE_PROBE_RESP:
1163 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", 1454 IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
1164 WLAN_FC_GET_STYPE(header->frame_ctl)); 1455 WLAN_FC_GET_STYPE(le16_to_cpu
1456 (header->frame_ctl)));
1165 IEEE80211_DEBUG_SCAN("Probe response\n"); 1457 IEEE80211_DEBUG_SCAN("Probe response\n");
1166 ieee80211_process_probe_response(ieee, 1458 ieee80211_process_probe_response(ieee,
1167 (struct 1459 (struct
@@ -1171,20 +1463,46 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
1171 1463
1172 case IEEE80211_STYPE_BEACON: 1464 case IEEE80211_STYPE_BEACON:
1173 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", 1465 IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
1174 WLAN_FC_GET_STYPE(header->frame_ctl)); 1466 WLAN_FC_GET_STYPE(le16_to_cpu
1467 (header->frame_ctl)));
1175 IEEE80211_DEBUG_SCAN("Beacon\n"); 1468 IEEE80211_DEBUG_SCAN("Beacon\n");
1176 ieee80211_process_probe_response(ieee, 1469 ieee80211_process_probe_response(ieee,
1177 (struct 1470 (struct
1178 ieee80211_probe_response *) 1471 ieee80211_probe_response *)
1179 header, stats); 1472 header, stats);
1180 break; 1473 break;
1474 case IEEE80211_STYPE_AUTH:
1181 1475
1476 IEEE80211_DEBUG_MGMT("recieved auth (%d)\n",
1477 WLAN_FC_GET_STYPE(le16_to_cpu
1478 (header->frame_ctl)));
1479
1480 if (ieee->handle_auth != NULL)
1481 ieee->handle_auth(ieee->dev,
1482 (struct ieee80211_auth *)header);
1483 break;
1484
1485 case IEEE80211_STYPE_DISASSOC:
1486 if (ieee->handle_disassoc != NULL)
1487 ieee->handle_disassoc(ieee->dev,
1488 (struct ieee80211_disassoc *)
1489 header);
1490 break;
1491
1492 case IEEE80211_STYPE_DEAUTH:
1493 printk("DEAUTH from AP\n");
1494 if (ieee->handle_deauth != NULL)
1495 ieee->handle_deauth(ieee->dev, (struct ieee80211_auth *)
1496 header);
1497 break;
1182 default: 1498 default:
1183 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n", 1499 IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
1184 WLAN_FC_GET_STYPE(header->frame_ctl)); 1500 WLAN_FC_GET_STYPE(le16_to_cpu
1501 (header->frame_ctl)));
1185 IEEE80211_WARNING("%s: Unknown management packet: %d\n", 1502 IEEE80211_WARNING("%s: Unknown management packet: %d\n",
1186 ieee->dev->name, 1503 ieee->dev->name,
1187 WLAN_FC_GET_STYPE(header->frame_ctl)); 1504 WLAN_FC_GET_STYPE(le16_to_cpu
1505 (header->frame_ctl)));
1188 break; 1506 break;
1189 } 1507 }
1190} 1508}