diff options
Diffstat (limited to 'net/mac80211')
35 files changed, 5329 insertions, 4938 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 80d693392b0f..8427518e4f20 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -179,19 +179,6 @@ config MAC80211_VERBOSE_MPL_DEBUG | |||
179 | 179 | ||
180 | Do not select this option. | 180 | Do not select this option. |
181 | 181 | ||
182 | config MAC80211_LOWTX_FRAME_DUMP | ||
183 | bool "Debug frame dumping" | ||
184 | depends on MAC80211_DEBUG_MENU | ||
185 | ---help--- | ||
186 | Selecting this option will cause the stack to | ||
187 | print a message for each frame that is handed | ||
188 | to the lowlevel driver for transmission. This | ||
189 | message includes all MAC addresses and the | ||
190 | frame control field. | ||
191 | |||
192 | If unsure, say N and insert the debugging code | ||
193 | you require into the driver you are debugging. | ||
194 | |||
195 | config MAC80211_DEBUG_COUNTERS | 182 | config MAC80211_DEBUG_COUNTERS |
196 | bool "Extra statistics for TX/RX debugging" | 183 | bool "Extra statistics for TX/RX debugging" |
197 | depends on MAC80211_DEBUG_MENU | 184 | depends on MAC80211_DEBUG_MENU |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index a169b0201d61..2dc8f2bff27b 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -7,6 +7,8 @@ mac80211-y := \ | |||
7 | sta_info.o \ | 7 | sta_info.o \ |
8 | wep.o \ | 8 | wep.o \ |
9 | wpa.o \ | 9 | wpa.o \ |
10 | scan.o \ | ||
11 | ht.o \ | ||
10 | mlme.o \ | 12 | mlme.o \ |
11 | iface.o \ | 13 | iface.o \ |
12 | rate.o \ | 14 | rate.o \ |
@@ -15,6 +17,7 @@ mac80211-y := \ | |||
15 | aes_ccm.o \ | 17 | aes_ccm.o \ |
16 | cfg.o \ | 18 | cfg.o \ |
17 | rx.o \ | 19 | rx.o \ |
20 | spectmgmt.o \ | ||
18 | tx.o \ | 21 | tx.o \ |
19 | key.o \ | 22 | key.o \ |
20 | util.o \ | 23 | util.o \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 297c257864c7..e2574885db4a 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -17,26 +17,26 @@ | |||
17 | #include "rate.h" | 17 | #include "rate.h" |
18 | #include "mesh.h" | 18 | #include "mesh.h" |
19 | 19 | ||
20 | static enum ieee80211_if_types | 20 | struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy) |
21 | nl80211_type_to_mac80211_type(enum nl80211_iftype type) | 21 | { |
22 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
23 | return &local->hw; | ||
24 | } | ||
25 | EXPORT_SYMBOL(wiphy_to_hw); | ||
26 | |||
27 | static bool nl80211_type_check(enum nl80211_iftype type) | ||
22 | { | 28 | { |
23 | switch (type) { | 29 | switch (type) { |
24 | case NL80211_IFTYPE_UNSPECIFIED: | ||
25 | return IEEE80211_IF_TYPE_STA; | ||
26 | case NL80211_IFTYPE_ADHOC: | 30 | case NL80211_IFTYPE_ADHOC: |
27 | return IEEE80211_IF_TYPE_IBSS; | ||
28 | case NL80211_IFTYPE_STATION: | 31 | case NL80211_IFTYPE_STATION: |
29 | return IEEE80211_IF_TYPE_STA; | ||
30 | case NL80211_IFTYPE_MONITOR: | 32 | case NL80211_IFTYPE_MONITOR: |
31 | return IEEE80211_IF_TYPE_MNTR; | ||
32 | #ifdef CONFIG_MAC80211_MESH | 33 | #ifdef CONFIG_MAC80211_MESH |
33 | case NL80211_IFTYPE_MESH_POINT: | 34 | case NL80211_IFTYPE_MESH_POINT: |
34 | return IEEE80211_IF_TYPE_MESH_POINT; | ||
35 | #endif | 35 | #endif |
36 | case NL80211_IFTYPE_WDS: | 36 | case NL80211_IFTYPE_WDS: |
37 | return IEEE80211_IF_TYPE_WDS; | 37 | return true; |
38 | default: | 38 | default: |
39 | return IEEE80211_IF_TYPE_INVALID; | 39 | return false; |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
@@ -45,17 +45,15 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
45 | struct vif_params *params) | 45 | struct vif_params *params) |
46 | { | 46 | { |
47 | struct ieee80211_local *local = wiphy_priv(wiphy); | 47 | struct ieee80211_local *local = wiphy_priv(wiphy); |
48 | enum ieee80211_if_types itype; | ||
49 | struct net_device *dev; | 48 | struct net_device *dev; |
50 | struct ieee80211_sub_if_data *sdata; | 49 | struct ieee80211_sub_if_data *sdata; |
51 | int err; | 50 | int err; |
52 | 51 | ||
53 | itype = nl80211_type_to_mac80211_type(type); | 52 | if (!nl80211_type_check(type)) |
54 | if (itype == IEEE80211_IF_TYPE_INVALID) | ||
55 | return -EINVAL; | 53 | return -EINVAL; |
56 | 54 | ||
57 | err = ieee80211_if_add(local, name, &dev, itype, params); | 55 | err = ieee80211_if_add(local, name, &dev, type, params); |
58 | if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags) | 56 | if (err || type != NL80211_IFTYPE_MONITOR || !flags) |
59 | return err; | 57 | return err; |
60 | 58 | ||
61 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 59 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -66,13 +64,16 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | |||
66 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) | 64 | static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex) |
67 | { | 65 | { |
68 | struct net_device *dev; | 66 | struct net_device *dev; |
67 | struct ieee80211_sub_if_data *sdata; | ||
69 | 68 | ||
70 | /* we're under RTNL */ | 69 | /* we're under RTNL */ |
71 | dev = __dev_get_by_index(&init_net, ifindex); | 70 | dev = __dev_get_by_index(&init_net, ifindex); |
72 | if (!dev) | 71 | if (!dev) |
73 | return -ENODEV; | 72 | return -ENODEV; |
74 | 73 | ||
75 | ieee80211_if_remove(dev); | 74 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
75 | |||
76 | ieee80211_if_remove(sdata); | ||
76 | 77 | ||
77 | return 0; | 78 | return 0; |
78 | } | 79 | } |
@@ -83,7 +84,6 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
83 | { | 84 | { |
84 | struct ieee80211_local *local = wiphy_priv(wiphy); | 85 | struct ieee80211_local *local = wiphy_priv(wiphy); |
85 | struct net_device *dev; | 86 | struct net_device *dev; |
86 | enum ieee80211_if_types itype; | ||
87 | struct ieee80211_sub_if_data *sdata; | 87 | struct ieee80211_sub_if_data *sdata; |
88 | int ret; | 88 | int ret; |
89 | 89 | ||
@@ -92,8 +92,7 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
92 | if (!dev) | 92 | if (!dev) |
93 | return -ENODEV; | 93 | return -ENODEV; |
94 | 94 | ||
95 | itype = nl80211_type_to_mac80211_type(type); | 95 | if (!nl80211_type_check(type)) |
96 | if (itype == IEEE80211_IF_TYPE_INVALID) | ||
97 | return -EINVAL; | 96 | return -EINVAL; |
98 | 97 | ||
99 | if (dev == local->mdev) | 98 | if (dev == local->mdev) |
@@ -101,16 +100,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | |||
101 | 100 | ||
102 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 101 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
103 | 102 | ||
104 | ret = ieee80211_if_change_type(sdata, itype); | 103 | ret = ieee80211_if_change_type(sdata, type); |
105 | if (ret) | 104 | if (ret) |
106 | return ret; | 105 | return ret; |
107 | 106 | ||
108 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) | 107 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) |
109 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 108 | ieee80211_sdata_set_mesh_id(sdata, |
110 | params->mesh_id_len, | 109 | params->mesh_id_len, |
111 | params->mesh_id); | 110 | params->mesh_id); |
112 | 111 | ||
113 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) | 112 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) |
114 | return 0; | 113 | return 0; |
115 | 114 | ||
116 | sdata->u.mntr_flags = *flags; | 115 | sdata->u.mntr_flags = *flags; |
@@ -365,7 +364,7 @@ static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
365 | sta = sta_info_get_by_idx(local, idx, dev); | 364 | sta = sta_info_get_by_idx(local, idx, dev); |
366 | if (sta) { | 365 | if (sta) { |
367 | ret = 0; | 366 | ret = 0; |
368 | memcpy(mac, sta->addr, ETH_ALEN); | 367 | memcpy(mac, sta->sta.addr, ETH_ALEN); |
369 | sta_set_sinfo(sta, sinfo); | 368 | sta_set_sinfo(sta, sinfo); |
370 | } | 369 | } |
371 | 370 | ||
@@ -506,7 +505,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
506 | 505 | ||
507 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 506 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
508 | 507 | ||
509 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 508 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
510 | return -EINVAL; | 509 | return -EINVAL; |
511 | 510 | ||
512 | old = sdata->u.ap.beacon; | 511 | old = sdata->u.ap.beacon; |
@@ -529,7 +528,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
529 | 528 | ||
530 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 529 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
531 | 530 | ||
532 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 531 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
533 | return -EINVAL; | 532 | return -EINVAL; |
534 | 533 | ||
535 | old = sdata->u.ap.beacon; | 534 | old = sdata->u.ap.beacon; |
@@ -551,7 +550,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
551 | 550 | ||
552 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 551 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
553 | 552 | ||
554 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 553 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
555 | return -EINVAL; | 554 | return -EINVAL; |
556 | 555 | ||
557 | old = sdata->u.ap.beacon; | 556 | old = sdata->u.ap.beacon; |
@@ -594,7 +593,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
594 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 593 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
595 | 594 | ||
596 | memset(msg->da, 0xff, ETH_ALEN); | 595 | memset(msg->da, 0xff, ETH_ALEN); |
597 | memcpy(msg->sa, sta->addr, ETH_ALEN); | 596 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
598 | msg->len = htons(6); | 597 | msg->len = htons(6); |
599 | msg->dsap = 0; | 598 | msg->dsap = 0; |
600 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ | 599 | msg->ssap = 0x01; /* NULL LSAP, CR Bit: Response */ |
@@ -649,9 +648,9 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
649 | */ | 648 | */ |
650 | 649 | ||
651 | if (params->aid) { | 650 | if (params->aid) { |
652 | sta->aid = params->aid; | 651 | sta->sta.aid = params->aid; |
653 | if (sta->aid > IEEE80211_MAX_AID) | 652 | if (sta->sta.aid > IEEE80211_MAX_AID) |
654 | sta->aid = 0; /* XXX: should this be an error? */ | 653 | sta->sta.aid = 0; /* XXX: should this be an error? */ |
655 | } | 654 | } |
656 | 655 | ||
657 | if (params->listen_interval >= 0) | 656 | if (params->listen_interval >= 0) |
@@ -668,7 +667,12 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
668 | rates |= BIT(j); | 667 | rates |= BIT(j); |
669 | } | 668 | } |
670 | } | 669 | } |
671 | sta->supp_rates[local->oper_channel->band] = rates; | 670 | sta->sta.supp_rates[local->oper_channel->band] = rates; |
671 | } | ||
672 | |||
673 | if (params->ht_capa) { | ||
674 | ieee80211_ht_cap_ie_to_ht_info(params->ht_capa, | ||
675 | &sta->sta.ht_info); | ||
672 | } | 676 | } |
673 | 677 | ||
674 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 678 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { |
@@ -701,8 +705,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
701 | if (params->vlan) { | 705 | if (params->vlan) { |
702 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 706 | sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
703 | 707 | ||
704 | if (sdata->vif.type != IEEE80211_IF_TYPE_VLAN && | 708 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
705 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | 709 | sdata->vif.type != NL80211_IFTYPE_AP) |
706 | return -EINVAL; | 710 | return -EINVAL; |
707 | } else | 711 | } else |
708 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 712 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -732,8 +736,8 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
732 | return err; | 736 | return err; |
733 | } | 737 | } |
734 | 738 | ||
735 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN || | 739 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
736 | sdata->vif.type == IEEE80211_IF_TYPE_AP) | 740 | sdata->vif.type == NL80211_IFTYPE_AP) |
737 | ieee80211_send_layer2_update(sta); | 741 | ieee80211_send_layer2_update(sta); |
738 | 742 | ||
739 | rcu_read_unlock(); | 743 | rcu_read_unlock(); |
@@ -797,8 +801,8 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
797 | if (params->vlan && params->vlan != sta->sdata->dev) { | 801 | if (params->vlan && params->vlan != sta->sdata->dev) { |
798 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); | 802 | vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); |
799 | 803 | ||
800 | if (vlansdata->vif.type != IEEE80211_IF_TYPE_VLAN && | 804 | if (vlansdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
801 | vlansdata->vif.type != IEEE80211_IF_TYPE_AP) { | 805 | vlansdata->vif.type != NL80211_IFTYPE_AP) { |
802 | rcu_read_unlock(); | 806 | rcu_read_unlock(); |
803 | return -EINVAL; | 807 | return -EINVAL; |
804 | } | 808 | } |
@@ -832,7 +836,7 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
832 | 836 | ||
833 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 837 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
834 | 838 | ||
835 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 839 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
836 | return -ENOTSUPP; | 840 | return -ENOTSUPP; |
837 | 841 | ||
838 | rcu_read_lock(); | 842 | rcu_read_lock(); |
@@ -842,13 +846,13 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
842 | return -ENOENT; | 846 | return -ENOENT; |
843 | } | 847 | } |
844 | 848 | ||
845 | err = mesh_path_add(dst, dev); | 849 | err = mesh_path_add(dst, sdata); |
846 | if (err) { | 850 | if (err) { |
847 | rcu_read_unlock(); | 851 | rcu_read_unlock(); |
848 | return err; | 852 | return err; |
849 | } | 853 | } |
850 | 854 | ||
851 | mpath = mesh_path_lookup(dst, dev); | 855 | mpath = mesh_path_lookup(dst, sdata); |
852 | if (!mpath) { | 856 | if (!mpath) { |
853 | rcu_read_unlock(); | 857 | rcu_read_unlock(); |
854 | return -ENXIO; | 858 | return -ENXIO; |
@@ -862,10 +866,12 @@ static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
862 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, | 866 | static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev, |
863 | u8 *dst) | 867 | u8 *dst) |
864 | { | 868 | { |
869 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
870 | |||
865 | if (dst) | 871 | if (dst) |
866 | return mesh_path_del(dst, dev); | 872 | return mesh_path_del(dst, sdata); |
867 | 873 | ||
868 | mesh_path_flush(dev); | 874 | mesh_path_flush(sdata); |
869 | return 0; | 875 | return 0; |
870 | } | 876 | } |
871 | 877 | ||
@@ -886,7 +892,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
886 | 892 | ||
887 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 893 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
888 | 894 | ||
889 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 895 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
890 | return -ENOTSUPP; | 896 | return -ENOTSUPP; |
891 | 897 | ||
892 | rcu_read_lock(); | 898 | rcu_read_lock(); |
@@ -897,7 +903,7 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
897 | return -ENOENT; | 903 | return -ENOENT; |
898 | } | 904 | } |
899 | 905 | ||
900 | mpath = mesh_path_lookup(dst, dev); | 906 | mpath = mesh_path_lookup(dst, sdata); |
901 | if (!mpath) { | 907 | if (!mpath) { |
902 | rcu_read_unlock(); | 908 | rcu_read_unlock(); |
903 | return -ENOENT; | 909 | return -ENOENT; |
@@ -913,7 +919,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | |||
913 | struct mpath_info *pinfo) | 919 | struct mpath_info *pinfo) |
914 | { | 920 | { |
915 | if (mpath->next_hop) | 921 | if (mpath->next_hop) |
916 | memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); | 922 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); |
917 | else | 923 | else |
918 | memset(next_hop, 0, ETH_ALEN); | 924 | memset(next_hop, 0, ETH_ALEN); |
919 | 925 | ||
@@ -961,11 +967,11 @@ static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
961 | 967 | ||
962 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 968 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
963 | 969 | ||
964 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 970 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
965 | return -ENOTSUPP; | 971 | return -ENOTSUPP; |
966 | 972 | ||
967 | rcu_read_lock(); | 973 | rcu_read_lock(); |
968 | mpath = mesh_path_lookup(dst, dev); | 974 | mpath = mesh_path_lookup(dst, sdata); |
969 | if (!mpath) { | 975 | if (!mpath) { |
970 | rcu_read_unlock(); | 976 | rcu_read_unlock(); |
971 | return -ENOENT; | 977 | return -ENOENT; |
@@ -989,11 +995,11 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
989 | 995 | ||
990 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 996 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
991 | 997 | ||
992 | if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT) | 998 | if (sdata->vif.type != NL80211_IFTYPE_MESH_POINT) |
993 | return -ENOTSUPP; | 999 | return -ENOTSUPP; |
994 | 1000 | ||
995 | rcu_read_lock(); | 1001 | rcu_read_lock(); |
996 | mpath = mesh_path_lookup_by_idx(idx, dev); | 1002 | mpath = mesh_path_lookup_by_idx(idx, sdata); |
997 | if (!mpath) { | 1003 | if (!mpath) { |
998 | rcu_read_unlock(); | 1004 | rcu_read_unlock(); |
999 | return -ENOENT; | 1005 | return -ENOENT; |
@@ -1005,6 +1011,42 @@ static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev, | |||
1005 | } | 1011 | } |
1006 | #endif | 1012 | #endif |
1007 | 1013 | ||
1014 | static int ieee80211_change_bss(struct wiphy *wiphy, | ||
1015 | struct net_device *dev, | ||
1016 | struct bss_parameters *params) | ||
1017 | { | ||
1018 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
1019 | struct ieee80211_sub_if_data *sdata; | ||
1020 | u32 changed = 0; | ||
1021 | |||
1022 | if (dev == local->mdev) | ||
1023 | return -EOPNOTSUPP; | ||
1024 | |||
1025 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1026 | |||
1027 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
1028 | return -EINVAL; | ||
1029 | |||
1030 | if (params->use_cts_prot >= 0) { | ||
1031 | sdata->bss_conf.use_cts_prot = params->use_cts_prot; | ||
1032 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
1033 | } | ||
1034 | if (params->use_short_preamble >= 0) { | ||
1035 | sdata->bss_conf.use_short_preamble = | ||
1036 | params->use_short_preamble; | ||
1037 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
1038 | } | ||
1039 | if (params->use_short_slot_time >= 0) { | ||
1040 | sdata->bss_conf.use_short_slot = | ||
1041 | params->use_short_slot_time; | ||
1042 | changed |= BSS_CHANGED_ERP_SLOT; | ||
1043 | } | ||
1044 | |||
1045 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1046 | |||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1008 | struct cfg80211_ops mac80211_config_ops = { | 1050 | struct cfg80211_ops mac80211_config_ops = { |
1009 | .add_virtual_intf = ieee80211_add_iface, | 1051 | .add_virtual_intf = ieee80211_add_iface, |
1010 | .del_virtual_intf = ieee80211_del_iface, | 1052 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1028,4 +1070,5 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1028 | .get_mpath = ieee80211_get_mpath, | 1070 | .get_mpath = ieee80211_get_mpath, |
1029 | .dump_mpath = ieee80211_dump_mpath, | 1071 | .dump_mpath = ieee80211_dump_mpath, |
1030 | #endif | 1072 | #endif |
1073 | .change_bss = ieee80211_change_bss, | ||
1031 | }; | 1074 | }; |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ee509f1109e2..24ce54463310 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -51,8 +51,6 @@ DEBUGFS_READONLY_FILE(antenna_sel_tx, 20, "%d", | |||
51 | local->hw.conf.antenna_sel_tx); | 51 | local->hw.conf.antenna_sel_tx); |
52 | DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", | 52 | DEBUGFS_READONLY_FILE(antenna_sel_rx, 20, "%d", |
53 | local->hw.conf.antenna_sel_rx); | 53 | local->hw.conf.antenna_sel_rx); |
54 | DEBUGFS_READONLY_FILE(bridge_packets, 20, "%d", | ||
55 | local->bridge_packets); | ||
56 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", | 54 | DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", |
57 | local->rts_threshold); | 55 | local->rts_threshold); |
58 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", | 56 | DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", |
@@ -206,7 +204,6 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
206 | DEBUGFS_ADD(frequency); | 204 | DEBUGFS_ADD(frequency); |
207 | DEBUGFS_ADD(antenna_sel_tx); | 205 | DEBUGFS_ADD(antenna_sel_tx); |
208 | DEBUGFS_ADD(antenna_sel_rx); | 206 | DEBUGFS_ADD(antenna_sel_rx); |
209 | DEBUGFS_ADD(bridge_packets); | ||
210 | DEBUGFS_ADD(rts_threshold); | 207 | DEBUGFS_ADD(rts_threshold); |
211 | DEBUGFS_ADD(fragmentation_threshold); | 208 | DEBUGFS_ADD(fragmentation_threshold); |
212 | DEBUGFS_ADD(short_retry_limit); | 209 | DEBUGFS_ADD(short_retry_limit); |
@@ -263,7 +260,6 @@ void debugfs_hw_del(struct ieee80211_local *local) | |||
263 | DEBUGFS_DEL(frequency); | 260 | DEBUGFS_DEL(frequency); |
264 | DEBUGFS_DEL(antenna_sel_tx); | 261 | DEBUGFS_DEL(antenna_sel_tx); |
265 | DEBUGFS_DEL(antenna_sel_rx); | 262 | DEBUGFS_DEL(antenna_sel_rx); |
266 | DEBUGFS_DEL(bridge_packets); | ||
267 | DEBUGFS_DEL(rts_threshold); | 263 | DEBUGFS_DEL(rts_threshold); |
268 | DEBUGFS_DEL(fragmentation_threshold); | 264 | DEBUGFS_DEL(fragmentation_threshold); |
269 | DEBUGFS_DEL(short_retry_limit); | 265 | DEBUGFS_DEL(short_retry_limit); |
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 7439b63df5d0..a3294d109322 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -206,7 +206,8 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
206 | rcu_read_lock(); | 206 | rcu_read_lock(); |
207 | sta = rcu_dereference(key->sta); | 207 | sta = rcu_dereference(key->sta); |
208 | if (sta) | 208 | if (sta) |
209 | sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr)); | 209 | sprintf(buf, "../../stations/%s", |
210 | print_mac(mac, sta->sta.addr)); | ||
210 | rcu_read_unlock(); | 211 | rcu_read_unlock(); |
211 | 212 | ||
212 | /* using sta as a boolean is fine outside RCU lock */ | 213 | /* using sta as a boolean is fine outside RCU lock */ |
@@ -265,7 +266,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) | |||
265 | key = sdata->default_key; | 266 | key = sdata->default_key; |
266 | if (key) { | 267 | if (key) { |
267 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 268 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
268 | sdata->debugfs.default_key = | 269 | sdata->common_debugfs.default_key = |
269 | debugfs_create_symlink("default_key", | 270 | debugfs_create_symlink("default_key", |
270 | sdata->debugfsdir, buf); | 271 | sdata->debugfsdir, buf); |
271 | } else | 272 | } else |
@@ -277,8 +278,8 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) | |||
277 | if (!sdata) | 278 | if (!sdata) |
278 | return; | 279 | return; |
279 | 280 | ||
280 | debugfs_remove(sdata->debugfs.default_key); | 281 | debugfs_remove(sdata->common_debugfs.default_key); |
281 | sdata->debugfs.default_key = NULL; | 282 | sdata->common_debugfs.default_key = NULL; |
282 | } | 283 | } |
283 | 284 | ||
284 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, | 285 | void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 8165df578c92..2a4515623776 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -173,7 +173,6 @@ IEEE80211_IF_FILE(assoc_tries, u.sta.assoc_tries, DEC); | |||
173 | IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); | 173 | IEEE80211_IF_FILE(auth_algs, u.sta.auth_algs, HEX); |
174 | IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); | 174 | IEEE80211_IF_FILE(auth_alg, u.sta.auth_alg, DEC); |
175 | IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); | 175 | IEEE80211_IF_FILE(auth_transaction, u.sta.auth_transaction, DEC); |
176 | IEEE80211_IF_FILE(num_beacons_sta, u.sta.num_beacons, DEC); | ||
177 | 176 | ||
178 | static ssize_t ieee80211_if_fmt_flags( | 177 | static ssize_t ieee80211_if_fmt_flags( |
179 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 178 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -192,7 +191,6 @@ __IEEE80211_IF_FILE(flags); | |||
192 | /* AP attributes */ | 191 | /* AP attributes */ |
193 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); | 192 | IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC); |
194 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); | 193 | IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC); |
195 | IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC); | ||
196 | 194 | ||
197 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( | 195 | static ssize_t ieee80211_if_fmt_num_buffered_multicast( |
198 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 196 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
@@ -207,37 +205,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
207 | 205 | ||
208 | #ifdef CONFIG_MAC80211_MESH | 206 | #ifdef CONFIG_MAC80211_MESH |
209 | /* Mesh stats attributes */ | 207 | /* Mesh stats attributes */ |
210 | IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); | 208 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); |
211 | IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC); | 209 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); |
212 | IEEE80211_IF_FILE(dropped_frames_no_route, | 210 | IEEE80211_IF_FILE(dropped_frames_no_route, |
213 | u.sta.mshstats.dropped_frames_no_route, DEC); | 211 | u.mesh.mshstats.dropped_frames_no_route, DEC); |
214 | IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); | 212 | IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC); |
215 | 213 | ||
216 | /* Mesh parameters */ | 214 | /* Mesh parameters */ |
217 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, | 215 | IEEE80211_IF_WFILE(dot11MeshMaxRetries, |
218 | u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); | 216 | u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8); |
219 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, | 217 | IEEE80211_IF_WFILE(dot11MeshRetryTimeout, |
220 | u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); | 218 | u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16); |
221 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, | 219 | IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, |
222 | u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); | 220 | u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16); |
223 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, | 221 | IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, |
224 | u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); | 222 | u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16); |
225 | IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); | 223 | IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8); |
226 | IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8); | 224 | IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8); |
227 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, | 225 | IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, |
228 | u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); | 226 | u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); |
229 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, | 227 | IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, |
230 | u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); | 228 | u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); |
231 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, | 229 | IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, |
232 | u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); | 230 | u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); |
233 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, | 231 | IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, |
234 | u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); | 232 | u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); |
235 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, | 233 | IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, |
236 | u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); | 234 | u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); |
237 | IEEE80211_IF_WFILE(path_refresh_time, | 235 | IEEE80211_IF_WFILE(path_refresh_time, |
238 | u.sta.mshcfg.path_refresh_time, DEC, u32); | 236 | u.mesh.mshcfg.path_refresh_time, DEC, u32); |
239 | IEEE80211_IF_WFILE(min_discovery_timeout, | 237 | IEEE80211_IF_WFILE(min_discovery_timeout, |
240 | u.sta.mshcfg.min_discovery_timeout, DEC, u16); | 238 | u.mesh.mshcfg.min_discovery_timeout, DEC, u16); |
241 | #endif | 239 | #endif |
242 | 240 | ||
243 | 241 | ||
@@ -265,7 +263,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
265 | DEBUGFS_ADD(auth_alg, sta); | 263 | DEBUGFS_ADD(auth_alg, sta); |
266 | DEBUGFS_ADD(auth_transaction, sta); | 264 | DEBUGFS_ADD(auth_transaction, sta); |
267 | DEBUGFS_ADD(flags, sta); | 265 | DEBUGFS_ADD(flags, sta); |
268 | DEBUGFS_ADD(num_beacons_sta, sta); | ||
269 | } | 266 | } |
270 | 267 | ||
271 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) | 268 | static void add_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -276,7 +273,6 @@ static void add_ap_files(struct ieee80211_sub_if_data *sdata) | |||
276 | 273 | ||
277 | DEBUGFS_ADD(num_sta_ps, ap); | 274 | DEBUGFS_ADD(num_sta_ps, ap); |
278 | DEBUGFS_ADD(dtim_count, ap); | 275 | DEBUGFS_ADD(dtim_count, ap); |
279 | DEBUGFS_ADD(num_beacons, ap); | ||
280 | DEBUGFS_ADD(num_buffered_multicast, ap); | 276 | DEBUGFS_ADD(num_buffered_multicast, ap); |
281 | } | 277 | } |
282 | 278 | ||
@@ -345,26 +341,26 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
345 | return; | 341 | return; |
346 | 342 | ||
347 | switch (sdata->vif.type) { | 343 | switch (sdata->vif.type) { |
348 | case IEEE80211_IF_TYPE_MESH_POINT: | 344 | case NL80211_IFTYPE_MESH_POINT: |
349 | #ifdef CONFIG_MAC80211_MESH | 345 | #ifdef CONFIG_MAC80211_MESH |
350 | add_mesh_stats(sdata); | 346 | add_mesh_stats(sdata); |
351 | add_mesh_config(sdata); | 347 | add_mesh_config(sdata); |
352 | #endif | 348 | #endif |
353 | /* fall through */ | 349 | break; |
354 | case IEEE80211_IF_TYPE_STA: | 350 | case NL80211_IFTYPE_STATION: |
355 | case IEEE80211_IF_TYPE_IBSS: | 351 | case NL80211_IFTYPE_ADHOC: |
356 | add_sta_files(sdata); | 352 | add_sta_files(sdata); |
357 | break; | 353 | break; |
358 | case IEEE80211_IF_TYPE_AP: | 354 | case NL80211_IFTYPE_AP: |
359 | add_ap_files(sdata); | 355 | add_ap_files(sdata); |
360 | break; | 356 | break; |
361 | case IEEE80211_IF_TYPE_WDS: | 357 | case NL80211_IFTYPE_WDS: |
362 | add_wds_files(sdata); | 358 | add_wds_files(sdata); |
363 | break; | 359 | break; |
364 | case IEEE80211_IF_TYPE_MNTR: | 360 | case NL80211_IFTYPE_MONITOR: |
365 | add_monitor_files(sdata); | 361 | add_monitor_files(sdata); |
366 | break; | 362 | break; |
367 | case IEEE80211_IF_TYPE_VLAN: | 363 | case NL80211_IFTYPE_AP_VLAN: |
368 | add_vlan_files(sdata); | 364 | add_vlan_files(sdata); |
369 | break; | 365 | break; |
370 | default: | 366 | default: |
@@ -398,7 +394,6 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata) | |||
398 | DEBUGFS_DEL(auth_alg, sta); | 394 | DEBUGFS_DEL(auth_alg, sta); |
399 | DEBUGFS_DEL(auth_transaction, sta); | 395 | DEBUGFS_DEL(auth_transaction, sta); |
400 | DEBUGFS_DEL(flags, sta); | 396 | DEBUGFS_DEL(flags, sta); |
401 | DEBUGFS_DEL(num_beacons_sta, sta); | ||
402 | } | 397 | } |
403 | 398 | ||
404 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) | 399 | static void del_ap_files(struct ieee80211_sub_if_data *sdata) |
@@ -409,7 +404,6 @@ static void del_ap_files(struct ieee80211_sub_if_data *sdata) | |||
409 | 404 | ||
410 | DEBUGFS_DEL(num_sta_ps, ap); | 405 | DEBUGFS_DEL(num_sta_ps, ap); |
411 | DEBUGFS_DEL(dtim_count, ap); | 406 | DEBUGFS_DEL(dtim_count, ap); |
412 | DEBUGFS_DEL(num_beacons, ap); | ||
413 | DEBUGFS_DEL(num_buffered_multicast, ap); | 407 | DEBUGFS_DEL(num_buffered_multicast, ap); |
414 | } | 408 | } |
415 | 409 | ||
@@ -482,26 +476,26 @@ static void del_files(struct ieee80211_sub_if_data *sdata) | |||
482 | return; | 476 | return; |
483 | 477 | ||
484 | switch (sdata->vif.type) { | 478 | switch (sdata->vif.type) { |
485 | case IEEE80211_IF_TYPE_MESH_POINT: | 479 | case NL80211_IFTYPE_MESH_POINT: |
486 | #ifdef CONFIG_MAC80211_MESH | 480 | #ifdef CONFIG_MAC80211_MESH |
487 | del_mesh_stats(sdata); | 481 | del_mesh_stats(sdata); |
488 | del_mesh_config(sdata); | 482 | del_mesh_config(sdata); |
489 | #endif | 483 | #endif |
490 | /* fall through */ | 484 | break; |
491 | case IEEE80211_IF_TYPE_STA: | 485 | case NL80211_IFTYPE_STATION: |
492 | case IEEE80211_IF_TYPE_IBSS: | 486 | case NL80211_IFTYPE_ADHOC: |
493 | del_sta_files(sdata); | 487 | del_sta_files(sdata); |
494 | break; | 488 | break; |
495 | case IEEE80211_IF_TYPE_AP: | 489 | case NL80211_IFTYPE_AP: |
496 | del_ap_files(sdata); | 490 | del_ap_files(sdata); |
497 | break; | 491 | break; |
498 | case IEEE80211_IF_TYPE_WDS: | 492 | case NL80211_IFTYPE_WDS: |
499 | del_wds_files(sdata); | 493 | del_wds_files(sdata); |
500 | break; | 494 | break; |
501 | case IEEE80211_IF_TYPE_MNTR: | 495 | case NL80211_IFTYPE_MONITOR: |
502 | del_monitor_files(sdata); | 496 | del_monitor_files(sdata); |
503 | break; | 497 | break; |
504 | case IEEE80211_IF_TYPE_VLAN: | 498 | case NL80211_IFTYPE_AP_VLAN: |
505 | del_vlan_files(sdata); | 499 | del_vlan_files(sdata); |
506 | break; | 500 | break; |
507 | default: | 501 | default: |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 79a062782d52..81f350eaf8a3 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -50,7 +50,7 @@ static const struct file_operations sta_ ##name## _ops = { \ | |||
50 | STA_READ_##format(name, field) \ | 50 | STA_READ_##format(name, field) \ |
51 | STA_OPS(name) | 51 | STA_OPS(name) |
52 | 52 | ||
53 | STA_FILE(aid, aid, D); | 53 | STA_FILE(aid, sta.aid, D); |
54 | STA_FILE(dev, sdata->dev->name, S); | 54 | STA_FILE(dev, sdata->dev->name, S); |
55 | STA_FILE(rx_packets, rx_packets, LU); | 55 | STA_FILE(rx_packets, rx_packets, LU); |
56 | STA_FILE(tx_packets, tx_packets, LU); | 56 | STA_FILE(tx_packets, tx_packets, LU); |
@@ -176,7 +176,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
176 | struct net_device *dev = sta->sdata->dev; | 176 | struct net_device *dev = sta->sdata->dev; |
177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 177 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
178 | struct ieee80211_hw *hw = &local->hw; | 178 | struct ieee80211_hw *hw = &local->hw; |
179 | u8 *da = sta->addr; | 179 | u8 *da = sta->sta.addr; |
180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, | 180 | static int tid_static_tx[16] = {0, 0, 0, 0, 0, 0, 0, 0, |
181 | 0, 0, 0, 0, 0, 0, 0, 0}; | 181 | 0, 0, 0, 0, 0, 0, 0, 0}; |
182 | static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, | 182 | static int tid_static_rx[16] = {1, 1, 1, 1, 1, 1, 1, 1, |
@@ -201,7 +201,7 @@ static ssize_t sta_agg_status_write(struct file *file, | |||
201 | tid_num = tid_num - 100; | 201 | tid_num = tid_num - 100; |
202 | if (tid_static_rx[tid_num] == 1) { | 202 | if (tid_static_rx[tid_num] == 1) { |
203 | strcpy(state, "off "); | 203 | strcpy(state, "off "); |
204 | ieee80211_sta_stop_rx_ba_session(dev, da, tid_num, 0, | 204 | ieee80211_sta_stop_rx_ba_session(sta->sdata, da, tid_num, 0, |
205 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 205 | WLAN_REASON_QSTA_REQUIRE_SETUP); |
206 | sta->ampdu_mlme.tid_state_rx[tid_num] |= | 206 | sta->ampdu_mlme.tid_state_rx[tid_num] |= |
207 | HT_AGG_STATE_DEBUGFS_CTL; | 207 | HT_AGG_STATE_DEBUGFS_CTL; |
@@ -253,7 +253,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
253 | if (!stations_dir) | 253 | if (!stations_dir) |
254 | return; | 254 | return; |
255 | 255 | ||
256 | mac = print_mac(mbuf, sta->addr); | 256 | mac = print_mac(mbuf, sta->sta.addr); |
257 | 257 | ||
258 | sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); | 258 | sta->debugfs.dir = debugfs_create_dir(mac, stations_dir); |
259 | if (!sta->debugfs.dir) | 259 | if (!sta->debugfs.dir) |
diff --git a/net/mac80211/event.c b/net/mac80211/event.c index 2280f40b4560..8de60de70bc9 100644 --- a/net/mac80211/event.c +++ b/net/mac80211/event.c | |||
@@ -8,7 +8,6 @@ | |||
8 | * mac80211 - events | 8 | * mac80211 - events |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/netdevice.h> | ||
12 | #include <net/iw_handler.h> | 11 | #include <net/iw_handler.h> |
13 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
14 | 13 | ||
@@ -17,7 +16,7 @@ | |||
17 | * (in the variable hdr) must be long enough to extract the TKIP | 16 | * (in the variable hdr) must be long enough to extract the TKIP |
18 | * fields like TSC | 17 | * fields like TSC |
19 | */ | 18 | */ |
20 | void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | 19 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
21 | struct ieee80211_hdr *hdr) | 20 | struct ieee80211_hdr *hdr) |
22 | { | 21 | { |
23 | union iwreq_data wrqu; | 22 | union iwreq_data wrqu; |
@@ -32,7 +31,7 @@ void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | |||
32 | print_mac(mac, hdr->addr2)); | 31 | print_mac(mac, hdr->addr2)); |
33 | memset(&wrqu, 0, sizeof(wrqu)); | 32 | memset(&wrqu, 0, sizeof(wrqu)); |
34 | wrqu.data.length = strlen(buf); | 33 | wrqu.data.length = strlen(buf); |
35 | wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf); | 34 | wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); |
36 | kfree(buf); | 35 | kfree(buf); |
37 | } | 36 | } |
38 | 37 | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c new file mode 100644 index 000000000000..dc7d9a3d70d5 --- /dev/null +++ b/net/mac80211/ht.c | |||
@@ -0,0 +1,992 @@ | |||
1 | /* | ||
2 | * HT handling | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2008, Intel Corporation | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/ieee80211.h> | ||
17 | #include <net/wireless.h> | ||
18 | #include <net/mac80211.h> | ||
19 | #include "ieee80211_i.h" | ||
20 | #include "sta_info.h" | ||
21 | #include "wme.h" | ||
22 | |||
23 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
24 | struct ieee80211_ht_info *ht_info) | ||
25 | { | ||
26 | |||
27 | if (ht_info == NULL) | ||
28 | return -EINVAL; | ||
29 | |||
30 | memset(ht_info, 0, sizeof(*ht_info)); | ||
31 | |||
32 | if (ht_cap_ie) { | ||
33 | u8 ampdu_info = ht_cap_ie->ampdu_params_info; | ||
34 | |||
35 | ht_info->ht_supported = 1; | ||
36 | ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); | ||
37 | ht_info->ampdu_factor = | ||
38 | ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; | ||
39 | ht_info->ampdu_density = | ||
40 | (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; | ||
41 | memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); | ||
42 | } else | ||
43 | ht_info->ht_supported = 0; | ||
44 | |||
45 | return 0; | ||
46 | } | ||
47 | |||
48 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
49 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
50 | struct ieee80211_ht_bss_info *bss_info) | ||
51 | { | ||
52 | if (bss_info == NULL) | ||
53 | return -EINVAL; | ||
54 | |||
55 | memset(bss_info, 0, sizeof(*bss_info)); | ||
56 | |||
57 | if (ht_add_info_ie) { | ||
58 | u16 op_mode; | ||
59 | op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); | ||
60 | |||
61 | bss_info->primary_channel = ht_add_info_ie->control_chan; | ||
62 | bss_info->bss_cap = ht_add_info_ie->ht_param; | ||
63 | bss_info->bss_op_mode = (u8)(op_mode & 0xff); | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | ||
70 | const u8 *da, u16 tid, | ||
71 | u8 dialog_token, u16 start_seq_num, | ||
72 | u16 agg_size, u16 timeout) | ||
73 | { | ||
74 | struct ieee80211_local *local = sdata->local; | ||
75 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
76 | struct sk_buff *skb; | ||
77 | struct ieee80211_mgmt *mgmt; | ||
78 | u16 capab; | ||
79 | |||
80 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
81 | |||
82 | if (!skb) { | ||
83 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
84 | "for addba request frame\n", sdata->dev->name); | ||
85 | return; | ||
86 | } | ||
87 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
88 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
89 | memset(mgmt, 0, 24); | ||
90 | memcpy(mgmt->da, da, ETH_ALEN); | ||
91 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
92 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
93 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
94 | else | ||
95 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
96 | |||
97 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
98 | IEEE80211_STYPE_ACTION); | ||
99 | |||
100 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | ||
101 | |||
102 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
103 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | ||
104 | |||
105 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | ||
106 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
107 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
108 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
109 | |||
110 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | ||
111 | |||
112 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | ||
113 | mgmt->u.action.u.addba_req.start_seq_num = | ||
114 | cpu_to_le16(start_seq_num << 4); | ||
115 | |||
116 | ieee80211_tx_skb(sdata, skb, 0); | ||
117 | } | ||
118 | |||
119 | static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *da, u16 tid, | ||
120 | u8 dialog_token, u16 status, u16 policy, | ||
121 | u16 buf_size, u16 timeout) | ||
122 | { | ||
123 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
124 | struct ieee80211_local *local = sdata->local; | ||
125 | struct sk_buff *skb; | ||
126 | struct ieee80211_mgmt *mgmt; | ||
127 | u16 capab; | ||
128 | |||
129 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
130 | |||
131 | if (!skb) { | ||
132 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
133 | "for addba resp frame\n", sdata->dev->name); | ||
134 | return; | ||
135 | } | ||
136 | |||
137 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
138 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
139 | memset(mgmt, 0, 24); | ||
140 | memcpy(mgmt->da, da, ETH_ALEN); | ||
141 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
142 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
143 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
144 | else | ||
145 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
146 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
147 | IEEE80211_STYPE_ACTION); | ||
148 | |||
149 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | ||
150 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
151 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | ||
152 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
153 | |||
154 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | ||
155 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
156 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
157 | |||
158 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | ||
159 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | ||
160 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | ||
161 | |||
162 | ieee80211_tx_skb(sdata, skb, 0); | ||
163 | } | ||
164 | |||
165 | static void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | ||
166 | const u8 *da, u16 tid, | ||
167 | u16 initiator, u16 reason_code) | ||
168 | { | ||
169 | struct ieee80211_local *local = sdata->local; | ||
170 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
171 | struct sk_buff *skb; | ||
172 | struct ieee80211_mgmt *mgmt; | ||
173 | u16 params; | ||
174 | |||
175 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
176 | |||
177 | if (!skb) { | ||
178 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
179 | "for delba frame\n", sdata->dev->name); | ||
180 | return; | ||
181 | } | ||
182 | |||
183 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
184 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
185 | memset(mgmt, 0, 24); | ||
186 | memcpy(mgmt->da, da, ETH_ALEN); | ||
187 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
188 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
189 | memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN); | ||
190 | else | ||
191 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
192 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
193 | IEEE80211_STYPE_ACTION); | ||
194 | |||
195 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); | ||
196 | |||
197 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | ||
198 | mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | ||
199 | params = (u16)(initiator << 11); /* bit 11 initiator */ | ||
200 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | ||
201 | |||
202 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | ||
203 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | ||
204 | |||
205 | ieee80211_tx_skb(sdata, skb, 0); | ||
206 | } | ||
207 | |||
208 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | ||
209 | { | ||
210 | struct ieee80211_local *local = sdata->local; | ||
211 | struct sk_buff *skb; | ||
212 | struct ieee80211_bar *bar; | ||
213 | u16 bar_control = 0; | ||
214 | |||
215 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | ||
216 | if (!skb) { | ||
217 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
218 | "bar frame\n", sdata->dev->name); | ||
219 | return; | ||
220 | } | ||
221 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
222 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
223 | memset(bar, 0, sizeof(*bar)); | ||
224 | bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | | ||
225 | IEEE80211_STYPE_BACK_REQ); | ||
226 | memcpy(bar->ra, ra, ETH_ALEN); | ||
227 | memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN); | ||
228 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
229 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
230 | bar_control |= (u16)(tid << 12); | ||
231 | bar->control = cpu_to_le16(bar_control); | ||
232 | bar->start_seq_num = cpu_to_le16(ssn); | ||
233 | |||
234 | ieee80211_tx_skb(sdata, skb, 0); | ||
235 | } | ||
236 | |||
237 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, | ||
238 | u16 initiator, u16 reason) | ||
239 | { | ||
240 | struct ieee80211_local *local = sdata->local; | ||
241 | struct ieee80211_hw *hw = &local->hw; | ||
242 | struct sta_info *sta; | ||
243 | int ret, i; | ||
244 | DECLARE_MAC_BUF(mac); | ||
245 | |||
246 | rcu_read_lock(); | ||
247 | |||
248 | sta = sta_info_get(local, ra); | ||
249 | if (!sta) { | ||
250 | rcu_read_unlock(); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | /* check if TID is in operational state */ | ||
255 | spin_lock_bh(&sta->lock); | ||
256 | if (sta->ampdu_mlme.tid_state_rx[tid] | ||
257 | != HT_AGG_STATE_OPERATIONAL) { | ||
258 | spin_unlock_bh(&sta->lock); | ||
259 | rcu_read_unlock(); | ||
260 | return; | ||
261 | } | ||
262 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
263 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
264 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
265 | spin_unlock_bh(&sta->lock); | ||
266 | |||
267 | /* stop HW Rx aggregation. ampdu_action existence | ||
268 | * already verified in session init so we add the BUG_ON */ | ||
269 | BUG_ON(!local->ops->ampdu_action); | ||
270 | |||
271 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
272 | printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", | ||
273 | print_mac(mac, ra), tid); | ||
274 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
275 | |||
276 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
277 | &sta->sta, tid, NULL); | ||
278 | if (ret) | ||
279 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
280 | "aggregation for tid %d\n", tid); | ||
281 | |||
282 | /* shutdown timer has not expired */ | ||
283 | if (initiator != WLAN_BACK_TIMER) | ||
284 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
285 | |||
286 | /* check if this is a self generated aggregation halt */ | ||
287 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
288 | ieee80211_send_delba(sdata, ra, tid, 0, reason); | ||
289 | |||
290 | /* free the reordering buffer */ | ||
291 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
292 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
293 | /* release the reordered frames */ | ||
294 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
295 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
296 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
297 | } | ||
298 | } | ||
299 | /* free resources */ | ||
300 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
301 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
302 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
303 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
304 | |||
305 | rcu_read_unlock(); | ||
306 | } | ||
307 | |||
308 | |||
309 | /* | ||
310 | * After sending add Block Ack request we activated a timer until | ||
311 | * add Block Ack response will arrive from the recipient. | ||
312 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
313 | */ | ||
314 | static void sta_addba_resp_timer_expired(unsigned long data) | ||
315 | { | ||
316 | /* not an elegant detour, but there is no choice as the timer passes | ||
317 | * only one argument, and both sta_info and TID are needed, so init | ||
318 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
319 | * array gives the sta through container_of */ | ||
320 | u16 tid = *(u8 *)data; | ||
321 | struct sta_info *temp_sta = container_of((void *)data, | ||
322 | struct sta_info, timer_to_tid[tid]); | ||
323 | |||
324 | struct ieee80211_local *local = temp_sta->local; | ||
325 | struct ieee80211_hw *hw = &local->hw; | ||
326 | struct sta_info *sta; | ||
327 | u8 *state; | ||
328 | |||
329 | rcu_read_lock(); | ||
330 | |||
331 | sta = sta_info_get(local, temp_sta->sta.addr); | ||
332 | if (!sta) { | ||
333 | rcu_read_unlock(); | ||
334 | return; | ||
335 | } | ||
336 | |||
337 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
338 | /* check if the TID waits for addBA response */ | ||
339 | spin_lock_bh(&sta->lock); | ||
340 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
341 | spin_unlock_bh(&sta->lock); | ||
342 | *state = HT_AGG_STATE_IDLE; | ||
343 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
344 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | ||
345 | "expecting addBA response there", tid); | ||
346 | #endif | ||
347 | goto timer_expired_exit; | ||
348 | } | ||
349 | |||
350 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
351 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
352 | #endif | ||
353 | |||
354 | /* go through the state check in stop_BA_session */ | ||
355 | *state = HT_AGG_STATE_OPERATIONAL; | ||
356 | spin_unlock_bh(&sta->lock); | ||
357 | ieee80211_stop_tx_ba_session(hw, temp_sta->sta.addr, tid, | ||
358 | WLAN_BACK_INITIATOR); | ||
359 | |||
360 | timer_expired_exit: | ||
361 | rcu_read_unlock(); | ||
362 | } | ||
363 | |||
364 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr) | ||
365 | { | ||
366 | struct ieee80211_local *local = sdata->local; | ||
367 | int i; | ||
368 | |||
369 | for (i = 0; i < STA_TID_NUM; i++) { | ||
370 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | ||
371 | WLAN_BACK_INITIATOR); | ||
372 | ieee80211_sta_stop_rx_ba_session(sdata, addr, i, | ||
373 | WLAN_BACK_RECIPIENT, | ||
374 | WLAN_REASON_QSTA_LEAVE_QBSS); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
379 | { | ||
380 | struct ieee80211_local *local = hw_to_local(hw); | ||
381 | struct sta_info *sta; | ||
382 | struct ieee80211_sub_if_data *sdata; | ||
383 | u16 start_seq_num; | ||
384 | u8 *state; | ||
385 | int ret; | ||
386 | DECLARE_MAC_BUF(mac); | ||
387 | |||
388 | if (tid >= STA_TID_NUM) | ||
389 | return -EINVAL; | ||
390 | |||
391 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
392 | printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", | ||
393 | print_mac(mac, ra), tid); | ||
394 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
395 | |||
396 | rcu_read_lock(); | ||
397 | |||
398 | sta = sta_info_get(local, ra); | ||
399 | if (!sta) { | ||
400 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
401 | printk(KERN_DEBUG "Could not find the station\n"); | ||
402 | #endif | ||
403 | ret = -ENOENT; | ||
404 | goto exit; | ||
405 | } | ||
406 | |||
407 | spin_lock_bh(&sta->lock); | ||
408 | |||
409 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
410 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
411 | ret = -EBUSY; | ||
412 | goto err_unlock_sta; | ||
413 | } | ||
414 | |||
415 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
416 | /* check if the TID is not in aggregation flow already */ | ||
417 | if (*state != HT_AGG_STATE_IDLE) { | ||
418 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
419 | printk(KERN_DEBUG "BA request denied - session is not " | ||
420 | "idle on tid %u\n", tid); | ||
421 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
422 | ret = -EAGAIN; | ||
423 | goto err_unlock_sta; | ||
424 | } | ||
425 | |||
426 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
427 | sta->ampdu_mlme.tid_tx[tid] = | ||
428 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
429 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
430 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
431 | if (net_ratelimit()) | ||
432 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
433 | tid); | ||
434 | #endif | ||
435 | ret = -ENOMEM; | ||
436 | goto err_unlock_sta; | ||
437 | } | ||
438 | /* Tx timer */ | ||
439 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
440 | sta_addba_resp_timer_expired; | ||
441 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
442 | (unsigned long)&sta->timer_to_tid[tid]; | ||
443 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
444 | |||
445 | /* create a new queue for this aggregation */ | ||
446 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
447 | |||
448 | /* case no queue is available to aggregation | ||
449 | * don't switch to aggregation */ | ||
450 | if (ret) { | ||
451 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
452 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | ||
453 | " tid %d\n", tid); | ||
454 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
455 | goto err_unlock_queue; | ||
456 | } | ||
457 | sdata = sta->sdata; | ||
458 | |||
459 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
460 | * call back right away, it must see that the flow has begun */ | ||
461 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
462 | |||
463 | /* This is slightly racy because the queue isn't stopped */ | ||
464 | start_seq_num = sta->tid_seq[tid]; | ||
465 | |||
466 | if (local->ops->ampdu_action) | ||
467 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
468 | &sta->sta, tid, &start_seq_num); | ||
469 | |||
470 | if (ret) { | ||
471 | /* No need to requeue the packets in the agg queue, since we | ||
472 | * held the tx lock: no packet could be enqueued to the newly | ||
473 | * allocated queue */ | ||
474 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
475 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
476 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
477 | " tid %d\n", tid); | ||
478 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
479 | *state = HT_AGG_STATE_IDLE; | ||
480 | goto err_unlock_queue; | ||
481 | } | ||
482 | |||
483 | /* Will put all the packets in the new SW queue */ | ||
484 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
485 | spin_unlock_bh(&sta->lock); | ||
486 | |||
487 | /* send an addBA request */ | ||
488 | sta->ampdu_mlme.dialog_token_allocator++; | ||
489 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
490 | sta->ampdu_mlme.dialog_token_allocator; | ||
491 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
492 | |||
493 | |||
494 | ieee80211_send_addba_request(sta->sdata, ra, tid, | ||
495 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
496 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
497 | 0x40, 5000); | ||
498 | /* activate the timer for the recipient's addBA response */ | ||
499 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
500 | jiffies + ADDBA_RESP_INTERVAL; | ||
501 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
502 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
503 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
504 | #endif | ||
505 | goto exit; | ||
506 | |||
507 | err_unlock_queue: | ||
508 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
509 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
510 | ret = -EBUSY; | ||
511 | err_unlock_sta: | ||
512 | spin_unlock_bh(&sta->lock); | ||
513 | exit: | ||
514 | rcu_read_unlock(); | ||
515 | return ret; | ||
516 | } | ||
517 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
518 | |||
519 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
520 | u8 *ra, u16 tid, | ||
521 | enum ieee80211_back_parties initiator) | ||
522 | { | ||
523 | struct ieee80211_local *local = hw_to_local(hw); | ||
524 | struct sta_info *sta; | ||
525 | u8 *state; | ||
526 | int ret = 0; | ||
527 | DECLARE_MAC_BUF(mac); | ||
528 | |||
529 | if (tid >= STA_TID_NUM) | ||
530 | return -EINVAL; | ||
531 | |||
532 | rcu_read_lock(); | ||
533 | sta = sta_info_get(local, ra); | ||
534 | if (!sta) { | ||
535 | rcu_read_unlock(); | ||
536 | return -ENOENT; | ||
537 | } | ||
538 | |||
539 | /* check if the TID is in aggregation */ | ||
540 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
541 | spin_lock_bh(&sta->lock); | ||
542 | |||
543 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
544 | ret = -ENOENT; | ||
545 | goto stop_BA_exit; | ||
546 | } | ||
547 | |||
548 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
549 | printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", | ||
550 | print_mac(mac, ra), tid); | ||
551 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
552 | |||
553 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
554 | |||
555 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
556 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
557 | |||
558 | if (local->ops->ampdu_action) | ||
559 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, | ||
560 | &sta->sta, tid, NULL); | ||
561 | |||
562 | /* case HW denied going back to legacy */ | ||
563 | if (ret) { | ||
564 | WARN_ON(ret != -EBUSY); | ||
565 | *state = HT_AGG_STATE_OPERATIONAL; | ||
566 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
567 | goto stop_BA_exit; | ||
568 | } | ||
569 | |||
570 | stop_BA_exit: | ||
571 | spin_unlock_bh(&sta->lock); | ||
572 | rcu_read_unlock(); | ||
573 | return ret; | ||
574 | } | ||
575 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
576 | |||
577 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
578 | { | ||
579 | struct ieee80211_local *local = hw_to_local(hw); | ||
580 | struct sta_info *sta; | ||
581 | u8 *state; | ||
582 | DECLARE_MAC_BUF(mac); | ||
583 | |||
584 | if (tid >= STA_TID_NUM) { | ||
585 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
586 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
587 | tid, STA_TID_NUM); | ||
588 | #endif | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | rcu_read_lock(); | ||
593 | sta = sta_info_get(local, ra); | ||
594 | if (!sta) { | ||
595 | rcu_read_unlock(); | ||
596 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
597 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
598 | print_mac(mac, ra)); | ||
599 | #endif | ||
600 | return; | ||
601 | } | ||
602 | |||
603 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
604 | spin_lock_bh(&sta->lock); | ||
605 | |||
606 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
607 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
608 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
609 | *state); | ||
610 | #endif | ||
611 | spin_unlock_bh(&sta->lock); | ||
612 | rcu_read_unlock(); | ||
613 | return; | ||
614 | } | ||
615 | |||
616 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
617 | |||
618 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
619 | |||
620 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
621 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
622 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
623 | #endif | ||
624 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
625 | } | ||
626 | spin_unlock_bh(&sta->lock); | ||
627 | rcu_read_unlock(); | ||
628 | } | ||
629 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
630 | |||
631 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
632 | { | ||
633 | struct ieee80211_local *local = hw_to_local(hw); | ||
634 | struct sta_info *sta; | ||
635 | u8 *state; | ||
636 | int agg_queue; | ||
637 | DECLARE_MAC_BUF(mac); | ||
638 | |||
639 | if (tid >= STA_TID_NUM) { | ||
640 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
641 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
642 | tid, STA_TID_NUM); | ||
643 | #endif | ||
644 | return; | ||
645 | } | ||
646 | |||
647 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
648 | printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", | ||
649 | print_mac(mac, ra), tid); | ||
650 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
651 | |||
652 | rcu_read_lock(); | ||
653 | sta = sta_info_get(local, ra); | ||
654 | if (!sta) { | ||
655 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
656 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
657 | print_mac(mac, ra)); | ||
658 | #endif | ||
659 | rcu_read_unlock(); | ||
660 | return; | ||
661 | } | ||
662 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
663 | |||
664 | /* NOTE: no need to use sta->lock in this state check, as | ||
665 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
666 | * pass through per sta/tid | ||
667 | */ | ||
668 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
669 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
670 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
671 | #endif | ||
672 | rcu_read_unlock(); | ||
673 | return; | ||
674 | } | ||
675 | |||
676 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
677 | ieee80211_send_delba(sta->sdata, ra, tid, | ||
678 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
679 | |||
680 | agg_queue = sta->tid_to_tx_q[tid]; | ||
681 | |||
682 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
683 | |||
684 | /* We just requeued the all the frames that were in the | ||
685 | * removed queue, and since we might miss a softirq we do | ||
686 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
687 | * here as this queue is not necessarily stopped | ||
688 | */ | ||
689 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | ||
690 | spin_lock_bh(&sta->lock); | ||
691 | *state = HT_AGG_STATE_IDLE; | ||
692 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
693 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
694 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
695 | spin_unlock_bh(&sta->lock); | ||
696 | |||
697 | rcu_read_unlock(); | ||
698 | } | ||
699 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
700 | |||
701 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
702 | const u8 *ra, u16 tid) | ||
703 | { | ||
704 | struct ieee80211_local *local = hw_to_local(hw); | ||
705 | struct ieee80211_ra_tid *ra_tid; | ||
706 | struct sk_buff *skb = dev_alloc_skb(0); | ||
707 | |||
708 | if (unlikely(!skb)) { | ||
709 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
710 | if (net_ratelimit()) | ||
711 | printk(KERN_WARNING "%s: Not enough memory, " | ||
712 | "dropping start BA session", skb->dev->name); | ||
713 | #endif | ||
714 | return; | ||
715 | } | ||
716 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
717 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
718 | ra_tid->tid = tid; | ||
719 | |||
720 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
721 | skb_queue_tail(&local->skb_queue, skb); | ||
722 | tasklet_schedule(&local->tasklet); | ||
723 | } | ||
724 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
725 | |||
726 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
727 | const u8 *ra, u16 tid) | ||
728 | { | ||
729 | struct ieee80211_local *local = hw_to_local(hw); | ||
730 | struct ieee80211_ra_tid *ra_tid; | ||
731 | struct sk_buff *skb = dev_alloc_skb(0); | ||
732 | |||
733 | if (unlikely(!skb)) { | ||
734 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
735 | if (net_ratelimit()) | ||
736 | printk(KERN_WARNING "%s: Not enough memory, " | ||
737 | "dropping stop BA session", skb->dev->name); | ||
738 | #endif | ||
739 | return; | ||
740 | } | ||
741 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
742 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
743 | ra_tid->tid = tid; | ||
744 | |||
745 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
746 | skb_queue_tail(&local->skb_queue, skb); | ||
747 | tasklet_schedule(&local->tasklet); | ||
748 | } | ||
749 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
750 | |||
751 | /* | ||
752 | * After accepting the AddBA Request we activated a timer, | ||
753 | * resetting it after each frame that arrives from the originator. | ||
754 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | ||
755 | */ | ||
756 | static void sta_rx_agg_session_timer_expired(unsigned long data) | ||
757 | { | ||
758 | /* not an elegant detour, but there is no choice as the timer passes | ||
759 | * only one argument, and various sta_info are needed here, so init | ||
760 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
761 | * array gives the sta through container_of */ | ||
762 | u8 *ptid = (u8 *)data; | ||
763 | u8 *timer_to_id = ptid - *ptid; | ||
764 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
765 | timer_to_tid[0]); | ||
766 | |||
767 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
768 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
769 | #endif | ||
770 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | ||
771 | (u16)*ptid, WLAN_BACK_TIMER, | ||
772 | WLAN_REASON_QSTA_TIMEOUT); | ||
773 | } | ||
774 | |||
775 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
776 | struct sta_info *sta, | ||
777 | struct ieee80211_mgmt *mgmt, | ||
778 | size_t len) | ||
779 | { | ||
780 | struct ieee80211_hw *hw = &local->hw; | ||
781 | struct ieee80211_conf *conf = &hw->conf; | ||
782 | struct tid_ampdu_rx *tid_agg_rx; | ||
783 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
784 | u8 dialog_token; | ||
785 | int ret = -EOPNOTSUPP; | ||
786 | DECLARE_MAC_BUF(mac); | ||
787 | |||
788 | /* extract session parameters from addba request frame */ | ||
789 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
790 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
791 | start_seq_num = | ||
792 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
793 | |||
794 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
795 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
796 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
797 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
798 | |||
799 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
800 | |||
801 | /* sanity check for incoming parameters: | ||
802 | * check if configuration can support the BA policy | ||
803 | * and if buffer size does not exceeds max value */ | ||
804 | if (((ba_policy != 1) | ||
805 | && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
806 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
807 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
808 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
809 | if (net_ratelimit()) | ||
810 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
811 | "%s on tid %u. policy %d, buffer size %d\n", | ||
812 | print_mac(mac, mgmt->sa), tid, ba_policy, | ||
813 | buf_size); | ||
814 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
815 | goto end_no_lock; | ||
816 | } | ||
817 | /* determine default buffer size */ | ||
818 | if (buf_size == 0) { | ||
819 | struct ieee80211_supported_band *sband; | ||
820 | |||
821 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
822 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
823 | buf_size = buf_size << sband->ht_info.ampdu_factor; | ||
824 | } | ||
825 | |||
826 | |||
827 | /* examine state machine */ | ||
828 | spin_lock_bh(&sta->lock); | ||
829 | |||
830 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | ||
831 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
832 | if (net_ratelimit()) | ||
833 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
834 | "%s on tid %u\n", | ||
835 | print_mac(mac, mgmt->sa), tid); | ||
836 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
837 | goto end; | ||
838 | } | ||
839 | |||
840 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
841 | sta->ampdu_mlme.tid_rx[tid] = | ||
842 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
843 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
844 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
845 | if (net_ratelimit()) | ||
846 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
847 | tid); | ||
848 | #endif | ||
849 | goto end; | ||
850 | } | ||
851 | /* rx timer */ | ||
852 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
853 | sta_rx_agg_session_timer_expired; | ||
854 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
855 | (unsigned long)&sta->timer_to_tid[tid]; | ||
856 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
857 | |||
858 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
859 | |||
860 | /* prepare reordering buffer */ | ||
861 | tid_agg_rx->reorder_buf = | ||
862 | kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
863 | if (!tid_agg_rx->reorder_buf) { | ||
864 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
865 | if (net_ratelimit()) | ||
866 | printk(KERN_ERR "can not allocate reordering buffer " | ||
867 | "to tid %d\n", tid); | ||
868 | #endif | ||
869 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
870 | goto end; | ||
871 | } | ||
872 | memset(tid_agg_rx->reorder_buf, 0, | ||
873 | buf_size * sizeof(struct sk_buff *)); | ||
874 | |||
875 | if (local->ops->ampdu_action) | ||
876 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
877 | &sta->sta, tid, &start_seq_num); | ||
878 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
879 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
880 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
881 | |||
882 | if (ret) { | ||
883 | kfree(tid_agg_rx->reorder_buf); | ||
884 | kfree(tid_agg_rx); | ||
885 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
886 | goto end; | ||
887 | } | ||
888 | |||
889 | /* change state and send addba resp */ | ||
890 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
891 | tid_agg_rx->dialog_token = dialog_token; | ||
892 | tid_agg_rx->ssn = start_seq_num; | ||
893 | tid_agg_rx->head_seq_num = start_seq_num; | ||
894 | tid_agg_rx->buf_size = buf_size; | ||
895 | tid_agg_rx->timeout = timeout; | ||
896 | tid_agg_rx->stored_mpdu_num = 0; | ||
897 | status = WLAN_STATUS_SUCCESS; | ||
898 | end: | ||
899 | spin_unlock_bh(&sta->lock); | ||
900 | |||
901 | end_no_lock: | ||
902 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | ||
903 | dialog_token, status, 1, buf_size, timeout); | ||
904 | } | ||
905 | |||
906 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
907 | struct sta_info *sta, | ||
908 | struct ieee80211_mgmt *mgmt, | ||
909 | size_t len) | ||
910 | { | ||
911 | struct ieee80211_hw *hw = &local->hw; | ||
912 | u16 capab; | ||
913 | u16 tid; | ||
914 | u8 *state; | ||
915 | |||
916 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | ||
917 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
918 | |||
919 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
920 | |||
921 | spin_lock_bh(&sta->lock); | ||
922 | |||
923 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
924 | spin_unlock_bh(&sta->lock); | ||
925 | return; | ||
926 | } | ||
927 | |||
928 | if (mgmt->u.action.u.addba_resp.dialog_token != | ||
929 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | ||
930 | spin_unlock_bh(&sta->lock); | ||
931 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
932 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
933 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
934 | return; | ||
935 | } | ||
936 | |||
937 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
938 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
939 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
940 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
941 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
942 | == WLAN_STATUS_SUCCESS) { | ||
943 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
944 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
945 | |||
946 | if (*state == HT_AGG_STATE_OPERATIONAL) | ||
947 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
948 | |||
949 | spin_unlock_bh(&sta->lock); | ||
950 | } else { | ||
951 | sta->ampdu_mlme.addba_req_num[tid]++; | ||
952 | /* this will allow the state check in stop_BA_session */ | ||
953 | *state = HT_AGG_STATE_OPERATIONAL; | ||
954 | spin_unlock_bh(&sta->lock); | ||
955 | ieee80211_stop_tx_ba_session(hw, sta->sta.addr, tid, | ||
956 | WLAN_BACK_INITIATOR); | ||
957 | } | ||
958 | } | ||
959 | |||
960 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | ||
961 | struct sta_info *sta, | ||
962 | struct ieee80211_mgmt *mgmt, size_t len) | ||
963 | { | ||
964 | struct ieee80211_local *local = sdata->local; | ||
965 | u16 tid, params; | ||
966 | u16 initiator; | ||
967 | DECLARE_MAC_BUF(mac); | ||
968 | |||
969 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | ||
970 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | ||
971 | initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; | ||
972 | |||
973 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
974 | if (net_ratelimit()) | ||
975 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | ||
976 | print_mac(mac, mgmt->sa), | ||
977 | initiator ? "initiator" : "recipient", tid, | ||
978 | mgmt->u.action.u.delba.reason_code); | ||
979 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
980 | |||
981 | if (initiator == WLAN_BACK_INITIATOR) | ||
982 | ieee80211_sta_stop_rx_ba_session(sdata, sta->sta.addr, tid, | ||
983 | WLAN_BACK_INITIATOR, 0); | ||
984 | else { /* WLAN_BACK_RECIPIENT */ | ||
985 | spin_lock_bh(&sta->lock); | ||
986 | sta->ampdu_mlme.tid_state_tx[tid] = | ||
987 | HT_AGG_STATE_OPERATIONAL; | ||
988 | spin_unlock_bh(&sta->lock); | ||
989 | ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid, | ||
990 | WLAN_BACK_RECIPIENT); | ||
991 | } | ||
992 | } | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 586a9b49b0fc..3912fba6d3d0 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -29,17 +29,6 @@ | |||
29 | #include "key.h" | 29 | #include "key.h" |
30 | #include "sta_info.h" | 30 | #include "sta_info.h" |
31 | 31 | ||
32 | /* ieee80211.o internal definitions, etc. These are not included into | ||
33 | * low-level drivers. */ | ||
34 | |||
35 | #ifndef ETH_P_PAE | ||
36 | #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ | ||
37 | #endif /* ETH_P_PAE */ | ||
38 | |||
39 | #define WLAN_FC_DATA_PRESENT(fc) (((fc) & 0x4c) == 0x08) | ||
40 | |||
41 | #define IEEE80211_FC(type, subtype) cpu_to_le16(type | subtype) | ||
42 | |||
43 | struct ieee80211_local; | 32 | struct ieee80211_local; |
44 | 33 | ||
45 | /* Maximum number of broadcast/multicast frames to buffer when some of the | 34 | /* Maximum number of broadcast/multicast frames to buffer when some of the |
@@ -61,6 +50,12 @@ struct ieee80211_local; | |||
61 | * increased memory use (about 2 kB of RAM per entry). */ | 50 | * increased memory use (about 2 kB of RAM per entry). */ |
62 | #define IEEE80211_FRAGMENT_MAX 4 | 51 | #define IEEE80211_FRAGMENT_MAX 4 |
63 | 52 | ||
53 | /* | ||
54 | * Time after which we ignore scan results and no longer report/use | ||
55 | * them in any way. | ||
56 | */ | ||
57 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
58 | |||
64 | struct ieee80211_fragment_entry { | 59 | struct ieee80211_fragment_entry { |
65 | unsigned long first_frag_time; | 60 | unsigned long first_frag_time; |
66 | unsigned int seq; | 61 | unsigned int seq; |
@@ -73,9 +68,9 @@ struct ieee80211_fragment_entry { | |||
73 | }; | 68 | }; |
74 | 69 | ||
75 | 70 | ||
76 | struct ieee80211_sta_bss { | 71 | struct ieee80211_bss { |
77 | struct list_head list; | 72 | struct list_head list; |
78 | struct ieee80211_sta_bss *hnext; | 73 | struct ieee80211_bss *hnext; |
79 | size_t ssid_len; | 74 | size_t ssid_len; |
80 | 75 | ||
81 | atomic_t users; | 76 | atomic_t users; |
@@ -87,16 +82,11 @@ struct ieee80211_sta_bss { | |||
87 | enum ieee80211_band band; | 82 | enum ieee80211_band band; |
88 | int freq; | 83 | int freq; |
89 | int signal, noise, qual; | 84 | int signal, noise, qual; |
90 | u8 *wpa_ie; | 85 | u8 *ies; /* all information elements from the last Beacon or Probe |
91 | size_t wpa_ie_len; | 86 | * Response frames; note Beacon frame is not allowed to |
92 | u8 *rsn_ie; | 87 | * override values from Probe Response */ |
93 | size_t rsn_ie_len; | 88 | size_t ies_len; |
94 | u8 *wmm_ie; | 89 | bool wmm_used; |
95 | size_t wmm_ie_len; | ||
96 | u8 *ht_ie; | ||
97 | size_t ht_ie_len; | ||
98 | u8 *ht_add_ie; | ||
99 | size_t ht_add_ie_len; | ||
100 | #ifdef CONFIG_MAC80211_MESH | 90 | #ifdef CONFIG_MAC80211_MESH |
101 | u8 *mesh_id; | 91 | u8 *mesh_id; |
102 | size_t mesh_id_len; | 92 | size_t mesh_id_len; |
@@ -108,7 +98,7 @@ struct ieee80211_sta_bss { | |||
108 | u64 timestamp; | 98 | u64 timestamp; |
109 | int beacon_int; | 99 | int beacon_int; |
110 | 100 | ||
111 | bool probe_resp; | 101 | unsigned long last_probe_resp; |
112 | unsigned long last_update; | 102 | unsigned long last_update; |
113 | 103 | ||
114 | /* during assocation, we save an ERP value from a probe response so | 104 | /* during assocation, we save an ERP value from a probe response so |
@@ -119,7 +109,7 @@ struct ieee80211_sta_bss { | |||
119 | u8 erp_value; | 109 | u8 erp_value; |
120 | }; | 110 | }; |
121 | 111 | ||
122 | static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) | 112 | static inline u8 *bss_mesh_cfg(struct ieee80211_bss *bss) |
123 | { | 113 | { |
124 | #ifdef CONFIG_MAC80211_MESH | 114 | #ifdef CONFIG_MAC80211_MESH |
125 | return bss->mesh_cfg; | 115 | return bss->mesh_cfg; |
@@ -127,7 +117,7 @@ static inline u8 *bss_mesh_cfg(struct ieee80211_sta_bss *bss) | |||
127 | return NULL; | 117 | return NULL; |
128 | } | 118 | } |
129 | 119 | ||
130 | static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) | 120 | static inline u8 *bss_mesh_id(struct ieee80211_bss *bss) |
131 | { | 121 | { |
132 | #ifdef CONFIG_MAC80211_MESH | 122 | #ifdef CONFIG_MAC80211_MESH |
133 | return bss->mesh_id; | 123 | return bss->mesh_id; |
@@ -135,7 +125,7 @@ static inline u8 *bss_mesh_id(struct ieee80211_sta_bss *bss) | |||
135 | return NULL; | 125 | return NULL; |
136 | } | 126 | } |
137 | 127 | ||
138 | static inline u8 bss_mesh_id_len(struct ieee80211_sta_bss *bss) | 128 | static inline u8 bss_mesh_id_len(struct ieee80211_bss *bss) |
139 | { | 129 | { |
140 | #ifdef CONFIG_MAC80211_MESH | 130 | #ifdef CONFIG_MAC80211_MESH |
141 | return bss->mesh_id_len; | 131 | return bss->mesh_id_len; |
@@ -174,7 +164,7 @@ struct ieee80211_tx_data { | |||
174 | struct sk_buff **extra_frag; | 164 | struct sk_buff **extra_frag; |
175 | int num_extra_frag; | 165 | int num_extra_frag; |
176 | 166 | ||
177 | u16 fc, ethertype; | 167 | u16 ethertype; |
178 | unsigned int flags; | 168 | unsigned int flags; |
179 | }; | 169 | }; |
180 | 170 | ||
@@ -202,7 +192,7 @@ struct ieee80211_rx_data { | |||
202 | struct ieee80211_rx_status *status; | 192 | struct ieee80211_rx_status *status; |
203 | struct ieee80211_rate *rate; | 193 | struct ieee80211_rate *rate; |
204 | 194 | ||
205 | u16 fc, ethertype; | 195 | u16 ethertype; |
206 | unsigned int flags; | 196 | unsigned int flags; |
207 | int sent_ps_buffered; | 197 | int sent_ps_buffered; |
208 | int queue; | 198 | int queue; |
@@ -239,7 +229,6 @@ struct ieee80211_if_ap { | |||
239 | struct sk_buff_head ps_bc_buf; | 229 | struct sk_buff_head ps_bc_buf; |
240 | atomic_t num_sta_ps; /* number of stations in PS mode */ | 230 | atomic_t num_sta_ps; /* number of stations in PS mode */ |
241 | int dtim_count; | 231 | int dtim_count; |
242 | int num_beacons; /* number of TXed beacon frames for this BSS */ | ||
243 | }; | 232 | }; |
244 | 233 | ||
245 | struct ieee80211_if_wds { | 234 | struct ieee80211_if_wds { |
@@ -300,48 +289,37 @@ struct mesh_config { | |||
300 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) | 289 | #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11) |
301 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) | 290 | #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12) |
302 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) | 291 | #define IEEE80211_STA_PRIVACY_INVOKED BIT(13) |
292 | /* flags for MLME request */ | ||
293 | #define IEEE80211_STA_REQ_SCAN 0 | ||
294 | #define IEEE80211_STA_REQ_DIRECT_PROBE 1 | ||
295 | #define IEEE80211_STA_REQ_AUTH 2 | ||
296 | #define IEEE80211_STA_REQ_RUN 3 | ||
297 | |||
298 | /* STA/IBSS MLME states */ | ||
299 | enum ieee80211_sta_mlme_state { | ||
300 | IEEE80211_STA_MLME_DISABLED, | ||
301 | IEEE80211_STA_MLME_DIRECT_PROBE, | ||
302 | IEEE80211_STA_MLME_AUTHENTICATE, | ||
303 | IEEE80211_STA_MLME_ASSOCIATE, | ||
304 | IEEE80211_STA_MLME_ASSOCIATED, | ||
305 | IEEE80211_STA_MLME_IBSS_SEARCH, | ||
306 | IEEE80211_STA_MLME_IBSS_JOINED, | ||
307 | }; | ||
308 | |||
309 | /* bitfield of allowed auth algs */ | ||
310 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | ||
311 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | ||
312 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) | ||
313 | |||
303 | struct ieee80211_if_sta { | 314 | struct ieee80211_if_sta { |
304 | struct timer_list timer; | 315 | struct timer_list timer; |
305 | struct work_struct work; | 316 | struct work_struct work; |
306 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; | 317 | u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN]; |
307 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 318 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
308 | enum { | 319 | enum ieee80211_sta_mlme_state state; |
309 | IEEE80211_DISABLED, IEEE80211_AUTHENTICATE, | ||
310 | IEEE80211_ASSOCIATE, IEEE80211_ASSOCIATED, | ||
311 | IEEE80211_IBSS_SEARCH, IEEE80211_IBSS_JOINED, | ||
312 | IEEE80211_MESH_UP | ||
313 | } state; | ||
314 | size_t ssid_len; | 320 | size_t ssid_len; |
315 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 321 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
316 | size_t scan_ssid_len; | 322 | size_t scan_ssid_len; |
317 | #ifdef CONFIG_MAC80211_MESH | ||
318 | struct timer_list mesh_path_timer; | ||
319 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
320 | size_t mesh_id_len; | ||
321 | /* Active Path Selection Protocol Identifier */ | ||
322 | u8 mesh_pp_id[4]; | ||
323 | /* Active Path Selection Metric Identifier */ | ||
324 | u8 mesh_pm_id[4]; | ||
325 | /* Congestion Control Mode Identifier */ | ||
326 | u8 mesh_cc_id[4]; | ||
327 | /* Local mesh Destination Sequence Number */ | ||
328 | u32 dsn; | ||
329 | /* Last used PREQ ID */ | ||
330 | u32 preq_id; | ||
331 | atomic_t mpaths; | ||
332 | /* Timestamp of last DSN update */ | ||
333 | unsigned long last_dsn_update; | ||
334 | /* Timestamp of last DSN sent */ | ||
335 | unsigned long last_preq; | ||
336 | struct mesh_rmc *rmc; | ||
337 | spinlock_t mesh_preq_queue_lock; | ||
338 | struct mesh_preq_queue preq_queue; | ||
339 | int preq_queue_len; | ||
340 | struct mesh_stats mshstats; | ||
341 | struct mesh_config mshcfg; | ||
342 | u32 mesh_seqnum; | ||
343 | bool accepting_plinks; | ||
344 | #endif | ||
345 | u16 aid; | 323 | u16 aid; |
346 | u16 ap_capab, capab; | 324 | u16 ap_capab, capab; |
347 | u8 *extra_ie; /* to be added to the end of AssocReq */ | 325 | u8 *extra_ie; /* to be added to the end of AssocReq */ |
@@ -353,20 +331,17 @@ struct ieee80211_if_sta { | |||
353 | 331 | ||
354 | struct sk_buff_head skb_queue; | 332 | struct sk_buff_head skb_queue; |
355 | 333 | ||
356 | int auth_tries, assoc_tries; | 334 | int assoc_scan_tries; /* number of scans done pre-association */ |
335 | int direct_probe_tries; /* retries for direct probes */ | ||
336 | int auth_tries; /* retries for auth req */ | ||
337 | int assoc_tries; /* retries for assoc req */ | ||
357 | 338 | ||
358 | unsigned long request; | 339 | unsigned long request; |
359 | 340 | ||
360 | unsigned long last_probe; | 341 | unsigned long last_probe; |
361 | 342 | ||
362 | unsigned int flags; | 343 | unsigned int flags; |
363 | #define IEEE80211_STA_REQ_SCAN 0 | ||
364 | #define IEEE80211_STA_REQ_AUTH 1 | ||
365 | #define IEEE80211_STA_REQ_RUN 2 | ||
366 | 344 | ||
367 | #define IEEE80211_AUTH_ALG_OPEN BIT(0) | ||
368 | #define IEEE80211_AUTH_ALG_SHARED_KEY BIT(1) | ||
369 | #define IEEE80211_AUTH_ALG_LEAP BIT(2) | ||
370 | unsigned int auth_algs; /* bitfield of allowed auth algs */ | 345 | unsigned int auth_algs; /* bitfield of allowed auth algs */ |
371 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ | 346 | int auth_alg; /* currently used IEEE 802.11 authentication algorithm */ |
372 | int auth_transaction; | 347 | int auth_transaction; |
@@ -376,31 +351,70 @@ struct ieee80211_if_sta { | |||
376 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; | 351 | u32 supp_rates_bits[IEEE80211_NUM_BANDS]; |
377 | 352 | ||
378 | int wmm_last_param_set; | 353 | int wmm_last_param_set; |
379 | int num_beacons; /* number of TXed beacon frames by this STA */ | ||
380 | }; | 354 | }; |
381 | 355 | ||
382 | static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, | 356 | struct ieee80211_if_mesh { |
383 | u8 mesh_id_len, u8 *mesh_id) | 357 | struct work_struct work; |
384 | { | 358 | struct timer_list housekeeping_timer; |
385 | #ifdef CONFIG_MAC80211_MESH | 359 | struct timer_list mesh_path_timer; |
386 | ifsta->mesh_id_len = mesh_id_len; | 360 | struct sk_buff_head skb_queue; |
387 | memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); | 361 | |
388 | #endif | 362 | bool housekeeping; |
389 | } | 363 | |
364 | u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; | ||
365 | size_t mesh_id_len; | ||
366 | /* Active Path Selection Protocol Identifier */ | ||
367 | u8 mesh_pp_id[4]; | ||
368 | /* Active Path Selection Metric Identifier */ | ||
369 | u8 mesh_pm_id[4]; | ||
370 | /* Congestion Control Mode Identifier */ | ||
371 | u8 mesh_cc_id[4]; | ||
372 | /* Local mesh Destination Sequence Number */ | ||
373 | u32 dsn; | ||
374 | /* Last used PREQ ID */ | ||
375 | u32 preq_id; | ||
376 | atomic_t mpaths; | ||
377 | /* Timestamp of last DSN update */ | ||
378 | unsigned long last_dsn_update; | ||
379 | /* Timestamp of last DSN sent */ | ||
380 | unsigned long last_preq; | ||
381 | struct mesh_rmc *rmc; | ||
382 | spinlock_t mesh_preq_queue_lock; | ||
383 | struct mesh_preq_queue preq_queue; | ||
384 | int preq_queue_len; | ||
385 | struct mesh_stats mshstats; | ||
386 | struct mesh_config mshcfg; | ||
387 | u32 mesh_seqnum; | ||
388 | bool accepting_plinks; | ||
389 | }; | ||
390 | 390 | ||
391 | #ifdef CONFIG_MAC80211_MESH | 391 | #ifdef CONFIG_MAC80211_MESH |
392 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 392 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
393 | do { (sta)->mshstats.name++; } while (0) | 393 | do { (msh)->mshstats.name++; } while (0) |
394 | #else | 394 | #else |
395 | #define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ | 395 | #define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \ |
396 | do { } while (0) | 396 | do { } while (0) |
397 | #endif | 397 | #endif |
398 | 398 | ||
399 | /* flags used in struct ieee80211_sub_if_data.flags */ | 399 | /** |
400 | #define IEEE80211_SDATA_ALLMULTI BIT(0) | 400 | * enum ieee80211_sub_if_data_flags - virtual interface flags |
401 | #define IEEE80211_SDATA_PROMISC BIT(1) | 401 | * |
402 | #define IEEE80211_SDATA_USERSPACE_MLME BIT(2) | 402 | * @IEEE80211_SDATA_ALLMULTI: interface wants all multicast packets |
403 | #define IEEE80211_SDATA_OPERATING_GMODE BIT(3) | 403 | * @IEEE80211_SDATA_PROMISC: interface is promisc |
404 | * @IEEE80211_SDATA_USERSPACE_MLME: userspace MLME is active | ||
405 | * @IEEE80211_SDATA_OPERATING_GMODE: operating in G-only mode | ||
406 | * @IEEE80211_SDATA_DONT_BRIDGE_PACKETS: bridge packets between | ||
407 | * associated stations and deliver multicast frames both | ||
408 | * back to wireless media and to the local net stack. | ||
409 | */ | ||
410 | enum ieee80211_sub_if_data_flags { | ||
411 | IEEE80211_SDATA_ALLMULTI = BIT(0), | ||
412 | IEEE80211_SDATA_PROMISC = BIT(1), | ||
413 | IEEE80211_SDATA_USERSPACE_MLME = BIT(2), | ||
414 | IEEE80211_SDATA_OPERATING_GMODE = BIT(3), | ||
415 | IEEE80211_SDATA_DONT_BRIDGE_PACKETS = BIT(4), | ||
416 | }; | ||
417 | |||
404 | struct ieee80211_sub_if_data { | 418 | struct ieee80211_sub_if_data { |
405 | struct list_head list; | 419 | struct list_head list; |
406 | 420 | ||
@@ -416,11 +430,6 @@ struct ieee80211_sub_if_data { | |||
416 | 430 | ||
417 | int drop_unencrypted; | 431 | int drop_unencrypted; |
418 | 432 | ||
419 | /* | ||
420 | * basic rates of this AP or the AP we're associated to | ||
421 | */ | ||
422 | u64 basic_rates; | ||
423 | |||
424 | /* Fragment table for host-based reassembly */ | 433 | /* Fragment table for host-based reassembly */ |
425 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 434 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
426 | unsigned int fragment_next; | 435 | unsigned int fragment_next; |
@@ -447,6 +456,9 @@ struct ieee80211_sub_if_data { | |||
447 | struct ieee80211_if_wds wds; | 456 | struct ieee80211_if_wds wds; |
448 | struct ieee80211_if_vlan vlan; | 457 | struct ieee80211_if_vlan vlan; |
449 | struct ieee80211_if_sta sta; | 458 | struct ieee80211_if_sta sta; |
459 | #ifdef CONFIG_MAC80211_MESH | ||
460 | struct ieee80211_if_mesh mesh; | ||
461 | #endif | ||
450 | u32 mntr_flags; | 462 | u32 mntr_flags; |
451 | } u; | 463 | } u; |
452 | 464 | ||
@@ -469,7 +481,6 @@ struct ieee80211_sub_if_data { | |||
469 | struct dentry *auth_alg; | 481 | struct dentry *auth_alg; |
470 | struct dentry *auth_transaction; | 482 | struct dentry *auth_transaction; |
471 | struct dentry *flags; | 483 | struct dentry *flags; |
472 | struct dentry *num_beacons_sta; | ||
473 | struct dentry *force_unicast_rateidx; | 484 | struct dentry *force_unicast_rateidx; |
474 | struct dentry *max_ratectrl_rateidx; | 485 | struct dentry *max_ratectrl_rateidx; |
475 | } sta; | 486 | } sta; |
@@ -477,7 +488,6 @@ struct ieee80211_sub_if_data { | |||
477 | struct dentry *drop_unencrypted; | 488 | struct dentry *drop_unencrypted; |
478 | struct dentry *num_sta_ps; | 489 | struct dentry *num_sta_ps; |
479 | struct dentry *dtim_count; | 490 | struct dentry *dtim_count; |
480 | struct dentry *num_beacons; | ||
481 | struct dentry *force_unicast_rateidx; | 491 | struct dentry *force_unicast_rateidx; |
482 | struct dentry *max_ratectrl_rateidx; | 492 | struct dentry *max_ratectrl_rateidx; |
483 | struct dentry *num_buffered_multicast; | 493 | struct dentry *num_buffered_multicast; |
@@ -496,8 +506,10 @@ struct ieee80211_sub_if_data { | |||
496 | struct { | 506 | struct { |
497 | struct dentry *mode; | 507 | struct dentry *mode; |
498 | } monitor; | 508 | } monitor; |
499 | struct dentry *default_key; | ||
500 | } debugfs; | 509 | } debugfs; |
510 | struct { | ||
511 | struct dentry *default_key; | ||
512 | } common_debugfs; | ||
501 | 513 | ||
502 | #ifdef CONFIG_MAC80211_MESH | 514 | #ifdef CONFIG_MAC80211_MESH |
503 | struct dentry *mesh_stats_dir; | 515 | struct dentry *mesh_stats_dir; |
@@ -538,6 +550,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) | |||
538 | return container_of(p, struct ieee80211_sub_if_data, vif); | 550 | return container_of(p, struct ieee80211_sub_if_data, vif); |
539 | } | 551 | } |
540 | 552 | ||
553 | static inline void | ||
554 | ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata, | ||
555 | u8 mesh_id_len, u8 *mesh_id) | ||
556 | { | ||
557 | #ifdef CONFIG_MAC80211_MESH | ||
558 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
559 | ifmsh->mesh_id_len = mesh_id_len; | ||
560 | memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len); | ||
561 | #else | ||
562 | WARN_ON(1); | ||
563 | #endif | ||
564 | } | ||
565 | |||
541 | enum { | 566 | enum { |
542 | IEEE80211_RX_MSG = 1, | 567 | IEEE80211_RX_MSG = 1, |
543 | IEEE80211_TX_STATUS_MSG = 2, | 568 | IEEE80211_TX_STATUS_MSG = 2, |
@@ -611,10 +636,6 @@ struct ieee80211_local { | |||
611 | struct crypto_blkcipher *wep_rx_tfm; | 636 | struct crypto_blkcipher *wep_rx_tfm; |
612 | u32 wep_iv; | 637 | u32 wep_iv; |
613 | 638 | ||
614 | int bridge_packets; /* bridge packets between associated stations and | ||
615 | * deliver multicast frames both back to wireless | ||
616 | * media and to the local net stack */ | ||
617 | |||
618 | struct list_head interfaces; | 639 | struct list_head interfaces; |
619 | 640 | ||
620 | /* | 641 | /* |
@@ -624,21 +645,21 @@ struct ieee80211_local { | |||
624 | spinlock_t key_lock; | 645 | spinlock_t key_lock; |
625 | 646 | ||
626 | 647 | ||
627 | bool sta_sw_scanning; | 648 | /* Scanning and BSS list */ |
628 | bool sta_hw_scanning; | 649 | bool sw_scanning, hw_scanning; |
629 | int scan_channel_idx; | 650 | int scan_channel_idx; |
630 | enum ieee80211_band scan_band; | 651 | enum ieee80211_band scan_band; |
631 | 652 | ||
632 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; | 653 | enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state; |
633 | unsigned long last_scan_completed; | 654 | unsigned long last_scan_completed; |
634 | struct delayed_work scan_work; | 655 | struct delayed_work scan_work; |
635 | struct net_device *scan_dev; | 656 | struct ieee80211_sub_if_data *scan_sdata; |
636 | struct ieee80211_channel *oper_channel, *scan_channel; | 657 | struct ieee80211_channel *oper_channel, *scan_channel; |
637 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 658 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
638 | size_t scan_ssid_len; | 659 | size_t scan_ssid_len; |
639 | struct list_head sta_bss_list; | 660 | struct list_head bss_list; |
640 | struct ieee80211_sta_bss *sta_bss_hash[STA_HASH_SIZE]; | 661 | struct ieee80211_bss *bss_hash[STA_HASH_SIZE]; |
641 | spinlock_t sta_bss_lock; | 662 | spinlock_t bss_lock; |
642 | 663 | ||
643 | /* SNMP counters */ | 664 | /* SNMP counters */ |
644 | /* dot11CountersTable */ | 665 | /* dot11CountersTable */ |
@@ -702,7 +723,6 @@ struct ieee80211_local { | |||
702 | struct dentry *frequency; | 723 | struct dentry *frequency; |
703 | struct dentry *antenna_sel_tx; | 724 | struct dentry *antenna_sel_tx; |
704 | struct dentry *antenna_sel_rx; | 725 | struct dentry *antenna_sel_rx; |
705 | struct dentry *bridge_packets; | ||
706 | struct dentry *rts_threshold; | 726 | struct dentry *rts_threshold; |
707 | struct dentry *fragmentation_threshold; | 727 | struct dentry *fragmentation_threshold; |
708 | struct dentry *short_retry_limit; | 728 | struct dentry *short_retry_limit; |
@@ -772,6 +792,9 @@ struct ieee80211_ra_tid { | |||
772 | 792 | ||
773 | /* Parsed Information Elements */ | 793 | /* Parsed Information Elements */ |
774 | struct ieee802_11_elems { | 794 | struct ieee802_11_elems { |
795 | u8 *ie_start; | ||
796 | size_t total_len; | ||
797 | |||
775 | /* pointers to IEs */ | 798 | /* pointers to IEs */ |
776 | u8 *ssid; | 799 | u8 *ssid; |
777 | u8 *supp_rates; | 800 | u8 *supp_rates; |
@@ -855,86 +878,82 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr) | |||
855 | } | 878 | } |
856 | 879 | ||
857 | 880 | ||
858 | /* ieee80211.c */ | ||
859 | int ieee80211_hw_config(struct ieee80211_local *local); | 881 | int ieee80211_hw_config(struct ieee80211_local *local); |
860 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); | 882 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed); |
861 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); | 883 | void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx); |
862 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | 884 | u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, |
863 | struct ieee80211_ht_info *req_ht_cap, | 885 | struct ieee80211_ht_info *req_ht_cap, |
864 | struct ieee80211_ht_bss_info *req_bss_cap); | 886 | struct ieee80211_ht_bss_info *req_bss_cap); |
887 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | ||
888 | u32 changed); | ||
889 | void ieee80211_configure_filter(struct ieee80211_local *local); | ||
865 | 890 | ||
866 | /* ieee80211_ioctl.c */ | 891 | /* wireless extensions */ |
867 | extern const struct iw_handler_def ieee80211_iw_handler_def; | 892 | extern const struct iw_handler_def ieee80211_iw_handler_def; |
868 | int ieee80211_set_freq(struct net_device *dev, int freq); | ||
869 | 893 | ||
870 | /* ieee80211_sta.c */ | 894 | /* STA/IBSS code */ |
871 | void ieee80211_sta_timer(unsigned long data); | 895 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); |
872 | void ieee80211_sta_work(struct work_struct *work); | 896 | void ieee80211_scan_work(struct work_struct *work); |
873 | void ieee80211_sta_scan_work(struct work_struct *work); | 897 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
874 | void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | ||
875 | struct ieee80211_rx_status *rx_status); | 898 | struct ieee80211_rx_status *rx_status); |
876 | int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len); | 899 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len); |
877 | int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len); | 900 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len); |
878 | int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); | 901 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid); |
879 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); | 902 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, |
880 | void ieee80211_sta_req_auth(struct net_device *dev, | ||
881 | struct ieee80211_if_sta *ifsta); | 903 | struct ieee80211_if_sta *ifsta); |
882 | int ieee80211_sta_scan_results(struct net_device *dev, | 904 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
883 | struct iw_request_info *info, | ||
884 | char *buf, size_t len); | ||
885 | ieee80211_rx_result ieee80211_sta_rx_scan( | ||
886 | struct net_device *dev, struct sk_buff *skb, | ||
887 | struct ieee80211_rx_status *rx_status); | ||
888 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | ||
889 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | ||
890 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len); | ||
891 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | ||
892 | struct sk_buff *skb, u8 *bssid, | 905 | struct sk_buff *skb, u8 *bssid, |
893 | u8 *addr, u64 supp_rates); | 906 | u8 *addr, u64 supp_rates); |
894 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); | 907 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason); |
895 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); | 908 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason); |
896 | void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | 909 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); |
897 | u32 changed); | ||
898 | u32 ieee80211_reset_erp_info(struct net_device *dev); | ||
899 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
900 | struct ieee80211_ht_info *ht_info); | ||
901 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
902 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
903 | struct ieee80211_ht_bss_info *bss_info); | ||
904 | void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | ||
905 | u16 tid, u8 dialog_token, u16 start_seq_num, | ||
906 | u16 agg_size, u16 timeout); | ||
907 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | ||
908 | u16 initiator, u16 reason_code); | ||
909 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); | ||
910 | |||
911 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, | ||
912 | u16 tid, u16 initiator, u16 reason); | ||
913 | void sta_addba_resp_timer_expired(unsigned long data); | ||
914 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); | ||
915 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 910 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
916 | struct ieee802_11_elems *elems, | 911 | struct ieee802_11_elems *elems, |
917 | enum ieee80211_band band); | 912 | enum ieee80211_band band); |
918 | void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | 913 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
919 | int encrypt); | 914 | u8 *ssid, size_t ssid_len); |
920 | void ieee802_11_parse_elems(u8 *start, size_t len, | 915 | |
921 | struct ieee802_11_elems *elems); | 916 | /* scan/BSS handling */ |
922 | 917 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | |
923 | #ifdef CONFIG_MAC80211_MESH | 918 | u8 *ssid, size_t ssid_len); |
924 | void ieee80211_start_mesh(struct net_device *dev); | 919 | int ieee80211_scan_results(struct ieee80211_local *local, |
925 | #else | 920 | struct iw_request_info *info, |
926 | static inline void ieee80211_start_mesh(struct net_device *dev) | 921 | char *buf, size_t len); |
927 | {} | 922 | ieee80211_rx_result |
928 | #endif | 923 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, |
924 | struct sk_buff *skb, | ||
925 | struct ieee80211_rx_status *rx_status); | ||
926 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local); | ||
927 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local); | ||
928 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, | ||
929 | char *ie, size_t len); | ||
930 | |||
931 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local); | ||
932 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | ||
933 | u8 *ssid, size_t ssid_len); | ||
934 | struct ieee80211_bss * | ||
935 | ieee80211_bss_info_update(struct ieee80211_local *local, | ||
936 | struct ieee80211_rx_status *rx_status, | ||
937 | struct ieee80211_mgmt *mgmt, | ||
938 | size_t len, | ||
939 | struct ieee802_11_elems *elems, | ||
940 | int freq, bool beacon); | ||
941 | struct ieee80211_bss * | ||
942 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
943 | u8 *ssid, u8 ssid_len); | ||
944 | struct ieee80211_bss * | ||
945 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | ||
946 | u8 *ssid, u8 ssid_len); | ||
947 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
948 | struct ieee80211_bss *bss); | ||
929 | 949 | ||
930 | /* interface handling */ | 950 | /* interface handling */ |
931 | void ieee80211_if_setup(struct net_device *dev); | ||
932 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 951 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
933 | struct net_device **new_dev, enum ieee80211_if_types type, | 952 | struct net_device **new_dev, enum nl80211_iftype type, |
934 | struct vif_params *params); | 953 | struct vif_params *params); |
935 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 954 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
936 | enum ieee80211_if_types type); | 955 | enum nl80211_iftype type); |
937 | void ieee80211_if_remove(struct net_device *dev); | 956 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); |
938 | void ieee80211_remove_interfaces(struct ieee80211_local *local); | 957 | void ieee80211_remove_interfaces(struct ieee80211_local *local); |
939 | 958 | ||
940 | /* tx handling */ | 959 | /* tx handling */ |
@@ -944,16 +963,52 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev); | |||
944 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); | 963 | int ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); |
945 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); | 964 | int ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); |
946 | 965 | ||
966 | /* HT */ | ||
967 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
968 | struct ieee80211_ht_info *ht_info); | ||
969 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
970 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
971 | struct ieee80211_ht_bss_info *bss_info); | ||
972 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn); | ||
973 | |||
974 | void ieee80211_sta_stop_rx_ba_session(struct ieee80211_sub_if_data *sdata, u8 *da, | ||
975 | u16 tid, u16 initiator, u16 reason); | ||
976 | void ieee80211_sta_tear_down_BA_sessions(struct ieee80211_sub_if_data *sdata, u8 *addr); | ||
977 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | ||
978 | struct sta_info *sta, | ||
979 | struct ieee80211_mgmt *mgmt, size_t len); | ||
980 | void ieee80211_process_addba_resp(struct ieee80211_local *local, | ||
981 | struct sta_info *sta, | ||
982 | struct ieee80211_mgmt *mgmt, | ||
983 | size_t len); | ||
984 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
985 | struct sta_info *sta, | ||
986 | struct ieee80211_mgmt *mgmt, | ||
987 | size_t len); | ||
988 | |||
989 | /* Spectrum management */ | ||
990 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | ||
991 | struct ieee80211_mgmt *mgmt, | ||
992 | size_t len); | ||
993 | |||
947 | /* utility functions/constants */ | 994 | /* utility functions/constants */ |
948 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 995 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ |
949 | extern const unsigned char rfc1042_header[6]; | 996 | extern const unsigned char rfc1042_header[6]; |
950 | extern const unsigned char bridge_tunnel_header[6]; | 997 | extern const unsigned char bridge_tunnel_header[6]; |
951 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 998 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
952 | enum ieee80211_if_types type); | 999 | enum nl80211_iftype type); |
953 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, | 1000 | int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, |
954 | int rate, int erp, int short_preamble); | 1001 | int rate, int erp, int short_preamble); |
955 | void mac80211_ev_michael_mic_failure(struct net_device *dev, int keyidx, | 1002 | void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, |
956 | struct ieee80211_hdr *hdr); | 1003 | struct ieee80211_hdr *hdr); |
1004 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | ||
1005 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
1006 | int encrypt); | ||
1007 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
1008 | struct ieee802_11_elems *elems); | ||
1009 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | ||
1010 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
1011 | enum ieee80211_band band); | ||
957 | 1012 | ||
958 | #ifdef CONFIG_MAC80211_NOINLINE | 1013 | #ifdef CONFIG_MAC80211_NOINLINE |
959 | #define debug_noinline noinline | 1014 | #define debug_noinline noinline |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 610ed1d9893a..a72fbebb8ea2 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Interface handling (except master interface) | ||
3 | * | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 4 | * Copyright 2002-2005, Instant802 Networks, Inc. |
3 | * Copyright 2005-2006, Devicescape Software, Inc. | 5 | * Copyright 2005-2006, Devicescape Software, Inc. |
4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 6 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
@@ -17,7 +19,540 @@ | |||
17 | #include "sta_info.h" | 19 | #include "sta_info.h" |
18 | #include "debugfs_netdev.h" | 20 | #include "debugfs_netdev.h" |
19 | #include "mesh.h" | 21 | #include "mesh.h" |
22 | #include "led.h" | ||
23 | |||
24 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | ||
25 | { | ||
26 | int meshhdrlen; | ||
27 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
28 | |||
29 | meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0; | ||
30 | |||
31 | /* FIX: what would be proper limits for MTU? | ||
32 | * This interface uses 802.3 frames. */ | ||
33 | if (new_mtu < 256 || | ||
34 | new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { | ||
35 | return -EINVAL; | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
39 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | ||
40 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
41 | dev->mtu = new_mtu; | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static inline int identical_mac_addr_allowed(int type1, int type2) | ||
46 | { | ||
47 | return type1 == NL80211_IFTYPE_MONITOR || | ||
48 | type2 == NL80211_IFTYPE_MONITOR || | ||
49 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || | ||
50 | (type1 == NL80211_IFTYPE_WDS && | ||
51 | (type2 == NL80211_IFTYPE_WDS || | ||
52 | type2 == NL80211_IFTYPE_AP)) || | ||
53 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_AP_VLAN) || | ||
54 | (type1 == NL80211_IFTYPE_AP_VLAN && | ||
55 | (type2 == NL80211_IFTYPE_AP || | ||
56 | type2 == NL80211_IFTYPE_AP_VLAN)); | ||
57 | } | ||
58 | |||
59 | static int ieee80211_open(struct net_device *dev) | ||
60 | { | ||
61 | struct ieee80211_sub_if_data *sdata, *nsdata; | ||
62 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
63 | struct sta_info *sta; | ||
64 | struct ieee80211_if_init_conf conf; | ||
65 | u32 changed = 0; | ||
66 | int res; | ||
67 | bool need_hw_reconfig = 0; | ||
68 | u8 null_addr[ETH_ALEN] = {0}; | ||
69 | |||
70 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
71 | |||
72 | /* fail early if user set an invalid address */ | ||
73 | if (compare_ether_addr(dev->dev_addr, null_addr) && | ||
74 | !is_valid_ether_addr(dev->dev_addr)) | ||
75 | return -EADDRNOTAVAIL; | ||
76 | |||
77 | /* we hold the RTNL here so can safely walk the list */ | ||
78 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
79 | struct net_device *ndev = nsdata->dev; | ||
80 | |||
81 | if (ndev != dev && netif_running(ndev)) { | ||
82 | /* | ||
83 | * Allow only a single IBSS interface to be up at any | ||
84 | * time. This is restricted because beacon distribution | ||
85 | * cannot work properly if both are in the same IBSS. | ||
86 | * | ||
87 | * To remove this restriction we'd have to disallow them | ||
88 | * from setting the same SSID on different IBSS interfaces | ||
89 | * belonging to the same hardware. Then, however, we're | ||
90 | * faced with having to adopt two different TSF timers... | ||
91 | */ | ||
92 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
93 | nsdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
94 | return -EBUSY; | ||
95 | |||
96 | /* | ||
97 | * The remaining checks are only performed for interfaces | ||
98 | * with the same MAC address. | ||
99 | */ | ||
100 | if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) | ||
101 | continue; | ||
102 | |||
103 | /* | ||
104 | * check whether it may have the same address | ||
105 | */ | ||
106 | if (!identical_mac_addr_allowed(sdata->vif.type, | ||
107 | nsdata->vif.type)) | ||
108 | return -ENOTUNIQ; | ||
109 | |||
110 | /* | ||
111 | * can only add VLANs to enabled APs | ||
112 | */ | ||
113 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && | ||
114 | nsdata->vif.type == NL80211_IFTYPE_AP) | ||
115 | sdata->bss = &nsdata->u.ap; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | switch (sdata->vif.type) { | ||
120 | case NL80211_IFTYPE_WDS: | ||
121 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | ||
122 | return -ENOLINK; | ||
123 | break; | ||
124 | case NL80211_IFTYPE_AP_VLAN: | ||
125 | if (!sdata->bss) | ||
126 | return -ENOLINK; | ||
127 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
128 | break; | ||
129 | case NL80211_IFTYPE_AP: | ||
130 | sdata->bss = &sdata->u.ap; | ||
131 | break; | ||
132 | case NL80211_IFTYPE_MESH_POINT: | ||
133 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | ||
134 | break; | ||
135 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
136 | atomic_inc(&local->iff_allmultis); | ||
137 | break; | ||
138 | case NL80211_IFTYPE_STATION: | ||
139 | case NL80211_IFTYPE_MONITOR: | ||
140 | case NL80211_IFTYPE_ADHOC: | ||
141 | /* no special treatment */ | ||
142 | break; | ||
143 | case NL80211_IFTYPE_UNSPECIFIED: | ||
144 | case __NL80211_IFTYPE_AFTER_LAST: | ||
145 | /* cannot happen */ | ||
146 | WARN_ON(1); | ||
147 | break; | ||
148 | } | ||
149 | |||
150 | if (local->open_count == 0) { | ||
151 | res = 0; | ||
152 | if (local->ops->start) | ||
153 | res = local->ops->start(local_to_hw(local)); | ||
154 | if (res) | ||
155 | goto err_del_bss; | ||
156 | need_hw_reconfig = 1; | ||
157 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Check all interfaces and copy the hopefully now-present | ||
162 | * MAC address to those that have the special null one. | ||
163 | */ | ||
164 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
165 | struct net_device *ndev = nsdata->dev; | ||
166 | |||
167 | /* | ||
168 | * No need to check netif_running since we do not allow | ||
169 | * it to start up with this invalid address. | ||
170 | */ | ||
171 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) | ||
172 | memcpy(ndev->dev_addr, | ||
173 | local->hw.wiphy->perm_addr, | ||
174 | ETH_ALEN); | ||
175 | } | ||
176 | |||
177 | if (compare_ether_addr(null_addr, local->mdev->dev_addr) == 0) | ||
178 | memcpy(local->mdev->dev_addr, local->hw.wiphy->perm_addr, | ||
179 | ETH_ALEN); | ||
180 | |||
181 | /* | ||
182 | * Validate the MAC address for this device. | ||
183 | */ | ||
184 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
185 | if (!local->open_count && local->ops->stop) | ||
186 | local->ops->stop(local_to_hw(local)); | ||
187 | return -EADDRNOTAVAIL; | ||
188 | } | ||
189 | |||
190 | switch (sdata->vif.type) { | ||
191 | case NL80211_IFTYPE_AP_VLAN: | ||
192 | /* no need to tell driver */ | ||
193 | break; | ||
194 | case NL80211_IFTYPE_MONITOR: | ||
195 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
196 | local->cooked_mntrs++; | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | /* must be before the call to ieee80211_configure_filter */ | ||
201 | local->monitors++; | ||
202 | if (local->monitors == 1) | ||
203 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
204 | |||
205 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
206 | local->fif_fcsfail++; | ||
207 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
208 | local->fif_plcpfail++; | ||
209 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
210 | local->fif_control++; | ||
211 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
212 | local->fif_other_bss++; | ||
213 | |||
214 | netif_addr_lock_bh(local->mdev); | ||
215 | ieee80211_configure_filter(local); | ||
216 | netif_addr_unlock_bh(local->mdev); | ||
217 | break; | ||
218 | case NL80211_IFTYPE_STATION: | ||
219 | case NL80211_IFTYPE_ADHOC: | ||
220 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
221 | /* fall through */ | ||
222 | default: | ||
223 | conf.vif = &sdata->vif; | ||
224 | conf.type = sdata->vif.type; | ||
225 | conf.mac_addr = dev->dev_addr; | ||
226 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
227 | if (res) | ||
228 | goto err_stop; | ||
229 | |||
230 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
231 | ieee80211_start_mesh(sdata); | ||
232 | changed |= ieee80211_reset_erp_info(sdata); | ||
233 | ieee80211_bss_info_change_notify(sdata, changed); | ||
234 | ieee80211_enable_keys(sdata); | ||
235 | |||
236 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
237 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | ||
238 | netif_carrier_off(dev); | ||
239 | else | ||
240 | netif_carrier_on(dev); | ||
241 | } | ||
242 | |||
243 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { | ||
244 | /* Create STA entry for the WDS peer */ | ||
245 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | ||
246 | GFP_KERNEL); | ||
247 | if (!sta) { | ||
248 | res = -ENOMEM; | ||
249 | goto err_del_interface; | ||
250 | } | ||
251 | |||
252 | /* no locking required since STA is not live yet */ | ||
253 | sta->flags |= WLAN_STA_AUTHORIZED; | ||
254 | |||
255 | res = sta_info_insert(sta); | ||
256 | if (res) { | ||
257 | /* STA has been freed */ | ||
258 | goto err_del_interface; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | if (local->open_count == 0) { | ||
263 | res = dev_open(local->mdev); | ||
264 | WARN_ON(res); | ||
265 | if (res) | ||
266 | goto err_del_interface; | ||
267 | tasklet_enable(&local->tx_pending_tasklet); | ||
268 | tasklet_enable(&local->tasklet); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * set_multicast_list will be invoked by the networking core | ||
273 | * which will check whether any increments here were done in | ||
274 | * error and sync them down to the hardware as filter flags. | ||
275 | */ | ||
276 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
277 | atomic_inc(&local->iff_allmultis); | ||
278 | |||
279 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
280 | atomic_inc(&local->iff_promiscs); | ||
281 | |||
282 | local->open_count++; | ||
283 | if (need_hw_reconfig) { | ||
284 | ieee80211_hw_config(local); | ||
285 | /* | ||
286 | * set default queue parameters so drivers don't | ||
287 | * need to initialise the hardware if the hardware | ||
288 | * doesn't start up with sane defaults | ||
289 | */ | ||
290 | ieee80211_set_wmm_default(sdata); | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * ieee80211_sta_work is disabled while network interface | ||
295 | * is down. Therefore, some configuration changes may not | ||
296 | * yet be effective. Trigger execution of ieee80211_sta_work | ||
297 | * to fix this. | ||
298 | */ | ||
299 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | ||
300 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
301 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
302 | queue_work(local->hw.workqueue, &ifsta->work); | ||
303 | } | ||
304 | |||
305 | netif_tx_start_all_queues(dev); | ||
306 | |||
307 | return 0; | ||
308 | err_del_interface: | ||
309 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
310 | err_stop: | ||
311 | if (!local->open_count && local->ops->stop) | ||
312 | local->ops->stop(local_to_hw(local)); | ||
313 | err_del_bss: | ||
314 | sdata->bss = NULL; | ||
315 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
316 | list_del(&sdata->u.vlan.list); | ||
317 | return res; | ||
318 | } | ||
319 | |||
320 | static int ieee80211_stop(struct net_device *dev) | ||
321 | { | ||
322 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
323 | struct ieee80211_local *local = sdata->local; | ||
324 | struct ieee80211_if_init_conf conf; | ||
325 | struct sta_info *sta; | ||
20 | 326 | ||
327 | /* | ||
328 | * Stop TX on this interface first. | ||
329 | */ | ||
330 | netif_tx_stop_all_queues(dev); | ||
331 | |||
332 | /* | ||
333 | * Now delete all active aggregation sessions. | ||
334 | */ | ||
335 | rcu_read_lock(); | ||
336 | |||
337 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
338 | if (sta->sdata == sdata) | ||
339 | ieee80211_sta_tear_down_BA_sessions(sdata, | ||
340 | sta->sta.addr); | ||
341 | } | ||
342 | |||
343 | rcu_read_unlock(); | ||
344 | |||
345 | /* | ||
346 | * Remove all stations associated with this interface. | ||
347 | * | ||
348 | * This must be done before calling ops->remove_interface() | ||
349 | * because otherwise we can later invoke ops->sta_notify() | ||
350 | * whenever the STAs are removed, and that invalidates driver | ||
351 | * assumptions about always getting a vif pointer that is valid | ||
352 | * (because if we remove a STA after ops->remove_interface() | ||
353 | * the driver will have removed the vif info already!) | ||
354 | * | ||
355 | * We could relax this and only unlink the stations from the | ||
356 | * hash table and list but keep them on a per-sdata list that | ||
357 | * will be inserted back again when the interface is brought | ||
358 | * up again, but I don't currently see a use case for that, | ||
359 | * except with WDS which gets a STA entry created when it is | ||
360 | * brought up. | ||
361 | */ | ||
362 | sta_info_flush(local, sdata); | ||
363 | |||
364 | /* | ||
365 | * Don't count this interface for promisc/allmulti while it | ||
366 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
367 | * on the master interface which will sync these down to the | ||
368 | * hardware as filter flags. | ||
369 | */ | ||
370 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
371 | atomic_dec(&local->iff_allmultis); | ||
372 | |||
373 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
374 | atomic_dec(&local->iff_promiscs); | ||
375 | |||
376 | dev_mc_unsync(local->mdev, dev); | ||
377 | |||
378 | /* APs need special treatment */ | ||
379 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | ||
380 | struct ieee80211_sub_if_data *vlan, *tmp; | ||
381 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | ||
382 | |||
383 | /* remove beacon */ | ||
384 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | ||
385 | synchronize_rcu(); | ||
386 | kfree(old_beacon); | ||
387 | |||
388 | /* down all dependent devices, that is VLANs */ | ||
389 | list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, | ||
390 | u.vlan.list) | ||
391 | dev_close(vlan->dev); | ||
392 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | ||
393 | } | ||
394 | |||
395 | local->open_count--; | ||
396 | |||
397 | switch (sdata->vif.type) { | ||
398 | case NL80211_IFTYPE_AP_VLAN: | ||
399 | list_del(&sdata->u.vlan.list); | ||
400 | /* no need to tell driver */ | ||
401 | break; | ||
402 | case NL80211_IFTYPE_MONITOR: | ||
403 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
404 | local->cooked_mntrs--; | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | local->monitors--; | ||
409 | if (local->monitors == 0) | ||
410 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
411 | |||
412 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
413 | local->fif_fcsfail--; | ||
414 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
415 | local->fif_plcpfail--; | ||
416 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
417 | local->fif_control--; | ||
418 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
419 | local->fif_other_bss--; | ||
420 | |||
421 | netif_addr_lock_bh(local->mdev); | ||
422 | ieee80211_configure_filter(local); | ||
423 | netif_addr_unlock_bh(local->mdev); | ||
424 | break; | ||
425 | case NL80211_IFTYPE_STATION: | ||
426 | case NL80211_IFTYPE_ADHOC: | ||
427 | sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; | ||
428 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); | ||
429 | del_timer_sync(&sdata->u.sta.timer); | ||
430 | /* | ||
431 | * If the timer fired while we waited for it, it will have | ||
432 | * requeued the work. Now the work will be running again | ||
433 | * but will not rearm the timer again because it checks | ||
434 | * whether the interface is running, which, at this point, | ||
435 | * it no longer is. | ||
436 | */ | ||
437 | cancel_work_sync(&sdata->u.sta.work); | ||
438 | /* | ||
439 | * When we get here, the interface is marked down. | ||
440 | * Call synchronize_rcu() to wait for the RX path | ||
441 | * should it be using the interface and enqueuing | ||
442 | * frames at this very time on another CPU. | ||
443 | */ | ||
444 | synchronize_rcu(); | ||
445 | skb_queue_purge(&sdata->u.sta.skb_queue); | ||
446 | |||
447 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | ||
448 | kfree(sdata->u.sta.extra_ie); | ||
449 | sdata->u.sta.extra_ie = NULL; | ||
450 | sdata->u.sta.extra_ie_len = 0; | ||
451 | /* fall through */ | ||
452 | case NL80211_IFTYPE_MESH_POINT: | ||
453 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
454 | /* allmulti is always set on mesh ifaces */ | ||
455 | atomic_dec(&local->iff_allmultis); | ||
456 | ieee80211_stop_mesh(sdata); | ||
457 | } | ||
458 | /* fall through */ | ||
459 | default: | ||
460 | if (local->scan_sdata == sdata) { | ||
461 | if (!local->ops->hw_scan) | ||
462 | cancel_delayed_work_sync(&local->scan_work); | ||
463 | /* | ||
464 | * The software scan can no longer run now, so we can | ||
465 | * clear out the scan_sdata reference. However, the | ||
466 | * hardware scan may still be running. The complete | ||
467 | * function must be prepared to handle a NULL value. | ||
468 | */ | ||
469 | local->scan_sdata = NULL; | ||
470 | /* | ||
471 | * The memory barrier guarantees that another CPU | ||
472 | * that is hardware-scanning will now see the fact | ||
473 | * that this interface is gone. | ||
474 | */ | ||
475 | smp_mb(); | ||
476 | /* | ||
477 | * If software scanning, complete the scan but since | ||
478 | * the scan_sdata is NULL already don't send out a | ||
479 | * scan event to userspace -- the scan is incomplete. | ||
480 | */ | ||
481 | if (local->sw_scanning) | ||
482 | ieee80211_scan_completed(&local->hw); | ||
483 | } | ||
484 | |||
485 | conf.vif = &sdata->vif; | ||
486 | conf.type = sdata->vif.type; | ||
487 | conf.mac_addr = dev->dev_addr; | ||
488 | /* disable all keys for as long as this netdev is down */ | ||
489 | ieee80211_disable_keys(sdata); | ||
490 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
491 | } | ||
492 | |||
493 | sdata->bss = NULL; | ||
494 | |||
495 | if (local->open_count == 0) { | ||
496 | if (netif_running(local->mdev)) | ||
497 | dev_close(local->mdev); | ||
498 | |||
499 | if (local->ops->stop) | ||
500 | local->ops->stop(local_to_hw(local)); | ||
501 | |||
502 | ieee80211_led_radio(local, 0); | ||
503 | |||
504 | flush_workqueue(local->hw.workqueue); | ||
505 | |||
506 | tasklet_disable(&local->tx_pending_tasklet); | ||
507 | tasklet_disable(&local->tasklet); | ||
508 | } | ||
509 | |||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static void ieee80211_set_multicast_list(struct net_device *dev) | ||
514 | { | ||
515 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
516 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
517 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | ||
518 | |||
519 | allmulti = !!(dev->flags & IFF_ALLMULTI); | ||
520 | promisc = !!(dev->flags & IFF_PROMISC); | ||
521 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); | ||
522 | sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); | ||
523 | |||
524 | if (allmulti != sdata_allmulti) { | ||
525 | if (dev->flags & IFF_ALLMULTI) | ||
526 | atomic_inc(&local->iff_allmultis); | ||
527 | else | ||
528 | atomic_dec(&local->iff_allmultis); | ||
529 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | ||
530 | } | ||
531 | |||
532 | if (promisc != sdata_promisc) { | ||
533 | if (dev->flags & IFF_PROMISC) | ||
534 | atomic_inc(&local->iff_promiscs); | ||
535 | else | ||
536 | atomic_dec(&local->iff_promiscs); | ||
537 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | ||
538 | } | ||
539 | |||
540 | dev_mc_sync(local->mdev, dev); | ||
541 | } | ||
542 | |||
543 | static void ieee80211_if_setup(struct net_device *dev) | ||
544 | { | ||
545 | ether_setup(dev); | ||
546 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
547 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
548 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
549 | dev->change_mtu = ieee80211_change_mtu; | ||
550 | dev->open = ieee80211_open; | ||
551 | dev->stop = ieee80211_stop; | ||
552 | dev->destructor = free_netdev; | ||
553 | /* we will validate the address ourselves in ->open */ | ||
554 | dev->validate_addr = NULL; | ||
555 | } | ||
21 | /* | 556 | /* |
22 | * Called when the netdev is removed or, by the code below, before | 557 | * Called when the netdev is removed or, by the code below, before |
23 | * the interface type changes. | 558 | * the interface type changes. |
@@ -31,17 +566,17 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
31 | int flushed; | 566 | int flushed; |
32 | int i; | 567 | int i; |
33 | 568 | ||
34 | ieee80211_debugfs_remove_netdev(sdata); | ||
35 | |||
36 | /* free extra data */ | 569 | /* free extra data */ |
37 | ieee80211_free_keys(sdata); | 570 | ieee80211_free_keys(sdata); |
38 | 571 | ||
572 | ieee80211_debugfs_remove_netdev(sdata); | ||
573 | |||
39 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) | 574 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) |
40 | __skb_queue_purge(&sdata->fragments[i].skb_list); | 575 | __skb_queue_purge(&sdata->fragments[i].skb_list); |
41 | sdata->fragment_next = 0; | 576 | sdata->fragment_next = 0; |
42 | 577 | ||
43 | switch (sdata->vif.type) { | 578 | switch (sdata->vif.type) { |
44 | case IEEE80211_IF_TYPE_AP: | 579 | case NL80211_IFTYPE_AP: |
45 | beacon = sdata->u.ap.beacon; | 580 | beacon = sdata->u.ap.beacon; |
46 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | 581 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); |
47 | synchronize_rcu(); | 582 | synchronize_rcu(); |
@@ -53,23 +588,23 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
53 | } | 588 | } |
54 | 589 | ||
55 | break; | 590 | break; |
56 | case IEEE80211_IF_TYPE_MESH_POINT: | 591 | case NL80211_IFTYPE_MESH_POINT: |
57 | /* Allow compiler to elide mesh_rmc_free call. */ | ||
58 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 592 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
59 | mesh_rmc_free(dev); | 593 | mesh_rmc_free(sdata); |
60 | /* fall through */ | 594 | break; |
61 | case IEEE80211_IF_TYPE_STA: | 595 | case NL80211_IFTYPE_STATION: |
62 | case IEEE80211_IF_TYPE_IBSS: | 596 | case NL80211_IFTYPE_ADHOC: |
63 | kfree(sdata->u.sta.extra_ie); | 597 | kfree(sdata->u.sta.extra_ie); |
64 | kfree(sdata->u.sta.assocreq_ies); | 598 | kfree(sdata->u.sta.assocreq_ies); |
65 | kfree(sdata->u.sta.assocresp_ies); | 599 | kfree(sdata->u.sta.assocresp_ies); |
66 | kfree_skb(sdata->u.sta.probe_resp); | 600 | kfree_skb(sdata->u.sta.probe_resp); |
67 | break; | 601 | break; |
68 | case IEEE80211_IF_TYPE_WDS: | 602 | case NL80211_IFTYPE_WDS: |
69 | case IEEE80211_IF_TYPE_VLAN: | 603 | case NL80211_IFTYPE_AP_VLAN: |
70 | case IEEE80211_IF_TYPE_MNTR: | 604 | case NL80211_IFTYPE_MONITOR: |
71 | break; | 605 | break; |
72 | case IEEE80211_IF_TYPE_INVALID: | 606 | case NL80211_IFTYPE_UNSPECIFIED: |
607 | case __NL80211_IFTYPE_AFTER_LAST: | ||
73 | BUG(); | 608 | BUG(); |
74 | break; | 609 | break; |
75 | } | 610 | } |
@@ -82,55 +617,42 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
82 | * Helper function to initialise an interface to a specific type. | 617 | * Helper function to initialise an interface to a specific type. |
83 | */ | 618 | */ |
84 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | 619 | static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, |
85 | enum ieee80211_if_types type) | 620 | enum nl80211_iftype type) |
86 | { | 621 | { |
87 | struct ieee80211_if_sta *ifsta; | ||
88 | |||
89 | /* clear type-dependent union */ | 622 | /* clear type-dependent union */ |
90 | memset(&sdata->u, 0, sizeof(sdata->u)); | 623 | memset(&sdata->u, 0, sizeof(sdata->u)); |
91 | 624 | ||
92 | /* and set some type-dependent values */ | 625 | /* and set some type-dependent values */ |
93 | sdata->vif.type = type; | 626 | sdata->vif.type = type; |
627 | sdata->dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
94 | 628 | ||
95 | /* only monitor differs */ | 629 | /* only monitor differs */ |
96 | sdata->dev->type = ARPHRD_ETHER; | 630 | sdata->dev->type = ARPHRD_ETHER; |
97 | 631 | ||
98 | switch (type) { | 632 | switch (type) { |
99 | case IEEE80211_IF_TYPE_AP: | 633 | case NL80211_IFTYPE_AP: |
100 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); | 634 | skb_queue_head_init(&sdata->u.ap.ps_bc_buf); |
101 | INIT_LIST_HEAD(&sdata->u.ap.vlans); | 635 | INIT_LIST_HEAD(&sdata->u.ap.vlans); |
102 | break; | 636 | break; |
103 | case IEEE80211_IF_TYPE_MESH_POINT: | 637 | case NL80211_IFTYPE_STATION: |
104 | case IEEE80211_IF_TYPE_STA: | 638 | case NL80211_IFTYPE_ADHOC: |
105 | case IEEE80211_IF_TYPE_IBSS: | 639 | ieee80211_sta_setup_sdata(sdata); |
106 | ifsta = &sdata->u.sta; | 640 | break; |
107 | INIT_WORK(&ifsta->work, ieee80211_sta_work); | 641 | case NL80211_IFTYPE_MESH_POINT: |
108 | setup_timer(&ifsta->timer, ieee80211_sta_timer, | ||
109 | (unsigned long) sdata); | ||
110 | skb_queue_head_init(&ifsta->skb_queue); | ||
111 | |||
112 | ifsta->capab = WLAN_CAPABILITY_ESS; | ||
113 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | | ||
114 | IEEE80211_AUTH_ALG_SHARED_KEY; | ||
115 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | ||
116 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
117 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
118 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | ||
119 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | ||
120 | |||
121 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 642 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
122 | ieee80211_mesh_init_sdata(sdata); | 643 | ieee80211_mesh_init_sdata(sdata); |
123 | break; | 644 | break; |
124 | case IEEE80211_IF_TYPE_MNTR: | 645 | case NL80211_IFTYPE_MONITOR: |
125 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; | 646 | sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP; |
126 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; | 647 | sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit; |
127 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | | 648 | sdata->u.mntr_flags = MONITOR_FLAG_CONTROL | |
128 | MONITOR_FLAG_OTHER_BSS; | 649 | MONITOR_FLAG_OTHER_BSS; |
129 | break; | 650 | break; |
130 | case IEEE80211_IF_TYPE_WDS: | 651 | case NL80211_IFTYPE_WDS: |
131 | case IEEE80211_IF_TYPE_VLAN: | 652 | case NL80211_IFTYPE_AP_VLAN: |
132 | break; | 653 | break; |
133 | case IEEE80211_IF_TYPE_INVALID: | 654 | case NL80211_IFTYPE_UNSPECIFIED: |
655 | case __NL80211_IFTYPE_AFTER_LAST: | ||
134 | BUG(); | 656 | BUG(); |
135 | break; | 657 | break; |
136 | } | 658 | } |
@@ -139,7 +661,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
139 | } | 661 | } |
140 | 662 | ||
141 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | 663 | int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, |
142 | enum ieee80211_if_types type) | 664 | enum nl80211_iftype type) |
143 | { | 665 | { |
144 | ASSERT_RTNL(); | 666 | ASSERT_RTNL(); |
145 | 667 | ||
@@ -160,14 +682,16 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
160 | ieee80211_setup_sdata(sdata, type); | 682 | ieee80211_setup_sdata(sdata, type); |
161 | 683 | ||
162 | /* reset some values that shouldn't be kept across type changes */ | 684 | /* reset some values that shouldn't be kept across type changes */ |
163 | sdata->basic_rates = 0; | 685 | sdata->bss_conf.basic_rates = |
686 | ieee80211_mandatory_rates(sdata->local, | ||
687 | sdata->local->hw.conf.channel->band); | ||
164 | sdata->drop_unencrypted = 0; | 688 | sdata->drop_unencrypted = 0; |
165 | 689 | ||
166 | return 0; | 690 | return 0; |
167 | } | 691 | } |
168 | 692 | ||
169 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, | 693 | int ieee80211_if_add(struct ieee80211_local *local, const char *name, |
170 | struct net_device **new_dev, enum ieee80211_if_types type, | 694 | struct net_device **new_dev, enum nl80211_iftype type, |
171 | struct vif_params *params) | 695 | struct vif_params *params) |
172 | { | 696 | { |
173 | struct net_device *ndev; | 697 | struct net_device *ndev; |
@@ -225,9 +749,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
225 | 749 | ||
226 | if (ieee80211_vif_is_mesh(&sdata->vif) && | 750 | if (ieee80211_vif_is_mesh(&sdata->vif) && |
227 | params && params->mesh_id_len) | 751 | params && params->mesh_id_len) |
228 | ieee80211_if_sta_set_mesh_id(&sdata->u.sta, | 752 | ieee80211_sdata_set_mesh_id(sdata, |
229 | params->mesh_id_len, | 753 | params->mesh_id_len, |
230 | params->mesh_id); | 754 | params->mesh_id); |
231 | 755 | ||
232 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 756 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
233 | 757 | ||
@@ -241,15 +765,13 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
241 | return ret; | 765 | return ret; |
242 | } | 766 | } |
243 | 767 | ||
244 | void ieee80211_if_remove(struct net_device *dev) | 768 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
245 | { | 769 | { |
246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
247 | |||
248 | ASSERT_RTNL(); | 770 | ASSERT_RTNL(); |
249 | 771 | ||
250 | list_del_rcu(&sdata->list); | 772 | list_del_rcu(&sdata->list); |
251 | synchronize_rcu(); | 773 | synchronize_rcu(); |
252 | unregister_netdevice(dev); | 774 | unregister_netdevice(sdata->dev); |
253 | } | 775 | } |
254 | 776 | ||
255 | /* | 777 | /* |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 6597c779e35a..57afcd38cd9e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -118,12 +118,12 @@ static const u8 *get_mac_for_key(struct ieee80211_key *key) | |||
118 | * address to indicate a transmit-only key. | 118 | * address to indicate a transmit-only key. |
119 | */ | 119 | */ |
120 | if (key->conf.alg != ALG_WEP && | 120 | if (key->conf.alg != ALG_WEP && |
121 | (key->sdata->vif.type == IEEE80211_IF_TYPE_AP || | 121 | (key->sdata->vif.type == NL80211_IFTYPE_AP || |
122 | key->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) | 122 | key->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) |
123 | addr = zero_addr; | 123 | addr = zero_addr; |
124 | 124 | ||
125 | if (key->sta) | 125 | if (key->sta) |
126 | addr = key->sta->addr; | 126 | addr = key->sta->sta.addr; |
127 | 127 | ||
128 | return addr; | 128 | return addr; |
129 | } | 129 | } |
@@ -331,7 +331,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
331 | */ | 331 | */ |
332 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; | 332 | key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE; |
333 | } else { | 333 | } else { |
334 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 334 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
335 | struct sta_info *ap; | 335 | struct sta_info *ap; |
336 | 336 | ||
337 | /* | 337 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index aa5a191598c9..c307dba7ec03 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -45,16 +45,9 @@ struct ieee80211_tx_status_rtap_hdr { | |||
45 | u8 data_retries; | 45 | u8 data_retries; |
46 | } __attribute__ ((packed)); | 46 | } __attribute__ ((packed)); |
47 | 47 | ||
48 | /* common interface routines */ | ||
49 | |||
50 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
51 | { | ||
52 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
53 | return ETH_ALEN; | ||
54 | } | ||
55 | 48 | ||
56 | /* must be called under mdev tx lock */ | 49 | /* must be called under mdev tx lock */ |
57 | static void ieee80211_configure_filter(struct ieee80211_local *local) | 50 | void ieee80211_configure_filter(struct ieee80211_local *local) |
58 | { | 51 | { |
59 | unsigned int changed_flags; | 52 | unsigned int changed_flags; |
60 | unsigned int new_flags = 0; | 53 | unsigned int new_flags = 0; |
@@ -97,6 +90,20 @@ static void ieee80211_configure_filter(struct ieee80211_local *local) | |||
97 | 90 | ||
98 | /* master interface */ | 91 | /* master interface */ |
99 | 92 | ||
93 | static int header_parse_80211(const struct sk_buff *skb, unsigned char *haddr) | ||
94 | { | ||
95 | memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ | ||
96 | return ETH_ALEN; | ||
97 | } | ||
98 | |||
99 | static const struct header_ops ieee80211_header_ops = { | ||
100 | .create = eth_header, | ||
101 | .parse = header_parse_80211, | ||
102 | .rebuild = eth_rebuild_header, | ||
103 | .cache = eth_header_cache, | ||
104 | .cache_update = eth_header_cache_update, | ||
105 | }; | ||
106 | |||
100 | static int ieee80211_master_open(struct net_device *dev) | 107 | static int ieee80211_master_open(struct net_device *dev) |
101 | { | 108 | { |
102 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 109 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
@@ -139,844 +146,6 @@ static void ieee80211_master_set_multicast_list(struct net_device *dev) | |||
139 | ieee80211_configure_filter(local); | 146 | ieee80211_configure_filter(local); |
140 | } | 147 | } |
141 | 148 | ||
142 | /* regular interfaces */ | ||
143 | |||
144 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | ||
145 | { | ||
146 | int meshhdrlen; | ||
147 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
148 | |||
149 | meshhdrlen = (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) ? 5 : 0; | ||
150 | |||
151 | /* FIX: what would be proper limits for MTU? | ||
152 | * This interface uses 802.3 frames. */ | ||
153 | if (new_mtu < 256 || | ||
154 | new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | |||
158 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
159 | printk(KERN_DEBUG "%s: setting MTU %d\n", dev->name, new_mtu); | ||
160 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
161 | dev->mtu = new_mtu; | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static inline int identical_mac_addr_allowed(int type1, int type2) | ||
166 | { | ||
167 | return (type1 == IEEE80211_IF_TYPE_MNTR || | ||
168 | type2 == IEEE80211_IF_TYPE_MNTR || | ||
169 | (type1 == IEEE80211_IF_TYPE_AP && | ||
170 | type2 == IEEE80211_IF_TYPE_WDS) || | ||
171 | (type1 == IEEE80211_IF_TYPE_WDS && | ||
172 | (type2 == IEEE80211_IF_TYPE_WDS || | ||
173 | type2 == IEEE80211_IF_TYPE_AP)) || | ||
174 | (type1 == IEEE80211_IF_TYPE_AP && | ||
175 | type2 == IEEE80211_IF_TYPE_VLAN) || | ||
176 | (type1 == IEEE80211_IF_TYPE_VLAN && | ||
177 | (type2 == IEEE80211_IF_TYPE_AP || | ||
178 | type2 == IEEE80211_IF_TYPE_VLAN))); | ||
179 | } | ||
180 | |||
181 | static int ieee80211_open(struct net_device *dev) | ||
182 | { | ||
183 | struct ieee80211_sub_if_data *sdata, *nsdata; | ||
184 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
185 | struct sta_info *sta; | ||
186 | struct ieee80211_if_init_conf conf; | ||
187 | u32 changed = 0; | ||
188 | int res; | ||
189 | bool need_hw_reconfig = 0; | ||
190 | |||
191 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
192 | |||
193 | /* we hold the RTNL here so can safely walk the list */ | ||
194 | list_for_each_entry(nsdata, &local->interfaces, list) { | ||
195 | struct net_device *ndev = nsdata->dev; | ||
196 | |||
197 | if (ndev != dev && netif_running(ndev)) { | ||
198 | /* | ||
199 | * Allow only a single IBSS interface to be up at any | ||
200 | * time. This is restricted because beacon distribution | ||
201 | * cannot work properly if both are in the same IBSS. | ||
202 | * | ||
203 | * To remove this restriction we'd have to disallow them | ||
204 | * from setting the same SSID on different IBSS interfaces | ||
205 | * belonging to the same hardware. Then, however, we're | ||
206 | * faced with having to adopt two different TSF timers... | ||
207 | */ | ||
208 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
209 | nsdata->vif.type == IEEE80211_IF_TYPE_IBSS) | ||
210 | return -EBUSY; | ||
211 | |||
212 | /* | ||
213 | * The remaining checks are only performed for interfaces | ||
214 | * with the same MAC address. | ||
215 | */ | ||
216 | if (compare_ether_addr(dev->dev_addr, ndev->dev_addr)) | ||
217 | continue; | ||
218 | |||
219 | /* | ||
220 | * check whether it may have the same address | ||
221 | */ | ||
222 | if (!identical_mac_addr_allowed(sdata->vif.type, | ||
223 | nsdata->vif.type)) | ||
224 | return -ENOTUNIQ; | ||
225 | |||
226 | /* | ||
227 | * can only add VLANs to enabled APs | ||
228 | */ | ||
229 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN && | ||
230 | nsdata->vif.type == IEEE80211_IF_TYPE_AP) | ||
231 | sdata->bss = &nsdata->u.ap; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | switch (sdata->vif.type) { | ||
236 | case IEEE80211_IF_TYPE_WDS: | ||
237 | if (!is_valid_ether_addr(sdata->u.wds.remote_addr)) | ||
238 | return -ENOLINK; | ||
239 | break; | ||
240 | case IEEE80211_IF_TYPE_VLAN: | ||
241 | if (!sdata->bss) | ||
242 | return -ENOLINK; | ||
243 | list_add(&sdata->u.vlan.list, &sdata->bss->vlans); | ||
244 | break; | ||
245 | case IEEE80211_IF_TYPE_AP: | ||
246 | sdata->bss = &sdata->u.ap; | ||
247 | break; | ||
248 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
249 | /* mesh ifaces must set allmulti to forward mcast traffic */ | ||
250 | atomic_inc(&local->iff_allmultis); | ||
251 | break; | ||
252 | case IEEE80211_IF_TYPE_STA: | ||
253 | case IEEE80211_IF_TYPE_MNTR: | ||
254 | case IEEE80211_IF_TYPE_IBSS: | ||
255 | /* no special treatment */ | ||
256 | break; | ||
257 | case IEEE80211_IF_TYPE_INVALID: | ||
258 | /* cannot happen */ | ||
259 | WARN_ON(1); | ||
260 | break; | ||
261 | } | ||
262 | |||
263 | if (local->open_count == 0) { | ||
264 | res = 0; | ||
265 | if (local->ops->start) | ||
266 | res = local->ops->start(local_to_hw(local)); | ||
267 | if (res) | ||
268 | goto err_del_bss; | ||
269 | need_hw_reconfig = 1; | ||
270 | ieee80211_led_radio(local, local->hw.conf.radio_enabled); | ||
271 | } | ||
272 | |||
273 | switch (sdata->vif.type) { | ||
274 | case IEEE80211_IF_TYPE_VLAN: | ||
275 | /* no need to tell driver */ | ||
276 | break; | ||
277 | case IEEE80211_IF_TYPE_MNTR: | ||
278 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
279 | local->cooked_mntrs++; | ||
280 | break; | ||
281 | } | ||
282 | |||
283 | /* must be before the call to ieee80211_configure_filter */ | ||
284 | local->monitors++; | ||
285 | if (local->monitors == 1) | ||
286 | local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP; | ||
287 | |||
288 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
289 | local->fif_fcsfail++; | ||
290 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
291 | local->fif_plcpfail++; | ||
292 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
293 | local->fif_control++; | ||
294 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
295 | local->fif_other_bss++; | ||
296 | |||
297 | netif_addr_lock_bh(local->mdev); | ||
298 | ieee80211_configure_filter(local); | ||
299 | netif_addr_unlock_bh(local->mdev); | ||
300 | break; | ||
301 | case IEEE80211_IF_TYPE_STA: | ||
302 | case IEEE80211_IF_TYPE_IBSS: | ||
303 | sdata->u.sta.flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
304 | /* fall through */ | ||
305 | default: | ||
306 | conf.vif = &sdata->vif; | ||
307 | conf.type = sdata->vif.type; | ||
308 | conf.mac_addr = dev->dev_addr; | ||
309 | res = local->ops->add_interface(local_to_hw(local), &conf); | ||
310 | if (res) | ||
311 | goto err_stop; | ||
312 | |||
313 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
314 | ieee80211_start_mesh(sdata->dev); | ||
315 | changed |= ieee80211_reset_erp_info(dev); | ||
316 | ieee80211_bss_info_change_notify(sdata, changed); | ||
317 | ieee80211_enable_keys(sdata); | ||
318 | |||
319 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | ||
320 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | ||
321 | netif_carrier_off(dev); | ||
322 | else | ||
323 | netif_carrier_on(dev); | ||
324 | } | ||
325 | |||
326 | if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | ||
327 | /* Create STA entry for the WDS peer */ | ||
328 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | ||
329 | GFP_KERNEL); | ||
330 | if (!sta) { | ||
331 | res = -ENOMEM; | ||
332 | goto err_del_interface; | ||
333 | } | ||
334 | |||
335 | /* no locking required since STA is not live yet */ | ||
336 | sta->flags |= WLAN_STA_AUTHORIZED; | ||
337 | |||
338 | res = sta_info_insert(sta); | ||
339 | if (res) { | ||
340 | /* STA has been freed */ | ||
341 | goto err_del_interface; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | if (local->open_count == 0) { | ||
346 | res = dev_open(local->mdev); | ||
347 | WARN_ON(res); | ||
348 | if (res) | ||
349 | goto err_del_interface; | ||
350 | tasklet_enable(&local->tx_pending_tasklet); | ||
351 | tasklet_enable(&local->tasklet); | ||
352 | } | ||
353 | |||
354 | /* | ||
355 | * set_multicast_list will be invoked by the networking core | ||
356 | * which will check whether any increments here were done in | ||
357 | * error and sync them down to the hardware as filter flags. | ||
358 | */ | ||
359 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
360 | atomic_inc(&local->iff_allmultis); | ||
361 | |||
362 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
363 | atomic_inc(&local->iff_promiscs); | ||
364 | |||
365 | local->open_count++; | ||
366 | if (need_hw_reconfig) | ||
367 | ieee80211_hw_config(local); | ||
368 | |||
369 | /* | ||
370 | * ieee80211_sta_work is disabled while network interface | ||
371 | * is down. Therefore, some configuration changes may not | ||
372 | * yet be effective. Trigger execution of ieee80211_sta_work | ||
373 | * to fix this. | ||
374 | */ | ||
375 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | ||
376 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
377 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
378 | queue_work(local->hw.workqueue, &ifsta->work); | ||
379 | } | ||
380 | |||
381 | netif_tx_start_all_queues(dev); | ||
382 | |||
383 | return 0; | ||
384 | err_del_interface: | ||
385 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
386 | err_stop: | ||
387 | if (!local->open_count && local->ops->stop) | ||
388 | local->ops->stop(local_to_hw(local)); | ||
389 | err_del_bss: | ||
390 | sdata->bss = NULL; | ||
391 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | ||
392 | list_del(&sdata->u.vlan.list); | ||
393 | return res; | ||
394 | } | ||
395 | |||
396 | static int ieee80211_stop(struct net_device *dev) | ||
397 | { | ||
398 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
399 | struct ieee80211_local *local = sdata->local; | ||
400 | struct ieee80211_if_init_conf conf; | ||
401 | struct sta_info *sta; | ||
402 | |||
403 | /* | ||
404 | * Stop TX on this interface first. | ||
405 | */ | ||
406 | netif_tx_stop_all_queues(dev); | ||
407 | |||
408 | /* | ||
409 | * Now delete all active aggregation sessions. | ||
410 | */ | ||
411 | rcu_read_lock(); | ||
412 | |||
413 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
414 | if (sta->sdata == sdata) | ||
415 | ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); | ||
416 | } | ||
417 | |||
418 | rcu_read_unlock(); | ||
419 | |||
420 | /* | ||
421 | * Remove all stations associated with this interface. | ||
422 | * | ||
423 | * This must be done before calling ops->remove_interface() | ||
424 | * because otherwise we can later invoke ops->sta_notify() | ||
425 | * whenever the STAs are removed, and that invalidates driver | ||
426 | * assumptions about always getting a vif pointer that is valid | ||
427 | * (because if we remove a STA after ops->remove_interface() | ||
428 | * the driver will have removed the vif info already!) | ||
429 | * | ||
430 | * We could relax this and only unlink the stations from the | ||
431 | * hash table and list but keep them on a per-sdata list that | ||
432 | * will be inserted back again when the interface is brought | ||
433 | * up again, but I don't currently see a use case for that, | ||
434 | * except with WDS which gets a STA entry created when it is | ||
435 | * brought up. | ||
436 | */ | ||
437 | sta_info_flush(local, sdata); | ||
438 | |||
439 | /* | ||
440 | * Don't count this interface for promisc/allmulti while it | ||
441 | * is down. dev_mc_unsync() will invoke set_multicast_list | ||
442 | * on the master interface which will sync these down to the | ||
443 | * hardware as filter flags. | ||
444 | */ | ||
445 | if (sdata->flags & IEEE80211_SDATA_ALLMULTI) | ||
446 | atomic_dec(&local->iff_allmultis); | ||
447 | |||
448 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | ||
449 | atomic_dec(&local->iff_promiscs); | ||
450 | |||
451 | dev_mc_unsync(local->mdev, dev); | ||
452 | |||
453 | /* APs need special treatment */ | ||
454 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | ||
455 | struct ieee80211_sub_if_data *vlan, *tmp; | ||
456 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | ||
457 | |||
458 | /* remove beacon */ | ||
459 | rcu_assign_pointer(sdata->u.ap.beacon, NULL); | ||
460 | synchronize_rcu(); | ||
461 | kfree(old_beacon); | ||
462 | |||
463 | /* down all dependent devices, that is VLANs */ | ||
464 | list_for_each_entry_safe(vlan, tmp, &sdata->u.ap.vlans, | ||
465 | u.vlan.list) | ||
466 | dev_close(vlan->dev); | ||
467 | WARN_ON(!list_empty(&sdata->u.ap.vlans)); | ||
468 | } | ||
469 | |||
470 | local->open_count--; | ||
471 | |||
472 | switch (sdata->vif.type) { | ||
473 | case IEEE80211_IF_TYPE_VLAN: | ||
474 | list_del(&sdata->u.vlan.list); | ||
475 | /* no need to tell driver */ | ||
476 | break; | ||
477 | case IEEE80211_IF_TYPE_MNTR: | ||
478 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) { | ||
479 | local->cooked_mntrs--; | ||
480 | break; | ||
481 | } | ||
482 | |||
483 | local->monitors--; | ||
484 | if (local->monitors == 0) | ||
485 | local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP; | ||
486 | |||
487 | if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL) | ||
488 | local->fif_fcsfail--; | ||
489 | if (sdata->u.mntr_flags & MONITOR_FLAG_PLCPFAIL) | ||
490 | local->fif_plcpfail--; | ||
491 | if (sdata->u.mntr_flags & MONITOR_FLAG_CONTROL) | ||
492 | local->fif_control--; | ||
493 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | ||
494 | local->fif_other_bss--; | ||
495 | |||
496 | netif_addr_lock_bh(local->mdev); | ||
497 | ieee80211_configure_filter(local); | ||
498 | netif_addr_unlock_bh(local->mdev); | ||
499 | break; | ||
500 | case IEEE80211_IF_TYPE_MESH_POINT: | ||
501 | /* allmulti is always set on mesh ifaces */ | ||
502 | atomic_dec(&local->iff_allmultis); | ||
503 | /* fall through */ | ||
504 | case IEEE80211_IF_TYPE_STA: | ||
505 | case IEEE80211_IF_TYPE_IBSS: | ||
506 | sdata->u.sta.state = IEEE80211_DISABLED; | ||
507 | memset(sdata->u.sta.bssid, 0, ETH_ALEN); | ||
508 | del_timer_sync(&sdata->u.sta.timer); | ||
509 | /* | ||
510 | * When we get here, the interface is marked down. | ||
511 | * Call synchronize_rcu() to wait for the RX path | ||
512 | * should it be using the interface and enqueuing | ||
513 | * frames at this very time on another CPU. | ||
514 | */ | ||
515 | synchronize_rcu(); | ||
516 | skb_queue_purge(&sdata->u.sta.skb_queue); | ||
517 | |||
518 | if (local->scan_dev == sdata->dev) { | ||
519 | if (!local->ops->hw_scan) { | ||
520 | local->sta_sw_scanning = 0; | ||
521 | cancel_delayed_work(&local->scan_work); | ||
522 | } else | ||
523 | local->sta_hw_scanning = 0; | ||
524 | } | ||
525 | |||
526 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | ||
527 | kfree(sdata->u.sta.extra_ie); | ||
528 | sdata->u.sta.extra_ie = NULL; | ||
529 | sdata->u.sta.extra_ie_len = 0; | ||
530 | /* fall through */ | ||
531 | default: | ||
532 | conf.vif = &sdata->vif; | ||
533 | conf.type = sdata->vif.type; | ||
534 | conf.mac_addr = dev->dev_addr; | ||
535 | /* disable all keys for as long as this netdev is down */ | ||
536 | ieee80211_disable_keys(sdata); | ||
537 | local->ops->remove_interface(local_to_hw(local), &conf); | ||
538 | } | ||
539 | |||
540 | sdata->bss = NULL; | ||
541 | |||
542 | if (local->open_count == 0) { | ||
543 | if (netif_running(local->mdev)) | ||
544 | dev_close(local->mdev); | ||
545 | |||
546 | if (local->ops->stop) | ||
547 | local->ops->stop(local_to_hw(local)); | ||
548 | |||
549 | ieee80211_led_radio(local, 0); | ||
550 | |||
551 | flush_workqueue(local->hw.workqueue); | ||
552 | |||
553 | tasklet_disable(&local->tx_pending_tasklet); | ||
554 | tasklet_disable(&local->tasklet); | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
561 | { | ||
562 | struct ieee80211_local *local = hw_to_local(hw); | ||
563 | struct sta_info *sta; | ||
564 | struct ieee80211_sub_if_data *sdata; | ||
565 | u16 start_seq_num = 0; | ||
566 | u8 *state; | ||
567 | int ret; | ||
568 | DECLARE_MAC_BUF(mac); | ||
569 | |||
570 | if (tid >= STA_TID_NUM) | ||
571 | return -EINVAL; | ||
572 | |||
573 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
574 | printk(KERN_DEBUG "Open BA session requested for %s tid %u\n", | ||
575 | print_mac(mac, ra), tid); | ||
576 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
577 | |||
578 | rcu_read_lock(); | ||
579 | |||
580 | sta = sta_info_get(local, ra); | ||
581 | if (!sta) { | ||
582 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
583 | printk(KERN_DEBUG "Could not find the station\n"); | ||
584 | #endif | ||
585 | ret = -ENOENT; | ||
586 | goto exit; | ||
587 | } | ||
588 | |||
589 | spin_lock_bh(&sta->lock); | ||
590 | |||
591 | /* we have tried too many times, receiver does not want A-MPDU */ | ||
592 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | ||
593 | ret = -EBUSY; | ||
594 | goto err_unlock_sta; | ||
595 | } | ||
596 | |||
597 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
598 | /* check if the TID is not in aggregation flow already */ | ||
599 | if (*state != HT_AGG_STATE_IDLE) { | ||
600 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
601 | printk(KERN_DEBUG "BA request denied - session is not " | ||
602 | "idle on tid %u\n", tid); | ||
603 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
604 | ret = -EAGAIN; | ||
605 | goto err_unlock_sta; | ||
606 | } | ||
607 | |||
608 | /* prepare A-MPDU MLME for Tx aggregation */ | ||
609 | sta->ampdu_mlme.tid_tx[tid] = | ||
610 | kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | ||
611 | if (!sta->ampdu_mlme.tid_tx[tid]) { | ||
612 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
613 | if (net_ratelimit()) | ||
614 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
615 | tid); | ||
616 | #endif | ||
617 | ret = -ENOMEM; | ||
618 | goto err_unlock_sta; | ||
619 | } | ||
620 | /* Tx timer */ | ||
621 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function = | ||
622 | sta_addba_resp_timer_expired; | ||
623 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data = | ||
624 | (unsigned long)&sta->timer_to_tid[tid]; | ||
625 | init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
626 | |||
627 | /* create a new queue for this aggregation */ | ||
628 | ret = ieee80211_ht_agg_queue_add(local, sta, tid); | ||
629 | |||
630 | /* case no queue is available to aggregation | ||
631 | * don't switch to aggregation */ | ||
632 | if (ret) { | ||
633 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
634 | printk(KERN_DEBUG "BA request denied - queue unavailable for" | ||
635 | " tid %d\n", tid); | ||
636 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
637 | goto err_unlock_queue; | ||
638 | } | ||
639 | sdata = sta->sdata; | ||
640 | |||
641 | /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the | ||
642 | * call back right away, it must see that the flow has begun */ | ||
643 | *state |= HT_ADDBA_REQUESTED_MSK; | ||
644 | |||
645 | if (local->ops->ampdu_action) | ||
646 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START, | ||
647 | ra, tid, &start_seq_num); | ||
648 | |||
649 | if (ret) { | ||
650 | /* No need to requeue the packets in the agg queue, since we | ||
651 | * held the tx lock: no packet could be enqueued to the newly | ||
652 | * allocated queue */ | ||
653 | ieee80211_ht_agg_queue_remove(local, sta, tid, 0); | ||
654 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
655 | printk(KERN_DEBUG "BA request denied - HW unavailable for" | ||
656 | " tid %d\n", tid); | ||
657 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
658 | *state = HT_AGG_STATE_IDLE; | ||
659 | goto err_unlock_queue; | ||
660 | } | ||
661 | |||
662 | /* Will put all the packets in the new SW queue */ | ||
663 | ieee80211_requeue(local, ieee802_1d_to_ac[tid]); | ||
664 | spin_unlock_bh(&sta->lock); | ||
665 | |||
666 | /* send an addBA request */ | ||
667 | sta->ampdu_mlme.dialog_token_allocator++; | ||
668 | sta->ampdu_mlme.tid_tx[tid]->dialog_token = | ||
669 | sta->ampdu_mlme.dialog_token_allocator; | ||
670 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | ||
671 | |||
672 | |||
673 | ieee80211_send_addba_request(sta->sdata->dev, ra, tid, | ||
674 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | ||
675 | sta->ampdu_mlme.tid_tx[tid]->ssn, | ||
676 | 0x40, 5000); | ||
677 | /* activate the timer for the recipient's addBA response */ | ||
678 | sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires = | ||
679 | jiffies + ADDBA_RESP_INTERVAL; | ||
680 | add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | ||
681 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
682 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | ||
683 | #endif | ||
684 | goto exit; | ||
685 | |||
686 | err_unlock_queue: | ||
687 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
688 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
689 | ret = -EBUSY; | ||
690 | err_unlock_sta: | ||
691 | spin_unlock_bh(&sta->lock); | ||
692 | exit: | ||
693 | rcu_read_unlock(); | ||
694 | return ret; | ||
695 | } | ||
696 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | ||
697 | |||
698 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | ||
699 | u8 *ra, u16 tid, | ||
700 | enum ieee80211_back_parties initiator) | ||
701 | { | ||
702 | struct ieee80211_local *local = hw_to_local(hw); | ||
703 | struct sta_info *sta; | ||
704 | u8 *state; | ||
705 | int ret = 0; | ||
706 | DECLARE_MAC_BUF(mac); | ||
707 | |||
708 | if (tid >= STA_TID_NUM) | ||
709 | return -EINVAL; | ||
710 | |||
711 | rcu_read_lock(); | ||
712 | sta = sta_info_get(local, ra); | ||
713 | if (!sta) { | ||
714 | rcu_read_unlock(); | ||
715 | return -ENOENT; | ||
716 | } | ||
717 | |||
718 | /* check if the TID is in aggregation */ | ||
719 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
720 | spin_lock_bh(&sta->lock); | ||
721 | |||
722 | if (*state != HT_AGG_STATE_OPERATIONAL) { | ||
723 | ret = -ENOENT; | ||
724 | goto stop_BA_exit; | ||
725 | } | ||
726 | |||
727 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
728 | printk(KERN_DEBUG "Tx BA session stop requested for %s tid %u\n", | ||
729 | print_mac(mac, ra), tid); | ||
730 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
731 | |||
732 | ieee80211_stop_queue(hw, sta->tid_to_tx_q[tid]); | ||
733 | |||
734 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
735 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
736 | |||
737 | if (local->ops->ampdu_action) | ||
738 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_STOP, | ||
739 | ra, tid, NULL); | ||
740 | |||
741 | /* case HW denied going back to legacy */ | ||
742 | if (ret) { | ||
743 | WARN_ON(ret != -EBUSY); | ||
744 | *state = HT_AGG_STATE_OPERATIONAL; | ||
745 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
746 | goto stop_BA_exit; | ||
747 | } | ||
748 | |||
749 | stop_BA_exit: | ||
750 | spin_unlock_bh(&sta->lock); | ||
751 | rcu_read_unlock(); | ||
752 | return ret; | ||
753 | } | ||
754 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | ||
755 | |||
756 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | ||
757 | { | ||
758 | struct ieee80211_local *local = hw_to_local(hw); | ||
759 | struct sta_info *sta; | ||
760 | u8 *state; | ||
761 | DECLARE_MAC_BUF(mac); | ||
762 | |||
763 | if (tid >= STA_TID_NUM) { | ||
764 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
765 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
766 | tid, STA_TID_NUM); | ||
767 | #endif | ||
768 | return; | ||
769 | } | ||
770 | |||
771 | rcu_read_lock(); | ||
772 | sta = sta_info_get(local, ra); | ||
773 | if (!sta) { | ||
774 | rcu_read_unlock(); | ||
775 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
776 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
777 | print_mac(mac, ra)); | ||
778 | #endif | ||
779 | return; | ||
780 | } | ||
781 | |||
782 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
783 | spin_lock_bh(&sta->lock); | ||
784 | |||
785 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | ||
786 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
787 | printk(KERN_DEBUG "addBA was not requested yet, state is %d\n", | ||
788 | *state); | ||
789 | #endif | ||
790 | spin_unlock_bh(&sta->lock); | ||
791 | rcu_read_unlock(); | ||
792 | return; | ||
793 | } | ||
794 | |||
795 | WARN_ON_ONCE(*state & HT_ADDBA_DRV_READY_MSK); | ||
796 | |||
797 | *state |= HT_ADDBA_DRV_READY_MSK; | ||
798 | |||
799 | if (*state == HT_AGG_STATE_OPERATIONAL) { | ||
800 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
801 | printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid); | ||
802 | #endif | ||
803 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | ||
804 | } | ||
805 | spin_unlock_bh(&sta->lock); | ||
806 | rcu_read_unlock(); | ||
807 | } | ||
808 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | ||
809 | |||
810 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | ||
811 | { | ||
812 | struct ieee80211_local *local = hw_to_local(hw); | ||
813 | struct sta_info *sta; | ||
814 | u8 *state; | ||
815 | int agg_queue; | ||
816 | DECLARE_MAC_BUF(mac); | ||
817 | |||
818 | if (tid >= STA_TID_NUM) { | ||
819 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
820 | printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n", | ||
821 | tid, STA_TID_NUM); | ||
822 | #endif | ||
823 | return; | ||
824 | } | ||
825 | |||
826 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
827 | printk(KERN_DEBUG "Stopping Tx BA session for %s tid %d\n", | ||
828 | print_mac(mac, ra), tid); | ||
829 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
830 | |||
831 | rcu_read_lock(); | ||
832 | sta = sta_info_get(local, ra); | ||
833 | if (!sta) { | ||
834 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
835 | printk(KERN_DEBUG "Could not find station: %s\n", | ||
836 | print_mac(mac, ra)); | ||
837 | #endif | ||
838 | rcu_read_unlock(); | ||
839 | return; | ||
840 | } | ||
841 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | ||
842 | |||
843 | /* NOTE: no need to use sta->lock in this state check, as | ||
844 | * ieee80211_stop_tx_ba_session will let only one stop call to | ||
845 | * pass through per sta/tid | ||
846 | */ | ||
847 | if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) { | ||
848 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
849 | printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n"); | ||
850 | #endif | ||
851 | rcu_read_unlock(); | ||
852 | return; | ||
853 | } | ||
854 | |||
855 | if (*state & HT_AGG_STATE_INITIATOR_MSK) | ||
856 | ieee80211_send_delba(sta->sdata->dev, ra, tid, | ||
857 | WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); | ||
858 | |||
859 | agg_queue = sta->tid_to_tx_q[tid]; | ||
860 | |||
861 | ieee80211_ht_agg_queue_remove(local, sta, tid, 1); | ||
862 | |||
863 | /* We just requeued the all the frames that were in the | ||
864 | * removed queue, and since we might miss a softirq we do | ||
865 | * netif_schedule_queue. ieee80211_wake_queue is not used | ||
866 | * here as this queue is not necessarily stopped | ||
867 | */ | ||
868 | netif_schedule_queue(netdev_get_tx_queue(local->mdev, agg_queue)); | ||
869 | spin_lock_bh(&sta->lock); | ||
870 | *state = HT_AGG_STATE_IDLE; | ||
871 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
872 | kfree(sta->ampdu_mlme.tid_tx[tid]); | ||
873 | sta->ampdu_mlme.tid_tx[tid] = NULL; | ||
874 | spin_unlock_bh(&sta->lock); | ||
875 | |||
876 | rcu_read_unlock(); | ||
877 | } | ||
878 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | ||
879 | |||
880 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
881 | const u8 *ra, u16 tid) | ||
882 | { | ||
883 | struct ieee80211_local *local = hw_to_local(hw); | ||
884 | struct ieee80211_ra_tid *ra_tid; | ||
885 | struct sk_buff *skb = dev_alloc_skb(0); | ||
886 | |||
887 | if (unlikely(!skb)) { | ||
888 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
889 | if (net_ratelimit()) | ||
890 | printk(KERN_WARNING "%s: Not enough memory, " | ||
891 | "dropping start BA session", skb->dev->name); | ||
892 | #endif | ||
893 | return; | ||
894 | } | ||
895 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
896 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
897 | ra_tid->tid = tid; | ||
898 | |||
899 | skb->pkt_type = IEEE80211_ADDBA_MSG; | ||
900 | skb_queue_tail(&local->skb_queue, skb); | ||
901 | tasklet_schedule(&local->tasklet); | ||
902 | } | ||
903 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); | ||
904 | |||
905 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | ||
906 | const u8 *ra, u16 tid) | ||
907 | { | ||
908 | struct ieee80211_local *local = hw_to_local(hw); | ||
909 | struct ieee80211_ra_tid *ra_tid; | ||
910 | struct sk_buff *skb = dev_alloc_skb(0); | ||
911 | |||
912 | if (unlikely(!skb)) { | ||
913 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
914 | if (net_ratelimit()) | ||
915 | printk(KERN_WARNING "%s: Not enough memory, " | ||
916 | "dropping stop BA session", skb->dev->name); | ||
917 | #endif | ||
918 | return; | ||
919 | } | ||
920 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | ||
921 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | ||
922 | ra_tid->tid = tid; | ||
923 | |||
924 | skb->pkt_type = IEEE80211_DELBA_MSG; | ||
925 | skb_queue_tail(&local->skb_queue, skb); | ||
926 | tasklet_schedule(&local->tasklet); | ||
927 | } | ||
928 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); | ||
929 | |||
930 | static void ieee80211_set_multicast_list(struct net_device *dev) | ||
931 | { | ||
932 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
933 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
934 | int allmulti, promisc, sdata_allmulti, sdata_promisc; | ||
935 | |||
936 | allmulti = !!(dev->flags & IFF_ALLMULTI); | ||
937 | promisc = !!(dev->flags & IFF_PROMISC); | ||
938 | sdata_allmulti = !!(sdata->flags & IEEE80211_SDATA_ALLMULTI); | ||
939 | sdata_promisc = !!(sdata->flags & IEEE80211_SDATA_PROMISC); | ||
940 | |||
941 | if (allmulti != sdata_allmulti) { | ||
942 | if (dev->flags & IFF_ALLMULTI) | ||
943 | atomic_inc(&local->iff_allmultis); | ||
944 | else | ||
945 | atomic_dec(&local->iff_allmultis); | ||
946 | sdata->flags ^= IEEE80211_SDATA_ALLMULTI; | ||
947 | } | ||
948 | |||
949 | if (promisc != sdata_promisc) { | ||
950 | if (dev->flags & IFF_PROMISC) | ||
951 | atomic_inc(&local->iff_promiscs); | ||
952 | else | ||
953 | atomic_dec(&local->iff_promiscs); | ||
954 | sdata->flags ^= IEEE80211_SDATA_PROMISC; | ||
955 | } | ||
956 | |||
957 | dev_mc_sync(local->mdev, dev); | ||
958 | } | ||
959 | |||
960 | static const struct header_ops ieee80211_header_ops = { | ||
961 | .create = eth_header, | ||
962 | .parse = header_parse_80211, | ||
963 | .rebuild = eth_rebuild_header, | ||
964 | .cache = eth_header_cache, | ||
965 | .cache_update = eth_header_cache_update, | ||
966 | }; | ||
967 | |||
968 | void ieee80211_if_setup(struct net_device *dev) | ||
969 | { | ||
970 | ether_setup(dev); | ||
971 | dev->hard_start_xmit = ieee80211_subif_start_xmit; | ||
972 | dev->wireless_handlers = &ieee80211_iw_handler_def; | ||
973 | dev->set_multicast_list = ieee80211_set_multicast_list; | ||
974 | dev->change_mtu = ieee80211_change_mtu; | ||
975 | dev->open = ieee80211_open; | ||
976 | dev->stop = ieee80211_stop; | ||
977 | dev->destructor = free_netdev; | ||
978 | } | ||
979 | |||
980 | /* everything else */ | 149 | /* everything else */ |
981 | 150 | ||
982 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | 151 | int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) |
@@ -987,18 +156,21 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
987 | if (WARN_ON(!netif_running(sdata->dev))) | 156 | if (WARN_ON(!netif_running(sdata->dev))) |
988 | return 0; | 157 | return 0; |
989 | 158 | ||
159 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
160 | return -EINVAL; | ||
161 | |||
990 | if (!local->ops->config_interface) | 162 | if (!local->ops->config_interface) |
991 | return 0; | 163 | return 0; |
992 | 164 | ||
993 | memset(&conf, 0, sizeof(conf)); | 165 | memset(&conf, 0, sizeof(conf)); |
994 | conf.changed = changed; | 166 | conf.changed = changed; |
995 | 167 | ||
996 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 168 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
997 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 169 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
998 | conf.bssid = sdata->u.sta.bssid; | 170 | conf.bssid = sdata->u.sta.bssid; |
999 | conf.ssid = sdata->u.sta.ssid; | 171 | conf.ssid = sdata->u.sta.ssid; |
1000 | conf.ssid_len = sdata->u.sta.ssid_len; | 172 | conf.ssid_len = sdata->u.sta.ssid_len; |
1001 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 173 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1002 | conf.bssid = sdata->dev->dev_addr; | 174 | conf.bssid = sdata->dev->dev_addr; |
1003 | conf.ssid = sdata->u.ap.ssid; | 175 | conf.ssid = sdata->u.ap.ssid; |
1004 | conf.ssid_len = sdata->u.ap.ssid_len; | 176 | conf.ssid_len = sdata->u.ap.ssid_len; |
@@ -1027,7 +199,7 @@ int ieee80211_hw_config(struct ieee80211_local *local) | |||
1027 | struct ieee80211_channel *chan; | 199 | struct ieee80211_channel *chan; |
1028 | int ret = 0; | 200 | int ret = 0; |
1029 | 201 | ||
1030 | if (local->sta_sw_scanning) | 202 | if (local->sw_scanning) |
1031 | chan = local->scan_channel; | 203 | chan = local->scan_channel; |
1032 | else | 204 | else |
1033 | chan = local->oper_channel; | 205 | chan = local->oper_channel; |
@@ -1099,8 +271,8 @@ u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht, | |||
1099 | ht_conf.ht_supported = 1; | 271 | ht_conf.ht_supported = 1; |
1100 | 272 | ||
1101 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; | 273 | ht_conf.cap = req_ht_cap->cap & sband->ht_info.cap; |
1102 | ht_conf.cap &= ~(IEEE80211_HT_CAP_MIMO_PS); | 274 | ht_conf.cap &= ~(IEEE80211_HT_CAP_SM_PS); |
1103 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_MIMO_PS; | 275 | ht_conf.cap |= sband->ht_info.cap & IEEE80211_HT_CAP_SM_PS; |
1104 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; | 276 | ht_bss_conf.primary_channel = req_bss_cap->primary_channel; |
1105 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; | 277 | ht_bss_conf.bss_cap = req_bss_cap->bss_cap; |
1106 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; | 278 | ht_bss_conf.bss_op_mode = req_bss_cap->bss_op_mode; |
@@ -1152,6 +324,9 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1152 | { | 324 | { |
1153 | struct ieee80211_local *local = sdata->local; | 325 | struct ieee80211_local *local = sdata->local; |
1154 | 326 | ||
327 | if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) | ||
328 | return; | ||
329 | |||
1155 | if (!changed) | 330 | if (!changed) |
1156 | return; | 331 | return; |
1157 | 332 | ||
@@ -1162,10 +337,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
1162 | changed); | 337 | changed); |
1163 | } | 338 | } |
1164 | 339 | ||
1165 | u32 ieee80211_reset_erp_info(struct net_device *dev) | 340 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
1166 | { | 341 | { |
1167 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1168 | |||
1169 | sdata->bss_conf.use_cts_prot = 0; | 342 | sdata->bss_conf.use_cts_prot = 0; |
1170 | sdata->bss_conf.use_short_preamble = 0; | 343 | sdata->bss_conf.use_short_preamble = 0; |
1171 | return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; | 344 | return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; |
@@ -1244,9 +417,10 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1244 | struct ieee80211_key *key, | 417 | struct ieee80211_key *key, |
1245 | struct sk_buff *skb) | 418 | struct sk_buff *skb) |
1246 | { | 419 | { |
1247 | int hdrlen, iv_len, mic_len; | 420 | unsigned int hdrlen, iv_len, mic_len; |
421 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1248 | 422 | ||
1249 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 423 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1250 | 424 | ||
1251 | if (!key) | 425 | if (!key) |
1252 | goto no_key; | 426 | goto no_key; |
@@ -1268,24 +442,20 @@ static void ieee80211_remove_tx_extra(struct ieee80211_local *local, | |||
1268 | goto no_key; | 442 | goto no_key; |
1269 | } | 443 | } |
1270 | 444 | ||
1271 | if (skb->len >= mic_len && | 445 | if (skb->len >= hdrlen + mic_len && |
1272 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) | 446 | !(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) |
1273 | skb_trim(skb, skb->len - mic_len); | 447 | skb_trim(skb, skb->len - mic_len); |
1274 | if (skb->len >= iv_len && skb->len > hdrlen) { | 448 | if (skb->len >= hdrlen + iv_len) { |
1275 | memmove(skb->data + iv_len, skb->data, hdrlen); | 449 | memmove(skb->data + iv_len, skb->data, hdrlen); |
1276 | skb_pull(skb, iv_len); | 450 | hdr = (struct ieee80211_hdr *)skb_pull(skb, iv_len); |
1277 | } | 451 | } |
1278 | 452 | ||
1279 | no_key: | 453 | no_key: |
1280 | { | 454 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
1281 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 455 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1282 | u16 fc = le16_to_cpu(hdr->frame_control); | 456 | memmove(skb->data + IEEE80211_QOS_CTL_LEN, skb->data, |
1283 | if ((fc & 0x8C) == 0x88) /* QoS Control Field */ { | 457 | hdrlen - IEEE80211_QOS_CTL_LEN); |
1284 | fc &= ~IEEE80211_STYPE_QOS_DATA; | 458 | skb_pull(skb, IEEE80211_QOS_CTL_LEN); |
1285 | hdr->frame_control = cpu_to_le16(fc); | ||
1286 | memmove(skb->data + 2, skb->data, hdrlen - 2); | ||
1287 | skb_pull(skb, 2); | ||
1288 | } | ||
1289 | } | 459 | } |
1290 | } | 460 | } |
1291 | 461 | ||
@@ -1376,47 +546,47 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1376 | 546 | ||
1377 | rcu_read_lock(); | 547 | rcu_read_lock(); |
1378 | 548 | ||
1379 | if (info->status.excessive_retries) { | 549 | sta = sta_info_get(local, hdr->addr1); |
1380 | sta = sta_info_get(local, hdr->addr1); | 550 | |
1381 | if (sta) { | 551 | if (sta) { |
1382 | if (test_sta_flags(sta, WLAN_STA_PS)) { | 552 | if (info->status.excessive_retries && |
1383 | /* | 553 | test_sta_flags(sta, WLAN_STA_PS)) { |
1384 | * The STA is in power save mode, so assume | 554 | /* |
1385 | * that this TX packet failed because of that. | 555 | * The STA is in power save mode, so assume |
1386 | */ | 556 | * that this TX packet failed because of that. |
1387 | ieee80211_handle_filtered_frame(local, sta, skb); | 557 | */ |
1388 | rcu_read_unlock(); | 558 | ieee80211_handle_filtered_frame(local, sta, skb); |
1389 | return; | 559 | rcu_read_unlock(); |
1390 | } | 560 | return; |
1391 | } | 561 | } |
1392 | } | ||
1393 | 562 | ||
1394 | fc = hdr->frame_control; | 563 | fc = hdr->frame_control; |
564 | |||
565 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
566 | (ieee80211_is_data_qos(fc))) { | ||
567 | u16 tid, ssn; | ||
568 | u8 *qc; | ||
1395 | 569 | ||
1396 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
1397 | (ieee80211_is_data_qos(fc))) { | ||
1398 | u16 tid, ssn; | ||
1399 | u8 *qc; | ||
1400 | sta = sta_info_get(local, hdr->addr1); | ||
1401 | if (sta) { | ||
1402 | qc = ieee80211_get_qos_ctl(hdr); | 570 | qc = ieee80211_get_qos_ctl(hdr); |
1403 | tid = qc[0] & 0xf; | 571 | tid = qc[0] & 0xf; |
1404 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | 572 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) |
1405 | & IEEE80211_SCTL_SEQ); | 573 | & IEEE80211_SCTL_SEQ); |
1406 | ieee80211_send_bar(sta->sdata->dev, hdr->addr1, | 574 | ieee80211_send_bar(sta->sdata, hdr->addr1, |
1407 | tid, ssn); | 575 | tid, ssn); |
1408 | } | 576 | } |
1409 | } | ||
1410 | 577 | ||
1411 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | 578 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { |
1412 | sta = sta_info_get(local, hdr->addr1); | ||
1413 | if (sta) { | ||
1414 | ieee80211_handle_filtered_frame(local, sta, skb); | 579 | ieee80211_handle_filtered_frame(local, sta, skb); |
1415 | rcu_read_unlock(); | 580 | rcu_read_unlock(); |
1416 | return; | 581 | return; |
582 | } else { | ||
583 | if (info->status.excessive_retries) | ||
584 | sta->tx_retry_failed++; | ||
585 | sta->tx_retry_count += info->status.retry_count; | ||
1417 | } | 586 | } |
1418 | } else | 587 | |
1419 | rate_control_tx_status(local->mdev, skb); | 588 | rate_control_tx_status(local->mdev, skb); |
589 | } | ||
1420 | 590 | ||
1421 | rcu_read_unlock(); | 591 | rcu_read_unlock(); |
1422 | 592 | ||
@@ -1504,7 +674,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1504 | 674 | ||
1505 | rcu_read_lock(); | 675 | rcu_read_lock(); |
1506 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 676 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
1507 | if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) { | 677 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
1508 | if (!netif_running(sdata->dev)) | 678 | if (!netif_running(sdata->dev)) |
1509 | continue; | 679 | continue; |
1510 | 680 | ||
@@ -1580,8 +750,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1580 | 750 | ||
1581 | local->hw.queues = 1; /* default */ | 751 | local->hw.queues = 1; /* default */ |
1582 | 752 | ||
1583 | local->bridge_packets = 1; | ||
1584 | |||
1585 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 753 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
1586 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; | 754 | local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; |
1587 | local->short_retry_limit = 7; | 755 | local->short_retry_limit = 7; |
@@ -1592,7 +760,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
1592 | 760 | ||
1593 | spin_lock_init(&local->key_lock); | 761 | spin_lock_init(&local->key_lock); |
1594 | 762 | ||
1595 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_sta_scan_work); | 763 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
1596 | 764 | ||
1597 | sta_info_init(local); | 765 | sta_info_init(local); |
1598 | 766 | ||
@@ -1639,6 +807,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1639 | } | 807 | } |
1640 | } | 808 | } |
1641 | 809 | ||
810 | /* if low-level driver supports AP, we also support VLAN */ | ||
811 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | ||
812 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | ||
813 | |||
814 | /* mac80211 always supports monitor */ | ||
815 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | ||
816 | |||
1642 | result = wiphy_register(local->hw.wiphy); | 817 | result = wiphy_register(local->hw.wiphy); |
1643 | if (result < 0) | 818 | if (result < 0) |
1644 | return result; | 819 | return result; |
@@ -1745,7 +920,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1745 | 920 | ||
1746 | /* add one default STA interface */ | 921 | /* add one default STA interface */ |
1747 | result = ieee80211_if_add(local, "wlan%d", NULL, | 922 | result = ieee80211_if_add(local, "wlan%d", NULL, |
1748 | IEEE80211_IF_TYPE_STA, NULL); | 923 | NL80211_IFTYPE_STATION, NULL); |
1749 | if (result) | 924 | if (result) |
1750 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 925 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", |
1751 | wiphy_name(local->hw.wiphy)); | 926 | wiphy_name(local->hw.wiphy)); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 35f2f95f2fa7..30cf891fd3a8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -12,6 +12,9 @@ | |||
12 | #include "ieee80211_i.h" | 12 | #include "ieee80211_i.h" |
13 | #include "mesh.h" | 13 | #include "mesh.h" |
14 | 14 | ||
15 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
17 | |||
15 | #define PP_OFFSET 1 /* Path Selection Protocol */ | 18 | #define PP_OFFSET 1 /* Path Selection Protocol */ |
16 | #define PM_OFFSET 5 /* Path Selection Metric */ | 19 | #define PM_OFFSET 5 /* Path Selection Metric */ |
17 | #define CC_OFFSET 9 /* Congestion Control Mode */ | 20 | #define CC_OFFSET 9 /* Congestion Control Mode */ |
@@ -35,19 +38,28 @@ void ieee80211s_stop(void) | |||
35 | kmem_cache_destroy(rm_cache); | 38 | kmem_cache_destroy(rm_cache); |
36 | } | 39 | } |
37 | 40 | ||
41 | static void ieee80211_mesh_housekeeping_timer(unsigned long data) | ||
42 | { | ||
43 | struct ieee80211_sub_if_data *sdata = (void *) data; | ||
44 | struct ieee80211_local *local = sdata->local; | ||
45 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
46 | |||
47 | ifmsh->housekeeping = true; | ||
48 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
49 | } | ||
50 | |||
38 | /** | 51 | /** |
39 | * mesh_matches_local - check if the config of a mesh point matches ours | 52 | * mesh_matches_local - check if the config of a mesh point matches ours |
40 | * | 53 | * |
41 | * @ie: information elements of a management frame from the mesh peer | 54 | * @ie: information elements of a management frame from the mesh peer |
42 | * @dev: local mesh interface | 55 | * @sdata: local mesh subif |
43 | * | 56 | * |
44 | * This function checks if the mesh configuration of a mesh point matches the | 57 | * This function checks if the mesh configuration of a mesh point matches the |
45 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. | 58 | * local mesh configuration, i.e. if both nodes belong to the same mesh network. |
46 | */ | 59 | */ |
47 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | 60 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) |
48 | { | 61 | { |
49 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 62 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
50 | struct ieee80211_if_sta *sta = &sdata->u.sta; | ||
51 | 63 | ||
52 | /* | 64 | /* |
53 | * As support for each feature is added, check for matching | 65 | * As support for each feature is added, check for matching |
@@ -59,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | |||
59 | * - MDA enabled | 71 | * - MDA enabled |
60 | * - Power management control on fc | 72 | * - Power management control on fc |
61 | */ | 73 | */ |
62 | if (sta->mesh_id_len == ie->mesh_id_len && | 74 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
63 | memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 75 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
64 | memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && | 76 | memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && |
65 | memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && | 77 | memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && |
66 | memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) | 78 | memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) |
67 | return true; | 79 | return true; |
68 | 80 | ||
69 | return false; | 81 | return false; |
@@ -73,10 +85,8 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev) | |||
73 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links | 85 | * mesh_peer_accepts_plinks - check if an mp is willing to establish peer links |
74 | * | 86 | * |
75 | * @ie: information elements of a management frame from the mesh peer | 87 | * @ie: information elements of a management frame from the mesh peer |
76 | * @dev: local mesh interface | ||
77 | */ | 88 | */ |
78 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, | 89 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
79 | struct net_device *dev) | ||
80 | { | 90 | { |
81 | return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; | 91 | return (*(ie->mesh_config + CAPAB_OFFSET) & ACCEPT_PLINKS) != 0; |
82 | } | 92 | } |
@@ -98,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
98 | */ | 108 | */ |
99 | free_plinks = mesh_plink_availables(sdata); | 109 | free_plinks = mesh_plink_availables(sdata); |
100 | 110 | ||
101 | if (free_plinks != sdata->u.sta.accepting_plinks) | 111 | if (free_plinks != sdata->u.mesh.accepting_plinks) |
102 | ieee80211_sta_timer((unsigned long) sdata); | 112 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); |
103 | } | 113 | } |
104 | 114 | ||
105 | void mesh_ids_set_default(struct ieee80211_if_sta *sta) | 115 | void mesh_ids_set_default(struct ieee80211_if_mesh *sta) |
106 | { | 116 | { |
107 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; | 117 | u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; |
108 | 118 | ||
@@ -111,28 +121,26 @@ void mesh_ids_set_default(struct ieee80211_if_sta *sta) | |||
111 | memcpy(sta->mesh_cc_id, def_id, 4); | 121 | memcpy(sta->mesh_cc_id, def_id, 4); |
112 | } | 122 | } |
113 | 123 | ||
114 | int mesh_rmc_init(struct net_device *dev) | 124 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
115 | { | 125 | { |
116 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
117 | int i; | 126 | int i; |
118 | 127 | ||
119 | sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); | 128 | sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); |
120 | if (!sdata->u.sta.rmc) | 129 | if (!sdata->u.mesh.rmc) |
121 | return -ENOMEM; | 130 | return -ENOMEM; |
122 | sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; | 131 | sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1; |
123 | for (i = 0; i < RMC_BUCKETS; i++) | 132 | for (i = 0; i < RMC_BUCKETS; i++) |
124 | INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); | 133 | INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list); |
125 | return 0; | 134 | return 0; |
126 | } | 135 | } |
127 | 136 | ||
128 | void mesh_rmc_free(struct net_device *dev) | 137 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) |
129 | { | 138 | { |
130 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 139 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
131 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | ||
132 | struct rmc_entry *p, *n; | 140 | struct rmc_entry *p, *n; |
133 | int i; | 141 | int i; |
134 | 142 | ||
135 | if (!sdata->u.sta.rmc) | 143 | if (!sdata->u.mesh.rmc) |
136 | return; | 144 | return; |
137 | 145 | ||
138 | for (i = 0; i < RMC_BUCKETS; i++) | 146 | for (i = 0; i < RMC_BUCKETS; i++) |
@@ -142,7 +150,7 @@ void mesh_rmc_free(struct net_device *dev) | |||
142 | } | 150 | } |
143 | 151 | ||
144 | kfree(rmc); | 152 | kfree(rmc); |
145 | sdata->u.sta.rmc = NULL; | 153 | sdata->u.mesh.rmc = NULL; |
146 | } | 154 | } |
147 | 155 | ||
148 | /** | 156 | /** |
@@ -158,10 +166,9 @@ void mesh_rmc_free(struct net_device *dev) | |||
158 | * it. | 166 | * it. |
159 | */ | 167 | */ |
160 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | 168 | int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, |
161 | struct net_device *dev) | 169 | struct ieee80211_sub_if_data *sdata) |
162 | { | 170 | { |
163 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 171 | struct mesh_rmc *rmc = sdata->u.mesh.rmc; |
164 | struct mesh_rmc *rmc = sdata->u.sta.rmc; | ||
165 | u32 seqnum = 0; | 172 | u32 seqnum = 0; |
166 | int entries = 0; | 173 | int entries = 0; |
167 | u8 idx; | 174 | u8 idx; |
@@ -194,10 +201,9 @@ int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, | |||
194 | return 0; | 201 | return 0; |
195 | } | 202 | } |
196 | 203 | ||
197 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | 204 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) |
198 | { | 205 | { |
199 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 206 | struct ieee80211_local *local = sdata->local; |
200 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
201 | struct ieee80211_supported_band *sband; | 207 | struct ieee80211_supported_band *sband; |
202 | u8 *pos; | 208 | u8 *pos; |
203 | int len, i, rate; | 209 | int len, i, rate; |
@@ -224,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
224 | } | 230 | } |
225 | } | 231 | } |
226 | 232 | ||
227 | pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); | 233 | pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len); |
228 | *pos++ = WLAN_EID_MESH_ID; | 234 | *pos++ = WLAN_EID_MESH_ID; |
229 | *pos++ = sdata->u.sta.mesh_id_len; | 235 | *pos++ = sdata->u.mesh.mesh_id_len; |
230 | if (sdata->u.sta.mesh_id_len) | 236 | if (sdata->u.mesh.mesh_id_len) |
231 | memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); | 237 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
232 | 238 | ||
233 | pos = skb_put(skb, 21); | 239 | pos = skb_put(skb, 21); |
234 | *pos++ = WLAN_EID_MESH_CONFIG; | 240 | *pos++ = WLAN_EID_MESH_CONFIG; |
@@ -237,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
237 | *pos++ = 1; | 243 | *pos++ = 1; |
238 | 244 | ||
239 | /* Active path selection protocol ID */ | 245 | /* Active path selection protocol ID */ |
240 | memcpy(pos, sdata->u.sta.mesh_pp_id, 4); | 246 | memcpy(pos, sdata->u.mesh.mesh_pp_id, 4); |
241 | pos += 4; | 247 | pos += 4; |
242 | 248 | ||
243 | /* Active path selection metric ID */ | 249 | /* Active path selection metric ID */ |
244 | memcpy(pos, sdata->u.sta.mesh_pm_id, 4); | 250 | memcpy(pos, sdata->u.mesh.mesh_pm_id, 4); |
245 | pos += 4; | 251 | pos += 4; |
246 | 252 | ||
247 | /* Congestion control mode identifier */ | 253 | /* Congestion control mode identifier */ |
248 | memcpy(pos, sdata->u.sta.mesh_cc_id, 4); | 254 | memcpy(pos, sdata->u.mesh.mesh_cc_id, 4); |
249 | pos += 4; | 255 | pos += 4; |
250 | 256 | ||
251 | /* Channel precedence: | 257 | /* Channel precedence: |
@@ -255,17 +261,17 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev) | |||
255 | pos += 4; | 261 | pos += 4; |
256 | 262 | ||
257 | /* Mesh capability */ | 263 | /* Mesh capability */ |
258 | sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); | 264 | sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata); |
259 | *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; | 265 | *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00; |
260 | *pos++ = 0x00; | 266 | *pos++ = 0x00; |
261 | 267 | ||
262 | return; | 268 | return; |
263 | } | 269 | } |
264 | 270 | ||
265 | u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl) | 271 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) |
266 | { | 272 | { |
267 | /* Use last four bytes of hw addr and interface index as hash index */ | 273 | /* Use last four bytes of hw addr and interface index as hash index */ |
268 | return jhash_2words(*(u32 *)(addr+2), dev->ifindex, tbl->hash_rnd) | 274 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) |
269 | & tbl->hash_mask; | 275 | & tbl->hash_mask; |
270 | } | 276 | } |
271 | 277 | ||
@@ -344,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data) | |||
344 | { | 350 | { |
345 | struct ieee80211_sub_if_data *sdata = | 351 | struct ieee80211_sub_if_data *sdata = |
346 | (struct ieee80211_sub_if_data *) data; | 352 | (struct ieee80211_sub_if_data *) data; |
347 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 353 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
348 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 354 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); |
349 | 355 | ||
350 | queue_work(local->hw.workqueue, &ifsta->work); | 356 | queue_work(local->hw.workqueue, &ifmsh->work); |
351 | } | 357 | } |
352 | 358 | ||
353 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) | 359 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl) |
@@ -399,50 +405,264 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
399 | struct ieee80211_sub_if_data *sdata) | 405 | struct ieee80211_sub_if_data *sdata) |
400 | { | 406 | { |
401 | meshhdr->flags = 0; | 407 | meshhdr->flags = 0; |
402 | meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 408 | meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
403 | put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); | 409 | put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); |
404 | sdata->u.sta.mesh_seqnum++; | 410 | sdata->u.mesh.mesh_seqnum++; |
405 | 411 | ||
406 | return 6; | 412 | return 6; |
407 | } | 413 | } |
408 | 414 | ||
415 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | ||
416 | struct ieee80211_if_mesh *ifmsh) | ||
417 | { | ||
418 | bool free_plinks; | ||
419 | |||
420 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
421 | printk(KERN_DEBUG "%s: running mesh housekeeping\n", | ||
422 | sdata->dev->name); | ||
423 | #endif | ||
424 | |||
425 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | ||
426 | mesh_path_expire(sdata); | ||
427 | |||
428 | free_plinks = mesh_plink_availables(sdata); | ||
429 | if (free_plinks != sdata->u.mesh.accepting_plinks) | ||
430 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
431 | |||
432 | ifmsh->housekeeping = false; | ||
433 | mod_timer(&ifmsh->housekeeping_timer, | ||
434 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | ||
435 | } | ||
436 | |||
437 | |||
438 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | ||
439 | { | ||
440 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
441 | struct ieee80211_local *local = sdata->local; | ||
442 | |||
443 | ifmsh->housekeeping = true; | ||
444 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
445 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
446 | } | ||
447 | |||
448 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | ||
449 | { | ||
450 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | ||
451 | /* | ||
452 | * If the timer fired while we waited for it, it will have | ||
453 | * requeued the work. Now the work will be running again | ||
454 | * but will not rearm the timer again because it checks | ||
455 | * whether the interface is running, which, at this point, | ||
456 | * it no longer is. | ||
457 | */ | ||
458 | cancel_work_sync(&sdata->u.mesh.work); | ||
459 | |||
460 | /* | ||
461 | * When we get here, the interface is marked down. | ||
462 | * Call synchronize_rcu() to wait for the RX path | ||
463 | * should it be using the interface and enqueuing | ||
464 | * frames at this very time on another CPU. | ||
465 | */ | ||
466 | synchronize_rcu(); | ||
467 | skb_queue_purge(&sdata->u.mesh.skb_queue); | ||
468 | } | ||
469 | |||
470 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||
471 | u16 stype, | ||
472 | struct ieee80211_mgmt *mgmt, | ||
473 | size_t len, | ||
474 | struct ieee80211_rx_status *rx_status) | ||
475 | { | ||
476 | struct ieee80211_local *local= sdata->local; | ||
477 | struct ieee802_11_elems elems; | ||
478 | struct ieee80211_channel *channel; | ||
479 | u64 supp_rates = 0; | ||
480 | size_t baselen; | ||
481 | int freq; | ||
482 | enum ieee80211_band band = rx_status->band; | ||
483 | |||
484 | /* ignore ProbeResp to foreign address */ | ||
485 | if (stype == IEEE80211_STYPE_PROBE_RESP && | ||
486 | compare_ether_addr(mgmt->da, sdata->dev->dev_addr)) | ||
487 | return; | ||
488 | |||
489 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
490 | if (baselen > len) | ||
491 | return; | ||
492 | |||
493 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | ||
494 | &elems); | ||
495 | |||
496 | if (elems.ds_params && elems.ds_params_len == 1) | ||
497 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | ||
498 | else | ||
499 | freq = rx_status->freq; | ||
500 | |||
501 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
502 | |||
503 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
504 | return; | ||
505 | |||
506 | if (elems.mesh_id && elems.mesh_config && | ||
507 | mesh_matches_local(&elems, sdata)) { | ||
508 | supp_rates = ieee80211_sta_get_rates(local, &elems, band); | ||
509 | |||
510 | mesh_neighbour_update(mgmt->sa, supp_rates, sdata, | ||
511 | mesh_peer_accepts_plinks(&elems)); | ||
512 | } | ||
513 | } | ||
514 | |||
515 | static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | ||
516 | struct ieee80211_mgmt *mgmt, | ||
517 | size_t len, | ||
518 | struct ieee80211_rx_status *rx_status) | ||
519 | { | ||
520 | switch (mgmt->u.action.category) { | ||
521 | case PLINK_CATEGORY: | ||
522 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | ||
523 | break; | ||
524 | case MESH_PATH_SEL_CATEGORY: | ||
525 | mesh_rx_path_sel_frame(sdata, mgmt, len); | ||
526 | break; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | ||
531 | struct sk_buff *skb) | ||
532 | { | ||
533 | struct ieee80211_rx_status *rx_status; | ||
534 | struct ieee80211_if_mesh *ifmsh; | ||
535 | struct ieee80211_mgmt *mgmt; | ||
536 | u16 stype; | ||
537 | |||
538 | ifmsh = &sdata->u.mesh; | ||
539 | |||
540 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
541 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
542 | stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; | ||
543 | |||
544 | switch (stype) { | ||
545 | case IEEE80211_STYPE_PROBE_RESP: | ||
546 | case IEEE80211_STYPE_BEACON: | ||
547 | ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len, | ||
548 | rx_status); | ||
549 | break; | ||
550 | case IEEE80211_STYPE_ACTION: | ||
551 | ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status); | ||
552 | break; | ||
553 | } | ||
554 | |||
555 | kfree_skb(skb); | ||
556 | } | ||
557 | |||
558 | static void ieee80211_mesh_work(struct work_struct *work) | ||
559 | { | ||
560 | struct ieee80211_sub_if_data *sdata = | ||
561 | container_of(work, struct ieee80211_sub_if_data, u.mesh.work); | ||
562 | struct ieee80211_local *local = sdata->local; | ||
563 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
564 | struct sk_buff *skb; | ||
565 | |||
566 | if (!netif_running(sdata->dev)) | ||
567 | return; | ||
568 | |||
569 | if (local->sw_scanning || local->hw_scanning) | ||
570 | return; | ||
571 | |||
572 | while ((skb = skb_dequeue(&ifmsh->skb_queue))) | ||
573 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); | ||
574 | |||
575 | if (ifmsh->preq_queue_len && | ||
576 | time_after(jiffies, | ||
577 | ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
578 | mesh_path_start_discovery(sdata); | ||
579 | |||
580 | if (ifmsh->housekeeping) | ||
581 | ieee80211_mesh_housekeeping(sdata, ifmsh); | ||
582 | } | ||
583 | |||
584 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) | ||
585 | { | ||
586 | struct ieee80211_sub_if_data *sdata; | ||
587 | |||
588 | rcu_read_lock(); | ||
589 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
590 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
591 | queue_work(local->hw.workqueue, &sdata->u.mesh.work); | ||
592 | rcu_read_unlock(); | ||
593 | } | ||
594 | |||
409 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | 595 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) |
410 | { | 596 | { |
411 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 597 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
412 | 598 | ||
413 | ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; | 599 | INIT_WORK(&ifmsh->work, ieee80211_mesh_work); |
414 | ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | 600 | setup_timer(&ifmsh->housekeeping_timer, |
415 | ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | 601 | ieee80211_mesh_housekeeping_timer, |
416 | ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | 602 | (unsigned long) sdata); |
417 | ifsta->mshcfg.dot11MeshTTL = MESH_TTL; | 603 | skb_queue_head_init(&sdata->u.mesh.skb_queue); |
418 | ifsta->mshcfg.auto_open_plinks = true; | 604 | |
419 | ifsta->mshcfg.dot11MeshMaxPeerLinks = | 605 | ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; |
606 | ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; | ||
607 | ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; | ||
608 | ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; | ||
609 | ifmsh->mshcfg.dot11MeshTTL = MESH_TTL; | ||
610 | ifmsh->mshcfg.auto_open_plinks = true; | ||
611 | ifmsh->mshcfg.dot11MeshMaxPeerLinks = | ||
420 | MESH_MAX_ESTAB_PLINKS; | 612 | MESH_MAX_ESTAB_PLINKS; |
421 | ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = | 613 | ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout = |
422 | MESH_PATH_TIMEOUT; | 614 | MESH_PATH_TIMEOUT; |
423 | ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = | 615 | ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval = |
424 | MESH_PREQ_MIN_INT; | 616 | MESH_PREQ_MIN_INT; |
425 | ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = | 617 | ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = |
426 | MESH_DIAM_TRAVERSAL_TIME; | 618 | MESH_DIAM_TRAVERSAL_TIME; |
427 | ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = | 619 | ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries = |
428 | MESH_MAX_PREQ_RETRIES; | 620 | MESH_MAX_PREQ_RETRIES; |
429 | ifsta->mshcfg.path_refresh_time = | 621 | ifmsh->mshcfg.path_refresh_time = |
430 | MESH_PATH_REFRESH_TIME; | 622 | MESH_PATH_REFRESH_TIME; |
431 | ifsta->mshcfg.min_discovery_timeout = | 623 | ifmsh->mshcfg.min_discovery_timeout = |
432 | MESH_MIN_DISCOVERY_TIMEOUT; | 624 | MESH_MIN_DISCOVERY_TIMEOUT; |
433 | ifsta->accepting_plinks = true; | 625 | ifmsh->accepting_plinks = true; |
434 | ifsta->preq_id = 0; | 626 | ifmsh->preq_id = 0; |
435 | ifsta->dsn = 0; | 627 | ifmsh->dsn = 0; |
436 | atomic_set(&ifsta->mpaths, 0); | 628 | atomic_set(&ifmsh->mpaths, 0); |
437 | mesh_rmc_init(sdata->dev); | 629 | mesh_rmc_init(sdata); |
438 | ifsta->last_preq = jiffies; | 630 | ifmsh->last_preq = jiffies; |
439 | /* Allocate all mesh structures when creating the first mesh interface. */ | 631 | /* Allocate all mesh structures when creating the first mesh interface. */ |
440 | if (!mesh_allocated) | 632 | if (!mesh_allocated) |
441 | ieee80211s_init(); | 633 | ieee80211s_init(); |
442 | mesh_ids_set_default(ifsta); | 634 | mesh_ids_set_default(ifmsh); |
443 | setup_timer(&ifsta->mesh_path_timer, | 635 | setup_timer(&ifmsh->mesh_path_timer, |
444 | ieee80211_mesh_path_timer, | 636 | ieee80211_mesh_path_timer, |
445 | (unsigned long) sdata); | 637 | (unsigned long) sdata); |
446 | INIT_LIST_HEAD(&ifsta->preq_queue.list); | 638 | INIT_LIST_HEAD(&ifmsh->preq_queue.list); |
447 | spin_lock_init(&ifsta->mesh_preq_queue_lock); | 639 | spin_lock_init(&ifmsh->mesh_preq_queue_lock); |
640 | } | ||
641 | |||
642 | ieee80211_rx_result | ||
643 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
644 | struct ieee80211_rx_status *rx_status) | ||
645 | { | ||
646 | struct ieee80211_local *local = sdata->local; | ||
647 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||
648 | struct ieee80211_mgmt *mgmt; | ||
649 | u16 fc; | ||
650 | |||
651 | if (skb->len < 24) | ||
652 | return RX_DROP_MONITOR; | ||
653 | |||
654 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
655 | fc = le16_to_cpu(mgmt->frame_control); | ||
656 | |||
657 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
658 | case IEEE80211_STYPE_PROBE_RESP: | ||
659 | case IEEE80211_STYPE_BEACON: | ||
660 | case IEEE80211_STYPE_ACTION: | ||
661 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | ||
662 | skb_queue_tail(&ifmsh->skb_queue, skb); | ||
663 | queue_work(local->hw.workqueue, &ifmsh->work); | ||
664 | return RX_QUEUED; | ||
665 | } | ||
666 | |||
667 | return RX_CONTINUE; | ||
448 | } | 668 | } |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 7495fbb0d211..8ee414a0447c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -47,7 +47,7 @@ enum mesh_path_flags { | |||
47 | * struct mesh_path - mac80211 mesh path structure | 47 | * struct mesh_path - mac80211 mesh path structure |
48 | * | 48 | * |
49 | * @dst: mesh path destination mac address | 49 | * @dst: mesh path destination mac address |
50 | * @dev: mesh path device | 50 | * @sdata: mesh subif |
51 | * @next_hop: mesh neighbor to which frames for this destination will be | 51 | * @next_hop: mesh neighbor to which frames for this destination will be |
52 | * forwarded | 52 | * forwarded |
53 | * @timer: mesh path discovery timer | 53 | * @timer: mesh path discovery timer |
@@ -64,14 +64,14 @@ enum mesh_path_flags { | |||
64 | * @state_lock: mesh pat state lock | 64 | * @state_lock: mesh pat state lock |
65 | * | 65 | * |
66 | * | 66 | * |
67 | * The combination of dst and dev is unique in the mesh path table. Since the | 67 | * The combination of dst and sdata is unique in the mesh path table. Since the |
68 | * next_hop STA is only protected by RCU as well, deleting the STA must also | 68 | * next_hop STA is only protected by RCU as well, deleting the STA must also |
69 | * remove/substitute the mesh_path structure and wait until that is no longer | 69 | * remove/substitute the mesh_path structure and wait until that is no longer |
70 | * reachable before destroying the STA completely. | 70 | * reachable before destroying the STA completely. |
71 | */ | 71 | */ |
72 | struct mesh_path { | 72 | struct mesh_path { |
73 | u8 dst[ETH_ALEN]; | 73 | u8 dst[ETH_ALEN]; |
74 | struct net_device *dev; | 74 | struct ieee80211_sub_if_data *sdata; |
75 | struct sta_info *next_hop; | 75 | struct sta_info *next_hop; |
76 | struct timer_list timer; | 76 | struct timer_list timer; |
77 | struct sk_buff_head frame_queue; | 77 | struct sk_buff_head frame_queue; |
@@ -203,67 +203,79 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | |||
203 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 203 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
204 | struct ieee80211_sub_if_data *sdata); | 204 | struct ieee80211_sub_if_data *sdata); |
205 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, | 205 | int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, |
206 | struct net_device *dev); | 206 | struct ieee80211_sub_if_data *sdata); |
207 | bool mesh_matches_local(struct ieee802_11_elems *ie, struct net_device *dev); | 207 | bool mesh_matches_local(struct ieee802_11_elems *ie, |
208 | void mesh_ids_set_default(struct ieee80211_if_sta *sta); | 208 | struct ieee80211_sub_if_data *sdata); |
209 | void mesh_mgmt_ies_add(struct sk_buff *skb, struct net_device *dev); | 209 | void mesh_ids_set_default(struct ieee80211_if_mesh *mesh); |
210 | void mesh_rmc_free(struct net_device *dev); | 210 | void mesh_mgmt_ies_add(struct sk_buff *skb, |
211 | int mesh_rmc_init(struct net_device *dev); | 211 | struct ieee80211_sub_if_data *sdata); |
212 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | ||
213 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | ||
212 | void ieee80211s_init(void); | 214 | void ieee80211s_init(void); |
213 | void ieee80211s_stop(void); | 215 | void ieee80211s_stop(void); |
214 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 216 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
217 | ieee80211_rx_result | ||
218 | ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
219 | struct ieee80211_rx_status *rx_status); | ||
220 | void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata); | ||
221 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata); | ||
215 | 222 | ||
216 | /* Mesh paths */ | 223 | /* Mesh paths */ |
217 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev); | 224 | int mesh_nexthop_lookup(struct sk_buff *skb, |
218 | void mesh_path_start_discovery(struct net_device *dev); | 225 | struct ieee80211_sub_if_data *sdata); |
219 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev); | 226 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata); |
220 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev); | 227 | struct mesh_path *mesh_path_lookup(u8 *dst, |
228 | struct ieee80211_sub_if_data *sdata); | ||
229 | struct mesh_path *mesh_path_lookup_by_idx(int idx, | ||
230 | struct ieee80211_sub_if_data *sdata); | ||
221 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); | 231 | void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop); |
222 | void mesh_path_expire(struct net_device *dev); | 232 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata); |
223 | void mesh_path_flush(struct net_device *dev); | 233 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata); |
224 | void mesh_rx_path_sel_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 234 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
225 | size_t len); | 235 | struct ieee80211_mgmt *mgmt, size_t len); |
226 | int mesh_path_add(u8 *dst, struct net_device *dev); | 236 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata); |
227 | /* Mesh plinks */ | 237 | /* Mesh plinks */ |
228 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | 238 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, |
229 | bool add); | 239 | struct ieee80211_sub_if_data *sdata, bool add); |
230 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie, | 240 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
231 | struct net_device *dev); | ||
232 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 241 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
233 | void mesh_plink_broken(struct sta_info *sta); | 242 | void mesh_plink_broken(struct sta_info *sta); |
234 | void mesh_plink_deactivate(struct sta_info *sta); | 243 | void mesh_plink_deactivate(struct sta_info *sta); |
235 | int mesh_plink_open(struct sta_info *sta); | 244 | int mesh_plink_open(struct sta_info *sta); |
236 | int mesh_plink_close(struct sta_info *sta); | 245 | int mesh_plink_close(struct sta_info *sta); |
237 | void mesh_plink_block(struct sta_info *sta); | 246 | void mesh_plink_block(struct sta_info *sta); |
238 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 247 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, |
239 | size_t len, struct ieee80211_rx_status *rx_status); | 248 | struct ieee80211_mgmt *mgmt, size_t len, |
249 | struct ieee80211_rx_status *rx_status); | ||
240 | 250 | ||
241 | /* Private interfaces */ | 251 | /* Private interfaces */ |
242 | /* Mesh tables */ | 252 | /* Mesh tables */ |
243 | struct mesh_table *mesh_table_alloc(int size_order); | 253 | struct mesh_table *mesh_table_alloc(int size_order); |
244 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs); | 254 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs); |
245 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl); | 255 | struct mesh_table *mesh_table_grow(struct mesh_table *tbl); |
246 | u32 mesh_table_hash(u8 *addr, struct net_device *dev, struct mesh_table *tbl); | 256 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, |
257 | struct mesh_table *tbl); | ||
247 | /* Mesh paths */ | 258 | /* Mesh paths */ |
248 | int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, | 259 | int mesh_path_error_tx(u8 *dest, __le32 dest_dsn, u8 *ra, |
249 | struct net_device *dev); | 260 | struct ieee80211_sub_if_data *sdata); |
250 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 261 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
251 | void mesh_path_flush_pending(struct mesh_path *mpath); | 262 | void mesh_path_flush_pending(struct mesh_path *mpath); |
252 | void mesh_path_tx_pending(struct mesh_path *mpath); | 263 | void mesh_path_tx_pending(struct mesh_path *mpath); |
253 | int mesh_pathtbl_init(void); | 264 | int mesh_pathtbl_init(void); |
254 | void mesh_pathtbl_unregister(void); | 265 | void mesh_pathtbl_unregister(void); |
255 | int mesh_path_del(u8 *addr, struct net_device *dev); | 266 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata); |
256 | void mesh_path_timer(unsigned long data); | 267 | void mesh_path_timer(unsigned long data); |
257 | void mesh_path_flush_by_nexthop(struct sta_info *sta); | 268 | void mesh_path_flush_by_nexthop(struct sta_info *sta); |
258 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev); | 269 | void mesh_path_discard_frame(struct sk_buff *skb, |
270 | struct ieee80211_sub_if_data *sdata); | ||
259 | 271 | ||
260 | #ifdef CONFIG_MAC80211_MESH | 272 | #ifdef CONFIG_MAC80211_MESH |
261 | extern int mesh_allocated; | 273 | extern int mesh_allocated; |
262 | 274 | ||
263 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) | 275 | static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) |
264 | { | 276 | { |
265 | return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - | 277 | return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks - |
266 | atomic_read(&sdata->u.sta.mshstats.estab_plinks); | 278 | atomic_read(&sdata->u.mesh.mshstats.estab_plinks); |
267 | } | 279 | } |
268 | 280 | ||
269 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) | 281 | static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) |
@@ -281,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath) | |||
281 | for (i = 0; i <= x->hash_mask; i++) \ | 293 | for (i = 0; i <= x->hash_mask; i++) \ |
282 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) | 294 | hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) |
283 | 295 | ||
296 | void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); | ||
297 | |||
284 | #else | 298 | #else |
285 | #define mesh_allocated 0 | 299 | #define mesh_allocated 0 |
300 | static inline void | ||
301 | ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} | ||
286 | #endif | 302 | #endif |
287 | 303 | ||
288 | #endif /* IEEE80211S_H */ | 304 | #endif /* IEEE80211S_H */ |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 08aca446ca01..501c7831adb4 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae) | |||
64 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) | 64 | #define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) |
65 | 65 | ||
66 | #define net_traversal_jiffies(s) \ | 66 | #define net_traversal_jiffies(s) \ |
67 | msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) | 67 | msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) |
68 | #define default_lifetime(s) \ | 68 | #define default_lifetime(s) \ |
69 | MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) | 69 | MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout) |
70 | #define min_preq_int_jiff(s) \ | 70 | #define min_preq_int_jiff(s) \ |
71 | (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) | 71 | (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval)) |
72 | #define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) | 72 | #define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries) |
73 | #define disc_timeout_jiff(s) \ | 73 | #define disc_timeout_jiff(s) \ |
74 | msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) | 74 | msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout) |
75 | 75 | ||
76 | enum mpath_frame_type { | 76 | enum mpath_frame_type { |
77 | MPATH_PREQ = 0, | 77 | MPATH_PREQ = 0, |
@@ -82,9 +82,9 @@ enum mpath_frame_type { | |||
82 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | 82 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, |
83 | u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, | 83 | u8 *orig_addr, __le32 orig_dsn, u8 dst_flags, u8 *dst, |
84 | __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, | 84 | __le32 dst_dsn, u8 *da, u8 hop_count, u8 ttl, __le32 lifetime, |
85 | __le32 metric, __le32 preq_id, struct net_device *dev) | 85 | __le32 metric, __le32 preq_id, struct ieee80211_sub_if_data *sdata) |
86 | { | 86 | { |
87 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 87 | struct ieee80211_local *local = sdata->local; |
88 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 88 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
89 | struct ieee80211_mgmt *mgmt; | 89 | struct ieee80211_mgmt *mgmt; |
90 | u8 *pos; | 90 | u8 *pos; |
@@ -99,11 +99,11 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
99 | mgmt = (struct ieee80211_mgmt *) | 99 | mgmt = (struct ieee80211_mgmt *) |
100 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 100 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
101 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 101 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
102 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 102 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
103 | IEEE80211_STYPE_ACTION); | 103 | IEEE80211_STYPE_ACTION); |
104 | 104 | ||
105 | memcpy(mgmt->da, da, ETH_ALEN); | 105 | memcpy(mgmt->da, da, ETH_ALEN); |
106 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 106 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
107 | /* BSSID is left zeroed, wildcard value */ | 107 | /* BSSID is left zeroed, wildcard value */ |
108 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 108 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
109 | mgmt->u.action.u.mesh_action.action_code = action; | 109 | mgmt->u.action.u.mesh_action.action_code = action; |
@@ -149,7 +149,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
149 | pos += ETH_ALEN; | 149 | pos += ETH_ALEN; |
150 | memcpy(pos, &dst_dsn, 4); | 150 | memcpy(pos, &dst_dsn, 4); |
151 | 151 | ||
152 | ieee80211_sta_tx(dev, skb, 0); | 152 | ieee80211_tx_skb(sdata, skb, 0); |
153 | return 0; | 153 | return 0; |
154 | } | 154 | } |
155 | 155 | ||
@@ -161,9 +161,9 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
161 | * @ra: node this frame is addressed to | 161 | * @ra: node this frame is addressed to |
162 | */ | 162 | */ |
163 | int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | 163 | int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, |
164 | struct net_device *dev) | 164 | struct ieee80211_sub_if_data *sdata) |
165 | { | 165 | { |
166 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 166 | struct ieee80211_local *local = sdata->local; |
167 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 167 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
168 | struct ieee80211_mgmt *mgmt; | 168 | struct ieee80211_mgmt *mgmt; |
169 | u8 *pos; | 169 | u8 *pos; |
@@ -178,11 +178,11 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
178 | mgmt = (struct ieee80211_mgmt *) | 178 | mgmt = (struct ieee80211_mgmt *) |
179 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 179 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
180 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); | 180 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.mesh_action)); |
181 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 181 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
182 | IEEE80211_STYPE_ACTION); | 182 | IEEE80211_STYPE_ACTION); |
183 | 183 | ||
184 | memcpy(mgmt->da, ra, ETH_ALEN); | 184 | memcpy(mgmt->da, ra, ETH_ALEN); |
185 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 185 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
186 | /* BSSID is left zeroed, wildcard value */ | 186 | /* BSSID is left zeroed, wildcard value */ |
187 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; | 187 | mgmt->u.action.category = MESH_PATH_SEL_CATEGORY; |
188 | mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; | 188 | mgmt->u.action.u.mesh_action.action_code = MPATH_PERR; |
@@ -198,7 +198,7 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
198 | pos += ETH_ALEN; | 198 | pos += ETH_ALEN; |
199 | memcpy(pos, &dst_dsn, 4); | 199 | memcpy(pos, &dst_dsn, 4); |
200 | 200 | ||
201 | ieee80211_sta_tx(dev, skb, 0); | 201 | ieee80211_tx_skb(sdata, skb, 0); |
202 | return 0; | 202 | return 0; |
203 | } | 203 | } |
204 | 204 | ||
@@ -223,7 +223,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
223 | /* bitrate is in units of 100 Kbps, while we need rate in units of | 223 | /* bitrate is in units of 100 Kbps, while we need rate in units of |
224 | * 1Mbps. This will be corrected on tx_time computation. | 224 | * 1Mbps. This will be corrected on tx_time computation. |
225 | */ | 225 | */ |
226 | rate = sband->bitrates[sta->txrate_idx].bitrate; | 226 | rate = sband->bitrates[sta->last_txrate_idx].bitrate; |
227 | tx_time = (device_constant + 10 * test_frame_len / rate); | 227 | tx_time = (device_constant + 10 * test_frame_len / rate); |
228 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); | 228 | estimated_retx = ((1 << (2 * ARITH_SHIFT)) / (s_unit - err)); |
229 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; | 229 | result = (tx_time * estimated_retx) >> (2 * ARITH_SHIFT) ; |
@@ -233,7 +233,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
233 | /** | 233 | /** |
234 | * hwmp_route_info_get - Update routing info to originator and transmitter | 234 | * hwmp_route_info_get - Update routing info to originator and transmitter |
235 | * | 235 | * |
236 | * @dev: local mesh interface | 236 | * @sdata: local mesh subif |
237 | * @mgmt: mesh management frame | 237 | * @mgmt: mesh management frame |
238 | * @hwmp_ie: hwmp information element (PREP or PREQ) | 238 | * @hwmp_ie: hwmp information element (PREP or PREQ) |
239 | * | 239 | * |
@@ -246,11 +246,11 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, | |||
246 | * Notes: this function is the only place (besides user-provided info) where | 246 | * Notes: this function is the only place (besides user-provided info) where |
247 | * path routing information is updated. | 247 | * path routing information is updated. |
248 | */ | 248 | */ |
249 | static u32 hwmp_route_info_get(struct net_device *dev, | 249 | static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, |
250 | struct ieee80211_mgmt *mgmt, | 250 | struct ieee80211_mgmt *mgmt, |
251 | u8 *hwmp_ie) | 251 | u8 *hwmp_ie) |
252 | { | 252 | { |
253 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 253 | struct ieee80211_local *local = sdata->local; |
254 | struct mesh_path *mpath; | 254 | struct mesh_path *mpath; |
255 | struct sta_info *sta; | 255 | struct sta_info *sta; |
256 | bool fresh_info; | 256 | bool fresh_info; |
@@ -301,14 +301,14 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
301 | new_metric = MAX_METRIC; | 301 | new_metric = MAX_METRIC; |
302 | exp_time = TU_TO_EXP_TIME(orig_lifetime); | 302 | exp_time = TU_TO_EXP_TIME(orig_lifetime); |
303 | 303 | ||
304 | if (memcmp(orig_addr, dev->dev_addr, ETH_ALEN) == 0) { | 304 | if (memcmp(orig_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { |
305 | /* This MP is the originator, we are not interested in this | 305 | /* This MP is the originator, we are not interested in this |
306 | * frame, except for updating transmitter's path info. | 306 | * frame, except for updating transmitter's path info. |
307 | */ | 307 | */ |
308 | process = false; | 308 | process = false; |
309 | fresh_info = false; | 309 | fresh_info = false; |
310 | } else { | 310 | } else { |
311 | mpath = mesh_path_lookup(orig_addr, dev); | 311 | mpath = mesh_path_lookup(orig_addr, sdata); |
312 | if (mpath) { | 312 | if (mpath) { |
313 | spin_lock_bh(&mpath->state_lock); | 313 | spin_lock_bh(&mpath->state_lock); |
314 | if (mpath->flags & MESH_PATH_FIXED) | 314 | if (mpath->flags & MESH_PATH_FIXED) |
@@ -324,8 +324,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
324 | } | 324 | } |
325 | } | 325 | } |
326 | } else { | 326 | } else { |
327 | mesh_path_add(orig_addr, dev); | 327 | mesh_path_add(orig_addr, sdata); |
328 | mpath = mesh_path_lookup(orig_addr, dev); | 328 | mpath = mesh_path_lookup(orig_addr, sdata); |
329 | if (!mpath) { | 329 | if (!mpath) { |
330 | rcu_read_unlock(); | 330 | rcu_read_unlock(); |
331 | return 0; | 331 | return 0; |
@@ -357,7 +357,7 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
357 | else { | 357 | else { |
358 | fresh_info = true; | 358 | fresh_info = true; |
359 | 359 | ||
360 | mpath = mesh_path_lookup(ta, dev); | 360 | mpath = mesh_path_lookup(ta, sdata); |
361 | if (mpath) { | 361 | if (mpath) { |
362 | spin_lock_bh(&mpath->state_lock); | 362 | spin_lock_bh(&mpath->state_lock); |
363 | if ((mpath->flags & MESH_PATH_FIXED) || | 363 | if ((mpath->flags & MESH_PATH_FIXED) || |
@@ -365,8 +365,8 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
365 | (last_hop_metric > mpath->metric))) | 365 | (last_hop_metric > mpath->metric))) |
366 | fresh_info = false; | 366 | fresh_info = false; |
367 | } else { | 367 | } else { |
368 | mesh_path_add(ta, dev); | 368 | mesh_path_add(ta, sdata); |
369 | mpath = mesh_path_lookup(ta, dev); | 369 | mpath = mesh_path_lookup(ta, sdata); |
370 | if (!mpath) { | 370 | if (!mpath) { |
371 | rcu_read_unlock(); | 371 | rcu_read_unlock(); |
372 | return 0; | 372 | return 0; |
@@ -392,11 +392,10 @@ static u32 hwmp_route_info_get(struct net_device *dev, | |||
392 | return process ? new_metric : 0; | 392 | return process ? new_metric : 0; |
393 | } | 393 | } |
394 | 394 | ||
395 | static void hwmp_preq_frame_process(struct net_device *dev, | 395 | static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, |
396 | struct ieee80211_mgmt *mgmt, | 396 | struct ieee80211_mgmt *mgmt, |
397 | u8 *preq_elem, u32 metric) { | 397 | u8 *preq_elem, u32 metric) { |
398 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 398 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
399 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
400 | struct mesh_path *mpath; | 399 | struct mesh_path *mpath; |
401 | u8 *dst_addr, *orig_addr; | 400 | u8 *dst_addr, *orig_addr; |
402 | u8 dst_flags, ttl; | 401 | u8 dst_flags, ttl; |
@@ -411,19 +410,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
411 | orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); | 410 | orig_dsn = PREQ_IE_ORIG_DSN(preq_elem); |
412 | dst_flags = PREQ_IE_DST_F(preq_elem); | 411 | dst_flags = PREQ_IE_DST_F(preq_elem); |
413 | 412 | ||
414 | if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) { | 413 | if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) { |
415 | forward = false; | 414 | forward = false; |
416 | reply = true; | 415 | reply = true; |
417 | metric = 0; | 416 | metric = 0; |
418 | if (time_after(jiffies, ifsta->last_dsn_update + | 417 | if (time_after(jiffies, ifmsh->last_dsn_update + |
419 | net_traversal_jiffies(sdata)) || | 418 | net_traversal_jiffies(sdata)) || |
420 | time_before(jiffies, ifsta->last_dsn_update)) { | 419 | time_before(jiffies, ifmsh->last_dsn_update)) { |
421 | dst_dsn = ++ifsta->dsn; | 420 | dst_dsn = ++ifmsh->dsn; |
422 | ifsta->last_dsn_update = jiffies; | 421 | ifmsh->last_dsn_update = jiffies; |
423 | } | 422 | } |
424 | } else { | 423 | } else { |
425 | rcu_read_lock(); | 424 | rcu_read_lock(); |
426 | mpath = mesh_path_lookup(dst_addr, dev); | 425 | mpath = mesh_path_lookup(dst_addr, sdata); |
427 | if (mpath) { | 426 | if (mpath) { |
428 | if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || | 427 | if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || |
429 | DSN_LT(mpath->dsn, dst_dsn)) { | 428 | DSN_LT(mpath->dsn, dst_dsn)) { |
@@ -445,15 +444,15 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
445 | 444 | ||
446 | if (reply) { | 445 | if (reply) { |
447 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 446 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
448 | ttl = ifsta->mshcfg.dot11MeshTTL; | 447 | ttl = ifmsh->mshcfg.dot11MeshTTL; |
449 | if (ttl != 0) | 448 | if (ttl != 0) |
450 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, | 449 | mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, |
451 | cpu_to_le32(dst_dsn), 0, orig_addr, | 450 | cpu_to_le32(dst_dsn), 0, orig_addr, |
452 | cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, | 451 | cpu_to_le32(orig_dsn), mgmt->sa, 0, ttl, |
453 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 452 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
454 | 0, dev); | 453 | 0, sdata); |
455 | else | 454 | else |
456 | ifsta->mshstats.dropped_frames_ttl++; | 455 | ifmsh->mshstats.dropped_frames_ttl++; |
457 | } | 456 | } |
458 | 457 | ||
459 | if (forward) { | 458 | if (forward) { |
@@ -463,7 +462,7 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
463 | ttl = PREQ_IE_TTL(preq_elem); | 462 | ttl = PREQ_IE_TTL(preq_elem); |
464 | lifetime = PREQ_IE_LIFETIME(preq_elem); | 463 | lifetime = PREQ_IE_LIFETIME(preq_elem); |
465 | if (ttl <= 1) { | 464 | if (ttl <= 1) { |
466 | ifsta->mshstats.dropped_frames_ttl++; | 465 | ifmsh->mshstats.dropped_frames_ttl++; |
467 | return; | 466 | return; |
468 | } | 467 | } |
469 | --ttl; | 468 | --ttl; |
@@ -472,20 +471,19 @@ static void hwmp_preq_frame_process(struct net_device *dev, | |||
472 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; | 471 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; |
473 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, | 472 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, |
474 | cpu_to_le32(orig_dsn), dst_flags, dst_addr, | 473 | cpu_to_le32(orig_dsn), dst_flags, dst_addr, |
475 | cpu_to_le32(dst_dsn), dev->broadcast, | 474 | cpu_to_le32(dst_dsn), sdata->dev->broadcast, |
476 | hopcount, ttl, cpu_to_le32(lifetime), | 475 | hopcount, ttl, cpu_to_le32(lifetime), |
477 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 476 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
478 | dev); | 477 | sdata); |
479 | ifsta->mshstats.fwded_frames++; | 478 | ifmsh->mshstats.fwded_frames++; |
480 | } | 479 | } |
481 | } | 480 | } |
482 | 481 | ||
483 | 482 | ||
484 | static void hwmp_prep_frame_process(struct net_device *dev, | 483 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, |
485 | struct ieee80211_mgmt *mgmt, | 484 | struct ieee80211_mgmt *mgmt, |
486 | u8 *prep_elem, u32 metric) | 485 | u8 *prep_elem, u32 metric) |
487 | { | 486 | { |
488 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
489 | struct mesh_path *mpath; | 487 | struct mesh_path *mpath; |
490 | u8 *dst_addr, *orig_addr; | 488 | u8 *dst_addr, *orig_addr; |
491 | u8 ttl, hopcount, flags; | 489 | u8 ttl, hopcount, flags; |
@@ -499,18 +497,18 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
499 | * replies | 497 | * replies |
500 | */ | 498 | */ |
501 | dst_addr = PREP_IE_DST_ADDR(prep_elem); | 499 | dst_addr = PREP_IE_DST_ADDR(prep_elem); |
502 | if (memcmp(dst_addr, dev->dev_addr, ETH_ALEN) == 0) | 500 | if (memcmp(dst_addr, sdata->dev->dev_addr, ETH_ALEN) == 0) |
503 | /* destination, no forwarding required */ | 501 | /* destination, no forwarding required */ |
504 | return; | 502 | return; |
505 | 503 | ||
506 | ttl = PREP_IE_TTL(prep_elem); | 504 | ttl = PREP_IE_TTL(prep_elem); |
507 | if (ttl <= 1) { | 505 | if (ttl <= 1) { |
508 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 506 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
509 | return; | 507 | return; |
510 | } | 508 | } |
511 | 509 | ||
512 | rcu_read_lock(); | 510 | rcu_read_lock(); |
513 | mpath = mesh_path_lookup(dst_addr, dev); | 511 | mpath = mesh_path_lookup(dst_addr, sdata); |
514 | if (mpath) | 512 | if (mpath) |
515 | spin_lock_bh(&mpath->state_lock); | 513 | spin_lock_bh(&mpath->state_lock); |
516 | else | 514 | else |
@@ -519,7 +517,7 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
519 | spin_unlock_bh(&mpath->state_lock); | 517 | spin_unlock_bh(&mpath->state_lock); |
520 | goto fail; | 518 | goto fail; |
521 | } | 519 | } |
522 | memcpy(next_hop, mpath->next_hop->addr, ETH_ALEN); | 520 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); |
523 | spin_unlock_bh(&mpath->state_lock); | 521 | spin_unlock_bh(&mpath->state_lock); |
524 | --ttl; | 522 | --ttl; |
525 | flags = PREP_IE_FLAGS(prep_elem); | 523 | flags = PREP_IE_FLAGS(prep_elem); |
@@ -531,20 +529,20 @@ static void hwmp_prep_frame_process(struct net_device *dev, | |||
531 | 529 | ||
532 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, | 530 | mesh_path_sel_frame_tx(MPATH_PREP, flags, orig_addr, |
533 | cpu_to_le32(orig_dsn), 0, dst_addr, | 531 | cpu_to_le32(orig_dsn), 0, dst_addr, |
534 | cpu_to_le32(dst_dsn), mpath->next_hop->addr, hopcount, ttl, | 532 | cpu_to_le32(dst_dsn), mpath->next_hop->sta.addr, hopcount, ttl, |
535 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 533 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
536 | 0, dev); | 534 | 0, sdata); |
537 | rcu_read_unlock(); | 535 | rcu_read_unlock(); |
538 | sdata->u.sta.mshstats.fwded_frames++; | 536 | sdata->u.mesh.mshstats.fwded_frames++; |
539 | return; | 537 | return; |
540 | 538 | ||
541 | fail: | 539 | fail: |
542 | rcu_read_unlock(); | 540 | rcu_read_unlock(); |
543 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 541 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
544 | return; | 542 | return; |
545 | } | 543 | } |
546 | 544 | ||
547 | static void hwmp_perr_frame_process(struct net_device *dev, | 545 | static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, |
548 | struct ieee80211_mgmt *mgmt, u8 *perr_elem) | 546 | struct ieee80211_mgmt *mgmt, u8 *perr_elem) |
549 | { | 547 | { |
550 | struct mesh_path *mpath; | 548 | struct mesh_path *mpath; |
@@ -555,18 +553,18 @@ static void hwmp_perr_frame_process(struct net_device *dev, | |||
555 | dst_addr = PERR_IE_DST_ADDR(perr_elem); | 553 | dst_addr = PERR_IE_DST_ADDR(perr_elem); |
556 | dst_dsn = PERR_IE_DST_DSN(perr_elem); | 554 | dst_dsn = PERR_IE_DST_DSN(perr_elem); |
557 | rcu_read_lock(); | 555 | rcu_read_lock(); |
558 | mpath = mesh_path_lookup(dst_addr, dev); | 556 | mpath = mesh_path_lookup(dst_addr, sdata); |
559 | if (mpath) { | 557 | if (mpath) { |
560 | spin_lock_bh(&mpath->state_lock); | 558 | spin_lock_bh(&mpath->state_lock); |
561 | if (mpath->flags & MESH_PATH_ACTIVE && | 559 | if (mpath->flags & MESH_PATH_ACTIVE && |
562 | memcmp(ta, mpath->next_hop->addr, ETH_ALEN) == 0 && | 560 | memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && |
563 | (!(mpath->flags & MESH_PATH_DSN_VALID) || | 561 | (!(mpath->flags & MESH_PATH_DSN_VALID) || |
564 | DSN_GT(dst_dsn, mpath->dsn))) { | 562 | DSN_GT(dst_dsn, mpath->dsn))) { |
565 | mpath->flags &= ~MESH_PATH_ACTIVE; | 563 | mpath->flags &= ~MESH_PATH_ACTIVE; |
566 | mpath->dsn = dst_dsn; | 564 | mpath->dsn = dst_dsn; |
567 | spin_unlock_bh(&mpath->state_lock); | 565 | spin_unlock_bh(&mpath->state_lock); |
568 | mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), | 566 | mesh_path_error_tx(dst_addr, cpu_to_le32(dst_dsn), |
569 | dev->broadcast, dev); | 567 | sdata->dev->broadcast, sdata); |
570 | } else | 568 | } else |
571 | spin_unlock_bh(&mpath->state_lock); | 569 | spin_unlock_bh(&mpath->state_lock); |
572 | } | 570 | } |
@@ -575,7 +573,7 @@ static void hwmp_perr_frame_process(struct net_device *dev, | |||
575 | 573 | ||
576 | 574 | ||
577 | 575 | ||
578 | void mesh_rx_path_sel_frame(struct net_device *dev, | 576 | void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, |
579 | struct ieee80211_mgmt *mgmt, | 577 | struct ieee80211_mgmt *mgmt, |
580 | size_t len) | 578 | size_t len) |
581 | { | 579 | { |
@@ -583,6 +581,10 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
583 | size_t baselen; | 581 | size_t baselen; |
584 | u32 last_hop_metric; | 582 | u32 last_hop_metric; |
585 | 583 | ||
584 | /* need action_code */ | ||
585 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
586 | return; | ||
587 | |||
586 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; | 588 | baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; |
587 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, | 589 | ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, |
588 | len - baselen, &elems); | 590 | len - baselen, &elems); |
@@ -592,25 +594,25 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
592 | if (!elems.preq || elems.preq_len != 37) | 594 | if (!elems.preq || elems.preq_len != 37) |
593 | /* Right now we support just 1 destination and no AE */ | 595 | /* Right now we support just 1 destination and no AE */ |
594 | return; | 596 | return; |
595 | last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.preq); | 597 | last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq); |
596 | if (!last_hop_metric) | 598 | if (!last_hop_metric) |
597 | return; | 599 | return; |
598 | hwmp_preq_frame_process(dev, mgmt, elems.preq, last_hop_metric); | 600 | hwmp_preq_frame_process(sdata, mgmt, elems.preq, last_hop_metric); |
599 | break; | 601 | break; |
600 | case MPATH_PREP: | 602 | case MPATH_PREP: |
601 | if (!elems.prep || elems.prep_len != 31) | 603 | if (!elems.prep || elems.prep_len != 31) |
602 | /* Right now we support no AE */ | 604 | /* Right now we support no AE */ |
603 | return; | 605 | return; |
604 | last_hop_metric = hwmp_route_info_get(dev, mgmt, elems.prep); | 606 | last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep); |
605 | if (!last_hop_metric) | 607 | if (!last_hop_metric) |
606 | return; | 608 | return; |
607 | hwmp_prep_frame_process(dev, mgmt, elems.prep, last_hop_metric); | 609 | hwmp_prep_frame_process(sdata, mgmt, elems.prep, last_hop_metric); |
608 | break; | 610 | break; |
609 | case MPATH_PERR: | 611 | case MPATH_PERR: |
610 | if (!elems.perr || elems.perr_len != 12) | 612 | if (!elems.perr || elems.perr_len != 12) |
611 | /* Right now we support only one destination per PERR */ | 613 | /* Right now we support only one destination per PERR */ |
612 | return; | 614 | return; |
613 | hwmp_perr_frame_process(dev, mgmt, elems.perr); | 615 | hwmp_perr_frame_process(sdata, mgmt, elems.perr); |
614 | default: | 616 | default: |
615 | return; | 617 | return; |
616 | } | 618 | } |
@@ -628,9 +630,8 @@ void mesh_rx_path_sel_frame(struct net_device *dev, | |||
628 | */ | 630 | */ |
629 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | 631 | static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) |
630 | { | 632 | { |
631 | struct ieee80211_sub_if_data *sdata = | 633 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
632 | IEEE80211_DEV_TO_SUB_IF(mpath->dev); | 634 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
633 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
634 | struct mesh_preq_queue *preq_node; | 635 | struct mesh_preq_queue *preq_node; |
635 | 636 | ||
636 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); | 637 | preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); |
@@ -639,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
639 | return; | 640 | return; |
640 | } | 641 | } |
641 | 642 | ||
642 | spin_lock(&ifsta->mesh_preq_queue_lock); | 643 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
643 | if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { | 644 | if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) { |
644 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 645 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
645 | kfree(preq_node); | 646 | kfree(preq_node); |
646 | if (printk_ratelimit()) | 647 | if (printk_ratelimit()) |
647 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); | 648 | printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); |
@@ -651,55 +652,53 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) | |||
651 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); | 652 | memcpy(preq_node->dst, mpath->dst, ETH_ALEN); |
652 | preq_node->flags = flags; | 653 | preq_node->flags = flags; |
653 | 654 | ||
654 | list_add_tail(&preq_node->list, &ifsta->preq_queue.list); | 655 | list_add_tail(&preq_node->list, &ifmsh->preq_queue.list); |
655 | ++ifsta->preq_queue_len; | 656 | ++ifmsh->preq_queue_len; |
656 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 657 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
657 | 658 | ||
658 | if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) | 659 | if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) |
659 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 660 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
660 | 661 | ||
661 | else if (time_before(jiffies, ifsta->last_preq)) { | 662 | else if (time_before(jiffies, ifmsh->last_preq)) { |
662 | /* avoid long wait if did not send preqs for a long time | 663 | /* avoid long wait if did not send preqs for a long time |
663 | * and jiffies wrapped around | 664 | * and jiffies wrapped around |
664 | */ | 665 | */ |
665 | ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; | 666 | ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; |
666 | queue_work(sdata->local->hw.workqueue, &ifsta->work); | 667 | queue_work(sdata->local->hw.workqueue, &ifmsh->work); |
667 | } else | 668 | } else |
668 | mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + | 669 | mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + |
669 | min_preq_int_jiff(sdata)); | 670 | min_preq_int_jiff(sdata)); |
670 | } | 671 | } |
671 | 672 | ||
672 | /** | 673 | /** |
673 | * mesh_path_start_discovery - launch a path discovery from the PREQ queue | 674 | * mesh_path_start_discovery - launch a path discovery from the PREQ queue |
674 | * | 675 | * |
675 | * @dev: local mesh interface | 676 | * @sdata: local mesh subif |
676 | */ | 677 | */ |
677 | void mesh_path_start_discovery(struct net_device *dev) | 678 | void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) |
678 | { | 679 | { |
679 | struct ieee80211_sub_if_data *sdata = | 680 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
680 | IEEE80211_DEV_TO_SUB_IF(dev); | ||
681 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
682 | struct mesh_preq_queue *preq_node; | 681 | struct mesh_preq_queue *preq_node; |
683 | struct mesh_path *mpath; | 682 | struct mesh_path *mpath; |
684 | u8 ttl, dst_flags; | 683 | u8 ttl, dst_flags; |
685 | u32 lifetime; | 684 | u32 lifetime; |
686 | 685 | ||
687 | spin_lock(&ifsta->mesh_preq_queue_lock); | 686 | spin_lock(&ifmsh->mesh_preq_queue_lock); |
688 | if (!ifsta->preq_queue_len || | 687 | if (!ifmsh->preq_queue_len || |
689 | time_before(jiffies, ifsta->last_preq + | 688 | time_before(jiffies, ifmsh->last_preq + |
690 | min_preq_int_jiff(sdata))) { | 689 | min_preq_int_jiff(sdata))) { |
691 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 690 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
692 | return; | 691 | return; |
693 | } | 692 | } |
694 | 693 | ||
695 | preq_node = list_first_entry(&ifsta->preq_queue.list, | 694 | preq_node = list_first_entry(&ifmsh->preq_queue.list, |
696 | struct mesh_preq_queue, list); | 695 | struct mesh_preq_queue, list); |
697 | list_del(&preq_node->list); | 696 | list_del(&preq_node->list); |
698 | --ifsta->preq_queue_len; | 697 | --ifmsh->preq_queue_len; |
699 | spin_unlock(&ifsta->mesh_preq_queue_lock); | 698 | spin_unlock(&ifmsh->mesh_preq_queue_lock); |
700 | 699 | ||
701 | rcu_read_lock(); | 700 | rcu_read_lock(); |
702 | mpath = mesh_path_lookup(preq_node->dst, dev); | 701 | mpath = mesh_path_lookup(preq_node->dst, sdata); |
703 | if (!mpath) | 702 | if (!mpath) |
704 | goto enddiscovery; | 703 | goto enddiscovery; |
705 | 704 | ||
@@ -721,18 +720,18 @@ void mesh_path_start_discovery(struct net_device *dev) | |||
721 | goto enddiscovery; | 720 | goto enddiscovery; |
722 | } | 721 | } |
723 | 722 | ||
724 | ifsta->last_preq = jiffies; | 723 | ifmsh->last_preq = jiffies; |
725 | 724 | ||
726 | if (time_after(jiffies, ifsta->last_dsn_update + | 725 | if (time_after(jiffies, ifmsh->last_dsn_update + |
727 | net_traversal_jiffies(sdata)) || | 726 | net_traversal_jiffies(sdata)) || |
728 | time_before(jiffies, ifsta->last_dsn_update)) { | 727 | time_before(jiffies, ifmsh->last_dsn_update)) { |
729 | ++ifsta->dsn; | 728 | ++ifmsh->dsn; |
730 | sdata->u.sta.last_dsn_update = jiffies; | 729 | sdata->u.mesh.last_dsn_update = jiffies; |
731 | } | 730 | } |
732 | lifetime = default_lifetime(sdata); | 731 | lifetime = default_lifetime(sdata); |
733 | ttl = sdata->u.sta.mshcfg.dot11MeshTTL; | 732 | ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; |
734 | if (ttl == 0) { | 733 | if (ttl == 0) { |
735 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 734 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
736 | spin_unlock_bh(&mpath->state_lock); | 735 | spin_unlock_bh(&mpath->state_lock); |
737 | goto enddiscovery; | 736 | goto enddiscovery; |
738 | } | 737 | } |
@@ -743,11 +742,11 @@ void mesh_path_start_discovery(struct net_device *dev) | |||
743 | dst_flags = MP_F_RF; | 742 | dst_flags = MP_F_RF; |
744 | 743 | ||
745 | spin_unlock_bh(&mpath->state_lock); | 744 | spin_unlock_bh(&mpath->state_lock); |
746 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, dev->dev_addr, | 745 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, |
747 | cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, | 746 | cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst, |
748 | cpu_to_le32(mpath->dsn), dev->broadcast, 0, | 747 | cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, |
749 | ttl, cpu_to_le32(lifetime), 0, | 748 | ttl, cpu_to_le32(lifetime), 0, |
750 | cpu_to_le32(ifsta->preq_id++), dev); | 749 | cpu_to_le32(ifmsh->preq_id++), sdata); |
751 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 750 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
752 | 751 | ||
753 | enddiscovery: | 752 | enddiscovery: |
@@ -759,7 +758,7 @@ enddiscovery: | |||
759 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame | 758 | * ieee80211s_lookup_nexthop - put the appropriate next hop on a mesh frame |
760 | * | 759 | * |
761 | * @skb: 802.11 frame to be sent | 760 | * @skb: 802.11 frame to be sent |
762 | * @dev: network device the frame will be sent through | 761 | * @sdata: network subif the frame will be sent through |
763 | * @fwd_frame: true if this frame was originally from a different host | 762 | * @fwd_frame: true if this frame was originally from a different host |
764 | * | 763 | * |
765 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is | 764 | * Returns: 0 if the next hop was found. Nonzero otherwise. If no next hop is |
@@ -767,9 +766,9 @@ enddiscovery: | |||
767 | * sent when the path is resolved. This means the caller must not free the skb | 766 | * sent when the path is resolved. This means the caller must not free the skb |
768 | * in this case. | 767 | * in this case. |
769 | */ | 768 | */ |
770 | int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | 769 | int mesh_nexthop_lookup(struct sk_buff *skb, |
770 | struct ieee80211_sub_if_data *sdata) | ||
771 | { | 771 | { |
772 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
773 | struct sk_buff *skb_to_free = NULL; | 772 | struct sk_buff *skb_to_free = NULL; |
774 | struct mesh_path *mpath; | 773 | struct mesh_path *mpath; |
775 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 774 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
@@ -777,14 +776,14 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
777 | int err = 0; | 776 | int err = 0; |
778 | 777 | ||
779 | rcu_read_lock(); | 778 | rcu_read_lock(); |
780 | mpath = mesh_path_lookup(dst_addr, dev); | 779 | mpath = mesh_path_lookup(dst_addr, sdata); |
781 | 780 | ||
782 | if (!mpath) { | 781 | if (!mpath) { |
783 | mesh_path_add(dst_addr, dev); | 782 | mesh_path_add(dst_addr, sdata); |
784 | mpath = mesh_path_lookup(dst_addr, dev); | 783 | mpath = mesh_path_lookup(dst_addr, sdata); |
785 | if (!mpath) { | 784 | if (!mpath) { |
786 | dev_kfree_skb(skb); | 785 | dev_kfree_skb(skb); |
787 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 786 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
788 | err = -ENOSPC; | 787 | err = -ENOSPC; |
789 | goto endlookup; | 788 | goto endlookup; |
790 | } | 789 | } |
@@ -792,14 +791,15 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
792 | 791 | ||
793 | if (mpath->flags & MESH_PATH_ACTIVE) { | 792 | if (mpath->flags & MESH_PATH_ACTIVE) { |
794 | if (time_after(jiffies, mpath->exp_time - | 793 | if (time_after(jiffies, mpath->exp_time - |
795 | msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) | 794 | msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) |
796 | && !memcmp(dev->dev_addr, hdr->addr4, ETH_ALEN) | 795 | && !memcmp(sdata->dev->dev_addr, hdr->addr4, |
796 | ETH_ALEN) | ||
797 | && !(mpath->flags & MESH_PATH_RESOLVING) | 797 | && !(mpath->flags & MESH_PATH_RESOLVING) |
798 | && !(mpath->flags & MESH_PATH_FIXED)) { | 798 | && !(mpath->flags & MESH_PATH_FIXED)) { |
799 | mesh_queue_preq(mpath, | 799 | mesh_queue_preq(mpath, |
800 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 800 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
801 | } | 801 | } |
802 | memcpy(hdr->addr1, mpath->next_hop->addr, | 802 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, |
803 | ETH_ALEN); | 803 | ETH_ALEN); |
804 | } else { | 804 | } else { |
805 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 805 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
@@ -815,7 +815,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, struct net_device *dev) | |||
815 | 815 | ||
816 | skb_queue_tail(&mpath->frame_queue, skb); | 816 | skb_queue_tail(&mpath->frame_queue, skb); |
817 | if (skb_to_free) | 817 | if (skb_to_free) |
818 | mesh_path_discard_frame(skb_to_free, dev); | 818 | mesh_path_discard_frame(skb_to_free, sdata); |
819 | err = -ENOENT; | 819 | err = -ENOENT; |
820 | } | 820 | } |
821 | 821 | ||
@@ -835,7 +835,7 @@ void mesh_path_timer(unsigned long data) | |||
835 | if (!mpath) | 835 | if (!mpath) |
836 | goto endmpathtimer; | 836 | goto endmpathtimer; |
837 | spin_lock_bh(&mpath->state_lock); | 837 | spin_lock_bh(&mpath->state_lock); |
838 | sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); | 838 | sdata = mpath->sdata; |
839 | if (mpath->flags & MESH_PATH_RESOLVED || | 839 | if (mpath->flags & MESH_PATH_RESOLVED || |
840 | (!(mpath->flags & MESH_PATH_RESOLVING))) | 840 | (!(mpath->flags & MESH_PATH_RESOLVING))) |
841 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); | 841 | mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 838ee60492ad..e4fa2905fadc 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | #include <linux/etherdevice.h> | 10 | #include <linux/etherdevice.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/random.h> | 12 | #include <linux/random.h> |
14 | #include <linux/spinlock.h> | 13 | #include <linux/spinlock.h> |
15 | #include <linux/string.h> | 14 | #include <linux/string.h> |
@@ -62,13 +61,13 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
62 | /** | 61 | /** |
63 | * mesh_path_lookup - look up a path in the mesh path table | 62 | * mesh_path_lookup - look up a path in the mesh path table |
64 | * @dst: hardware address (ETH_ALEN length) of destination | 63 | * @dst: hardware address (ETH_ALEN length) of destination |
65 | * @dev: local interface | 64 | * @sdata: local subif |
66 | * | 65 | * |
67 | * Returns: pointer to the mesh path structure, or NULL if not found | 66 | * Returns: pointer to the mesh path structure, or NULL if not found |
68 | * | 67 | * |
69 | * Locking: must be called within a read rcu section. | 68 | * Locking: must be called within a read rcu section. |
70 | */ | 69 | */ |
71 | struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | 70 | struct mesh_path *mesh_path_lookup(u8 *dst, struct ieee80211_sub_if_data *sdata) |
72 | { | 71 | { |
73 | struct mesh_path *mpath; | 72 | struct mesh_path *mpath; |
74 | struct hlist_node *n; | 73 | struct hlist_node *n; |
@@ -78,10 +77,10 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | |||
78 | 77 | ||
79 | tbl = rcu_dereference(mesh_paths); | 78 | tbl = rcu_dereference(mesh_paths); |
80 | 79 | ||
81 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, dev, tbl)]; | 80 | bucket = &tbl->hash_buckets[mesh_table_hash(dst, sdata, tbl)]; |
82 | hlist_for_each_entry_rcu(node, n, bucket, list) { | 81 | hlist_for_each_entry_rcu(node, n, bucket, list) { |
83 | mpath = node->mpath; | 82 | mpath = node->mpath; |
84 | if (mpath->dev == dev && | 83 | if (mpath->sdata == sdata && |
85 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { | 84 | memcmp(dst, mpath->dst, ETH_ALEN) == 0) { |
86 | if (MPATH_EXPIRED(mpath)) { | 85 | if (MPATH_EXPIRED(mpath)) { |
87 | spin_lock_bh(&mpath->state_lock); | 86 | spin_lock_bh(&mpath->state_lock); |
@@ -98,13 +97,13 @@ struct mesh_path *mesh_path_lookup(u8 *dst, struct net_device *dev) | |||
98 | /** | 97 | /** |
99 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index | 98 | * mesh_path_lookup_by_idx - look up a path in the mesh path table by its index |
100 | * @idx: index | 99 | * @idx: index |
101 | * @dev: local interface, or NULL for all entries | 100 | * @sdata: local subif, or NULL for all entries |
102 | * | 101 | * |
103 | * Returns: pointer to the mesh path structure, or NULL if not found. | 102 | * Returns: pointer to the mesh path structure, or NULL if not found. |
104 | * | 103 | * |
105 | * Locking: must be called within a read rcu section. | 104 | * Locking: must be called within a read rcu section. |
106 | */ | 105 | */ |
107 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | 106 | struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data *sdata) |
108 | { | 107 | { |
109 | struct mpath_node *node; | 108 | struct mpath_node *node; |
110 | struct hlist_node *p; | 109 | struct hlist_node *p; |
@@ -112,7 +111,7 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | |||
112 | int j = 0; | 111 | int j = 0; |
113 | 112 | ||
114 | for_each_mesh_entry(mesh_paths, p, node, i) { | 113 | for_each_mesh_entry(mesh_paths, p, node, i) { |
115 | if (dev && node->mpath->dev != dev) | 114 | if (sdata && node->mpath->sdata != sdata) |
116 | continue; | 115 | continue; |
117 | if (j++ == idx) { | 116 | if (j++ == idx) { |
118 | if (MPATH_EXPIRED(node->mpath)) { | 117 | if (MPATH_EXPIRED(node->mpath)) { |
@@ -131,15 +130,14 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct net_device *dev) | |||
131 | /** | 130 | /** |
132 | * mesh_path_add - allocate and add a new path to the mesh path table | 131 | * mesh_path_add - allocate and add a new path to the mesh path table |
133 | * @addr: destination address of the path (ETH_ALEN length) | 132 | * @addr: destination address of the path (ETH_ALEN length) |
134 | * @dev: local interface | 133 | * @sdata: local subif |
135 | * | 134 | * |
136 | * Returns: 0 on sucess | 135 | * Returns: 0 on sucess |
137 | * | 136 | * |
138 | * State: the initial state of the new path is set to 0 | 137 | * State: the initial state of the new path is set to 0 |
139 | */ | 138 | */ |
140 | int mesh_path_add(u8 *dst, struct net_device *dev) | 139 | int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) |
141 | { | 140 | { |
142 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
143 | struct mesh_path *mpath, *new_mpath; | 141 | struct mesh_path *mpath, *new_mpath; |
144 | struct mpath_node *node, *new_node; | 142 | struct mpath_node *node, *new_node; |
145 | struct hlist_head *bucket; | 143 | struct hlist_head *bucket; |
@@ -148,14 +146,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
148 | int err = 0; | 146 | int err = 0; |
149 | u32 hash_idx; | 147 | u32 hash_idx; |
150 | 148 | ||
151 | if (memcmp(dst, dev->dev_addr, ETH_ALEN) == 0) | 149 | if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) |
152 | /* never add ourselves as neighbours */ | 150 | /* never add ourselves as neighbours */ |
153 | return -ENOTSUPP; | 151 | return -ENOTSUPP; |
154 | 152 | ||
155 | if (is_multicast_ether_addr(dst)) | 153 | if (is_multicast_ether_addr(dst)) |
156 | return -ENOTSUPP; | 154 | return -ENOTSUPP; |
157 | 155 | ||
158 | if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) | 156 | if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0) |
159 | return -ENOSPC; | 157 | return -ENOSPC; |
160 | 158 | ||
161 | err = -ENOMEM; | 159 | err = -ENOMEM; |
@@ -169,7 +167,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
169 | 167 | ||
170 | read_lock(&pathtbl_resize_lock); | 168 | read_lock(&pathtbl_resize_lock); |
171 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 169 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
172 | new_mpath->dev = dev; | 170 | new_mpath->sdata = sdata; |
173 | new_mpath->flags = 0; | 171 | new_mpath->flags = 0; |
174 | skb_queue_head_init(&new_mpath->frame_queue); | 172 | skb_queue_head_init(&new_mpath->frame_queue); |
175 | new_node->mpath = new_mpath; | 173 | new_node->mpath = new_mpath; |
@@ -179,7 +177,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
179 | spin_lock_init(&new_mpath->state_lock); | 177 | spin_lock_init(&new_mpath->state_lock); |
180 | init_timer(&new_mpath->timer); | 178 | init_timer(&new_mpath->timer); |
181 | 179 | ||
182 | hash_idx = mesh_table_hash(dst, dev, mesh_paths); | 180 | hash_idx = mesh_table_hash(dst, sdata, mesh_paths); |
183 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 181 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
184 | 182 | ||
185 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 183 | spin_lock(&mesh_paths->hashwlock[hash_idx]); |
@@ -187,7 +185,7 @@ int mesh_path_add(u8 *dst, struct net_device *dev) | |||
187 | err = -EEXIST; | 185 | err = -EEXIST; |
188 | hlist_for_each_entry(node, n, bucket, list) { | 186 | hlist_for_each_entry(node, n, bucket, list) { |
189 | mpath = node->mpath; | 187 | mpath = node->mpath; |
190 | if (mpath->dev == dev && memcmp(dst, mpath->dst, ETH_ALEN) == 0) | 188 | if (mpath->sdata == sdata && memcmp(dst, mpath->dst, ETH_ALEN) == 0) |
191 | goto err_exists; | 189 | goto err_exists; |
192 | } | 190 | } |
193 | 191 | ||
@@ -223,7 +221,7 @@ err_exists: | |||
223 | err_node_alloc: | 221 | err_node_alloc: |
224 | kfree(new_mpath); | 222 | kfree(new_mpath); |
225 | err_path_alloc: | 223 | err_path_alloc: |
226 | atomic_dec(&sdata->u.sta.mpaths); | 224 | atomic_dec(&sdata->u.mesh.mpaths); |
227 | return err; | 225 | return err; |
228 | } | 226 | } |
229 | 227 | ||
@@ -241,7 +239,7 @@ void mesh_plink_broken(struct sta_info *sta) | |||
241 | struct mesh_path *mpath; | 239 | struct mesh_path *mpath; |
242 | struct mpath_node *node; | 240 | struct mpath_node *node; |
243 | struct hlist_node *p; | 241 | struct hlist_node *p; |
244 | struct net_device *dev = sta->sdata->dev; | 242 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
245 | int i; | 243 | int i; |
246 | 244 | ||
247 | rcu_read_lock(); | 245 | rcu_read_lock(); |
@@ -256,7 +254,7 @@ void mesh_plink_broken(struct sta_info *sta) | |||
256 | spin_unlock_bh(&mpath->state_lock); | 254 | spin_unlock_bh(&mpath->state_lock); |
257 | mesh_path_error_tx(mpath->dst, | 255 | mesh_path_error_tx(mpath->dst, |
258 | cpu_to_le32(mpath->dsn), | 256 | cpu_to_le32(mpath->dsn), |
259 | dev->broadcast, dev); | 257 | sdata->dev->broadcast, sdata); |
260 | } else | 258 | } else |
261 | spin_unlock_bh(&mpath->state_lock); | 259 | spin_unlock_bh(&mpath->state_lock); |
262 | } | 260 | } |
@@ -284,11 +282,11 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta) | |||
284 | for_each_mesh_entry(mesh_paths, p, node, i) { | 282 | for_each_mesh_entry(mesh_paths, p, node, i) { |
285 | mpath = node->mpath; | 283 | mpath = node->mpath; |
286 | if (mpath->next_hop == sta) | 284 | if (mpath->next_hop == sta) |
287 | mesh_path_del(mpath->dst, mpath->dev); | 285 | mesh_path_del(mpath->dst, mpath->sdata); |
288 | } | 286 | } |
289 | } | 287 | } |
290 | 288 | ||
291 | void mesh_path_flush(struct net_device *dev) | 289 | void mesh_path_flush(struct ieee80211_sub_if_data *sdata) |
292 | { | 290 | { |
293 | struct mesh_path *mpath; | 291 | struct mesh_path *mpath; |
294 | struct mpath_node *node; | 292 | struct mpath_node *node; |
@@ -297,19 +295,18 @@ void mesh_path_flush(struct net_device *dev) | |||
297 | 295 | ||
298 | for_each_mesh_entry(mesh_paths, p, node, i) { | 296 | for_each_mesh_entry(mesh_paths, p, node, i) { |
299 | mpath = node->mpath; | 297 | mpath = node->mpath; |
300 | if (mpath->dev == dev) | 298 | if (mpath->sdata == sdata) |
301 | mesh_path_del(mpath->dst, mpath->dev); | 299 | mesh_path_del(mpath->dst, mpath->sdata); |
302 | } | 300 | } |
303 | } | 301 | } |
304 | 302 | ||
305 | static void mesh_path_node_reclaim(struct rcu_head *rp) | 303 | static void mesh_path_node_reclaim(struct rcu_head *rp) |
306 | { | 304 | { |
307 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); | 305 | struct mpath_node *node = container_of(rp, struct mpath_node, rcu); |
308 | struct ieee80211_sub_if_data *sdata = | 306 | struct ieee80211_sub_if_data *sdata = node->mpath->sdata; |
309 | IEEE80211_DEV_TO_SUB_IF(node->mpath->dev); | ||
310 | 307 | ||
311 | del_timer_sync(&node->mpath->timer); | 308 | del_timer_sync(&node->mpath->timer); |
312 | atomic_dec(&sdata->u.sta.mpaths); | 309 | atomic_dec(&sdata->u.mesh.mpaths); |
313 | kfree(node->mpath); | 310 | kfree(node->mpath); |
314 | kfree(node); | 311 | kfree(node); |
315 | } | 312 | } |
@@ -318,11 +315,11 @@ static void mesh_path_node_reclaim(struct rcu_head *rp) | |||
318 | * mesh_path_del - delete a mesh path from the table | 315 | * mesh_path_del - delete a mesh path from the table |
319 | * | 316 | * |
320 | * @addr: dst address (ETH_ALEN length) | 317 | * @addr: dst address (ETH_ALEN length) |
321 | * @dev: local interface | 318 | * @sdata: local subif |
322 | * | 319 | * |
323 | * Returns: 0 if succesful | 320 | * Returns: 0 if succesful |
324 | */ | 321 | */ |
325 | int mesh_path_del(u8 *addr, struct net_device *dev) | 322 | int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) |
326 | { | 323 | { |
327 | struct mesh_path *mpath; | 324 | struct mesh_path *mpath; |
328 | struct mpath_node *node; | 325 | struct mpath_node *node; |
@@ -332,13 +329,13 @@ int mesh_path_del(u8 *addr, struct net_device *dev) | |||
332 | int err = 0; | 329 | int err = 0; |
333 | 330 | ||
334 | read_lock(&pathtbl_resize_lock); | 331 | read_lock(&pathtbl_resize_lock); |
335 | hash_idx = mesh_table_hash(addr, dev, mesh_paths); | 332 | hash_idx = mesh_table_hash(addr, sdata, mesh_paths); |
336 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 333 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
337 | 334 | ||
338 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 335 | spin_lock(&mesh_paths->hashwlock[hash_idx]); |
339 | hlist_for_each_entry(node, n, bucket, list) { | 336 | hlist_for_each_entry(node, n, bucket, list) { |
340 | mpath = node->mpath; | 337 | mpath = node->mpath; |
341 | if (mpath->dev == dev && | 338 | if (mpath->sdata == sdata && |
342 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { | 339 | memcmp(addr, mpath->dst, ETH_ALEN) == 0) { |
343 | spin_lock_bh(&mpath->state_lock); | 340 | spin_lock_bh(&mpath->state_lock); |
344 | mpath->flags |= MESH_PATH_RESOLVING; | 341 | mpath->flags |= MESH_PATH_RESOLVING; |
@@ -378,33 +375,33 @@ void mesh_path_tx_pending(struct mesh_path *mpath) | |||
378 | * mesh_path_discard_frame - discard a frame whose path could not be resolved | 375 | * mesh_path_discard_frame - discard a frame whose path could not be resolved |
379 | * | 376 | * |
380 | * @skb: frame to discard | 377 | * @skb: frame to discard |
381 | * @dev: network device the frame was to be sent through | 378 | * @sdata: network subif the frame was to be sent through |
382 | * | 379 | * |
383 | * If the frame was beign forwarded from another MP, a PERR frame will be sent | 380 | * If the frame was beign forwarded from another MP, a PERR frame will be sent |
384 | * to the precursor. | 381 | * to the precursor. |
385 | * | 382 | * |
386 | * Locking: the function must me called within a rcu_read_lock region | 383 | * Locking: the function must me called within a rcu_read_lock region |
387 | */ | 384 | */ |
388 | void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) | 385 | void mesh_path_discard_frame(struct sk_buff *skb, |
386 | struct ieee80211_sub_if_data *sdata) | ||
389 | { | 387 | { |
390 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
391 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 388 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
392 | struct mesh_path *mpath; | 389 | struct mesh_path *mpath; |
393 | u32 dsn = 0; | 390 | u32 dsn = 0; |
394 | 391 | ||
395 | if (memcmp(hdr->addr4, dev->dev_addr, ETH_ALEN) != 0) { | 392 | if (memcmp(hdr->addr4, sdata->dev->dev_addr, ETH_ALEN) != 0) { |
396 | u8 *ra, *da; | 393 | u8 *ra, *da; |
397 | 394 | ||
398 | da = hdr->addr3; | 395 | da = hdr->addr3; |
399 | ra = hdr->addr2; | 396 | ra = hdr->addr2; |
400 | mpath = mesh_path_lookup(da, dev); | 397 | mpath = mesh_path_lookup(da, sdata); |
401 | if (mpath) | 398 | if (mpath) |
402 | dsn = ++mpath->dsn; | 399 | dsn = ++mpath->dsn; |
403 | mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, dev); | 400 | mesh_path_error_tx(skb->data, cpu_to_le32(dsn), ra, sdata); |
404 | } | 401 | } |
405 | 402 | ||
406 | kfree_skb(skb); | 403 | kfree_skb(skb); |
407 | sdata->u.sta.mshstats.dropped_frames_no_route++; | 404 | sdata->u.mesh.mshstats.dropped_frames_no_route++; |
408 | } | 405 | } |
409 | 406 | ||
410 | /** | 407 | /** |
@@ -416,14 +413,11 @@ void mesh_path_discard_frame(struct sk_buff *skb, struct net_device *dev) | |||
416 | */ | 413 | */ |
417 | void mesh_path_flush_pending(struct mesh_path *mpath) | 414 | void mesh_path_flush_pending(struct mesh_path *mpath) |
418 | { | 415 | { |
419 | struct ieee80211_sub_if_data *sdata; | ||
420 | struct sk_buff *skb; | 416 | struct sk_buff *skb; |
421 | 417 | ||
422 | sdata = IEEE80211_DEV_TO_SUB_IF(mpath->dev); | ||
423 | |||
424 | while ((skb = skb_dequeue(&mpath->frame_queue)) && | 418 | while ((skb = skb_dequeue(&mpath->frame_queue)) && |
425 | (mpath->flags & MESH_PATH_ACTIVE)) | 419 | (mpath->flags & MESH_PATH_ACTIVE)) |
426 | mesh_path_discard_frame(skb, mpath->dev); | 420 | mesh_path_discard_frame(skb, mpath->sdata); |
427 | } | 421 | } |
428 | 422 | ||
429 | /** | 423 | /** |
@@ -472,7 +466,7 @@ static int mesh_path_node_copy(struct hlist_node *p, struct mesh_table *newtbl) | |||
472 | node = hlist_entry(p, struct mpath_node, list); | 466 | node = hlist_entry(p, struct mpath_node, list); |
473 | mpath = node->mpath; | 467 | mpath = node->mpath; |
474 | new_node->mpath = mpath; | 468 | new_node->mpath = mpath; |
475 | hash_idx = mesh_table_hash(mpath->dst, mpath->dev, newtbl); | 469 | hash_idx = mesh_table_hash(mpath->dst, mpath->sdata, newtbl); |
476 | hlist_add_head(&new_node->list, | 470 | hlist_add_head(&new_node->list, |
477 | &newtbl->hash_buckets[hash_idx]); | 471 | &newtbl->hash_buckets[hash_idx]); |
478 | return 0; | 472 | return 0; |
@@ -489,7 +483,7 @@ int mesh_pathtbl_init(void) | |||
489 | return 0; | 483 | return 0; |
490 | } | 484 | } |
491 | 485 | ||
492 | void mesh_path_expire(struct net_device *dev) | 486 | void mesh_path_expire(struct ieee80211_sub_if_data *sdata) |
493 | { | 487 | { |
494 | struct mesh_path *mpath; | 488 | struct mesh_path *mpath; |
495 | struct mpath_node *node; | 489 | struct mpath_node *node; |
@@ -498,7 +492,7 @@ void mesh_path_expire(struct net_device *dev) | |||
498 | 492 | ||
499 | read_lock(&pathtbl_resize_lock); | 493 | read_lock(&pathtbl_resize_lock); |
500 | for_each_mesh_entry(mesh_paths, p, node, i) { | 494 | for_each_mesh_entry(mesh_paths, p, node, i) { |
501 | if (node->mpath->dev != dev) | 495 | if (node->mpath->sdata != sdata) |
502 | continue; | 496 | continue; |
503 | mpath = node->mpath; | 497 | mpath = node->mpath; |
504 | spin_lock_bh(&mpath->state_lock); | 498 | spin_lock_bh(&mpath->state_lock); |
@@ -507,7 +501,7 @@ void mesh_path_expire(struct net_device *dev) | |||
507 | time_after(jiffies, | 501 | time_after(jiffies, |
508 | mpath->exp_time + MESH_PATH_EXPIRE)) { | 502 | mpath->exp_time + MESH_PATH_EXPIRE)) { |
509 | spin_unlock_bh(&mpath->state_lock); | 503 | spin_unlock_bh(&mpath->state_lock); |
510 | mesh_path_del(mpath->dst, mpath->dev); | 504 | mesh_path_del(mpath->dst, mpath->sdata); |
511 | } else | 505 | } else |
512 | spin_unlock_bh(&mpath->state_lock); | 506 | spin_unlock_bh(&mpath->state_lock); |
513 | } | 507 | } |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 9efeb1f07025..faac101c0f85 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -36,11 +36,11 @@ | |||
36 | #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 | 36 | #define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 |
37 | #define MESH_SECURITY_FAILED_VERIFICATION 10 | 37 | #define MESH_SECURITY_FAILED_VERIFICATION 10 |
38 | 38 | ||
39 | #define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) | 39 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) |
40 | #define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) | 40 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) |
41 | #define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) | 41 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) |
42 | #define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) | 42 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) |
43 | #define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) | 43 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) |
44 | 44 | ||
45 | enum plink_frame_type { | 45 | enum plink_frame_type { |
46 | PLINK_OPEN = 0, | 46 | PLINK_OPEN = 0, |
@@ -63,14 +63,14 @@ enum plink_event { | |||
63 | static inline | 63 | static inline |
64 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 64 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
65 | { | 65 | { |
66 | atomic_inc(&sdata->u.sta.mshstats.estab_plinks); | 66 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); |
67 | mesh_accept_plinks_update(sdata); | 67 | mesh_accept_plinks_update(sdata); |
68 | } | 68 | } |
69 | 69 | ||
70 | static inline | 70 | static inline |
71 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | 71 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) |
72 | { | 72 | { |
73 | atomic_dec(&sdata->u.sta.mshstats.estab_plinks); | 73 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); |
74 | mesh_accept_plinks_update(sdata); | 74 | mesh_accept_plinks_update(sdata); |
75 | } | 75 | } |
76 | 76 | ||
@@ -106,7 +106,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | sta->flags = WLAN_STA_AUTHORIZED; | 108 | sta->flags = WLAN_STA_AUTHORIZED; |
109 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 109 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
110 | 110 | ||
111 | return sta; | 111 | return sta; |
112 | } | 112 | } |
@@ -144,10 +144,10 @@ void mesh_plink_deactivate(struct sta_info *sta) | |||
144 | spin_unlock_bh(&sta->lock); | 144 | spin_unlock_bh(&sta->lock); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int mesh_plink_frame_tx(struct net_device *dev, | 147 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
148 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, | 148 | enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, |
149 | __le16 reason) { | 149 | __le16 reason) { |
150 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 150 | struct ieee80211_local *local = sdata->local; |
151 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 151 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
152 | struct ieee80211_mgmt *mgmt; | 152 | struct ieee80211_mgmt *mgmt; |
153 | bool include_plid = false; | 153 | bool include_plid = false; |
@@ -163,10 +163,10 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
163 | mgmt = (struct ieee80211_mgmt *) | 163 | mgmt = (struct ieee80211_mgmt *) |
164 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); | 164 | skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); |
165 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); | 165 | memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); |
166 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 166 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
167 | IEEE80211_STYPE_ACTION); | 167 | IEEE80211_STYPE_ACTION); |
168 | memcpy(mgmt->da, da, ETH_ALEN); | 168 | memcpy(mgmt->da, da, ETH_ALEN); |
169 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 169 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
170 | /* BSSID is left zeroed, wildcard value */ | 170 | /* BSSID is left zeroed, wildcard value */ |
171 | mgmt->u.action.category = PLINK_CATEGORY; | 171 | mgmt->u.action.category = PLINK_CATEGORY; |
172 | mgmt->u.action.u.plink_action.action_code = action; | 172 | mgmt->u.action.u.plink_action.action_code = action; |
@@ -180,7 +180,7 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
180 | /* two-byte status code followed by two-byte AID */ | 180 | /* two-byte status code followed by two-byte AID */ |
181 | memset(pos, 0, 4); | 181 | memset(pos, 0, 4); |
182 | } | 182 | } |
183 | mesh_mgmt_ies_add(skb, dev); | 183 | mesh_mgmt_ies_add(skb, sdata); |
184 | } | 184 | } |
185 | 185 | ||
186 | /* Add Peer Link Management element */ | 186 | /* Add Peer Link Management element */ |
@@ -217,15 +217,14 @@ static int mesh_plink_frame_tx(struct net_device *dev, | |||
217 | memcpy(pos, &reason, 2); | 217 | memcpy(pos, &reason, 2); |
218 | } | 218 | } |
219 | 219 | ||
220 | ieee80211_sta_tx(dev, skb, 0); | 220 | ieee80211_tx_skb(sdata, skb, 0); |
221 | return 0; | 221 | return 0; |
222 | } | 222 | } |
223 | 223 | ||
224 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | 224 | void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data *sdata, |
225 | bool peer_accepting_plinks) | 225 | bool peer_accepting_plinks) |
226 | { | 226 | { |
227 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 227 | struct ieee80211_local *local = sdata->local; |
228 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
229 | struct sta_info *sta; | 228 | struct sta_info *sta; |
230 | 229 | ||
231 | rcu_read_lock(); | 230 | rcu_read_lock(); |
@@ -244,10 +243,10 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, | |||
244 | } | 243 | } |
245 | 244 | ||
246 | sta->last_rx = jiffies; | 245 | sta->last_rx = jiffies; |
247 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 246 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
248 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && | 247 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && |
249 | sdata->u.sta.accepting_plinks && | 248 | sdata->u.mesh.accepting_plinks && |
250 | sdata->u.sta.mshcfg.auto_open_plinks) | 249 | sdata->u.mesh.mshcfg.auto_open_plinks) |
251 | mesh_plink_open(sta); | 250 | mesh_plink_open(sta); |
252 | 251 | ||
253 | rcu_read_unlock(); | 252 | rcu_read_unlock(); |
@@ -257,7 +256,6 @@ static void mesh_plink_timer(unsigned long data) | |||
257 | { | 256 | { |
258 | struct sta_info *sta; | 257 | struct sta_info *sta; |
259 | __le16 llid, plid, reason; | 258 | __le16 llid, plid, reason; |
260 | struct net_device *dev = NULL; | ||
261 | struct ieee80211_sub_if_data *sdata; | 259 | struct ieee80211_sub_if_data *sdata; |
262 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 260 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
263 | DECLARE_MAC_BUF(mac); | 261 | DECLARE_MAC_BUF(mac); |
@@ -277,12 +275,11 @@ static void mesh_plink_timer(unsigned long data) | |||
277 | return; | 275 | return; |
278 | } | 276 | } |
279 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", | 277 | mpl_dbg("Mesh plink timer for %s fired on state %d\n", |
280 | print_mac(mac, sta->addr), sta->plink_state); | 278 | print_mac(mac, sta->sta.addr), sta->plink_state); |
281 | reason = 0; | 279 | reason = 0; |
282 | llid = sta->llid; | 280 | llid = sta->llid; |
283 | plid = sta->plid; | 281 | plid = sta->plid; |
284 | sdata = sta->sdata; | 282 | sdata = sta->sdata; |
285 | dev = sdata->dev; | ||
286 | 283 | ||
287 | switch (sta->plink_state) { | 284 | switch (sta->plink_state) { |
288 | case PLINK_OPN_RCVD: | 285 | case PLINK_OPN_RCVD: |
@@ -291,7 +288,7 @@ static void mesh_plink_timer(unsigned long data) | |||
291 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { | 288 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { |
292 | u32 rand; | 289 | u32 rand; |
293 | mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", | 290 | mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", |
294 | print_mac(mac, sta->addr), | 291 | print_mac(mac, sta->sta.addr), |
295 | sta->plink_retries, sta->plink_timeout); | 292 | sta->plink_retries, sta->plink_timeout); |
296 | get_random_bytes(&rand, sizeof(u32)); | 293 | get_random_bytes(&rand, sizeof(u32)); |
297 | sta->plink_timeout = sta->plink_timeout + | 294 | sta->plink_timeout = sta->plink_timeout + |
@@ -299,7 +296,7 @@ static void mesh_plink_timer(unsigned long data) | |||
299 | ++sta->plink_retries; | 296 | ++sta->plink_retries; |
300 | mod_plink_timer(sta, sta->plink_timeout); | 297 | mod_plink_timer(sta, sta->plink_timeout); |
301 | spin_unlock_bh(&sta->lock); | 298 | spin_unlock_bh(&sta->lock); |
302 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 299 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, |
303 | 0, 0); | 300 | 0, 0); |
304 | break; | 301 | break; |
305 | } | 302 | } |
@@ -312,7 +309,7 @@ static void mesh_plink_timer(unsigned long data) | |||
312 | sta->plink_state = PLINK_HOLDING; | 309 | sta->plink_state = PLINK_HOLDING; |
313 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 310 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
314 | spin_unlock_bh(&sta->lock); | 311 | spin_unlock_bh(&sta->lock); |
315 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, | 312 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, |
316 | reason); | 313 | reason); |
317 | break; | 314 | break; |
318 | case PLINK_HOLDING: | 315 | case PLINK_HOLDING: |
@@ -355,10 +352,10 @@ int mesh_plink_open(struct sta_info *sta) | |||
355 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 352 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
356 | spin_unlock_bh(&sta->lock); | 353 | spin_unlock_bh(&sta->lock); |
357 | mpl_dbg("Mesh plink: starting establishment with %s\n", | 354 | mpl_dbg("Mesh plink: starting establishment with %s\n", |
358 | print_mac(mac, sta->addr)); | 355 | print_mac(mac, sta->sta.addr)); |
359 | 356 | ||
360 | return mesh_plink_frame_tx(sdata->dev, PLINK_OPEN, | 357 | return mesh_plink_frame_tx(sdata, PLINK_OPEN, |
361 | sta->addr, llid, 0, 0); | 358 | sta->sta.addr, llid, 0, 0); |
362 | } | 359 | } |
363 | 360 | ||
364 | void mesh_plink_block(struct sta_info *sta) | 361 | void mesh_plink_block(struct sta_info *sta) |
@@ -382,7 +379,7 @@ int mesh_plink_close(struct sta_info *sta) | |||
382 | #endif | 379 | #endif |
383 | 380 | ||
384 | mpl_dbg("Mesh plink: closing link with %s\n", | 381 | mpl_dbg("Mesh plink: closing link with %s\n", |
385 | print_mac(mac, sta->addr)); | 382 | print_mac(mac, sta->sta.addr)); |
386 | spin_lock_bh(&sta->lock); | 383 | spin_lock_bh(&sta->lock); |
387 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); | 384 | sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); |
388 | reason = sta->reason; | 385 | reason = sta->reason; |
@@ -403,15 +400,14 @@ int mesh_plink_close(struct sta_info *sta) | |||
403 | llid = sta->llid; | 400 | llid = sta->llid; |
404 | plid = sta->plid; | 401 | plid = sta->plid; |
405 | spin_unlock_bh(&sta->lock); | 402 | spin_unlock_bh(&sta->lock); |
406 | mesh_plink_frame_tx(sta->sdata->dev, PLINK_CLOSE, sta->addr, llid, | 403 | mesh_plink_frame_tx(sta->sdata, PLINK_CLOSE, sta->sta.addr, llid, |
407 | plid, reason); | 404 | plid, reason); |
408 | return 0; | 405 | return 0; |
409 | } | 406 | } |
410 | 407 | ||
411 | void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | 408 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
412 | size_t len, struct ieee80211_rx_status *rx_status) | 409 | size_t len, struct ieee80211_rx_status *rx_status) |
413 | { | 410 | { |
414 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
415 | struct ieee80211_local *local = sdata->local; | 411 | struct ieee80211_local *local = sdata->local; |
416 | struct ieee802_11_elems elems; | 412 | struct ieee802_11_elems elems; |
417 | struct sta_info *sta; | 413 | struct sta_info *sta; |
@@ -425,6 +421,10 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
425 | DECLARE_MAC_BUF(mac); | 421 | DECLARE_MAC_BUF(mac); |
426 | #endif | 422 | #endif |
427 | 423 | ||
424 | /* need action_code, aux */ | ||
425 | if (len < IEEE80211_MIN_ACTION_SIZE + 3) | ||
426 | return; | ||
427 | |||
428 | if (is_multicast_ether_addr(mgmt->da)) { | 428 | if (is_multicast_ether_addr(mgmt->da)) { |
429 | mpl_dbg("Mesh plink: ignore frame from multicast address"); | 429 | mpl_dbg("Mesh plink: ignore frame from multicast address"); |
430 | return; | 430 | return; |
@@ -478,7 +478,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
478 | 478 | ||
479 | /* Now we will figure out the appropriate event... */ | 479 | /* Now we will figure out the appropriate event... */ |
480 | event = PLINK_UNDEFINED; | 480 | event = PLINK_UNDEFINED; |
481 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) { | 481 | if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { |
482 | switch (ftype) { | 482 | switch (ftype) { |
483 | case PLINK_OPEN: | 483 | case PLINK_OPEN: |
484 | event = OPN_RJCT; | 484 | event = OPN_RJCT; |
@@ -577,9 +577,9 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
577 | sta->llid = llid; | 577 | sta->llid = llid; |
578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 578 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
579 | spin_unlock_bh(&sta->lock); | 579 | spin_unlock_bh(&sta->lock); |
580 | mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, | 580 | mesh_plink_frame_tx(sdata, PLINK_OPEN, sta->sta.addr, llid, |
581 | 0, 0); | 581 | 0, 0); |
582 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, | 582 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, |
583 | llid, plid, 0); | 583 | llid, plid, 0); |
584 | break; | 584 | break; |
585 | default: | 585 | default: |
@@ -604,7 +604,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
604 | 604 | ||
605 | llid = sta->llid; | 605 | llid = sta->llid; |
606 | spin_unlock_bh(&sta->lock); | 606 | spin_unlock_bh(&sta->lock); |
607 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 607 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
608 | plid, reason); | 608 | plid, reason); |
609 | break; | 609 | break; |
610 | case OPN_ACPT: | 610 | case OPN_ACPT: |
@@ -613,7 +613,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
613 | sta->plid = plid; | 613 | sta->plid = plid; |
614 | llid = sta->llid; | 614 | llid = sta->llid; |
615 | spin_unlock_bh(&sta->lock); | 615 | spin_unlock_bh(&sta->lock); |
616 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 616 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
617 | plid, 0); | 617 | plid, 0); |
618 | break; | 618 | break; |
619 | case CNF_ACPT: | 619 | case CNF_ACPT: |
@@ -646,13 +646,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
646 | 646 | ||
647 | llid = sta->llid; | 647 | llid = sta->llid; |
648 | spin_unlock_bh(&sta->lock); | 648 | spin_unlock_bh(&sta->lock); |
649 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 649 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
650 | plid, reason); | 650 | plid, reason); |
651 | break; | 651 | break; |
652 | case OPN_ACPT: | 652 | case OPN_ACPT: |
653 | llid = sta->llid; | 653 | llid = sta->llid; |
654 | spin_unlock_bh(&sta->lock); | 654 | spin_unlock_bh(&sta->lock); |
655 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 655 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
656 | plid, 0); | 656 | plid, 0); |
657 | break; | 657 | break; |
658 | case CNF_ACPT: | 658 | case CNF_ACPT: |
@@ -661,7 +661,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
661 | mesh_plink_inc_estab_count(sdata); | 661 | mesh_plink_inc_estab_count(sdata); |
662 | spin_unlock_bh(&sta->lock); | 662 | spin_unlock_bh(&sta->lock); |
663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 663 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
664 | print_mac(mac, sta->addr)); | 664 | print_mac(mac, sta->sta.addr)); |
665 | break; | 665 | break; |
666 | default: | 666 | default: |
667 | spin_unlock_bh(&sta->lock); | 667 | spin_unlock_bh(&sta->lock); |
@@ -685,7 +685,7 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
685 | 685 | ||
686 | llid = sta->llid; | 686 | llid = sta->llid; |
687 | spin_unlock_bh(&sta->lock); | 687 | spin_unlock_bh(&sta->lock); |
688 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 688 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
689 | plid, reason); | 689 | plid, reason); |
690 | break; | 690 | break; |
691 | case OPN_ACPT: | 691 | case OPN_ACPT: |
@@ -694,8 +694,8 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
694 | mesh_plink_inc_estab_count(sdata); | 694 | mesh_plink_inc_estab_count(sdata); |
695 | spin_unlock_bh(&sta->lock); | 695 | spin_unlock_bh(&sta->lock); |
696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", | 696 | mpl_dbg("Mesh plink with %s ESTABLISHED\n", |
697 | print_mac(mac, sta->addr)); | 697 | print_mac(mac, sta->sta.addr)); |
698 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 698 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
699 | plid, 0); | 699 | plid, 0); |
700 | break; | 700 | break; |
701 | default: | 701 | default: |
@@ -714,13 +714,13 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
714 | llid = sta->llid; | 714 | llid = sta->llid; |
715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 715 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
716 | spin_unlock_bh(&sta->lock); | 716 | spin_unlock_bh(&sta->lock); |
717 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 717 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, |
718 | plid, reason); | 718 | plid, reason); |
719 | break; | 719 | break; |
720 | case OPN_ACPT: | 720 | case OPN_ACPT: |
721 | llid = sta->llid; | 721 | llid = sta->llid; |
722 | spin_unlock_bh(&sta->lock); | 722 | spin_unlock_bh(&sta->lock); |
723 | mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, | 723 | mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid, |
724 | plid, 0); | 724 | plid, 0); |
725 | break; | 725 | break; |
726 | default: | 726 | default: |
@@ -743,8 +743,8 @@ void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, | |||
743 | llid = sta->llid; | 743 | llid = sta->llid; |
744 | reason = sta->reason; | 744 | reason = sta->reason; |
745 | spin_unlock_bh(&sta->lock); | 745 | spin_unlock_bh(&sta->lock); |
746 | mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, | 746 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, |
747 | plid, reason); | 747 | llid, plid, reason); |
748 | break; | 748 | break; |
749 | default: | 749 | default: |
750 | spin_unlock_bh(&sta->lock); | 750 | spin_unlock_bh(&sta->lock); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9bb68c6a8f44..8611a8318c9c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -11,11 +11,6 @@ | |||
11 | * published by the Free Software Foundation. | 11 | * published by the Free Software Foundation. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | /* TODO: | ||
15 | * order BSS list by RSSI(?) ("quality of AP") | ||
16 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
17 | * SSID) | ||
18 | */ | ||
19 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
20 | #include <linux/if_ether.h> | 15 | #include <linux/if_ether.h> |
21 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
@@ -26,577 +21,184 @@ | |||
26 | #include <linux/etherdevice.h> | 21 | #include <linux/etherdevice.h> |
27 | #include <linux/rtnetlink.h> | 22 | #include <linux/rtnetlink.h> |
28 | #include <net/iw_handler.h> | 23 | #include <net/iw_handler.h> |
29 | #include <asm/types.h> | ||
30 | |||
31 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
25 | #include <asm/unaligned.h> | ||
26 | |||
32 | #include "ieee80211_i.h" | 27 | #include "ieee80211_i.h" |
33 | #include "rate.h" | 28 | #include "rate.h" |
34 | #include "led.h" | 29 | #include "led.h" |
35 | #include "mesh.h" | ||
36 | 30 | ||
31 | #define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 | ||
37 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 32 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
38 | #define IEEE80211_AUTH_MAX_TRIES 3 | 33 | #define IEEE80211_AUTH_MAX_TRIES 3 |
39 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 34 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
40 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 35 | #define IEEE80211_ASSOC_MAX_TRIES 3 |
41 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) | 36 | #define IEEE80211_MONITORING_INTERVAL (2 * HZ) |
42 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | ||
43 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) | 37 | #define IEEE80211_PROBE_INTERVAL (60 * HZ) |
44 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) | 38 | #define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) |
45 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) | 39 | #define IEEE80211_SCAN_INTERVAL (2 * HZ) |
46 | #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) | 40 | #define IEEE80211_SCAN_INTERVAL_SLOW (15 * HZ) |
47 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) | 41 | #define IEEE80211_IBSS_JOIN_TIMEOUT (7 * HZ) |
48 | 42 | ||
49 | #define IEEE80211_PROBE_DELAY (HZ / 33) | ||
50 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | ||
51 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | ||
52 | #define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ) | ||
53 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) | 43 | #define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) |
54 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) | 44 | #define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) |
55 | #define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ) | ||
56 | 45 | ||
57 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 | 46 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
58 | 47 | ||
59 | 48 | ||
60 | #define ERP_INFO_USE_PROTECTION BIT(1) | 49 | /* utils */ |
61 | |||
62 | /* mgmt header + 1 byte action code */ | ||
63 | #define IEEE80211_MIN_ACTION_SIZE (24 + 1) | ||
64 | |||
65 | #define IEEE80211_ADDBA_PARAM_POLICY_MASK 0x0002 | ||
66 | #define IEEE80211_ADDBA_PARAM_TID_MASK 0x003C | ||
67 | #define IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK 0xFFA0 | ||
68 | #define IEEE80211_DELBA_PARAM_TID_MASK 0xF000 | ||
69 | #define IEEE80211_DELBA_PARAM_INITIATOR_MASK 0x0800 | ||
70 | |||
71 | /* next values represent the buffer size for A-MPDU frame. | ||
72 | * According to IEEE802.11n spec size varies from 8K to 64K (in powers of 2) */ | ||
73 | #define IEEE80211_MIN_AMPDU_BUF 0x8 | ||
74 | #define IEEE80211_MAX_AMPDU_BUF 0x40 | ||
75 | |||
76 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | ||
77 | u8 *ssid, size_t ssid_len); | ||
78 | static struct ieee80211_sta_bss * | ||
79 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | ||
80 | u8 *ssid, u8 ssid_len); | ||
81 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
82 | struct ieee80211_sta_bss *bss); | ||
83 | static int ieee80211_sta_find_ibss(struct net_device *dev, | ||
84 | struct ieee80211_if_sta *ifsta); | ||
85 | static int ieee80211_sta_wep_configured(struct net_device *dev); | ||
86 | static int ieee80211_sta_start_scan(struct net_device *dev, | ||
87 | u8 *ssid, size_t ssid_len); | ||
88 | static int ieee80211_sta_config_auth(struct net_device *dev, | ||
89 | struct ieee80211_if_sta *ifsta); | ||
90 | static void sta_rx_agg_session_timer_expired(unsigned long data); | ||
91 | |||
92 | |||
93 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
94 | struct ieee802_11_elems *elems) | ||
95 | { | ||
96 | size_t left = len; | ||
97 | u8 *pos = start; | ||
98 | |||
99 | memset(elems, 0, sizeof(*elems)); | ||
100 | |||
101 | while (left >= 2) { | ||
102 | u8 id, elen; | ||
103 | |||
104 | id = *pos++; | ||
105 | elen = *pos++; | ||
106 | left -= 2; | ||
107 | |||
108 | if (elen > left) | ||
109 | return; | ||
110 | |||
111 | switch (id) { | ||
112 | case WLAN_EID_SSID: | ||
113 | elems->ssid = pos; | ||
114 | elems->ssid_len = elen; | ||
115 | break; | ||
116 | case WLAN_EID_SUPP_RATES: | ||
117 | elems->supp_rates = pos; | ||
118 | elems->supp_rates_len = elen; | ||
119 | break; | ||
120 | case WLAN_EID_FH_PARAMS: | ||
121 | elems->fh_params = pos; | ||
122 | elems->fh_params_len = elen; | ||
123 | break; | ||
124 | case WLAN_EID_DS_PARAMS: | ||
125 | elems->ds_params = pos; | ||
126 | elems->ds_params_len = elen; | ||
127 | break; | ||
128 | case WLAN_EID_CF_PARAMS: | ||
129 | elems->cf_params = pos; | ||
130 | elems->cf_params_len = elen; | ||
131 | break; | ||
132 | case WLAN_EID_TIM: | ||
133 | elems->tim = pos; | ||
134 | elems->tim_len = elen; | ||
135 | break; | ||
136 | case WLAN_EID_IBSS_PARAMS: | ||
137 | elems->ibss_params = pos; | ||
138 | elems->ibss_params_len = elen; | ||
139 | break; | ||
140 | case WLAN_EID_CHALLENGE: | ||
141 | elems->challenge = pos; | ||
142 | elems->challenge_len = elen; | ||
143 | break; | ||
144 | case WLAN_EID_WPA: | ||
145 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
146 | pos[2] == 0xf2) { | ||
147 | /* Microsoft OUI (00:50:F2) */ | ||
148 | if (pos[3] == 1) { | ||
149 | /* OUI Type 1 - WPA IE */ | ||
150 | elems->wpa = pos; | ||
151 | elems->wpa_len = elen; | ||
152 | } else if (elen >= 5 && pos[3] == 2) { | ||
153 | if (pos[4] == 0) { | ||
154 | elems->wmm_info = pos; | ||
155 | elems->wmm_info_len = elen; | ||
156 | } else if (pos[4] == 1) { | ||
157 | elems->wmm_param = pos; | ||
158 | elems->wmm_param_len = elen; | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | break; | ||
163 | case WLAN_EID_RSN: | ||
164 | elems->rsn = pos; | ||
165 | elems->rsn_len = elen; | ||
166 | break; | ||
167 | case WLAN_EID_ERP_INFO: | ||
168 | elems->erp_info = pos; | ||
169 | elems->erp_info_len = elen; | ||
170 | break; | ||
171 | case WLAN_EID_EXT_SUPP_RATES: | ||
172 | elems->ext_supp_rates = pos; | ||
173 | elems->ext_supp_rates_len = elen; | ||
174 | break; | ||
175 | case WLAN_EID_HT_CAPABILITY: | ||
176 | elems->ht_cap_elem = pos; | ||
177 | elems->ht_cap_elem_len = elen; | ||
178 | break; | ||
179 | case WLAN_EID_HT_EXTRA_INFO: | ||
180 | elems->ht_info_elem = pos; | ||
181 | elems->ht_info_elem_len = elen; | ||
182 | break; | ||
183 | case WLAN_EID_MESH_ID: | ||
184 | elems->mesh_id = pos; | ||
185 | elems->mesh_id_len = elen; | ||
186 | break; | ||
187 | case WLAN_EID_MESH_CONFIG: | ||
188 | elems->mesh_config = pos; | ||
189 | elems->mesh_config_len = elen; | ||
190 | break; | ||
191 | case WLAN_EID_PEER_LINK: | ||
192 | elems->peer_link = pos; | ||
193 | elems->peer_link_len = elen; | ||
194 | break; | ||
195 | case WLAN_EID_PREQ: | ||
196 | elems->preq = pos; | ||
197 | elems->preq_len = elen; | ||
198 | break; | ||
199 | case WLAN_EID_PREP: | ||
200 | elems->prep = pos; | ||
201 | elems->prep_len = elen; | ||
202 | break; | ||
203 | case WLAN_EID_PERR: | ||
204 | elems->perr = pos; | ||
205 | elems->perr_len = elen; | ||
206 | break; | ||
207 | case WLAN_EID_CHANNEL_SWITCH: | ||
208 | elems->ch_switch_elem = pos; | ||
209 | elems->ch_switch_elem_len = elen; | ||
210 | break; | ||
211 | case WLAN_EID_QUIET: | ||
212 | if (!elems->quiet_elem) { | ||
213 | elems->quiet_elem = pos; | ||
214 | elems->quiet_elem_len = elen; | ||
215 | } | ||
216 | elems->num_of_quiet_elem++; | ||
217 | break; | ||
218 | case WLAN_EID_COUNTRY: | ||
219 | elems->country_elem = pos; | ||
220 | elems->country_elem_len = elen; | ||
221 | break; | ||
222 | case WLAN_EID_PWR_CONSTRAINT: | ||
223 | elems->pwr_constr_elem = pos; | ||
224 | elems->pwr_constr_elem_len = elen; | ||
225 | break; | ||
226 | default: | ||
227 | break; | ||
228 | } | ||
229 | |||
230 | left -= elen; | ||
231 | pos += elen; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | |||
236 | static int ecw2cw(int ecw) | 50 | static int ecw2cw(int ecw) |
237 | { | 51 | { |
238 | return (1 << ecw) - 1; | 52 | return (1 << ecw) - 1; |
239 | } | 53 | } |
240 | 54 | ||
241 | 55 | static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie) | |
242 | static void ieee80211_sta_def_wmm_params(struct net_device *dev, | ||
243 | struct ieee80211_sta_bss *bss, | ||
244 | int ibss) | ||
245 | { | 56 | { |
246 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 57 | u8 *end, *pos; |
247 | struct ieee80211_local *local = sdata->local; | ||
248 | int i, have_higher_than_11mbit = 0; | ||
249 | |||
250 | 58 | ||
251 | /* cf. IEEE 802.11 9.2.12 */ | 59 | pos = bss->ies; |
252 | for (i = 0; i < bss->supp_rates_len; i++) | 60 | if (pos == NULL) |
253 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) | 61 | return NULL; |
254 | have_higher_than_11mbit = 1; | 62 | end = pos + bss->ies_len; |
255 | |||
256 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
257 | have_higher_than_11mbit) | ||
258 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
259 | else | ||
260 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
261 | |||
262 | |||
263 | if (local->ops->conf_tx) { | ||
264 | struct ieee80211_tx_queue_params qparam; | ||
265 | |||
266 | memset(&qparam, 0, sizeof(qparam)); | ||
267 | |||
268 | qparam.aifs = 2; | ||
269 | |||
270 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
271 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
272 | qparam.cw_min = 31; | ||
273 | else | ||
274 | qparam.cw_min = 15; | ||
275 | |||
276 | qparam.cw_max = 1023; | ||
277 | qparam.txop = 0; | ||
278 | |||
279 | for (i = 0; i < local_to_hw(local)->queues; i++) | ||
280 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void ieee80211_sta_wmm_params(struct net_device *dev, | ||
285 | struct ieee80211_if_sta *ifsta, | ||
286 | u8 *wmm_param, size_t wmm_param_len) | ||
287 | { | ||
288 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
289 | struct ieee80211_tx_queue_params params; | ||
290 | size_t left; | ||
291 | int count; | ||
292 | u8 *pos; | ||
293 | |||
294 | if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) | ||
295 | return; | ||
296 | |||
297 | if (!wmm_param) | ||
298 | return; | ||
299 | |||
300 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) | ||
301 | return; | ||
302 | count = wmm_param[6] & 0x0f; | ||
303 | if (count == ifsta->wmm_last_param_set) | ||
304 | return; | ||
305 | ifsta->wmm_last_param_set = count; | ||
306 | |||
307 | pos = wmm_param + 8; | ||
308 | left = wmm_param_len - 8; | ||
309 | |||
310 | memset(¶ms, 0, sizeof(params)); | ||
311 | |||
312 | if (!local->ops->conf_tx) | ||
313 | return; | ||
314 | |||
315 | local->wmm_acm = 0; | ||
316 | for (; left >= 4; left -= 4, pos += 4) { | ||
317 | int aci = (pos[0] >> 5) & 0x03; | ||
318 | int acm = (pos[0] >> 4) & 0x01; | ||
319 | int queue; | ||
320 | 63 | ||
321 | switch (aci) { | 64 | while (pos + 1 < end) { |
322 | case 1: | 65 | if (pos + 2 + pos[1] > end) |
323 | queue = 3; | ||
324 | if (acm) | ||
325 | local->wmm_acm |= BIT(0) | BIT(3); | ||
326 | break; | ||
327 | case 2: | ||
328 | queue = 1; | ||
329 | if (acm) | ||
330 | local->wmm_acm |= BIT(4) | BIT(5); | ||
331 | break; | ||
332 | case 3: | ||
333 | queue = 0; | ||
334 | if (acm) | ||
335 | local->wmm_acm |= BIT(6) | BIT(7); | ||
336 | break; | 66 | break; |
337 | case 0: | 67 | if (pos[0] == ie) |
338 | default: | 68 | return pos; |
339 | queue = 2; | 69 | pos += 2 + pos[1]; |
340 | if (acm) | ||
341 | local->wmm_acm |= BIT(1) | BIT(2); | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | params.aifs = pos[0] & 0x0f; | ||
346 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | ||
347 | params.cw_min = ecw2cw(pos[1] & 0x0f); | ||
348 | params.txop = get_unaligned_le16(pos + 2); | ||
349 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
350 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | ||
351 | "cWmin=%d cWmax=%d txop=%d\n", | ||
352 | dev->name, queue, aci, acm, params.aifs, params.cw_min, | ||
353 | params.cw_max, params.txop); | ||
354 | #endif | ||
355 | /* TODO: handle ACM (block TX, fallback to next lowest allowed | ||
356 | * AC for now) */ | ||
357 | if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
358 | printk(KERN_DEBUG "%s: failed to set TX queue " | ||
359 | "parameters for queue %d\n", dev->name, queue); | ||
360 | } | ||
361 | } | 70 | } |
362 | } | ||
363 | 71 | ||
364 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | 72 | return NULL; |
365 | bool use_protection, | ||
366 | bool use_short_preamble) | ||
367 | { | ||
368 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | ||
369 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
370 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
371 | DECLARE_MAC_BUF(mac); | ||
372 | #endif | ||
373 | u32 changed = 0; | ||
374 | |||
375 | if (use_protection != bss_conf->use_cts_prot) { | ||
376 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
377 | if (net_ratelimit()) { | ||
378 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | ||
379 | "%s)\n", | ||
380 | sdata->dev->name, | ||
381 | use_protection ? "enabled" : "disabled", | ||
382 | print_mac(mac, ifsta->bssid)); | ||
383 | } | ||
384 | #endif | ||
385 | bss_conf->use_cts_prot = use_protection; | ||
386 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
387 | } | ||
388 | |||
389 | if (use_short_preamble != bss_conf->use_short_preamble) { | ||
390 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
391 | if (net_ratelimit()) { | ||
392 | printk(KERN_DEBUG "%s: switched to %s barker preamble" | ||
393 | " (BSSID=%s)\n", | ||
394 | sdata->dev->name, | ||
395 | use_short_preamble ? "short" : "long", | ||
396 | print_mac(mac, ifsta->bssid)); | ||
397 | } | ||
398 | #endif | ||
399 | bss_conf->use_short_preamble = use_short_preamble; | ||
400 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
401 | } | ||
402 | |||
403 | return changed; | ||
404 | } | 73 | } |
405 | 74 | ||
406 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | 75 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, |
407 | u8 erp_value) | 76 | struct ieee80211_supported_band *sband, |
408 | { | 77 | u64 *rates) |
409 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | ||
410 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; | ||
411 | |||
412 | return ieee80211_handle_protect_preamb(sdata, | ||
413 | use_protection, use_short_preamble); | ||
414 | } | ||
415 | |||
416 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | ||
417 | struct ieee80211_sta_bss *bss) | ||
418 | { | ||
419 | u32 changed = 0; | ||
420 | |||
421 | if (bss->has_erp_value) | ||
422 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); | ||
423 | else { | ||
424 | u16 capab = bss->capability; | ||
425 | changed |= ieee80211_handle_protect_preamb(sdata, false, | ||
426 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | ||
427 | } | ||
428 | |||
429 | return changed; | ||
430 | } | ||
431 | |||
432 | int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, | ||
433 | struct ieee80211_ht_info *ht_info) | ||
434 | { | ||
435 | |||
436 | if (ht_info == NULL) | ||
437 | return -EINVAL; | ||
438 | |||
439 | memset(ht_info, 0, sizeof(*ht_info)); | ||
440 | |||
441 | if (ht_cap_ie) { | ||
442 | u8 ampdu_info = ht_cap_ie->ampdu_params_info; | ||
443 | |||
444 | ht_info->ht_supported = 1; | ||
445 | ht_info->cap = le16_to_cpu(ht_cap_ie->cap_info); | ||
446 | ht_info->ampdu_factor = | ||
447 | ampdu_info & IEEE80211_HT_CAP_AMPDU_FACTOR; | ||
448 | ht_info->ampdu_density = | ||
449 | (ampdu_info & IEEE80211_HT_CAP_AMPDU_DENSITY) >> 2; | ||
450 | memcpy(ht_info->supp_mcs_set, ht_cap_ie->supp_mcs_set, 16); | ||
451 | } else | ||
452 | ht_info->ht_supported = 0; | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | int ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
458 | struct ieee80211_ht_addt_info *ht_add_info_ie, | ||
459 | struct ieee80211_ht_bss_info *bss_info) | ||
460 | { | 78 | { |
461 | if (bss_info == NULL) | 79 | int i, j, count; |
462 | return -EINVAL; | 80 | *rates = 0; |
463 | 81 | count = 0; | |
464 | memset(bss_info, 0, sizeof(*bss_info)); | 82 | for (i = 0; i < bss->supp_rates_len; i++) { |
465 | 83 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | |
466 | if (ht_add_info_ie) { | ||
467 | u16 op_mode; | ||
468 | op_mode = le16_to_cpu(ht_add_info_ie->operation_mode); | ||
469 | 84 | ||
470 | bss_info->primary_channel = ht_add_info_ie->control_chan; | 85 | for (j = 0; j < sband->n_bitrates; j++) |
471 | bss_info->bss_cap = ht_add_info_ie->ht_param; | 86 | if (sband->bitrates[j].bitrate == rate) { |
472 | bss_info->bss_op_mode = (u8)(op_mode & 0xff); | 87 | *rates |= BIT(j); |
88 | count++; | ||
89 | break; | ||
90 | } | ||
473 | } | 91 | } |
474 | 92 | ||
475 | return 0; | 93 | return count; |
476 | } | 94 | } |
477 | 95 | ||
478 | static void ieee80211_sta_send_associnfo(struct net_device *dev, | 96 | /* also used by mesh code */ |
479 | struct ieee80211_if_sta *ifsta) | 97 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
98 | struct ieee802_11_elems *elems, | ||
99 | enum ieee80211_band band) | ||
480 | { | 100 | { |
481 | union iwreq_data wrqu; | 101 | struct ieee80211_supported_band *sband; |
102 | struct ieee80211_rate *bitrates; | ||
103 | size_t num_rates; | ||
104 | u64 supp_rates; | ||
105 | int i, j; | ||
106 | sband = local->hw.wiphy->bands[band]; | ||
482 | 107 | ||
483 | if (ifsta->assocreq_ies) { | 108 | if (!sband) { |
484 | memset(&wrqu, 0, sizeof(wrqu)); | 109 | WARN_ON(1); |
485 | wrqu.data.length = ifsta->assocreq_ies_len; | 110 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
486 | wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, | ||
487 | ifsta->assocreq_ies); | ||
488 | } | 111 | } |
489 | 112 | ||
490 | if (ifsta->assocresp_ies) { | 113 | bitrates = sband->bitrates; |
491 | memset(&wrqu, 0, sizeof(wrqu)); | 114 | num_rates = sband->n_bitrates; |
492 | wrqu.data.length = ifsta->assocresp_ies_len; | 115 | supp_rates = 0; |
493 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, | 116 | for (i = 0; i < elems->supp_rates_len + |
494 | ifsta->assocresp_ies); | 117 | elems->ext_supp_rates_len; i++) { |
118 | u8 rate = 0; | ||
119 | int own_rate; | ||
120 | if (i < elems->supp_rates_len) | ||
121 | rate = elems->supp_rates[i]; | ||
122 | else if (elems->ext_supp_rates) | ||
123 | rate = elems->ext_supp_rates | ||
124 | [i - elems->supp_rates_len]; | ||
125 | own_rate = 5 * (rate & 0x7f); | ||
126 | for (j = 0; j < num_rates; j++) | ||
127 | if (bitrates[j].bitrate == own_rate) | ||
128 | supp_rates |= BIT(j); | ||
495 | } | 129 | } |
130 | return supp_rates; | ||
496 | } | 131 | } |
497 | 132 | ||
133 | /* frame sending functions */ | ||
498 | 134 | ||
499 | static void ieee80211_set_associated(struct net_device *dev, | 135 | /* also used by scanning code */ |
500 | struct ieee80211_if_sta *ifsta, | 136 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
501 | bool assoc) | 137 | u8 *ssid, size_t ssid_len) |
502 | { | 138 | { |
503 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
504 | struct ieee80211_local *local = sdata->local; | 139 | struct ieee80211_local *local = sdata->local; |
505 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; | 140 | struct ieee80211_supported_band *sband; |
506 | union iwreq_data wrqu; | 141 | struct sk_buff *skb; |
507 | u32 changed = BSS_CHANGED_ASSOC; | 142 | struct ieee80211_mgmt *mgmt; |
508 | 143 | u8 *pos, *supp_rates, *esupp_rates = NULL; | |
509 | if (assoc) { | 144 | int i; |
510 | struct ieee80211_sta_bss *bss; | ||
511 | |||
512 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; | ||
513 | |||
514 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
515 | return; | ||
516 | |||
517 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | ||
518 | conf->channel->center_freq, | ||
519 | ifsta->ssid, ifsta->ssid_len); | ||
520 | if (bss) { | ||
521 | /* set timing information */ | ||
522 | sdata->bss_conf.beacon_int = bss->beacon_int; | ||
523 | sdata->bss_conf.timestamp = bss->timestamp; | ||
524 | sdata->bss_conf.dtim_period = bss->dtim_period; | ||
525 | |||
526 | changed |= ieee80211_handle_bss_capability(sdata, bss); | ||
527 | |||
528 | ieee80211_rx_bss_put(local, bss); | ||
529 | } | ||
530 | 145 | ||
531 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 146 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); |
532 | changed |= BSS_CHANGED_HT; | 147 | if (!skb) { |
533 | sdata->bss_conf.assoc_ht = 1; | 148 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " |
534 | sdata->bss_conf.ht_conf = &conf->ht_conf; | 149 | "request\n", sdata->dev->name); |
535 | sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; | 150 | return; |
536 | } | 151 | } |
152 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
537 | 153 | ||
538 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; | 154 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
539 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); | 155 | memset(mgmt, 0, 24); |
540 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); | 156 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
541 | ieee80211_sta_send_associnfo(dev, ifsta); | 157 | IEEE80211_STYPE_PROBE_REQ); |
158 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
159 | if (dst) { | ||
160 | memcpy(mgmt->da, dst, ETH_ALEN); | ||
161 | memcpy(mgmt->bssid, dst, ETH_ALEN); | ||
542 | } else { | 162 | } else { |
543 | netif_carrier_off(dev); | 163 | memset(mgmt->da, 0xff, ETH_ALEN); |
544 | ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); | 164 | memset(mgmt->bssid, 0xff, ETH_ALEN); |
545 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | ||
546 | changed |= ieee80211_reset_erp_info(dev); | ||
547 | |||
548 | sdata->bss_conf.assoc_ht = 0; | ||
549 | sdata->bss_conf.ht_conf = NULL; | ||
550 | sdata->bss_conf.ht_bss_conf = NULL; | ||
551 | |||
552 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | ||
553 | } | 165 | } |
554 | ifsta->last_probe = jiffies; | 166 | pos = skb_put(skb, 2 + ssid_len); |
555 | ieee80211_led_assoc(local, assoc); | 167 | *pos++ = WLAN_EID_SSID; |
556 | 168 | *pos++ = ssid_len; | |
557 | sdata->bss_conf.assoc = assoc; | 169 | memcpy(pos, ssid, ssid_len); |
558 | ieee80211_bss_info_change_notify(sdata, changed); | ||
559 | |||
560 | if (assoc) | ||
561 | netif_carrier_on(dev); | ||
562 | |||
563 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
564 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | ||
565 | } | ||
566 | |||
567 | static void ieee80211_set_disassoc(struct net_device *dev, | ||
568 | struct ieee80211_if_sta *ifsta, int deauth) | ||
569 | { | ||
570 | if (deauth) | ||
571 | ifsta->auth_tries = 0; | ||
572 | ifsta->assoc_tries = 0; | ||
573 | ieee80211_set_associated(dev, ifsta, 0); | ||
574 | } | ||
575 | |||
576 | void ieee80211_sta_tx(struct net_device *dev, struct sk_buff *skb, | ||
577 | int encrypt) | ||
578 | { | ||
579 | struct ieee80211_sub_if_data *sdata; | ||
580 | 170 | ||
581 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 171 | supp_rates = skb_put(skb, 2); |
582 | skb->dev = sdata->local->mdev; | 172 | supp_rates[0] = WLAN_EID_SUPP_RATES; |
583 | skb_set_mac_header(skb, 0); | 173 | supp_rates[1] = 0; |
584 | skb_set_network_header(skb, 0); | 174 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
585 | skb_set_transport_header(skb, 0); | ||
586 | 175 | ||
587 | skb->iif = sdata->dev->ifindex; | 176 | for (i = 0; i < sband->n_bitrates; i++) { |
588 | skb->do_not_encrypt = !encrypt; | 177 | struct ieee80211_rate *rate = &sband->bitrates[i]; |
178 | if (esupp_rates) { | ||
179 | pos = skb_put(skb, 1); | ||
180 | esupp_rates[1]++; | ||
181 | } else if (supp_rates[1] == 8) { | ||
182 | esupp_rates = skb_put(skb, 3); | ||
183 | esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; | ||
184 | esupp_rates[1] = 1; | ||
185 | pos = &esupp_rates[2]; | ||
186 | } else { | ||
187 | pos = skb_put(skb, 1); | ||
188 | supp_rates[1]++; | ||
189 | } | ||
190 | *pos = rate->bitrate / 5; | ||
191 | } | ||
589 | 192 | ||
590 | dev_queue_xmit(skb); | 193 | ieee80211_tx_skb(sdata, skb, 0); |
591 | } | 194 | } |
592 | 195 | ||
593 | 196 | static void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |
594 | static void ieee80211_send_auth(struct net_device *dev, | ||
595 | struct ieee80211_if_sta *ifsta, | 197 | struct ieee80211_if_sta *ifsta, |
596 | int transaction, u8 *extra, size_t extra_len, | 198 | int transaction, u8 *extra, size_t extra_len, |
597 | int encrypt) | 199 | int encrypt) |
598 | { | 200 | { |
599 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 201 | struct ieee80211_local *local = sdata->local; |
600 | struct sk_buff *skb; | 202 | struct sk_buff *skb; |
601 | struct ieee80211_mgmt *mgmt; | 203 | struct ieee80211_mgmt *mgmt; |
602 | 204 | ||
@@ -604,19 +206,19 @@ static void ieee80211_send_auth(struct net_device *dev, | |||
604 | sizeof(*mgmt) + 6 + extra_len); | 206 | sizeof(*mgmt) + 6 + extra_len); |
605 | if (!skb) { | 207 | if (!skb) { |
606 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " | 208 | printk(KERN_DEBUG "%s: failed to allocate buffer for auth " |
607 | "frame\n", dev->name); | 209 | "frame\n", sdata->dev->name); |
608 | return; | 210 | return; |
609 | } | 211 | } |
610 | skb_reserve(skb, local->hw.extra_tx_headroom); | 212 | skb_reserve(skb, local->hw.extra_tx_headroom); |
611 | 213 | ||
612 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); | 214 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6); |
613 | memset(mgmt, 0, 24 + 6); | 215 | memset(mgmt, 0, 24 + 6); |
614 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 216 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
615 | IEEE80211_STYPE_AUTH); | 217 | IEEE80211_STYPE_AUTH); |
616 | if (encrypt) | 218 | if (encrypt) |
617 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); | 219 | mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
618 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 220 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
619 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 221 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
620 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 222 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
621 | mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); | 223 | mgmt->u.auth.auth_alg = cpu_to_le16(ifsta->auth_alg); |
622 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); | 224 | mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); |
@@ -625,64 +227,19 @@ static void ieee80211_send_auth(struct net_device *dev, | |||
625 | if (extra) | 227 | if (extra) |
626 | memcpy(skb_put(skb, extra_len), extra, extra_len); | 228 | memcpy(skb_put(skb, extra_len), extra, extra_len); |
627 | 229 | ||
628 | ieee80211_sta_tx(dev, skb, encrypt); | 230 | ieee80211_tx_skb(sdata, skb, encrypt); |
629 | } | ||
630 | |||
631 | |||
632 | static void ieee80211_authenticate(struct net_device *dev, | ||
633 | struct ieee80211_if_sta *ifsta) | ||
634 | { | ||
635 | DECLARE_MAC_BUF(mac); | ||
636 | |||
637 | ifsta->auth_tries++; | ||
638 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | ||
639 | printk(KERN_DEBUG "%s: authentication with AP %s" | ||
640 | " timed out\n", | ||
641 | dev->name, print_mac(mac, ifsta->bssid)); | ||
642 | ifsta->state = IEEE80211_DISABLED; | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
647 | printk(KERN_DEBUG "%s: authenticate with AP %s\n", | ||
648 | dev->name, print_mac(mac, ifsta->bssid)); | ||
649 | |||
650 | ieee80211_send_auth(dev, ifsta, 1, NULL, 0, 0); | ||
651 | |||
652 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | ||
653 | } | 231 | } |
654 | 232 | ||
655 | static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, | 233 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, |
656 | struct ieee80211_supported_band *sband, | ||
657 | u64 *rates) | ||
658 | { | ||
659 | int i, j, count; | ||
660 | *rates = 0; | ||
661 | count = 0; | ||
662 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
663 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
664 | |||
665 | for (j = 0; j < sband->n_bitrates; j++) | ||
666 | if (sband->bitrates[j].bitrate == rate) { | ||
667 | *rates |= BIT(j); | ||
668 | count++; | ||
669 | break; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | return count; | ||
674 | } | ||
675 | |||
676 | static void ieee80211_send_assoc(struct net_device *dev, | ||
677 | struct ieee80211_if_sta *ifsta) | 234 | struct ieee80211_if_sta *ifsta) |
678 | { | 235 | { |
679 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 236 | struct ieee80211_local *local = sdata->local; |
680 | struct sk_buff *skb; | 237 | struct sk_buff *skb; |
681 | struct ieee80211_mgmt *mgmt; | 238 | struct ieee80211_mgmt *mgmt; |
682 | u8 *pos, *ies; | 239 | u8 *pos, *ies, *ht_add_ie; |
683 | int i, len, count, rates_len, supp_rates_len; | 240 | int i, len, count, rates_len, supp_rates_len; |
684 | u16 capab; | 241 | u16 capab; |
685 | struct ieee80211_sta_bss *bss; | 242 | struct ieee80211_bss *bss; |
686 | int wmm = 0; | 243 | int wmm = 0; |
687 | struct ieee80211_supported_band *sband; | 244 | struct ieee80211_supported_band *sband; |
688 | u64 rates = 0; | 245 | u64 rates = 0; |
@@ -692,7 +249,7 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
692 | ifsta->ssid_len); | 249 | ifsta->ssid_len); |
693 | if (!skb) { | 250 | if (!skb) { |
694 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | 251 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " |
695 | "frame\n", dev->name); | 252 | "frame\n", sdata->dev->name); |
696 | return; | 253 | return; |
697 | } | 254 | } |
698 | skb_reserve(skb, local->hw.extra_tx_headroom); | 255 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -708,13 +265,13 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
708 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | 265 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; |
709 | } | 266 | } |
710 | 267 | ||
711 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 268 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
712 | local->hw.conf.channel->center_freq, | 269 | local->hw.conf.channel->center_freq, |
713 | ifsta->ssid, ifsta->ssid_len); | 270 | ifsta->ssid, ifsta->ssid_len); |
714 | if (bss) { | 271 | if (bss) { |
715 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | 272 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) |
716 | capab |= WLAN_CAPABILITY_PRIVACY; | 273 | capab |= WLAN_CAPABILITY_PRIVACY; |
717 | if (bss->wmm_ie) | 274 | if (bss->wmm_used) |
718 | wmm = 1; | 275 | wmm = 1; |
719 | 276 | ||
720 | /* get all rates supported by the device and the AP as | 277 | /* get all rates supported by the device and the AP as |
@@ -736,13 +293,13 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
736 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 293 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
737 | memset(mgmt, 0, 24); | 294 | memset(mgmt, 0, 24); |
738 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 295 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
739 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 296 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
740 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 297 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
741 | 298 | ||
742 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { | 299 | if (ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) { |
743 | skb_put(skb, 10); | 300 | skb_put(skb, 10); |
744 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 301 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
745 | IEEE80211_STYPE_REASSOC_REQ); | 302 | IEEE80211_STYPE_REASSOC_REQ); |
746 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | 303 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); |
747 | mgmt->u.reassoc_req.listen_interval = | 304 | mgmt->u.reassoc_req.listen_interval = |
748 | cpu_to_le16(local->hw.conf.listen_interval); | 305 | cpu_to_le16(local->hw.conf.listen_interval); |
@@ -750,8 +307,8 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
750 | ETH_ALEN); | 307 | ETH_ALEN); |
751 | } else { | 308 | } else { |
752 | skb_put(skb, 4); | 309 | skb_put(skb, 4); |
753 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 310 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
754 | IEEE80211_STYPE_ASSOC_REQ); | 311 | IEEE80211_STYPE_ASSOC_REQ); |
755 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | 312 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); |
756 | mgmt->u.reassoc_req.listen_interval = | 313 | mgmt->u.reassoc_req.listen_interval = |
757 | cpu_to_le16(local->hw.conf.listen_interval); | 314 | cpu_to_le16(local->hw.conf.listen_interval); |
@@ -836,9 +393,10 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
836 | 393 | ||
837 | /* wmm support is a must to HT */ | 394 | /* wmm support is a must to HT */ |
838 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && | 395 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
839 | sband->ht_info.ht_supported && bss->ht_add_ie) { | 396 | sband->ht_info.ht_supported && |
397 | (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { | ||
840 | struct ieee80211_ht_addt_info *ht_add_info = | 398 | struct ieee80211_ht_addt_info *ht_add_info = |
841 | (struct ieee80211_ht_addt_info *)bss->ht_add_ie; | 399 | (struct ieee80211_ht_addt_info *)ht_add_ie; |
842 | u16 cap = sband->ht_info.cap; | 400 | u16 cap = sband->ht_info.cap; |
843 | __le16 tmp; | 401 | __le16 tmp; |
844 | u32 flags = local->hw.conf.channel->flags; | 402 | u32 flags = local->hw.conf.channel->flags; |
@@ -877,21 +435,22 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
877 | if (ifsta->assocreq_ies) | 435 | if (ifsta->assocreq_ies) |
878 | memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); | 436 | memcpy(ifsta->assocreq_ies, ies, ifsta->assocreq_ies_len); |
879 | 437 | ||
880 | ieee80211_sta_tx(dev, skb, 0); | 438 | ieee80211_tx_skb(sdata, skb, 0); |
881 | } | 439 | } |
882 | 440 | ||
883 | 441 | ||
884 | static void ieee80211_send_deauth(struct net_device *dev, | 442 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
885 | struct ieee80211_if_sta *ifsta, u16 reason) | 443 | u16 stype, u16 reason) |
886 | { | 444 | { |
887 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 445 | struct ieee80211_local *local = sdata->local; |
446 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
888 | struct sk_buff *skb; | 447 | struct sk_buff *skb; |
889 | struct ieee80211_mgmt *mgmt; | 448 | struct ieee80211_mgmt *mgmt; |
890 | 449 | ||
891 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 450 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); |
892 | if (!skb) { | 451 | if (!skb) { |
893 | printk(KERN_DEBUG "%s: failed to allocate buffer for deauth " | 452 | printk(KERN_DEBUG "%s: failed to allocate buffer for " |
894 | "frame\n", dev->name); | 453 | "deauth/disassoc frame\n", sdata->dev->name); |
895 | return; | 454 | return; |
896 | } | 455 | } |
897 | skb_reserve(skb, local->hw.extra_tx_headroom); | 456 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -899,940 +458,561 @@ static void ieee80211_send_deauth(struct net_device *dev, | |||
899 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 458 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
900 | memset(mgmt, 0, 24); | 459 | memset(mgmt, 0, 24); |
901 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 460 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); |
902 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 461 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
903 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 462 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
904 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 463 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); |
905 | IEEE80211_STYPE_DEAUTH); | ||
906 | skb_put(skb, 2); | 464 | skb_put(skb, 2); |
465 | /* u.deauth.reason_code == u.disassoc.reason_code */ | ||
907 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); | 466 | mgmt->u.deauth.reason_code = cpu_to_le16(reason); |
908 | 467 | ||
909 | ieee80211_sta_tx(dev, skb, 0); | 468 | ieee80211_tx_skb(sdata, skb, 0); |
910 | } | 469 | } |
911 | 470 | ||
912 | 471 | /* MLME */ | |
913 | static void ieee80211_send_disassoc(struct net_device *dev, | 472 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
914 | struct ieee80211_if_sta *ifsta, u16 reason) | 473 | struct ieee80211_bss *bss) |
915 | { | 474 | { |
916 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 475 | struct ieee80211_local *local = sdata->local; |
917 | struct sk_buff *skb; | 476 | int i, have_higher_than_11mbit = 0; |
918 | struct ieee80211_mgmt *mgmt; | ||
919 | 477 | ||
920 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt)); | 478 | /* cf. IEEE 802.11 9.2.12 */ |
921 | if (!skb) { | 479 | for (i = 0; i < bss->supp_rates_len; i++) |
922 | printk(KERN_DEBUG "%s: failed to allocate buffer for disassoc " | 480 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) |
923 | "frame\n", dev->name); | 481 | have_higher_than_11mbit = 1; |
924 | return; | ||
925 | } | ||
926 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
927 | 482 | ||
928 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 483 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
929 | memset(mgmt, 0, 24); | 484 | have_higher_than_11mbit) |
930 | memcpy(mgmt->da, ifsta->bssid, ETH_ALEN); | 485 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
931 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 486 | else |
932 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 487 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
933 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
934 | IEEE80211_STYPE_DISASSOC); | ||
935 | skb_put(skb, 2); | ||
936 | mgmt->u.disassoc.reason_code = cpu_to_le16(reason); | ||
937 | 488 | ||
938 | ieee80211_sta_tx(dev, skb, 0); | 489 | ieee80211_set_wmm_default(sdata); |
939 | } | 490 | } |
940 | 491 | ||
941 | 492 | static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |
942 | static int ieee80211_privacy_mismatch(struct net_device *dev, | 493 | struct ieee80211_if_sta *ifsta, |
943 | struct ieee80211_if_sta *ifsta) | 494 | u8 *wmm_param, size_t wmm_param_len) |
944 | { | 495 | { |
945 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 496 | struct ieee80211_tx_queue_params params; |
946 | struct ieee80211_sta_bss *bss; | 497 | size_t left; |
947 | int bss_privacy; | 498 | int count; |
948 | int wep_privacy; | 499 | u8 *pos; |
949 | int privacy_invoked; | ||
950 | |||
951 | if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) | ||
952 | return 0; | ||
953 | |||
954 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | ||
955 | local->hw.conf.channel->center_freq, | ||
956 | ifsta->ssid, ifsta->ssid_len); | ||
957 | if (!bss) | ||
958 | return 0; | ||
959 | |||
960 | bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); | ||
961 | wep_privacy = !!ieee80211_sta_wep_configured(dev); | ||
962 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | ||
963 | 500 | ||
964 | ieee80211_rx_bss_put(local, bss); | 501 | if (!(ifsta->flags & IEEE80211_STA_WMM_ENABLED)) |
502 | return; | ||
965 | 503 | ||
966 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) | 504 | if (!wmm_param) |
967 | return 0; | 505 | return; |
968 | 506 | ||
969 | return 1; | 507 | if (wmm_param_len < 8 || wmm_param[5] /* version */ != 1) |
970 | } | 508 | return; |
509 | count = wmm_param[6] & 0x0f; | ||
510 | if (count == ifsta->wmm_last_param_set) | ||
511 | return; | ||
512 | ifsta->wmm_last_param_set = count; | ||
971 | 513 | ||
514 | pos = wmm_param + 8; | ||
515 | left = wmm_param_len - 8; | ||
972 | 516 | ||
973 | static void ieee80211_associate(struct net_device *dev, | 517 | memset(¶ms, 0, sizeof(params)); |
974 | struct ieee80211_if_sta *ifsta) | ||
975 | { | ||
976 | DECLARE_MAC_BUF(mac); | ||
977 | 518 | ||
978 | ifsta->assoc_tries++; | 519 | if (!local->ops->conf_tx) |
979 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
980 | printk(KERN_DEBUG "%s: association with AP %s" | ||
981 | " timed out\n", | ||
982 | dev->name, print_mac(mac, ifsta->bssid)); | ||
983 | ifsta->state = IEEE80211_DISABLED; | ||
984 | return; | 520 | return; |
985 | } | ||
986 | 521 | ||
987 | ifsta->state = IEEE80211_ASSOCIATE; | 522 | local->wmm_acm = 0; |
988 | printk(KERN_DEBUG "%s: associate with AP %s\n", | 523 | for (; left >= 4; left -= 4, pos += 4) { |
989 | dev->name, print_mac(mac, ifsta->bssid)); | 524 | int aci = (pos[0] >> 5) & 0x03; |
990 | if (ieee80211_privacy_mismatch(dev, ifsta)) { | 525 | int acm = (pos[0] >> 4) & 0x01; |
991 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " | 526 | int queue; |
992 | "mixed-cell disabled - abort association\n", dev->name); | ||
993 | ifsta->state = IEEE80211_DISABLED; | ||
994 | return; | ||
995 | } | ||
996 | 527 | ||
997 | ieee80211_send_assoc(dev, ifsta); | 528 | switch (aci) { |
529 | case 1: | ||
530 | queue = 3; | ||
531 | if (acm) | ||
532 | local->wmm_acm |= BIT(0) | BIT(3); | ||
533 | break; | ||
534 | case 2: | ||
535 | queue = 1; | ||
536 | if (acm) | ||
537 | local->wmm_acm |= BIT(4) | BIT(5); | ||
538 | break; | ||
539 | case 3: | ||
540 | queue = 0; | ||
541 | if (acm) | ||
542 | local->wmm_acm |= BIT(6) | BIT(7); | ||
543 | break; | ||
544 | case 0: | ||
545 | default: | ||
546 | queue = 2; | ||
547 | if (acm) | ||
548 | local->wmm_acm |= BIT(1) | BIT(2); | ||
549 | break; | ||
550 | } | ||
998 | 551 | ||
999 | mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); | 552 | params.aifs = pos[0] & 0x0f; |
553 | params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4); | ||
554 | params.cw_min = ecw2cw(pos[1] & 0x0f); | ||
555 | params.txop = get_unaligned_le16(pos + 2); | ||
556 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
557 | printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d " | ||
558 | "cWmin=%d cWmax=%d txop=%d\n", | ||
559 | local->mdev->name, queue, aci, acm, params.aifs, params.cw_min, | ||
560 | params.cw_max, params.txop); | ||
561 | #endif | ||
562 | /* TODO: handle ACM (block TX, fallback to next lowest allowed | ||
563 | * AC for now) */ | ||
564 | if (local->ops->conf_tx(local_to_hw(local), queue, ¶ms)) { | ||
565 | printk(KERN_DEBUG "%s: failed to set TX queue " | ||
566 | "parameters for queue %d\n", local->mdev->name, queue); | ||
567 | } | ||
568 | } | ||
1000 | } | 569 | } |
1001 | 570 | ||
1002 | 571 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | |
1003 | static void ieee80211_associated(struct net_device *dev, | 572 | bool use_protection, |
1004 | struct ieee80211_if_sta *ifsta) | 573 | bool use_short_preamble) |
1005 | { | 574 | { |
1006 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 575 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; |
1007 | struct sta_info *sta; | 576 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1008 | int disassoc; | 577 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
1009 | DECLARE_MAC_BUF(mac); | 578 | DECLARE_MAC_BUF(mac); |
579 | #endif | ||
580 | u32 changed = 0; | ||
1010 | 581 | ||
1011 | /* TODO: start monitoring current AP signal quality and number of | 582 | if (use_protection != bss_conf->use_cts_prot) { |
1012 | * missed beacons. Scan other channels every now and then and search | 583 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
1013 | * for better APs. */ | 584 | if (net_ratelimit()) { |
1014 | /* TODO: remove expired BSSes */ | 585 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" |
1015 | 586 | "%s)\n", | |
1016 | ifsta->state = IEEE80211_ASSOCIATED; | 587 | sdata->dev->name, |
1017 | 588 | use_protection ? "enabled" : "disabled", | |
1018 | rcu_read_lock(); | 589 | print_mac(mac, ifsta->bssid)); |
1019 | |||
1020 | sta = sta_info_get(local, ifsta->bssid); | ||
1021 | if (!sta) { | ||
1022 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", | ||
1023 | dev->name, print_mac(mac, ifsta->bssid)); | ||
1024 | disassoc = 1; | ||
1025 | } else { | ||
1026 | disassoc = 0; | ||
1027 | if (time_after(jiffies, | ||
1028 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { | ||
1029 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { | ||
1030 | printk(KERN_DEBUG "%s: No ProbeResp from " | ||
1031 | "current AP %s - assume out of " | ||
1032 | "range\n", | ||
1033 | dev->name, print_mac(mac, ifsta->bssid)); | ||
1034 | disassoc = 1; | ||
1035 | sta_info_unlink(&sta); | ||
1036 | } else | ||
1037 | ieee80211_send_probe_req(dev, ifsta->bssid, | ||
1038 | local->scan_ssid, | ||
1039 | local->scan_ssid_len); | ||
1040 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | ||
1041 | } else { | ||
1042 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | ||
1043 | if (time_after(jiffies, ifsta->last_probe + | ||
1044 | IEEE80211_PROBE_INTERVAL)) { | ||
1045 | ifsta->last_probe = jiffies; | ||
1046 | ieee80211_send_probe_req(dev, ifsta->bssid, | ||
1047 | ifsta->ssid, | ||
1048 | ifsta->ssid_len); | ||
1049 | } | ||
1050 | } | 590 | } |
591 | #endif | ||
592 | bss_conf->use_cts_prot = use_protection; | ||
593 | changed |= BSS_CHANGED_ERP_CTS_PROT; | ||
1051 | } | 594 | } |
1052 | 595 | ||
1053 | rcu_read_unlock(); | 596 | if (use_short_preamble != bss_conf->use_short_preamble) { |
1054 | 597 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | |
1055 | if (disassoc && sta) | 598 | if (net_ratelimit()) { |
1056 | sta_info_destroy(sta); | 599 | printk(KERN_DEBUG "%s: switched to %s barker preamble" |
1057 | 600 | " (BSSID=%s)\n", | |
1058 | if (disassoc) { | 601 | sdata->dev->name, |
1059 | ifsta->state = IEEE80211_DISABLED; | 602 | use_short_preamble ? "short" : "long", |
1060 | ieee80211_set_associated(dev, ifsta, 0); | 603 | print_mac(mac, ifsta->bssid)); |
1061 | } else { | 604 | } |
1062 | mod_timer(&ifsta->timer, jiffies + | 605 | #endif |
1063 | IEEE80211_MONITORING_INTERVAL); | 606 | bss_conf->use_short_preamble = use_short_preamble; |
607 | changed |= BSS_CHANGED_ERP_PREAMBLE; | ||
1064 | } | 608 | } |
1065 | } | ||
1066 | 609 | ||
610 | return changed; | ||
611 | } | ||
1067 | 612 | ||
1068 | static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst, | 613 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, |
1069 | u8 *ssid, size_t ssid_len) | 614 | u8 erp_value) |
1070 | { | 615 | { |
1071 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 616 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; |
1072 | struct ieee80211_supported_band *sband; | 617 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; |
1073 | struct sk_buff *skb; | ||
1074 | struct ieee80211_mgmt *mgmt; | ||
1075 | u8 *pos, *supp_rates, *esupp_rates = NULL; | ||
1076 | int i; | ||
1077 | |||
1078 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200); | ||
1079 | if (!skb) { | ||
1080 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | ||
1081 | "request\n", dev->name); | ||
1082 | return; | ||
1083 | } | ||
1084 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1085 | 618 | ||
1086 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 619 | return ieee80211_handle_protect_preamb(sdata, |
1087 | memset(mgmt, 0, 24); | 620 | use_protection, use_short_preamble); |
1088 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 621 | } |
1089 | IEEE80211_STYPE_PROBE_REQ); | ||
1090 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | ||
1091 | if (dst) { | ||
1092 | memcpy(mgmt->da, dst, ETH_ALEN); | ||
1093 | memcpy(mgmt->bssid, dst, ETH_ALEN); | ||
1094 | } else { | ||
1095 | memset(mgmt->da, 0xff, ETH_ALEN); | ||
1096 | memset(mgmt->bssid, 0xff, ETH_ALEN); | ||
1097 | } | ||
1098 | pos = skb_put(skb, 2 + ssid_len); | ||
1099 | *pos++ = WLAN_EID_SSID; | ||
1100 | *pos++ = ssid_len; | ||
1101 | memcpy(pos, ssid, ssid_len); | ||
1102 | 622 | ||
1103 | supp_rates = skb_put(skb, 2); | 623 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
1104 | supp_rates[0] = WLAN_EID_SUPP_RATES; | 624 | struct ieee80211_bss *bss) |
1105 | supp_rates[1] = 0; | 625 | { |
1106 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 626 | u32 changed = 0; |
1107 | 627 | ||
1108 | for (i = 0; i < sband->n_bitrates; i++) { | 628 | if (bss->has_erp_value) |
1109 | struct ieee80211_rate *rate = &sband->bitrates[i]; | 629 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); |
1110 | if (esupp_rates) { | 630 | else { |
1111 | pos = skb_put(skb, 1); | 631 | u16 capab = bss->capability; |
1112 | esupp_rates[1]++; | 632 | changed |= ieee80211_handle_protect_preamb(sdata, false, |
1113 | } else if (supp_rates[1] == 8) { | 633 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); |
1114 | esupp_rates = skb_put(skb, 3); | ||
1115 | esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; | ||
1116 | esupp_rates[1] = 1; | ||
1117 | pos = &esupp_rates[2]; | ||
1118 | } else { | ||
1119 | pos = skb_put(skb, 1); | ||
1120 | supp_rates[1]++; | ||
1121 | } | ||
1122 | *pos = rate->bitrate / 5; | ||
1123 | } | 634 | } |
1124 | 635 | ||
1125 | ieee80211_sta_tx(dev, skb, 0); | 636 | return changed; |
1126 | } | 637 | } |
1127 | 638 | ||
639 | static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, | ||
640 | struct ieee80211_if_sta *ifsta) | ||
641 | { | ||
642 | union iwreq_data wrqu; | ||
643 | memset(&wrqu, 0, sizeof(wrqu)); | ||
644 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) | ||
645 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); | ||
646 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
647 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | ||
648 | } | ||
1128 | 649 | ||
1129 | static int ieee80211_sta_wep_configured(struct net_device *dev) | 650 | static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, |
651 | struct ieee80211_if_sta *ifsta) | ||
1130 | { | 652 | { |
1131 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 653 | union iwreq_data wrqu; |
1132 | if (!sdata || !sdata->default_key || | 654 | |
1133 | sdata->default_key->conf.alg != ALG_WEP) | 655 | if (ifsta->assocreq_ies) { |
1134 | return 0; | 656 | memset(&wrqu, 0, sizeof(wrqu)); |
1135 | return 1; | 657 | wrqu.data.length = ifsta->assocreq_ies_len; |
658 | wireless_send_event(sdata->dev, IWEVASSOCREQIE, &wrqu, | ||
659 | ifsta->assocreq_ies); | ||
660 | } | ||
661 | if (ifsta->assocresp_ies) { | ||
662 | memset(&wrqu, 0, sizeof(wrqu)); | ||
663 | wrqu.data.length = ifsta->assocresp_ies_len; | ||
664 | wireless_send_event(sdata->dev, IWEVASSOCRESPIE, &wrqu, | ||
665 | ifsta->assocresp_ies); | ||
666 | } | ||
1136 | } | 667 | } |
1137 | 668 | ||
1138 | 669 | ||
1139 | static void ieee80211_auth_completed(struct net_device *dev, | 670 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
1140 | struct ieee80211_if_sta *ifsta) | 671 | struct ieee80211_if_sta *ifsta) |
1141 | { | 672 | { |
1142 | printk(KERN_DEBUG "%s: authenticated\n", dev->name); | 673 | struct ieee80211_local *local = sdata->local; |
1143 | ifsta->flags |= IEEE80211_STA_AUTHENTICATED; | 674 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; |
1144 | ieee80211_associate(dev, ifsta); | 675 | u32 changed = BSS_CHANGED_ASSOC; |
1145 | } | ||
1146 | 676 | ||
677 | struct ieee80211_bss *bss; | ||
1147 | 678 | ||
1148 | static void ieee80211_auth_challenge(struct net_device *dev, | 679 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; |
1149 | struct ieee80211_if_sta *ifsta, | ||
1150 | struct ieee80211_mgmt *mgmt, | ||
1151 | size_t len) | ||
1152 | { | ||
1153 | u8 *pos; | ||
1154 | struct ieee802_11_elems elems; | ||
1155 | 680 | ||
1156 | pos = mgmt->u.auth.variable; | 681 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1157 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1158 | if (!elems.challenge) | ||
1159 | return; | 682 | return; |
1160 | ieee80211_send_auth(dev, ifsta, 3, elems.challenge - 2, | ||
1161 | elems.challenge_len + 2, 1); | ||
1162 | } | ||
1163 | 683 | ||
1164 | static void ieee80211_send_addba_resp(struct net_device *dev, u8 *da, u16 tid, | 684 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
1165 | u8 dialog_token, u16 status, u16 policy, | 685 | conf->channel->center_freq, |
1166 | u16 buf_size, u16 timeout) | 686 | ifsta->ssid, ifsta->ssid_len); |
1167 | { | 687 | if (bss) { |
1168 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 688 | /* set timing information */ |
1169 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 689 | sdata->bss_conf.beacon_int = bss->beacon_int; |
1170 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 690 | sdata->bss_conf.timestamp = bss->timestamp; |
1171 | struct sk_buff *skb; | 691 | sdata->bss_conf.dtim_period = bss->dtim_period; |
1172 | struct ieee80211_mgmt *mgmt; | ||
1173 | u16 capab; | ||
1174 | 692 | ||
1175 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 693 | changed |= ieee80211_handle_bss_capability(sdata, bss); |
1176 | 694 | ||
1177 | if (!skb) { | 695 | ieee80211_rx_bss_put(local, bss); |
1178 | printk(KERN_DEBUG "%s: failed to allocate buffer " | ||
1179 | "for addba resp frame\n", dev->name); | ||
1180 | return; | ||
1181 | } | 696 | } |
1182 | 697 | ||
1183 | skb_reserve(skb, local->hw.extra_tx_headroom); | 698 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { |
1184 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 699 | changed |= BSS_CHANGED_HT; |
1185 | memset(mgmt, 0, 24); | 700 | sdata->bss_conf.assoc_ht = 1; |
1186 | memcpy(mgmt->da, da, ETH_ALEN); | 701 | sdata->bss_conf.ht_conf = &conf->ht_conf; |
1187 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 702 | sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; |
1188 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | 703 | } |
1189 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | ||
1190 | else | ||
1191 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1192 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1193 | IEEE80211_STYPE_ACTION); | ||
1194 | 704 | ||
1195 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_resp)); | 705 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; |
1196 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 706 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); |
1197 | mgmt->u.action.u.addba_resp.action_code = WLAN_ACTION_ADDBA_RESP; | 707 | ieee80211_sta_send_associnfo(sdata, ifsta); |
1198 | mgmt->u.action.u.addba_resp.dialog_token = dialog_token; | ||
1199 | 708 | ||
1200 | capab = (u16)(policy << 1); /* bit 1 aggregation policy */ | 709 | ifsta->last_probe = jiffies; |
1201 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | 710 | ieee80211_led_assoc(local, 1); |
1202 | capab |= (u16)(buf_size << 6); /* bit 15:6 max size of aggregation */ | ||
1203 | 711 | ||
1204 | mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); | 712 | sdata->bss_conf.assoc = 1; |
1205 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | 713 | /* |
1206 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | 714 | * For now just always ask the driver to update the basic rateset |
715 | * when we have associated, we aren't checking whether it actually | ||
716 | * changed or not. | ||
717 | */ | ||
718 | changed |= BSS_CHANGED_BASIC_RATES; | ||
719 | ieee80211_bss_info_change_notify(sdata, changed); | ||
1207 | 720 | ||
1208 | ieee80211_sta_tx(dev, skb, 0); | 721 | netif_tx_start_all_queues(sdata->dev); |
722 | netif_carrier_on(sdata->dev); | ||
1209 | 723 | ||
1210 | return; | 724 | ieee80211_sta_send_apinfo(sdata, ifsta); |
1211 | } | 725 | } |
1212 | 726 | ||
1213 | void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | 727 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, |
1214 | u16 tid, u8 dialog_token, u16 start_seq_num, | 728 | struct ieee80211_if_sta *ifsta) |
1215 | u16 agg_size, u16 timeout) | ||
1216 | { | 729 | { |
1217 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 730 | DECLARE_MAC_BUF(mac); |
1218 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1219 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1220 | struct sk_buff *skb; | ||
1221 | struct ieee80211_mgmt *mgmt; | ||
1222 | u16 capab; | ||
1223 | |||
1224 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
1225 | 731 | ||
1226 | if (!skb) { | 732 | ifsta->direct_probe_tries++; |
1227 | printk(KERN_ERR "%s: failed to allocate buffer " | 733 | if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { |
1228 | "for addba request frame\n", dev->name); | 734 | printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", |
735 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | ||
736 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1229 | return; | 737 | return; |
1230 | } | 738 | } |
1231 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1232 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
1233 | memset(mgmt, 0, 24); | ||
1234 | memcpy(mgmt->da, da, ETH_ALEN); | ||
1235 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | ||
1236 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | ||
1237 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | ||
1238 | else | ||
1239 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1240 | |||
1241 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1242 | IEEE80211_STYPE_ACTION); | ||
1243 | 739 | ||
1244 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req)); | 740 | printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", |
741 | sdata->dev->name, print_mac(mac, ifsta->bssid), | ||
742 | ifsta->direct_probe_tries); | ||
1245 | 743 | ||
1246 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 744 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1247 | mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ; | ||
1248 | 745 | ||
1249 | mgmt->u.action.u.addba_req.dialog_token = dialog_token; | 746 | set_bit(IEEE80211_STA_REQ_DIRECT_PROBE, &ifsta->request); |
1250 | capab = (u16)(1 << 1); /* bit 1 aggregation policy */ | ||
1251 | capab |= (u16)(tid << 2); /* bit 5:2 TID number */ | ||
1252 | capab |= (u16)(agg_size << 6); /* bit 15:6 max size of aggergation */ | ||
1253 | 747 | ||
1254 | mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); | 748 | /* Direct probe is sent to broadcast address as some APs |
1255 | 749 | * will not answer to direct packet in unassociated state. | |
1256 | mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout); | 750 | */ |
1257 | mgmt->u.action.u.addba_req.start_seq_num = | 751 | ieee80211_send_probe_req(sdata, NULL, |
1258 | cpu_to_le16(start_seq_num << 4); | 752 | ifsta->ssid, ifsta->ssid_len); |
1259 | 753 | ||
1260 | ieee80211_sta_tx(dev, skb, 0); | 754 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
1261 | } | 755 | } |
1262 | 756 | ||
1263 | static void ieee80211_sta_process_addba_request(struct net_device *dev, | 757 | |
1264 | struct ieee80211_mgmt *mgmt, | 758 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, |
1265 | size_t len) | 759 | struct ieee80211_if_sta *ifsta) |
1266 | { | 760 | { |
1267 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1268 | struct ieee80211_hw *hw = &local->hw; | ||
1269 | struct ieee80211_conf *conf = &hw->conf; | ||
1270 | struct sta_info *sta; | ||
1271 | struct tid_ampdu_rx *tid_agg_rx; | ||
1272 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | ||
1273 | u8 dialog_token; | ||
1274 | int ret = -EOPNOTSUPP; | ||
1275 | DECLARE_MAC_BUF(mac); | 761 | DECLARE_MAC_BUF(mac); |
1276 | 762 | ||
1277 | rcu_read_lock(); | 763 | ifsta->auth_tries++; |
1278 | 764 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | |
1279 | sta = sta_info_get(local, mgmt->sa); | 765 | printk(KERN_DEBUG "%s: authentication with AP %s" |
1280 | if (!sta) { | 766 | " timed out\n", |
1281 | rcu_read_unlock(); | 767 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
768 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1282 | return; | 769 | return; |
1283 | } | 770 | } |
1284 | 771 | ||
1285 | /* extract session parameters from addba request frame */ | 772 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
1286 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | 773 | printk(KERN_DEBUG "%s: authenticate with AP %s\n", |
1287 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | 774 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1288 | start_seq_num = | ||
1289 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
1290 | |||
1291 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
1292 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
1293 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
1294 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
1295 | |||
1296 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
1297 | |||
1298 | /* sanity check for incoming parameters: | ||
1299 | * check if configuration can support the BA policy | ||
1300 | * and if buffer size does not exceeds max value */ | ||
1301 | if (((ba_policy != 1) | ||
1302 | && (!(conf->ht_conf.cap & IEEE80211_HT_CAP_DELAY_BA))) | ||
1303 | || (buf_size > IEEE80211_MAX_AMPDU_BUF)) { | ||
1304 | status = WLAN_STATUS_INVALID_QOS_PARAM; | ||
1305 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1306 | if (net_ratelimit()) | ||
1307 | printk(KERN_DEBUG "AddBA Req with bad params from " | ||
1308 | "%s on tid %u. policy %d, buffer size %d\n", | ||
1309 | print_mac(mac, mgmt->sa), tid, ba_policy, | ||
1310 | buf_size); | ||
1311 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1312 | goto end_no_lock; | ||
1313 | } | ||
1314 | /* determine default buffer size */ | ||
1315 | if (buf_size == 0) { | ||
1316 | struct ieee80211_supported_band *sband; | ||
1317 | |||
1318 | sband = local->hw.wiphy->bands[conf->channel->band]; | ||
1319 | buf_size = IEEE80211_MIN_AMPDU_BUF; | ||
1320 | buf_size = buf_size << sband->ht_info.ampdu_factor; | ||
1321 | } | ||
1322 | |||
1323 | 775 | ||
1324 | /* examine state machine */ | 776 | ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); |
1325 | spin_lock_bh(&sta->lock); | ||
1326 | 777 | ||
1327 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_IDLE) { | 778 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
1328 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1329 | if (net_ratelimit()) | ||
1330 | printk(KERN_DEBUG "unexpected AddBA Req from " | ||
1331 | "%s on tid %u\n", | ||
1332 | print_mac(mac, mgmt->sa), tid); | ||
1333 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1334 | goto end; | ||
1335 | } | ||
1336 | |||
1337 | /* prepare A-MPDU MLME for Rx aggregation */ | ||
1338 | sta->ampdu_mlme.tid_rx[tid] = | ||
1339 | kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | ||
1340 | if (!sta->ampdu_mlme.tid_rx[tid]) { | ||
1341 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1342 | if (net_ratelimit()) | ||
1343 | printk(KERN_ERR "allocate rx mlme to tid %d failed\n", | ||
1344 | tid); | ||
1345 | #endif | ||
1346 | goto end; | ||
1347 | } | ||
1348 | /* rx timer */ | ||
1349 | sta->ampdu_mlme.tid_rx[tid]->session_timer.function = | ||
1350 | sta_rx_agg_session_timer_expired; | ||
1351 | sta->ampdu_mlme.tid_rx[tid]->session_timer.data = | ||
1352 | (unsigned long)&sta->timer_to_tid[tid]; | ||
1353 | init_timer(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1354 | |||
1355 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | ||
1356 | |||
1357 | /* prepare reordering buffer */ | ||
1358 | tid_agg_rx->reorder_buf = | ||
1359 | kmalloc(buf_size * sizeof(struct sk_buff *), GFP_ATOMIC); | ||
1360 | if (!tid_agg_rx->reorder_buf) { | ||
1361 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1362 | if (net_ratelimit()) | ||
1363 | printk(KERN_ERR "can not allocate reordering buffer " | ||
1364 | "to tid %d\n", tid); | ||
1365 | #endif | ||
1366 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1367 | goto end; | ||
1368 | } | ||
1369 | memset(tid_agg_rx->reorder_buf, 0, | ||
1370 | buf_size * sizeof(struct sk_buff *)); | ||
1371 | |||
1372 | if (local->ops->ampdu_action) | ||
1373 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_START, | ||
1374 | sta->addr, tid, &start_seq_num); | ||
1375 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1376 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | ||
1377 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1378 | |||
1379 | if (ret) { | ||
1380 | kfree(tid_agg_rx->reorder_buf); | ||
1381 | kfree(tid_agg_rx); | ||
1382 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1383 | goto end; | ||
1384 | } | ||
1385 | |||
1386 | /* change state and send addba resp */ | ||
1387 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_OPERATIONAL; | ||
1388 | tid_agg_rx->dialog_token = dialog_token; | ||
1389 | tid_agg_rx->ssn = start_seq_num; | ||
1390 | tid_agg_rx->head_seq_num = start_seq_num; | ||
1391 | tid_agg_rx->buf_size = buf_size; | ||
1392 | tid_agg_rx->timeout = timeout; | ||
1393 | tid_agg_rx->stored_mpdu_num = 0; | ||
1394 | status = WLAN_STATUS_SUCCESS; | ||
1395 | end: | ||
1396 | spin_unlock_bh(&sta->lock); | ||
1397 | |||
1398 | end_no_lock: | ||
1399 | ieee80211_send_addba_resp(sta->sdata->dev, sta->addr, tid, | ||
1400 | dialog_token, status, 1, buf_size, timeout); | ||
1401 | rcu_read_unlock(); | ||
1402 | } | 779 | } |
1403 | 780 | ||
1404 | static void ieee80211_sta_process_addba_resp(struct net_device *dev, | 781 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
1405 | struct ieee80211_mgmt *mgmt, | 782 | struct ieee80211_if_sta *ifsta, bool deauth, |
1406 | size_t len) | 783 | bool self_disconnected, u16 reason) |
1407 | { | 784 | { |
1408 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 785 | struct ieee80211_local *local = sdata->local; |
1409 | struct ieee80211_hw *hw = &local->hw; | ||
1410 | struct sta_info *sta; | 786 | struct sta_info *sta; |
1411 | u16 capab; | 787 | u32 changed = BSS_CHANGED_ASSOC; |
1412 | u16 tid; | ||
1413 | u8 *state; | ||
1414 | 788 | ||
1415 | rcu_read_lock(); | 789 | rcu_read_lock(); |
1416 | 790 | ||
1417 | sta = sta_info_get(local, mgmt->sa); | 791 | sta = sta_info_get(local, ifsta->bssid); |
1418 | if (!sta) { | 792 | if (!sta) { |
1419 | rcu_read_unlock(); | 793 | rcu_read_unlock(); |
1420 | return; | 794 | return; |
1421 | } | 795 | } |
1422 | 796 | ||
1423 | capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); | 797 | if (deauth) { |
1424 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | 798 | ifsta->direct_probe_tries = 0; |
799 | ifsta->auth_tries = 0; | ||
800 | } | ||
801 | ifsta->assoc_scan_tries = 0; | ||
802 | ifsta->assoc_tries = 0; | ||
1425 | 803 | ||
1426 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 804 | netif_tx_stop_all_queues(sdata->dev); |
805 | netif_carrier_off(sdata->dev); | ||
1427 | 806 | ||
1428 | spin_lock_bh(&sta->lock); | 807 | ieee80211_sta_tear_down_BA_sessions(sdata, sta->sta.addr); |
1429 | 808 | ||
1430 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 809 | if (self_disconnected) { |
1431 | spin_unlock_bh(&sta->lock); | 810 | if (deauth) |
1432 | goto addba_resp_exit; | 811 | ieee80211_send_deauth_disassoc(sdata, |
812 | IEEE80211_STYPE_DEAUTH, reason); | ||
813 | else | ||
814 | ieee80211_send_deauth_disassoc(sdata, | ||
815 | IEEE80211_STYPE_DISASSOC, reason); | ||
1433 | } | 816 | } |
1434 | 817 | ||
1435 | if (mgmt->u.action.u.addba_resp.dialog_token != | 818 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
1436 | sta->ampdu_mlme.tid_tx[tid]->dialog_token) { | 819 | changed |= ieee80211_reset_erp_info(sdata); |
1437 | spin_unlock_bh(&sta->lock); | ||
1438 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1439 | printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid); | ||
1440 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1441 | goto addba_resp_exit; | ||
1442 | } | ||
1443 | 820 | ||
1444 | del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer); | 821 | if (sdata->bss_conf.assoc_ht) |
1445 | #ifdef CONFIG_MAC80211_HT_DEBUG | 822 | changed |= BSS_CHANGED_HT; |
1446 | printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid); | ||
1447 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1448 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | ||
1449 | == WLAN_STATUS_SUCCESS) { | ||
1450 | *state |= HT_ADDBA_RECEIVED_MSK; | ||
1451 | sta->ampdu_mlme.addba_req_num[tid] = 0; | ||
1452 | 823 | ||
1453 | if (*state == HT_AGG_STATE_OPERATIONAL) | 824 | sdata->bss_conf.assoc_ht = 0; |
1454 | ieee80211_wake_queue(hw, sta->tid_to_tx_q[tid]); | 825 | sdata->bss_conf.ht_conf = NULL; |
826 | sdata->bss_conf.ht_bss_conf = NULL; | ||
1455 | 827 | ||
1456 | spin_unlock_bh(&sta->lock); | 828 | ieee80211_led_assoc(local, 0); |
1457 | } else { | 829 | sdata->bss_conf.assoc = 0; |
1458 | sta->ampdu_mlme.addba_req_num[tid]++; | 830 | |
1459 | /* this will allow the state check in stop_BA_session */ | 831 | ieee80211_sta_send_apinfo(sdata, ifsta); |
1460 | *state = HT_AGG_STATE_OPERATIONAL; | 832 | |
1461 | spin_unlock_bh(&sta->lock); | 833 | if (self_disconnected) |
1462 | ieee80211_stop_tx_ba_session(hw, sta->addr, tid, | 834 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
1463 | WLAN_BACK_INITIATOR); | 835 | |
1464 | } | 836 | sta_info_unlink(&sta); |
1465 | 837 | ||
1466 | addba_resp_exit: | ||
1467 | rcu_read_unlock(); | 838 | rcu_read_unlock(); |
839 | |||
840 | sta_info_destroy(sta); | ||
1468 | } | 841 | } |
1469 | 842 | ||
1470 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | 843 | static int ieee80211_sta_wep_configured(struct ieee80211_sub_if_data *sdata) |
1471 | u16 initiator, u16 reason_code) | ||
1472 | { | 844 | { |
1473 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 845 | if (!sdata || !sdata->default_key || |
1474 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 846 | sdata->default_key->conf.alg != ALG_WEP) |
1475 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 847 | return 0; |
1476 | struct sk_buff *skb; | 848 | return 1; |
1477 | struct ieee80211_mgmt *mgmt; | 849 | } |
1478 | u16 params; | ||
1479 | |||
1480 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | ||
1481 | |||
1482 | if (!skb) { | ||
1483 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
1484 | "for delba frame\n", dev->name); | ||
1485 | return; | ||
1486 | } | ||
1487 | 850 | ||
1488 | skb_reserve(skb, local->hw.extra_tx_headroom); | 851 | static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, |
1489 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 852 | struct ieee80211_if_sta *ifsta) |
1490 | memset(mgmt, 0, 24); | 853 | { |
1491 | memcpy(mgmt->da, da, ETH_ALEN); | 854 | struct ieee80211_local *local = sdata->local; |
1492 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 855 | struct ieee80211_bss *bss; |
1493 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) | 856 | int bss_privacy; |
1494 | memcpy(mgmt->bssid, dev->dev_addr, ETH_ALEN); | 857 | int wep_privacy; |
1495 | else | 858 | int privacy_invoked; |
1496 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1497 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1498 | IEEE80211_STYPE_ACTION); | ||
1499 | 859 | ||
1500 | skb_put(skb, 1 + sizeof(mgmt->u.action.u.delba)); | 860 | if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL)) |
861 | return 0; | ||
1501 | 862 | ||
1502 | mgmt->u.action.category = WLAN_CATEGORY_BACK; | 863 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
1503 | mgmt->u.action.u.delba.action_code = WLAN_ACTION_DELBA; | 864 | local->hw.conf.channel->center_freq, |
1504 | params = (u16)(initiator << 11); /* bit 11 initiator */ | 865 | ifsta->ssid, ifsta->ssid_len); |
1505 | params |= (u16)(tid << 12); /* bit 15:12 TID number */ | 866 | if (!bss) |
867 | return 0; | ||
1506 | 868 | ||
1507 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 869 | bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY); |
1508 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 870 | wep_privacy = !!ieee80211_sta_wep_configured(sdata); |
871 | privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED); | ||
1509 | 872 | ||
1510 | ieee80211_sta_tx(dev, skb, 0); | 873 | ieee80211_rx_bss_put(local, bss); |
1511 | } | ||
1512 | 874 | ||
1513 | void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) | 875 | if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked)) |
1514 | { | 876 | return 0; |
1515 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1516 | struct sk_buff *skb; | ||
1517 | struct ieee80211_bar *bar; | ||
1518 | u16 bar_control = 0; | ||
1519 | 877 | ||
1520 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 878 | return 1; |
1521 | if (!skb) { | ||
1522 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
1523 | "bar frame\n", dev->name); | ||
1524 | return; | ||
1525 | } | ||
1526 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1527 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | ||
1528 | memset(bar, 0, sizeof(*bar)); | ||
1529 | bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, | ||
1530 | IEEE80211_STYPE_BACK_REQ); | ||
1531 | memcpy(bar->ra, ra, ETH_ALEN); | ||
1532 | memcpy(bar->ta, dev->dev_addr, ETH_ALEN); | ||
1533 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | ||
1534 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | ||
1535 | bar_control |= (u16)(tid << 12); | ||
1536 | bar->control = cpu_to_le16(bar_control); | ||
1537 | bar->start_seq_num = cpu_to_le16(ssn); | ||
1538 | |||
1539 | ieee80211_sta_tx(dev, skb, 0); | ||
1540 | } | 879 | } |
1541 | 880 | ||
1542 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, | 881 | static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, |
1543 | u16 initiator, u16 reason) | 882 | struct ieee80211_if_sta *ifsta) |
1544 | { | 883 | { |
1545 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1546 | struct ieee80211_hw *hw = &local->hw; | ||
1547 | struct sta_info *sta; | ||
1548 | int ret, i; | ||
1549 | DECLARE_MAC_BUF(mac); | 884 | DECLARE_MAC_BUF(mac); |
1550 | 885 | ||
1551 | rcu_read_lock(); | 886 | ifsta->assoc_tries++; |
1552 | 887 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { | |
1553 | sta = sta_info_get(local, ra); | 888 | printk(KERN_DEBUG "%s: association with AP %s" |
1554 | if (!sta) { | 889 | " timed out\n", |
1555 | rcu_read_unlock(); | 890 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
891 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1556 | return; | 892 | return; |
1557 | } | 893 | } |
1558 | 894 | ||
1559 | /* check if TID is in operational state */ | 895 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
1560 | spin_lock_bh(&sta->lock); | 896 | printk(KERN_DEBUG "%s: associate with AP %s\n", |
1561 | if (sta->ampdu_mlme.tid_state_rx[tid] | 897 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1562 | != HT_AGG_STATE_OPERATIONAL) { | 898 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { |
1563 | spin_unlock_bh(&sta->lock); | 899 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " |
1564 | rcu_read_unlock(); | 900 | "mixed-cell disabled - abort association\n", sdata->dev->name); |
901 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
1565 | return; | 902 | return; |
1566 | } | 903 | } |
1567 | sta->ampdu_mlme.tid_state_rx[tid] = | ||
1568 | HT_AGG_STATE_REQ_STOP_BA_MSK | | ||
1569 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | ||
1570 | spin_unlock_bh(&sta->lock); | ||
1571 | |||
1572 | /* stop HW Rx aggregation. ampdu_action existence | ||
1573 | * already verified in session init so we add the BUG_ON */ | ||
1574 | BUG_ON(!local->ops->ampdu_action); | ||
1575 | |||
1576 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1577 | printk(KERN_DEBUG "Rx BA session stop requested for %s tid %u\n", | ||
1578 | print_mac(mac, ra), tid); | ||
1579 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1580 | |||
1581 | ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_RX_STOP, | ||
1582 | ra, tid, NULL); | ||
1583 | if (ret) | ||
1584 | printk(KERN_DEBUG "HW problem - can not stop rx " | ||
1585 | "aggregation for tid %d\n", tid); | ||
1586 | |||
1587 | /* shutdown timer has not expired */ | ||
1588 | if (initiator != WLAN_BACK_TIMER) | ||
1589 | del_timer_sync(&sta->ampdu_mlme.tid_rx[tid]->session_timer); | ||
1590 | |||
1591 | /* check if this is a self generated aggregation halt */ | ||
1592 | if (initiator == WLAN_BACK_RECIPIENT || initiator == WLAN_BACK_TIMER) | ||
1593 | ieee80211_send_delba(dev, ra, tid, 0, reason); | ||
1594 | |||
1595 | /* free the reordering buffer */ | ||
1596 | for (i = 0; i < sta->ampdu_mlme.tid_rx[tid]->buf_size; i++) { | ||
1597 | if (sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]) { | ||
1598 | /* release the reordered frames */ | ||
1599 | dev_kfree_skb(sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i]); | ||
1600 | sta->ampdu_mlme.tid_rx[tid]->stored_mpdu_num--; | ||
1601 | sta->ampdu_mlme.tid_rx[tid]->reorder_buf[i] = NULL; | ||
1602 | } | ||
1603 | } | ||
1604 | /* free resources */ | ||
1605 | kfree(sta->ampdu_mlme.tid_rx[tid]->reorder_buf); | ||
1606 | kfree(sta->ampdu_mlme.tid_rx[tid]); | ||
1607 | sta->ampdu_mlme.tid_rx[tid] = NULL; | ||
1608 | sta->ampdu_mlme.tid_state_rx[tid] = HT_AGG_STATE_IDLE; | ||
1609 | 904 | ||
1610 | rcu_read_unlock(); | 905 | ieee80211_send_assoc(sdata, ifsta); |
906 | |||
907 | mod_timer(&ifsta->timer, jiffies + IEEE80211_ASSOC_TIMEOUT); | ||
1611 | } | 908 | } |
1612 | 909 | ||
1613 | 910 | ||
1614 | static void ieee80211_sta_process_delba(struct net_device *dev, | 911 | static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, |
1615 | struct ieee80211_mgmt *mgmt, size_t len) | 912 | struct ieee80211_if_sta *ifsta) |
1616 | { | 913 | { |
1617 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 914 | struct ieee80211_local *local = sdata->local; |
1618 | struct sta_info *sta; | 915 | struct sta_info *sta; |
1619 | u16 tid, params; | 916 | int disassoc; |
1620 | u16 initiator; | ||
1621 | DECLARE_MAC_BUF(mac); | 917 | DECLARE_MAC_BUF(mac); |
1622 | 918 | ||
1623 | rcu_read_lock(); | 919 | /* TODO: start monitoring current AP signal quality and number of |
1624 | 920 | * missed beacons. Scan other channels every now and then and search | |
1625 | sta = sta_info_get(local, mgmt->sa); | 921 | * for better APs. */ |
1626 | if (!sta) { | 922 | /* TODO: remove expired BSSes */ |
1627 | rcu_read_unlock(); | ||
1628 | return; | ||
1629 | } | ||
1630 | |||
1631 | params = le16_to_cpu(mgmt->u.action.u.delba.params); | ||
1632 | tid = (params & IEEE80211_DELBA_PARAM_TID_MASK) >> 12; | ||
1633 | initiator = (params & IEEE80211_DELBA_PARAM_INITIATOR_MASK) >> 11; | ||
1634 | |||
1635 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1636 | if (net_ratelimit()) | ||
1637 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | ||
1638 | print_mac(mac, mgmt->sa), | ||
1639 | initiator ? "initiator" : "recipient", tid, | ||
1640 | mgmt->u.action.u.delba.reason_code); | ||
1641 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | ||
1642 | |||
1643 | if (initiator == WLAN_BACK_INITIATOR) | ||
1644 | ieee80211_sta_stop_rx_ba_session(dev, sta->addr, tid, | ||
1645 | WLAN_BACK_INITIATOR, 0); | ||
1646 | else { /* WLAN_BACK_RECIPIENT */ | ||
1647 | spin_lock_bh(&sta->lock); | ||
1648 | sta->ampdu_mlme.tid_state_tx[tid] = | ||
1649 | HT_AGG_STATE_OPERATIONAL; | ||
1650 | spin_unlock_bh(&sta->lock); | ||
1651 | ieee80211_stop_tx_ba_session(&local->hw, sta->addr, tid, | ||
1652 | WLAN_BACK_RECIPIENT); | ||
1653 | } | ||
1654 | rcu_read_unlock(); | ||
1655 | } | ||
1656 | 923 | ||
1657 | /* | 924 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATED; |
1658 | * After sending add Block Ack request we activated a timer until | ||
1659 | * add Block Ack response will arrive from the recipient. | ||
1660 | * If this timer expires sta_addba_resp_timer_expired will be executed. | ||
1661 | */ | ||
1662 | void sta_addba_resp_timer_expired(unsigned long data) | ||
1663 | { | ||
1664 | /* not an elegant detour, but there is no choice as the timer passes | ||
1665 | * only one argument, and both sta_info and TID are needed, so init | ||
1666 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
1667 | * array gives the sta through container_of */ | ||
1668 | u16 tid = *(u8 *)data; | ||
1669 | struct sta_info *temp_sta = container_of((void *)data, | ||
1670 | struct sta_info, timer_to_tid[tid]); | ||
1671 | |||
1672 | struct ieee80211_local *local = temp_sta->local; | ||
1673 | struct ieee80211_hw *hw = &local->hw; | ||
1674 | struct sta_info *sta; | ||
1675 | u8 *state; | ||
1676 | 925 | ||
1677 | rcu_read_lock(); | 926 | rcu_read_lock(); |
1678 | 927 | ||
1679 | sta = sta_info_get(local, temp_sta->addr); | 928 | sta = sta_info_get(local, ifsta->bssid); |
1680 | if (!sta) { | 929 | if (!sta) { |
1681 | rcu_read_unlock(); | 930 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", |
1682 | return; | 931 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1683 | } | 932 | disassoc = 1; |
1684 | 933 | } else { | |
1685 | state = &sta->ampdu_mlme.tid_state_tx[tid]; | 934 | disassoc = 0; |
1686 | /* check if the TID waits for addBA response */ | 935 | if (time_after(jiffies, |
1687 | spin_lock_bh(&sta->lock); | 936 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { |
1688 | if (!(*state & HT_ADDBA_REQUESTED_MSK)) { | 937 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { |
1689 | spin_unlock_bh(&sta->lock); | 938 | printk(KERN_DEBUG "%s: No ProbeResp from " |
1690 | *state = HT_AGG_STATE_IDLE; | 939 | "current AP %s - assume out of " |
1691 | #ifdef CONFIG_MAC80211_HT_DEBUG | 940 | "range\n", |
1692 | printk(KERN_DEBUG "timer expired on tid %d but we are not " | 941 | sdata->dev->name, print_mac(mac, ifsta->bssid)); |
1693 | "expecting addBA response there", tid); | 942 | disassoc = 1; |
1694 | #endif | 943 | } else |
1695 | goto timer_expired_exit; | 944 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
945 | local->scan_ssid, | ||
946 | local->scan_ssid_len); | ||
947 | ifsta->flags ^= IEEE80211_STA_PROBEREQ_POLL; | ||
948 | } else { | ||
949 | ifsta->flags &= ~IEEE80211_STA_PROBEREQ_POLL; | ||
950 | if (time_after(jiffies, ifsta->last_probe + | ||
951 | IEEE80211_PROBE_INTERVAL)) { | ||
952 | ifsta->last_probe = jiffies; | ||
953 | ieee80211_send_probe_req(sdata, ifsta->bssid, | ||
954 | ifsta->ssid, | ||
955 | ifsta->ssid_len); | ||
956 | } | ||
957 | } | ||
1696 | } | 958 | } |
1697 | 959 | ||
1698 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1699 | printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid); | ||
1700 | #endif | ||
1701 | |||
1702 | /* go through the state check in stop_BA_session */ | ||
1703 | *state = HT_AGG_STATE_OPERATIONAL; | ||
1704 | spin_unlock_bh(&sta->lock); | ||
1705 | ieee80211_stop_tx_ba_session(hw, temp_sta->addr, tid, | ||
1706 | WLAN_BACK_INITIATOR); | ||
1707 | |||
1708 | timer_expired_exit: | ||
1709 | rcu_read_unlock(); | 960 | rcu_read_unlock(); |
1710 | } | ||
1711 | 961 | ||
1712 | /* | 962 | if (disassoc) |
1713 | * After accepting the AddBA Request we activated a timer, | 963 | ieee80211_set_disassoc(sdata, ifsta, true, true, |
1714 | * resetting it after each frame that arrives from the originator. | 964 | WLAN_REASON_PREV_AUTH_NOT_VALID); |
1715 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | 965 | else |
1716 | */ | 966 | mod_timer(&ifsta->timer, jiffies + |
1717 | static void sta_rx_agg_session_timer_expired(unsigned long data) | 967 | IEEE80211_MONITORING_INTERVAL); |
1718 | { | ||
1719 | /* not an elegant detour, but there is no choice as the timer passes | ||
1720 | * only one argument, and various sta_info are needed here, so init | ||
1721 | * flow in sta_info_create gives the TID as data, while the timer_to_id | ||
1722 | * array gives the sta through container_of */ | ||
1723 | u8 *ptid = (u8 *)data; | ||
1724 | u8 *timer_to_id = ptid - *ptid; | ||
1725 | struct sta_info *sta = container_of(timer_to_id, struct sta_info, | ||
1726 | timer_to_tid[0]); | ||
1727 | |||
1728 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
1729 | printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); | ||
1730 | #endif | ||
1731 | ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, | ||
1732 | (u16)*ptid, WLAN_BACK_TIMER, | ||
1733 | WLAN_REASON_QSTA_TIMEOUT); | ||
1734 | } | 968 | } |
1735 | 969 | ||
1736 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) | ||
1737 | { | ||
1738 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1739 | int i; | ||
1740 | 970 | ||
1741 | for (i = 0; i < STA_TID_NUM; i++) { | 971 | static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, |
1742 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | 972 | struct ieee80211_if_sta *ifsta) |
1743 | WLAN_BACK_INITIATOR); | 973 | { |
1744 | ieee80211_sta_stop_rx_ba_session(dev, addr, i, | 974 | printk(KERN_DEBUG "%s: authenticated\n", sdata->dev->name); |
1745 | WLAN_BACK_RECIPIENT, | 975 | ifsta->flags |= IEEE80211_STA_AUTHENTICATED; |
1746 | WLAN_REASON_QSTA_LEAVE_QBSS); | 976 | ieee80211_associate(sdata, ifsta); |
1747 | } | ||
1748 | } | 977 | } |
1749 | 978 | ||
1750 | static void ieee80211_send_refuse_measurement_request(struct net_device *dev, | ||
1751 | struct ieee80211_msrment_ie *request_ie, | ||
1752 | const u8 *da, const u8 *bssid, | ||
1753 | u8 dialog_token) | ||
1754 | { | ||
1755 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1756 | struct sk_buff *skb; | ||
1757 | struct ieee80211_mgmt *msr_report; | ||
1758 | 979 | ||
1759 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | 980 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, |
1760 | sizeof(struct ieee80211_msrment_ie)); | 981 | struct ieee80211_if_sta *ifsta, |
982 | struct ieee80211_mgmt *mgmt, | ||
983 | size_t len) | ||
984 | { | ||
985 | u8 *pos; | ||
986 | struct ieee802_11_elems elems; | ||
1761 | 987 | ||
1762 | if (!skb) { | 988 | pos = mgmt->u.auth.variable; |
1763 | printk(KERN_ERR "%s: failed to allocate buffer for " | 989 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
1764 | "measurement report frame\n", dev->name); | 990 | if (!elems.challenge) |
1765 | return; | 991 | return; |
1766 | } | 992 | ieee80211_send_auth(sdata, ifsta, 3, elems.challenge - 2, |
1767 | 993 | elems.challenge_len + 2, 1); | |
1768 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1769 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
1770 | memset(msr_report, 0, 24); | ||
1771 | memcpy(msr_report->da, da, ETH_ALEN); | ||
1772 | memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); | ||
1773 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
1774 | msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1775 | IEEE80211_STYPE_ACTION); | ||
1776 | |||
1777 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
1778 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
1779 | msr_report->u.action.u.measurement.action_code = | ||
1780 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
1781 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
1782 | |||
1783 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
1784 | msr_report->u.action.u.measurement.length = | ||
1785 | sizeof(struct ieee80211_msrment_ie); | ||
1786 | |||
1787 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
1788 | sizeof(struct ieee80211_msrment_ie)); | ||
1789 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
1790 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
1791 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
1792 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
1793 | |||
1794 | ieee80211_sta_tx(dev, skb, 0); | ||
1795 | } | ||
1796 | |||
1797 | static void ieee80211_sta_process_measurement_req(struct net_device *dev, | ||
1798 | struct ieee80211_mgmt *mgmt, | ||
1799 | size_t len) | ||
1800 | { | ||
1801 | /* | ||
1802 | * Ignoring measurement request is spec violation. | ||
1803 | * Mandatory measurements must be reported optional | ||
1804 | * measurements might be refused or reported incapable | ||
1805 | * For now just refuse | ||
1806 | * TODO: Answer basic measurement as unmeasured | ||
1807 | */ | ||
1808 | ieee80211_send_refuse_measurement_request(dev, | ||
1809 | &mgmt->u.action.u.measurement.msr_elem, | ||
1810 | mgmt->sa, mgmt->bssid, | ||
1811 | mgmt->u.action.u.measurement.dialog_token); | ||
1812 | } | 994 | } |
1813 | 995 | ||
1814 | 996 | static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |
1815 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | ||
1816 | struct ieee80211_if_sta *ifsta, | 997 | struct ieee80211_if_sta *ifsta, |
1817 | struct ieee80211_mgmt *mgmt, | 998 | struct ieee80211_mgmt *mgmt, |
1818 | size_t len) | 999 | size_t len) |
1819 | { | 1000 | { |
1820 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1821 | u16 auth_alg, auth_transaction, status_code; | 1001 | u16 auth_alg, auth_transaction, status_code; |
1822 | DECLARE_MAC_BUF(mac); | 1002 | DECLARE_MAC_BUF(mac); |
1823 | 1003 | ||
1824 | if (ifsta->state != IEEE80211_AUTHENTICATE && | 1004 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
1825 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 1005 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1826 | return; | 1006 | return; |
1827 | 1007 | ||
1828 | if (len < 24 + 6) | 1008 | if (len < 24 + 6) |
1829 | return; | 1009 | return; |
1830 | 1010 | ||
1831 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1011 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
1832 | memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) | 1012 | memcmp(ifsta->bssid, mgmt->sa, ETH_ALEN) != 0) |
1833 | return; | 1013 | return; |
1834 | 1014 | ||
1835 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1015 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
1836 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | 1016 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
1837 | return; | 1017 | return; |
1838 | 1018 | ||
@@ -1840,7 +1020,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1840 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | 1020 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); |
1841 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | 1021 | status_code = le16_to_cpu(mgmt->u.auth.status_code); |
1842 | 1022 | ||
1843 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1023 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1844 | /* | 1024 | /* |
1845 | * IEEE 802.11 standard does not require authentication in IBSS | 1025 | * IEEE 802.11 standard does not require authentication in IBSS |
1846 | * networks and most implementations do not seem to use it. | 1026 | * networks and most implementations do not seem to use it. |
@@ -1849,7 +1029,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1849 | */ | 1029 | */ |
1850 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | 1030 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) |
1851 | return; | 1031 | return; |
1852 | ieee80211_send_auth(dev, ifsta, 2, NULL, 0, 0); | 1032 | ieee80211_send_auth(sdata, ifsta, 2, NULL, 0, 0); |
1853 | } | 1033 | } |
1854 | 1034 | ||
1855 | if (auth_alg != ifsta->auth_alg || | 1035 | if (auth_alg != ifsta->auth_alg || |
@@ -1882,7 +1062,7 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1882 | algs[pos] == 0xff) | 1062 | algs[pos] == 0xff) |
1883 | continue; | 1063 | continue; |
1884 | if (algs[pos] == WLAN_AUTH_SHARED_KEY && | 1064 | if (algs[pos] == WLAN_AUTH_SHARED_KEY && |
1885 | !ieee80211_sta_wep_configured(dev)) | 1065 | !ieee80211_sta_wep_configured(sdata)) |
1886 | continue; | 1066 | continue; |
1887 | ifsta->auth_alg = algs[pos]; | 1067 | ifsta->auth_alg = algs[pos]; |
1888 | break; | 1068 | break; |
@@ -1894,19 +1074,19 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1894 | switch (ifsta->auth_alg) { | 1074 | switch (ifsta->auth_alg) { |
1895 | case WLAN_AUTH_OPEN: | 1075 | case WLAN_AUTH_OPEN: |
1896 | case WLAN_AUTH_LEAP: | 1076 | case WLAN_AUTH_LEAP: |
1897 | ieee80211_auth_completed(dev, ifsta); | 1077 | ieee80211_auth_completed(sdata, ifsta); |
1898 | break; | 1078 | break; |
1899 | case WLAN_AUTH_SHARED_KEY: | 1079 | case WLAN_AUTH_SHARED_KEY: |
1900 | if (ifsta->auth_transaction == 4) | 1080 | if (ifsta->auth_transaction == 4) |
1901 | ieee80211_auth_completed(dev, ifsta); | 1081 | ieee80211_auth_completed(sdata, ifsta); |
1902 | else | 1082 | else |
1903 | ieee80211_auth_challenge(dev, ifsta, mgmt, len); | 1083 | ieee80211_auth_challenge(sdata, ifsta, mgmt, len); |
1904 | break; | 1084 | break; |
1905 | } | 1085 | } |
1906 | } | 1086 | } |
1907 | 1087 | ||
1908 | 1088 | ||
1909 | static void ieee80211_rx_mgmt_deauth(struct net_device *dev, | 1089 | static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
1910 | struct ieee80211_if_sta *ifsta, | 1090 | struct ieee80211_if_sta *ifsta, |
1911 | struct ieee80211_mgmt *mgmt, | 1091 | struct ieee80211_mgmt *mgmt, |
1912 | size_t len) | 1092 | size_t len) |
@@ -1923,22 +1103,22 @@ static void ieee80211_rx_mgmt_deauth(struct net_device *dev, | |||
1923 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1103 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1924 | 1104 | ||
1925 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) | 1105 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) |
1926 | printk(KERN_DEBUG "%s: deauthenticated\n", dev->name); | 1106 | printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); |
1927 | 1107 | ||
1928 | if (ifsta->state == IEEE80211_AUTHENTICATE || | 1108 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || |
1929 | ifsta->state == IEEE80211_ASSOCIATE || | 1109 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || |
1930 | ifsta->state == IEEE80211_ASSOCIATED) { | 1110 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1931 | ifsta->state = IEEE80211_AUTHENTICATE; | 1111 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
1932 | mod_timer(&ifsta->timer, jiffies + | 1112 | mod_timer(&ifsta->timer, jiffies + |
1933 | IEEE80211_RETRY_AUTH_INTERVAL); | 1113 | IEEE80211_RETRY_AUTH_INTERVAL); |
1934 | } | 1114 | } |
1935 | 1115 | ||
1936 | ieee80211_set_disassoc(dev, ifsta, 1); | 1116 | ieee80211_set_disassoc(sdata, ifsta, true, false, 0); |
1937 | ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; | 1117 | ifsta->flags &= ~IEEE80211_STA_AUTHENTICATED; |
1938 | } | 1118 | } |
1939 | 1119 | ||
1940 | 1120 | ||
1941 | static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, | 1121 | static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, |
1942 | struct ieee80211_if_sta *ifsta, | 1122 | struct ieee80211_if_sta *ifsta, |
1943 | struct ieee80211_mgmt *mgmt, | 1123 | struct ieee80211_mgmt *mgmt, |
1944 | size_t len) | 1124 | size_t len) |
@@ -1955,15 +1135,15 @@ static void ieee80211_rx_mgmt_disassoc(struct net_device *dev, | |||
1955 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1135 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1956 | 1136 | ||
1957 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) | 1137 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) |
1958 | printk(KERN_DEBUG "%s: disassociated\n", dev->name); | 1138 | printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); |
1959 | 1139 | ||
1960 | if (ifsta->state == IEEE80211_ASSOCIATED) { | 1140 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1961 | ifsta->state = IEEE80211_ASSOCIATE; | 1141 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
1962 | mod_timer(&ifsta->timer, jiffies + | 1142 | mod_timer(&ifsta->timer, jiffies + |
1963 | IEEE80211_RETRY_AUTH_INTERVAL); | 1143 | IEEE80211_RETRY_AUTH_INTERVAL); |
1964 | } | 1144 | } |
1965 | 1145 | ||
1966 | ieee80211_set_disassoc(dev, ifsta, 0); | 1146 | ieee80211_set_disassoc(sdata, ifsta, false, false, 0); |
1967 | } | 1147 | } |
1968 | 1148 | ||
1969 | 1149 | ||
@@ -1974,7 +1154,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1974 | int reassoc) | 1154 | int reassoc) |
1975 | { | 1155 | { |
1976 | struct ieee80211_local *local = sdata->local; | 1156 | struct ieee80211_local *local = sdata->local; |
1977 | struct net_device *dev = sdata->dev; | ||
1978 | struct ieee80211_supported_band *sband; | 1157 | struct ieee80211_supported_band *sband; |
1979 | struct sta_info *sta; | 1158 | struct sta_info *sta; |
1980 | u64 rates, basic_rates; | 1159 | u64 rates, basic_rates; |
@@ -1989,7 +1168,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1989 | /* AssocResp and ReassocResp have identical structure, so process both | 1168 | /* AssocResp and ReassocResp have identical structure, so process both |
1990 | * of them in this function. */ | 1169 | * of them in this function. */ |
1991 | 1170 | ||
1992 | if (ifsta->state != IEEE80211_ASSOCIATE) | 1171 | if (ifsta->state != IEEE80211_STA_MLME_ASSOCIATE) |
1993 | return; | 1172 | return; |
1994 | 1173 | ||
1995 | if (len < 24 + 6) | 1174 | if (len < 24 + 6) |
@@ -2004,12 +1183,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2004 | 1183 | ||
2005 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " | 1184 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " |
2006 | "status=%d aid=%d)\n", | 1185 | "status=%d aid=%d)\n", |
2007 | dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), | 1186 | sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), |
2008 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1187 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
2009 | 1188 | ||
2010 | if (status_code != WLAN_STATUS_SUCCESS) { | 1189 | if (status_code != WLAN_STATUS_SUCCESS) { |
2011 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | 1190 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", |
2012 | dev->name, status_code); | 1191 | sdata->dev->name, status_code); |
2013 | /* if this was a reassociation, ensure we try a "full" | 1192 | /* if this was a reassociation, ensure we try a "full" |
2014 | * association next time. This works around some broken APs | 1193 | * association next time. This works around some broken APs |
2015 | * which do not correctly reject reassociation requests. */ | 1194 | * which do not correctly reject reassociation requests. */ |
@@ -2019,7 +1198,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2019 | 1198 | ||
2020 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1199 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
2021 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1200 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
2022 | "set\n", dev->name, aid); | 1201 | "set\n", sdata->dev->name, aid); |
2023 | aid &= ~(BIT(15) | BIT(14)); | 1202 | aid &= ~(BIT(15) | BIT(14)); |
2024 | 1203 | ||
2025 | pos = mgmt->u.assoc_resp.variable; | 1204 | pos = mgmt->u.assoc_resp.variable; |
@@ -2027,11 +1206,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2027 | 1206 | ||
2028 | if (!elems.supp_rates) { | 1207 | if (!elems.supp_rates) { |
2029 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1208 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
2030 | dev->name); | 1209 | sdata->dev->name); |
2031 | return; | 1210 | return; |
2032 | } | 1211 | } |
2033 | 1212 | ||
2034 | printk(KERN_DEBUG "%s: associated\n", dev->name); | 1213 | printk(KERN_DEBUG "%s: associated\n", sdata->dev->name); |
2035 | ifsta->aid = aid; | 1214 | ifsta->aid = aid; |
2036 | ifsta->ap_capab = capab_info; | 1215 | ifsta->ap_capab = capab_info; |
2037 | 1216 | ||
@@ -2046,17 +1225,17 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2046 | /* Add STA entry for the AP */ | 1225 | /* Add STA entry for the AP */ |
2047 | sta = sta_info_get(local, ifsta->bssid); | 1226 | sta = sta_info_get(local, ifsta->bssid); |
2048 | if (!sta) { | 1227 | if (!sta) { |
2049 | struct ieee80211_sta_bss *bss; | 1228 | struct ieee80211_bss *bss; |
2050 | int err; | 1229 | int err; |
2051 | 1230 | ||
2052 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); | 1231 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); |
2053 | if (!sta) { | 1232 | if (!sta) { |
2054 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | 1233 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
2055 | " the AP\n", dev->name); | 1234 | " the AP\n", sdata->dev->name); |
2056 | rcu_read_unlock(); | 1235 | rcu_read_unlock(); |
2057 | return; | 1236 | return; |
2058 | } | 1237 | } |
2059 | bss = ieee80211_rx_bss_get(dev, ifsta->bssid, | 1238 | bss = ieee80211_rx_bss_get(local, ifsta->bssid, |
2060 | local->hw.conf.channel->center_freq, | 1239 | local->hw.conf.channel->center_freq, |
2061 | ifsta->ssid, ifsta->ssid_len); | 1240 | ifsta->ssid, ifsta->ssid_len); |
2062 | if (bss) { | 1241 | if (bss) { |
@@ -2069,7 +1248,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2069 | err = sta_info_insert(sta); | 1248 | err = sta_info_insert(sta); |
2070 | if (err) { | 1249 | if (err) { |
2071 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | 1250 | printk(KERN_DEBUG "%s: failed to insert STA entry for" |
2072 | " the AP (error %d)\n", dev->name, err); | 1251 | " the AP (error %d)\n", sdata->dev->name, err); |
2073 | rcu_read_unlock(); | 1252 | rcu_read_unlock(); |
2074 | return; | 1253 | return; |
2075 | } | 1254 | } |
@@ -2122,8 +1301,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2122 | } | 1301 | } |
2123 | } | 1302 | } |
2124 | 1303 | ||
2125 | sta->supp_rates[local->hw.conf.channel->band] = rates; | 1304 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
2126 | sdata->basic_rates = basic_rates; | 1305 | sdata->bss_conf.basic_rates = basic_rates; |
2127 | 1306 | ||
2128 | /* cf. IEEE 802.11 9.2.12 */ | 1307 | /* cf. IEEE 802.11 9.2.12 */ |
2129 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1308 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
@@ -2137,11 +1316,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2137 | struct ieee80211_ht_bss_info bss_info; | 1316 | struct ieee80211_ht_bss_info bss_info; |
2138 | ieee80211_ht_cap_ie_to_ht_info( | 1317 | ieee80211_ht_cap_ie_to_ht_info( |
2139 | (struct ieee80211_ht_cap *) | 1318 | (struct ieee80211_ht_cap *) |
2140 | elems.ht_cap_elem, &sta->ht_info); | 1319 | elems.ht_cap_elem, &sta->sta.ht_info); |
2141 | ieee80211_ht_addt_info_ie_to_ht_bss_info( | 1320 | ieee80211_ht_addt_info_ie_to_ht_bss_info( |
2142 | (struct ieee80211_ht_addt_info *) | 1321 | (struct ieee80211_ht_addt_info *) |
2143 | elems.ht_info_elem, &bss_info); | 1322 | elems.ht_info_elem, &bss_info); |
2144 | ieee80211_handle_ht(local, 1, &sta->ht_info, &bss_info); | 1323 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); |
2145 | } | 1324 | } |
2146 | 1325 | ||
2147 | rate_control_rate_init(sta, local); | 1326 | rate_control_rate_init(sta, local); |
@@ -2149,7 +1328,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2149 | if (elems.wmm_param) { | 1328 | if (elems.wmm_param) { |
2150 | set_sta_flags(sta, WLAN_STA_WME); | 1329 | set_sta_flags(sta, WLAN_STA_WME); |
2151 | rcu_read_unlock(); | 1330 | rcu_read_unlock(); |
2152 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1331 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
2153 | elems.wmm_param_len); | 1332 | elems.wmm_param_len); |
2154 | } else | 1333 | } else |
2155 | rcu_read_unlock(); | 1334 | rcu_read_unlock(); |
@@ -2158,234 +1337,26 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2158 | * ieee80211_set_associated() will tell the driver */ | 1337 | * ieee80211_set_associated() will tell the driver */ |
2159 | bss_conf->aid = aid; | 1338 | bss_conf->aid = aid; |
2160 | bss_conf->assoc_capability = capab_info; | 1339 | bss_conf->assoc_capability = capab_info; |
2161 | ieee80211_set_associated(dev, ifsta, 1); | 1340 | ieee80211_set_associated(sdata, ifsta); |
2162 | |||
2163 | ieee80211_associated(dev, ifsta); | ||
2164 | } | ||
2165 | |||
2166 | |||
2167 | /* Caller must hold local->sta_bss_lock */ | ||
2168 | static void __ieee80211_rx_bss_hash_add(struct net_device *dev, | ||
2169 | struct ieee80211_sta_bss *bss) | ||
2170 | { | ||
2171 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2172 | u8 hash_idx; | ||
2173 | |||
2174 | if (bss_mesh_cfg(bss)) | ||
2175 | hash_idx = mesh_id_hash(bss_mesh_id(bss), | ||
2176 | bss_mesh_id_len(bss)); | ||
2177 | else | ||
2178 | hash_idx = STA_HASH(bss->bssid); | ||
2179 | |||
2180 | bss->hnext = local->sta_bss_hash[hash_idx]; | ||
2181 | local->sta_bss_hash[hash_idx] = bss; | ||
2182 | } | ||
2183 | |||
2184 | |||
2185 | /* Caller must hold local->sta_bss_lock */ | ||
2186 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | ||
2187 | struct ieee80211_sta_bss *bss) | ||
2188 | { | ||
2189 | struct ieee80211_sta_bss *b, *prev = NULL; | ||
2190 | b = local->sta_bss_hash[STA_HASH(bss->bssid)]; | ||
2191 | while (b) { | ||
2192 | if (b == bss) { | ||
2193 | if (!prev) | ||
2194 | local->sta_bss_hash[STA_HASH(bss->bssid)] = | ||
2195 | bss->hnext; | ||
2196 | else | ||
2197 | prev->hnext = bss->hnext; | ||
2198 | break; | ||
2199 | } | ||
2200 | prev = b; | ||
2201 | b = b->hnext; | ||
2202 | } | ||
2203 | } | ||
2204 | |||
2205 | |||
2206 | static struct ieee80211_sta_bss * | ||
2207 | ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int freq, | ||
2208 | u8 *ssid, u8 ssid_len) | ||
2209 | { | ||
2210 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2211 | struct ieee80211_sta_bss *bss; | ||
2212 | |||
2213 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
2214 | if (!bss) | ||
2215 | return NULL; | ||
2216 | atomic_inc(&bss->users); | ||
2217 | atomic_inc(&bss->users); | ||
2218 | memcpy(bss->bssid, bssid, ETH_ALEN); | ||
2219 | bss->freq = freq; | ||
2220 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
2221 | memcpy(bss->ssid, ssid, ssid_len); | ||
2222 | bss->ssid_len = ssid_len; | ||
2223 | } | ||
2224 | |||
2225 | spin_lock_bh(&local->sta_bss_lock); | ||
2226 | /* TODO: order by RSSI? */ | ||
2227 | list_add_tail(&bss->list, &local->sta_bss_list); | ||
2228 | __ieee80211_rx_bss_hash_add(dev, bss); | ||
2229 | spin_unlock_bh(&local->sta_bss_lock); | ||
2230 | return bss; | ||
2231 | } | ||
2232 | 1341 | ||
2233 | static struct ieee80211_sta_bss * | 1342 | ieee80211_associated(sdata, ifsta); |
2234 | ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq, | ||
2235 | u8 *ssid, u8 ssid_len) | ||
2236 | { | ||
2237 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2238 | struct ieee80211_sta_bss *bss; | ||
2239 | |||
2240 | spin_lock_bh(&local->sta_bss_lock); | ||
2241 | bss = local->sta_bss_hash[STA_HASH(bssid)]; | ||
2242 | while (bss) { | ||
2243 | if (!bss_mesh_cfg(bss) && | ||
2244 | !memcmp(bss->bssid, bssid, ETH_ALEN) && | ||
2245 | bss->freq == freq && | ||
2246 | bss->ssid_len == ssid_len && | ||
2247 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
2248 | atomic_inc(&bss->users); | ||
2249 | break; | ||
2250 | } | ||
2251 | bss = bss->hnext; | ||
2252 | } | ||
2253 | spin_unlock_bh(&local->sta_bss_lock); | ||
2254 | return bss; | ||
2255 | } | 1343 | } |
2256 | 1344 | ||
2257 | #ifdef CONFIG_MAC80211_MESH | ||
2258 | static struct ieee80211_sta_bss * | ||
2259 | ieee80211_rx_mesh_bss_get(struct net_device *dev, u8 *mesh_id, int mesh_id_len, | ||
2260 | u8 *mesh_cfg, int freq) | ||
2261 | { | ||
2262 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2263 | struct ieee80211_sta_bss *bss; | ||
2264 | |||
2265 | spin_lock_bh(&local->sta_bss_lock); | ||
2266 | bss = local->sta_bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; | ||
2267 | while (bss) { | ||
2268 | if (bss_mesh_cfg(bss) && | ||
2269 | !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && | ||
2270 | bss->freq == freq && | ||
2271 | mesh_id_len == bss->mesh_id_len && | ||
2272 | (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, | ||
2273 | mesh_id_len))) { | ||
2274 | atomic_inc(&bss->users); | ||
2275 | break; | ||
2276 | } | ||
2277 | bss = bss->hnext; | ||
2278 | } | ||
2279 | spin_unlock_bh(&local->sta_bss_lock); | ||
2280 | return bss; | ||
2281 | } | ||
2282 | |||
2283 | static struct ieee80211_sta_bss * | ||
2284 | ieee80211_rx_mesh_bss_add(struct net_device *dev, u8 *mesh_id, int mesh_id_len, | ||
2285 | u8 *mesh_cfg, int mesh_config_len, int freq) | ||
2286 | { | ||
2287 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
2288 | struct ieee80211_sta_bss *bss; | ||
2289 | |||
2290 | if (mesh_config_len != MESH_CFG_LEN) | ||
2291 | return NULL; | ||
2292 | |||
2293 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
2294 | if (!bss) | ||
2295 | return NULL; | ||
2296 | |||
2297 | bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); | ||
2298 | if (!bss->mesh_cfg) { | ||
2299 | kfree(bss); | ||
2300 | return NULL; | ||
2301 | } | ||
2302 | |||
2303 | if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { | ||
2304 | bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); | ||
2305 | if (!bss->mesh_id) { | ||
2306 | kfree(bss->mesh_cfg); | ||
2307 | kfree(bss); | ||
2308 | return NULL; | ||
2309 | } | ||
2310 | memcpy(bss->mesh_id, mesh_id, mesh_id_len); | ||
2311 | } | ||
2312 | |||
2313 | atomic_inc(&bss->users); | ||
2314 | atomic_inc(&bss->users); | ||
2315 | memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); | ||
2316 | bss->mesh_id_len = mesh_id_len; | ||
2317 | bss->freq = freq; | ||
2318 | spin_lock_bh(&local->sta_bss_lock); | ||
2319 | /* TODO: order by RSSI? */ | ||
2320 | list_add_tail(&bss->list, &local->sta_bss_list); | ||
2321 | __ieee80211_rx_bss_hash_add(dev, bss); | ||
2322 | spin_unlock_bh(&local->sta_bss_lock); | ||
2323 | return bss; | ||
2324 | } | ||
2325 | #endif | ||
2326 | 1345 | ||
2327 | static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss) | 1346 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
2328 | { | ||
2329 | kfree(bss->wpa_ie); | ||
2330 | kfree(bss->rsn_ie); | ||
2331 | kfree(bss->wmm_ie); | ||
2332 | kfree(bss->ht_ie); | ||
2333 | kfree(bss->ht_add_ie); | ||
2334 | kfree(bss_mesh_id(bss)); | ||
2335 | kfree(bss_mesh_cfg(bss)); | ||
2336 | kfree(bss); | ||
2337 | } | ||
2338 | |||
2339 | |||
2340 | static void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
2341 | struct ieee80211_sta_bss *bss) | ||
2342 | { | ||
2343 | local_bh_disable(); | ||
2344 | if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) { | ||
2345 | local_bh_enable(); | ||
2346 | return; | ||
2347 | } | ||
2348 | |||
2349 | __ieee80211_rx_bss_hash_del(local, bss); | ||
2350 | list_del(&bss->list); | ||
2351 | spin_unlock_bh(&local->sta_bss_lock); | ||
2352 | ieee80211_rx_bss_free(bss); | ||
2353 | } | ||
2354 | |||
2355 | |||
2356 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) | ||
2357 | { | ||
2358 | spin_lock_init(&local->sta_bss_lock); | ||
2359 | INIT_LIST_HEAD(&local->sta_bss_list); | ||
2360 | } | ||
2361 | |||
2362 | |||
2363 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) | ||
2364 | { | ||
2365 | struct ieee80211_sta_bss *bss, *tmp; | ||
2366 | |||
2367 | list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list) | ||
2368 | ieee80211_rx_bss_put(local, bss); | ||
2369 | } | ||
2370 | |||
2371 | |||
2372 | static int ieee80211_sta_join_ibss(struct net_device *dev, | ||
2373 | struct ieee80211_if_sta *ifsta, | 1347 | struct ieee80211_if_sta *ifsta, |
2374 | struct ieee80211_sta_bss *bss) | 1348 | struct ieee80211_bss *bss) |
2375 | { | 1349 | { |
2376 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1350 | struct ieee80211_local *local = sdata->local; |
2377 | int res, rates, i, j; | 1351 | int res, rates, i, j; |
2378 | struct sk_buff *skb; | 1352 | struct sk_buff *skb; |
2379 | struct ieee80211_mgmt *mgmt; | 1353 | struct ieee80211_mgmt *mgmt; |
2380 | u8 *pos; | 1354 | u8 *pos; |
2381 | struct ieee80211_sub_if_data *sdata; | ||
2382 | struct ieee80211_supported_band *sband; | 1355 | struct ieee80211_supported_band *sband; |
2383 | union iwreq_data wrqu; | 1356 | union iwreq_data wrqu; |
2384 | 1357 | ||
2385 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2386 | 1359 | ||
2387 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2388 | |||
2389 | /* Remove possible STA entries from other IBSS networks. */ | 1360 | /* Remove possible STA entries from other IBSS networks. */ |
2390 | sta_info_flush_delayed(sdata); | 1361 | sta_info_flush_delayed(sdata); |
2391 | 1362 | ||
@@ -2403,7 +1374,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2403 | sdata->drop_unencrypted = bss->capability & | 1374 | sdata->drop_unencrypted = bss->capability & |
2404 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 1375 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
2405 | 1376 | ||
2406 | res = ieee80211_set_freq(dev, bss->freq); | 1377 | res = ieee80211_set_freq(sdata, bss->freq); |
2407 | 1378 | ||
2408 | if (res) | 1379 | if (res) |
2409 | return res; | 1380 | return res; |
@@ -2416,10 +1387,10 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2416 | mgmt = (struct ieee80211_mgmt *) | 1387 | mgmt = (struct ieee80211_mgmt *) |
2417 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1388 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
2418 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1389 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
2419 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1390 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2420 | IEEE80211_STYPE_PROBE_RESP); | 1391 | IEEE80211_STYPE_PROBE_RESP); |
2421 | memset(mgmt->da, 0xff, ETH_ALEN); | 1392 | memset(mgmt->da, 0xff, ETH_ALEN); |
2422 | memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); | 1393 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
2423 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 1394 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
2424 | mgmt->u.beacon.beacon_int = | 1395 | mgmt->u.beacon.beacon_int = |
2425 | cpu_to_le16(local->hw.conf.beacon_int); | 1396 | cpu_to_le16(local->hw.conf.beacon_int); |
@@ -2476,108 +1447,36 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2476 | } | 1447 | } |
2477 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | 1448 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; |
2478 | 1449 | ||
2479 | ieee80211_sta_def_wmm_params(dev, bss, 1); | 1450 | ieee80211_sta_def_wmm_params(sdata, bss); |
2480 | 1451 | ||
2481 | ifsta->state = IEEE80211_IBSS_JOINED; | 1452 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
2482 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1453 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
2483 | 1454 | ||
2484 | memset(&wrqu, 0, sizeof(wrqu)); | 1455 | memset(&wrqu, 0, sizeof(wrqu)); |
2485 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1456 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
2486 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 1457 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
2487 | 1458 | ||
2488 | return res; | 1459 | return res; |
2489 | } | 1460 | } |
2490 | 1461 | ||
2491 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 1462 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
2492 | struct ieee802_11_elems *elems, | ||
2493 | enum ieee80211_band band) | ||
2494 | { | ||
2495 | struct ieee80211_supported_band *sband; | ||
2496 | struct ieee80211_rate *bitrates; | ||
2497 | size_t num_rates; | ||
2498 | u64 supp_rates; | ||
2499 | int i, j; | ||
2500 | sband = local->hw.wiphy->bands[band]; | ||
2501 | |||
2502 | if (!sband) { | ||
2503 | WARN_ON(1); | ||
2504 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
2505 | } | ||
2506 | |||
2507 | bitrates = sband->bitrates; | ||
2508 | num_rates = sband->n_bitrates; | ||
2509 | supp_rates = 0; | ||
2510 | for (i = 0; i < elems->supp_rates_len + | ||
2511 | elems->ext_supp_rates_len; i++) { | ||
2512 | u8 rate = 0; | ||
2513 | int own_rate; | ||
2514 | if (i < elems->supp_rates_len) | ||
2515 | rate = elems->supp_rates[i]; | ||
2516 | else if (elems->ext_supp_rates) | ||
2517 | rate = elems->ext_supp_rates | ||
2518 | [i - elems->supp_rates_len]; | ||
2519 | own_rate = 5 * (rate & 0x7f); | ||
2520 | for (j = 0; j < num_rates; j++) | ||
2521 | if (bitrates[j].bitrate == own_rate) | ||
2522 | supp_rates |= BIT(j); | ||
2523 | } | ||
2524 | return supp_rates; | ||
2525 | } | ||
2526 | |||
2527 | |||
2528 | static void ieee80211_rx_bss_info(struct net_device *dev, | ||
2529 | struct ieee80211_mgmt *mgmt, | 1463 | struct ieee80211_mgmt *mgmt, |
2530 | size_t len, | 1464 | size_t len, |
2531 | struct ieee80211_rx_status *rx_status, | 1465 | struct ieee80211_rx_status *rx_status, |
2532 | struct ieee802_11_elems *elems, | 1466 | struct ieee802_11_elems *elems, |
2533 | int beacon) | 1467 | bool beacon) |
2534 | { | 1468 | { |
2535 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1469 | struct ieee80211_local *local = sdata->local; |
2536 | int freq, clen; | 1470 | int freq; |
2537 | struct ieee80211_sta_bss *bss; | 1471 | struct ieee80211_bss *bss; |
2538 | struct sta_info *sta; | 1472 | struct sta_info *sta; |
2539 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2540 | u64 beacon_timestamp, rx_timestamp; | ||
2541 | struct ieee80211_channel *channel; | 1473 | struct ieee80211_channel *channel; |
1474 | u64 beacon_timestamp, rx_timestamp; | ||
1475 | u64 supp_rates = 0; | ||
1476 | enum ieee80211_band band = rx_status->band; | ||
2542 | DECLARE_MAC_BUF(mac); | 1477 | DECLARE_MAC_BUF(mac); |
2543 | DECLARE_MAC_BUF(mac2); | 1478 | DECLARE_MAC_BUF(mac2); |
2544 | 1479 | ||
2545 | if (!beacon && memcmp(mgmt->da, dev->dev_addr, ETH_ALEN)) | ||
2546 | return; /* ignore ProbeResp to foreign address */ | ||
2547 | |||
2548 | beacon_timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
2549 | |||
2550 | if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id && | ||
2551 | elems->mesh_config && mesh_matches_local(elems, dev)) { | ||
2552 | u64 rates = ieee80211_sta_get_rates(local, elems, | ||
2553 | rx_status->band); | ||
2554 | |||
2555 | mesh_neighbour_update(mgmt->sa, rates, dev, | ||
2556 | mesh_peer_accepts_plinks(elems, dev)); | ||
2557 | } | ||
2558 | |||
2559 | rcu_read_lock(); | ||
2560 | |||
2561 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && | ||
2562 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 && | ||
2563 | (sta = sta_info_get(local, mgmt->sa))) { | ||
2564 | u64 prev_rates; | ||
2565 | u64 supp_rates = ieee80211_sta_get_rates(local, elems, | ||
2566 | rx_status->band); | ||
2567 | |||
2568 | prev_rates = sta->supp_rates[rx_status->band]; | ||
2569 | sta->supp_rates[rx_status->band] &= supp_rates; | ||
2570 | if (sta->supp_rates[rx_status->band] == 0) { | ||
2571 | /* No matching rates - this should not really happen. | ||
2572 | * Make sure that at least one rate is marked | ||
2573 | * supported to avoid issues with TX rate ctrl. */ | ||
2574 | sta->supp_rates[rx_status->band] = | ||
2575 | sdata->u.sta.supp_rates_bits[rx_status->band]; | ||
2576 | } | ||
2577 | } | ||
2578 | |||
2579 | rcu_read_unlock(); | ||
2580 | |||
2581 | if (elems->ds_params && elems->ds_params_len == 1) | 1480 | if (elems->ds_params && elems->ds_params_len == 1) |
2582 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1481 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); |
2583 | else | 1482 | else |
@@ -2588,215 +1487,60 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2588 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 1487 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
2589 | return; | 1488 | return; |
2590 | 1489 | ||
2591 | #ifdef CONFIG_MAC80211_MESH | 1490 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && elems->supp_rates && |
2592 | if (elems->mesh_config) | 1491 | memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { |
2593 | bss = ieee80211_rx_mesh_bss_get(dev, elems->mesh_id, | 1492 | supp_rates = ieee80211_sta_get_rates(local, elems, band); |
2594 | elems->mesh_id_len, elems->mesh_config, freq); | ||
2595 | else | ||
2596 | #endif | ||
2597 | bss = ieee80211_rx_bss_get(dev, mgmt->bssid, freq, | ||
2598 | elems->ssid, elems->ssid_len); | ||
2599 | if (!bss) { | ||
2600 | #ifdef CONFIG_MAC80211_MESH | ||
2601 | if (elems->mesh_config) | ||
2602 | bss = ieee80211_rx_mesh_bss_add(dev, elems->mesh_id, | ||
2603 | elems->mesh_id_len, elems->mesh_config, | ||
2604 | elems->mesh_config_len, freq); | ||
2605 | else | ||
2606 | #endif | ||
2607 | bss = ieee80211_rx_bss_add(dev, mgmt->bssid, freq, | ||
2608 | elems->ssid, elems->ssid_len); | ||
2609 | if (!bss) | ||
2610 | return; | ||
2611 | } else { | ||
2612 | #if 0 | ||
2613 | /* TODO: order by RSSI? */ | ||
2614 | spin_lock_bh(&local->sta_bss_lock); | ||
2615 | list_move_tail(&bss->list, &local->sta_bss_list); | ||
2616 | spin_unlock_bh(&local->sta_bss_lock); | ||
2617 | #endif | ||
2618 | } | ||
2619 | 1493 | ||
2620 | /* save the ERP value so that it is available at association time */ | 1494 | rcu_read_lock(); |
2621 | if (elems->erp_info && elems->erp_info_len >= 1) { | ||
2622 | bss->erp_value = elems->erp_info[0]; | ||
2623 | bss->has_erp_value = 1; | ||
2624 | } | ||
2625 | 1495 | ||
2626 | if (elems->ht_cap_elem && | 1496 | sta = sta_info_get(local, mgmt->sa); |
2627 | (!bss->ht_ie || bss->ht_ie_len != elems->ht_cap_elem_len || | 1497 | if (sta) { |
2628 | memcmp(bss->ht_ie, elems->ht_cap_elem, elems->ht_cap_elem_len))) { | 1498 | u64 prev_rates; |
2629 | kfree(bss->ht_ie); | ||
2630 | bss->ht_ie = kmalloc(elems->ht_cap_elem_len + 2, GFP_ATOMIC); | ||
2631 | if (bss->ht_ie) { | ||
2632 | memcpy(bss->ht_ie, elems->ht_cap_elem - 2, | ||
2633 | elems->ht_cap_elem_len + 2); | ||
2634 | bss->ht_ie_len = elems->ht_cap_elem_len + 2; | ||
2635 | } else | ||
2636 | bss->ht_ie_len = 0; | ||
2637 | } else if (!elems->ht_cap_elem && bss->ht_ie) { | ||
2638 | kfree(bss->ht_ie); | ||
2639 | bss->ht_ie = NULL; | ||
2640 | bss->ht_ie_len = 0; | ||
2641 | } | ||
2642 | 1499 | ||
2643 | if (elems->ht_info_elem && | 1500 | prev_rates = sta->sta.supp_rates[band]; |
2644 | (!bss->ht_add_ie || | 1501 | /* make sure mandatory rates are always added */ |
2645 | bss->ht_add_ie_len != elems->ht_info_elem_len || | 1502 | sta->sta.supp_rates[band] = supp_rates | |
2646 | memcmp(bss->ht_add_ie, elems->ht_info_elem, | 1503 | ieee80211_mandatory_rates(local, band); |
2647 | elems->ht_info_elem_len))) { | ||
2648 | kfree(bss->ht_add_ie); | ||
2649 | bss->ht_add_ie = | ||
2650 | kmalloc(elems->ht_info_elem_len + 2, GFP_ATOMIC); | ||
2651 | if (bss->ht_add_ie) { | ||
2652 | memcpy(bss->ht_add_ie, elems->ht_info_elem - 2, | ||
2653 | elems->ht_info_elem_len + 2); | ||
2654 | bss->ht_add_ie_len = elems->ht_info_elem_len + 2; | ||
2655 | } else | ||
2656 | bss->ht_add_ie_len = 0; | ||
2657 | } else if (!elems->ht_info_elem && bss->ht_add_ie) { | ||
2658 | kfree(bss->ht_add_ie); | ||
2659 | bss->ht_add_ie = NULL; | ||
2660 | bss->ht_add_ie_len = 0; | ||
2661 | } | ||
2662 | 1504 | ||
2663 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | 1505 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2664 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | 1506 | if (sta->sta.supp_rates[band] != prev_rates) |
1507 | printk(KERN_DEBUG "%s: updated supp_rates set " | ||
1508 | "for %s based on beacon info (0x%llx | " | ||
1509 | "0x%llx -> 0x%llx)\n", | ||
1510 | sdata->dev->name, | ||
1511 | print_mac(mac, sta->sta.addr), | ||
1512 | (unsigned long long) prev_rates, | ||
1513 | (unsigned long long) supp_rates, | ||
1514 | (unsigned long long) sta->sta.supp_rates[band]); | ||
1515 | #endif | ||
1516 | } else { | ||
1517 | ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, | ||
1518 | mgmt->sa, supp_rates); | ||
1519 | } | ||
2665 | 1520 | ||
2666 | if (elems->tim) { | 1521 | rcu_read_unlock(); |
2667 | struct ieee80211_tim_ie *tim_ie = | ||
2668 | (struct ieee80211_tim_ie *)elems->tim; | ||
2669 | bss->dtim_period = tim_ie->dtim_period; | ||
2670 | } | 1522 | } |
2671 | 1523 | ||
2672 | /* set default value for buggy APs */ | 1524 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
2673 | if (!elems->tim || bss->dtim_period == 0) | 1525 | freq, beacon); |
2674 | bss->dtim_period = 1; | 1526 | if (!bss) |
2675 | 1527 | return; | |
2676 | bss->supp_rates_len = 0; | ||
2677 | if (elems->supp_rates) { | ||
2678 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
2679 | if (clen > elems->supp_rates_len) | ||
2680 | clen = elems->supp_rates_len; | ||
2681 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | ||
2682 | clen); | ||
2683 | bss->supp_rates_len += clen; | ||
2684 | } | ||
2685 | if (elems->ext_supp_rates) { | ||
2686 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
2687 | if (clen > elems->ext_supp_rates_len) | ||
2688 | clen = elems->ext_supp_rates_len; | ||
2689 | memcpy(&bss->supp_rates[bss->supp_rates_len], | ||
2690 | elems->ext_supp_rates, clen); | ||
2691 | bss->supp_rates_len += clen; | ||
2692 | } | ||
2693 | 1528 | ||
2694 | bss->band = rx_status->band; | 1529 | /* was just updated in ieee80211_bss_info_update */ |
2695 | 1530 | beacon_timestamp = bss->timestamp; | |
2696 | bss->timestamp = beacon_timestamp; | ||
2697 | bss->last_update = jiffies; | ||
2698 | bss->signal = rx_status->signal; | ||
2699 | bss->noise = rx_status->noise; | ||
2700 | bss->qual = rx_status->qual; | ||
2701 | if (!beacon && !bss->probe_resp) | ||
2702 | bss->probe_resp = true; | ||
2703 | 1531 | ||
2704 | /* | 1532 | /* |
2705 | * In STA mode, the remaining parameters should not be overridden | 1533 | * In STA mode, the remaining parameters should not be overridden |
2706 | * by beacons because they're not necessarily accurate there. | 1534 | * by beacons because they're not necessarily accurate there. |
2707 | */ | 1535 | */ |
2708 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 1536 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC && |
2709 | bss->probe_resp && beacon) { | 1537 | bss->last_probe_resp && beacon) { |
2710 | ieee80211_rx_bss_put(local, bss); | 1538 | ieee80211_rx_bss_put(local, bss); |
2711 | return; | 1539 | return; |
2712 | } | 1540 | } |
2713 | 1541 | ||
2714 | if (elems->wpa && | ||
2715 | (!bss->wpa_ie || bss->wpa_ie_len != elems->wpa_len || | ||
2716 | memcmp(bss->wpa_ie, elems->wpa, elems->wpa_len))) { | ||
2717 | kfree(bss->wpa_ie); | ||
2718 | bss->wpa_ie = kmalloc(elems->wpa_len + 2, GFP_ATOMIC); | ||
2719 | if (bss->wpa_ie) { | ||
2720 | memcpy(bss->wpa_ie, elems->wpa - 2, elems->wpa_len + 2); | ||
2721 | bss->wpa_ie_len = elems->wpa_len + 2; | ||
2722 | } else | ||
2723 | bss->wpa_ie_len = 0; | ||
2724 | } else if (!elems->wpa && bss->wpa_ie) { | ||
2725 | kfree(bss->wpa_ie); | ||
2726 | bss->wpa_ie = NULL; | ||
2727 | bss->wpa_ie_len = 0; | ||
2728 | } | ||
2729 | |||
2730 | if (elems->rsn && | ||
2731 | (!bss->rsn_ie || bss->rsn_ie_len != elems->rsn_len || | ||
2732 | memcmp(bss->rsn_ie, elems->rsn, elems->rsn_len))) { | ||
2733 | kfree(bss->rsn_ie); | ||
2734 | bss->rsn_ie = kmalloc(elems->rsn_len + 2, GFP_ATOMIC); | ||
2735 | if (bss->rsn_ie) { | ||
2736 | memcpy(bss->rsn_ie, elems->rsn - 2, elems->rsn_len + 2); | ||
2737 | bss->rsn_ie_len = elems->rsn_len + 2; | ||
2738 | } else | ||
2739 | bss->rsn_ie_len = 0; | ||
2740 | } else if (!elems->rsn && bss->rsn_ie) { | ||
2741 | kfree(bss->rsn_ie); | ||
2742 | bss->rsn_ie = NULL; | ||
2743 | bss->rsn_ie_len = 0; | ||
2744 | } | ||
2745 | |||
2746 | /* | ||
2747 | * Cf. | ||
2748 | * http://www.wipo.int/pctdb/en/wo.jsp?wo=2007047181&IA=WO2007047181&DISPLAY=DESC | ||
2749 | * | ||
2750 | * quoting: | ||
2751 | * | ||
2752 | * In particular, "Wi-Fi CERTIFIED for WMM - Support for Multimedia | ||
2753 | * Applications with Quality of Service in Wi-Fi Networks," Wi- Fi | ||
2754 | * Alliance (September 1, 2004) is incorporated by reference herein. | ||
2755 | * The inclusion of the WMM Parameters in probe responses and | ||
2756 | * association responses is mandatory for WMM enabled networks. The | ||
2757 | * inclusion of the WMM Parameters in beacons, however, is optional. | ||
2758 | */ | ||
2759 | |||
2760 | if (elems->wmm_param && | ||
2761 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_param_len || | ||
2762 | memcmp(bss->wmm_ie, elems->wmm_param, elems->wmm_param_len))) { | ||
2763 | kfree(bss->wmm_ie); | ||
2764 | bss->wmm_ie = kmalloc(elems->wmm_param_len + 2, GFP_ATOMIC); | ||
2765 | if (bss->wmm_ie) { | ||
2766 | memcpy(bss->wmm_ie, elems->wmm_param - 2, | ||
2767 | elems->wmm_param_len + 2); | ||
2768 | bss->wmm_ie_len = elems->wmm_param_len + 2; | ||
2769 | } else | ||
2770 | bss->wmm_ie_len = 0; | ||
2771 | } else if (elems->wmm_info && | ||
2772 | (!bss->wmm_ie || bss->wmm_ie_len != elems->wmm_info_len || | ||
2773 | memcmp(bss->wmm_ie, elems->wmm_info, | ||
2774 | elems->wmm_info_len))) { | ||
2775 | /* As for certain AP's Fifth bit is not set in WMM IE in | ||
2776 | * beacon frames.So while parsing the beacon frame the | ||
2777 | * wmm_info structure is used instead of wmm_param. | ||
2778 | * wmm_info structure was never used to set bss->wmm_ie. | ||
2779 | * This code fixes this problem by copying the WME | ||
2780 | * information from wmm_info to bss->wmm_ie and enabling | ||
2781 | * n-band association. | ||
2782 | */ | ||
2783 | kfree(bss->wmm_ie); | ||
2784 | bss->wmm_ie = kmalloc(elems->wmm_info_len + 2, GFP_ATOMIC); | ||
2785 | if (bss->wmm_ie) { | ||
2786 | memcpy(bss->wmm_ie, elems->wmm_info - 2, | ||
2787 | elems->wmm_info_len + 2); | ||
2788 | bss->wmm_ie_len = elems->wmm_info_len + 2; | ||
2789 | } else | ||
2790 | bss->wmm_ie_len = 0; | ||
2791 | } else if (!elems->wmm_param && !elems->wmm_info && bss->wmm_ie) { | ||
2792 | kfree(bss->wmm_ie); | ||
2793 | bss->wmm_ie = NULL; | ||
2794 | bss->wmm_ie_len = 0; | ||
2795 | } | ||
2796 | |||
2797 | /* check if we need to merge IBSS */ | 1542 | /* check if we need to merge IBSS */ |
2798 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && beacon && | 1543 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon && |
2799 | !local->sta_sw_scanning && !local->sta_hw_scanning && | ||
2800 | bss->capability & WLAN_CAPABILITY_IBSS && | 1544 | bss->capability & WLAN_CAPABILITY_IBSS && |
2801 | bss->freq == local->oper_channel->center_freq && | 1545 | bss->freq == local->oper_channel->center_freq && |
2802 | elems->ssid_len == sdata->u.sta.ssid_len && | 1546 | elems->ssid_len == sdata->u.sta.ssid_len && |
@@ -2818,7 +1562,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2818 | * e.g: at 1 MBit that means mactime is 192 usec earlier | 1562 | * e.g: at 1 MBit that means mactime is 192 usec earlier |
2819 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 1563 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
2820 | */ | 1564 | */ |
2821 | int rate = local->hw.wiphy->bands[rx_status->band]-> | 1565 | int rate = local->hw.wiphy->bands[band]-> |
2822 | bitrates[rx_status->rate_idx].bitrate; | 1566 | bitrates[rx_status->rate_idx].bitrate; |
2823 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 1567 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
2824 | } else if (local && local->ops && local->ops->get_tsf) | 1568 | } else if (local && local->ops && local->ops->get_tsf) |
@@ -2841,12 +1585,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2841 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1585 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2842 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 1586 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
2843 | "local TSF - IBSS merge with BSSID %s\n", | 1587 | "local TSF - IBSS merge with BSSID %s\n", |
2844 | dev->name, print_mac(mac, mgmt->bssid)); | 1588 | sdata->dev->name, print_mac(mac, mgmt->bssid)); |
2845 | #endif | 1589 | #endif |
2846 | ieee80211_sta_join_ibss(dev, &sdata->u.sta, bss); | 1590 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); |
2847 | ieee80211_ibss_add_sta(dev, NULL, | 1591 | ieee80211_ibss_add_sta(sdata, NULL, |
2848 | mgmt->bssid, mgmt->sa, | 1592 | mgmt->bssid, mgmt->sa, |
2849 | BIT(rx_status->rate_idx)); | 1593 | supp_rates); |
2850 | } | 1594 | } |
2851 | } | 1595 | } |
2852 | 1596 | ||
@@ -2854,13 +1598,17 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2854 | } | 1598 | } |
2855 | 1599 | ||
2856 | 1600 | ||
2857 | static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, | 1601 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
2858 | struct ieee80211_mgmt *mgmt, | 1602 | struct ieee80211_mgmt *mgmt, |
2859 | size_t len, | 1603 | size_t len, |
2860 | struct ieee80211_rx_status *rx_status) | 1604 | struct ieee80211_rx_status *rx_status) |
2861 | { | 1605 | { |
2862 | size_t baselen; | 1606 | size_t baselen; |
2863 | struct ieee802_11_elems elems; | 1607 | struct ieee802_11_elems elems; |
1608 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
1609 | |||
1610 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | ||
1611 | return; /* ignore ProbeResp to foreign address */ | ||
2864 | 1612 | ||
2865 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | 1613 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
2866 | if (baselen > len) | 1614 | if (baselen > len) |
@@ -2869,20 +1617,27 @@ static void ieee80211_rx_mgmt_probe_resp(struct net_device *dev, | |||
2869 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, | 1617 | ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, |
2870 | &elems); | 1618 | &elems); |
2871 | 1619 | ||
2872 | ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 0); | 1620 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1621 | |||
1622 | /* direct probe may be part of the association flow */ | ||
1623 | if (test_and_clear_bit(IEEE80211_STA_REQ_DIRECT_PROBE, | ||
1624 | &ifsta->request)) { | ||
1625 | printk(KERN_DEBUG "%s direct probe responded\n", | ||
1626 | sdata->dev->name); | ||
1627 | ieee80211_authenticate(sdata, ifsta); | ||
1628 | } | ||
2873 | } | 1629 | } |
2874 | 1630 | ||
2875 | 1631 | ||
2876 | static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | 1632 | static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, |
2877 | struct ieee80211_mgmt *mgmt, | 1633 | struct ieee80211_mgmt *mgmt, |
2878 | size_t len, | 1634 | size_t len, |
2879 | struct ieee80211_rx_status *rx_status) | 1635 | struct ieee80211_rx_status *rx_status) |
2880 | { | 1636 | { |
2881 | struct ieee80211_sub_if_data *sdata; | ||
2882 | struct ieee80211_if_sta *ifsta; | 1637 | struct ieee80211_if_sta *ifsta; |
2883 | size_t baselen; | 1638 | size_t baselen; |
2884 | struct ieee802_11_elems elems; | 1639 | struct ieee802_11_elems elems; |
2885 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1640 | struct ieee80211_local *local = sdata->local; |
2886 | struct ieee80211_conf *conf = &local->hw.conf; | 1641 | struct ieee80211_conf *conf = &local->hw.conf; |
2887 | u32 changed = 0; | 1642 | u32 changed = 0; |
2888 | 1643 | ||
@@ -2893,10 +1648,9 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2893 | 1648 | ||
2894 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); | 1649 | ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems); |
2895 | 1650 | ||
2896 | ieee80211_rx_bss_info(dev, mgmt, len, rx_status, &elems, 1); | 1651 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); |
2897 | 1652 | ||
2898 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1653 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
2899 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
2900 | return; | 1654 | return; |
2901 | ifsta = &sdata->u.sta; | 1655 | ifsta = &sdata->u.sta; |
2902 | 1656 | ||
@@ -2904,15 +1658,9 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2904 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) | 1658 | memcmp(ifsta->bssid, mgmt->bssid, ETH_ALEN) != 0) |
2905 | return; | 1659 | return; |
2906 | 1660 | ||
2907 | ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, | 1661 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
2908 | elems.wmm_param_len); | 1662 | elems.wmm_param_len); |
2909 | 1663 | ||
2910 | /* Do not send changes to driver if we are scanning. This removes | ||
2911 | * requirement that driver's bss_info_changed function needs to be | ||
2912 | * atomic. */ | ||
2913 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
2914 | return; | ||
2915 | |||
2916 | if (elems.erp_info && elems.erp_info_len >= 1) | 1664 | if (elems.erp_info && elems.erp_info_len >= 1) |
2917 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); | 1665 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); |
2918 | else { | 1666 | else { |
@@ -2936,14 +1684,13 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev, | |||
2936 | } | 1684 | } |
2937 | 1685 | ||
2938 | 1686 | ||
2939 | static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | 1687 | static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, |
2940 | struct ieee80211_if_sta *ifsta, | 1688 | struct ieee80211_if_sta *ifsta, |
2941 | struct ieee80211_mgmt *mgmt, | 1689 | struct ieee80211_mgmt *mgmt, |
2942 | size_t len, | 1690 | size_t len, |
2943 | struct ieee80211_rx_status *rx_status) | 1691 | struct ieee80211_rx_status *rx_status) |
2944 | { | 1692 | { |
2945 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1693 | struct ieee80211_local *local = sdata->local; |
2946 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
2947 | int tx_last_beacon; | 1694 | int tx_last_beacon; |
2948 | struct sk_buff *skb; | 1695 | struct sk_buff *skb; |
2949 | struct ieee80211_mgmt *resp; | 1696 | struct ieee80211_mgmt *resp; |
@@ -2954,8 +1701,8 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
2954 | DECLARE_MAC_BUF(mac3); | 1701 | DECLARE_MAC_BUF(mac3); |
2955 | #endif | 1702 | #endif |
2956 | 1703 | ||
2957 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS || | 1704 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC || |
2958 | ifsta->state != IEEE80211_IBSS_JOINED || | 1705 | ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || |
2959 | len < 24 + 2 || !ifsta->probe_resp) | 1706 | len < 24 + 2 || !ifsta->probe_resp) |
2960 | return; | 1707 | return; |
2961 | 1708 | ||
@@ -2967,7 +1714,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
2967 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1714 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2968 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" | 1715 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" |
2969 | "%s (tx_last_beacon=%d)\n", | 1716 | "%s (tx_last_beacon=%d)\n", |
2970 | dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), | 1717 | sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), |
2971 | print_mac(mac3, mgmt->bssid), tx_last_beacon); | 1718 | print_mac(mac3, mgmt->bssid), tx_last_beacon); |
2972 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1719 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2973 | 1720 | ||
@@ -2985,7 +1732,7 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
2985 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1732 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2986 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 1733 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " |
2987 | "from %s\n", | 1734 | "from %s\n", |
2988 | dev->name, print_mac(mac, mgmt->sa)); | 1735 | sdata->dev->name, print_mac(mac, mgmt->sa)); |
2989 | #endif | 1736 | #endif |
2990 | return; | 1737 | return; |
2991 | } | 1738 | } |
@@ -3005,74 +1752,15 @@ static void ieee80211_rx_mgmt_probe_req(struct net_device *dev, | |||
3005 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 1752 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
3006 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1753 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3007 | printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", | 1754 | printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", |
3008 | dev->name, print_mac(mac, resp->da)); | 1755 | sdata->dev->name, print_mac(mac, resp->da)); |
3009 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1756 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3010 | ieee80211_sta_tx(dev, skb, 0); | 1757 | ieee80211_tx_skb(sdata, skb, 0); |
3011 | } | 1758 | } |
3012 | 1759 | ||
3013 | static void ieee80211_rx_mgmt_action(struct net_device *dev, | 1760 | void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, |
3014 | struct ieee80211_if_sta *ifsta, | ||
3015 | struct ieee80211_mgmt *mgmt, | ||
3016 | size_t len, | ||
3017 | struct ieee80211_rx_status *rx_status) | ||
3018 | { | ||
3019 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3020 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3021 | |||
3022 | if (len < IEEE80211_MIN_ACTION_SIZE) | ||
3023 | return; | ||
3024 | |||
3025 | switch (mgmt->u.action.category) { | ||
3026 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
3027 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
3028 | break; | ||
3029 | switch (mgmt->u.action.u.chan_switch.action_code) { | ||
3030 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
3031 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3032 | sizeof(mgmt->u.action.u.measurement))) | ||
3033 | break; | ||
3034 | ieee80211_sta_process_measurement_req(dev, mgmt, len); | ||
3035 | break; | ||
3036 | } | ||
3037 | break; | ||
3038 | case WLAN_CATEGORY_BACK: | ||
3039 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
3040 | case WLAN_ACTION_ADDBA_REQ: | ||
3041 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3042 | sizeof(mgmt->u.action.u.addba_req))) | ||
3043 | break; | ||
3044 | ieee80211_sta_process_addba_request(dev, mgmt, len); | ||
3045 | break; | ||
3046 | case WLAN_ACTION_ADDBA_RESP: | ||
3047 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3048 | sizeof(mgmt->u.action.u.addba_resp))) | ||
3049 | break; | ||
3050 | ieee80211_sta_process_addba_resp(dev, mgmt, len); | ||
3051 | break; | ||
3052 | case WLAN_ACTION_DELBA: | ||
3053 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3054 | sizeof(mgmt->u.action.u.delba))) | ||
3055 | break; | ||
3056 | ieee80211_sta_process_delba(dev, mgmt, len); | ||
3057 | break; | ||
3058 | } | ||
3059 | break; | ||
3060 | case PLINK_CATEGORY: | ||
3061 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3062 | mesh_rx_plink_frame(dev, mgmt, len, rx_status); | ||
3063 | break; | ||
3064 | case MESH_PATH_SEL_CATEGORY: | ||
3065 | if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3066 | mesh_rx_path_sel_frame(dev, mgmt, len); | ||
3067 | break; | ||
3068 | } | ||
3069 | } | ||
3070 | |||
3071 | void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | ||
3072 | struct ieee80211_rx_status *rx_status) | 1761 | struct ieee80211_rx_status *rx_status) |
3073 | { | 1762 | { |
3074 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1763 | struct ieee80211_local *local = sdata->local; |
3075 | struct ieee80211_sub_if_data *sdata; | ||
3076 | struct ieee80211_if_sta *ifsta; | 1764 | struct ieee80211_if_sta *ifsta; |
3077 | struct ieee80211_mgmt *mgmt; | 1765 | struct ieee80211_mgmt *mgmt; |
3078 | u16 fc; | 1766 | u16 fc; |
@@ -3080,7 +1768,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3080 | if (skb->len < 24) | 1768 | if (skb->len < 24) |
3081 | goto fail; | 1769 | goto fail; |
3082 | 1770 | ||
3083 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3084 | ifsta = &sdata->u.sta; | 1771 | ifsta = &sdata->u.sta; |
3085 | 1772 | ||
3086 | mgmt = (struct ieee80211_mgmt *) skb->data; | 1773 | mgmt = (struct ieee80211_mgmt *) skb->data; |
@@ -3090,7 +1777,6 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3090 | case IEEE80211_STYPE_PROBE_REQ: | 1777 | case IEEE80211_STYPE_PROBE_REQ: |
3091 | case IEEE80211_STYPE_PROBE_RESP: | 1778 | case IEEE80211_STYPE_PROBE_RESP: |
3092 | case IEEE80211_STYPE_BEACON: | 1779 | case IEEE80211_STYPE_BEACON: |
3093 | case IEEE80211_STYPE_ACTION: | ||
3094 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); | 1780 | memcpy(skb->cb, rx_status, sizeof(*rx_status)); |
3095 | case IEEE80211_STYPE_AUTH: | 1781 | case IEEE80211_STYPE_AUTH: |
3096 | case IEEE80211_STYPE_ASSOC_RESP: | 1782 | case IEEE80211_STYPE_ASSOC_RESP: |
@@ -3106,17 +1792,14 @@ void ieee80211_sta_rx_mgmt(struct net_device *dev, struct sk_buff *skb, | |||
3106 | kfree_skb(skb); | 1792 | kfree_skb(skb); |
3107 | } | 1793 | } |
3108 | 1794 | ||
3109 | 1795 | static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |
3110 | static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | ||
3111 | struct sk_buff *skb) | 1796 | struct sk_buff *skb) |
3112 | { | 1797 | { |
3113 | struct ieee80211_rx_status *rx_status; | 1798 | struct ieee80211_rx_status *rx_status; |
3114 | struct ieee80211_sub_if_data *sdata; | ||
3115 | struct ieee80211_if_sta *ifsta; | 1799 | struct ieee80211_if_sta *ifsta; |
3116 | struct ieee80211_mgmt *mgmt; | 1800 | struct ieee80211_mgmt *mgmt; |
3117 | u16 fc; | 1801 | u16 fc; |
3118 | 1802 | ||
3119 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3120 | ifsta = &sdata->u.sta; | 1803 | ifsta = &sdata->u.sta; |
3121 | 1804 | ||
3122 | rx_status = (struct ieee80211_rx_status *) skb->cb; | 1805 | rx_status = (struct ieee80211_rx_status *) skb->cb; |
@@ -3125,17 +1808,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3125 | 1808 | ||
3126 | switch (fc & IEEE80211_FCTL_STYPE) { | 1809 | switch (fc & IEEE80211_FCTL_STYPE) { |
3127 | case IEEE80211_STYPE_PROBE_REQ: | 1810 | case IEEE80211_STYPE_PROBE_REQ: |
3128 | ieee80211_rx_mgmt_probe_req(dev, ifsta, mgmt, skb->len, | 1811 | ieee80211_rx_mgmt_probe_req(sdata, ifsta, mgmt, skb->len, |
3129 | rx_status); | 1812 | rx_status); |
3130 | break; | 1813 | break; |
3131 | case IEEE80211_STYPE_PROBE_RESP: | 1814 | case IEEE80211_STYPE_PROBE_RESP: |
3132 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); | 1815 | ieee80211_rx_mgmt_probe_resp(sdata, mgmt, skb->len, rx_status); |
3133 | break; | 1816 | break; |
3134 | case IEEE80211_STYPE_BEACON: | 1817 | case IEEE80211_STYPE_BEACON: |
3135 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | 1818 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status); |
3136 | break; | 1819 | break; |
3137 | case IEEE80211_STYPE_AUTH: | 1820 | case IEEE80211_STYPE_AUTH: |
3138 | ieee80211_rx_mgmt_auth(dev, ifsta, mgmt, skb->len); | 1821 | ieee80211_rx_mgmt_auth(sdata, ifsta, mgmt, skb->len); |
3139 | break; | 1822 | break; |
3140 | case IEEE80211_STYPE_ASSOC_RESP: | 1823 | case IEEE80211_STYPE_ASSOC_RESP: |
3141 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); | 1824 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 0); |
@@ -3144,13 +1827,10 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3144 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); | 1827 | ieee80211_rx_mgmt_assoc_resp(sdata, ifsta, mgmt, skb->len, 1); |
3145 | break; | 1828 | break; |
3146 | case IEEE80211_STYPE_DEAUTH: | 1829 | case IEEE80211_STYPE_DEAUTH: |
3147 | ieee80211_rx_mgmt_deauth(dev, ifsta, mgmt, skb->len); | 1830 | ieee80211_rx_mgmt_deauth(sdata, ifsta, mgmt, skb->len); |
3148 | break; | 1831 | break; |
3149 | case IEEE80211_STYPE_DISASSOC: | 1832 | case IEEE80211_STYPE_DISASSOC: |
3150 | ieee80211_rx_mgmt_disassoc(dev, ifsta, mgmt, skb->len); | 1833 | ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); |
3151 | break; | ||
3152 | case IEEE80211_STYPE_ACTION: | ||
3153 | ieee80211_rx_mgmt_action(dev, ifsta, mgmt, skb->len, rx_status); | ||
3154 | break; | 1834 | break; |
3155 | } | 1835 | } |
3156 | 1836 | ||
@@ -3158,47 +1838,11 @@ static void ieee80211_sta_rx_queued_mgmt(struct net_device *dev, | |||
3158 | } | 1838 | } |
3159 | 1839 | ||
3160 | 1840 | ||
3161 | ieee80211_rx_result | 1841 | static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) |
3162 | ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | ||
3163 | struct ieee80211_rx_status *rx_status) | ||
3164 | { | ||
3165 | struct ieee80211_mgmt *mgmt; | ||
3166 | __le16 fc; | ||
3167 | |||
3168 | if (skb->len < 2) | ||
3169 | return RX_DROP_UNUSABLE; | ||
3170 | |||
3171 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
3172 | fc = mgmt->frame_control; | ||
3173 | |||
3174 | if (ieee80211_is_ctl(fc)) | ||
3175 | return RX_CONTINUE; | ||
3176 | |||
3177 | if (skb->len < 24) | ||
3178 | return RX_DROP_MONITOR; | ||
3179 | |||
3180 | if (ieee80211_is_probe_resp(fc)) { | ||
3181 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); | ||
3182 | dev_kfree_skb(skb); | ||
3183 | return RX_QUEUED; | ||
3184 | } | ||
3185 | |||
3186 | if (ieee80211_is_beacon(fc)) { | ||
3187 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | ||
3188 | dev_kfree_skb(skb); | ||
3189 | return RX_QUEUED; | ||
3190 | } | ||
3191 | |||
3192 | return RX_CONTINUE; | ||
3193 | } | ||
3194 | |||
3195 | |||
3196 | static int ieee80211_sta_active_ibss(struct net_device *dev) | ||
3197 | { | 1842 | { |
3198 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1843 | struct ieee80211_local *local = sdata->local; |
3199 | int active = 0; | 1844 | int active = 0; |
3200 | struct sta_info *sta; | 1845 | struct sta_info *sta; |
3201 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3202 | 1846 | ||
3203 | rcu_read_lock(); | 1847 | rcu_read_lock(); |
3204 | 1848 | ||
@@ -3217,179 +1861,36 @@ static int ieee80211_sta_active_ibss(struct net_device *dev) | |||
3217 | } | 1861 | } |
3218 | 1862 | ||
3219 | 1863 | ||
3220 | static void ieee80211_sta_expire(struct net_device *dev, unsigned long exp_time) | 1864 | static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata, |
3221 | { | ||
3222 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3223 | struct sta_info *sta, *tmp; | ||
3224 | LIST_HEAD(tmp_list); | ||
3225 | DECLARE_MAC_BUF(mac); | ||
3226 | unsigned long flags; | ||
3227 | |||
3228 | spin_lock_irqsave(&local->sta_lock, flags); | ||
3229 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
3230 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
3231 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
3232 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
3233 | dev->name, print_mac(mac, sta->addr)); | ||
3234 | #endif | ||
3235 | __sta_info_unlink(&sta); | ||
3236 | if (sta) | ||
3237 | list_add(&sta->list, &tmp_list); | ||
3238 | } | ||
3239 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
3240 | |||
3241 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
3242 | sta_info_destroy(sta); | ||
3243 | } | ||
3244 | |||
3245 | |||
3246 | static void ieee80211_sta_merge_ibss(struct net_device *dev, | ||
3247 | struct ieee80211_if_sta *ifsta) | 1865 | struct ieee80211_if_sta *ifsta) |
3248 | { | 1866 | { |
3249 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); | 1867 | mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL); |
3250 | 1868 | ||
3251 | ieee80211_sta_expire(dev, IEEE80211_IBSS_INACTIVITY_LIMIT); | 1869 | ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT); |
3252 | if (ieee80211_sta_active_ibss(dev)) | 1870 | if (ieee80211_sta_active_ibss(sdata)) |
3253 | return; | 1871 | return; |
3254 | 1872 | ||
3255 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " | 1873 | printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " |
3256 | "IBSS networks with same SSID (merge)\n", dev->name); | 1874 | "IBSS networks with same SSID (merge)\n", sdata->dev->name); |
3257 | ieee80211_sta_req_scan(dev, ifsta->ssid, ifsta->ssid_len); | 1875 | ieee80211_request_scan(sdata, ifsta->ssid, ifsta->ssid_len); |
3258 | } | ||
3259 | |||
3260 | |||
3261 | #ifdef CONFIG_MAC80211_MESH | ||
3262 | static void ieee80211_mesh_housekeeping(struct net_device *dev, | ||
3263 | struct ieee80211_if_sta *ifsta) | ||
3264 | { | ||
3265 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3266 | bool free_plinks; | ||
3267 | |||
3268 | ieee80211_sta_expire(dev, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | ||
3269 | mesh_path_expire(dev); | ||
3270 | |||
3271 | free_plinks = mesh_plink_availables(sdata); | ||
3272 | if (free_plinks != sdata->u.sta.accepting_plinks) | ||
3273 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
3274 | |||
3275 | mod_timer(&ifsta->timer, jiffies + | ||
3276 | IEEE80211_MESH_HOUSEKEEPING_INTERVAL); | ||
3277 | } | 1876 | } |
3278 | 1877 | ||
3279 | 1878 | ||
3280 | void ieee80211_start_mesh(struct net_device *dev) | 1879 | static void ieee80211_sta_timer(unsigned long data) |
3281 | { | ||
3282 | struct ieee80211_if_sta *ifsta; | ||
3283 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3284 | ifsta = &sdata->u.sta; | ||
3285 | ifsta->state = IEEE80211_MESH_UP; | ||
3286 | ieee80211_sta_timer((unsigned long)sdata); | ||
3287 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
3288 | } | ||
3289 | #endif | ||
3290 | |||
3291 | |||
3292 | void ieee80211_sta_timer(unsigned long data) | ||
3293 | { | 1880 | { |
3294 | struct ieee80211_sub_if_data *sdata = | 1881 | struct ieee80211_sub_if_data *sdata = |
3295 | (struct ieee80211_sub_if_data *) data; | 1882 | (struct ieee80211_sub_if_data *) data; |
3296 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 1883 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
3297 | struct ieee80211_local *local = wdev_priv(&sdata->wdev); | 1884 | struct ieee80211_local *local = sdata->local; |
3298 | 1885 | ||
3299 | set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); | 1886 | set_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); |
3300 | queue_work(local->hw.workqueue, &ifsta->work); | 1887 | queue_work(local->hw.workqueue, &ifsta->work); |
3301 | } | 1888 | } |
3302 | 1889 | ||
3303 | void ieee80211_sta_work(struct work_struct *work) | 1890 | static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata, |
3304 | { | ||
3305 | struct ieee80211_sub_if_data *sdata = | ||
3306 | container_of(work, struct ieee80211_sub_if_data, u.sta.work); | ||
3307 | struct net_device *dev = sdata->dev; | ||
3308 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3309 | struct ieee80211_if_sta *ifsta; | ||
3310 | struct sk_buff *skb; | ||
3311 | |||
3312 | if (!netif_running(dev)) | ||
3313 | return; | ||
3314 | |||
3315 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
3316 | return; | ||
3317 | |||
3318 | if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && | ||
3319 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | ||
3320 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) | ||
3321 | return; | ||
3322 | ifsta = &sdata->u.sta; | ||
3323 | |||
3324 | while ((skb = skb_dequeue(&ifsta->skb_queue))) | ||
3325 | ieee80211_sta_rx_queued_mgmt(dev, skb); | ||
3326 | |||
3327 | #ifdef CONFIG_MAC80211_MESH | ||
3328 | if (ifsta->preq_queue_len && | ||
3329 | time_after(jiffies, | ||
3330 | ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval))) | ||
3331 | mesh_path_start_discovery(dev); | ||
3332 | #endif | ||
3333 | |||
3334 | if (ifsta->state != IEEE80211_AUTHENTICATE && | ||
3335 | ifsta->state != IEEE80211_ASSOCIATE && | ||
3336 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { | ||
3337 | if (ifsta->scan_ssid_len) | ||
3338 | ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len); | ||
3339 | else | ||
3340 | ieee80211_sta_start_scan(dev, NULL, 0); | ||
3341 | return; | ||
3342 | } | ||
3343 | |||
3344 | if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { | ||
3345 | if (ieee80211_sta_config_auth(dev, ifsta)) | ||
3346 | return; | ||
3347 | clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); | ||
3348 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) | ||
3349 | return; | ||
3350 | |||
3351 | switch (ifsta->state) { | ||
3352 | case IEEE80211_DISABLED: | ||
3353 | break; | ||
3354 | case IEEE80211_AUTHENTICATE: | ||
3355 | ieee80211_authenticate(dev, ifsta); | ||
3356 | break; | ||
3357 | case IEEE80211_ASSOCIATE: | ||
3358 | ieee80211_associate(dev, ifsta); | ||
3359 | break; | ||
3360 | case IEEE80211_ASSOCIATED: | ||
3361 | ieee80211_associated(dev, ifsta); | ||
3362 | break; | ||
3363 | case IEEE80211_IBSS_SEARCH: | ||
3364 | ieee80211_sta_find_ibss(dev, ifsta); | ||
3365 | break; | ||
3366 | case IEEE80211_IBSS_JOINED: | ||
3367 | ieee80211_sta_merge_ibss(dev, ifsta); | ||
3368 | break; | ||
3369 | #ifdef CONFIG_MAC80211_MESH | ||
3370 | case IEEE80211_MESH_UP: | ||
3371 | ieee80211_mesh_housekeeping(dev, ifsta); | ||
3372 | break; | ||
3373 | #endif | ||
3374 | default: | ||
3375 | WARN_ON(1); | ||
3376 | break; | ||
3377 | } | ||
3378 | |||
3379 | if (ieee80211_privacy_mismatch(dev, ifsta)) { | ||
3380 | printk(KERN_DEBUG "%s: privacy configuration mismatch and " | ||
3381 | "mixed-cell disabled - disassociate\n", dev->name); | ||
3382 | |||
3383 | ieee80211_send_disassoc(dev, ifsta, WLAN_REASON_UNSPECIFIED); | ||
3384 | ieee80211_set_disassoc(dev, ifsta, 0); | ||
3385 | } | ||
3386 | } | ||
3387 | |||
3388 | |||
3389 | static void ieee80211_sta_reset_auth(struct net_device *dev, | ||
3390 | struct ieee80211_if_sta *ifsta) | 1891 | struct ieee80211_if_sta *ifsta) |
3391 | { | 1892 | { |
3392 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1893 | struct ieee80211_local *local = sdata->local; |
3393 | 1894 | ||
3394 | if (local->ops->reset_tsf) { | 1895 | if (local->ops->reset_tsf) { |
3395 | /* Reset own TSF to allow time synchronization work. */ | 1896 | /* Reset own TSF to allow time synchronization work. */ |
@@ -3409,29 +1910,15 @@ static void ieee80211_sta_reset_auth(struct net_device *dev, | |||
3409 | ifsta->auth_alg = WLAN_AUTH_OPEN; | 1910 | ifsta->auth_alg = WLAN_AUTH_OPEN; |
3410 | ifsta->auth_transaction = -1; | 1911 | ifsta->auth_transaction = -1; |
3411 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 1912 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
3412 | ifsta->auth_tries = ifsta->assoc_tries = 0; | 1913 | ifsta->assoc_scan_tries = 0; |
3413 | netif_carrier_off(dev); | 1914 | ifsta->direct_probe_tries = 0; |
1915 | ifsta->auth_tries = 0; | ||
1916 | ifsta->assoc_tries = 0; | ||
1917 | netif_tx_stop_all_queues(sdata->dev); | ||
1918 | netif_carrier_off(sdata->dev); | ||
3414 | } | 1919 | } |
3415 | 1920 | ||
3416 | 1921 | ||
3417 | void ieee80211_sta_req_auth(struct net_device *dev, | ||
3418 | struct ieee80211_if_sta *ifsta) | ||
3419 | { | ||
3420 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3421 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3422 | |||
3423 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
3424 | return; | ||
3425 | |||
3426 | if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | | ||
3427 | IEEE80211_STA_AUTO_BSSID_SEL)) && | ||
3428 | (ifsta->flags & (IEEE80211_STA_SSID_SET | | ||
3429 | IEEE80211_STA_AUTO_SSID_SEL))) { | ||
3430 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
3431 | queue_work(local->hw.workqueue, &ifsta->work); | ||
3432 | } | ||
3433 | } | ||
3434 | |||
3435 | static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | 1922 | static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, |
3436 | const char *ssid, int ssid_len) | 1923 | const char *ssid, int ssid_len) |
3437 | { | 1924 | { |
@@ -3462,81 +1949,11 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | |||
3462 | return 0; | 1949 | return 0; |
3463 | } | 1950 | } |
3464 | 1951 | ||
3465 | static int ieee80211_sta_config_auth(struct net_device *dev, | 1952 | static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, |
3466 | struct ieee80211_if_sta *ifsta) | 1953 | struct ieee80211_if_sta *ifsta) |
3467 | { | 1954 | { |
3468 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1955 | struct ieee80211_local *local = sdata->local; |
3469 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1956 | struct ieee80211_bss *bss; |
3470 | struct ieee80211_sta_bss *bss, *selected = NULL; | ||
3471 | int top_rssi = 0, freq; | ||
3472 | |||
3473 | spin_lock_bh(&local->sta_bss_lock); | ||
3474 | freq = local->oper_channel->center_freq; | ||
3475 | list_for_each_entry(bss, &local->sta_bss_list, list) { | ||
3476 | if (!(bss->capability & WLAN_CAPABILITY_ESS)) | ||
3477 | continue; | ||
3478 | |||
3479 | if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | | ||
3480 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
3481 | IEEE80211_STA_AUTO_CHANNEL_SEL)) && | ||
3482 | (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ | ||
3483 | !!sdata->default_key)) | ||
3484 | continue; | ||
3485 | |||
3486 | if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && | ||
3487 | bss->freq != freq) | ||
3488 | continue; | ||
3489 | |||
3490 | if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && | ||
3491 | memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) | ||
3492 | continue; | ||
3493 | |||
3494 | if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && | ||
3495 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) | ||
3496 | continue; | ||
3497 | |||
3498 | if (!selected || top_rssi < bss->signal) { | ||
3499 | selected = bss; | ||
3500 | top_rssi = bss->signal; | ||
3501 | } | ||
3502 | } | ||
3503 | if (selected) | ||
3504 | atomic_inc(&selected->users); | ||
3505 | spin_unlock_bh(&local->sta_bss_lock); | ||
3506 | |||
3507 | if (selected) { | ||
3508 | ieee80211_set_freq(dev, selected->freq); | ||
3509 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) | ||
3510 | ieee80211_sta_set_ssid(dev, selected->ssid, | ||
3511 | selected->ssid_len); | ||
3512 | ieee80211_sta_set_bssid(dev, selected->bssid); | ||
3513 | ieee80211_sta_def_wmm_params(dev, selected, 0); | ||
3514 | ieee80211_rx_bss_put(local, selected); | ||
3515 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
3516 | ieee80211_sta_reset_auth(dev, ifsta); | ||
3517 | return 0; | ||
3518 | } else { | ||
3519 | if (ifsta->state != IEEE80211_AUTHENTICATE) { | ||
3520 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) | ||
3521 | ieee80211_sta_start_scan(dev, NULL, 0); | ||
3522 | else | ||
3523 | ieee80211_sta_start_scan(dev, ifsta->ssid, | ||
3524 | ifsta->ssid_len); | ||
3525 | ifsta->state = IEEE80211_AUTHENTICATE; | ||
3526 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
3527 | } else | ||
3528 | ifsta->state = IEEE80211_DISABLED; | ||
3529 | } | ||
3530 | return -1; | ||
3531 | } | ||
3532 | |||
3533 | |||
3534 | static int ieee80211_sta_create_ibss(struct net_device *dev, | ||
3535 | struct ieee80211_if_sta *ifsta) | ||
3536 | { | ||
3537 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3538 | struct ieee80211_sta_bss *bss; | ||
3539 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3540 | struct ieee80211_supported_band *sband; | 1957 | struct ieee80211_supported_band *sband; |
3541 | u8 bssid[ETH_ALEN], *pos; | 1958 | u8 bssid[ETH_ALEN], *pos; |
3542 | int i; | 1959 | int i; |
@@ -3552,15 +1969,15 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3552 | * random number generator get different BSSID. */ | 1969 | * random number generator get different BSSID. */ |
3553 | get_random_bytes(bssid, ETH_ALEN); | 1970 | get_random_bytes(bssid, ETH_ALEN); |
3554 | for (i = 0; i < ETH_ALEN; i++) | 1971 | for (i = 0; i < ETH_ALEN; i++) |
3555 | bssid[i] ^= dev->dev_addr[i]; | 1972 | bssid[i] ^= sdata->dev->dev_addr[i]; |
3556 | bssid[0] &= ~0x01; | 1973 | bssid[0] &= ~0x01; |
3557 | bssid[0] |= 0x02; | 1974 | bssid[0] |= 0x02; |
3558 | #endif | 1975 | #endif |
3559 | 1976 | ||
3560 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 1977 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", |
3561 | dev->name, print_mac(mac, bssid)); | 1978 | sdata->dev->name, print_mac(mac, bssid)); |
3562 | 1979 | ||
3563 | bss = ieee80211_rx_bss_add(dev, bssid, | 1980 | bss = ieee80211_rx_bss_add(local, bssid, |
3564 | local->hw.conf.channel->center_freq, | 1981 | local->hw.conf.channel->center_freq, |
3565 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | 1982 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); |
3566 | if (!bss) | 1983 | if (!bss) |
@@ -3587,17 +2004,17 @@ static int ieee80211_sta_create_ibss(struct net_device *dev, | |||
3587 | *pos++ = (u8) (rate / 5); | 2004 | *pos++ = (u8) (rate / 5); |
3588 | } | 2005 | } |
3589 | 2006 | ||
3590 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 2007 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
3591 | ieee80211_rx_bss_put(local, bss); | 2008 | ieee80211_rx_bss_put(local, bss); |
3592 | return ret; | 2009 | return ret; |
3593 | } | 2010 | } |
3594 | 2011 | ||
3595 | 2012 | ||
3596 | static int ieee80211_sta_find_ibss(struct net_device *dev, | 2013 | static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, |
3597 | struct ieee80211_if_sta *ifsta) | 2014 | struct ieee80211_if_sta *ifsta) |
3598 | { | 2015 | { |
3599 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2016 | struct ieee80211_local *local = sdata->local; |
3600 | struct ieee80211_sta_bss *bss; | 2017 | struct ieee80211_bss *bss; |
3601 | int found = 0; | 2018 | int found = 0; |
3602 | u8 bssid[ETH_ALEN]; | 2019 | u8 bssid[ETH_ALEN]; |
3603 | int active_ibss; | 2020 | int active_ibss; |
@@ -3607,13 +2024,13 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3607 | if (ifsta->ssid_len == 0) | 2024 | if (ifsta->ssid_len == 0) |
3608 | return -EINVAL; | 2025 | return -EINVAL; |
3609 | 2026 | ||
3610 | active_ibss = ieee80211_sta_active_ibss(dev); | 2027 | active_ibss = ieee80211_sta_active_ibss(sdata); |
3611 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2028 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3612 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 2029 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
3613 | dev->name, active_ibss); | 2030 | sdata->dev->name, active_ibss); |
3614 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2031 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3615 | spin_lock_bh(&local->sta_bss_lock); | 2032 | spin_lock_bh(&local->bss_lock); |
3616 | list_for_each_entry(bss, &local->sta_bss_list, list) { | 2033 | list_for_each_entry(bss, &local->bss_list, list) { |
3617 | if (ifsta->ssid_len != bss->ssid_len || | 2034 | if (ifsta->ssid_len != bss->ssid_len || |
3618 | memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 | 2035 | memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0 |
3619 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) | 2036 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) |
@@ -3627,7 +2044,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3627 | if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) | 2044 | if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0) |
3628 | break; | 2045 | break; |
3629 | } | 2046 | } |
3630 | spin_unlock_bh(&local->sta_bss_lock); | 2047 | spin_unlock_bh(&local->bss_lock); |
3631 | 2048 | ||
3632 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2049 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
3633 | if (found) | 2050 | if (found) |
@@ -3645,15 +2062,15 @@ static int ieee80211_sta_find_ibss(struct net_device *dev, | |||
3645 | else | 2062 | else |
3646 | search_freq = local->hw.conf.channel->center_freq; | 2063 | search_freq = local->hw.conf.channel->center_freq; |
3647 | 2064 | ||
3648 | bss = ieee80211_rx_bss_get(dev, bssid, search_freq, | 2065 | bss = ieee80211_rx_bss_get(local, bssid, search_freq, |
3649 | ifsta->ssid, ifsta->ssid_len); | 2066 | ifsta->ssid, ifsta->ssid_len); |
3650 | if (!bss) | 2067 | if (!bss) |
3651 | goto dont_join; | 2068 | goto dont_join; |
3652 | 2069 | ||
3653 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2070 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" |
3654 | " based on configured SSID\n", | 2071 | " based on configured SSID\n", |
3655 | dev->name, print_mac(mac, bssid)); | 2072 | sdata->dev->name, print_mac(mac, bssid)); |
3656 | ret = ieee80211_sta_join_ibss(dev, ifsta, bss); | 2073 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
3657 | ieee80211_rx_bss_put(local, bss); | 2074 | ieee80211_rx_bss_put(local, bss); |
3658 | return ret; | 2075 | return ret; |
3659 | } | 2076 | } |
@@ -3664,17 +2081,17 @@ dont_join: | |||
3664 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2081 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
3665 | 2082 | ||
3666 | /* Selected IBSS not found in current scan results - try to scan */ | 2083 | /* Selected IBSS not found in current scan results - try to scan */ |
3667 | if (ifsta->state == IEEE80211_IBSS_JOINED && | 2084 | if (ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED && |
3668 | !ieee80211_sta_active_ibss(dev)) { | 2085 | !ieee80211_sta_active_ibss(sdata)) { |
3669 | mod_timer(&ifsta->timer, jiffies + | 2086 | mod_timer(&ifsta->timer, jiffies + |
3670 | IEEE80211_IBSS_MERGE_INTERVAL); | 2087 | IEEE80211_IBSS_MERGE_INTERVAL); |
3671 | } else if (time_after(jiffies, local->last_scan_completed + | 2088 | } else if (time_after(jiffies, local->last_scan_completed + |
3672 | IEEE80211_SCAN_INTERVAL)) { | 2089 | IEEE80211_SCAN_INTERVAL)) { |
3673 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " | 2090 | printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " |
3674 | "join\n", dev->name); | 2091 | "join\n", sdata->dev->name); |
3675 | return ieee80211_sta_req_scan(dev, ifsta->ssid, | 2092 | return ieee80211_request_scan(sdata, ifsta->ssid, |
3676 | ifsta->ssid_len); | 2093 | ifsta->ssid_len); |
3677 | } else if (ifsta->state != IEEE80211_IBSS_JOINED) { | 2094 | } else if (ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED) { |
3678 | int interval = IEEE80211_SCAN_INTERVAL; | 2095 | int interval = IEEE80211_SCAN_INTERVAL; |
3679 | 2096 | ||
3680 | if (time_after(jiffies, ifsta->ibss_join_req + | 2097 | if (time_after(jiffies, ifsta->ibss_join_req + |
@@ -3682,10 +2099,10 @@ dont_join: | |||
3682 | if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && | 2099 | if ((ifsta->flags & IEEE80211_STA_CREATE_IBSS) && |
3683 | (!(local->oper_channel->flags & | 2100 | (!(local->oper_channel->flags & |
3684 | IEEE80211_CHAN_NO_IBSS))) | 2101 | IEEE80211_CHAN_NO_IBSS))) |
3685 | return ieee80211_sta_create_ibss(dev, ifsta); | 2102 | return ieee80211_sta_create_ibss(sdata, ifsta); |
3686 | if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { | 2103 | if (ifsta->flags & IEEE80211_STA_CREATE_IBSS) { |
3687 | printk(KERN_DEBUG "%s: IBSS not allowed on" | 2104 | printk(KERN_DEBUG "%s: IBSS not allowed on" |
3688 | " %d MHz\n", dev->name, | 2105 | " %d MHz\n", sdata->dev->name, |
3689 | local->hw.conf.channel->center_freq); | 2106 | local->hw.conf.channel->center_freq); |
3690 | } | 2107 | } |
3691 | 2108 | ||
@@ -3694,7 +2111,7 @@ dont_join: | |||
3694 | interval = IEEE80211_SCAN_INTERVAL_SLOW; | 2111 | interval = IEEE80211_SCAN_INTERVAL_SLOW; |
3695 | } | 2112 | } |
3696 | 2113 | ||
3697 | ifsta->state = IEEE80211_IBSS_SEARCH; | 2114 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; |
3698 | mod_timer(&ifsta->timer, jiffies + interval); | 2115 | mod_timer(&ifsta->timer, jiffies + interval); |
3699 | return 0; | 2116 | return 0; |
3700 | } | 2117 | } |
@@ -3703,620 +2120,344 @@ dont_join: | |||
3703 | } | 2120 | } |
3704 | 2121 | ||
3705 | 2122 | ||
3706 | int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | 2123 | static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, |
2124 | struct ieee80211_if_sta *ifsta) | ||
3707 | { | 2125 | { |
3708 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2126 | struct ieee80211_local *local = sdata->local; |
3709 | struct ieee80211_if_sta *ifsta; | 2127 | struct ieee80211_bss *bss, *selected = NULL; |
3710 | int res; | 2128 | int top_rssi = 0, freq; |
3711 | 2129 | ||
3712 | if (len > IEEE80211_MAX_SSID_LEN) | 2130 | spin_lock_bh(&local->bss_lock); |
3713 | return -EINVAL; | 2131 | freq = local->oper_channel->center_freq; |
2132 | list_for_each_entry(bss, &local->bss_list, list) { | ||
2133 | if (!(bss->capability & WLAN_CAPABILITY_ESS)) | ||
2134 | continue; | ||
3714 | 2135 | ||
3715 | ifsta = &sdata->u.sta; | 2136 | if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL | |
2137 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
2138 | IEEE80211_STA_AUTO_CHANNEL_SEL)) && | ||
2139 | (!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^ | ||
2140 | !!sdata->default_key)) | ||
2141 | continue; | ||
3716 | 2142 | ||
3717 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { | 2143 | if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) && |
3718 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); | 2144 | bss->freq != freq) |
3719 | memcpy(ifsta->ssid, ssid, len); | 2145 | continue; |
3720 | ifsta->ssid_len = len; | ||
3721 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | ||
3722 | 2146 | ||
3723 | res = 0; | 2147 | if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) && |
3724 | /* | 2148 | memcmp(bss->bssid, ifsta->bssid, ETH_ALEN)) |
3725 | * Hack! MLME code needs to be cleaned up to have different | 2149 | continue; |
3726 | * entry points for configuration and internal selection change | ||
3727 | */ | ||
3728 | if (netif_running(sdata->dev)) | ||
3729 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
3730 | if (res) { | ||
3731 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
3732 | "the low-level driver\n", dev->name); | ||
3733 | return res; | ||
3734 | } | ||
3735 | } | ||
3736 | 2150 | ||
3737 | if (len) | 2151 | if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) && |
3738 | ifsta->flags |= IEEE80211_STA_SSID_SET; | 2152 | !ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len)) |
3739 | else | 2153 | continue; |
3740 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | ||
3741 | 2154 | ||
3742 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | 2155 | if (!selected || top_rssi < bss->signal) { |
3743 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { | 2156 | selected = bss; |
3744 | ifsta->ibss_join_req = jiffies; | 2157 | top_rssi = bss->signal; |
3745 | ifsta->state = IEEE80211_IBSS_SEARCH; | 2158 | } |
3746 | return ieee80211_sta_find_ibss(dev, ifsta); | ||
3747 | } | 2159 | } |
2160 | if (selected) | ||
2161 | atomic_inc(&selected->users); | ||
2162 | spin_unlock_bh(&local->bss_lock); | ||
3748 | 2163 | ||
3749 | return 0; | 2164 | if (selected) { |
3750 | } | 2165 | ieee80211_set_freq(sdata, selected->freq); |
2166 | if (!(ifsta->flags & IEEE80211_STA_SSID_SET)) | ||
2167 | ieee80211_sta_set_ssid(sdata, selected->ssid, | ||
2168 | selected->ssid_len); | ||
2169 | ieee80211_sta_set_bssid(sdata, selected->bssid); | ||
2170 | ieee80211_sta_def_wmm_params(sdata, selected); | ||
3751 | 2171 | ||
2172 | /* Send out direct probe if no probe resp was received or | ||
2173 | * the one we have is outdated | ||
2174 | */ | ||
2175 | if (!selected->last_probe_resp || | ||
2176 | time_after(jiffies, selected->last_probe_resp | ||
2177 | + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
2178 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | ||
2179 | else | ||
2180 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
3752 | 2181 | ||
3753 | int ieee80211_sta_get_ssid(struct net_device *dev, char *ssid, size_t *len) | 2182 | ieee80211_rx_bss_put(local, selected); |
3754 | { | 2183 | ieee80211_sta_reset_auth(sdata, ifsta); |
3755 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2184 | return 0; |
3756 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2185 | } else { |
3757 | memcpy(ssid, ifsta->ssid, ifsta->ssid_len); | 2186 | if (ifsta->assoc_scan_tries < IEEE80211_ASSOC_SCANS_MAX_TRIES) { |
3758 | *len = ifsta->ssid_len; | 2187 | ifsta->assoc_scan_tries++; |
3759 | return 0; | 2188 | if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) |
2189 | ieee80211_start_scan(sdata, NULL, 0); | ||
2190 | else | ||
2191 | ieee80211_start_scan(sdata, ifsta->ssid, | ||
2192 | ifsta->ssid_len); | ||
2193 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | ||
2194 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); | ||
2195 | } else | ||
2196 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | ||
2197 | } | ||
2198 | return -1; | ||
3760 | } | 2199 | } |
3761 | 2200 | ||
3762 | 2201 | ||
3763 | int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid) | 2202 | static void ieee80211_sta_work(struct work_struct *work) |
3764 | { | 2203 | { |
3765 | struct ieee80211_sub_if_data *sdata; | 2204 | struct ieee80211_sub_if_data *sdata = |
2205 | container_of(work, struct ieee80211_sub_if_data, u.sta.work); | ||
2206 | struct ieee80211_local *local = sdata->local; | ||
3766 | struct ieee80211_if_sta *ifsta; | 2207 | struct ieee80211_if_sta *ifsta; |
3767 | int res; | 2208 | struct sk_buff *skb; |
3768 | |||
3769 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3770 | ifsta = &sdata->u.sta; | ||
3771 | 2209 | ||
3772 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 2210 | if (!netif_running(sdata->dev)) |
3773 | memcpy(ifsta->bssid, bssid, ETH_ALEN); | 2211 | return; |
3774 | res = 0; | ||
3775 | /* | ||
3776 | * Hack! See also ieee80211_sta_set_ssid. | ||
3777 | */ | ||
3778 | if (netif_running(sdata->dev)) | ||
3779 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | ||
3780 | if (res) { | ||
3781 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " | ||
3782 | "the low-level driver\n", dev->name); | ||
3783 | return res; | ||
3784 | } | ||
3785 | } | ||
3786 | 2212 | ||
3787 | if (is_valid_ether_addr(bssid)) | 2213 | if (local->sw_scanning || local->hw_scanning) |
3788 | ifsta->flags |= IEEE80211_STA_BSSID_SET; | 2214 | return; |
3789 | else | ||
3790 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; | ||
3791 | 2215 | ||
3792 | return 0; | 2216 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION && |
3793 | } | 2217 | sdata->vif.type != NL80211_IFTYPE_ADHOC)) |
2218 | return; | ||
2219 | ifsta = &sdata->u.sta; | ||
3794 | 2220 | ||
2221 | while ((skb = skb_dequeue(&ifsta->skb_queue))) | ||
2222 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | ||
3795 | 2223 | ||
3796 | static void ieee80211_send_nullfunc(struct ieee80211_local *local, | 2224 | if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && |
3797 | struct ieee80211_sub_if_data *sdata, | 2225 | ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
3798 | int powersave) | 2226 | ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && |
3799 | { | 2227 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) { |
3800 | struct sk_buff *skb; | 2228 | ieee80211_start_scan(sdata, ifsta->scan_ssid, |
3801 | struct ieee80211_hdr *nullfunc; | 2229 | ifsta->scan_ssid_len); |
3802 | __le16 fc; | 2230 | return; |
2231 | } | ||
3803 | 2232 | ||
3804 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 2233 | if (test_and_clear_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request)) { |
3805 | if (!skb) { | 2234 | if (ieee80211_sta_config_auth(sdata, ifsta)) |
3806 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | 2235 | return; |
3807 | "frame\n", sdata->dev->name); | 2236 | clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request); |
2237 | } else if (!test_and_clear_bit(IEEE80211_STA_REQ_RUN, &ifsta->request)) | ||
3808 | return; | 2238 | return; |
2239 | |||
2240 | switch (ifsta->state) { | ||
2241 | case IEEE80211_STA_MLME_DISABLED: | ||
2242 | break; | ||
2243 | case IEEE80211_STA_MLME_DIRECT_PROBE: | ||
2244 | ieee80211_direct_probe(sdata, ifsta); | ||
2245 | break; | ||
2246 | case IEEE80211_STA_MLME_AUTHENTICATE: | ||
2247 | ieee80211_authenticate(sdata, ifsta); | ||
2248 | break; | ||
2249 | case IEEE80211_STA_MLME_ASSOCIATE: | ||
2250 | ieee80211_associate(sdata, ifsta); | ||
2251 | break; | ||
2252 | case IEEE80211_STA_MLME_ASSOCIATED: | ||
2253 | ieee80211_associated(sdata, ifsta); | ||
2254 | break; | ||
2255 | case IEEE80211_STA_MLME_IBSS_SEARCH: | ||
2256 | ieee80211_sta_find_ibss(sdata, ifsta); | ||
2257 | break; | ||
2258 | case IEEE80211_STA_MLME_IBSS_JOINED: | ||
2259 | ieee80211_sta_merge_ibss(sdata, ifsta); | ||
2260 | break; | ||
2261 | default: | ||
2262 | WARN_ON(1); | ||
2263 | break; | ||
3809 | } | 2264 | } |
3810 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
3811 | 2265 | ||
3812 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | 2266 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { |
3813 | memset(nullfunc, 0, 24); | 2267 | printk(KERN_DEBUG "%s: privacy configuration mismatch and " |
3814 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | 2268 | "mixed-cell disabled - disassociate\n", sdata->dev->name); |
3815 | IEEE80211_FCTL_TODS); | ||
3816 | if (powersave) | ||
3817 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
3818 | nullfunc->frame_control = fc; | ||
3819 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | ||
3820 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | ||
3821 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | ||
3822 | |||
3823 | ieee80211_sta_tx(sdata->dev, skb, 0); | ||
3824 | } | ||
3825 | 2269 | ||
2270 | ieee80211_set_disassoc(sdata, ifsta, false, true, | ||
2271 | WLAN_REASON_UNSPECIFIED); | ||
2272 | } | ||
2273 | } | ||
3826 | 2274 | ||
3827 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | 2275 | static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) |
3828 | { | 2276 | { |
3829 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 2277 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
3830 | ieee80211_vif_is_mesh(&sdata->vif)) | 2278 | queue_work(sdata->local->hw.workqueue, |
3831 | ieee80211_sta_timer((unsigned long)sdata); | 2279 | &sdata->u.sta.work); |
3832 | } | 2280 | } |
3833 | 2281 | ||
3834 | void ieee80211_scan_completed(struct ieee80211_hw *hw) | 2282 | /* interface setup */ |
2283 | void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | ||
3835 | { | 2284 | { |
3836 | struct ieee80211_local *local = hw_to_local(hw); | 2285 | struct ieee80211_if_sta *ifsta; |
3837 | struct net_device *dev = local->scan_dev; | ||
3838 | struct ieee80211_sub_if_data *sdata; | ||
3839 | union iwreq_data wrqu; | ||
3840 | 2286 | ||
3841 | local->last_scan_completed = jiffies; | 2287 | ifsta = &sdata->u.sta; |
3842 | memset(&wrqu, 0, sizeof(wrqu)); | 2288 | INIT_WORK(&ifsta->work, ieee80211_sta_work); |
3843 | wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL); | 2289 | setup_timer(&ifsta->timer, ieee80211_sta_timer, |
3844 | 2290 | (unsigned long) sdata); | |
3845 | if (local->sta_hw_scanning) { | 2291 | skb_queue_head_init(&ifsta->skb_queue); |
3846 | local->sta_hw_scanning = 0; | ||
3847 | if (ieee80211_hw_config(local)) | ||
3848 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
3849 | "channel after scan\n", dev->name); | ||
3850 | /* Restart STA timer for HW scan case */ | ||
3851 | rcu_read_lock(); | ||
3852 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
3853 | ieee80211_restart_sta_timer(sdata); | ||
3854 | rcu_read_unlock(); | ||
3855 | 2292 | ||
3856 | goto done; | 2293 | ifsta->capab = WLAN_CAPABILITY_ESS; |
2294 | ifsta->auth_algs = IEEE80211_AUTH_ALG_OPEN | | ||
2295 | IEEE80211_AUTH_ALG_SHARED_KEY; | ||
2296 | ifsta->flags |= IEEE80211_STA_CREATE_IBSS | | ||
2297 | IEEE80211_STA_AUTO_BSSID_SEL | | ||
2298 | IEEE80211_STA_AUTO_CHANNEL_SEL; | ||
2299 | if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) | ||
2300 | ifsta->flags |= IEEE80211_STA_WMM_ENABLED; | ||
2301 | } | ||
2302 | |||
2303 | /* | ||
2304 | * Add a new IBSS station, will also be called by the RX code when, | ||
2305 | * in IBSS mode, receiving a frame from a yet-unknown station, hence | ||
2306 | * must be callable in atomic context. | ||
2307 | */ | ||
2308 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | ||
2309 | struct sk_buff *skb, u8 *bssid, | ||
2310 | u8 *addr, u64 supp_rates) | ||
2311 | { | ||
2312 | struct ieee80211_local *local = sdata->local; | ||
2313 | struct sta_info *sta; | ||
2314 | DECLARE_MAC_BUF(mac); | ||
2315 | int band = local->hw.conf.channel->band; | ||
2316 | |||
2317 | /* TODO: Could consider removing the least recently used entry and | ||
2318 | * allow new one to be added. */ | ||
2319 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
2320 | if (net_ratelimit()) { | ||
2321 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " | ||
2322 | "entry %s\n", sdata->dev->name, print_mac(mac, addr)); | ||
2323 | } | ||
2324 | return NULL; | ||
3857 | } | 2325 | } |
3858 | 2326 | ||
3859 | local->sta_sw_scanning = 0; | 2327 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) |
3860 | if (ieee80211_hw_config(local)) | 2328 | return NULL; |
3861 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
3862 | "channel after scan\n", dev->name); | ||
3863 | 2329 | ||
2330 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
2331 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | ||
2332 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); | ||
2333 | #endif | ||
3864 | 2334 | ||
3865 | netif_tx_lock_bh(local->mdev); | 2335 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
3866 | netif_addr_lock(local->mdev); | 2336 | if (!sta) |
3867 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | 2337 | return NULL; |
3868 | local->ops->configure_filter(local_to_hw(local), | ||
3869 | FIF_BCN_PRBRESP_PROMISC, | ||
3870 | &local->filter_flags, | ||
3871 | local->mdev->mc_count, | ||
3872 | local->mdev->mc_list); | ||
3873 | 2338 | ||
3874 | netif_addr_unlock(local->mdev); | 2339 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); |
3875 | netif_tx_unlock_bh(local->mdev); | ||
3876 | 2340 | ||
3877 | rcu_read_lock(); | 2341 | /* make sure mandatory rates are always added */ |
3878 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2342 | sta->sta.supp_rates[band] = supp_rates | |
3879 | /* Tell AP we're back */ | 2343 | ieee80211_mandatory_rates(local, band); |
3880 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | ||
3881 | sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) | ||
3882 | ieee80211_send_nullfunc(local, sdata, 0); | ||
3883 | 2344 | ||
3884 | ieee80211_restart_sta_timer(sdata); | 2345 | rate_control_rate_init(sta, local); |
3885 | 2346 | ||
3886 | netif_wake_queue(sdata->dev); | 2347 | if (sta_info_insert(sta)) |
3887 | } | 2348 | return NULL; |
3888 | rcu_read_unlock(); | ||
3889 | 2349 | ||
3890 | done: | 2350 | return sta; |
3891 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3892 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | ||
3893 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
3894 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | ||
3895 | (!(ifsta->state == IEEE80211_IBSS_JOINED) && | ||
3896 | !ieee80211_sta_active_ibss(dev))) | ||
3897 | ieee80211_sta_find_ibss(dev, ifsta); | ||
3898 | } | ||
3899 | } | 2351 | } |
3900 | EXPORT_SYMBOL(ieee80211_scan_completed); | ||
3901 | 2352 | ||
3902 | void ieee80211_sta_scan_work(struct work_struct *work) | 2353 | /* configuration hooks */ |
2354 | void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, | ||
2355 | struct ieee80211_if_sta *ifsta) | ||
3903 | { | 2356 | { |
3904 | struct ieee80211_local *local = | 2357 | struct ieee80211_local *local = sdata->local; |
3905 | container_of(work, struct ieee80211_local, scan_work.work); | ||
3906 | struct net_device *dev = local->scan_dev; | ||
3907 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3908 | struct ieee80211_supported_band *sband; | ||
3909 | struct ieee80211_channel *chan; | ||
3910 | int skip; | ||
3911 | unsigned long next_delay = 0; | ||
3912 | 2358 | ||
3913 | if (!local->sta_sw_scanning) | 2359 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
3914 | return; | 2360 | return; |
3915 | 2361 | ||
3916 | switch (local->scan_state) { | 2362 | if ((ifsta->flags & (IEEE80211_STA_BSSID_SET | |
3917 | case SCAN_SET_CHANNEL: | 2363 | IEEE80211_STA_AUTO_BSSID_SEL)) && |
3918 | /* | 2364 | (ifsta->flags & (IEEE80211_STA_SSID_SET | |
3919 | * Get current scan band. scan_band may be IEEE80211_NUM_BANDS | 2365 | IEEE80211_STA_AUTO_SSID_SEL))) { |
3920 | * after we successfully scanned the last channel of the last | ||
3921 | * band (and the last band is supported by the hw) | ||
3922 | */ | ||
3923 | if (local->scan_band < IEEE80211_NUM_BANDS) | ||
3924 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
3925 | else | ||
3926 | sband = NULL; | ||
3927 | |||
3928 | /* | ||
3929 | * If we are at an unsupported band and have more bands | ||
3930 | * left to scan, advance to the next supported one. | ||
3931 | */ | ||
3932 | while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { | ||
3933 | local->scan_band++; | ||
3934 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
3935 | local->scan_channel_idx = 0; | ||
3936 | } | ||
3937 | |||
3938 | /* if no more bands/channels left, complete scan */ | ||
3939 | if (!sband || local->scan_channel_idx >= sband->n_channels) { | ||
3940 | ieee80211_scan_completed(local_to_hw(local)); | ||
3941 | return; | ||
3942 | } | ||
3943 | skip = 0; | ||
3944 | chan = &sband->channels[local->scan_channel_idx]; | ||
3945 | |||
3946 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
3947 | (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
3948 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
3949 | skip = 1; | ||
3950 | |||
3951 | if (!skip) { | ||
3952 | local->scan_channel = chan; | ||
3953 | if (ieee80211_hw_config(local)) { | ||
3954 | printk(KERN_DEBUG "%s: failed to set freq to " | ||
3955 | "%d MHz for scan\n", dev->name, | ||
3956 | chan->center_freq); | ||
3957 | skip = 1; | ||
3958 | } | ||
3959 | } | ||
3960 | |||
3961 | /* advance state machine to next channel/band */ | ||
3962 | local->scan_channel_idx++; | ||
3963 | if (local->scan_channel_idx >= sband->n_channels) { | ||
3964 | /* | ||
3965 | * scan_band may end up == IEEE80211_NUM_BANDS, but | ||
3966 | * we'll catch that case above and complete the scan | ||
3967 | * if that is the case. | ||
3968 | */ | ||
3969 | local->scan_band++; | ||
3970 | local->scan_channel_idx = 0; | ||
3971 | } | ||
3972 | |||
3973 | if (skip) | ||
3974 | break; | ||
3975 | 2366 | ||
3976 | next_delay = IEEE80211_PROBE_DELAY + | 2367 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) |
3977 | usecs_to_jiffies(local->hw.channel_change_time); | 2368 | ieee80211_set_disassoc(sdata, ifsta, true, true, |
3978 | local->scan_state = SCAN_SEND_PROBE; | 2369 | WLAN_REASON_DEAUTH_LEAVING); |
3979 | break; | ||
3980 | case SCAN_SEND_PROBE: | ||
3981 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
3982 | local->scan_state = SCAN_SET_CHANNEL; | ||
3983 | 2370 | ||
3984 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) | 2371 | set_bit(IEEE80211_STA_REQ_AUTH, &ifsta->request); |
3985 | break; | 2372 | queue_work(local->hw.workqueue, &ifsta->work); |
3986 | ieee80211_send_probe_req(dev, NULL, local->scan_ssid, | ||
3987 | local->scan_ssid_len); | ||
3988 | next_delay = IEEE80211_CHANNEL_TIME; | ||
3989 | break; | ||
3990 | } | 2373 | } |
3991 | |||
3992 | if (local->sta_sw_scanning) | ||
3993 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
3994 | next_delay); | ||
3995 | } | 2374 | } |
3996 | 2375 | ||
3997 | 2376 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) | |
3998 | static int ieee80211_sta_start_scan(struct net_device *dev, | ||
3999 | u8 *ssid, size_t ssid_len) | ||
4000 | { | 2377 | { |
4001 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2378 | struct ieee80211_if_sta *ifsta; |
4002 | struct ieee80211_sub_if_data *sdata; | 2379 | int res; |
4003 | 2380 | ||
4004 | if (ssid_len > IEEE80211_MAX_SSID_LEN) | 2381 | if (len > IEEE80211_MAX_SSID_LEN) |
4005 | return -EINVAL; | 2382 | return -EINVAL; |
4006 | 2383 | ||
4007 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | 2384 | ifsta = &sdata->u.sta; |
4008 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | ||
4009 | * BSSID: MACAddress | ||
4010 | * SSID | ||
4011 | * ScanType: ACTIVE, PASSIVE | ||
4012 | * ProbeDelay: delay (in microseconds) to be used prior to transmitting | ||
4013 | * a Probe frame during active scanning | ||
4014 | * ChannelList | ||
4015 | * MinChannelTime (>= ProbeDelay), in TU | ||
4016 | * MaxChannelTime: (>= MinChannelTime), in TU | ||
4017 | */ | ||
4018 | |||
4019 | /* MLME-SCAN.confirm | ||
4020 | * BSSDescriptionSet | ||
4021 | * ResultCode: SUCCESS, INVALID_PARAMETERS | ||
4022 | */ | ||
4023 | 2385 | ||
4024 | if (local->sta_sw_scanning || local->sta_hw_scanning) { | 2386 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) { |
4025 | if (local->scan_dev == dev) | 2387 | memset(ifsta->ssid, 0, sizeof(ifsta->ssid)); |
4026 | return 0; | 2388 | memcpy(ifsta->ssid, ssid, len); |
4027 | return -EBUSY; | 2389 | ifsta->ssid_len = len; |
4028 | } | 2390 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
4029 | 2391 | ||
4030 | if (local->ops->hw_scan) { | 2392 | res = 0; |
4031 | int rc = local->ops->hw_scan(local_to_hw(local), | 2393 | /* |
4032 | ssid, ssid_len); | 2394 | * Hack! MLME code needs to be cleaned up to have different |
4033 | if (!rc) { | 2395 | * entry points for configuration and internal selection change |
4034 | local->sta_hw_scanning = 1; | 2396 | */ |
4035 | local->scan_dev = dev; | 2397 | if (netif_running(sdata->dev)) |
2398 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
2399 | if (res) { | ||
2400 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
2401 | "the low-level driver\n", sdata->dev->name); | ||
2402 | return res; | ||
4036 | } | 2403 | } |
4037 | return rc; | ||
4038 | } | 2404 | } |
4039 | 2405 | ||
4040 | local->sta_sw_scanning = 1; | 2406 | if (len) |
2407 | ifsta->flags |= IEEE80211_STA_SSID_SET; | ||
2408 | else | ||
2409 | ifsta->flags &= ~IEEE80211_STA_SSID_SET; | ||
4041 | 2410 | ||
4042 | rcu_read_lock(); | 2411 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
4043 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2412 | !(ifsta->flags & IEEE80211_STA_BSSID_SET)) { |
4044 | netif_stop_queue(sdata->dev); | 2413 | ifsta->ibss_join_req = jiffies; |
4045 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA && | 2414 | ifsta->state = IEEE80211_STA_MLME_IBSS_SEARCH; |
4046 | (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)) | 2415 | return ieee80211_sta_find_ibss(sdata, ifsta); |
4047 | ieee80211_send_nullfunc(local, sdata, 1); | ||
4048 | } | 2416 | } |
4049 | rcu_read_unlock(); | ||
4050 | |||
4051 | if (ssid) { | ||
4052 | local->scan_ssid_len = ssid_len; | ||
4053 | memcpy(local->scan_ssid, ssid, ssid_len); | ||
4054 | } else | ||
4055 | local->scan_ssid_len = 0; | ||
4056 | local->scan_state = SCAN_SET_CHANNEL; | ||
4057 | local->scan_channel_idx = 0; | ||
4058 | local->scan_band = IEEE80211_BAND_2GHZ; | ||
4059 | local->scan_dev = dev; | ||
4060 | |||
4061 | netif_addr_lock_bh(local->mdev); | ||
4062 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
4063 | local->ops->configure_filter(local_to_hw(local), | ||
4064 | FIF_BCN_PRBRESP_PROMISC, | ||
4065 | &local->filter_flags, | ||
4066 | local->mdev->mc_count, | ||
4067 | local->mdev->mc_list); | ||
4068 | netif_addr_unlock_bh(local->mdev); | ||
4069 | |||
4070 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
4071 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
4072 | IEEE80211_CHANNEL_TIME); | ||
4073 | 2417 | ||
4074 | return 0; | 2418 | return 0; |
4075 | } | 2419 | } |
4076 | 2420 | ||
4077 | 2421 | int ieee80211_sta_get_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t *len) | |
4078 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) | ||
4079 | { | 2422 | { |
4080 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4081 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2423 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4082 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2424 | memcpy(ssid, ifsta->ssid, ifsta->ssid_len); |
4083 | 2425 | *len = ifsta->ssid_len; | |
4084 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | ||
4085 | return ieee80211_sta_start_scan(dev, ssid, ssid_len); | ||
4086 | |||
4087 | if (local->sta_sw_scanning || local->sta_hw_scanning) { | ||
4088 | if (local->scan_dev == dev) | ||
4089 | return 0; | ||
4090 | return -EBUSY; | ||
4091 | } | ||
4092 | |||
4093 | ifsta->scan_ssid_len = ssid_len; | ||
4094 | if (ssid_len) | ||
4095 | memcpy(ifsta->scan_ssid, ssid, ssid_len); | ||
4096 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); | ||
4097 | queue_work(local->hw.workqueue, &ifsta->work); | ||
4098 | return 0; | 2426 | return 0; |
4099 | } | 2427 | } |
4100 | 2428 | ||
4101 | static char * | 2429 | int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid) |
4102 | ieee80211_sta_scan_result(struct net_device *dev, | ||
4103 | struct iw_request_info *info, | ||
4104 | struct ieee80211_sta_bss *bss, | ||
4105 | char *current_ev, char *end_buf) | ||
4106 | { | 2430 | { |
4107 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 2431 | struct ieee80211_if_sta *ifsta; |
4108 | struct iw_event iwe; | 2432 | int res; |
4109 | |||
4110 | if (time_after(jiffies, | ||
4111 | bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
4112 | return current_ev; | ||
4113 | |||
4114 | memset(&iwe, 0, sizeof(iwe)); | ||
4115 | iwe.cmd = SIOCGIWAP; | ||
4116 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
4117 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | ||
4118 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4119 | IW_EV_ADDR_LEN); | ||
4120 | |||
4121 | memset(&iwe, 0, sizeof(iwe)); | ||
4122 | iwe.cmd = SIOCGIWESSID; | ||
4123 | if (bss_mesh_cfg(bss)) { | ||
4124 | iwe.u.data.length = bss_mesh_id_len(bss); | ||
4125 | iwe.u.data.flags = 1; | ||
4126 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4127 | &iwe, bss_mesh_id(bss)); | ||
4128 | } else { | ||
4129 | iwe.u.data.length = bss->ssid_len; | ||
4130 | iwe.u.data.flags = 1; | ||
4131 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4132 | &iwe, bss->ssid); | ||
4133 | } | ||
4134 | |||
4135 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
4136 | || bss_mesh_cfg(bss)) { | ||
4137 | memset(&iwe, 0, sizeof(iwe)); | ||
4138 | iwe.cmd = SIOCGIWMODE; | ||
4139 | if (bss_mesh_cfg(bss)) | ||
4140 | iwe.u.mode = IW_MODE_MESH; | ||
4141 | else if (bss->capability & WLAN_CAPABILITY_ESS) | ||
4142 | iwe.u.mode = IW_MODE_MASTER; | ||
4143 | else | ||
4144 | iwe.u.mode = IW_MODE_ADHOC; | ||
4145 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
4146 | &iwe, IW_EV_UINT_LEN); | ||
4147 | } | ||
4148 | |||
4149 | memset(&iwe, 0, sizeof(iwe)); | ||
4150 | iwe.cmd = SIOCGIWFREQ; | ||
4151 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | ||
4152 | iwe.u.freq.e = 0; | ||
4153 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4154 | IW_EV_FREQ_LEN); | ||
4155 | |||
4156 | memset(&iwe, 0, sizeof(iwe)); | ||
4157 | iwe.cmd = SIOCGIWFREQ; | ||
4158 | iwe.u.freq.m = bss->freq; | ||
4159 | iwe.u.freq.e = 6; | ||
4160 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4161 | IW_EV_FREQ_LEN); | ||
4162 | memset(&iwe, 0, sizeof(iwe)); | ||
4163 | iwe.cmd = IWEVQUAL; | ||
4164 | iwe.u.qual.qual = bss->qual; | ||
4165 | iwe.u.qual.level = bss->signal; | ||
4166 | iwe.u.qual.noise = bss->noise; | ||
4167 | iwe.u.qual.updated = local->wstats_flags; | ||
4168 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
4169 | IW_EV_QUAL_LEN); | ||
4170 | |||
4171 | memset(&iwe, 0, sizeof(iwe)); | ||
4172 | iwe.cmd = SIOCGIWENCODE; | ||
4173 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
4174 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
4175 | else | ||
4176 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
4177 | iwe.u.data.length = 0; | ||
4178 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4179 | &iwe, ""); | ||
4180 | |||
4181 | if (bss && bss->wpa_ie) { | ||
4182 | memset(&iwe, 0, sizeof(iwe)); | ||
4183 | iwe.cmd = IWEVGENIE; | ||
4184 | iwe.u.data.length = bss->wpa_ie_len; | ||
4185 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4186 | &iwe, bss->wpa_ie); | ||
4187 | } | ||
4188 | |||
4189 | if (bss && bss->rsn_ie) { | ||
4190 | memset(&iwe, 0, sizeof(iwe)); | ||
4191 | iwe.cmd = IWEVGENIE; | ||
4192 | iwe.u.data.length = bss->rsn_ie_len; | ||
4193 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4194 | &iwe, bss->rsn_ie); | ||
4195 | } | ||
4196 | |||
4197 | if (bss && bss->ht_ie) { | ||
4198 | memset(&iwe, 0, sizeof(iwe)); | ||
4199 | iwe.cmd = IWEVGENIE; | ||
4200 | iwe.u.data.length = bss->ht_ie_len; | ||
4201 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
4202 | &iwe, bss->ht_ie); | ||
4203 | } | ||
4204 | |||
4205 | if (bss && bss->supp_rates_len > 0) { | ||
4206 | /* display all supported rates in readable format */ | ||
4207 | char *p = current_ev + iwe_stream_lcp_len(info); | ||
4208 | int i; | ||
4209 | |||
4210 | memset(&iwe, 0, sizeof(iwe)); | ||
4211 | iwe.cmd = SIOCGIWRATE; | ||
4212 | /* Those two flags are ignored... */ | ||
4213 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
4214 | |||
4215 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
4216 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | ||
4217 | 0x7f) * 500000); | ||
4218 | p = iwe_stream_add_value(info, current_ev, p, | ||
4219 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
4220 | } | ||
4221 | current_ev = p; | ||
4222 | } | ||
4223 | 2433 | ||
4224 | if (bss) { | 2434 | ifsta = &sdata->u.sta; |
4225 | char *buf; | ||
4226 | buf = kmalloc(30, GFP_ATOMIC); | ||
4227 | if (buf) { | ||
4228 | memset(&iwe, 0, sizeof(iwe)); | ||
4229 | iwe.cmd = IWEVCUSTOM; | ||
4230 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | ||
4231 | iwe.u.data.length = strlen(buf); | ||
4232 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4233 | end_buf, | ||
4234 | &iwe, buf); | ||
4235 | memset(&iwe, 0, sizeof(iwe)); | ||
4236 | iwe.cmd = IWEVCUSTOM; | ||
4237 | sprintf(buf, " Last beacon: %dms ago", | ||
4238 | jiffies_to_msecs(jiffies - bss->last_update)); | ||
4239 | iwe.u.data.length = strlen(buf); | ||
4240 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4241 | end_buf, &iwe, buf); | ||
4242 | kfree(buf); | ||
4243 | } | ||
4244 | } | ||
4245 | 2435 | ||
4246 | if (bss_mesh_cfg(bss)) { | 2436 | if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
4247 | char *buf; | 2437 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
4248 | u8 *cfg = bss_mesh_cfg(bss); | 2438 | res = 0; |
4249 | buf = kmalloc(50, GFP_ATOMIC); | 2439 | /* |
4250 | if (buf) { | 2440 | * Hack! See also ieee80211_sta_set_ssid. |
4251 | memset(&iwe, 0, sizeof(iwe)); | 2441 | */ |
4252 | iwe.cmd = IWEVCUSTOM; | 2442 | if (netif_running(sdata->dev)) |
4253 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 2443 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
4254 | iwe.u.data.length = strlen(buf); | 2444 | if (res) { |
4255 | current_ev = iwe_stream_add_point(info, current_ev, | 2445 | printk(KERN_DEBUG "%s: Failed to config new BSSID to " |
4256 | end_buf, | 2446 | "the low-level driver\n", sdata->dev->name); |
4257 | &iwe, buf); | 2447 | return res; |
4258 | sprintf(buf, "Path Selection Protocol ID: " | ||
4259 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
4260 | cfg[4]); | ||
4261 | iwe.u.data.length = strlen(buf); | ||
4262 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4263 | end_buf, | ||
4264 | &iwe, buf); | ||
4265 | sprintf(buf, "Path Selection Metric ID: " | ||
4266 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
4267 | cfg[8]); | ||
4268 | iwe.u.data.length = strlen(buf); | ||
4269 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4270 | end_buf, | ||
4271 | &iwe, buf); | ||
4272 | sprintf(buf, "Congestion Control Mode ID: " | ||
4273 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
4274 | cfg[11], cfg[12]); | ||
4275 | iwe.u.data.length = strlen(buf); | ||
4276 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4277 | end_buf, | ||
4278 | &iwe, buf); | ||
4279 | sprintf(buf, "Channel Precedence: " | ||
4280 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
4281 | cfg[15], cfg[16]); | ||
4282 | iwe.u.data.length = strlen(buf); | ||
4283 | current_ev = iwe_stream_add_point(info, current_ev, | ||
4284 | end_buf, | ||
4285 | &iwe, buf); | ||
4286 | kfree(buf); | ||
4287 | } | 2448 | } |
4288 | } | 2449 | } |
4289 | 2450 | ||
4290 | return current_ev; | 2451 | if (is_valid_ether_addr(bssid)) |
4291 | } | 2452 | ifsta->flags |= IEEE80211_STA_BSSID_SET; |
4292 | 2453 | else | |
2454 | ifsta->flags &= ~IEEE80211_STA_BSSID_SET; | ||
4293 | 2455 | ||
4294 | int ieee80211_sta_scan_results(struct net_device *dev, | 2456 | return 0; |
4295 | struct iw_request_info *info, | ||
4296 | char *buf, size_t len) | ||
4297 | { | ||
4298 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
4299 | char *current_ev = buf; | ||
4300 | char *end_buf = buf + len; | ||
4301 | struct ieee80211_sta_bss *bss; | ||
4302 | |||
4303 | spin_lock_bh(&local->sta_bss_lock); | ||
4304 | list_for_each_entry(bss, &local->sta_bss_list, list) { | ||
4305 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
4306 | spin_unlock_bh(&local->sta_bss_lock); | ||
4307 | return -E2BIG; | ||
4308 | } | ||
4309 | current_ev = ieee80211_sta_scan_result(dev, info, bss, | ||
4310 | current_ev, end_buf); | ||
4311 | } | ||
4312 | spin_unlock_bh(&local->sta_bss_lock); | ||
4313 | return current_ev - buf; | ||
4314 | } | 2457 | } |
4315 | 2458 | ||
4316 | 2459 | int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata, char *ie, size_t len) | |
4317 | int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | ||
4318 | { | 2460 | { |
4319 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4320 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2461 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4321 | 2462 | ||
4322 | kfree(ifsta->extra_ie); | 2463 | kfree(ifsta->extra_ie); |
@@ -4335,92 +2476,60 @@ int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len) | |||
4335 | return 0; | 2476 | return 0; |
4336 | } | 2477 | } |
4337 | 2478 | ||
4338 | 2479 | int ieee80211_sta_deauthenticate(struct ieee80211_sub_if_data *sdata, u16 reason) | |
4339 | struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev, | ||
4340 | struct sk_buff *skb, u8 *bssid, | ||
4341 | u8 *addr, u64 supp_rates) | ||
4342 | { | ||
4343 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
4344 | struct sta_info *sta; | ||
4345 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4346 | DECLARE_MAC_BUF(mac); | ||
4347 | int band = local->hw.conf.channel->band; | ||
4348 | |||
4349 | /* TODO: Could consider removing the least recently used entry and | ||
4350 | * allow new one to be added. */ | ||
4351 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | ||
4352 | if (net_ratelimit()) { | ||
4353 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " | ||
4354 | "entry %s\n", dev->name, print_mac(mac, addr)); | ||
4355 | } | ||
4356 | return NULL; | ||
4357 | } | ||
4358 | |||
4359 | if (compare_ether_addr(bssid, sdata->u.sta.bssid)) | ||
4360 | return NULL; | ||
4361 | |||
4362 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
4363 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | ||
4364 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), dev->name); | ||
4365 | #endif | ||
4366 | |||
4367 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | ||
4368 | if (!sta) | ||
4369 | return NULL; | ||
4370 | |||
4371 | set_sta_flags(sta, WLAN_STA_AUTHORIZED); | ||
4372 | |||
4373 | if (supp_rates) | ||
4374 | sta->supp_rates[band] = supp_rates; | ||
4375 | else | ||
4376 | sta->supp_rates[band] = sdata->u.sta.supp_rates_bits[band]; | ||
4377 | |||
4378 | rate_control_rate_init(sta, local); | ||
4379 | |||
4380 | if (sta_info_insert(sta)) | ||
4381 | return NULL; | ||
4382 | |||
4383 | return sta; | ||
4384 | } | ||
4385 | |||
4386 | |||
4387 | int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason) | ||
4388 | { | 2480 | { |
4389 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4390 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2481 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4391 | 2482 | ||
4392 | printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", | 2483 | printk(KERN_DEBUG "%s: deauthenticating by local choice (reason=%d)\n", |
4393 | dev->name, reason); | 2484 | sdata->dev->name, reason); |
4394 | 2485 | ||
4395 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 2486 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
4396 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 2487 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
4397 | return -EINVAL; | 2488 | return -EINVAL; |
4398 | 2489 | ||
4399 | ieee80211_send_deauth(dev, ifsta, reason); | 2490 | ieee80211_set_disassoc(sdata, ifsta, true, true, reason); |
4400 | ieee80211_set_disassoc(dev, ifsta, 1); | ||
4401 | return 0; | 2491 | return 0; |
4402 | } | 2492 | } |
4403 | 2493 | ||
4404 | 2494 | int ieee80211_sta_disassociate(struct ieee80211_sub_if_data *sdata, u16 reason) | |
4405 | int ieee80211_sta_disassociate(struct net_device *dev, u16 reason) | ||
4406 | { | 2495 | { |
4407 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
4408 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 2496 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
4409 | 2497 | ||
4410 | printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", | 2498 | printk(KERN_DEBUG "%s: disassociating by local choice (reason=%d)\n", |
4411 | dev->name, reason); | 2499 | sdata->dev->name, reason); |
4412 | 2500 | ||
4413 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 2501 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
4414 | return -EINVAL; | 2502 | return -EINVAL; |
4415 | 2503 | ||
4416 | if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) | 2504 | if (!(ifsta->flags & IEEE80211_STA_ASSOCIATED)) |
4417 | return -1; | 2505 | return -1; |
4418 | 2506 | ||
4419 | ieee80211_send_disassoc(dev, ifsta, reason); | 2507 | ieee80211_set_disassoc(sdata, ifsta, false, true, reason); |
4420 | ieee80211_set_disassoc(dev, ifsta, 0); | ||
4421 | return 0; | 2508 | return 0; |
4422 | } | 2509 | } |
4423 | 2510 | ||
2511 | /* scan finished notification */ | ||
2512 | void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | ||
2513 | { | ||
2514 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
2515 | struct ieee80211_if_sta *ifsta; | ||
2516 | |||
2517 | if (sdata && sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||
2518 | ifsta = &sdata->u.sta; | ||
2519 | if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) || | ||
2520 | (!(ifsta->state == IEEE80211_STA_MLME_IBSS_JOINED) && | ||
2521 | !ieee80211_sta_active_ibss(sdata))) | ||
2522 | ieee80211_sta_find_ibss(sdata, ifsta); | ||
2523 | } | ||
2524 | |||
2525 | /* Restart STA timers */ | ||
2526 | rcu_read_lock(); | ||
2527 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | ||
2528 | ieee80211_restart_sta_timer(sdata); | ||
2529 | rcu_read_unlock(); | ||
2530 | } | ||
2531 | |||
2532 | /* driver notification call */ | ||
4424 | void ieee80211_notify_mac(struct ieee80211_hw *hw, | 2533 | void ieee80211_notify_mac(struct ieee80211_hw *hw, |
4425 | enum ieee80211_notification_types notif_type) | 2534 | enum ieee80211_notification_types notif_type) |
4426 | { | 2535 | { |
@@ -4431,10 +2540,10 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw, | |||
4431 | case IEEE80211_NOTIFY_RE_ASSOC: | 2540 | case IEEE80211_NOTIFY_RE_ASSOC: |
4432 | rcu_read_lock(); | 2541 | rcu_read_lock(); |
4433 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2542 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
4434 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 2543 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
4435 | continue; | 2544 | continue; |
4436 | 2545 | ||
4437 | ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta); | 2546 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
4438 | } | 2547 | } |
4439 | rcu_read_unlock(); | 2548 | rcu_read_unlock(); |
4440 | break; | 2549 | break; |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index ede7ab56f65b..5f18c27eb900 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -134,7 +134,7 @@ static inline int rate_supported(struct sta_info *sta, | |||
134 | enum ieee80211_band band, | 134 | enum ieee80211_band band, |
135 | int index) | 135 | int index) |
136 | { | 136 | { |
137 | return (sta == NULL || sta->supp_rates[band] & BIT(index)); | 137 | return (sta == NULL || sta->sta.supp_rates[band] & BIT(index)); |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline s8 | 140 | static inline s8 |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 0a9135b974b5..ffafc5da572e 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -180,6 +180,8 @@ struct rc_pid_sta_info { | |||
180 | u32 tx_num_failed; | 180 | u32 tx_num_failed; |
181 | u32 tx_num_xmit; | 181 | u32 tx_num_xmit; |
182 | 182 | ||
183 | int txrate_idx; | ||
184 | |||
183 | /* Average failed frames percentage error (i.e. actual vs. target | 185 | /* Average failed frames percentage error (i.e. actual vs. target |
184 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed | 186 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed |
185 | * using using an exponential weighted average technique: | 187 | * using using an exponential weighted average technique: |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index a914ba73ccf5..bc1c4569caa1 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -75,7 +75,8 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | |||
75 | struct ieee80211_sub_if_data *sdata; | 75 | struct ieee80211_sub_if_data *sdata; |
76 | struct ieee80211_supported_band *sband; | 76 | struct ieee80211_supported_band *sband; |
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | 77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; |
78 | int cur = sta->txrate_idx; | 78 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; |
79 | int cur = spinfo->txrate_idx; | ||
79 | 80 | ||
80 | sdata = sta->sdata; | 81 | sdata = sta->sdata; |
81 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 82 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
@@ -111,7 +112,7 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | |||
111 | /* Fit the rate found to the nearest supported rate. */ | 112 | /* Fit the rate found to the nearest supported rate. */ |
112 | do { | 113 | do { |
113 | if (rate_supported(sta, band, rinfo[tmp].index)) { | 114 | if (rate_supported(sta, band, rinfo[tmp].index)) { |
114 | sta->txrate_idx = rinfo[tmp].index; | 115 | spinfo->txrate_idx = rinfo[tmp].index; |
115 | break; | 116 | break; |
116 | } | 117 | } |
117 | if (adj < 0) | 118 | if (adj < 0) |
@@ -121,9 +122,9 @@ static void rate_control_pid_adjust_rate(struct ieee80211_local *local, | |||
121 | } while (tmp < n_bitrates && tmp >= 0); | 122 | } while (tmp < n_bitrates && tmp >= 0); |
122 | 123 | ||
123 | #ifdef CONFIG_MAC80211_DEBUGFS | 124 | #ifdef CONFIG_MAC80211_DEBUGFS |
124 | rate_control_pid_event_rate_change( | 125 | rate_control_pid_event_rate_change(&spinfo->events, |
125 | &((struct rc_pid_sta_info *)sta->rate_ctrl_priv)->events, | 126 | spinfo->txrate_idx, |
126 | sta->txrate_idx, sband->bitrates[sta->txrate_idx].bitrate); | 127 | sband->bitrates[spinfo->txrate_idx].bitrate); |
127 | #endif | 128 | #endif |
128 | } | 129 | } |
129 | 130 | ||
@@ -148,9 +149,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
148 | struct ieee80211_local *local, | 149 | struct ieee80211_local *local, |
149 | struct sta_info *sta) | 150 | struct sta_info *sta) |
150 | { | 151 | { |
151 | #ifdef CONFIG_MAC80211_MESH | ||
152 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 152 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
153 | #endif | ||
154 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; | 153 | struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; |
155 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 154 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
156 | struct ieee80211_supported_band *sband; | 155 | struct ieee80211_supported_band *sband; |
@@ -181,11 +180,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
181 | pf = spinfo->last_pf; | 180 | pf = spinfo->last_pf; |
182 | else { | 181 | else { |
183 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 182 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
184 | #ifdef CONFIG_MAC80211_MESH | 183 | if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100) |
185 | if (pf == 100 && | ||
186 | sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | ||
187 | mesh_plink_broken(sta); | 184 | mesh_plink_broken(sta); |
188 | #endif | ||
189 | pf <<= RC_PID_ARITH_SHIFT; | 185 | pf <<= RC_PID_ARITH_SHIFT; |
190 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | 186 | sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) |
191 | >> RC_PID_ARITH_SHIFT; | 187 | >> RC_PID_ARITH_SHIFT; |
@@ -195,16 +191,16 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
195 | spinfo->tx_num_failed = 0; | 191 | spinfo->tx_num_failed = 0; |
196 | 192 | ||
197 | /* If we just switched rate, update the rate behaviour info. */ | 193 | /* If we just switched rate, update the rate behaviour info. */ |
198 | if (pinfo->oldrate != sta->txrate_idx) { | 194 | if (pinfo->oldrate != spinfo->txrate_idx) { |
199 | 195 | ||
200 | i = rinfo[pinfo->oldrate].rev_index; | 196 | i = rinfo[pinfo->oldrate].rev_index; |
201 | j = rinfo[sta->txrate_idx].rev_index; | 197 | j = rinfo[spinfo->txrate_idx].rev_index; |
202 | 198 | ||
203 | tmp = (pf - spinfo->last_pf); | 199 | tmp = (pf - spinfo->last_pf); |
204 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); | 200 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); |
205 | 201 | ||
206 | rinfo[j].diff = rinfo[i].diff + tmp; | 202 | rinfo[j].diff = rinfo[i].diff + tmp; |
207 | pinfo->oldrate = sta->txrate_idx; | 203 | pinfo->oldrate = spinfo->txrate_idx; |
208 | } | 204 | } |
209 | rate_control_pid_normalize(pinfo, sband->n_bitrates); | 205 | rate_control_pid_normalize(pinfo, sband->n_bitrates); |
210 | 206 | ||
@@ -257,19 +253,20 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
257 | if (!sta) | 253 | if (!sta) |
258 | goto unlock; | 254 | goto unlock; |
259 | 255 | ||
256 | spinfo = sta->rate_ctrl_priv; | ||
257 | |||
260 | /* Don't update the state if we're not controlling the rate. */ | 258 | /* Don't update the state if we're not controlling the rate. */ |
261 | sdata = sta->sdata; | 259 | sdata = sta->sdata; |
262 | if (sdata->force_unicast_rateidx > -1) { | 260 | if (sdata->force_unicast_rateidx > -1) { |
263 | sta->txrate_idx = sdata->max_ratectrl_rateidx; | 261 | spinfo->txrate_idx = sdata->max_ratectrl_rateidx; |
264 | goto unlock; | 262 | goto unlock; |
265 | } | 263 | } |
266 | 264 | ||
267 | /* Ignore all frames that were sent with a different rate than the rate | 265 | /* Ignore all frames that were sent with a different rate than the rate |
268 | * we currently advise mac80211 to use. */ | 266 | * we currently advise mac80211 to use. */ |
269 | if (info->tx_rate_idx != sta->txrate_idx) | 267 | if (info->tx_rate_idx != spinfo->txrate_idx) |
270 | goto unlock; | 268 | goto unlock; |
271 | 269 | ||
272 | spinfo = sta->rate_ctrl_priv; | ||
273 | spinfo->tx_num_xmit++; | 270 | spinfo->tx_num_xmit++; |
274 | 271 | ||
275 | #ifdef CONFIG_MAC80211_DEBUGFS | 272 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -287,17 +284,6 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev, | |||
287 | spinfo->tx_num_xmit++; | 284 | spinfo->tx_num_xmit++; |
288 | } | 285 | } |
289 | 286 | ||
290 | if (info->status.excessive_retries) { | ||
291 | sta->tx_retry_failed++; | ||
292 | sta->tx_num_consecutive_failures++; | ||
293 | sta->tx_num_mpdu_fail++; | ||
294 | } else { | ||
295 | sta->tx_num_consecutive_failures = 0; | ||
296 | sta->tx_num_mpdu_ok++; | ||
297 | } | ||
298 | sta->tx_retry_count += info->status.retry_count; | ||
299 | sta->tx_num_mpdu_fail += info->status.retry_count; | ||
300 | |||
301 | /* Update PID controller state. */ | 287 | /* Update PID controller state. */ |
302 | period = (HZ * pinfo->sampling_period + 500) / 1000; | 288 | period = (HZ * pinfo->sampling_period + 500) / 1000; |
303 | if (!period) | 289 | if (!period) |
@@ -317,6 +303,7 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
317 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 303 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
318 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 304 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
319 | struct ieee80211_sub_if_data *sdata; | 305 | struct ieee80211_sub_if_data *sdata; |
306 | struct rc_pid_sta_info *spinfo; | ||
320 | struct sta_info *sta; | 307 | struct sta_info *sta; |
321 | int rateidx; | 308 | int rateidx; |
322 | u16 fc; | 309 | u16 fc; |
@@ -337,16 +324,15 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev, | |||
337 | 324 | ||
338 | /* If a forced rate is in effect, select it. */ | 325 | /* If a forced rate is in effect, select it. */ |
339 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 326 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
327 | spinfo = (struct rc_pid_sta_info *)sta->rate_ctrl_priv; | ||
340 | if (sdata->force_unicast_rateidx > -1) | 328 | if (sdata->force_unicast_rateidx > -1) |
341 | sta->txrate_idx = sdata->force_unicast_rateidx; | 329 | spinfo->txrate_idx = sdata->force_unicast_rateidx; |
342 | 330 | ||
343 | rateidx = sta->txrate_idx; | 331 | rateidx = spinfo->txrate_idx; |
344 | 332 | ||
345 | if (rateidx >= sband->n_bitrates) | 333 | if (rateidx >= sband->n_bitrates) |
346 | rateidx = sband->n_bitrates - 1; | 334 | rateidx = sband->n_bitrates - 1; |
347 | 335 | ||
348 | sta->last_txrate_idx = rateidx; | ||
349 | |||
350 | rcu_read_unlock(); | 336 | rcu_read_unlock(); |
351 | 337 | ||
352 | sel->rate_idx = rateidx; | 338 | sel->rate_idx = rateidx; |
@@ -367,9 +353,10 @@ static void rate_control_pid_rate_init(void *priv, void *priv_sta, | |||
367 | * Until that method is implemented, we will use the lowest supported | 353 | * Until that method is implemented, we will use the lowest supported |
368 | * rate as a workaround. */ | 354 | * rate as a workaround. */ |
369 | struct ieee80211_supported_band *sband; | 355 | struct ieee80211_supported_band *sband; |
356 | struct rc_pid_sta_info *spinfo = (void *)sta->rate_ctrl_priv; | ||
370 | 357 | ||
371 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 358 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
372 | sta->txrate_idx = rate_lowest_index(local, sband, sta); | 359 | spinfo->txrate_idx = rate_lowest_index(local, sband, sta); |
373 | sta->fail_avg = 0; | 360 | sta->fail_avg = 0; |
374 | } | 361 | } |
375 | 362 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6db854505193..92d898b901e9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -143,6 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
143 | /* IEEE80211_RADIOTAP_FLAGS */ | 143 | /* IEEE80211_RADIOTAP_FLAGS */ |
144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 144 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
145 | *pos |= IEEE80211_RADIOTAP_F_FCS; | 145 | *pos |= IEEE80211_RADIOTAP_F_FCS; |
146 | if (status->flag & RX_FLAG_SHORTPRE) | ||
147 | *pos |= IEEE80211_RADIOTAP_F_SHORTPRE; | ||
146 | pos++; | 148 | pos++; |
147 | 149 | ||
148 | /* IEEE80211_RADIOTAP_RATE */ | 150 | /* IEEE80211_RADIOTAP_RATE */ |
@@ -155,8 +157,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
155 | if (status->band == IEEE80211_BAND_5GHZ) | 157 | if (status->band == IEEE80211_BAND_5GHZ) |
156 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | 158 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | |
157 | IEEE80211_CHAN_5GHZ); | 159 | IEEE80211_CHAN_5GHZ); |
160 | else if (rate->flags & IEEE80211_RATE_ERP_G) | ||
161 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM | | ||
162 | IEEE80211_CHAN_2GHZ); | ||
158 | else | 163 | else |
159 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN | | 164 | *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK | |
160 | IEEE80211_CHAN_2GHZ); | 165 | IEEE80211_CHAN_2GHZ); |
161 | pos += 2; | 166 | pos += 2; |
162 | 167 | ||
@@ -290,7 +295,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
290 | if (!netif_running(sdata->dev)) | 295 | if (!netif_running(sdata->dev)) |
291 | continue; | 296 | continue; |
292 | 297 | ||
293 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR) | 298 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
294 | continue; | 299 | continue; |
295 | 300 | ||
296 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 301 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
@@ -398,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
398 | struct ieee80211_local *local = rx->local; | 403 | struct ieee80211_local *local = rx->local; |
399 | struct sk_buff *skb = rx->skb; | 404 | struct sk_buff *skb = rx->skb; |
400 | 405 | ||
401 | if (unlikely(local->sta_hw_scanning)) | 406 | if (unlikely(local->hw_scanning)) |
402 | return ieee80211_sta_rx_scan(rx->dev, skb, rx->status); | 407 | return ieee80211_scan_rx(rx->sdata, skb, rx->status); |
403 | 408 | ||
404 | if (unlikely(local->sta_sw_scanning)) { | 409 | if (unlikely(local->sw_scanning)) { |
405 | /* drop all the other packets during a software scan anyway */ | 410 | /* drop all the other packets during a software scan anyway */ |
406 | if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status) | 411 | if (ieee80211_scan_rx(rx->sdata, skb, rx->status) |
407 | != RX_QUEUED) | 412 | != RX_QUEUED) |
408 | dev_kfree_skb(skb); | 413 | dev_kfree_skb(skb); |
409 | return RX_QUEUED; | 414 | return RX_QUEUED; |
@@ -461,7 +466,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
461 | 466 | ||
462 | if (ieee80211_is_data(hdr->frame_control) && | 467 | if (ieee80211_is_data(hdr->frame_control) && |
463 | is_multicast_ether_addr(hdr->addr1) && | 468 | is_multicast_ether_addr(hdr->addr1) && |
464 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) | 469 | mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) |
465 | return RX_DROP_MONITOR; | 470 | return RX_DROP_MONITOR; |
466 | #undef msh_h_get | 471 | #undef msh_h_get |
467 | 472 | ||
@@ -496,8 +501,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
496 | /* Drop disallowed frame classes based on STA auth/assoc state; | 501 | /* Drop disallowed frame classes based on STA auth/assoc state; |
497 | * IEEE 802.11, Chap 5.5. | 502 | * IEEE 802.11, Chap 5.5. |
498 | * | 503 | * |
499 | * 80211.o does filtering only based on association state, i.e., it | 504 | * mac80211 filters only based on association state, i.e. it drops |
500 | * drops Class 3 frames from not associated stations. hostapd sends | 505 | * Class 3 frames from not associated stations. hostapd sends |
501 | * deauth/disassoc frames when needed. In addition, hostapd is | 506 | * deauth/disassoc frames when needed. In addition, hostapd is |
502 | * responsible for filtering on both auth and assoc states. | 507 | * responsible for filtering on both auth and assoc states. |
503 | */ | 508 | */ |
@@ -507,7 +512,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
507 | 512 | ||
508 | if (unlikely((ieee80211_is_data(hdr->frame_control) || | 513 | if (unlikely((ieee80211_is_data(hdr->frame_control) || |
509 | ieee80211_is_pspoll(hdr->frame_control)) && | 514 | ieee80211_is_pspoll(hdr->frame_control)) && |
510 | rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 515 | rx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
511 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { | 516 | (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { |
512 | if ((!ieee80211_has_fromds(hdr->frame_control) && | 517 | if ((!ieee80211_has_fromds(hdr->frame_control) && |
513 | !ieee80211_has_tods(hdr->frame_control) && | 518 | !ieee80211_has_tods(hdr->frame_control) && |
@@ -656,7 +661,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta) | |||
656 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); | 661 | set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); |
657 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 662 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
658 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", | 663 | printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n", |
659 | dev->name, print_mac(mac, sta->addr), sta->aid); | 664 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
660 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 665 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
661 | } | 666 | } |
662 | 667 | ||
@@ -680,7 +685,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
680 | 685 | ||
681 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 686 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
682 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", | 687 | printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n", |
683 | dev->name, print_mac(mac, sta->addr), sta->aid); | 688 | dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid); |
684 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 689 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
685 | 690 | ||
686 | /* Send all buffered frames to the station */ | 691 | /* Send all buffered frames to the station */ |
@@ -697,7 +702,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta) | |||
697 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 702 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
698 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " | 703 | printk(KERN_DEBUG "%s: STA %s aid %d send PS frame " |
699 | "since STA not sleeping anymore\n", dev->name, | 704 | "since STA not sleeping anymore\n", dev->name, |
700 | print_mac(mac, sta->addr), sta->aid); | 705 | print_mac(mac, sta->sta.addr), sta->sta.aid); |
701 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 706 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
702 | info->flags |= IEEE80211_TX_CTL_REQUEUE; | 707 | info->flags |= IEEE80211_TX_CTL_REQUEUE; |
703 | dev_queue_xmit(skb); | 708 | dev_queue_xmit(skb); |
@@ -719,14 +724,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
719 | /* Update last_rx only for IBSS packets which are for the current | 724 | /* Update last_rx only for IBSS packets which are for the current |
720 | * BSSID to avoid keeping the current IBSS network alive in cases where | 725 | * BSSID to avoid keeping the current IBSS network alive in cases where |
721 | * other STAs are using different BSSID. */ | 726 | * other STAs are using different BSSID. */ |
722 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 727 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
723 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 728 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
724 | IEEE80211_IF_TYPE_IBSS); | 729 | NL80211_IFTYPE_ADHOC); |
725 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) | 730 | if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) |
726 | sta->last_rx = jiffies; | 731 | sta->last_rx = jiffies; |
727 | } else | 732 | } else |
728 | if (!is_multicast_ether_addr(hdr->addr1) || | 733 | if (!is_multicast_ether_addr(hdr->addr1) || |
729 | rx->sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 734 | rx->sdata->vif.type == NL80211_IFTYPE_STATION) { |
730 | /* Update last_rx only for unicast frames in order to prevent | 735 | /* Update last_rx only for unicast frames in order to prevent |
731 | * the Probe Request frames (the only broadcast frames from a | 736 | * the Probe Request frames (the only broadcast frames from a |
732 | * STA in infrastructure mode) from keeping a connection alive. | 737 | * STA in infrastructure mode) from keeping a connection alive. |
@@ -746,8 +751,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
746 | sta->last_noise = rx->status->noise; | 751 | sta->last_noise = rx->status->noise; |
747 | 752 | ||
748 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 753 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
749 | (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP || | 754 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
750 | rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) { | 755 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { |
751 | /* Change STA power saving mode only in the end of a frame | 756 | /* Change STA power saving mode only in the end of a frame |
752 | * exchange sequence */ | 757 | * exchange sequence */ |
753 | if (test_sta_flags(sta, WLAN_STA_PS) && | 758 | if (test_sta_flags(sta, WLAN_STA_PS) && |
@@ -816,7 +821,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata, | |||
816 | 821 | ||
817 | static inline struct ieee80211_fragment_entry * | 822 | static inline struct ieee80211_fragment_entry * |
818 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | 823 | ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, |
819 | u16 fc, unsigned int frag, unsigned int seq, | 824 | unsigned int frag, unsigned int seq, |
820 | int rx_queue, struct ieee80211_hdr *hdr) | 825 | int rx_queue, struct ieee80211_hdr *hdr) |
821 | { | 826 | { |
822 | struct ieee80211_fragment_entry *entry; | 827 | struct ieee80211_fragment_entry *entry; |
@@ -825,7 +830,6 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | |||
825 | idx = sdata->fragment_next; | 830 | idx = sdata->fragment_next; |
826 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { | 831 | for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) { |
827 | struct ieee80211_hdr *f_hdr; | 832 | struct ieee80211_hdr *f_hdr; |
828 | u16 f_fc; | ||
829 | 833 | ||
830 | idx--; | 834 | idx--; |
831 | if (idx < 0) | 835 | if (idx < 0) |
@@ -837,10 +841,13 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata, | |||
837 | entry->last_frag + 1 != frag) | 841 | entry->last_frag + 1 != frag) |
838 | continue; | 842 | continue; |
839 | 843 | ||
840 | f_hdr = (struct ieee80211_hdr *) entry->skb_list.next->data; | 844 | f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data; |
841 | f_fc = le16_to_cpu(f_hdr->frame_control); | ||
842 | 845 | ||
843 | if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) || | 846 | /* |
847 | * Check ftype and addresses are equal, else check next fragment | ||
848 | */ | ||
849 | if (((hdr->frame_control ^ f_hdr->frame_control) & | ||
850 | cpu_to_le16(IEEE80211_FCTL_FTYPE)) || | ||
844 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || | 851 | compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 || |
845 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) | 852 | compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0) |
846 | continue; | 853 | continue; |
@@ -860,16 +867,18 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
860 | { | 867 | { |
861 | struct ieee80211_hdr *hdr; | 868 | struct ieee80211_hdr *hdr; |
862 | u16 sc; | 869 | u16 sc; |
870 | __le16 fc; | ||
863 | unsigned int frag, seq; | 871 | unsigned int frag, seq; |
864 | struct ieee80211_fragment_entry *entry; | 872 | struct ieee80211_fragment_entry *entry; |
865 | struct sk_buff *skb; | 873 | struct sk_buff *skb; |
866 | DECLARE_MAC_BUF(mac); | 874 | DECLARE_MAC_BUF(mac); |
867 | 875 | ||
868 | hdr = (struct ieee80211_hdr *) rx->skb->data; | 876 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
877 | fc = hdr->frame_control; | ||
869 | sc = le16_to_cpu(hdr->seq_ctrl); | 878 | sc = le16_to_cpu(hdr->seq_ctrl); |
870 | frag = sc & IEEE80211_SCTL_FRAG; | 879 | frag = sc & IEEE80211_SCTL_FRAG; |
871 | 880 | ||
872 | if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) || | 881 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
873 | (rx->skb)->len < 24 || | 882 | (rx->skb)->len < 24 || |
874 | is_multicast_ether_addr(hdr->addr1))) { | 883 | is_multicast_ether_addr(hdr->addr1))) { |
875 | /* not fragmented */ | 884 | /* not fragmented */ |
@@ -884,7 +893,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
884 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, | 893 | entry = ieee80211_reassemble_add(rx->sdata, frag, seq, |
885 | rx->queue, &(rx->skb)); | 894 | rx->queue, &(rx->skb)); |
886 | if (rx->key && rx->key->conf.alg == ALG_CCMP && | 895 | if (rx->key && rx->key->conf.alg == ALG_CCMP && |
887 | (rx->fc & IEEE80211_FCTL_PROTECTED)) { | 896 | ieee80211_has_protected(fc)) { |
888 | /* Store CCMP PN so that we can verify that the next | 897 | /* Store CCMP PN so that we can verify that the next |
889 | * fragment has a sequential PN value. */ | 898 | * fragment has a sequential PN value. */ |
890 | entry->ccmp = 1; | 899 | entry->ccmp = 1; |
@@ -898,8 +907,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
898 | /* This is a fragment for a frame that should already be pending in | 907 | /* This is a fragment for a frame that should already be pending in |
899 | * fragment cache. Add this fragment to the end of the pending entry. | 908 | * fragment cache. Add this fragment to the end of the pending entry. |
900 | */ | 909 | */ |
901 | entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq, | 910 | entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr); |
902 | rx->queue, hdr); | ||
903 | if (!entry) { | 911 | if (!entry) { |
904 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); | 912 | I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag); |
905 | return RX_DROP_MONITOR; | 913 | return RX_DROP_MONITOR; |
@@ -924,11 +932,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
924 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); | 932 | memcpy(entry->last_pn, pn, CCMP_PN_LEN); |
925 | } | 933 | } |
926 | 934 | ||
927 | skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc)); | 935 | skb_pull(rx->skb, ieee80211_hdrlen(fc)); |
928 | __skb_queue_tail(&entry->skb_list, rx->skb); | 936 | __skb_queue_tail(&entry->skb_list, rx->skb); |
929 | entry->last_frag = frag; | 937 | entry->last_frag = frag; |
930 | entry->extra_len += rx->skb->len; | 938 | entry->extra_len += rx->skb->len; |
931 | if (rx->fc & IEEE80211_FCTL_MOREFRAGS) { | 939 | if (ieee80211_has_morefrags(fc)) { |
932 | rx->skb = NULL; | 940 | rx->skb = NULL; |
933 | return RX_QUEUED; | 941 | return RX_QUEUED; |
934 | } | 942 | } |
@@ -968,15 +976,14 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
968 | struct sk_buff *skb; | 976 | struct sk_buff *skb; |
969 | int no_pending_pkts; | 977 | int no_pending_pkts; |
970 | DECLARE_MAC_BUF(mac); | 978 | DECLARE_MAC_BUF(mac); |
979 | __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control; | ||
971 | 980 | ||
972 | if (likely(!rx->sta || | 981 | if (likely(!rx->sta || !ieee80211_is_pspoll(fc) || |
973 | (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL || | ||
974 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL || | ||
975 | !(rx->flags & IEEE80211_RX_RA_MATCH))) | 982 | !(rx->flags & IEEE80211_RX_RA_MATCH))) |
976 | return RX_CONTINUE; | 983 | return RX_CONTINUE; |
977 | 984 | ||
978 | if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) && | 985 | if ((sdata->vif.type != NL80211_IFTYPE_AP) && |
979 | (sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) | 986 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
980 | return RX_DROP_UNUSABLE; | 987 | return RX_DROP_UNUSABLE; |
981 | 988 | ||
982 | skb = skb_dequeue(&rx->sta->tx_filtered); | 989 | skb = skb_dequeue(&rx->sta->tx_filtered); |
@@ -1000,7 +1007,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1000 | 1007 | ||
1001 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1008 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
1002 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", | 1009 | printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n", |
1003 | print_mac(mac, rx->sta->addr), rx->sta->aid, | 1010 | print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid, |
1004 | skb_queue_len(&rx->sta->ps_tx_buf)); | 1011 | skb_queue_len(&rx->sta->ps_tx_buf)); |
1005 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1012 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1006 | 1013 | ||
@@ -1025,7 +1032,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) | |||
1025 | */ | 1032 | */ |
1026 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " | 1033 | printk(KERN_DEBUG "%s: STA %s sent PS Poll even " |
1027 | "though there are no buffered frames for it\n", | 1034 | "though there are no buffered frames for it\n", |
1028 | rx->dev->name, print_mac(mac, rx->sta->addr)); | 1035 | rx->dev->name, print_mac(mac, rx->sta->sta.addr)); |
1029 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1036 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1030 | } | 1037 | } |
1031 | 1038 | ||
@@ -1050,7 +1057,6 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | |||
1050 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); | 1057 | ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); |
1051 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); | 1058 | hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); |
1052 | /* change frame type to non QOS */ | 1059 | /* change frame type to non QOS */ |
1053 | rx->fc &= ~IEEE80211_STYPE_QOS_DATA; | ||
1054 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); | 1060 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1055 | 1061 | ||
1056 | return RX_CONTINUE; | 1062 | return RX_CONTINUE; |
@@ -1067,7 +1073,7 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | |||
1067 | } | 1073 | } |
1068 | 1074 | ||
1069 | static int | 1075 | static int |
1070 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) | 1076 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) |
1071 | { | 1077 | { |
1072 | /* | 1078 | /* |
1073 | * Pass through unencrypted frames if the hardware has | 1079 | * Pass through unencrypted frames if the hardware has |
@@ -1077,9 +1083,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx) | |||
1077 | return 0; | 1083 | return 0; |
1078 | 1084 | ||
1079 | /* Drop unencrypted frames if key is set. */ | 1085 | /* Drop unencrypted frames if key is set. */ |
1080 | if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) && | 1086 | if (unlikely(!ieee80211_has_protected(fc) && |
1081 | (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 1087 | !ieee80211_is_nullfunc(fc) && |
1082 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC && | ||
1083 | (rx->key || rx->sdata->drop_unencrypted))) | 1088 | (rx->key || rx->sdata->drop_unencrypted))) |
1084 | return -EACCES; | 1089 | return -EACCES; |
1085 | 1090 | ||
@@ -1091,7 +1096,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1091 | { | 1096 | { |
1092 | struct net_device *dev = rx->dev; | 1097 | struct net_device *dev = rx->dev; |
1093 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; | 1098 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; |
1094 | u16 fc, hdrlen, ethertype; | 1099 | u16 hdrlen, ethertype; |
1095 | u8 *payload; | 1100 | u8 *payload; |
1096 | u8 dst[ETH_ALEN]; | 1101 | u8 dst[ETH_ALEN]; |
1097 | u8 src[ETH_ALEN] __aligned(2); | 1102 | u8 src[ETH_ALEN] __aligned(2); |
@@ -1102,12 +1107,10 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1102 | DECLARE_MAC_BUF(mac3); | 1107 | DECLARE_MAC_BUF(mac3); |
1103 | DECLARE_MAC_BUF(mac4); | 1108 | DECLARE_MAC_BUF(mac4); |
1104 | 1109 | ||
1105 | fc = rx->fc; | 1110 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1106 | |||
1107 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | ||
1108 | return -1; | 1111 | return -1; |
1109 | 1112 | ||
1110 | hdrlen = ieee80211_get_hdrlen(fc); | 1113 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1111 | 1114 | ||
1112 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1115 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1113 | hdrlen += ieee80211_get_mesh_hdrlen( | 1116 | hdrlen += ieee80211_get_mesh_hdrlen( |
@@ -1122,42 +1125,29 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1122 | * 1 0 BSSID SA DA n/a | 1125 | * 1 0 BSSID SA DA n/a |
1123 | * 1 1 RA TA DA SA | 1126 | * 1 1 RA TA DA SA |
1124 | */ | 1127 | */ |
1125 | 1128 | memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN); | |
1126 | switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { | 1129 | memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN); |
1127 | case IEEE80211_FCTL_TODS: | 1130 | |
1128 | /* BSSID SA DA */ | 1131 | switch (hdr->frame_control & |
1129 | memcpy(dst, hdr->addr3, ETH_ALEN); | 1132 | cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) { |
1130 | memcpy(src, hdr->addr2, ETH_ALEN); | 1133 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS): |
1131 | 1134 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP && | |
1132 | if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP && | 1135 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN)) |
1133 | sdata->vif.type != IEEE80211_IF_TYPE_VLAN)) | ||
1134 | return -1; | 1136 | return -1; |
1135 | break; | 1137 | break; |
1136 | case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): | 1138 | case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS): |
1137 | /* RA TA DA SA */ | 1139 | if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS && |
1138 | memcpy(dst, hdr->addr3, ETH_ALEN); | 1140 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT)) |
1139 | memcpy(src, hdr->addr4, ETH_ALEN); | ||
1140 | |||
1141 | if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS && | ||
1142 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)) | ||
1143 | return -1; | 1141 | return -1; |
1144 | break; | 1142 | break; |
1145 | case IEEE80211_FCTL_FROMDS: | 1143 | case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS): |
1146 | /* DA BSSID SA */ | 1144 | if (sdata->vif.type != NL80211_IFTYPE_STATION || |
1147 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
1148 | memcpy(src, hdr->addr3, ETH_ALEN); | ||
1149 | |||
1150 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA || | ||
1151 | (is_multicast_ether_addr(dst) && | 1145 | (is_multicast_ether_addr(dst) && |
1152 | !compare_ether_addr(src, dev->dev_addr))) | 1146 | !compare_ether_addr(src, dev->dev_addr))) |
1153 | return -1; | 1147 | return -1; |
1154 | break; | 1148 | break; |
1155 | case 0: | 1149 | case __constant_cpu_to_le16(0): |
1156 | /* DA SA BSSID */ | 1150 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1157 | memcpy(dst, hdr->addr1, ETH_ALEN); | ||
1158 | memcpy(src, hdr->addr2, ETH_ALEN); | ||
1159 | |||
1160 | if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | ||
1161 | return -1; | 1151 | return -1; |
1162 | break; | 1152 | break; |
1163 | } | 1153 | } |
@@ -1193,7 +1183,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | |||
1193 | /* | 1183 | /* |
1194 | * requires that rx->skb is a frame with ethernet header | 1184 | * requires that rx->skb is a frame with ethernet header |
1195 | */ | 1185 | */ |
1196 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) | 1186 | static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) |
1197 | { | 1187 | { |
1198 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) | 1188 | static const u8 pae_group_addr[ETH_ALEN] __aligned(2) |
1199 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; | 1189 | = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 }; |
@@ -1209,7 +1199,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx) | |||
1209 | return true; | 1199 | return true; |
1210 | 1200 | ||
1211 | if (ieee80211_802_1x_port_control(rx) || | 1201 | if (ieee80211_802_1x_port_control(rx) || |
1212 | ieee80211_drop_unencrypted(rx)) | 1202 | ieee80211_drop_unencrypted(rx, fc)) |
1213 | return false; | 1203 | return false; |
1214 | 1204 | ||
1215 | return true; | 1205 | return true; |
@@ -1231,8 +1221,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1231 | skb = rx->skb; | 1221 | skb = rx->skb; |
1232 | xmit_skb = NULL; | 1222 | xmit_skb = NULL; |
1233 | 1223 | ||
1234 | if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP || | 1224 | if ((sdata->vif.type == NL80211_IFTYPE_AP || |
1235 | sdata->vif.type == IEEE80211_IF_TYPE_VLAN) && | 1225 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1226 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && | ||
1236 | (rx->flags & IEEE80211_RX_RA_MATCH)) { | 1227 | (rx->flags & IEEE80211_RX_RA_MATCH)) { |
1237 | if (is_multicast_ether_addr(ehdr->h_dest)) { | 1228 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
1238 | /* | 1229 | /* |
@@ -1279,20 +1270,21 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1279 | { | 1270 | { |
1280 | struct net_device *dev = rx->dev; | 1271 | struct net_device *dev = rx->dev; |
1281 | struct ieee80211_local *local = rx->local; | 1272 | struct ieee80211_local *local = rx->local; |
1282 | u16 fc, ethertype; | 1273 | u16 ethertype; |
1283 | u8 *payload; | 1274 | u8 *payload; |
1284 | struct sk_buff *skb = rx->skb, *frame = NULL; | 1275 | struct sk_buff *skb = rx->skb, *frame = NULL; |
1276 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
1277 | __le16 fc = hdr->frame_control; | ||
1285 | const struct ethhdr *eth; | 1278 | const struct ethhdr *eth; |
1286 | int remaining, err; | 1279 | int remaining, err; |
1287 | u8 dst[ETH_ALEN]; | 1280 | u8 dst[ETH_ALEN]; |
1288 | u8 src[ETH_ALEN]; | 1281 | u8 src[ETH_ALEN]; |
1289 | DECLARE_MAC_BUF(mac); | 1282 | DECLARE_MAC_BUF(mac); |
1290 | 1283 | ||
1291 | fc = rx->fc; | 1284 | if (unlikely(!ieee80211_is_data(fc))) |
1292 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) | ||
1293 | return RX_CONTINUE; | 1285 | return RX_CONTINUE; |
1294 | 1286 | ||
1295 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | 1287 | if (unlikely(!ieee80211_is_data_present(fc))) |
1296 | return RX_DROP_MONITOR; | 1288 | return RX_DROP_MONITOR; |
1297 | 1289 | ||
1298 | if (!(rx->flags & IEEE80211_RX_AMSDU)) | 1290 | if (!(rx->flags & IEEE80211_RX_AMSDU)) |
@@ -1374,7 +1366,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1374 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); | 1366 | memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN); |
1375 | } | 1367 | } |
1376 | 1368 | ||
1377 | if (!ieee80211_frame_allowed(rx)) { | 1369 | if (!ieee80211_frame_allowed(rx, fc)) { |
1378 | if (skb == frame) /* last frame */ | 1370 | if (skb == frame) /* last frame */ |
1379 | return RX_DROP_UNUSABLE; | 1371 | return RX_DROP_UNUSABLE; |
1380 | dev_kfree_skb(frame); | 1372 | dev_kfree_skb(frame); |
@@ -1413,7 +1405,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1413 | 1405 | ||
1414 | if (rx->flags & IEEE80211_RX_RA_MATCH) { | 1406 | if (rx->flags & IEEE80211_RX_RA_MATCH) { |
1415 | if (!mesh_hdr->ttl) | 1407 | if (!mesh_hdr->ttl) |
1416 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, | 1408 | IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh, |
1417 | dropped_frames_ttl); | 1409 | dropped_frames_ttl); |
1418 | else { | 1410 | else { |
1419 | struct ieee80211_hdr *fwd_hdr; | 1411 | struct ieee80211_hdr *fwd_hdr; |
@@ -1448,21 +1440,21 @@ static ieee80211_rx_result debug_noinline | |||
1448 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1440 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1449 | { | 1441 | { |
1450 | struct net_device *dev = rx->dev; | 1442 | struct net_device *dev = rx->dev; |
1451 | u16 fc; | 1443 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1444 | __le16 fc = hdr->frame_control; | ||
1452 | int err; | 1445 | int err; |
1453 | 1446 | ||
1454 | fc = rx->fc; | 1447 | if (unlikely(!ieee80211_is_data(hdr->frame_control))) |
1455 | if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)) | ||
1456 | return RX_CONTINUE; | 1448 | return RX_CONTINUE; |
1457 | 1449 | ||
1458 | if (unlikely(!WLAN_FC_DATA_PRESENT(fc))) | 1450 | if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) |
1459 | return RX_DROP_MONITOR; | 1451 | return RX_DROP_MONITOR; |
1460 | 1452 | ||
1461 | err = ieee80211_data_to_8023(rx); | 1453 | err = ieee80211_data_to_8023(rx); |
1462 | if (unlikely(err)) | 1454 | if (unlikely(err)) |
1463 | return RX_DROP_UNUSABLE; | 1455 | return RX_DROP_UNUSABLE; |
1464 | 1456 | ||
1465 | if (!ieee80211_frame_allowed(rx)) | 1457 | if (!ieee80211_frame_allowed(rx, fc)) |
1466 | return RX_DROP_MONITOR; | 1458 | return RX_DROP_MONITOR; |
1467 | 1459 | ||
1468 | rx->skb->dev = dev; | 1460 | rx->skb->dev = dev; |
@@ -1520,22 +1512,97 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1520 | } | 1512 | } |
1521 | 1513 | ||
1522 | static ieee80211_rx_result debug_noinline | 1514 | static ieee80211_rx_result debug_noinline |
1515 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | ||
1516 | { | ||
1517 | struct ieee80211_local *local = rx->local; | ||
1518 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1519 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | ||
1520 | int len = rx->skb->len; | ||
1521 | |||
1522 | if (!ieee80211_is_action(mgmt->frame_control)) | ||
1523 | return RX_CONTINUE; | ||
1524 | |||
1525 | if (!rx->sta) | ||
1526 | return RX_DROP_MONITOR; | ||
1527 | |||
1528 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | ||
1529 | return RX_DROP_MONITOR; | ||
1530 | |||
1531 | /* all categories we currently handle have action_code */ | ||
1532 | if (len < IEEE80211_MIN_ACTION_SIZE + 1) | ||
1533 | return RX_DROP_MONITOR; | ||
1534 | |||
1535 | /* | ||
1536 | * FIXME: revisit this, I'm sure we should handle most | ||
1537 | * of these frames in other modes as well! | ||
1538 | */ | ||
1539 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
1540 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | ||
1541 | return RX_DROP_MONITOR; | ||
1542 | |||
1543 | switch (mgmt->u.action.category) { | ||
1544 | case WLAN_CATEGORY_BACK: | ||
1545 | switch (mgmt->u.action.u.addba_req.action_code) { | ||
1546 | case WLAN_ACTION_ADDBA_REQ: | ||
1547 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1548 | sizeof(mgmt->u.action.u.addba_req))) | ||
1549 | return RX_DROP_MONITOR; | ||
1550 | ieee80211_process_addba_request(local, rx->sta, mgmt, len); | ||
1551 | break; | ||
1552 | case WLAN_ACTION_ADDBA_RESP: | ||
1553 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1554 | sizeof(mgmt->u.action.u.addba_resp))) | ||
1555 | return RX_DROP_MONITOR; | ||
1556 | ieee80211_process_addba_resp(local, rx->sta, mgmt, len); | ||
1557 | break; | ||
1558 | case WLAN_ACTION_DELBA: | ||
1559 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1560 | sizeof(mgmt->u.action.u.delba))) | ||
1561 | return RX_DROP_MONITOR; | ||
1562 | ieee80211_process_delba(sdata, rx->sta, mgmt, len); | ||
1563 | break; | ||
1564 | } | ||
1565 | break; | ||
1566 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
1567 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
1568 | return RX_DROP_MONITOR; | ||
1569 | switch (mgmt->u.action.u.measurement.action_code) { | ||
1570 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
1571 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
1572 | sizeof(mgmt->u.action.u.measurement))) | ||
1573 | return RX_DROP_MONITOR; | ||
1574 | ieee80211_process_measurement_req(sdata, mgmt, len); | ||
1575 | break; | ||
1576 | } | ||
1577 | break; | ||
1578 | default: | ||
1579 | return RX_CONTINUE; | ||
1580 | } | ||
1581 | |||
1582 | rx->sta->rx_packets++; | ||
1583 | dev_kfree_skb(rx->skb); | ||
1584 | return RX_QUEUED; | ||
1585 | } | ||
1586 | |||
1587 | static ieee80211_rx_result debug_noinline | ||
1523 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1588 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1524 | { | 1589 | { |
1525 | struct ieee80211_sub_if_data *sdata; | 1590 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); |
1526 | 1591 | ||
1527 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1592 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1528 | return RX_DROP_MONITOR; | 1593 | return RX_DROP_MONITOR; |
1529 | 1594 | ||
1530 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1595 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1531 | if ((sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1596 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status); |
1532 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS || | 1597 | |
1533 | sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) && | 1598 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
1534 | !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)) | 1599 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
1535 | ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status); | 1600 | return RX_DROP_MONITOR; |
1536 | else | 1601 | |
1602 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | ||
1537 | return RX_DROP_MONITOR; | 1603 | return RX_DROP_MONITOR; |
1538 | 1604 | ||
1605 | ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status); | ||
1539 | return RX_QUEUED; | 1606 | return RX_QUEUED; |
1540 | } | 1607 | } |
1541 | 1608 | ||
@@ -1565,7 +1632,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1565 | if (!ieee80211_has_protected(hdr->frame_control)) | 1632 | if (!ieee80211_has_protected(hdr->frame_control)) |
1566 | goto ignore; | 1633 | goto ignore; |
1567 | 1634 | ||
1568 | if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { | 1635 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { |
1569 | /* | 1636 | /* |
1570 | * APs with pairwise keys should never receive Michael MIC | 1637 | * APs with pairwise keys should never receive Michael MIC |
1571 | * errors for non-zero keyidx because these are reserved for | 1638 | * errors for non-zero keyidx because these are reserved for |
@@ -1579,7 +1646,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, | |||
1579 | !ieee80211_is_auth(hdr->frame_control)) | 1646 | !ieee80211_is_auth(hdr->frame_control)) |
1580 | goto ignore; | 1647 | goto ignore; |
1581 | 1648 | ||
1582 | mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); | 1649 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr); |
1583 | ignore: | 1650 | ignore: |
1584 | dev_kfree_skb(rx->skb); | 1651 | dev_kfree_skb(rx->skb); |
1585 | rx->skb = NULL; | 1652 | rx->skb = NULL; |
@@ -1635,7 +1702,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | |||
1635 | if (!netif_running(sdata->dev)) | 1702 | if (!netif_running(sdata->dev)) |
1636 | continue; | 1703 | continue; |
1637 | 1704 | ||
1638 | if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || | 1705 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || |
1639 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) | 1706 | !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)) |
1640 | continue; | 1707 | continue; |
1641 | 1708 | ||
@@ -1698,6 +1765,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1698 | CALL_RXH(ieee80211_rx_h_mesh_fwding); | 1765 | CALL_RXH(ieee80211_rx_h_mesh_fwding); |
1699 | CALL_RXH(ieee80211_rx_h_data) | 1766 | CALL_RXH(ieee80211_rx_h_data) |
1700 | CALL_RXH(ieee80211_rx_h_ctrl) | 1767 | CALL_RXH(ieee80211_rx_h_ctrl) |
1768 | CALL_RXH(ieee80211_rx_h_action) | ||
1701 | CALL_RXH(ieee80211_rx_h_mgmt) | 1769 | CALL_RXH(ieee80211_rx_h_mgmt) |
1702 | 1770 | ||
1703 | #undef CALL_RXH | 1771 | #undef CALL_RXH |
@@ -1733,7 +1801,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1733 | int multicast = is_multicast_ether_addr(hdr->addr1); | 1801 | int multicast = is_multicast_ether_addr(hdr->addr1); |
1734 | 1802 | ||
1735 | switch (sdata->vif.type) { | 1803 | switch (sdata->vif.type) { |
1736 | case IEEE80211_IF_TYPE_STA: | 1804 | case NL80211_IFTYPE_STATION: |
1737 | if (!bssid) | 1805 | if (!bssid) |
1738 | return 0; | 1806 | return 0; |
1739 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1807 | if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
@@ -1748,14 +1816,10 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1748 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1816 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1749 | } | 1817 | } |
1750 | break; | 1818 | break; |
1751 | case IEEE80211_IF_TYPE_IBSS: | 1819 | case NL80211_IFTYPE_ADHOC: |
1752 | if (!bssid) | 1820 | if (!bssid) |
1753 | return 0; | 1821 | return 0; |
1754 | if (ieee80211_is_beacon(hdr->frame_control)) { | 1822 | if (ieee80211_is_beacon(hdr->frame_control)) { |
1755 | if (!rx->sta) | ||
1756 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, | ||
1757 | rx->skb, bssid, hdr->addr2, | ||
1758 | BIT(rx->status->rate_idx)); | ||
1759 | return 1; | 1823 | return 1; |
1760 | } | 1824 | } |
1761 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { | 1825 | else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) { |
@@ -1769,11 +1833,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1769 | return 0; | 1833 | return 0; |
1770 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1834 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1771 | } else if (!rx->sta) | 1835 | } else if (!rx->sta) |
1772 | rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, | 1836 | rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb, |
1773 | bssid, hdr->addr2, | 1837 | bssid, hdr->addr2, |
1774 | BIT(rx->status->rate_idx)); | 1838 | BIT(rx->status->rate_idx)); |
1775 | break; | 1839 | break; |
1776 | case IEEE80211_IF_TYPE_MESH_POINT: | 1840 | case NL80211_IFTYPE_MESH_POINT: |
1777 | if (!multicast && | 1841 | if (!multicast && |
1778 | compare_ether_addr(sdata->dev->dev_addr, | 1842 | compare_ether_addr(sdata->dev->dev_addr, |
1779 | hdr->addr1) != 0) { | 1843 | hdr->addr1) != 0) { |
@@ -1783,8 +1847,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1783 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1847 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1784 | } | 1848 | } |
1785 | break; | 1849 | break; |
1786 | case IEEE80211_IF_TYPE_VLAN: | 1850 | case NL80211_IFTYPE_AP_VLAN: |
1787 | case IEEE80211_IF_TYPE_AP: | 1851 | case NL80211_IFTYPE_AP: |
1788 | if (!bssid) { | 1852 | if (!bssid) { |
1789 | if (compare_ether_addr(sdata->dev->dev_addr, | 1853 | if (compare_ether_addr(sdata->dev->dev_addr, |
1790 | hdr->addr1)) | 1854 | hdr->addr1)) |
@@ -1796,16 +1860,17 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1796 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1860 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1797 | } | 1861 | } |
1798 | break; | 1862 | break; |
1799 | case IEEE80211_IF_TYPE_WDS: | 1863 | case NL80211_IFTYPE_WDS: |
1800 | if (bssid || !ieee80211_is_data(hdr->frame_control)) | 1864 | if (bssid || !ieee80211_is_data(hdr->frame_control)) |
1801 | return 0; | 1865 | return 0; |
1802 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) | 1866 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
1803 | return 0; | 1867 | return 0; |
1804 | break; | 1868 | break; |
1805 | case IEEE80211_IF_TYPE_MNTR: | 1869 | case NL80211_IFTYPE_MONITOR: |
1806 | /* take everything */ | 1870 | /* take everything */ |
1807 | break; | 1871 | break; |
1808 | case IEEE80211_IF_TYPE_INVALID: | 1872 | case NL80211_IFTYPE_UNSPECIFIED: |
1873 | case __NL80211_IFTYPE_AFTER_LAST: | ||
1809 | /* should never get here */ | 1874 | /* should never get here */ |
1810 | WARN_ON(1); | 1875 | WARN_ON(1); |
1811 | break; | 1876 | break; |
@@ -1827,23 +1892,20 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1827 | struct ieee80211_sub_if_data *sdata; | 1892 | struct ieee80211_sub_if_data *sdata; |
1828 | struct ieee80211_hdr *hdr; | 1893 | struct ieee80211_hdr *hdr; |
1829 | struct ieee80211_rx_data rx; | 1894 | struct ieee80211_rx_data rx; |
1830 | u16 type; | ||
1831 | int prepares; | 1895 | int prepares; |
1832 | struct ieee80211_sub_if_data *prev = NULL; | 1896 | struct ieee80211_sub_if_data *prev = NULL; |
1833 | struct sk_buff *skb_new; | 1897 | struct sk_buff *skb_new; |
1834 | u8 *bssid; | 1898 | u8 *bssid; |
1835 | 1899 | ||
1836 | hdr = (struct ieee80211_hdr *) skb->data; | 1900 | hdr = (struct ieee80211_hdr *)skb->data; |
1837 | memset(&rx, 0, sizeof(rx)); | 1901 | memset(&rx, 0, sizeof(rx)); |
1838 | rx.skb = skb; | 1902 | rx.skb = skb; |
1839 | rx.local = local; | 1903 | rx.local = local; |
1840 | 1904 | ||
1841 | rx.status = status; | 1905 | rx.status = status; |
1842 | rx.rate = rate; | 1906 | rx.rate = rate; |
1843 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1844 | type = rx.fc & IEEE80211_FCTL_FTYPE; | ||
1845 | 1907 | ||
1846 | if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT) | 1908 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) |
1847 | local->dot11ReceivedFragmentCount++; | 1909 | local->dot11ReceivedFragmentCount++; |
1848 | 1910 | ||
1849 | rx.sta = sta_info_get(local, hdr->addr2); | 1911 | rx.sta = sta_info_get(local, hdr->addr2); |
@@ -1857,7 +1919,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1857 | return; | 1919 | return; |
1858 | } | 1920 | } |
1859 | 1921 | ||
1860 | if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning)) | 1922 | if (unlikely(local->sw_scanning || local->hw_scanning)) |
1861 | rx.flags |= IEEE80211_RX_IN_SCAN; | 1923 | rx.flags |= IEEE80211_RX_IN_SCAN; |
1862 | 1924 | ||
1863 | ieee80211_parse_qos(&rx); | 1925 | ieee80211_parse_qos(&rx); |
@@ -1869,7 +1931,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1869 | if (!netif_running(sdata->dev)) | 1931 | if (!netif_running(sdata->dev)) |
1870 | continue; | 1932 | continue; |
1871 | 1933 | ||
1872 | if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR) | 1934 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) |
1873 | continue; | 1935 | continue; |
1874 | 1936 | ||
1875 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | 1937 | bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); |
@@ -1904,14 +1966,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
1904 | prev->dev->name); | 1966 | prev->dev->name); |
1905 | continue; | 1967 | continue; |
1906 | } | 1968 | } |
1907 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1908 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); | 1969 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); |
1909 | prev = sdata; | 1970 | prev = sdata; |
1910 | } | 1971 | } |
1911 | if (prev) { | 1972 | if (prev) |
1912 | rx.fc = le16_to_cpu(hdr->frame_control); | ||
1913 | ieee80211_invoke_rx_handlers(prev, &rx, skb); | 1973 | ieee80211_invoke_rx_handlers(prev, &rx, skb); |
1914 | } else | 1974 | else |
1915 | dev_kfree_skb(skb); | 1975 | dev_kfree_skb(skb); |
1916 | } | 1976 | } |
1917 | 1977 | ||
@@ -2080,7 +2140,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2080 | /* if this mpdu is fragmented - terminate rx aggregation session */ | 2140 | /* if this mpdu is fragmented - terminate rx aggregation session */ |
2081 | sc = le16_to_cpu(hdr->seq_ctrl); | 2141 | sc = le16_to_cpu(hdr->seq_ctrl); |
2082 | if (sc & IEEE80211_SCTL_FRAG) { | 2142 | if (sc & IEEE80211_SCTL_FRAG) { |
2083 | ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr, | 2143 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, |
2084 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 2144 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); |
2085 | ret = 1; | 2145 | ret = 1; |
2086 | goto end_reorder; | 2146 | goto end_reorder; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c new file mode 100644 index 000000000000..8e6685e7ae85 --- /dev/null +++ b/net/mac80211/scan.c | |||
@@ -0,0 +1,937 @@ | |||
1 | /* | ||
2 | * Scanning implementation | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /* TODO: | ||
16 | * order BSS list by RSSI(?) ("quality of AP") | ||
17 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
18 | * SSID) | ||
19 | */ | ||
20 | |||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/if_arp.h> | ||
23 | #include <net/mac80211.h> | ||
24 | #include <net/iw_handler.h> | ||
25 | |||
26 | #include "ieee80211_i.h" | ||
27 | #include "mesh.h" | ||
28 | |||
29 | #define IEEE80211_PROBE_DELAY (HZ / 33) | ||
30 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | ||
31 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | ||
32 | |||
33 | void ieee80211_rx_bss_list_init(struct ieee80211_local *local) | ||
34 | { | ||
35 | spin_lock_init(&local->bss_lock); | ||
36 | INIT_LIST_HEAD(&local->bss_list); | ||
37 | } | ||
38 | |||
39 | void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local) | ||
40 | { | ||
41 | struct ieee80211_bss *bss, *tmp; | ||
42 | |||
43 | list_for_each_entry_safe(bss, tmp, &local->bss_list, list) | ||
44 | ieee80211_rx_bss_put(local, bss); | ||
45 | } | ||
46 | |||
47 | struct ieee80211_bss * | ||
48 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | ||
49 | u8 *ssid, u8 ssid_len) | ||
50 | { | ||
51 | struct ieee80211_bss *bss; | ||
52 | |||
53 | spin_lock_bh(&local->bss_lock); | ||
54 | bss = local->bss_hash[STA_HASH(bssid)]; | ||
55 | while (bss) { | ||
56 | if (!bss_mesh_cfg(bss) && | ||
57 | !memcmp(bss->bssid, bssid, ETH_ALEN) && | ||
58 | bss->freq == freq && | ||
59 | bss->ssid_len == ssid_len && | ||
60 | (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) { | ||
61 | atomic_inc(&bss->users); | ||
62 | break; | ||
63 | } | ||
64 | bss = bss->hnext; | ||
65 | } | ||
66 | spin_unlock_bh(&local->bss_lock); | ||
67 | return bss; | ||
68 | } | ||
69 | |||
70 | /* Caller must hold local->bss_lock */ | ||
71 | static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local, | ||
72 | struct ieee80211_bss *bss) | ||
73 | { | ||
74 | u8 hash_idx; | ||
75 | |||
76 | if (bss_mesh_cfg(bss)) | ||
77 | hash_idx = mesh_id_hash(bss_mesh_id(bss), | ||
78 | bss_mesh_id_len(bss)); | ||
79 | else | ||
80 | hash_idx = STA_HASH(bss->bssid); | ||
81 | |||
82 | bss->hnext = local->bss_hash[hash_idx]; | ||
83 | local->bss_hash[hash_idx] = bss; | ||
84 | } | ||
85 | |||
86 | /* Caller must hold local->bss_lock */ | ||
87 | static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | ||
88 | struct ieee80211_bss *bss) | ||
89 | { | ||
90 | struct ieee80211_bss *b, *prev = NULL; | ||
91 | b = local->bss_hash[STA_HASH(bss->bssid)]; | ||
92 | while (b) { | ||
93 | if (b == bss) { | ||
94 | if (!prev) | ||
95 | local->bss_hash[STA_HASH(bss->bssid)] = | ||
96 | bss->hnext; | ||
97 | else | ||
98 | prev->hnext = bss->hnext; | ||
99 | break; | ||
100 | } | ||
101 | prev = b; | ||
102 | b = b->hnext; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | struct ieee80211_bss * | ||
107 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
108 | u8 *ssid, u8 ssid_len) | ||
109 | { | ||
110 | struct ieee80211_bss *bss; | ||
111 | |||
112 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
113 | if (!bss) | ||
114 | return NULL; | ||
115 | atomic_set(&bss->users, 2); | ||
116 | memcpy(bss->bssid, bssid, ETH_ALEN); | ||
117 | bss->freq = freq; | ||
118 | if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) { | ||
119 | memcpy(bss->ssid, ssid, ssid_len); | ||
120 | bss->ssid_len = ssid_len; | ||
121 | } | ||
122 | |||
123 | spin_lock_bh(&local->bss_lock); | ||
124 | /* TODO: order by RSSI? */ | ||
125 | list_add_tail(&bss->list, &local->bss_list); | ||
126 | __ieee80211_rx_bss_hash_add(local, bss); | ||
127 | spin_unlock_bh(&local->bss_lock); | ||
128 | return bss; | ||
129 | } | ||
130 | |||
131 | #ifdef CONFIG_MAC80211_MESH | ||
132 | static struct ieee80211_bss * | ||
133 | ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
134 | u8 *mesh_cfg, int freq) | ||
135 | { | ||
136 | struct ieee80211_bss *bss; | ||
137 | |||
138 | spin_lock_bh(&local->bss_lock); | ||
139 | bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)]; | ||
140 | while (bss) { | ||
141 | if (bss_mesh_cfg(bss) && | ||
142 | !memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) && | ||
143 | bss->freq == freq && | ||
144 | mesh_id_len == bss->mesh_id_len && | ||
145 | (mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id, | ||
146 | mesh_id_len))) { | ||
147 | atomic_inc(&bss->users); | ||
148 | break; | ||
149 | } | ||
150 | bss = bss->hnext; | ||
151 | } | ||
152 | spin_unlock_bh(&local->bss_lock); | ||
153 | return bss; | ||
154 | } | ||
155 | |||
156 | static struct ieee80211_bss * | ||
157 | ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len, | ||
158 | u8 *mesh_cfg, int mesh_config_len, int freq) | ||
159 | { | ||
160 | struct ieee80211_bss *bss; | ||
161 | |||
162 | if (mesh_config_len != MESH_CFG_LEN) | ||
163 | return NULL; | ||
164 | |||
165 | bss = kzalloc(sizeof(*bss), GFP_ATOMIC); | ||
166 | if (!bss) | ||
167 | return NULL; | ||
168 | |||
169 | bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC); | ||
170 | if (!bss->mesh_cfg) { | ||
171 | kfree(bss); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
175 | if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) { | ||
176 | bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC); | ||
177 | if (!bss->mesh_id) { | ||
178 | kfree(bss->mesh_cfg); | ||
179 | kfree(bss); | ||
180 | return NULL; | ||
181 | } | ||
182 | memcpy(bss->mesh_id, mesh_id, mesh_id_len); | ||
183 | } | ||
184 | |||
185 | atomic_set(&bss->users, 2); | ||
186 | memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN); | ||
187 | bss->mesh_id_len = mesh_id_len; | ||
188 | bss->freq = freq; | ||
189 | spin_lock_bh(&local->bss_lock); | ||
190 | /* TODO: order by RSSI? */ | ||
191 | list_add_tail(&bss->list, &local->bss_list); | ||
192 | __ieee80211_rx_bss_hash_add(local, bss); | ||
193 | spin_unlock_bh(&local->bss_lock); | ||
194 | return bss; | ||
195 | } | ||
196 | #endif | ||
197 | |||
198 | static void ieee80211_rx_bss_free(struct ieee80211_bss *bss) | ||
199 | { | ||
200 | kfree(bss->ies); | ||
201 | kfree(bss_mesh_id(bss)); | ||
202 | kfree(bss_mesh_cfg(bss)); | ||
203 | kfree(bss); | ||
204 | } | ||
205 | |||
206 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | ||
207 | struct ieee80211_bss *bss) | ||
208 | { | ||
209 | local_bh_disable(); | ||
210 | if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) { | ||
211 | local_bh_enable(); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | __ieee80211_rx_bss_hash_del(local, bss); | ||
216 | list_del(&bss->list); | ||
217 | spin_unlock_bh(&local->bss_lock); | ||
218 | ieee80211_rx_bss_free(bss); | ||
219 | } | ||
220 | |||
221 | struct ieee80211_bss * | ||
222 | ieee80211_bss_info_update(struct ieee80211_local *local, | ||
223 | struct ieee80211_rx_status *rx_status, | ||
224 | struct ieee80211_mgmt *mgmt, | ||
225 | size_t len, | ||
226 | struct ieee802_11_elems *elems, | ||
227 | int freq, bool beacon) | ||
228 | { | ||
229 | struct ieee80211_bss *bss; | ||
230 | int clen; | ||
231 | |||
232 | #ifdef CONFIG_MAC80211_MESH | ||
233 | if (elems->mesh_config) | ||
234 | bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id, | ||
235 | elems->mesh_id_len, elems->mesh_config, freq); | ||
236 | else | ||
237 | #endif | ||
238 | bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq, | ||
239 | elems->ssid, elems->ssid_len); | ||
240 | if (!bss) { | ||
241 | #ifdef CONFIG_MAC80211_MESH | ||
242 | if (elems->mesh_config) | ||
243 | bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id, | ||
244 | elems->mesh_id_len, elems->mesh_config, | ||
245 | elems->mesh_config_len, freq); | ||
246 | else | ||
247 | #endif | ||
248 | bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq, | ||
249 | elems->ssid, elems->ssid_len); | ||
250 | if (!bss) | ||
251 | return NULL; | ||
252 | } else { | ||
253 | #if 0 | ||
254 | /* TODO: order by RSSI? */ | ||
255 | spin_lock_bh(&local->bss_lock); | ||
256 | list_move_tail(&bss->list, &local->bss_list); | ||
257 | spin_unlock_bh(&local->bss_lock); | ||
258 | #endif | ||
259 | } | ||
260 | |||
261 | /* save the ERP value so that it is available at association time */ | ||
262 | if (elems->erp_info && elems->erp_info_len >= 1) { | ||
263 | bss->erp_value = elems->erp_info[0]; | ||
264 | bss->has_erp_value = 1; | ||
265 | } | ||
266 | |||
267 | bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); | ||
268 | bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); | ||
269 | |||
270 | if (elems->tim) { | ||
271 | struct ieee80211_tim_ie *tim_ie = | ||
272 | (struct ieee80211_tim_ie *)elems->tim; | ||
273 | bss->dtim_period = tim_ie->dtim_period; | ||
274 | } | ||
275 | |||
276 | /* set default value for buggy APs */ | ||
277 | if (!elems->tim || bss->dtim_period == 0) | ||
278 | bss->dtim_period = 1; | ||
279 | |||
280 | bss->supp_rates_len = 0; | ||
281 | if (elems->supp_rates) { | ||
282 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
283 | if (clen > elems->supp_rates_len) | ||
284 | clen = elems->supp_rates_len; | ||
285 | memcpy(&bss->supp_rates[bss->supp_rates_len], elems->supp_rates, | ||
286 | clen); | ||
287 | bss->supp_rates_len += clen; | ||
288 | } | ||
289 | if (elems->ext_supp_rates) { | ||
290 | clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len; | ||
291 | if (clen > elems->ext_supp_rates_len) | ||
292 | clen = elems->ext_supp_rates_len; | ||
293 | memcpy(&bss->supp_rates[bss->supp_rates_len], | ||
294 | elems->ext_supp_rates, clen); | ||
295 | bss->supp_rates_len += clen; | ||
296 | } | ||
297 | |||
298 | bss->band = rx_status->band; | ||
299 | |||
300 | bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp); | ||
301 | bss->last_update = jiffies; | ||
302 | bss->signal = rx_status->signal; | ||
303 | bss->noise = rx_status->noise; | ||
304 | bss->qual = rx_status->qual; | ||
305 | bss->wmm_used = elems->wmm_param || elems->wmm_info; | ||
306 | |||
307 | if (!beacon) | ||
308 | bss->last_probe_resp = jiffies; | ||
309 | |||
310 | /* | ||
311 | * For probe responses, or if we don't have any information yet, | ||
312 | * use the IEs from the beacon. | ||
313 | */ | ||
314 | if (!bss->ies || !beacon) { | ||
315 | if (bss->ies == NULL || bss->ies_len < elems->total_len) { | ||
316 | kfree(bss->ies); | ||
317 | bss->ies = kmalloc(elems->total_len, GFP_ATOMIC); | ||
318 | } | ||
319 | if (bss->ies) { | ||
320 | memcpy(bss->ies, elems->ie_start, elems->total_len); | ||
321 | bss->ies_len = elems->total_len; | ||
322 | } else | ||
323 | bss->ies_len = 0; | ||
324 | } | ||
325 | |||
326 | return bss; | ||
327 | } | ||
328 | |||
329 | ieee80211_rx_result | ||
330 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
331 | struct ieee80211_rx_status *rx_status) | ||
332 | { | ||
333 | struct ieee80211_mgmt *mgmt; | ||
334 | struct ieee80211_bss *bss; | ||
335 | u8 *elements; | ||
336 | struct ieee80211_channel *channel; | ||
337 | size_t baselen; | ||
338 | int freq; | ||
339 | __le16 fc; | ||
340 | bool presp, beacon = false; | ||
341 | struct ieee802_11_elems elems; | ||
342 | |||
343 | if (skb->len < 2) | ||
344 | return RX_DROP_UNUSABLE; | ||
345 | |||
346 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
347 | fc = mgmt->frame_control; | ||
348 | |||
349 | if (ieee80211_is_ctl(fc)) | ||
350 | return RX_CONTINUE; | ||
351 | |||
352 | if (skb->len < 24) | ||
353 | return RX_DROP_MONITOR; | ||
354 | |||
355 | presp = ieee80211_is_probe_resp(fc); | ||
356 | if (presp) { | ||
357 | /* ignore ProbeResp to foreign address */ | ||
358 | if (memcmp(mgmt->da, sdata->dev->dev_addr, ETH_ALEN)) | ||
359 | return RX_DROP_MONITOR; | ||
360 | |||
361 | presp = true; | ||
362 | elements = mgmt->u.probe_resp.variable; | ||
363 | baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); | ||
364 | } else { | ||
365 | beacon = ieee80211_is_beacon(fc); | ||
366 | baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable); | ||
367 | elements = mgmt->u.beacon.variable; | ||
368 | } | ||
369 | |||
370 | if (!presp && !beacon) | ||
371 | return RX_CONTINUE; | ||
372 | |||
373 | if (baselen > skb->len) | ||
374 | return RX_DROP_MONITOR; | ||
375 | |||
376 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | ||
377 | |||
378 | if (elems.ds_params && elems.ds_params_len == 1) | ||
379 | freq = ieee80211_channel_to_frequency(elems.ds_params[0]); | ||
380 | else | ||
381 | freq = rx_status->freq; | ||
382 | |||
383 | channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq); | ||
384 | |||
385 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
386 | return RX_DROP_MONITOR; | ||
387 | |||
388 | bss = ieee80211_bss_info_update(sdata->local, rx_status, | ||
389 | mgmt, skb->len, &elems, | ||
390 | freq, beacon); | ||
391 | ieee80211_rx_bss_put(sdata->local, bss); | ||
392 | |||
393 | dev_kfree_skb(skb); | ||
394 | return RX_QUEUED; | ||
395 | } | ||
396 | |||
397 | static void ieee80211_send_nullfunc(struct ieee80211_local *local, | ||
398 | struct ieee80211_sub_if_data *sdata, | ||
399 | int powersave) | ||
400 | { | ||
401 | struct sk_buff *skb; | ||
402 | struct ieee80211_hdr *nullfunc; | ||
403 | __le16 fc; | ||
404 | |||
405 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | ||
406 | if (!skb) { | ||
407 | printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " | ||
408 | "frame\n", sdata->dev->name); | ||
409 | return; | ||
410 | } | ||
411 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
412 | |||
413 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | ||
414 | memset(nullfunc, 0, 24); | ||
415 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | ||
416 | IEEE80211_FCTL_TODS); | ||
417 | if (powersave) | ||
418 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); | ||
419 | nullfunc->frame_control = fc; | ||
420 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | ||
421 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | ||
422 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | ||
423 | |||
424 | ieee80211_tx_skb(sdata, skb, 0); | ||
425 | } | ||
426 | |||
427 | void ieee80211_scan_completed(struct ieee80211_hw *hw) | ||
428 | { | ||
429 | struct ieee80211_local *local = hw_to_local(hw); | ||
430 | struct ieee80211_sub_if_data *sdata; | ||
431 | union iwreq_data wrqu; | ||
432 | |||
433 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) | ||
434 | return; | ||
435 | |||
436 | local->last_scan_completed = jiffies; | ||
437 | memset(&wrqu, 0, sizeof(wrqu)); | ||
438 | |||
439 | /* | ||
440 | * local->scan_sdata could have been NULLed by the interface | ||
441 | * down code in case we were scanning on an interface that is | ||
442 | * being taken down. | ||
443 | */ | ||
444 | sdata = local->scan_sdata; | ||
445 | if (sdata) | ||
446 | wireless_send_event(sdata->dev, SIOCGIWSCAN, &wrqu, NULL); | ||
447 | |||
448 | if (local->hw_scanning) { | ||
449 | local->hw_scanning = false; | ||
450 | if (ieee80211_hw_config(local)) | ||
451 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
452 | "channel after scan\n", wiphy_name(local->hw.wiphy)); | ||
453 | |||
454 | goto done; | ||
455 | } | ||
456 | |||
457 | local->sw_scanning = false; | ||
458 | if (ieee80211_hw_config(local)) | ||
459 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
460 | "channel after scan\n", wiphy_name(local->hw.wiphy)); | ||
461 | |||
462 | |||
463 | netif_tx_lock_bh(local->mdev); | ||
464 | netif_addr_lock(local->mdev); | ||
465 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | ||
466 | local->ops->configure_filter(local_to_hw(local), | ||
467 | FIF_BCN_PRBRESP_PROMISC, | ||
468 | &local->filter_flags, | ||
469 | local->mdev->mc_count, | ||
470 | local->mdev->mc_list); | ||
471 | |||
472 | netif_addr_unlock(local->mdev); | ||
473 | netif_tx_unlock_bh(local->mdev); | ||
474 | |||
475 | rcu_read_lock(); | ||
476 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
477 | /* Tell AP we're back */ | ||
478 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
479 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | ||
480 | ieee80211_send_nullfunc(local, sdata, 0); | ||
481 | netif_tx_wake_all_queues(sdata->dev); | ||
482 | } | ||
483 | } else | ||
484 | netif_tx_wake_all_queues(sdata->dev); | ||
485 | } | ||
486 | rcu_read_unlock(); | ||
487 | |||
488 | done: | ||
489 | ieee80211_mlme_notify_scan_completed(local); | ||
490 | ieee80211_mesh_notify_scan_completed(local); | ||
491 | } | ||
492 | EXPORT_SYMBOL(ieee80211_scan_completed); | ||
493 | |||
494 | |||
495 | void ieee80211_scan_work(struct work_struct *work) | ||
496 | { | ||
497 | struct ieee80211_local *local = | ||
498 | container_of(work, struct ieee80211_local, scan_work.work); | ||
499 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
500 | struct ieee80211_supported_band *sband; | ||
501 | struct ieee80211_channel *chan; | ||
502 | int skip; | ||
503 | unsigned long next_delay = 0; | ||
504 | |||
505 | /* | ||
506 | * Avoid re-scheduling when the sdata is going away. | ||
507 | */ | ||
508 | if (!netif_running(sdata->dev)) | ||
509 | return; | ||
510 | |||
511 | switch (local->scan_state) { | ||
512 | case SCAN_SET_CHANNEL: | ||
513 | /* | ||
514 | * Get current scan band. scan_band may be IEEE80211_NUM_BANDS | ||
515 | * after we successfully scanned the last channel of the last | ||
516 | * band (and the last band is supported by the hw) | ||
517 | */ | ||
518 | if (local->scan_band < IEEE80211_NUM_BANDS) | ||
519 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
520 | else | ||
521 | sband = NULL; | ||
522 | |||
523 | /* | ||
524 | * If we are at an unsupported band and have more bands | ||
525 | * left to scan, advance to the next supported one. | ||
526 | */ | ||
527 | while (!sband && local->scan_band < IEEE80211_NUM_BANDS - 1) { | ||
528 | local->scan_band++; | ||
529 | sband = local->hw.wiphy->bands[local->scan_band]; | ||
530 | local->scan_channel_idx = 0; | ||
531 | } | ||
532 | |||
533 | /* if no more bands/channels left, complete scan */ | ||
534 | if (!sband || local->scan_channel_idx >= sband->n_channels) { | ||
535 | ieee80211_scan_completed(local_to_hw(local)); | ||
536 | return; | ||
537 | } | ||
538 | skip = 0; | ||
539 | chan = &sband->channels[local->scan_channel_idx]; | ||
540 | |||
541 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
542 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
543 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
544 | skip = 1; | ||
545 | |||
546 | if (!skip) { | ||
547 | local->scan_channel = chan; | ||
548 | if (ieee80211_hw_config(local)) { | ||
549 | printk(KERN_DEBUG "%s: failed to set freq to " | ||
550 | "%d MHz for scan\n", wiphy_name(local->hw.wiphy), | ||
551 | chan->center_freq); | ||
552 | skip = 1; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* advance state machine to next channel/band */ | ||
557 | local->scan_channel_idx++; | ||
558 | if (local->scan_channel_idx >= sband->n_channels) { | ||
559 | /* | ||
560 | * scan_band may end up == IEEE80211_NUM_BANDS, but | ||
561 | * we'll catch that case above and complete the scan | ||
562 | * if that is the case. | ||
563 | */ | ||
564 | local->scan_band++; | ||
565 | local->scan_channel_idx = 0; | ||
566 | } | ||
567 | |||
568 | if (skip) | ||
569 | break; | ||
570 | |||
571 | next_delay = IEEE80211_PROBE_DELAY + | ||
572 | usecs_to_jiffies(local->hw.channel_change_time); | ||
573 | local->scan_state = SCAN_SEND_PROBE; | ||
574 | break; | ||
575 | case SCAN_SEND_PROBE: | ||
576 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
577 | local->scan_state = SCAN_SET_CHANNEL; | ||
578 | |||
579 | if (local->scan_channel->flags & IEEE80211_CHAN_PASSIVE_SCAN) | ||
580 | break; | ||
581 | ieee80211_send_probe_req(sdata, NULL, local->scan_ssid, | ||
582 | local->scan_ssid_len); | ||
583 | next_delay = IEEE80211_CHANNEL_TIME; | ||
584 | break; | ||
585 | } | ||
586 | |||
587 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
588 | next_delay); | ||
589 | } | ||
590 | |||
591 | |||
592 | int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | ||
593 | u8 *ssid, size_t ssid_len) | ||
594 | { | ||
595 | struct ieee80211_local *local = scan_sdata->local; | ||
596 | struct ieee80211_sub_if_data *sdata; | ||
597 | |||
598 | if (ssid_len > IEEE80211_MAX_SSID_LEN) | ||
599 | return -EINVAL; | ||
600 | |||
601 | /* MLME-SCAN.request (page 118) page 144 (11.1.3.1) | ||
602 | * BSSType: INFRASTRUCTURE, INDEPENDENT, ANY_BSS | ||
603 | * BSSID: MACAddress | ||
604 | * SSID | ||
605 | * ScanType: ACTIVE, PASSIVE | ||
606 | * ProbeDelay: delay (in microseconds) to be used prior to transmitting | ||
607 | * a Probe frame during active scanning | ||
608 | * ChannelList | ||
609 | * MinChannelTime (>= ProbeDelay), in TU | ||
610 | * MaxChannelTime: (>= MinChannelTime), in TU | ||
611 | */ | ||
612 | |||
613 | /* MLME-SCAN.confirm | ||
614 | * BSSDescriptionSet | ||
615 | * ResultCode: SUCCESS, INVALID_PARAMETERS | ||
616 | */ | ||
617 | |||
618 | if (local->sw_scanning || local->hw_scanning) { | ||
619 | if (local->scan_sdata == scan_sdata) | ||
620 | return 0; | ||
621 | return -EBUSY; | ||
622 | } | ||
623 | |||
624 | if (local->ops->hw_scan) { | ||
625 | int rc; | ||
626 | |||
627 | local->hw_scanning = true; | ||
628 | rc = local->ops->hw_scan(local_to_hw(local), ssid, ssid_len); | ||
629 | if (rc) { | ||
630 | local->hw_scanning = false; | ||
631 | return rc; | ||
632 | } | ||
633 | local->scan_sdata = scan_sdata; | ||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | local->sw_scanning = true; | ||
638 | |||
639 | rcu_read_lock(); | ||
640 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
641 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
642 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | ||
643 | netif_tx_stop_all_queues(sdata->dev); | ||
644 | ieee80211_send_nullfunc(local, sdata, 1); | ||
645 | } | ||
646 | } else | ||
647 | netif_tx_stop_all_queues(sdata->dev); | ||
648 | } | ||
649 | rcu_read_unlock(); | ||
650 | |||
651 | if (ssid) { | ||
652 | local->scan_ssid_len = ssid_len; | ||
653 | memcpy(local->scan_ssid, ssid, ssid_len); | ||
654 | } else | ||
655 | local->scan_ssid_len = 0; | ||
656 | local->scan_state = SCAN_SET_CHANNEL; | ||
657 | local->scan_channel_idx = 0; | ||
658 | local->scan_band = IEEE80211_BAND_2GHZ; | ||
659 | local->scan_sdata = scan_sdata; | ||
660 | |||
661 | netif_addr_lock_bh(local->mdev); | ||
662 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
663 | local->ops->configure_filter(local_to_hw(local), | ||
664 | FIF_BCN_PRBRESP_PROMISC, | ||
665 | &local->filter_flags, | ||
666 | local->mdev->mc_count, | ||
667 | local->mdev->mc_list); | ||
668 | netif_addr_unlock_bh(local->mdev); | ||
669 | |||
670 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
671 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
672 | IEEE80211_CHANNEL_TIME); | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | |||
678 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | ||
679 | u8 *ssid, size_t ssid_len) | ||
680 | { | ||
681 | struct ieee80211_local *local = sdata->local; | ||
682 | struct ieee80211_if_sta *ifsta; | ||
683 | |||
684 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
685 | return ieee80211_start_scan(sdata, ssid, ssid_len); | ||
686 | |||
687 | /* | ||
688 | * STA has a state machine that might need to defer scanning | ||
689 | * while it's trying to associate/authenticate, therefore we | ||
690 | * queue it up to the state machine in that case. | ||
691 | */ | ||
692 | |||
693 | if (local->sw_scanning || local->hw_scanning) { | ||
694 | if (local->scan_sdata == sdata) | ||
695 | return 0; | ||
696 | return -EBUSY; | ||
697 | } | ||
698 | |||
699 | ifsta = &sdata->u.sta; | ||
700 | |||
701 | ifsta->scan_ssid_len = ssid_len; | ||
702 | if (ssid_len) | ||
703 | memcpy(ifsta->scan_ssid, ssid, ssid_len); | ||
704 | set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request); | ||
705 | queue_work(local->hw.workqueue, &ifsta->work); | ||
706 | |||
707 | return 0; | ||
708 | } | ||
709 | |||
710 | |||
711 | static void ieee80211_scan_add_ies(struct iw_request_info *info, | ||
712 | struct ieee80211_bss *bss, | ||
713 | char **current_ev, char *end_buf) | ||
714 | { | ||
715 | u8 *pos, *end, *next; | ||
716 | struct iw_event iwe; | ||
717 | |||
718 | if (bss == NULL || bss->ies == NULL) | ||
719 | return; | ||
720 | |||
721 | /* | ||
722 | * If needed, fragment the IEs buffer (at IE boundaries) into short | ||
723 | * enough fragments to fit into IW_GENERIC_IE_MAX octet messages. | ||
724 | */ | ||
725 | pos = bss->ies; | ||
726 | end = pos + bss->ies_len; | ||
727 | |||
728 | while (end - pos > IW_GENERIC_IE_MAX) { | ||
729 | next = pos + 2 + pos[1]; | ||
730 | while (next + 2 + next[1] - pos < IW_GENERIC_IE_MAX) | ||
731 | next = next + 2 + next[1]; | ||
732 | |||
733 | memset(&iwe, 0, sizeof(iwe)); | ||
734 | iwe.cmd = IWEVGENIE; | ||
735 | iwe.u.data.length = next - pos; | ||
736 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
737 | end_buf, &iwe, pos); | ||
738 | |||
739 | pos = next; | ||
740 | } | ||
741 | |||
742 | if (end > pos) { | ||
743 | memset(&iwe, 0, sizeof(iwe)); | ||
744 | iwe.cmd = IWEVGENIE; | ||
745 | iwe.u.data.length = end - pos; | ||
746 | *current_ev = iwe_stream_add_point(info, *current_ev, | ||
747 | end_buf, &iwe, pos); | ||
748 | } | ||
749 | } | ||
750 | |||
751 | |||
752 | static char * | ||
753 | ieee80211_scan_result(struct ieee80211_local *local, | ||
754 | struct iw_request_info *info, | ||
755 | struct ieee80211_bss *bss, | ||
756 | char *current_ev, char *end_buf) | ||
757 | { | ||
758 | struct iw_event iwe; | ||
759 | char *buf; | ||
760 | |||
761 | if (time_after(jiffies, | ||
762 | bss->last_update + IEEE80211_SCAN_RESULT_EXPIRE)) | ||
763 | return current_ev; | ||
764 | |||
765 | memset(&iwe, 0, sizeof(iwe)); | ||
766 | iwe.cmd = SIOCGIWAP; | ||
767 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | ||
768 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | ||
769 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
770 | IW_EV_ADDR_LEN); | ||
771 | |||
772 | memset(&iwe, 0, sizeof(iwe)); | ||
773 | iwe.cmd = SIOCGIWESSID; | ||
774 | if (bss_mesh_cfg(bss)) { | ||
775 | iwe.u.data.length = bss_mesh_id_len(bss); | ||
776 | iwe.u.data.flags = 1; | ||
777 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
778 | &iwe, bss_mesh_id(bss)); | ||
779 | } else { | ||
780 | iwe.u.data.length = bss->ssid_len; | ||
781 | iwe.u.data.flags = 1; | ||
782 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
783 | &iwe, bss->ssid); | ||
784 | } | ||
785 | |||
786 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | ||
787 | || bss_mesh_cfg(bss)) { | ||
788 | memset(&iwe, 0, sizeof(iwe)); | ||
789 | iwe.cmd = SIOCGIWMODE; | ||
790 | if (bss_mesh_cfg(bss)) | ||
791 | iwe.u.mode = IW_MODE_MESH; | ||
792 | else if (bss->capability & WLAN_CAPABILITY_ESS) | ||
793 | iwe.u.mode = IW_MODE_MASTER; | ||
794 | else | ||
795 | iwe.u.mode = IW_MODE_ADHOC; | ||
796 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, | ||
797 | &iwe, IW_EV_UINT_LEN); | ||
798 | } | ||
799 | |||
800 | memset(&iwe, 0, sizeof(iwe)); | ||
801 | iwe.cmd = SIOCGIWFREQ; | ||
802 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | ||
803 | iwe.u.freq.e = 0; | ||
804 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
805 | IW_EV_FREQ_LEN); | ||
806 | |||
807 | memset(&iwe, 0, sizeof(iwe)); | ||
808 | iwe.cmd = SIOCGIWFREQ; | ||
809 | iwe.u.freq.m = bss->freq; | ||
810 | iwe.u.freq.e = 6; | ||
811 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
812 | IW_EV_FREQ_LEN); | ||
813 | memset(&iwe, 0, sizeof(iwe)); | ||
814 | iwe.cmd = IWEVQUAL; | ||
815 | iwe.u.qual.qual = bss->qual; | ||
816 | iwe.u.qual.level = bss->signal; | ||
817 | iwe.u.qual.noise = bss->noise; | ||
818 | iwe.u.qual.updated = local->wstats_flags; | ||
819 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, | ||
820 | IW_EV_QUAL_LEN); | ||
821 | |||
822 | memset(&iwe, 0, sizeof(iwe)); | ||
823 | iwe.cmd = SIOCGIWENCODE; | ||
824 | if (bss->capability & WLAN_CAPABILITY_PRIVACY) | ||
825 | iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; | ||
826 | else | ||
827 | iwe.u.data.flags = IW_ENCODE_DISABLED; | ||
828 | iwe.u.data.length = 0; | ||
829 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
830 | &iwe, ""); | ||
831 | |||
832 | ieee80211_scan_add_ies(info, bss, ¤t_ev, end_buf); | ||
833 | |||
834 | if (bss->supp_rates_len > 0) { | ||
835 | /* display all supported rates in readable format */ | ||
836 | char *p = current_ev + iwe_stream_lcp_len(info); | ||
837 | int i; | ||
838 | |||
839 | memset(&iwe, 0, sizeof(iwe)); | ||
840 | iwe.cmd = SIOCGIWRATE; | ||
841 | /* Those two flags are ignored... */ | ||
842 | iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; | ||
843 | |||
844 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
845 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | ||
846 | 0x7f) * 500000); | ||
847 | p = iwe_stream_add_value(info, current_ev, p, | ||
848 | end_buf, &iwe, IW_EV_PARAM_LEN); | ||
849 | } | ||
850 | current_ev = p; | ||
851 | } | ||
852 | |||
853 | buf = kmalloc(30, GFP_ATOMIC); | ||
854 | if (buf) { | ||
855 | memset(&iwe, 0, sizeof(iwe)); | ||
856 | iwe.cmd = IWEVCUSTOM; | ||
857 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | ||
858 | iwe.u.data.length = strlen(buf); | ||
859 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, | ||
860 | &iwe, buf); | ||
861 | memset(&iwe, 0, sizeof(iwe)); | ||
862 | iwe.cmd = IWEVCUSTOM; | ||
863 | sprintf(buf, " Last beacon: %dms ago", | ||
864 | jiffies_to_msecs(jiffies - bss->last_update)); | ||
865 | iwe.u.data.length = strlen(buf); | ||
866 | current_ev = iwe_stream_add_point(info, current_ev, | ||
867 | end_buf, &iwe, buf); | ||
868 | kfree(buf); | ||
869 | } | ||
870 | |||
871 | if (bss_mesh_cfg(bss)) { | ||
872 | u8 *cfg = bss_mesh_cfg(bss); | ||
873 | buf = kmalloc(50, GFP_ATOMIC); | ||
874 | if (buf) { | ||
875 | memset(&iwe, 0, sizeof(iwe)); | ||
876 | iwe.cmd = IWEVCUSTOM; | ||
877 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | ||
878 | iwe.u.data.length = strlen(buf); | ||
879 | current_ev = iwe_stream_add_point(info, current_ev, | ||
880 | end_buf, | ||
881 | &iwe, buf); | ||
882 | sprintf(buf, "Path Selection Protocol ID: " | ||
883 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | ||
884 | cfg[4]); | ||
885 | iwe.u.data.length = strlen(buf); | ||
886 | current_ev = iwe_stream_add_point(info, current_ev, | ||
887 | end_buf, | ||
888 | &iwe, buf); | ||
889 | sprintf(buf, "Path Selection Metric ID: " | ||
890 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | ||
891 | cfg[8]); | ||
892 | iwe.u.data.length = strlen(buf); | ||
893 | current_ev = iwe_stream_add_point(info, current_ev, | ||
894 | end_buf, | ||
895 | &iwe, buf); | ||
896 | sprintf(buf, "Congestion Control Mode ID: " | ||
897 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
898 | cfg[11], cfg[12]); | ||
899 | iwe.u.data.length = strlen(buf); | ||
900 | current_ev = iwe_stream_add_point(info, current_ev, | ||
901 | end_buf, | ||
902 | &iwe, buf); | ||
903 | sprintf(buf, "Channel Precedence: " | ||
904 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | ||
905 | cfg[15], cfg[16]); | ||
906 | iwe.u.data.length = strlen(buf); | ||
907 | current_ev = iwe_stream_add_point(info, current_ev, | ||
908 | end_buf, | ||
909 | &iwe, buf); | ||
910 | kfree(buf); | ||
911 | } | ||
912 | } | ||
913 | |||
914 | return current_ev; | ||
915 | } | ||
916 | |||
917 | |||
918 | int ieee80211_scan_results(struct ieee80211_local *local, | ||
919 | struct iw_request_info *info, | ||
920 | char *buf, size_t len) | ||
921 | { | ||
922 | char *current_ev = buf; | ||
923 | char *end_buf = buf + len; | ||
924 | struct ieee80211_bss *bss; | ||
925 | |||
926 | spin_lock_bh(&local->bss_lock); | ||
927 | list_for_each_entry(bss, &local->bss_list, list) { | ||
928 | if (buf + len - current_ev <= IW_EV_ADDR_LEN) { | ||
929 | spin_unlock_bh(&local->bss_lock); | ||
930 | return -E2BIG; | ||
931 | } | ||
932 | current_ev = ieee80211_scan_result(local, info, bss, | ||
933 | current_ev, end_buf); | ||
934 | } | ||
935 | spin_unlock_bh(&local->bss_lock); | ||
936 | return current_ev - buf; | ||
937 | } | ||
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c new file mode 100644 index 000000000000..f72bad636d8e --- /dev/null +++ b/net/mac80211/spectmgmt.c | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * spectrum management | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
6 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2007-2008, Intel Corporation | ||
10 | * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | */ | ||
16 | |||
17 | #include <linux/ieee80211.h> | ||
18 | #include <net/wireless.h> | ||
19 | #include <net/mac80211.h> | ||
20 | #include "ieee80211_i.h" | ||
21 | #include "sta_info.h" | ||
22 | #include "wme.h" | ||
23 | |||
24 | static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, | ||
25 | struct ieee80211_msrment_ie *request_ie, | ||
26 | const u8 *da, const u8 *bssid, | ||
27 | u8 dialog_token) | ||
28 | { | ||
29 | struct ieee80211_local *local = sdata->local; | ||
30 | struct sk_buff *skb; | ||
31 | struct ieee80211_mgmt *msr_report; | ||
32 | |||
33 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | ||
34 | sizeof(struct ieee80211_msrment_ie)); | ||
35 | |||
36 | if (!skb) { | ||
37 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
38 | "measurement report frame\n", sdata->dev->name); | ||
39 | return; | ||
40 | } | ||
41 | |||
42 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
43 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
44 | memset(msr_report, 0, 24); | ||
45 | memcpy(msr_report->da, da, ETH_ALEN); | ||
46 | memcpy(msr_report->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
47 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
48 | msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
49 | IEEE80211_STYPE_ACTION); | ||
50 | |||
51 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
52 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
53 | msr_report->u.action.u.measurement.action_code = | ||
54 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
55 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
56 | |||
57 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
58 | msr_report->u.action.u.measurement.length = | ||
59 | sizeof(struct ieee80211_msrment_ie); | ||
60 | |||
61 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
62 | sizeof(struct ieee80211_msrment_ie)); | ||
63 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
64 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
67 | |||
68 | ieee80211_tx_skb(sdata, skb, 0); | ||
69 | } | ||
70 | |||
71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | ||
72 | struct ieee80211_mgmt *mgmt, | ||
73 | size_t len) | ||
74 | { | ||
75 | /* | ||
76 | * Ignoring measurement request is spec violation. | ||
77 | * Mandatory measurements must be reported optional | ||
78 | * measurements might be refused or reported incapable | ||
79 | * For now just refuse | ||
80 | * TODO: Answer basic measurement as unmeasured | ||
81 | */ | ||
82 | ieee80211_send_refuse_measurement_request(sdata, | ||
83 | &mgmt->u.action.u.measurement.msr_elem, | ||
84 | mgmt->sa, mgmt->bssid, | ||
85 | mgmt->u.action.u.measurement.dialog_token); | ||
86 | } | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2ba653b9d69..d9774ac2e0f7 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -73,11 +73,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
73 | { | 73 | { |
74 | struct sta_info *s; | 74 | struct sta_info *s; |
75 | 75 | ||
76 | s = local->sta_hash[STA_HASH(sta->addr)]; | 76 | s = local->sta_hash[STA_HASH(sta->sta.addr)]; |
77 | if (!s) | 77 | if (!s) |
78 | return -ENOENT; | 78 | return -ENOENT; |
79 | if (s == sta) { | 79 | if (s == sta) { |
80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], | 80 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], |
81 | s->hnext); | 81 | s->hnext); |
82 | return 0; | 82 | return 0; |
83 | } | 83 | } |
@@ -94,13 +94,13 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
94 | 94 | ||
95 | /* protected by RCU */ | 95 | /* protected by RCU */ |
96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, | 96 | static struct sta_info *__sta_info_find(struct ieee80211_local *local, |
97 | u8 *addr) | 97 | const u8 *addr) |
98 | { | 98 | { |
99 | struct sta_info *sta; | 99 | struct sta_info *sta; |
100 | 100 | ||
101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); | 101 | sta = rcu_dereference(local->sta_hash[STA_HASH(addr)]); |
102 | while (sta) { | 102 | while (sta) { |
103 | if (compare_ether_addr(sta->addr, addr) == 0) | 103 | if (compare_ether_addr(sta->sta.addr, addr) == 0) |
104 | break; | 104 | break; |
105 | sta = rcu_dereference(sta->hnext); | 105 | sta = rcu_dereference(sta->hnext); |
106 | } | 106 | } |
@@ -151,7 +151,7 @@ static void __sta_info_free(struct ieee80211_local *local, | |||
151 | 151 | ||
152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 152 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", | 153 | printk(KERN_DEBUG "%s: Destroyed STA %s\n", |
154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 154 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 155 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
156 | 156 | ||
157 | kfree(sta); | 157 | kfree(sta); |
@@ -219,8 +219,8 @@ void sta_info_destroy(struct sta_info *sta) | |||
219 | static void sta_info_hash_add(struct ieee80211_local *local, | 219 | static void sta_info_hash_add(struct ieee80211_local *local, |
220 | struct sta_info *sta) | 220 | struct sta_info *sta) |
221 | { | 221 | { |
222 | sta->hnext = local->sta_hash[STA_HASH(sta->addr)]; | 222 | sta->hnext = local->sta_hash[STA_HASH(sta->sta.addr)]; |
223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->addr)], sta); | 223 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
224 | } | 224 | } |
225 | 225 | ||
226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 226 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
@@ -231,14 +231,14 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
231 | int i; | 231 | int i; |
232 | DECLARE_MAC_BUF(mbuf); | 232 | DECLARE_MAC_BUF(mbuf); |
233 | 233 | ||
234 | sta = kzalloc(sizeof(*sta), gfp); | 234 | sta = kzalloc(sizeof(*sta) + local->hw.sta_data_size, gfp); |
235 | if (!sta) | 235 | if (!sta) |
236 | return NULL; | 236 | return NULL; |
237 | 237 | ||
238 | spin_lock_init(&sta->lock); | 238 | spin_lock_init(&sta->lock); |
239 | spin_lock_init(&sta->flaglock); | 239 | spin_lock_init(&sta->flaglock); |
240 | 240 | ||
241 | memcpy(sta->addr, addr, ETH_ALEN); | 241 | memcpy(sta->sta.addr, addr, ETH_ALEN); |
242 | sta->local = local; | 242 | sta->local = local; |
243 | sta->sdata = sdata; | 243 | sta->sdata = sdata; |
244 | 244 | ||
@@ -271,7 +271,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
271 | 271 | ||
272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 272 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", | 273 | printk(KERN_DEBUG "%s: Allocated STA %s\n", |
274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->addr)); | 274 | wiphy_name(local->hw.wiphy), print_mac(mbuf, sta->sta.addr)); |
275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 275 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
276 | 276 | ||
277 | #ifdef CONFIG_MAC80211_MESH | 277 | #ifdef CONFIG_MAC80211_MESH |
@@ -300,15 +300,15 @@ int sta_info_insert(struct sta_info *sta) | |||
300 | goto out_free; | 300 | goto out_free; |
301 | } | 301 | } |
302 | 302 | ||
303 | if (WARN_ON(compare_ether_addr(sta->addr, sdata->dev->dev_addr) == 0 || | 303 | if (WARN_ON(compare_ether_addr(sta->sta.addr, sdata->dev->dev_addr) == 0 || |
304 | is_multicast_ether_addr(sta->addr))) { | 304 | is_multicast_ether_addr(sta->sta.addr))) { |
305 | err = -EINVAL; | 305 | err = -EINVAL; |
306 | goto out_free; | 306 | goto out_free; |
307 | } | 307 | } |
308 | 308 | ||
309 | spin_lock_irqsave(&local->sta_lock, flags); | 309 | spin_lock_irqsave(&local->sta_lock, flags); |
310 | /* check if STA exists already */ | 310 | /* check if STA exists already */ |
311 | if (__sta_info_find(local, sta->addr)) { | 311 | if (__sta_info_find(local, sta->sta.addr)) { |
312 | spin_unlock_irqrestore(&local->sta_lock, flags); | 312 | spin_unlock_irqrestore(&local->sta_lock, flags); |
313 | err = -EEXIST; | 313 | err = -EEXIST; |
314 | goto out_free; | 314 | goto out_free; |
@@ -319,18 +319,18 @@ int sta_info_insert(struct sta_info *sta) | |||
319 | 319 | ||
320 | /* notify driver */ | 320 | /* notify driver */ |
321 | if (local->ops->sta_notify) { | 321 | if (local->ops->sta_notify) { |
322 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 322 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
323 | sdata = container_of(sdata->bss, | 323 | sdata = container_of(sdata->bss, |
324 | struct ieee80211_sub_if_data, | 324 | struct ieee80211_sub_if_data, |
325 | u.ap); | 325 | u.ap); |
326 | 326 | ||
327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 327 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
328 | STA_NOTIFY_ADD, sta->addr); | 328 | STA_NOTIFY_ADD, &sta->sta); |
329 | } | 329 | } |
330 | 330 | ||
331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 331 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", | 332 | printk(KERN_DEBUG "%s: Inserted STA %s\n", |
333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->addr)); | 333 | wiphy_name(local->hw.wiphy), print_mac(mac, sta->sta.addr)); |
334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 334 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
335 | 335 | ||
336 | spin_unlock_irqrestore(&local->sta_lock, flags); | 336 | spin_unlock_irqrestore(&local->sta_lock, flags); |
@@ -379,11 +379,12 @@ static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss, | |||
379 | { | 379 | { |
380 | BUG_ON(!bss); | 380 | BUG_ON(!bss); |
381 | 381 | ||
382 | __bss_tim_set(bss, sta->aid); | 382 | __bss_tim_set(bss, sta->sta.aid); |
383 | 383 | ||
384 | if (sta->local->ops->set_tim) { | 384 | if (sta->local->ops->set_tim) { |
385 | sta->local->tim_in_locked_section = true; | 385 | sta->local->tim_in_locked_section = true; |
386 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1); | 386 | sta->local->ops->set_tim(local_to_hw(sta->local), |
387 | &sta->sta, true); | ||
387 | sta->local->tim_in_locked_section = false; | 388 | sta->local->tim_in_locked_section = false; |
388 | } | 389 | } |
389 | } | 390 | } |
@@ -404,11 +405,12 @@ static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss, | |||
404 | { | 405 | { |
405 | BUG_ON(!bss); | 406 | BUG_ON(!bss); |
406 | 407 | ||
407 | __bss_tim_clear(bss, sta->aid); | 408 | __bss_tim_clear(bss, sta->sta.aid); |
408 | 409 | ||
409 | if (sta->local->ops->set_tim) { | 410 | if (sta->local->ops->set_tim) { |
410 | sta->local->tim_in_locked_section = true; | 411 | sta->local->tim_in_locked_section = true; |
411 | sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0); | 412 | sta->local->ops->set_tim(local_to_hw(sta->local), |
413 | &sta->sta, false); | ||
412 | sta->local->tim_in_locked_section = false; | 414 | sta->local->tim_in_locked_section = false; |
413 | } | 415 | } |
414 | } | 416 | } |
@@ -424,7 +426,7 @@ void sta_info_clear_tim_bit(struct sta_info *sta) | |||
424 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); | 426 | spin_unlock_irqrestore(&sta->local->sta_lock, flags); |
425 | } | 427 | } |
426 | 428 | ||
427 | void __sta_info_unlink(struct sta_info **sta) | 429 | static void __sta_info_unlink(struct sta_info **sta) |
428 | { | 430 | { |
429 | struct ieee80211_local *local = (*sta)->local; | 431 | struct ieee80211_local *local = (*sta)->local; |
430 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; | 432 | struct ieee80211_sub_if_data *sdata = (*sta)->sdata; |
@@ -456,13 +458,13 @@ void __sta_info_unlink(struct sta_info **sta) | |||
456 | local->num_sta--; | 458 | local->num_sta--; |
457 | 459 | ||
458 | if (local->ops->sta_notify) { | 460 | if (local->ops->sta_notify) { |
459 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 461 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
460 | sdata = container_of(sdata->bss, | 462 | sdata = container_of(sdata->bss, |
461 | struct ieee80211_sub_if_data, | 463 | struct ieee80211_sub_if_data, |
462 | u.ap); | 464 | u.ap); |
463 | 465 | ||
464 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, | 466 | local->ops->sta_notify(local_to_hw(local), &sdata->vif, |
465 | STA_NOTIFY_REMOVE, (*sta)->addr); | 467 | STA_NOTIFY_REMOVE, &(*sta)->sta); |
466 | } | 468 | } |
467 | 469 | ||
468 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 470 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
@@ -474,7 +476,7 @@ void __sta_info_unlink(struct sta_info **sta) | |||
474 | 476 | ||
475 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 477 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
476 | printk(KERN_DEBUG "%s: Removed STA %s\n", | 478 | printk(KERN_DEBUG "%s: Removed STA %s\n", |
477 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->addr)); | 479 | wiphy_name(local->hw.wiphy), print_mac(mbuf, (*sta)->sta.addr)); |
478 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 480 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
479 | 481 | ||
480 | /* | 482 | /* |
@@ -570,7 +572,7 @@ static void sta_info_cleanup_expire_buffered(struct ieee80211_local *local, | |||
570 | local->total_ps_buffered--; | 572 | local->total_ps_buffered--; |
571 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 573 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
572 | printk(KERN_DEBUG "Buffered frame expired (STA " | 574 | printk(KERN_DEBUG "Buffered frame expired (STA " |
573 | "%s)\n", print_mac(mac, sta->addr)); | 575 | "%s)\n", print_mac(mac, sta->sta.addr)); |
574 | #endif | 576 | #endif |
575 | dev_kfree_skb(skb); | 577 | dev_kfree_skb(skb); |
576 | 578 | ||
@@ -802,3 +804,40 @@ void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata) | |||
802 | schedule_work(&local->sta_flush_work); | 804 | schedule_work(&local->sta_flush_work); |
803 | spin_unlock_irqrestore(&local->sta_lock, flags); | 805 | spin_unlock_irqrestore(&local->sta_lock, flags); |
804 | } | 806 | } |
807 | |||
808 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
809 | unsigned long exp_time) | ||
810 | { | ||
811 | struct ieee80211_local *local = sdata->local; | ||
812 | struct sta_info *sta, *tmp; | ||
813 | LIST_HEAD(tmp_list); | ||
814 | DECLARE_MAC_BUF(mac); | ||
815 | unsigned long flags; | ||
816 | |||
817 | spin_lock_irqsave(&local->sta_lock, flags); | ||
818 | list_for_each_entry_safe(sta, tmp, &local->sta_list, list) | ||
819 | if (time_after(jiffies, sta->last_rx + exp_time)) { | ||
820 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
821 | printk(KERN_DEBUG "%s: expiring inactive STA %s\n", | ||
822 | sdata->dev->name, print_mac(mac, sta->sta.addr)); | ||
823 | #endif | ||
824 | __sta_info_unlink(&sta); | ||
825 | if (sta) | ||
826 | list_add(&sta->list, &tmp_list); | ||
827 | } | ||
828 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
829 | |||
830 | list_for_each_entry_safe(sta, tmp, &tmp_list, list) | ||
831 | sta_info_destroy(sta); | ||
832 | } | ||
833 | |||
834 | struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw, | ||
835 | const u8 *addr) | ||
836 | { | ||
837 | struct sta_info *sta = __sta_info_find(hw_to_local(hw), addr); | ||
838 | |||
839 | if (!sta) | ||
840 | return NULL; | ||
841 | return &sta->sta; | ||
842 | } | ||
843 | EXPORT_SYMBOL(ieee80211_find_sta); | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 109db787ccb7..daedfa9e1c63 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -167,8 +167,6 @@ struct sta_ampdu_mlme { | |||
167 | * @lock: used for locking all fields that require locking, see comments | 167 | * @lock: used for locking all fields that require locking, see comments |
168 | * in the header file. | 168 | * in the header file. |
169 | * @flaglock: spinlock for flags accesses | 169 | * @flaglock: spinlock for flags accesses |
170 | * @ht_info: HT capabilities of this STA | ||
171 | * @supp_rates: Bitmap of supported rates (per band) | ||
172 | * @addr: MAC address of this STA | 170 | * @addr: MAC address of this STA |
173 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), | 171 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), |
174 | * only used in AP (and IBSS?) mode | 172 | * only used in AP (and IBSS?) mode |
@@ -195,15 +193,12 @@ struct sta_ampdu_mlme { | |||
195 | * @tx_filtered_count: TBD | 193 | * @tx_filtered_count: TBD |
196 | * @tx_retry_failed: TBD | 194 | * @tx_retry_failed: TBD |
197 | * @tx_retry_count: TBD | 195 | * @tx_retry_count: TBD |
198 | * @tx_num_consecutive_failures: TBD | ||
199 | * @tx_num_mpdu_ok: TBD | ||
200 | * @tx_num_mpdu_fail: TBD | ||
201 | * @fail_avg: moving percentage of failed MSDUs | 196 | * @fail_avg: moving percentage of failed MSDUs |
202 | * @tx_packets: number of RX/TX MSDUs | 197 | * @tx_packets: number of RX/TX MSDUs |
203 | * @tx_bytes: TBD | 198 | * @tx_bytes: TBD |
204 | * @tx_fragments: number of transmitted MPDUs | 199 | * @tx_fragments: number of transmitted MPDUs |
205 | * @txrate_idx: TBD | 200 | * @last_txrate_idx: Index of the last used transmit rate |
206 | * @last_txrate_idx: TBD | 201 | * @tid_seq: TBD |
207 | * @wme_tx_queue: TBD | 202 | * @wme_tx_queue: TBD |
208 | * @ampdu_mlme: TBD | 203 | * @ampdu_mlme: TBD |
209 | * @timer_to_tid: identity mapping to ID timers | 204 | * @timer_to_tid: identity mapping to ID timers |
@@ -217,6 +212,7 @@ struct sta_ampdu_mlme { | |||
217 | * @plink_timeout: TBD | 212 | * @plink_timeout: TBD |
218 | * @plink_timer: TBD | 213 | * @plink_timer: TBD |
219 | * @debugfs: debug filesystem info | 214 | * @debugfs: debug filesystem info |
215 | * @sta: station information we share with the driver | ||
220 | */ | 216 | */ |
221 | struct sta_info { | 217 | struct sta_info { |
222 | /* General information, mostly static */ | 218 | /* General information, mostly static */ |
@@ -229,10 +225,7 @@ struct sta_info { | |||
229 | void *rate_ctrl_priv; | 225 | void *rate_ctrl_priv; |
230 | spinlock_t lock; | 226 | spinlock_t lock; |
231 | spinlock_t flaglock; | 227 | spinlock_t flaglock; |
232 | struct ieee80211_ht_info ht_info; | 228 | |
233 | u64 supp_rates[IEEE80211_NUM_BANDS]; | ||
234 | u8 addr[ETH_ALEN]; | ||
235 | u16 aid; | ||
236 | u16 listen_interval; | 229 | u16 listen_interval; |
237 | 230 | ||
238 | /* | 231 | /* |
@@ -272,10 +265,6 @@ struct sta_info { | |||
272 | /* Updated from TX status path only, no locking requirements */ | 265 | /* Updated from TX status path only, no locking requirements */ |
273 | unsigned long tx_filtered_count; | 266 | unsigned long tx_filtered_count; |
274 | unsigned long tx_retry_failed, tx_retry_count; | 267 | unsigned long tx_retry_failed, tx_retry_count; |
275 | /* TODO: update in generic code not rate control? */ | ||
276 | u32 tx_num_consecutive_failures; | ||
277 | u32 tx_num_mpdu_ok; | ||
278 | u32 tx_num_mpdu_fail; | ||
279 | /* moving percentage of failed MSDUs */ | 268 | /* moving percentage of failed MSDUs */ |
280 | unsigned int fail_avg; | 269 | unsigned int fail_avg; |
281 | 270 | ||
@@ -283,8 +272,7 @@ struct sta_info { | |||
283 | unsigned long tx_packets; | 272 | unsigned long tx_packets; |
284 | unsigned long tx_bytes; | 273 | unsigned long tx_bytes; |
285 | unsigned long tx_fragments; | 274 | unsigned long tx_fragments; |
286 | int txrate_idx; | 275 | unsigned int last_txrate_idx; |
287 | int last_txrate_idx; | ||
288 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 276 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
289 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS | 277 | #ifdef CONFIG_MAC80211_DEBUG_COUNTERS |
290 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; | 278 | unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES]; |
@@ -326,6 +314,9 @@ struct sta_info { | |||
326 | struct dentry *agg_status; | 314 | struct dentry *agg_status; |
327 | } debugfs; | 315 | } debugfs; |
328 | #endif | 316 | #endif |
317 | |||
318 | /* keep last! */ | ||
319 | struct ieee80211_sta sta; | ||
329 | }; | 320 | }; |
330 | 321 | ||
331 | static inline enum plink_state sta_plink_state(struct sta_info *sta) | 322 | static inline enum plink_state sta_plink_state(struct sta_info *sta) |
@@ -451,7 +442,6 @@ int sta_info_insert(struct sta_info *sta); | |||
451 | * has already unlinked it. | 442 | * has already unlinked it. |
452 | */ | 443 | */ |
453 | void sta_info_unlink(struct sta_info **sta); | 444 | void sta_info_unlink(struct sta_info **sta); |
454 | void __sta_info_unlink(struct sta_info **sta); | ||
455 | 445 | ||
456 | void sta_info_destroy(struct sta_info *sta); | 446 | void sta_info_destroy(struct sta_info *sta); |
457 | void sta_info_set_tim_bit(struct sta_info *sta); | 447 | void sta_info_set_tim_bit(struct sta_info *sta); |
@@ -463,5 +453,7 @@ void sta_info_stop(struct ieee80211_local *local); | |||
463 | int sta_info_flush(struct ieee80211_local *local, | 453 | int sta_info_flush(struct ieee80211_local *local, |
464 | struct ieee80211_sub_if_data *sdata); | 454 | struct ieee80211_sub_if_data *sdata); |
465 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); | 455 | void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata); |
456 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | ||
457 | unsigned long exp_time); | ||
466 | 458 | ||
467 | #endif /* STA_INFO_H */ | 459 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 995f7af3d25e..34b32bc8f609 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -304,7 +304,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 304 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
305 | u8 bcast[ETH_ALEN] = | 305 | u8 bcast[ETH_ALEN] = |
306 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 306 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
307 | u8 *sta_addr = key->sta->addr; | 307 | u8 *sta_addr = key->sta->sta.addr; |
308 | 308 | ||
309 | if (is_multicast_ether_addr(ra)) | 309 | if (is_multicast_ether_addr(ra)) |
310 | sta_addr = bcast; | 310 | sta_addr = bcast; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4788f7b91f49..20d683641b42 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -38,43 +38,6 @@ | |||
38 | 38 | ||
39 | /* misc utils */ | 39 | /* misc utils */ |
40 | 40 | ||
41 | #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP | ||
42 | static void ieee80211_dump_frame(const char *ifname, const char *title, | ||
43 | const struct sk_buff *skb) | ||
44 | { | ||
45 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
46 | unsigned int hdrlen; | ||
47 | DECLARE_MAC_BUF(mac); | ||
48 | |||
49 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); | ||
50 | if (skb->len < 4) { | ||
51 | printk("\n"); | ||
52 | return; | ||
53 | } | ||
54 | |||
55 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
56 | if (hdrlen > skb->len) | ||
57 | hdrlen = skb->len; | ||
58 | if (hdrlen >= 4) | ||
59 | printk(" FC=0x%04x DUR=0x%04x", | ||
60 | le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); | ||
61 | if (hdrlen >= 10) | ||
62 | printk(" A1=%s", print_mac(mac, hdr->addr1)); | ||
63 | if (hdrlen >= 16) | ||
64 | printk(" A2=%s", print_mac(mac, hdr->addr2)); | ||
65 | if (hdrlen >= 24) | ||
66 | printk(" A3=%s", print_mac(mac, hdr->addr3)); | ||
67 | if (hdrlen >= 30) | ||
68 | printk(" A4=%s", print_mac(mac, hdr->addr4)); | ||
69 | printk("\n"); | ||
70 | } | ||
71 | #else /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | ||
72 | static inline void ieee80211_dump_frame(const char *ifname, const char *title, | ||
73 | struct sk_buff *skb) | ||
74 | { | ||
75 | } | ||
76 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | ||
77 | |||
78 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 41 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, |
79 | int next_frag_len) | 42 | int next_frag_len) |
80 | { | 43 | { |
@@ -82,6 +45,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
82 | struct ieee80211_rate *txrate; | 45 | struct ieee80211_rate *txrate; |
83 | struct ieee80211_local *local = tx->local; | 46 | struct ieee80211_local *local = tx->local; |
84 | struct ieee80211_supported_band *sband; | 47 | struct ieee80211_supported_band *sband; |
48 | struct ieee80211_hdr *hdr; | ||
85 | 49 | ||
86 | sband = local->hw.wiphy->bands[tx->channel->band]; | 50 | sband = local->hw.wiphy->bands[tx->channel->band]; |
87 | txrate = &sband->bitrates[tx->rate_idx]; | 51 | txrate = &sband->bitrates[tx->rate_idx]; |
@@ -107,10 +71,10 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
107 | * at the highest possible rate belonging to the PHY rates in the | 71 | * at the highest possible rate belonging to the PHY rates in the |
108 | * BSSBasicRateSet | 72 | * BSSBasicRateSet |
109 | */ | 73 | */ |
110 | 74 | hdr = (struct ieee80211_hdr *)tx->skb->data; | |
111 | if ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) { | 75 | if (ieee80211_is_ctl(hdr->frame_control)) { |
112 | /* TODO: These control frames are not currently sent by | 76 | /* TODO: These control frames are not currently sent by |
113 | * 80211.o, but should they be implemented, this function | 77 | * mac80211, but should they be implemented, this function |
114 | * needs to be updated to support duration field calculation. | 78 | * needs to be updated to support duration field calculation. |
115 | * | 79 | * |
116 | * RTS: time needed to transmit pending data/mgmt frame plus | 80 | * RTS: time needed to transmit pending data/mgmt frame plus |
@@ -152,7 +116,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
152 | if (r->bitrate > txrate->bitrate) | 116 | if (r->bitrate > txrate->bitrate) |
153 | break; | 117 | break; |
154 | 118 | ||
155 | if (tx->sdata->basic_rates & BIT(i)) | 119 | if (tx->sdata->bss_conf.basic_rates & BIT(i)) |
156 | rate = r->bitrate; | 120 | rate = r->bitrate; |
157 | 121 | ||
158 | switch (sband->band) { | 122 | switch (sband->band) { |
@@ -213,21 +177,19 @@ static int inline is_ieee80211_device(struct net_device *dev, | |||
213 | static ieee80211_tx_result debug_noinline | 177 | static ieee80211_tx_result debug_noinline |
214 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | 178 | ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) |
215 | { | 179 | { |
216 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 180 | |
217 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 181 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
218 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | ||
219 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 182 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
220 | u32 sta_flags; | 183 | u32 sta_flags; |
221 | 184 | ||
222 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | 185 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) |
223 | return TX_CONTINUE; | 186 | return TX_CONTINUE; |
224 | 187 | ||
225 | if (unlikely(tx->local->sta_sw_scanning) && | 188 | if (unlikely(tx->local->sw_scanning) && |
226 | ((tx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || | 189 | !ieee80211_is_probe_req(hdr->frame_control)) |
227 | (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) | ||
228 | return TX_DROP; | 190 | return TX_DROP; |
229 | 191 | ||
230 | if (tx->sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) | 192 | if (tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT) |
231 | return TX_CONTINUE; | 193 | return TX_CONTINUE; |
232 | 194 | ||
233 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) | 195 | if (tx->flags & IEEE80211_TX_PS_BUFFERED) |
@@ -237,8 +199,8 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
237 | 199 | ||
238 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { | 200 | if (likely(tx->flags & IEEE80211_TX_UNICAST)) { |
239 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && | 201 | if (unlikely(!(sta_flags & WLAN_STA_ASSOC) && |
240 | tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 202 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC && |
241 | (tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) { | 203 | ieee80211_is_data(hdr->frame_control))) { |
242 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 204 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
243 | DECLARE_MAC_BUF(mac); | 205 | DECLARE_MAC_BUF(mac); |
244 | printk(KERN_DEBUG "%s: dropped data frame to not " | 206 | printk(KERN_DEBUG "%s: dropped data frame to not " |
@@ -249,9 +211,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | |||
249 | return TX_DROP; | 211 | return TX_DROP; |
250 | } | 212 | } |
251 | } else { | 213 | } else { |
252 | if (unlikely((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && | 214 | if (unlikely(ieee80211_is_data(hdr->frame_control) && |
253 | tx->local->num_sta == 0 && | 215 | tx->local->num_sta == 0 && |
254 | tx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS)) { | 216 | tx->sdata->vif.type != NL80211_IFTYPE_ADHOC)) { |
255 | /* | 217 | /* |
256 | * No associated STAs - no need to send multicast | 218 | * No associated STAs - no need to send multicast |
257 | * frames. | 219 | * frames. |
@@ -282,7 +244,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local) | |||
282 | 244 | ||
283 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 245 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
284 | struct ieee80211_if_ap *ap; | 246 | struct ieee80211_if_ap *ap; |
285 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP) | 247 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
286 | continue; | 248 | continue; |
287 | ap = &sdata->u.ap; | 249 | ap = &sdata->u.ap; |
288 | skb = skb_dequeue(&ap->ps_bc_buf); | 250 | skb = skb_dequeue(&ap->ps_bc_buf); |
@@ -315,6 +277,7 @@ static ieee80211_tx_result | |||
315 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | 277 | ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) |
316 | { | 278 | { |
317 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 279 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
318 | 281 | ||
319 | /* | 282 | /* |
320 | * broadcast/multicast frame | 283 | * broadcast/multicast frame |
@@ -329,7 +292,7 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) | |||
329 | return TX_CONTINUE; | 292 | return TX_CONTINUE; |
330 | 293 | ||
331 | /* no buffering for ordered frames */ | 294 | /* no buffering for ordered frames */ |
332 | if (tx->fc & IEEE80211_FCTL_ORDER) | 295 | if (ieee80211_has_order(hdr->frame_control)) |
333 | return TX_CONTINUE; | 296 | return TX_CONTINUE; |
334 | 297 | ||
335 | /* no stations in PS mode */ | 298 | /* no stations in PS mode */ |
@@ -367,12 +330,11 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
367 | { | 330 | { |
368 | struct sta_info *sta = tx->sta; | 331 | struct sta_info *sta = tx->sta; |
369 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 332 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
333 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
370 | u32 staflags; | 334 | u32 staflags; |
371 | DECLARE_MAC_BUF(mac); | 335 | DECLARE_MAC_BUF(mac); |
372 | 336 | ||
373 | if (unlikely(!sta || | 337 | if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) |
374 | ((tx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && | ||
375 | (tx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP))) | ||
376 | return TX_CONTINUE; | 338 | return TX_CONTINUE; |
377 | 339 | ||
378 | staflags = get_sta_flags(sta); | 340 | staflags = get_sta_flags(sta); |
@@ -382,7 +344,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
382 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 344 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
383 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " | 345 | printk(KERN_DEBUG "STA %s aid %d: PS buffer (entries " |
384 | "before %d)\n", | 346 | "before %d)\n", |
385 | print_mac(mac, sta->addr), sta->aid, | 347 | print_mac(mac, sta->sta.addr), sta->sta.aid, |
386 | skb_queue_len(&sta->ps_tx_buf)); | 348 | skb_queue_len(&sta->ps_tx_buf)); |
387 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 349 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
388 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) | 350 | if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) |
@@ -393,7 +355,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
393 | if (net_ratelimit()) { | 355 | if (net_ratelimit()) { |
394 | printk(KERN_DEBUG "%s: STA %s TX " | 356 | printk(KERN_DEBUG "%s: STA %s TX " |
395 | "buffer full - dropping oldest frame\n", | 357 | "buffer full - dropping oldest frame\n", |
396 | tx->dev->name, print_mac(mac, sta->addr)); | 358 | tx->dev->name, print_mac(mac, sta->sta.addr)); |
397 | } | 359 | } |
398 | #endif | 360 | #endif |
399 | dev_kfree_skb(old); | 361 | dev_kfree_skb(old); |
@@ -412,7 +374,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
412 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { | 374 | else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) { |
413 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " | 375 | printk(KERN_DEBUG "%s: STA %s in PS mode, but pspoll " |
414 | "set -> send frame\n", tx->dev->name, | 376 | "set -> send frame\n", tx->dev->name, |
415 | print_mac(mac, sta->addr)); | 377 | print_mac(mac, sta->sta.addr)); |
416 | } | 378 | } |
417 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 379 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
418 | clear_sta_flags(sta, WLAN_STA_PSPOLL); | 380 | clear_sta_flags(sta, WLAN_STA_PSPOLL); |
@@ -437,7 +399,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
437 | { | 399 | { |
438 | struct ieee80211_key *key; | 400 | struct ieee80211_key *key; |
439 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 401 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
440 | u16 fc = tx->fc; | 402 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
441 | 403 | ||
442 | if (unlikely(tx->skb->do_not_encrypt)) | 404 | if (unlikely(tx->skb->do_not_encrypt)) |
443 | tx->key = NULL; | 405 | tx->key = NULL; |
@@ -454,22 +416,16 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
454 | tx->key = NULL; | 416 | tx->key = NULL; |
455 | 417 | ||
456 | if (tx->key) { | 418 | if (tx->key) { |
457 | u16 ftype, stype; | ||
458 | |||
459 | tx->key->tx_rx_count++; | 419 | tx->key->tx_rx_count++; |
460 | /* TODO: add threshold stuff again */ | 420 | /* TODO: add threshold stuff again */ |
461 | 421 | ||
462 | switch (tx->key->conf.alg) { | 422 | switch (tx->key->conf.alg) { |
463 | case ALG_WEP: | 423 | case ALG_WEP: |
464 | ftype = fc & IEEE80211_FCTL_FTYPE; | 424 | if (ieee80211_is_auth(hdr->frame_control)) |
465 | stype = fc & IEEE80211_FCTL_STYPE; | ||
466 | |||
467 | if (ftype == IEEE80211_FTYPE_MGMT && | ||
468 | stype == IEEE80211_STYPE_AUTH) | ||
469 | break; | 425 | break; |
470 | case ALG_TKIP: | 426 | case ALG_TKIP: |
471 | case ALG_CCMP: | 427 | case ALG_CCMP: |
472 | if (!WLAN_FC_DATA_PRESENT(fc)) | 428 | if (!ieee80211_is_data_present(hdr->frame_control)) |
473 | tx->key = NULL; | 429 | tx->key = NULL; |
474 | break; | 430 | break; |
475 | } | 431 | } |
@@ -492,6 +448,8 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
492 | 448 | ||
493 | if (likely(tx->rate_idx < 0)) { | 449 | if (likely(tx->rate_idx < 0)) { |
494 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); | 450 | rate_control_get_rate(tx->dev, sband, tx->skb, &rsel); |
451 | if (tx->sta) | ||
452 | tx->sta->last_txrate_idx = rsel.rate_idx; | ||
495 | tx->rate_idx = rsel.rate_idx; | 453 | tx->rate_idx = rsel.rate_idx; |
496 | if (unlikely(rsel.probe_idx >= 0)) { | 454 | if (unlikely(rsel.probe_idx >= 0)) { |
497 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 455 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
@@ -535,7 +493,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
535 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 493 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
536 | 494 | ||
537 | if (tx->sta) | 495 | if (tx->sta) |
538 | info->control.aid = tx->sta->aid; | 496 | info->control.sta = &tx->sta->sta; |
539 | 497 | ||
540 | if (!info->control.retry_limit) { | 498 | if (!info->control.retry_limit) { |
541 | if (!is_multicast_ether_addr(hdr->addr1)) { | 499 | if (!is_multicast_ether_addr(hdr->addr1)) { |
@@ -601,7 +559,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
601 | for (idx = 0; idx < sband->n_bitrates; idx++) { | 559 | for (idx = 0; idx < sband->n_bitrates; idx++) { |
602 | if (sband->bitrates[idx].bitrate > rate->bitrate) | 560 | if (sband->bitrates[idx].bitrate > rate->bitrate) |
603 | continue; | 561 | continue; |
604 | if (tx->sdata->basic_rates & BIT(idx) && | 562 | if (tx->sdata->bss_conf.basic_rates & BIT(idx) && |
605 | (baserate < 0 || | 563 | (baserate < 0 || |
606 | (sband->bitrates[baserate].bitrate | 564 | (sband->bitrates[baserate].bitrate |
607 | < sband->bitrates[idx].bitrate))) | 565 | < sband->bitrates[idx].bitrate))) |
@@ -615,7 +573,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
615 | } | 573 | } |
616 | 574 | ||
617 | if (tx->sta) | 575 | if (tx->sta) |
618 | info->control.aid = tx->sta->aid; | 576 | info->control.sta = &tx->sta->sta; |
619 | 577 | ||
620 | return TX_CONTINUE; | 578 | return TX_CONTINUE; |
621 | } | 579 | } |
@@ -629,7 +587,14 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
629 | u8 *qc; | 587 | u8 *qc; |
630 | int tid; | 588 | int tid; |
631 | 589 | ||
632 | /* only for injected frames */ | 590 | /* |
591 | * Packet injection may want to control the sequence | ||
592 | * number, if we have no matching interface then we | ||
593 | * neither assign one ourselves nor ask the driver to. | ||
594 | */ | ||
595 | if (unlikely(!info->control.vif)) | ||
596 | return TX_CONTINUE; | ||
597 | |||
633 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) | 598 | if (unlikely(ieee80211_is_ctl(hdr->frame_control))) |
634 | return TX_CONTINUE; | 599 | return TX_CONTINUE; |
635 | 600 | ||
@@ -854,7 +819,6 @@ __ieee80211_parse_tx_radiotap(struct ieee80211_tx_data *tx, | |||
854 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 819 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; |
855 | 820 | ||
856 | skb->do_not_encrypt = 1; | 821 | skb->do_not_encrypt = 1; |
857 | info->flags |= IEEE80211_TX_CTL_INJECTED; | ||
858 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; | 822 | tx->flags &= ~IEEE80211_TX_FRAGMENTED; |
859 | 823 | ||
860 | /* | 824 | /* |
@@ -986,7 +950,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
986 | 950 | ||
987 | /* process and remove the injection radiotap header */ | 951 | /* process and remove the injection radiotap header */ |
988 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 952 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
989 | if (unlikely(sdata->vif.type == IEEE80211_IF_TYPE_MNTR)) { | 953 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) { |
990 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) | 954 | if (__ieee80211_parse_tx_radiotap(tx, skb) == TX_DROP) |
991 | return TX_DROP; | 955 | return TX_DROP; |
992 | 956 | ||
@@ -1000,7 +964,6 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1000 | hdr = (struct ieee80211_hdr *) skb->data; | 964 | hdr = (struct ieee80211_hdr *) skb->data; |
1001 | 965 | ||
1002 | tx->sta = sta_info_get(local, hdr->addr1); | 966 | tx->sta = sta_info_get(local, hdr->addr1); |
1003 | tx->fc = le16_to_cpu(hdr->frame_control); | ||
1004 | 967 | ||
1005 | if (is_multicast_ether_addr(hdr->addr1)) { | 968 | if (is_multicast_ether_addr(hdr->addr1)) { |
1006 | tx->flags &= ~IEEE80211_TX_UNICAST; | 969 | tx->flags &= ~IEEE80211_TX_UNICAST; |
@@ -1025,7 +988,7 @@ __ieee80211_tx_prepare(struct ieee80211_tx_data *tx, | |||
1025 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) | 988 | else if (test_and_clear_sta_flags(tx->sta, WLAN_STA_CLEAR_PS_FILT)) |
1026 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | 989 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; |
1027 | 990 | ||
1028 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 991 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1029 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { | 992 | if (skb->len > hdrlen + sizeof(rfc1042_header) + 2) { |
1030 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; | 993 | u8 *pos = &skb->data[hdrlen + sizeof(rfc1042_header)]; |
1031 | tx->ethertype = (pos[0] << 8) | pos[1]; | 994 | tx->ethertype = (pos[0] << 8) | pos[1]; |
@@ -1068,8 +1031,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1068 | return IEEE80211_TX_AGAIN; | 1031 | return IEEE80211_TX_AGAIN; |
1069 | info = IEEE80211_SKB_CB(skb); | 1032 | info = IEEE80211_SKB_CB(skb); |
1070 | 1033 | ||
1071 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | ||
1072 | "TX to low-level driver", skb); | ||
1073 | ret = local->ops->tx(local_to_hw(local), skb); | 1034 | ret = local->ops->tx(local_to_hw(local), skb); |
1074 | if (ret) | 1035 | if (ret) |
1075 | return IEEE80211_TX_AGAIN; | 1036 | return IEEE80211_TX_AGAIN; |
@@ -1099,9 +1060,6 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1099 | ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 1060 | ~IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
1100 | } | 1061 | } |
1101 | 1062 | ||
1102 | ieee80211_dump_frame(wiphy_name(local->hw.wiphy), | ||
1103 | "TX to low-level driver", | ||
1104 | tx->extra_frag[i]); | ||
1105 | ret = local->ops->tx(local_to_hw(local), | 1063 | ret = local->ops->tx(local_to_hw(local), |
1106 | tx->extra_frag[i]); | 1064 | tx->extra_frag[i]); |
1107 | if (ret) | 1065 | if (ret) |
@@ -1306,6 +1264,11 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1306 | struct ieee80211_sub_if_data *osdata; | 1264 | struct ieee80211_sub_if_data *osdata; |
1307 | int headroom; | 1265 | int headroom; |
1308 | bool may_encrypt; | 1266 | bool may_encrypt; |
1267 | enum { | ||
1268 | NOT_MONITOR, | ||
1269 | FOUND_SDATA, | ||
1270 | UNKNOWN_ADDRESS, | ||
1271 | } monitor_iface = NOT_MONITOR; | ||
1309 | int ret; | 1272 | int ret; |
1310 | 1273 | ||
1311 | if (skb->iif) | 1274 | if (skb->iif) |
@@ -1335,12 +1298,56 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1335 | if (is_multicast_ether_addr(hdr->addr3)) | 1298 | if (is_multicast_ether_addr(hdr->addr3)) |
1336 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1299 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1337 | else | 1300 | else |
1338 | if (mesh_nexthop_lookup(skb, odev)) | 1301 | if (mesh_nexthop_lookup(skb, osdata)) |
1339 | return 0; | 1302 | return 0; |
1340 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1303 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) |
1341 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, | 1304 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, |
1342 | fwded_frames); | 1305 | fwded_frames); |
1343 | } | 1306 | } |
1307 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { | ||
1308 | struct ieee80211_sub_if_data *sdata; | ||
1309 | struct ieee80211_local *local = osdata->local; | ||
1310 | struct ieee80211_hdr *hdr; | ||
1311 | int hdrlen; | ||
1312 | u16 len_rthdr; | ||
1313 | |||
1314 | info->flags |= IEEE80211_TX_CTL_INJECTED; | ||
1315 | monitor_iface = UNKNOWN_ADDRESS; | ||
1316 | |||
1317 | len_rthdr = ieee80211_get_radiotap_len(skb->data); | ||
1318 | hdr = (struct ieee80211_hdr *)skb->data + len_rthdr; | ||
1319 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
1320 | |||
1321 | /* check the header is complete in the frame */ | ||
1322 | if (likely(skb->len >= len_rthdr + hdrlen)) { | ||
1323 | /* | ||
1324 | * We process outgoing injected frames that have a | ||
1325 | * local address we handle as though they are our | ||
1326 | * own frames. | ||
1327 | * This code here isn't entirely correct, the local | ||
1328 | * MAC address is not necessarily enough to find | ||
1329 | * the interface to use; for that proper VLAN/WDS | ||
1330 | * support we will need a different mechanism. | ||
1331 | */ | ||
1332 | |||
1333 | rcu_read_lock(); | ||
1334 | list_for_each_entry_rcu(sdata, &local->interfaces, | ||
1335 | list) { | ||
1336 | if (!netif_running(sdata->dev)) | ||
1337 | continue; | ||
1338 | if (compare_ether_addr(sdata->dev->dev_addr, | ||
1339 | hdr->addr2)) { | ||
1340 | dev_hold(sdata->dev); | ||
1341 | dev_put(odev); | ||
1342 | osdata = sdata; | ||
1343 | odev = osdata->dev; | ||
1344 | skb->iif = sdata->dev->ifindex; | ||
1345 | monitor_iface = FOUND_SDATA; | ||
1346 | break; | ||
1347 | } | ||
1348 | } | ||
1349 | rcu_read_unlock(); | ||
1350 | } | ||
1344 | } | 1351 | } |
1345 | 1352 | ||
1346 | may_encrypt = !skb->do_not_encrypt; | 1353 | may_encrypt = !skb->do_not_encrypt; |
@@ -1357,7 +1364,12 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1357 | return 0; | 1364 | return 0; |
1358 | } | 1365 | } |
1359 | 1366 | ||
1360 | info->control.vif = &osdata->vif; | 1367 | if (osdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1368 | osdata = container_of(osdata->bss, | ||
1369 | struct ieee80211_sub_if_data, | ||
1370 | u.ap); | ||
1371 | if (likely(monitor_iface != UNKNOWN_ADDRESS)) | ||
1372 | info->control.vif = &osdata->vif; | ||
1361 | ret = ieee80211_tx(odev, skb); | 1373 | ret = ieee80211_tx(odev, skb); |
1362 | dev_put(odev); | 1374 | dev_put(odev); |
1363 | 1375 | ||
@@ -1465,8 +1477,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1465 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); | 1477 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1466 | 1478 | ||
1467 | switch (sdata->vif.type) { | 1479 | switch (sdata->vif.type) { |
1468 | case IEEE80211_IF_TYPE_AP: | 1480 | case NL80211_IFTYPE_AP: |
1469 | case IEEE80211_IF_TYPE_VLAN: | 1481 | case NL80211_IFTYPE_AP_VLAN: |
1470 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 1482 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1471 | /* DA BSSID SA */ | 1483 | /* DA BSSID SA */ |
1472 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1484 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1474,7 +1486,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1474 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); | 1486 | memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN); |
1475 | hdrlen = 24; | 1487 | hdrlen = 24; |
1476 | break; | 1488 | break; |
1477 | case IEEE80211_IF_TYPE_WDS: | 1489 | case NL80211_IFTYPE_WDS: |
1478 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1490 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1479 | /* RA TA DA SA */ | 1491 | /* RA TA DA SA */ |
1480 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1492 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
@@ -1484,16 +1496,16 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1484 | hdrlen = 30; | 1496 | hdrlen = 30; |
1485 | break; | 1497 | break; |
1486 | #ifdef CONFIG_MAC80211_MESH | 1498 | #ifdef CONFIG_MAC80211_MESH |
1487 | case IEEE80211_IF_TYPE_MESH_POINT: | 1499 | case NL80211_IFTYPE_MESH_POINT: |
1488 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1500 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1489 | /* RA TA DA SA */ | 1501 | /* RA TA DA SA */ |
1490 | memset(hdr.addr1, 0, ETH_ALEN); | 1502 | memset(hdr.addr1, 0, ETH_ALEN); |
1491 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1503 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
1492 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1504 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1493 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); | 1505 | memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); |
1494 | if (!sdata->u.sta.mshcfg.dot11MeshTTL) { | 1506 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1495 | /* Do not send frames with mesh_ttl == 0 */ | 1507 | /* Do not send frames with mesh_ttl == 0 */ |
1496 | sdata->u.sta.mshstats.dropped_frames_ttl++; | 1508 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1497 | ret = 0; | 1509 | ret = 0; |
1498 | goto fail; | 1510 | goto fail; |
1499 | } | 1511 | } |
@@ -1501,7 +1513,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1501 | hdrlen = 30; | 1513 | hdrlen = 30; |
1502 | break; | 1514 | break; |
1503 | #endif | 1515 | #endif |
1504 | case IEEE80211_IF_TYPE_STA: | 1516 | case NL80211_IFTYPE_STATION: |
1505 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); | 1517 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1506 | /* BSSID SA DA */ | 1518 | /* BSSID SA DA */ |
1507 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); | 1519 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); |
@@ -1509,7 +1521,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1509 | memcpy(hdr.addr3, skb->data, ETH_ALEN); | 1521 | memcpy(hdr.addr3, skb->data, ETH_ALEN); |
1510 | hdrlen = 24; | 1522 | hdrlen = 24; |
1511 | break; | 1523 | break; |
1512 | case IEEE80211_IF_TYPE_IBSS: | 1524 | case NL80211_IFTYPE_ADHOC: |
1513 | /* DA SA BSSID */ | 1525 | /* DA SA BSSID */ |
1514 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1526 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1515 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1527 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1588,19 +1600,6 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1588 | nh_pos -= skip_header_bytes; | 1600 | nh_pos -= skip_header_bytes; |
1589 | h_pos -= skip_header_bytes; | 1601 | h_pos -= skip_header_bytes; |
1590 | 1602 | ||
1591 | /* TODO: implement support for fragments so that there is no need to | ||
1592 | * reallocate and copy payload; it might be enough to support one | ||
1593 | * extra fragment that would be copied in the beginning of the frame | ||
1594 | * data.. anyway, it would be nice to include this into skb structure | ||
1595 | * somehow | ||
1596 | * | ||
1597 | * There are few options for this: | ||
1598 | * use skb->cb as an extra space for 802.11 header | ||
1599 | * allocate new buffer if not enough headroom | ||
1600 | * make sure that there is enough headroom in every skb by increasing | ||
1601 | * build in headroom in __dev_alloc_skb() (linux/skbuff.h) and | ||
1602 | * alloc_skb() (net/core/skbuff.c) | ||
1603 | */ | ||
1604 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); | 1603 | head_need = hdrlen + encaps_len + meshhdrlen - skb_headroom(skb); |
1605 | 1604 | ||
1606 | /* | 1605 | /* |
@@ -1823,10 +1822,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1823 | struct rate_selection rsel; | 1822 | struct rate_selection rsel; |
1824 | struct beacon_data *beacon; | 1823 | struct beacon_data *beacon; |
1825 | struct ieee80211_supported_band *sband; | 1824 | struct ieee80211_supported_band *sband; |
1826 | struct ieee80211_mgmt *mgmt; | ||
1827 | int *num_beacons; | ||
1828 | enum ieee80211_band band = local->hw.conf.channel->band; | 1825 | enum ieee80211_band band = local->hw.conf.channel->band; |
1829 | u8 *pos; | ||
1830 | 1826 | ||
1831 | sband = local->hw.wiphy->bands[band]; | 1827 | sband = local->hw.wiphy->bands[band]; |
1832 | 1828 | ||
@@ -1835,7 +1831,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1835 | sdata = vif_to_sdata(vif); | 1831 | sdata = vif_to_sdata(vif); |
1836 | bdev = sdata->dev; | 1832 | bdev = sdata->dev; |
1837 | 1833 | ||
1838 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 1834 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
1839 | ap = &sdata->u.ap; | 1835 | ap = &sdata->u.ap; |
1840 | beacon = rcu_dereference(ap->beacon); | 1836 | beacon = rcu_dereference(ap->beacon); |
1841 | if (ap && beacon) { | 1837 | if (ap && beacon) { |
@@ -1873,11 +1869,9 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1873 | if (beacon->tail) | 1869 | if (beacon->tail) |
1874 | memcpy(skb_put(skb, beacon->tail_len), | 1870 | memcpy(skb_put(skb, beacon->tail_len), |
1875 | beacon->tail, beacon->tail_len); | 1871 | beacon->tail, beacon->tail_len); |
1876 | |||
1877 | num_beacons = &ap->num_beacons; | ||
1878 | } else | 1872 | } else |
1879 | goto out; | 1873 | goto out; |
1880 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1874 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1881 | struct ieee80211_hdr *hdr; | 1875 | struct ieee80211_hdr *hdr; |
1882 | ifsta = &sdata->u.sta; | 1876 | ifsta = &sdata->u.sta; |
1883 | 1877 | ||
@@ -1889,11 +1883,13 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1889 | goto out; | 1883 | goto out; |
1890 | 1884 | ||
1891 | hdr = (struct ieee80211_hdr *) skb->data; | 1885 | hdr = (struct ieee80211_hdr *) skb->data; |
1892 | hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1886 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1893 | IEEE80211_STYPE_BEACON); | 1887 | IEEE80211_STYPE_BEACON); |
1894 | 1888 | ||
1895 | num_beacons = &ifsta->num_beacons; | ||
1896 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1889 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
1890 | struct ieee80211_mgmt *mgmt; | ||
1891 | u8 *pos; | ||
1892 | |||
1897 | /* headroom, head length, tail length and maximum TIM length */ | 1893 | /* headroom, head length, tail length and maximum TIM length */ |
1898 | skb = dev_alloc_skb(local->tx_headroom + 400); | 1894 | skb = dev_alloc_skb(local->tx_headroom + 400); |
1899 | if (!skb) | 1895 | if (!skb) |
@@ -1916,9 +1912,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1916 | *pos++ = WLAN_EID_SSID; | 1912 | *pos++ = WLAN_EID_SSID; |
1917 | *pos++ = 0x0; | 1913 | *pos++ = 0x0; |
1918 | 1914 | ||
1919 | mesh_mgmt_ies_add(skb, sdata->dev); | 1915 | mesh_mgmt_ies_add(skb, sdata); |
1920 | |||
1921 | num_beacons = &sdata->u.sta.num_beacons; | ||
1922 | } else { | 1916 | } else { |
1923 | WARN_ON(1); | 1917 | WARN_ON(1); |
1924 | goto out; | 1918 | goto out; |
@@ -1955,7 +1949,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1955 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; | 1949 | info->antenna_sel_tx = local->hw.conf.antenna_sel_tx; |
1956 | info->control.retry_limit = 1; | 1950 | info->control.retry_limit = 1; |
1957 | 1951 | ||
1958 | (*num_beacons)++; | ||
1959 | out: | 1952 | out: |
1960 | rcu_read_unlock(); | 1953 | rcu_read_unlock(); |
1961 | return skb; | 1954 | return skb; |
@@ -2017,7 +2010,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2017 | rcu_read_lock(); | 2010 | rcu_read_lock(); |
2018 | beacon = rcu_dereference(bss->beacon); | 2011 | beacon = rcu_dereference(bss->beacon); |
2019 | 2012 | ||
2020 | if (sdata->vif.type != IEEE80211_IF_TYPE_AP || !beacon || !beacon->head) | 2013 | if (sdata->vif.type != NL80211_IFTYPE_AP || !beacon || !beacon->head) |
2021 | goto out; | 2014 | goto out; |
2022 | 2015 | ||
2023 | if (bss->dtim_count != 0) | 2016 | if (bss->dtim_count != 0) |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 0d463c80c404..f32561ec224c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -43,7 +43,7 @@ const unsigned char bridge_tunnel_header[] __aligned(2) = | |||
43 | 43 | ||
44 | 44 | ||
45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 45 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
46 | enum ieee80211_if_types type) | 46 | enum nl80211_iftype type) |
47 | { | 47 | { |
48 | __le16 fc = hdr->frame_control; | 48 | __le16 fc = hdr->frame_control; |
49 | 49 | ||
@@ -77,10 +77,10 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
77 | 77 | ||
78 | if (ieee80211_is_back_req(fc)) { | 78 | if (ieee80211_is_back_req(fc)) { |
79 | switch (type) { | 79 | switch (type) { |
80 | case IEEE80211_IF_TYPE_STA: | 80 | case NL80211_IFTYPE_STATION: |
81 | return hdr->addr2; | 81 | return hdr->addr2; |
82 | case IEEE80211_IF_TYPE_AP: | 82 | case NL80211_IFTYPE_AP: |
83 | case IEEE80211_IF_TYPE_VLAN: | 83 | case NL80211_IFTYPE_AP_VLAN: |
84 | return hdr->addr1; | 84 | return hdr->addr1; |
85 | default: | 85 | default: |
86 | break; /* fall through to the return */ | 86 | break; /* fall through to the return */ |
@@ -91,45 +91,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | |||
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
93 | 93 | ||
94 | int ieee80211_get_hdrlen(u16 fc) | ||
95 | { | ||
96 | int hdrlen = 24; | ||
97 | |||
98 | switch (fc & IEEE80211_FCTL_FTYPE) { | ||
99 | case IEEE80211_FTYPE_DATA: | ||
100 | if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) | ||
101 | hdrlen = 30; /* Addr4 */ | ||
102 | /* | ||
103 | * The QoS Control field is two bytes and its presence is | ||
104 | * indicated by the IEEE80211_STYPE_QOS_DATA bit. Add 2 to | ||
105 | * hdrlen if that bit is set. | ||
106 | * This works by masking out the bit and shifting it to | ||
107 | * bit position 1 so the result has the value 0 or 2. | ||
108 | */ | ||
109 | hdrlen += (fc & IEEE80211_STYPE_QOS_DATA) | ||
110 | >> (ilog2(IEEE80211_STYPE_QOS_DATA)-1); | ||
111 | break; | ||
112 | case IEEE80211_FTYPE_CTL: | ||
113 | /* | ||
114 | * ACK and CTS are 10 bytes, all others 16. To see how | ||
115 | * to get this condition consider | ||
116 | * subtype mask: 0b0000000011110000 (0x00F0) | ||
117 | * ACK subtype: 0b0000000011010000 (0x00D0) | ||
118 | * CTS subtype: 0b0000000011000000 (0x00C0) | ||
119 | * bits that matter: ^^^ (0x00E0) | ||
120 | * value of those: 0b0000000011000000 (0x00C0) | ||
121 | */ | ||
122 | if ((fc & 0xE0) == 0xC0) | ||
123 | hdrlen = 10; | ||
124 | else | ||
125 | hdrlen = 16; | ||
126 | break; | ||
127 | } | ||
128 | |||
129 | return hdrlen; | ||
130 | } | ||
131 | EXPORT_SYMBOL(ieee80211_get_hdrlen); | ||
132 | |||
133 | unsigned int ieee80211_hdrlen(__le16 fc) | 94 | unsigned int ieee80211_hdrlen(__le16 fc) |
134 | { | 95 | { |
135 | unsigned int hdrlen = 24; | 96 | unsigned int hdrlen = 24; |
@@ -270,16 +231,21 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
270 | struct ieee80211_rate *rate) | 231 | struct ieee80211_rate *rate) |
271 | { | 232 | { |
272 | struct ieee80211_local *local = hw_to_local(hw); | 233 | struct ieee80211_local *local = hw_to_local(hw); |
273 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 234 | struct ieee80211_sub_if_data *sdata; |
274 | u16 dur; | 235 | u16 dur; |
275 | int erp; | 236 | int erp; |
237 | bool short_preamble = false; | ||
276 | 238 | ||
277 | erp = 0; | 239 | erp = 0; |
278 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 240 | if (vif) { |
279 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 241 | sdata = vif_to_sdata(vif); |
242 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
243 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
244 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
245 | } | ||
280 | 246 | ||
281 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, | 247 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, |
282 | sdata->bss_conf.use_short_preamble); | 248 | short_preamble); |
283 | 249 | ||
284 | return cpu_to_le16(dur); | 250 | return cpu_to_le16(dur); |
285 | } | 251 | } |
@@ -291,7 +257,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
291 | { | 257 | { |
292 | struct ieee80211_local *local = hw_to_local(hw); | 258 | struct ieee80211_local *local = hw_to_local(hw); |
293 | struct ieee80211_rate *rate; | 259 | struct ieee80211_rate *rate; |
294 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 260 | struct ieee80211_sub_if_data *sdata; |
295 | bool short_preamble; | 261 | bool short_preamble; |
296 | int erp; | 262 | int erp; |
297 | u16 dur; | 263 | u16 dur; |
@@ -299,13 +265,17 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
299 | 265 | ||
300 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 266 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
301 | 267 | ||
302 | short_preamble = sdata->bss_conf.use_short_preamble; | 268 | short_preamble = false; |
303 | 269 | ||
304 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 270 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
305 | 271 | ||
306 | erp = 0; | 272 | erp = 0; |
307 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 273 | if (vif) { |
308 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 274 | sdata = vif_to_sdata(vif); |
275 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
276 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
277 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
278 | } | ||
309 | 279 | ||
310 | /* CTS duration */ | 280 | /* CTS duration */ |
311 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, | 281 | dur = ieee80211_frame_duration(local, 10, rate->bitrate, |
@@ -328,7 +298,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
328 | { | 298 | { |
329 | struct ieee80211_local *local = hw_to_local(hw); | 299 | struct ieee80211_local *local = hw_to_local(hw); |
330 | struct ieee80211_rate *rate; | 300 | struct ieee80211_rate *rate; |
331 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 301 | struct ieee80211_sub_if_data *sdata; |
332 | bool short_preamble; | 302 | bool short_preamble; |
333 | int erp; | 303 | int erp; |
334 | u16 dur; | 304 | u16 dur; |
@@ -336,12 +306,16 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
336 | 306 | ||
337 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 307 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
338 | 308 | ||
339 | short_preamble = sdata->bss_conf.use_short_preamble; | 309 | short_preamble = false; |
340 | 310 | ||
341 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; | 311 | rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx]; |
342 | erp = 0; | 312 | erp = 0; |
343 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | 313 | if (vif) { |
344 | erp = rate->flags & IEEE80211_RATE_ERP_G; | 314 | sdata = vif_to_sdata(vif); |
315 | short_preamble = sdata->bss_conf.use_short_preamble; | ||
316 | if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE) | ||
317 | erp = rate->flags & IEEE80211_RATE_ERP_G; | ||
318 | } | ||
345 | 319 | ||
346 | /* Data frame duration */ | 320 | /* Data frame duration */ |
347 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, | 321 | dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, |
@@ -386,6 +360,13 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw) | |||
386 | } | 360 | } |
387 | EXPORT_SYMBOL(ieee80211_stop_queues); | 361 | EXPORT_SYMBOL(ieee80211_stop_queues); |
388 | 362 | ||
363 | int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | ||
364 | { | ||
365 | struct ieee80211_local *local = hw_to_local(hw); | ||
366 | return __netif_subqueue_stopped(local->mdev, queue); | ||
367 | } | ||
368 | EXPORT_SYMBOL(ieee80211_queue_stopped); | ||
369 | |||
389 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
390 | { | 371 | { |
391 | int i; | 372 | int i; |
@@ -408,15 +389,16 @@ void ieee80211_iterate_active_interfaces( | |||
408 | 389 | ||
409 | list_for_each_entry(sdata, &local->interfaces, list) { | 390 | list_for_each_entry(sdata, &local->interfaces, list) { |
410 | switch (sdata->vif.type) { | 391 | switch (sdata->vif.type) { |
411 | case IEEE80211_IF_TYPE_INVALID: | 392 | case __NL80211_IFTYPE_AFTER_LAST: |
412 | case IEEE80211_IF_TYPE_MNTR: | 393 | case NL80211_IFTYPE_UNSPECIFIED: |
413 | case IEEE80211_IF_TYPE_VLAN: | 394 | case NL80211_IFTYPE_MONITOR: |
395 | case NL80211_IFTYPE_AP_VLAN: | ||
414 | continue; | 396 | continue; |
415 | case IEEE80211_IF_TYPE_AP: | 397 | case NL80211_IFTYPE_AP: |
416 | case IEEE80211_IF_TYPE_STA: | 398 | case NL80211_IFTYPE_STATION: |
417 | case IEEE80211_IF_TYPE_IBSS: | 399 | case NL80211_IFTYPE_ADHOC: |
418 | case IEEE80211_IF_TYPE_WDS: | 400 | case NL80211_IFTYPE_WDS: |
419 | case IEEE80211_IF_TYPE_MESH_POINT: | 401 | case NL80211_IFTYPE_MESH_POINT: |
420 | break; | 402 | break; |
421 | } | 403 | } |
422 | if (netif_running(sdata->dev)) | 404 | if (netif_running(sdata->dev)) |
@@ -441,15 +423,16 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
441 | 423 | ||
442 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 424 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
443 | switch (sdata->vif.type) { | 425 | switch (sdata->vif.type) { |
444 | case IEEE80211_IF_TYPE_INVALID: | 426 | case __NL80211_IFTYPE_AFTER_LAST: |
445 | case IEEE80211_IF_TYPE_MNTR: | 427 | case NL80211_IFTYPE_UNSPECIFIED: |
446 | case IEEE80211_IF_TYPE_VLAN: | 428 | case NL80211_IFTYPE_MONITOR: |
429 | case NL80211_IFTYPE_AP_VLAN: | ||
447 | continue; | 430 | continue; |
448 | case IEEE80211_IF_TYPE_AP: | 431 | case NL80211_IFTYPE_AP: |
449 | case IEEE80211_IF_TYPE_STA: | 432 | case NL80211_IFTYPE_STATION: |
450 | case IEEE80211_IF_TYPE_IBSS: | 433 | case NL80211_IFTYPE_ADHOC: |
451 | case IEEE80211_IF_TYPE_WDS: | 434 | case NL80211_IFTYPE_WDS: |
452 | case IEEE80211_IF_TYPE_MESH_POINT: | 435 | case NL80211_IFTYPE_MESH_POINT: |
453 | break; | 436 | break; |
454 | } | 437 | } |
455 | if (netif_running(sdata->dev)) | 438 | if (netif_running(sdata->dev)) |
@@ -460,3 +443,243 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
460 | rcu_read_unlock(); | 443 | rcu_read_unlock(); |
461 | } | 444 | } |
462 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); | 445 | EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); |
446 | |||
447 | void ieee802_11_parse_elems(u8 *start, size_t len, | ||
448 | struct ieee802_11_elems *elems) | ||
449 | { | ||
450 | size_t left = len; | ||
451 | u8 *pos = start; | ||
452 | |||
453 | memset(elems, 0, sizeof(*elems)); | ||
454 | elems->ie_start = start; | ||
455 | elems->total_len = len; | ||
456 | |||
457 | while (left >= 2) { | ||
458 | u8 id, elen; | ||
459 | |||
460 | id = *pos++; | ||
461 | elen = *pos++; | ||
462 | left -= 2; | ||
463 | |||
464 | if (elen > left) | ||
465 | return; | ||
466 | |||
467 | switch (id) { | ||
468 | case WLAN_EID_SSID: | ||
469 | elems->ssid = pos; | ||
470 | elems->ssid_len = elen; | ||
471 | break; | ||
472 | case WLAN_EID_SUPP_RATES: | ||
473 | elems->supp_rates = pos; | ||
474 | elems->supp_rates_len = elen; | ||
475 | break; | ||
476 | case WLAN_EID_FH_PARAMS: | ||
477 | elems->fh_params = pos; | ||
478 | elems->fh_params_len = elen; | ||
479 | break; | ||
480 | case WLAN_EID_DS_PARAMS: | ||
481 | elems->ds_params = pos; | ||
482 | elems->ds_params_len = elen; | ||
483 | break; | ||
484 | case WLAN_EID_CF_PARAMS: | ||
485 | elems->cf_params = pos; | ||
486 | elems->cf_params_len = elen; | ||
487 | break; | ||
488 | case WLAN_EID_TIM: | ||
489 | elems->tim = pos; | ||
490 | elems->tim_len = elen; | ||
491 | break; | ||
492 | case WLAN_EID_IBSS_PARAMS: | ||
493 | elems->ibss_params = pos; | ||
494 | elems->ibss_params_len = elen; | ||
495 | break; | ||
496 | case WLAN_EID_CHALLENGE: | ||
497 | elems->challenge = pos; | ||
498 | elems->challenge_len = elen; | ||
499 | break; | ||
500 | case WLAN_EID_WPA: | ||
501 | if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||
502 | pos[2] == 0xf2) { | ||
503 | /* Microsoft OUI (00:50:F2) */ | ||
504 | if (pos[3] == 1) { | ||
505 | /* OUI Type 1 - WPA IE */ | ||
506 | elems->wpa = pos; | ||
507 | elems->wpa_len = elen; | ||
508 | } else if (elen >= 5 && pos[3] == 2) { | ||
509 | if (pos[4] == 0) { | ||
510 | elems->wmm_info = pos; | ||
511 | elems->wmm_info_len = elen; | ||
512 | } else if (pos[4] == 1) { | ||
513 | elems->wmm_param = pos; | ||
514 | elems->wmm_param_len = elen; | ||
515 | } | ||
516 | } | ||
517 | } | ||
518 | break; | ||
519 | case WLAN_EID_RSN: | ||
520 | elems->rsn = pos; | ||
521 | elems->rsn_len = elen; | ||
522 | break; | ||
523 | case WLAN_EID_ERP_INFO: | ||
524 | elems->erp_info = pos; | ||
525 | elems->erp_info_len = elen; | ||
526 | break; | ||
527 | case WLAN_EID_EXT_SUPP_RATES: | ||
528 | elems->ext_supp_rates = pos; | ||
529 | elems->ext_supp_rates_len = elen; | ||
530 | break; | ||
531 | case WLAN_EID_HT_CAPABILITY: | ||
532 | elems->ht_cap_elem = pos; | ||
533 | elems->ht_cap_elem_len = elen; | ||
534 | break; | ||
535 | case WLAN_EID_HT_EXTRA_INFO: | ||
536 | elems->ht_info_elem = pos; | ||
537 | elems->ht_info_elem_len = elen; | ||
538 | break; | ||
539 | case WLAN_EID_MESH_ID: | ||
540 | elems->mesh_id = pos; | ||
541 | elems->mesh_id_len = elen; | ||
542 | break; | ||
543 | case WLAN_EID_MESH_CONFIG: | ||
544 | elems->mesh_config = pos; | ||
545 | elems->mesh_config_len = elen; | ||
546 | break; | ||
547 | case WLAN_EID_PEER_LINK: | ||
548 | elems->peer_link = pos; | ||
549 | elems->peer_link_len = elen; | ||
550 | break; | ||
551 | case WLAN_EID_PREQ: | ||
552 | elems->preq = pos; | ||
553 | elems->preq_len = elen; | ||
554 | break; | ||
555 | case WLAN_EID_PREP: | ||
556 | elems->prep = pos; | ||
557 | elems->prep_len = elen; | ||
558 | break; | ||
559 | case WLAN_EID_PERR: | ||
560 | elems->perr = pos; | ||
561 | elems->perr_len = elen; | ||
562 | break; | ||
563 | case WLAN_EID_CHANNEL_SWITCH: | ||
564 | elems->ch_switch_elem = pos; | ||
565 | elems->ch_switch_elem_len = elen; | ||
566 | break; | ||
567 | case WLAN_EID_QUIET: | ||
568 | if (!elems->quiet_elem) { | ||
569 | elems->quiet_elem = pos; | ||
570 | elems->quiet_elem_len = elen; | ||
571 | } | ||
572 | elems->num_of_quiet_elem++; | ||
573 | break; | ||
574 | case WLAN_EID_COUNTRY: | ||
575 | elems->country_elem = pos; | ||
576 | elems->country_elem_len = elen; | ||
577 | break; | ||
578 | case WLAN_EID_PWR_CONSTRAINT: | ||
579 | elems->pwr_constr_elem = pos; | ||
580 | elems->pwr_constr_elem_len = elen; | ||
581 | break; | ||
582 | default: | ||
583 | break; | ||
584 | } | ||
585 | |||
586 | left -= elen; | ||
587 | pos += elen; | ||
588 | } | ||
589 | } | ||
590 | |||
591 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | ||
592 | { | ||
593 | struct ieee80211_local *local = sdata->local; | ||
594 | struct ieee80211_tx_queue_params qparam; | ||
595 | int i; | ||
596 | |||
597 | if (!local->ops->conf_tx) | ||
598 | return; | ||
599 | |||
600 | memset(&qparam, 0, sizeof(qparam)); | ||
601 | |||
602 | qparam.aifs = 2; | ||
603 | |||
604 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
605 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
606 | qparam.cw_min = 31; | ||
607 | else | ||
608 | qparam.cw_min = 15; | ||
609 | |||
610 | qparam.cw_max = 1023; | ||
611 | qparam.txop = 0; | ||
612 | |||
613 | for (i = 0; i < local_to_hw(local)->queues; i++) | ||
614 | local->ops->conf_tx(local_to_hw(local), i, &qparam); | ||
615 | } | ||
616 | |||
617 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | ||
618 | int encrypt) | ||
619 | { | ||
620 | skb->dev = sdata->local->mdev; | ||
621 | skb_set_mac_header(skb, 0); | ||
622 | skb_set_network_header(skb, 0); | ||
623 | skb_set_transport_header(skb, 0); | ||
624 | |||
625 | skb->iif = sdata->dev->ifindex; | ||
626 | skb->do_not_encrypt = !encrypt; | ||
627 | |||
628 | dev_queue_xmit(skb); | ||
629 | } | ||
630 | |||
631 | int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | ||
632 | { | ||
633 | int ret = -EINVAL; | ||
634 | struct ieee80211_channel *chan; | ||
635 | struct ieee80211_local *local = sdata->local; | ||
636 | |||
637 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
638 | |||
639 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
640 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
642 | printk(KERN_DEBUG "%s: IBSS not allowed on frequency " | ||
643 | "%d MHz\n", sdata->dev->name, chan->center_freq); | ||
644 | return ret; | ||
645 | } | ||
646 | local->oper_channel = chan; | ||
647 | |||
648 | if (local->sw_scanning || local->hw_scanning) | ||
649 | ret = 0; | ||
650 | else | ||
651 | ret = ieee80211_hw_config(local); | ||
652 | |||
653 | rate_control_clear(local); | ||
654 | } | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | ||
660 | enum ieee80211_band band) | ||
661 | { | ||
662 | struct ieee80211_supported_band *sband; | ||
663 | struct ieee80211_rate *bitrates; | ||
664 | u64 mandatory_rates; | ||
665 | enum ieee80211_rate_flags mandatory_flag; | ||
666 | int i; | ||
667 | |||
668 | sband = local->hw.wiphy->bands[band]; | ||
669 | if (!sband) { | ||
670 | WARN_ON(1); | ||
671 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
672 | } | ||
673 | |||
674 | if (band == IEEE80211_BAND_2GHZ) | ||
675 | mandatory_flag = IEEE80211_RATE_MANDATORY_B; | ||
676 | else | ||
677 | mandatory_flag = IEEE80211_RATE_MANDATORY_A; | ||
678 | |||
679 | bitrates = sband->bitrates; | ||
680 | mandatory_rates = 0; | ||
681 | for (i = 0; i < sband->n_bitrates; i++) | ||
682 | if (bitrates[i].flags & mandatory_flag) | ||
683 | mandatory_rates |= BIT(i); | ||
684 | return mandatory_rates; | ||
685 | } | ||
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 5c2bf0a3d4db..376c84987e4f 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -228,11 +228,10 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
228 | return -1; | 228 | return -1; |
229 | 229 | ||
230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
231 | 231 | if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) | |
232 | if (skb->len < 8 + hdrlen) | ||
233 | return -1; | 232 | return -1; |
234 | 233 | ||
235 | len = skb->len - hdrlen - 8; | 234 | len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; |
236 | 235 | ||
237 | keyidx = skb->data[hdrlen + 3] >> 6; | 236 | keyidx = skb->data[hdrlen + 3] >> 6; |
238 | 237 | ||
@@ -292,9 +291,10 @@ u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | |||
292 | ieee80211_rx_result | 291 | ieee80211_rx_result |
293 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | 292 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) |
294 | { | 293 | { |
295 | if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && | 294 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
296 | ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || | 295 | |
297 | (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) | 296 | if (!ieee80211_is_data(hdr->frame_control) && |
297 | !ieee80211_is_auth(hdr->frame_control)) | ||
298 | return RX_CONTINUE; | 298 | return RX_CONTINUE; |
299 | 299 | ||
300 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 300 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { |
@@ -303,7 +303,7 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | |||
303 | } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { | 303 | } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { |
304 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); | 304 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); |
305 | /* remove ICV */ | 305 | /* remove ICV */ |
306 | skb_trim(rx->skb, rx->skb->len - 4); | 306 | skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); |
307 | } | 307 | } |
308 | 308 | ||
309 | return RX_CONTINUE; | 309 | return RX_CONTINUE; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 34fa8ed1e784..7e0d53abde24 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -27,22 +27,19 @@ | |||
27 | #include "aes_ccm.h" | 27 | #include "aes_ccm.h" |
28 | 28 | ||
29 | 29 | ||
30 | static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr, | 30 | static int ieee80211_set_encryption(struct ieee80211_sub_if_data *sdata, u8 *sta_addr, |
31 | int idx, int alg, int remove, | 31 | int idx, int alg, int remove, |
32 | int set_tx_key, const u8 *_key, | 32 | int set_tx_key, const u8 *_key, |
33 | size_t key_len) | 33 | size_t key_len) |
34 | { | 34 | { |
35 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 35 | struct ieee80211_local *local = sdata->local; |
36 | struct sta_info *sta; | 36 | struct sta_info *sta; |
37 | struct ieee80211_key *key; | 37 | struct ieee80211_key *key; |
38 | struct ieee80211_sub_if_data *sdata; | ||
39 | int err; | 38 | int err; |
40 | 39 | ||
41 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
42 | |||
43 | if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { | 40 | if (idx < 0 || idx >= NUM_DEFAULT_KEYS) { |
44 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", | 41 | printk(KERN_DEBUG "%s: set_encrypt - invalid idx=%d\n", |
45 | dev->name, idx); | 42 | sdata->dev->name, idx); |
46 | return -EINVAL; | 43 | return -EINVAL; |
47 | } | 44 | } |
48 | 45 | ||
@@ -125,13 +122,13 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev, | |||
125 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) | 122 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) |
126 | return -EOPNOTSUPP; | 123 | return -EOPNOTSUPP; |
127 | 124 | ||
128 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 125 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
129 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 126 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
130 | int ret = ieee80211_sta_set_extra_ie(dev, extra, data->length); | 127 | int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); |
131 | if (ret) | 128 | if (ret) |
132 | return ret; | 129 | return ret; |
133 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 130 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
134 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 131 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
135 | return 0; | 132 | return 0; |
136 | } | 133 | } |
137 | 134 | ||
@@ -276,21 +273,21 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, | |||
276 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 273 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
277 | int type; | 274 | int type; |
278 | 275 | ||
279 | if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN) | 276 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
280 | return -EOPNOTSUPP; | 277 | return -EOPNOTSUPP; |
281 | 278 | ||
282 | switch (*mode) { | 279 | switch (*mode) { |
283 | case IW_MODE_INFRA: | 280 | case IW_MODE_INFRA: |
284 | type = IEEE80211_IF_TYPE_STA; | 281 | type = NL80211_IFTYPE_STATION; |
285 | break; | 282 | break; |
286 | case IW_MODE_ADHOC: | 283 | case IW_MODE_ADHOC: |
287 | type = IEEE80211_IF_TYPE_IBSS; | 284 | type = NL80211_IFTYPE_ADHOC; |
288 | break; | 285 | break; |
289 | case IW_MODE_REPEAT: | 286 | case IW_MODE_REPEAT: |
290 | type = IEEE80211_IF_TYPE_WDS; | 287 | type = NL80211_IFTYPE_WDS; |
291 | break; | 288 | break; |
292 | case IW_MODE_MONITOR: | 289 | case IW_MODE_MONITOR: |
293 | type = IEEE80211_IF_TYPE_MNTR; | 290 | type = NL80211_IFTYPE_MONITOR; |
294 | break; | 291 | break; |
295 | default: | 292 | default: |
296 | return -EINVAL; | 293 | return -EINVAL; |
@@ -308,22 +305,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, | |||
308 | 305 | ||
309 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 306 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
310 | switch (sdata->vif.type) { | 307 | switch (sdata->vif.type) { |
311 | case IEEE80211_IF_TYPE_AP: | 308 | case NL80211_IFTYPE_AP: |
312 | *mode = IW_MODE_MASTER; | 309 | *mode = IW_MODE_MASTER; |
313 | break; | 310 | break; |
314 | case IEEE80211_IF_TYPE_STA: | 311 | case NL80211_IFTYPE_STATION: |
315 | *mode = IW_MODE_INFRA; | 312 | *mode = IW_MODE_INFRA; |
316 | break; | 313 | break; |
317 | case IEEE80211_IF_TYPE_IBSS: | 314 | case NL80211_IFTYPE_ADHOC: |
318 | *mode = IW_MODE_ADHOC; | 315 | *mode = IW_MODE_ADHOC; |
319 | break; | 316 | break; |
320 | case IEEE80211_IF_TYPE_MNTR: | 317 | case NL80211_IFTYPE_MONITOR: |
321 | *mode = IW_MODE_MONITOR; | 318 | *mode = IW_MODE_MONITOR; |
322 | break; | 319 | break; |
323 | case IEEE80211_IF_TYPE_WDS: | 320 | case NL80211_IFTYPE_WDS: |
324 | *mode = IW_MODE_REPEAT; | 321 | *mode = IW_MODE_REPEAT; |
325 | break; | 322 | break; |
326 | case IEEE80211_IF_TYPE_VLAN: | 323 | case NL80211_IFTYPE_AP_VLAN: |
327 | *mode = IW_MODE_SECOND; /* FIXME */ | 324 | *mode = IW_MODE_SECOND; /* FIXME */ |
328 | break; | 325 | break; |
329 | default: | 326 | default: |
@@ -333,60 +330,31 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, | |||
333 | return 0; | 330 | return 0; |
334 | } | 331 | } |
335 | 332 | ||
336 | int ieee80211_set_freq(struct net_device *dev, int freqMHz) | ||
337 | { | ||
338 | int ret = -EINVAL; | ||
339 | struct ieee80211_channel *chan; | ||
340 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
341 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
342 | |||
343 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); | ||
344 | |||
345 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { | ||
346 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && | ||
347 | chan->flags & IEEE80211_CHAN_NO_IBSS) { | ||
348 | printk(KERN_DEBUG "%s: IBSS not allowed on frequency " | ||
349 | "%d MHz\n", dev->name, chan->center_freq); | ||
350 | return ret; | ||
351 | } | ||
352 | local->oper_channel = chan; | ||
353 | |||
354 | if (local->sta_sw_scanning || local->sta_hw_scanning) | ||
355 | ret = 0; | ||
356 | else | ||
357 | ret = ieee80211_hw_config(local); | ||
358 | |||
359 | rate_control_clear(local); | ||
360 | } | ||
361 | |||
362 | return ret; | ||
363 | } | ||
364 | |||
365 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, | 333 | static int ieee80211_ioctl_siwfreq(struct net_device *dev, |
366 | struct iw_request_info *info, | 334 | struct iw_request_info *info, |
367 | struct iw_freq *freq, char *extra) | 335 | struct iw_freq *freq, char *extra) |
368 | { | 336 | { |
369 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 337 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
370 | 338 | ||
371 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) | 339 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
372 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; | 340 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_CHANNEL_SEL; |
373 | 341 | ||
374 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ | 342 | /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ |
375 | if (freq->e == 0) { | 343 | if (freq->e == 0) { |
376 | if (freq->m < 0) { | 344 | if (freq->m < 0) { |
377 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) | 345 | if (sdata->vif.type == NL80211_IFTYPE_STATION) |
378 | sdata->u.sta.flags |= | 346 | sdata->u.sta.flags |= |
379 | IEEE80211_STA_AUTO_CHANNEL_SEL; | 347 | IEEE80211_STA_AUTO_CHANNEL_SEL; |
380 | return 0; | 348 | return 0; |
381 | } else | 349 | } else |
382 | return ieee80211_set_freq(dev, | 350 | return ieee80211_set_freq(sdata, |
383 | ieee80211_channel_to_frequency(freq->m)); | 351 | ieee80211_channel_to_frequency(freq->m)); |
384 | } else { | 352 | } else { |
385 | int i, div = 1000000; | 353 | int i, div = 1000000; |
386 | for (i = 0; i < freq->e; i++) | 354 | for (i = 0; i < freq->e; i++) |
387 | div /= 10; | 355 | div /= 10; |
388 | if (div > 0) | 356 | if (div > 0) |
389 | return ieee80211_set_freq(dev, freq->m / div); | 357 | return ieee80211_set_freq(sdata, freq->m / div); |
390 | else | 358 | else |
391 | return -EINVAL; | 359 | return -EINVAL; |
392 | } | 360 | } |
@@ -418,8 +386,8 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
418 | len--; | 386 | len--; |
419 | 387 | ||
420 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 388 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
421 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 389 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
422 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 390 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
423 | int ret; | 391 | int ret; |
424 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { | 392 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { |
425 | if (len > IEEE80211_MAX_SSID_LEN) | 393 | if (len > IEEE80211_MAX_SSID_LEN) |
@@ -432,14 +400,14 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev, | |||
432 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; | 400 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_SSID_SEL; |
433 | else | 401 | else |
434 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; | 402 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_SSID_SEL; |
435 | ret = ieee80211_sta_set_ssid(dev, ssid, len); | 403 | ret = ieee80211_sta_set_ssid(sdata, ssid, len); |
436 | if (ret) | 404 | if (ret) |
437 | return ret; | 405 | return ret; |
438 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 406 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
439 | return 0; | 407 | return 0; |
440 | } | 408 | } |
441 | 409 | ||
442 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 410 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
443 | memcpy(sdata->u.ap.ssid, ssid, len); | 411 | memcpy(sdata->u.ap.ssid, ssid, len); |
444 | memset(sdata->u.ap.ssid + len, 0, | 412 | memset(sdata->u.ap.ssid + len, 0, |
445 | IEEE80211_MAX_SSID_LEN - len); | 413 | IEEE80211_MAX_SSID_LEN - len); |
@@ -458,9 +426,9 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
458 | 426 | ||
459 | struct ieee80211_sub_if_data *sdata; | 427 | struct ieee80211_sub_if_data *sdata; |
460 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 428 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
461 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 429 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
462 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 430 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
463 | int res = ieee80211_sta_get_ssid(dev, ssid, &len); | 431 | int res = ieee80211_sta_get_ssid(sdata, ssid, &len); |
464 | if (res == 0) { | 432 | if (res == 0) { |
465 | data->length = len; | 433 | data->length = len; |
466 | data->flags = 1; | 434 | data->flags = 1; |
@@ -469,7 +437,7 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, | |||
469 | return res; | 437 | return res; |
470 | } | 438 | } |
471 | 439 | ||
472 | if (sdata->vif.type == IEEE80211_IF_TYPE_AP) { | 440 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
473 | len = sdata->u.ap.ssid_len; | 441 | len = sdata->u.ap.ssid_len; |
474 | if (len > IW_ESSID_MAX_SIZE) | 442 | if (len > IW_ESSID_MAX_SIZE) |
475 | len = IW_ESSID_MAX_SIZE; | 443 | len = IW_ESSID_MAX_SIZE; |
@@ -489,8 +457,8 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
489 | struct ieee80211_sub_if_data *sdata; | 457 | struct ieee80211_sub_if_data *sdata; |
490 | 458 | ||
491 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 459 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
492 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 460 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
493 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 461 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
494 | int ret; | 462 | int ret; |
495 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { | 463 | if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) { |
496 | memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data, | 464 | memcpy(sdata->u.sta.bssid, (u8 *) &ap_addr->sa_data, |
@@ -504,12 +472,12 @@ static int ieee80211_ioctl_siwap(struct net_device *dev, | |||
504 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; | 472 | sdata->u.sta.flags |= IEEE80211_STA_AUTO_BSSID_SEL; |
505 | else | 473 | else |
506 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; | 474 | sdata->u.sta.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; |
507 | ret = ieee80211_sta_set_bssid(dev, (u8 *) &ap_addr->sa_data); | 475 | ret = ieee80211_sta_set_bssid(sdata, (u8 *) &ap_addr->sa_data); |
508 | if (ret) | 476 | if (ret) |
509 | return ret; | 477 | return ret; |
510 | ieee80211_sta_req_auth(dev, &sdata->u.sta); | 478 | ieee80211_sta_req_auth(sdata, &sdata->u.sta); |
511 | return 0; | 479 | return 0; |
512 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | 480 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
513 | /* | 481 | /* |
514 | * If it is necessary to update the WDS peer address | 482 | * If it is necessary to update the WDS peer address |
515 | * while the interface is running, then we need to do | 483 | * while the interface is running, then we need to do |
@@ -537,10 +505,10 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
537 | struct ieee80211_sub_if_data *sdata; | 505 | struct ieee80211_sub_if_data *sdata; |
538 | 506 | ||
539 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 507 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
540 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 508 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
541 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 509 | sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
542 | if (sdata->u.sta.state == IEEE80211_ASSOCIATED || | 510 | if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATED || |
543 | sdata->u.sta.state == IEEE80211_IBSS_JOINED) { | 511 | sdata->u.sta.state == IEEE80211_STA_MLME_IBSS_JOINED) { |
544 | ap_addr->sa_family = ARPHRD_ETHER; | 512 | ap_addr->sa_family = ARPHRD_ETHER; |
545 | memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); | 513 | memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN); |
546 | return 0; | 514 | return 0; |
@@ -548,7 +516,7 @@ static int ieee80211_ioctl_giwap(struct net_device *dev, | |||
548 | memset(&ap_addr->sa_data, 0, ETH_ALEN); | 516 | memset(&ap_addr->sa_data, 0, ETH_ALEN); |
549 | return 0; | 517 | return 0; |
550 | } | 518 | } |
551 | } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) { | 519 | } else if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
552 | ap_addr->sa_family = ARPHRD_ETHER; | 520 | ap_addr->sa_family = ARPHRD_ETHER; |
553 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); | 521 | memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN); |
554 | return 0; | 522 | return 0; |
@@ -570,10 +538,10 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, | |||
570 | if (!netif_running(dev)) | 538 | if (!netif_running(dev)) |
571 | return -ENETDOWN; | 539 | return -ENETDOWN; |
572 | 540 | ||
573 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 541 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
574 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS && | 542 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
575 | sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT && | 543 | sdata->vif.type != NL80211_IFTYPE_MESH_POINT && |
576 | sdata->vif.type != IEEE80211_IF_TYPE_AP) | 544 | sdata->vif.type != NL80211_IFTYPE_AP) |
577 | return -EOPNOTSUPP; | 545 | return -EOPNOTSUPP; |
578 | 546 | ||
579 | /* if SSID was specified explicitly then use that */ | 547 | /* if SSID was specified explicitly then use that */ |
@@ -584,7 +552,7 @@ static int ieee80211_ioctl_siwscan(struct net_device *dev, | |||
584 | ssid_len = req->essid_len; | 552 | ssid_len = req->essid_len; |
585 | } | 553 | } |
586 | 554 | ||
587 | return ieee80211_sta_req_scan(dev, ssid, ssid_len); | 555 | return ieee80211_request_scan(sdata, ssid, ssid_len); |
588 | } | 556 | } |
589 | 557 | ||
590 | 558 | ||
@@ -594,11 +562,14 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
594 | { | 562 | { |
595 | int res; | 563 | int res; |
596 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 564 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
565 | struct ieee80211_sub_if_data *sdata; | ||
566 | |||
567 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
597 | 568 | ||
598 | if (local->sta_sw_scanning || local->sta_hw_scanning) | 569 | if (local->sw_scanning || local->hw_scanning) |
599 | return -EAGAIN; | 570 | return -EAGAIN; |
600 | 571 | ||
601 | res = ieee80211_sta_scan_results(dev, info, extra, data->length); | 572 | res = ieee80211_scan_results(local, info, extra, data->length); |
602 | if (res >= 0) { | 573 | if (res >= 0) { |
603 | data->length = res; | 574 | data->length = res; |
604 | return 0; | 575 | return 0; |
@@ -656,7 +627,7 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, | |||
656 | 627 | ||
657 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 628 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
658 | 629 | ||
659 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 630 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
660 | return -EOPNOTSUPP; | 631 | return -EOPNOTSUPP; |
661 | 632 | ||
662 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 633 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
@@ -665,8 +636,8 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, | |||
665 | 636 | ||
666 | sta = sta_info_get(local, sdata->u.sta.bssid); | 637 | sta = sta_info_get(local, sdata->u.sta.bssid); |
667 | 638 | ||
668 | if (sta && sta->txrate_idx < sband->n_bitrates) | 639 | if (sta && sta->last_txrate_idx < sband->n_bitrates) |
669 | rate->value = sband->bitrates[sta->txrate_idx].bitrate; | 640 | rate->value = sband->bitrates[sta->last_txrate_idx].bitrate; |
670 | else | 641 | else |
671 | rate->value = 0; | 642 | rate->value = 0; |
672 | 643 | ||
@@ -887,17 +858,17 @@ static int ieee80211_ioctl_siwmlme(struct net_device *dev, | |||
887 | struct iw_mlme *mlme = (struct iw_mlme *) extra; | 858 | struct iw_mlme *mlme = (struct iw_mlme *) extra; |
888 | 859 | ||
889 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 860 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
890 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA && | 861 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
891 | sdata->vif.type != IEEE80211_IF_TYPE_IBSS) | 862 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
892 | return -EINVAL; | 863 | return -EINVAL; |
893 | 864 | ||
894 | switch (mlme->cmd) { | 865 | switch (mlme->cmd) { |
895 | case IW_MLME_DEAUTH: | 866 | case IW_MLME_DEAUTH: |
896 | /* TODO: mlme->addr.sa_data */ | 867 | /* TODO: mlme->addr.sa_data */ |
897 | return ieee80211_sta_deauthenticate(dev, mlme->reason_code); | 868 | return ieee80211_sta_deauthenticate(sdata, mlme->reason_code); |
898 | case IW_MLME_DISASSOC: | 869 | case IW_MLME_DISASSOC: |
899 | /* TODO: mlme->addr.sa_data */ | 870 | /* TODO: mlme->addr.sa_data */ |
900 | return ieee80211_sta_disassociate(dev, mlme->reason_code); | 871 | return ieee80211_sta_disassociate(sdata, mlme->reason_code); |
901 | default: | 872 | default: |
902 | return -EOPNOTSUPP; | 873 | return -EOPNOTSUPP; |
903 | } | 874 | } |
@@ -938,7 +909,7 @@ static int ieee80211_ioctl_siwencode(struct net_device *dev, | |||
938 | } | 909 | } |
939 | 910 | ||
940 | return ieee80211_set_encryption( | 911 | return ieee80211_set_encryption( |
941 | dev, bcaddr, | 912 | sdata, bcaddr, |
942 | idx, alg, remove, | 913 | idx, alg, remove, |
943 | !sdata->default_key, | 914 | !sdata->default_key, |
944 | keybuf, erq->length); | 915 | keybuf, erq->length); |
@@ -983,7 +954,7 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
983 | erq->length = sdata->keys[idx]->conf.keylen; | 954 | erq->length = sdata->keys[idx]->conf.keylen; |
984 | erq->flags |= IW_ENCODE_ENABLED; | 955 | erq->flags |= IW_ENCODE_ENABLED; |
985 | 956 | ||
986 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | 957 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
987 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 958 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
988 | switch (ifsta->auth_alg) { | 959 | switch (ifsta->auth_alg) { |
989 | case WLAN_AUTH_OPEN: | 960 | case WLAN_AUTH_OPEN: |
@@ -1057,7 +1028,7 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
1057 | sdata->drop_unencrypted = !!data->value; | 1028 | sdata->drop_unencrypted = !!data->value; |
1058 | break; | 1029 | break; |
1059 | case IW_AUTH_PRIVACY_INVOKED: | 1030 | case IW_AUTH_PRIVACY_INVOKED: |
1060 | if (sdata->vif.type != IEEE80211_IF_TYPE_STA) | 1031 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1061 | ret = -EINVAL; | 1032 | ret = -EINVAL; |
1062 | else { | 1033 | else { |
1063 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; | 1034 | sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED; |
@@ -1072,8 +1043,8 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev, | |||
1072 | } | 1043 | } |
1073 | break; | 1044 | break; |
1074 | case IW_AUTH_80211_AUTH_ALG: | 1045 | case IW_AUTH_80211_AUTH_ALG: |
1075 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1046 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1076 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1047 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1077 | sdata->u.sta.auth_algs = data->value; | 1048 | sdata->u.sta.auth_algs = data->value; |
1078 | else | 1049 | else |
1079 | ret = -EOPNOTSUPP; | 1050 | ret = -EOPNOTSUPP; |
@@ -1095,8 +1066,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev | |||
1095 | 1066 | ||
1096 | rcu_read_lock(); | 1067 | rcu_read_lock(); |
1097 | 1068 | ||
1098 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1069 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1099 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1070 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1100 | sta = sta_info_get(local, sdata->u.sta.bssid); | 1071 | sta = sta_info_get(local, sdata->u.sta.bssid); |
1101 | if (!sta) { | 1072 | if (!sta) { |
1102 | wstats->discard.fragment = 0; | 1073 | wstats->discard.fragment = 0; |
@@ -1126,8 +1097,8 @@ static int ieee80211_ioctl_giwauth(struct net_device *dev, | |||
1126 | 1097 | ||
1127 | switch (data->flags & IW_AUTH_INDEX) { | 1098 | switch (data->flags & IW_AUTH_INDEX) { |
1128 | case IW_AUTH_80211_AUTH_ALG: | 1099 | case IW_AUTH_80211_AUTH_ALG: |
1129 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA || | 1100 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
1130 | sdata->vif.type == IEEE80211_IF_TYPE_IBSS) | 1101 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
1131 | data->value = sdata->u.sta.auth_algs; | 1102 | data->value = sdata->u.sta.auth_algs; |
1132 | else | 1103 | else |
1133 | ret = -EOPNOTSUPP; | 1104 | ret = -EOPNOTSUPP; |
@@ -1184,7 +1155,7 @@ static int ieee80211_ioctl_siwencodeext(struct net_device *dev, | |||
1184 | } else | 1155 | } else |
1185 | idx--; | 1156 | idx--; |
1186 | 1157 | ||
1187 | return ieee80211_set_encryption(dev, ext->addr.sa_data, idx, alg, | 1158 | return ieee80211_set_encryption(sdata, ext->addr.sa_data, idx, alg, |
1188 | remove, | 1159 | remove, |
1189 | ext->ext_flags & | 1160 | ext->ext_flags & |
1190 | IW_ENCODE_EXT_SET_TX_KEY, | 1161 | IW_ENCODE_EXT_SET_TX_KEY, |
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 4310e2f65661..c703f8b44e92 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -39,7 +39,7 @@ static unsigned int classify_1d(struct sk_buff *skb) | |||
39 | return skb->priority - 256; | 39 | return skb->priority - 256; |
40 | 40 | ||
41 | switch (skb->protocol) { | 41 | switch (skb->protocol) { |
42 | case __constant_htons(ETH_P_IP): | 42 | case htons(ETH_P_IP): |
43 | dscp = ip_hdr(skb)->tos & 0xfc; | 43 | dscp = ip_hdr(skb)->tos & 0xfc; |
44 | break; | 44 | break; |
45 | 45 | ||
@@ -47,8 +47,6 @@ static unsigned int classify_1d(struct sk_buff *skb) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (dscp & 0x1c) | ||
51 | return 0; | ||
52 | return dscp >> 5; | 50 | return dscp >> 5; |
53 | } | 51 | } |
54 | 52 | ||
@@ -212,7 +210,7 @@ int ieee80211_ht_agg_queue_add(struct ieee80211_local *local, | |||
212 | DECLARE_MAC_BUF(mac); | 210 | DECLARE_MAC_BUF(mac); |
213 | printk(KERN_DEBUG "allocated aggregation queue" | 211 | printk(KERN_DEBUG "allocated aggregation queue" |
214 | " %d tid %d addr %s pool=0x%lX\n", | 212 | " %d tid %d addr %s pool=0x%lX\n", |
215 | i, tid, print_mac(mac, sta->addr), | 213 | i, tid, print_mac(mac, sta->sta.addr), |
216 | local->queue_pool[0]); | 214 | local->queue_pool[0]); |
217 | } | 215 | } |
218 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 216 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index 04de28c071a6..bc62f28a4d3d 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * IEEE 802.11 driver (80211.o) - QoS datatypes | ||
3 | * Copyright 2004, Instant802 Networks, Inc. | 2 | * Copyright 2004, Instant802 Networks, Inc. |
4 | * Copyright 2005, Devicescape Software, Inc. | 3 | * Copyright 2005, Devicescape Software, Inc. |
5 | * | 4 | * |
@@ -14,8 +13,6 @@ | |||
14 | #include <linux/netdevice.h> | 13 | #include <linux/netdevice.h> |
15 | #include "ieee80211_i.h" | 14 | #include "ieee80211_i.h" |
16 | 15 | ||
17 | #define QOS_CONTROL_LEN 2 | ||
18 | |||
19 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 | 16 | #define QOS_CONTROL_ACK_POLICY_NORMAL 0 |
20 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 | 17 | #define QOS_CONTROL_ACK_POLICY_NOACK 1 |
21 | 18 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 2f33df0dcccf..37ae9a959f63 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -127,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
127 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 127 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
128 | return RX_DROP_UNUSABLE; | 128 | return RX_DROP_UNUSABLE; |
129 | 129 | ||
130 | mac80211_ev_michael_mic_failure(rx->dev, rx->key->conf.keyidx, | 130 | mac80211_ev_michael_mic_failure(rx->sdata, rx->key->conf.keyidx, |
131 | (void *) skb->data); | 131 | (void *) skb->data); |
132 | return RX_DROP_UNUSABLE; | 132 | return RX_DROP_UNUSABLE; |
133 | } | 133 | } |
@@ -256,7 +256,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
256 | 256 | ||
257 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 257 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
258 | key, skb->data + hdrlen, | 258 | key, skb->data + hdrlen, |
259 | skb->len - hdrlen, rx->sta->addr, | 259 | skb->len - hdrlen, rx->sta->sta.addr, |
260 | hdr->addr1, hwaccel, rx->queue, | 260 | hdr->addr1, hwaccel, rx->queue, |
261 | &rx->tkip_iv32, | 261 | &rx->tkip_iv32, |
262 | &rx->tkip_iv16); | 262 | &rx->tkip_iv16); |