diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
commit | 28f49d8fec19833672a6a813bfde0068fee50bc9 (patch) | |
tree | 6905c5cabc063e44b891ae0af5b5d7cce69e6e71 /net/mac80211 | |
parent | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (diff) | |
parent | ff28bd94e307c67abb1bccda5d3a9018bd798e08 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/Kconfig | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 14 | ||||
-rw-r--r-- | net/mac80211/key.h | 37 | ||||
-rw-r--r-- | net/mac80211/main.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 207 | ||||
-rw-r--r-- | net/mac80211/rx.c | 7 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 1 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 40 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 30 | ||||
-rw-r--r-- | net/mac80211/tx.c | 204 | ||||
-rw-r--r-- | net/mac80211/wep.c | 39 | ||||
-rw-r--r-- | net/mac80211/wext.c | 50 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 20 |
13 files changed, 410 insertions, 243 deletions
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 590e00b2766c..0d3661d9b6a0 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -150,7 +150,7 @@ config MAC80211_LOWTX_FRAME_DUMP | |||
150 | If unsure, say N and insert the debugging code | 150 | If unsure, say N and insert the debugging code |
151 | you require into the driver you are debugging. | 151 | you require into the driver you are debugging. |
152 | 152 | ||
153 | config TKIP_DEBUG | 153 | config MAC80211_TKIP_DEBUG |
154 | bool "TKIP debugging" | 154 | bool "TKIP debugging" |
155 | depends on MAC80211_DEBUG | 155 | depends on MAC80211_DEBUG |
156 | 156 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 14fccf16b80f..af352c05c983 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/wireless.h> | 26 | #include <net/wireless.h> |
27 | #include <net/iw_handler.h> | ||
27 | #include "key.h" | 28 | #include "key.h" |
28 | #include "sta_info.h" | 29 | #include "sta_info.h" |
29 | 30 | ||
@@ -790,6 +791,10 @@ struct ieee802_11_elems { | |||
790 | u8 *preq; | 791 | u8 *preq; |
791 | u8 *prep; | 792 | u8 *prep; |
792 | u8 *perr; | 793 | u8 *perr; |
794 | u8 *ch_switch_elem; | ||
795 | u8 *country_elem; | ||
796 | u8 *pwr_constr_elem; | ||
797 | u8 *quiet_elem; /* first quite element */ | ||
793 | 798 | ||
794 | /* length of them, respectively */ | 799 | /* length of them, respectively */ |
795 | u8 ssid_len; | 800 | u8 ssid_len; |
@@ -814,6 +819,11 @@ struct ieee802_11_elems { | |||
814 | u8 preq_len; | 819 | u8 preq_len; |
815 | u8 prep_len; | 820 | u8 prep_len; |
816 | u8 perr_len; | 821 | u8 perr_len; |
822 | u8 ch_switch_elem_len; | ||
823 | u8 country_elem_len; | ||
824 | u8 pwr_constr_elem_len; | ||
825 | u8 quiet_elem_len; | ||
826 | u8 num_of_quiet_elem; /* can be more the one */ | ||
817 | }; | 827 | }; |
818 | 828 | ||
819 | static inline struct ieee80211_local *hw_to_local( | 829 | static inline struct ieee80211_local *hw_to_local( |
@@ -867,7 +877,9 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid); | |||
867 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); | 877 | int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len); |
868 | void ieee80211_sta_req_auth(struct net_device *dev, | 878 | void ieee80211_sta_req_auth(struct net_device *dev, |
869 | struct ieee80211_if_sta *ifsta); | 879 | struct ieee80211_if_sta *ifsta); |
870 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len); | 880 | int ieee80211_sta_scan_results(struct net_device *dev, |
881 | struct iw_request_info *info, | ||
882 | char *buf, size_t len); | ||
871 | ieee80211_rx_result ieee80211_sta_rx_scan( | 883 | ieee80211_rx_result ieee80211_sta_rx_scan( |
872 | struct net_device *dev, struct sk_buff *skb, | 884 | struct net_device *dev, struct sk_buff *skb, |
873 | struct ieee80211_rx_status *rx_status); | 885 | struct ieee80211_rx_status *rx_status); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index a0f774aafa45..425816e0996c 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -16,31 +16,18 @@ | |||
16 | #include <linux/rcupdate.h> | 16 | #include <linux/rcupdate.h> |
17 | #include <net/mac80211.h> | 17 | #include <net/mac80211.h> |
18 | 18 | ||
19 | /* ALG_TKIP | 19 | #define WEP_IV_LEN 4 |
20 | * struct ieee80211_key::key is encoded as a 256-bit (32 byte) data block: | 20 | #define WEP_ICV_LEN 4 |
21 | * Temporal Encryption Key (128 bits) | 21 | #define ALG_TKIP_KEY_LEN 32 |
22 | * Temporal Authenticator Tx MIC Key (64 bits) | 22 | #define ALG_CCMP_KEY_LEN 16 |
23 | * Temporal Authenticator Rx MIC Key (64 bits) | 23 | #define CCMP_HDR_LEN 8 |
24 | */ | 24 | #define CCMP_MIC_LEN 8 |
25 | 25 | #define CCMP_TK_LEN 16 | |
26 | #define WEP_IV_LEN 4 | 26 | #define CCMP_PN_LEN 6 |
27 | #define WEP_ICV_LEN 4 | 27 | #define TKIP_IV_LEN 8 |
28 | 28 | #define TKIP_ICV_LEN 4 | |
29 | #define ALG_TKIP_KEY_LEN 32 | 29 | |
30 | /* Starting offsets for each key */ | 30 | #define NUM_RX_DATA_QUEUES 17 |
31 | #define ALG_TKIP_TEMP_ENCR_KEY 0 | ||
32 | #define ALG_TKIP_TEMP_AUTH_TX_MIC_KEY 16 | ||
33 | #define ALG_TKIP_TEMP_AUTH_RX_MIC_KEY 24 | ||
34 | #define TKIP_IV_LEN 8 | ||
35 | #define TKIP_ICV_LEN 4 | ||
36 | |||
37 | #define ALG_CCMP_KEY_LEN 16 | ||
38 | #define CCMP_HDR_LEN 8 | ||
39 | #define CCMP_MIC_LEN 8 | ||
40 | #define CCMP_TK_LEN 16 | ||
41 | #define CCMP_PN_LEN 6 | ||
42 | |||
43 | #define NUM_RX_DATA_QUEUES 17 | ||
44 | 31 | ||
45 | struct ieee80211_local; | 32 | struct ieee80211_local; |
46 | struct ieee80211_sub_if_data; | 33 | struct ieee80211_sub_if_data; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 5c5396edad32..b661ee5bb824 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1691,7 +1691,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
1691 | list_add_tail(&sdata->list, &local->interfaces); | 1691 | list_add_tail(&sdata->list, &local->interfaces); |
1692 | 1692 | ||
1693 | name = wiphy_dev(local->hw.wiphy)->driver->name; | 1693 | name = wiphy_dev(local->hw.wiphy)->driver->name; |
1694 | local->hw.workqueue = create_singlethread_workqueue(name); | 1694 | local->hw.workqueue = create_freezeable_workqueue(name); |
1695 | if (!local->hw.workqueue) { | 1695 | if (!local->hw.workqueue) { |
1696 | result = -ENOMEM; | 1696 | result = -ENOMEM; |
1697 | goto fail_workqueue; | 1697 | goto fail_workqueue; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 55659a730dc1..7b4d4d46843b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -204,6 +204,25 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
204 | elems->perr = pos; | 204 | elems->perr = pos; |
205 | elems->perr_len = elen; | 205 | elems->perr_len = elen; |
206 | break; | 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; | ||
207 | default: | 226 | default: |
208 | break; | 227 | break; |
209 | } | 228 | } |
@@ -1701,6 +1720,71 @@ void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) | |||
1701 | } | 1720 | } |
1702 | } | 1721 | } |
1703 | 1722 | ||
1723 | static void ieee80211_send_refuse_measurement_request(struct net_device *dev, | ||
1724 | struct ieee80211_msrment_ie *request_ie, | ||
1725 | const u8 *da, const u8 *bssid, | ||
1726 | u8 dialog_token) | ||
1727 | { | ||
1728 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1729 | struct sk_buff *skb; | ||
1730 | struct ieee80211_mgmt *msr_report; | ||
1731 | |||
1732 | skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + | ||
1733 | sizeof(struct ieee80211_msrment_ie)); | ||
1734 | |||
1735 | if (!skb) { | ||
1736 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
1737 | "measurement report frame\n", dev->name); | ||
1738 | return; | ||
1739 | } | ||
1740 | |||
1741 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1742 | msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); | ||
1743 | memset(msr_report, 0, 24); | ||
1744 | memcpy(msr_report->da, da, ETH_ALEN); | ||
1745 | memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN); | ||
1746 | memcpy(msr_report->bssid, bssid, ETH_ALEN); | ||
1747 | msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | ||
1748 | IEEE80211_STYPE_ACTION); | ||
1749 | |||
1750 | skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); | ||
1751 | msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; | ||
1752 | msr_report->u.action.u.measurement.action_code = | ||
1753 | WLAN_ACTION_SPCT_MSR_RPRT; | ||
1754 | msr_report->u.action.u.measurement.dialog_token = dialog_token; | ||
1755 | |||
1756 | msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; | ||
1757 | msr_report->u.action.u.measurement.length = | ||
1758 | sizeof(struct ieee80211_msrment_ie); | ||
1759 | |||
1760 | memset(&msr_report->u.action.u.measurement.msr_elem, 0, | ||
1761 | sizeof(struct ieee80211_msrment_ie)); | ||
1762 | msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; | ||
1763 | msr_report->u.action.u.measurement.msr_elem.mode |= | ||
1764 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | ||
1765 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | ||
1766 | |||
1767 | ieee80211_sta_tx(dev, skb, 0); | ||
1768 | } | ||
1769 | |||
1770 | static void ieee80211_sta_process_measurement_req(struct net_device *dev, | ||
1771 | struct ieee80211_mgmt *mgmt, | ||
1772 | size_t len) | ||
1773 | { | ||
1774 | /* | ||
1775 | * Ignoring measurement request is spec violation. | ||
1776 | * Mandatory measurements must be reported optional | ||
1777 | * measurements might be refused or reported incapable | ||
1778 | * For now just refuse | ||
1779 | * TODO: Answer basic measurement as unmeasured | ||
1780 | */ | ||
1781 | ieee80211_send_refuse_measurement_request(dev, | ||
1782 | &mgmt->u.action.u.measurement.msr_elem, | ||
1783 | mgmt->sa, mgmt->bssid, | ||
1784 | mgmt->u.action.u.measurement.dialog_token); | ||
1785 | } | ||
1786 | |||
1787 | |||
1704 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | 1788 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, |
1705 | struct ieee80211_if_sta *ifsta, | 1789 | struct ieee80211_if_sta *ifsta, |
1706 | struct ieee80211_mgmt *mgmt, | 1790 | struct ieee80211_mgmt *mgmt, |
@@ -1753,11 +1837,12 @@ static void ieee80211_rx_mgmt_auth(struct net_device *dev, | |||
1753 | auth_transaction, status_code); | 1837 | auth_transaction, status_code); |
1754 | 1838 | ||
1755 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { | 1839 | if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) { |
1756 | /* IEEE 802.11 standard does not require authentication in IBSS | 1840 | /* |
1841 | * IEEE 802.11 standard does not require authentication in IBSS | ||
1757 | * networks and most implementations do not seem to use it. | 1842 | * networks and most implementations do not seem to use it. |
1758 | * However, try to reply to authentication attempts if someone | 1843 | * However, try to reply to authentication attempts if someone |
1759 | * has actually implemented this. | 1844 | * has actually implemented this. |
1760 | * TODO: Could implement shared key authentication. */ | 1845 | */ |
1761 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { | 1846 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) { |
1762 | printk(KERN_DEBUG "%s: unexpected IBSS authentication " | 1847 | printk(KERN_DEBUG "%s: unexpected IBSS authentication " |
1763 | "frame (alg=%d transaction=%d)\n", | 1848 | "frame (alg=%d transaction=%d)\n", |
@@ -3025,11 +3110,24 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev, | |||
3025 | struct ieee80211_rx_status *rx_status) | 3110 | struct ieee80211_rx_status *rx_status) |
3026 | { | 3111 | { |
3027 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3112 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3113 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3028 | 3114 | ||
3029 | if (len < IEEE80211_MIN_ACTION_SIZE) | 3115 | if (len < IEEE80211_MIN_ACTION_SIZE) |
3030 | return; | 3116 | return; |
3031 | 3117 | ||
3032 | switch (mgmt->u.action.category) { | 3118 | switch (mgmt->u.action.category) { |
3119 | case WLAN_CATEGORY_SPECTRUM_MGMT: | ||
3120 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | ||
3121 | break; | ||
3122 | switch (mgmt->u.action.u.chan_switch.action_code) { | ||
3123 | case WLAN_ACTION_SPCT_MSR_REQ: | ||
3124 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
3125 | sizeof(mgmt->u.action.u.measurement))) | ||
3126 | break; | ||
3127 | ieee80211_sta_process_measurement_req(dev, mgmt, len); | ||
3128 | break; | ||
3129 | } | ||
3130 | break; | ||
3033 | case WLAN_CATEGORY_BACK: | 3131 | case WLAN_CATEGORY_BACK: |
3034 | switch (mgmt->u.action.u.addba_req.action_code) { | 3132 | switch (mgmt->u.action.u.addba_req.action_code) { |
3035 | case WLAN_ACTION_ADDBA_REQ: | 3133 | case WLAN_ACTION_ADDBA_REQ: |
@@ -3173,33 +3271,32 @@ ieee80211_sta_rx_scan(struct net_device *dev, struct sk_buff *skb, | |||
3173 | struct ieee80211_rx_status *rx_status) | 3271 | struct ieee80211_rx_status *rx_status) |
3174 | { | 3272 | { |
3175 | struct ieee80211_mgmt *mgmt; | 3273 | struct ieee80211_mgmt *mgmt; |
3176 | u16 fc; | 3274 | __le16 fc; |
3177 | 3275 | ||
3178 | if (skb->len < 2) | 3276 | if (skb->len < 2) |
3179 | return RX_DROP_UNUSABLE; | 3277 | return RX_DROP_UNUSABLE; |
3180 | 3278 | ||
3181 | mgmt = (struct ieee80211_mgmt *) skb->data; | 3279 | mgmt = (struct ieee80211_mgmt *) skb->data; |
3182 | fc = le16_to_cpu(mgmt->frame_control); | 3280 | fc = mgmt->frame_control; |
3183 | 3281 | ||
3184 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) | 3282 | if (ieee80211_is_ctl(fc)) |
3185 | return RX_CONTINUE; | 3283 | return RX_CONTINUE; |
3186 | 3284 | ||
3187 | if (skb->len < 24) | 3285 | if (skb->len < 24) |
3188 | return RX_DROP_MONITOR; | 3286 | return RX_DROP_MONITOR; |
3189 | 3287 | ||
3190 | if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { | 3288 | if (ieee80211_is_probe_resp(fc)) { |
3191 | if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP) { | 3289 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, skb->len, rx_status); |
3192 | ieee80211_rx_mgmt_probe_resp(dev, mgmt, | 3290 | dev_kfree_skb(skb); |
3193 | skb->len, rx_status); | 3291 | return RX_QUEUED; |
3194 | dev_kfree_skb(skb); | ||
3195 | return RX_QUEUED; | ||
3196 | } else if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { | ||
3197 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, | ||
3198 | rx_status); | ||
3199 | dev_kfree_skb(skb); | ||
3200 | return RX_QUEUED; | ||
3201 | } | ||
3202 | } | 3292 | } |
3293 | |||
3294 | if (ieee80211_is_beacon(fc)) { | ||
3295 | ieee80211_rx_mgmt_beacon(dev, mgmt, skb->len, rx_status); | ||
3296 | dev_kfree_skb(skb); | ||
3297 | return RX_QUEUED; | ||
3298 | } | ||
3299 | |||
3203 | return RX_CONTINUE; | 3300 | return RX_CONTINUE; |
3204 | } | 3301 | } |
3205 | 3302 | ||
@@ -3777,7 +3874,7 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
3777 | { | 3874 | { |
3778 | struct sk_buff *skb; | 3875 | struct sk_buff *skb; |
3779 | struct ieee80211_hdr *nullfunc; | 3876 | struct ieee80211_hdr *nullfunc; |
3780 | u16 fc; | 3877 | __le16 fc; |
3781 | 3878 | ||
3782 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); | 3879 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); |
3783 | if (!skb) { | 3880 | if (!skb) { |
@@ -3789,11 +3886,11 @@ static void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
3789 | 3886 | ||
3790 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); | 3887 | nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); |
3791 | memset(nullfunc, 0, 24); | 3888 | memset(nullfunc, 0, 24); |
3792 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | | 3889 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | |
3793 | IEEE80211_FCTL_TODS; | 3890 | IEEE80211_FCTL_TODS); |
3794 | if (powersave) | 3891 | if (powersave) |
3795 | fc |= IEEE80211_FCTL_PM; | 3892 | fc |= cpu_to_le16(IEEE80211_FCTL_PM); |
3796 | nullfunc->frame_control = cpu_to_le16(fc); | 3893 | nullfunc->frame_control = fc; |
3797 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); | 3894 | memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); |
3798 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 3895 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); |
3799 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); | 3896 | memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); |
@@ -4087,6 +4184,7 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len) | |||
4087 | 4184 | ||
4088 | static char * | 4185 | static char * |
4089 | ieee80211_sta_scan_result(struct net_device *dev, | 4186 | ieee80211_sta_scan_result(struct net_device *dev, |
4187 | struct iw_request_info *info, | ||
4090 | struct ieee80211_sta_bss *bss, | 4188 | struct ieee80211_sta_bss *bss, |
4091 | char *current_ev, char *end_buf) | 4189 | char *current_ev, char *end_buf) |
4092 | { | 4190 | { |
@@ -4101,7 +4199,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4101 | iwe.cmd = SIOCGIWAP; | 4199 | iwe.cmd = SIOCGIWAP; |
4102 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; | 4200 | iwe.u.ap_addr.sa_family = ARPHRD_ETHER; |
4103 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 4201 | memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); |
4104 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4202 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4105 | IW_EV_ADDR_LEN); | 4203 | IW_EV_ADDR_LEN); |
4106 | 4204 | ||
4107 | memset(&iwe, 0, sizeof(iwe)); | 4205 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4109,13 +4207,13 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4109 | if (bss_mesh_cfg(bss)) { | 4207 | if (bss_mesh_cfg(bss)) { |
4110 | iwe.u.data.length = bss_mesh_id_len(bss); | 4208 | iwe.u.data.length = bss_mesh_id_len(bss); |
4111 | iwe.u.data.flags = 1; | 4209 | iwe.u.data.flags = 1; |
4112 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4210 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4113 | bss_mesh_id(bss)); | 4211 | &iwe, bss_mesh_id(bss)); |
4114 | } else { | 4212 | } else { |
4115 | iwe.u.data.length = bss->ssid_len; | 4213 | iwe.u.data.length = bss->ssid_len; |
4116 | iwe.u.data.flags = 1; | 4214 | iwe.u.data.flags = 1; |
4117 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4215 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4118 | bss->ssid); | 4216 | &iwe, bss->ssid); |
4119 | } | 4217 | } |
4120 | 4218 | ||
4121 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) | 4219 | if (bss->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS) |
@@ -4128,22 +4226,22 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4128 | iwe.u.mode = IW_MODE_MASTER; | 4226 | iwe.u.mode = IW_MODE_MASTER; |
4129 | else | 4227 | else |
4130 | iwe.u.mode = IW_MODE_ADHOC; | 4228 | iwe.u.mode = IW_MODE_ADHOC; |
4131 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4229 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, |
4132 | IW_EV_UINT_LEN); | 4230 | &iwe, IW_EV_UINT_LEN); |
4133 | } | 4231 | } |
4134 | 4232 | ||
4135 | memset(&iwe, 0, sizeof(iwe)); | 4233 | memset(&iwe, 0, sizeof(iwe)); |
4136 | iwe.cmd = SIOCGIWFREQ; | 4234 | iwe.cmd = SIOCGIWFREQ; |
4137 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); | 4235 | iwe.u.freq.m = ieee80211_frequency_to_channel(bss->freq); |
4138 | iwe.u.freq.e = 0; | 4236 | iwe.u.freq.e = 0; |
4139 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4237 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4140 | IW_EV_FREQ_LEN); | 4238 | IW_EV_FREQ_LEN); |
4141 | 4239 | ||
4142 | memset(&iwe, 0, sizeof(iwe)); | 4240 | memset(&iwe, 0, sizeof(iwe)); |
4143 | iwe.cmd = SIOCGIWFREQ; | 4241 | iwe.cmd = SIOCGIWFREQ; |
4144 | iwe.u.freq.m = bss->freq; | 4242 | iwe.u.freq.m = bss->freq; |
4145 | iwe.u.freq.e = 6; | 4243 | iwe.u.freq.e = 6; |
4146 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4244 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4147 | IW_EV_FREQ_LEN); | 4245 | IW_EV_FREQ_LEN); |
4148 | memset(&iwe, 0, sizeof(iwe)); | 4246 | memset(&iwe, 0, sizeof(iwe)); |
4149 | iwe.cmd = IWEVQUAL; | 4247 | iwe.cmd = IWEVQUAL; |
@@ -4151,7 +4249,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4151 | iwe.u.qual.level = bss->signal; | 4249 | iwe.u.qual.level = bss->signal; |
4152 | iwe.u.qual.noise = bss->noise; | 4250 | iwe.u.qual.noise = bss->noise; |
4153 | iwe.u.qual.updated = local->wstats_flags; | 4251 | iwe.u.qual.updated = local->wstats_flags; |
4154 | current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, | 4252 | current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, |
4155 | IW_EV_QUAL_LEN); | 4253 | IW_EV_QUAL_LEN); |
4156 | 4254 | ||
4157 | memset(&iwe, 0, sizeof(iwe)); | 4255 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4161,35 +4259,36 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4161 | else | 4259 | else |
4162 | iwe.u.data.flags = IW_ENCODE_DISABLED; | 4260 | iwe.u.data.flags = IW_ENCODE_DISABLED; |
4163 | iwe.u.data.length = 0; | 4261 | iwe.u.data.length = 0; |
4164 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, ""); | 4262 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4263 | &iwe, ""); | ||
4165 | 4264 | ||
4166 | if (bss && bss->wpa_ie) { | 4265 | if (bss && bss->wpa_ie) { |
4167 | memset(&iwe, 0, sizeof(iwe)); | 4266 | memset(&iwe, 0, sizeof(iwe)); |
4168 | iwe.cmd = IWEVGENIE; | 4267 | iwe.cmd = IWEVGENIE; |
4169 | iwe.u.data.length = bss->wpa_ie_len; | 4268 | iwe.u.data.length = bss->wpa_ie_len; |
4170 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4269 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4171 | bss->wpa_ie); | 4270 | &iwe, bss->wpa_ie); |
4172 | } | 4271 | } |
4173 | 4272 | ||
4174 | if (bss && bss->rsn_ie) { | 4273 | if (bss && bss->rsn_ie) { |
4175 | memset(&iwe, 0, sizeof(iwe)); | 4274 | memset(&iwe, 0, sizeof(iwe)); |
4176 | iwe.cmd = IWEVGENIE; | 4275 | iwe.cmd = IWEVGENIE; |
4177 | iwe.u.data.length = bss->rsn_ie_len; | 4276 | iwe.u.data.length = bss->rsn_ie_len; |
4178 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4277 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4179 | bss->rsn_ie); | 4278 | &iwe, bss->rsn_ie); |
4180 | } | 4279 | } |
4181 | 4280 | ||
4182 | if (bss && bss->ht_ie) { | 4281 | if (bss && bss->ht_ie) { |
4183 | memset(&iwe, 0, sizeof(iwe)); | 4282 | memset(&iwe, 0, sizeof(iwe)); |
4184 | iwe.cmd = IWEVGENIE; | 4283 | iwe.cmd = IWEVGENIE; |
4185 | iwe.u.data.length = bss->ht_ie_len; | 4284 | iwe.u.data.length = bss->ht_ie_len; |
4186 | current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, | 4285 | current_ev = iwe_stream_add_point(info, current_ev, end_buf, |
4187 | bss->ht_ie); | 4286 | &iwe, bss->ht_ie); |
4188 | } | 4287 | } |
4189 | 4288 | ||
4190 | if (bss && bss->supp_rates_len > 0) { | 4289 | if (bss && bss->supp_rates_len > 0) { |
4191 | /* display all supported rates in readable format */ | 4290 | /* display all supported rates in readable format */ |
4192 | char *p = current_ev + IW_EV_LCP_LEN; | 4291 | char *p = current_ev + iwe_stream_lcp_len(info); |
4193 | int i; | 4292 | int i; |
4194 | 4293 | ||
4195 | memset(&iwe, 0, sizeof(iwe)); | 4294 | memset(&iwe, 0, sizeof(iwe)); |
@@ -4200,7 +4299,7 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4200 | for (i = 0; i < bss->supp_rates_len; i++) { | 4299 | for (i = 0; i < bss->supp_rates_len; i++) { |
4201 | iwe.u.bitrate.value = ((bss->supp_rates[i] & | 4300 | iwe.u.bitrate.value = ((bss->supp_rates[i] & |
4202 | 0x7f) * 500000); | 4301 | 0x7f) * 500000); |
4203 | p = iwe_stream_add_value(current_ev, p, | 4302 | p = iwe_stream_add_value(info, current_ev, p, |
4204 | end_buf, &iwe, IW_EV_PARAM_LEN); | 4303 | end_buf, &iwe, IW_EV_PARAM_LEN); |
4205 | } | 4304 | } |
4206 | current_ev = p; | 4305 | current_ev = p; |
@@ -4214,7 +4313,8 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4214 | iwe.cmd = IWEVCUSTOM; | 4313 | iwe.cmd = IWEVCUSTOM; |
4215 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); | 4314 | sprintf(buf, "tsf=%016llx", (unsigned long long)(bss->timestamp)); |
4216 | iwe.u.data.length = strlen(buf); | 4315 | iwe.u.data.length = strlen(buf); |
4217 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4316 | current_ev = iwe_stream_add_point(info, current_ev, |
4317 | end_buf, | ||
4218 | &iwe, buf); | 4318 | &iwe, buf); |
4219 | kfree(buf); | 4319 | kfree(buf); |
4220 | } | 4320 | } |
@@ -4229,31 +4329,36 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4229 | iwe.cmd = IWEVCUSTOM; | 4329 | iwe.cmd = IWEVCUSTOM; |
4230 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 4330 | sprintf(buf, "Mesh network (version %d)", cfg[0]); |
4231 | iwe.u.data.length = strlen(buf); | 4331 | iwe.u.data.length = strlen(buf); |
4232 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4332 | current_ev = iwe_stream_add_point(info, current_ev, |
4333 | end_buf, | ||
4233 | &iwe, buf); | 4334 | &iwe, buf); |
4234 | sprintf(buf, "Path Selection Protocol ID: " | 4335 | sprintf(buf, "Path Selection Protocol ID: " |
4235 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | 4336 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], |
4236 | cfg[4]); | 4337 | cfg[4]); |
4237 | iwe.u.data.length = strlen(buf); | 4338 | iwe.u.data.length = strlen(buf); |
4238 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4339 | current_ev = iwe_stream_add_point(info, current_ev, |
4340 | end_buf, | ||
4239 | &iwe, buf); | 4341 | &iwe, buf); |
4240 | sprintf(buf, "Path Selection Metric ID: " | 4342 | sprintf(buf, "Path Selection Metric ID: " |
4241 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | 4343 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], |
4242 | cfg[8]); | 4344 | cfg[8]); |
4243 | iwe.u.data.length = strlen(buf); | 4345 | iwe.u.data.length = strlen(buf); |
4244 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4346 | current_ev = iwe_stream_add_point(info, current_ev, |
4347 | end_buf, | ||
4245 | &iwe, buf); | 4348 | &iwe, buf); |
4246 | sprintf(buf, "Congestion Control Mode ID: " | 4349 | sprintf(buf, "Congestion Control Mode ID: " |
4247 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | 4350 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], |
4248 | cfg[11], cfg[12]); | 4351 | cfg[11], cfg[12]); |
4249 | iwe.u.data.length = strlen(buf); | 4352 | iwe.u.data.length = strlen(buf); |
4250 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4353 | current_ev = iwe_stream_add_point(info, current_ev, |
4354 | end_buf, | ||
4251 | &iwe, buf); | 4355 | &iwe, buf); |
4252 | sprintf(buf, "Channel Precedence: " | 4356 | sprintf(buf, "Channel Precedence: " |
4253 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | 4357 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], |
4254 | cfg[15], cfg[16]); | 4358 | cfg[15], cfg[16]); |
4255 | iwe.u.data.length = strlen(buf); | 4359 | iwe.u.data.length = strlen(buf); |
4256 | current_ev = iwe_stream_add_point(current_ev, end_buf, | 4360 | current_ev = iwe_stream_add_point(info, current_ev, |
4361 | end_buf, | ||
4257 | &iwe, buf); | 4362 | &iwe, buf); |
4258 | kfree(buf); | 4363 | kfree(buf); |
4259 | } | 4364 | } |
@@ -4263,7 +4368,9 @@ ieee80211_sta_scan_result(struct net_device *dev, | |||
4263 | } | 4368 | } |
4264 | 4369 | ||
4265 | 4370 | ||
4266 | int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) | 4371 | int ieee80211_sta_scan_results(struct net_device *dev, |
4372 | struct iw_request_info *info, | ||
4373 | char *buf, size_t len) | ||
4267 | { | 4374 | { |
4268 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 4375 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
4269 | char *current_ev = buf; | 4376 | char *current_ev = buf; |
@@ -4276,8 +4383,8 @@ int ieee80211_sta_scan_results(struct net_device *dev, char *buf, size_t len) | |||
4276 | spin_unlock_bh(&local->sta_bss_lock); | 4383 | spin_unlock_bh(&local->sta_bss_lock); |
4277 | return -E2BIG; | 4384 | return -E2BIG; |
4278 | } | 4385 | } |
4279 | current_ev = ieee80211_sta_scan_result(dev, bss, current_ev, | 4386 | current_ev = ieee80211_sta_scan_result(dev, info, bss, |
4280 | end_buf); | 4387 | current_ev, end_buf); |
4281 | } | 4388 | } |
4282 | spin_unlock_bh(&local->sta_bss_lock); | 4389 | spin_unlock_bh(&local->sta_bss_lock); |
4283 | return current_ev - buf; | 4390 | return current_ev - buf; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c32a0bcd53b7..8962d1355f04 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -61,7 +61,7 @@ static inline int should_drop_frame(struct ieee80211_rx_status *status, | |||
61 | int present_fcs_len, | 61 | int present_fcs_len, |
62 | int radiotap_len) | 62 | int radiotap_len) |
63 | { | 63 | { |
64 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 64 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
65 | 65 | ||
66 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 66 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) |
67 | return 1; | 67 | return 1; |
@@ -2123,7 +2123,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2123 | struct tid_ampdu_rx *tid_agg_rx; | 2123 | struct tid_ampdu_rx *tid_agg_rx; |
2124 | u16 sc; | 2124 | u16 sc; |
2125 | u16 mpdu_seq_num; | 2125 | u16 mpdu_seq_num; |
2126 | u8 ret = 0, *qc; | 2126 | u8 ret = 0; |
2127 | int tid; | 2127 | int tid; |
2128 | 2128 | ||
2129 | sta = sta_info_get(local, hdr->addr2); | 2129 | sta = sta_info_get(local, hdr->addr2); |
@@ -2135,8 +2135,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2135 | if (!ieee80211_is_data_qos(hdr->frame_control)) | 2135 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
2136 | goto end_reorder; | 2136 | goto end_reorder; |
2137 | 2137 | ||
2138 | qc = ieee80211_get_qos_ctl(hdr); | 2138 | tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK; |
2139 | tid = qc[0] & QOS_CONTROL_TID_MASK; | ||
2140 | 2139 | ||
2141 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 2140 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2142 | goto end_reorder; | 2141 | goto end_reorder; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index c24770cb02c5..b3c733162fc1 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -235,6 +235,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
235 | return NULL; | 235 | return NULL; |
236 | 236 | ||
237 | spin_lock_init(&sta->lock); | 237 | spin_lock_init(&sta->lock); |
238 | spin_lock_init(&sta->flaglock); | ||
238 | 239 | ||
239 | memcpy(sta->addr, addr, ETH_ALEN); | 240 | memcpy(sta->addr, addr, ETH_ALEN); |
240 | sta->local = local; | 241 | sta->local = local; |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 95753f860acf..fd228c198e31 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -164,6 +164,7 @@ struct sta_ampdu_mlme { | |||
164 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), | 164 | * @aid: STA's unique AID (1..2007, 0 = not assigned yet), |
165 | * only used in AP (and IBSS?) mode | 165 | * only used in AP (and IBSS?) mode |
166 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 166 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
167 | * @flaglock: spinlock for flags accesses | ||
167 | * @ps_tx_buf: buffer of frames to transmit to this station | 168 | * @ps_tx_buf: buffer of frames to transmit to this station |
168 | * when it leaves power saving state | 169 | * when it leaves power saving state |
169 | * @tx_filtered: buffer of frames we already tried to transmit | 170 | * @tx_filtered: buffer of frames we already tried to transmit |
@@ -186,6 +187,7 @@ struct sta_info { | |||
186 | struct rate_control_ref *rate_ctrl; | 187 | struct rate_control_ref *rate_ctrl; |
187 | void *rate_ctrl_priv; | 188 | void *rate_ctrl_priv; |
188 | spinlock_t lock; | 189 | spinlock_t lock; |
190 | spinlock_t flaglock; | ||
189 | struct ieee80211_ht_info ht_info; | 191 | struct ieee80211_ht_info ht_info; |
190 | u64 supp_rates[IEEE80211_NUM_BANDS]; | 192 | u64 supp_rates[IEEE80211_NUM_BANDS]; |
191 | u8 addr[ETH_ALEN]; | 193 | u8 addr[ETH_ALEN]; |
@@ -198,7 +200,10 @@ struct sta_info { | |||
198 | */ | 200 | */ |
199 | u8 pin_status; | 201 | u8 pin_status; |
200 | 202 | ||
201 | /* frequently updated information, locked with lock spinlock */ | 203 | /* |
204 | * frequently updated, locked with own spinlock (flaglock), | ||
205 | * use the accessors defined below | ||
206 | */ | ||
202 | u32 flags; | 207 | u32 flags; |
203 | 208 | ||
204 | /* | 209 | /* |
@@ -293,34 +298,41 @@ static inline enum plink_state sta_plink_state(struct sta_info *sta) | |||
293 | 298 | ||
294 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | 299 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) |
295 | { | 300 | { |
296 | spin_lock_bh(&sta->lock); | 301 | unsigned long irqfl; |
302 | |||
303 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
297 | sta->flags |= flags; | 304 | sta->flags |= flags; |
298 | spin_unlock_bh(&sta->lock); | 305 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
299 | } | 306 | } |
300 | 307 | ||
301 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) | 308 | static inline void clear_sta_flags(struct sta_info *sta, const u32 flags) |
302 | { | 309 | { |
303 | spin_lock_bh(&sta->lock); | 310 | unsigned long irqfl; |
311 | |||
312 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
304 | sta->flags &= ~flags; | 313 | sta->flags &= ~flags; |
305 | spin_unlock_bh(&sta->lock); | 314 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
306 | } | 315 | } |
307 | 316 | ||
308 | static inline void set_and_clear_sta_flags(struct sta_info *sta, | 317 | static inline void set_and_clear_sta_flags(struct sta_info *sta, |
309 | const u32 set, const u32 clear) | 318 | const u32 set, const u32 clear) |
310 | { | 319 | { |
311 | spin_lock_bh(&sta->lock); | 320 | unsigned long irqfl; |
321 | |||
322 | spin_lock_irqsave(&sta->flaglock, irqfl); | ||
312 | sta->flags |= set; | 323 | sta->flags |= set; |
313 | sta->flags &= ~clear; | 324 | sta->flags &= ~clear; |
314 | spin_unlock_bh(&sta->lock); | 325 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
315 | } | 326 | } |
316 | 327 | ||
317 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) | 328 | static inline u32 test_sta_flags(struct sta_info *sta, const u32 flags) |
318 | { | 329 | { |
319 | u32 ret; | 330 | u32 ret; |
331 | unsigned long irqfl; | ||
320 | 332 | ||
321 | spin_lock_bh(&sta->lock); | 333 | spin_lock_irqsave(&sta->flaglock, irqfl); |
322 | ret = sta->flags & flags; | 334 | ret = sta->flags & flags; |
323 | spin_unlock_bh(&sta->lock); | 335 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
324 | 336 | ||
325 | return ret; | 337 | return ret; |
326 | } | 338 | } |
@@ -329,11 +341,12 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | |||
329 | const u32 flags) | 341 | const u32 flags) |
330 | { | 342 | { |
331 | u32 ret; | 343 | u32 ret; |
344 | unsigned long irqfl; | ||
332 | 345 | ||
333 | spin_lock_bh(&sta->lock); | 346 | spin_lock_irqsave(&sta->flaglock, irqfl); |
334 | ret = sta->flags & flags; | 347 | ret = sta->flags & flags; |
335 | sta->flags &= ~flags; | 348 | sta->flags &= ~flags; |
336 | spin_unlock_bh(&sta->lock); | 349 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
337 | 350 | ||
338 | return ret; | 351 | return ret; |
339 | } | 352 | } |
@@ -341,10 +354,11 @@ static inline u32 test_and_clear_sta_flags(struct sta_info *sta, | |||
341 | static inline u32 get_sta_flags(struct sta_info *sta) | 354 | static inline u32 get_sta_flags(struct sta_info *sta) |
342 | { | 355 | { |
343 | u32 ret; | 356 | u32 ret; |
357 | unsigned long irqfl; | ||
344 | 358 | ||
345 | spin_lock_bh(&sta->lock); | 359 | spin_lock_irqsave(&sta->flaglock, irqfl); |
346 | ret = sta->flags; | 360 | ret = sta->flags; |
347 | spin_unlock_bh(&sta->lock); | 361 | spin_unlock_irqrestore(&sta->flaglock, irqfl); |
348 | 362 | ||
349 | return ret; | 363 | return ret; |
350 | } | 364 | } |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index e710243d82e2..995f7af3d25e 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -164,10 +164,10 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
164 | iv16 = data[2] | (data[0] << 8); | 164 | iv16 = data[2] | (data[0] << 8); |
165 | iv32 = get_unaligned_le32(&data[4]); | 165 | iv32 = get_unaligned_le32(&data[4]); |
166 | 166 | ||
167 | tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 167 | tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
168 | ctx = &key->u.tkip.tx; | 168 | ctx = &key->u.tkip.tx; |
169 | 169 | ||
170 | #ifdef CONFIG_TKIP_DEBUG | 170 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
171 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | 171 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", |
172 | iv16, iv32); | 172 | iv16, iv32); |
173 | 173 | ||
@@ -177,7 +177,7 @@ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | |||
177 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | 177 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " |
178 | "fragmented packet\n"); | 178 | "fragmented packet\n"); |
179 | } | 179 | } |
180 | #endif /* CONFIG_TKIP_DEBUG */ | 180 | #endif |
181 | 181 | ||
182 | /* Update the p1k only when the iv16 in the packet wraps around, this | 182 | /* Update the p1k only when the iv16 in the packet wraps around, this |
183 | * might occur after the wrap around of iv16 in the key in case of | 183 | * might occur after the wrap around of iv16 in the key in case of |
@@ -205,7 +205,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
205 | { | 205 | { |
206 | u8 rc4key[16]; | 206 | u8 rc4key[16]; |
207 | struct tkip_ctx *ctx = &key->u.tkip.tx; | 207 | struct tkip_ctx *ctx = &key->u.tkip.tx; |
208 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 208 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
209 | 209 | ||
210 | /* Calculate per-packet key */ | 210 | /* Calculate per-packet key */ |
211 | if (ctx->iv16 == 0 || !ctx->initialized) | 211 | if (ctx->iv16 == 0 || !ctx->initialized) |
@@ -231,7 +231,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
231 | u32 iv16; | 231 | u32 iv16; |
232 | u8 rc4key[16], keyid, *pos = payload; | 232 | u8 rc4key[16], keyid, *pos = payload; |
233 | int res; | 233 | int res; |
234 | const u8 *tk = &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY]; | 234 | const u8 *tk = &key->conf.key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY]; |
235 | 235 | ||
236 | if (payload_len < 12) | 236 | if (payload_len < 12) |
237 | return -1; | 237 | return -1; |
@@ -240,7 +240,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
240 | keyid = pos[3]; | 240 | keyid = pos[3]; |
241 | iv32 = get_unaligned_le32(pos + 4); | 241 | iv32 = get_unaligned_le32(pos + 4); |
242 | pos += 8; | 242 | pos += 8; |
243 | #ifdef CONFIG_TKIP_DEBUG | 243 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
244 | { | 244 | { |
245 | int i; | 245 | int i; |
246 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); | 246 | printk(KERN_DEBUG "TKIP decrypt: data(len=%zd)", payload_len); |
@@ -250,7 +250,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
250 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", | 250 | printk(KERN_DEBUG "TKIP decrypt: iv16=%04x iv32=%08x\n", |
251 | iv16, iv32); | 251 | iv16, iv32); |
252 | } | 252 | } |
253 | #endif /* CONFIG_TKIP_DEBUG */ | 253 | #endif |
254 | 254 | ||
255 | if (!(keyid & (1 << 5))) | 255 | if (!(keyid & (1 << 5))) |
256 | return TKIP_DECRYPT_NO_EXT_IV; | 256 | return TKIP_DECRYPT_NO_EXT_IV; |
@@ -262,14 +262,14 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
262 | (iv32 < key->u.tkip.rx[queue].iv32 || | 262 | (iv32 < key->u.tkip.rx[queue].iv32 || |
263 | (iv32 == key->u.tkip.rx[queue].iv32 && | 263 | (iv32 == key->u.tkip.rx[queue].iv32 && |
264 | iv16 <= key->u.tkip.rx[queue].iv16))) { | 264 | iv16 <= key->u.tkip.rx[queue].iv16))) { |
265 | #ifdef CONFIG_TKIP_DEBUG | 265 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
266 | DECLARE_MAC_BUF(mac); | 266 | DECLARE_MAC_BUF(mac); |
267 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " | 267 | printk(KERN_DEBUG "TKIP replay detected for RX frame from " |
268 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", | 268 | "%s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x)\n", |
269 | print_mac(mac, ta), | 269 | print_mac(mac, ta), |
270 | iv32, iv16, key->u.tkip.rx[queue].iv32, | 270 | iv32, iv16, key->u.tkip.rx[queue].iv32, |
271 | key->u.tkip.rx[queue].iv16); | 271 | key->u.tkip.rx[queue].iv16); |
272 | #endif /* CONFIG_TKIP_DEBUG */ | 272 | #endif |
273 | return TKIP_DECRYPT_REPLAY; | 273 | return TKIP_DECRYPT_REPLAY; |
274 | } | 274 | } |
275 | 275 | ||
@@ -283,23 +283,23 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
283 | key->u.tkip.rx[queue].iv32 != iv32) { | 283 | key->u.tkip.rx[queue].iv32 != iv32) { |
284 | /* IV16 wrapped around - perform TKIP phase 1 */ | 284 | /* IV16 wrapped around - perform TKIP phase 1 */ |
285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); | 285 | tkip_mixing_phase1(tk, &key->u.tkip.rx[queue], ta, iv32); |
286 | #ifdef CONFIG_TKIP_DEBUG | 286 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
287 | { | 287 | { |
288 | int i; | 288 | int i; |
289 | u8 key_offset = NL80211_TKIP_DATA_OFFSET_ENCR_KEY; | ||
289 | DECLARE_MAC_BUF(mac); | 290 | DECLARE_MAC_BUF(mac); |
290 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s" | 291 | printk(KERN_DEBUG "TKIP decrypt: Phase1 TA=%s" |
291 | " TK=", print_mac(mac, ta)); | 292 | " TK=", print_mac(mac, ta)); |
292 | for (i = 0; i < 16; i++) | 293 | for (i = 0; i < 16; i++) |
293 | printk("%02x ", | 294 | printk("%02x ", |
294 | key->conf.key[ | 295 | key->conf.key[key_offset + i]); |
295 | ALG_TKIP_TEMP_ENCR_KEY + i]); | ||
296 | printk("\n"); | 296 | printk("\n"); |
297 | printk(KERN_DEBUG "TKIP decrypt: P1K="); | 297 | printk(KERN_DEBUG "TKIP decrypt: P1K="); |
298 | for (i = 0; i < 5; i++) | 298 | for (i = 0; i < 5; i++) |
299 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); | 299 | printk("%04x ", key->u.tkip.rx[queue].p1k[i]); |
300 | printk("\n"); | 300 | printk("\n"); |
301 | } | 301 | } |
302 | #endif /* CONFIG_TKIP_DEBUG */ | 302 | #endif |
303 | if (key->local->ops->update_tkip_key && | 303 | if (key->local->ops->update_tkip_key && |
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] = |
@@ -316,7 +316,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
316 | } | 316 | } |
317 | 317 | ||
318 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); | 318 | tkip_mixing_phase2(tk, &key->u.tkip.rx[queue], iv16, rc4key); |
319 | #ifdef CONFIG_TKIP_DEBUG | 319 | #ifdef CONFIG_MAC80211_TKIP_DEBUG |
320 | { | 320 | { |
321 | int i; | 321 | int i; |
322 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); | 322 | printk(KERN_DEBUG "TKIP decrypt: Phase2 rc4key="); |
@@ -324,7 +324,7 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
324 | printk("%02x ", rc4key[i]); | 324 | printk("%02x ", rc4key[i]); |
325 | printk("\n"); | 325 | printk("\n"); |
326 | } | 326 | } |
327 | #endif /* CONFIG_TKIP_DEBUG */ | 327 | #endif |
328 | 328 | ||
329 | res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); | 329 | res = ieee80211_wep_decrypt_data(tfm, rc4key, 16, pos, payload_len - 12); |
330 | done: | 330 | done: |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ce06e791bf43..52ab85c4341b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -52,9 +52,8 @@ static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdat | |||
52 | static void ieee80211_dump_frame(const char *ifname, const char *title, | 52 | static void ieee80211_dump_frame(const char *ifname, const char *title, |
53 | const struct sk_buff *skb) | 53 | const struct sk_buff *skb) |
54 | { | 54 | { |
55 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 55 | const struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
56 | u16 fc; | 56 | unsigned int hdrlen; |
57 | int hdrlen; | ||
58 | DECLARE_MAC_BUF(mac); | 57 | DECLARE_MAC_BUF(mac); |
59 | 58 | ||
60 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); | 59 | printk(KERN_DEBUG "%s: %s (len=%d)", ifname, title, skb->len); |
@@ -63,13 +62,12 @@ static void ieee80211_dump_frame(const char *ifname, const char *title, | |||
63 | return; | 62 | return; |
64 | } | 63 | } |
65 | 64 | ||
66 | fc = le16_to_cpu(hdr->frame_control); | 65 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
67 | hdrlen = ieee80211_get_hdrlen(fc); | ||
68 | if (hdrlen > skb->len) | 66 | if (hdrlen > skb->len) |
69 | hdrlen = skb->len; | 67 | hdrlen = skb->len; |
70 | if (hdrlen >= 4) | 68 | if (hdrlen >= 4) |
71 | printk(" FC=0x%04x DUR=0x%04x", | 69 | printk(" FC=0x%04x DUR=0x%04x", |
72 | fc, le16_to_cpu(hdr->duration_id)); | 70 | le16_to_cpu(hdr->frame_control), le16_to_cpu(hdr->duration_id)); |
73 | if (hdrlen >= 10) | 71 | if (hdrlen >= 10) |
74 | printk(" A1=%s", print_mac(mac, hdr->addr1)); | 72 | printk(" A1=%s", print_mac(mac, hdr->addr1)); |
75 | if (hdrlen >= 16) | 73 | if (hdrlen >= 16) |
@@ -87,8 +85,8 @@ static inline void ieee80211_dump_frame(const char *ifname, const char *title, | |||
87 | } | 85 | } |
88 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ | 86 | #endif /* CONFIG_MAC80211_LOWTX_FRAME_DUMP */ |
89 | 87 | ||
90 | static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | 88 | static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, |
91 | int next_frag_len) | 89 | int next_frag_len) |
92 | { | 90 | { |
93 | int rate, mrate, erp, dur, i; | 91 | int rate, mrate, erp, dur, i; |
94 | struct ieee80211_rate *txrate; | 92 | struct ieee80211_rate *txrate; |
@@ -140,7 +138,7 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
140 | 138 | ||
141 | /* data/mgmt */ | 139 | /* data/mgmt */ |
142 | if (0 /* FIX: data/mgmt during CFP */) | 140 | if (0 /* FIX: data/mgmt during CFP */) |
143 | return 32768; | 141 | return cpu_to_le16(32768); |
144 | 142 | ||
145 | if (group_addr) /* Group address as the destination - no ACK */ | 143 | if (group_addr) /* Group address as the destination - no ACK */ |
146 | return 0; | 144 | return 0; |
@@ -210,7 +208,7 @@ static u16 ieee80211_duration(struct ieee80211_tx_data *tx, int group_addr, | |||
210 | tx->sdata->bss_conf.use_short_preamble); | 208 | tx->sdata->bss_conf.use_short_preamble); |
211 | } | 209 | } |
212 | 210 | ||
213 | return dur; | 211 | return cpu_to_le16(dur); |
214 | } | 212 | } |
215 | 213 | ||
216 | static int inline is_ieee80211_device(struct net_device *dev, | 214 | static int inline is_ieee80211_device(struct net_device *dev, |
@@ -281,7 +279,7 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx) | |||
281 | { | 279 | { |
282 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | 280 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
283 | 281 | ||
284 | if (ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)) >= 24) | 282 | if (ieee80211_hdrlen(hdr->frame_control) >= 24) |
285 | ieee80211_include_sequence(tx->sdata, hdr); | 283 | ieee80211_include_sequence(tx->sdata, hdr); |
286 | 284 | ||
287 | return TX_CONTINUE; | 285 | return TX_CONTINUE; |
@@ -542,9 +540,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
542 | static ieee80211_tx_result | 540 | static ieee80211_tx_result |
543 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | 541 | ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) |
544 | { | 542 | { |
545 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 543 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
546 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
547 | u16 dur; | ||
548 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); | 544 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); |
549 | struct ieee80211_supported_band *sband; | 545 | struct ieee80211_supported_band *sband; |
550 | 546 | ||
@@ -595,21 +591,13 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
595 | /* Transmit data frames using short preambles if the driver supports | 591 | /* Transmit data frames using short preambles if the driver supports |
596 | * short preambles at the selected rate and short preambles are | 592 | * short preambles at the selected rate and short preambles are |
597 | * available on the network at the current point in time. */ | 593 | * available on the network at the current point in time. */ |
598 | if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && | 594 | if (ieee80211_is_data(hdr->frame_control) && |
599 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && | 595 | (sband->bitrates[tx->rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE) && |
600 | tx->sdata->bss_conf.use_short_preamble && | 596 | tx->sdata->bss_conf.use_short_preamble && |
601 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { | 597 | (!tx->sta || test_sta_flags(tx->sta, WLAN_STA_SHORT_PREAMBLE))) { |
602 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; | 598 | info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; |
603 | } | 599 | } |
604 | 600 | ||
605 | /* Setup duration field for the first fragment of the frame. Duration | ||
606 | * for remaining fragments will be updated when they are being sent | ||
607 | * to low-level driver in ieee80211_tx(). */ | ||
608 | dur = ieee80211_duration(tx, is_multicast_ether_addr(hdr->addr1), | ||
609 | (tx->flags & IEEE80211_TX_FRAGMENTED) ? | ||
610 | tx->extra_frag[0]->len : 0); | ||
611 | hdr->duration_id = cpu_to_le16(dur); | ||
612 | |||
613 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | 601 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || |
614 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { | 602 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) { |
615 | struct ieee80211_rate *rate; | 603 | struct ieee80211_rate *rate; |
@@ -647,7 +635,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
647 | static ieee80211_tx_result | 635 | static ieee80211_tx_result |
648 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | 636 | ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) |
649 | { | 637 | { |
650 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx->skb->data; | 638 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; |
651 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; | 639 | size_t hdrlen, per_fragm, num_fragm, payload_len, left; |
652 | struct sk_buff **frags, *first, *frag; | 640 | struct sk_buff **frags, *first, *frag; |
653 | int i; | 641 | int i; |
@@ -670,7 +658,7 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
670 | 658 | ||
671 | first = tx->skb; | 659 | first = tx->skb; |
672 | 660 | ||
673 | hdrlen = ieee80211_get_hdrlen(tx->fc); | 661 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
674 | payload_len = first->len - hdrlen; | 662 | payload_len = first->len - hdrlen; |
675 | per_fragm = frag_threshold - hdrlen - FCS_LEN; | 663 | per_fragm = frag_threshold - hdrlen - FCS_LEN; |
676 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); | 664 | num_fragm = DIV_ROUND_UP(payload_len, per_fragm); |
@@ -711,6 +699,8 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx) | |||
711 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); | 699 | fhdr->seq_ctrl = cpu_to_le16(seq | ((i + 1) & IEEE80211_SCTL_FRAG)); |
712 | copylen = left > per_fragm ? per_fragm : left; | 700 | copylen = left > per_fragm ? per_fragm : left; |
713 | memcpy(skb_put(frag, copylen), pos, copylen); | 701 | memcpy(skb_put(frag, copylen), pos, copylen); |
702 | memcpy(frag->cb, first->cb, sizeof(frag->cb)); | ||
703 | skb_copy_queue_mapping(frag, first); | ||
714 | 704 | ||
715 | pos += copylen; | 705 | pos += copylen; |
716 | left -= copylen; | 706 | left -= copylen; |
@@ -755,6 +745,36 @@ ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) | |||
755 | } | 745 | } |
756 | 746 | ||
757 | static ieee80211_tx_result | 747 | static ieee80211_tx_result |
748 | ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx) | ||
749 | { | ||
750 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; | ||
751 | int next_len, i; | ||
752 | int group_addr = is_multicast_ether_addr(hdr->addr1); | ||
753 | |||
754 | if (!(tx->flags & IEEE80211_TX_FRAGMENTED)) { | ||
755 | hdr->duration_id = ieee80211_duration(tx, group_addr, 0); | ||
756 | return TX_CONTINUE; | ||
757 | } | ||
758 | |||
759 | hdr->duration_id = ieee80211_duration(tx, group_addr, | ||
760 | tx->extra_frag[0]->len); | ||
761 | |||
762 | for (i = 0; i < tx->num_extra_frag; i++) { | ||
763 | if (i + 1 < tx->num_extra_frag) { | ||
764 | next_len = tx->extra_frag[i + 1]->len; | ||
765 | } else { | ||
766 | next_len = 0; | ||
767 | tx->rate_idx = tx->last_frag_rate_idx; | ||
768 | } | ||
769 | |||
770 | hdr = (struct ieee80211_hdr *)tx->extra_frag[i]->data; | ||
771 | hdr->duration_id = ieee80211_duration(tx, 0, next_len); | ||
772 | } | ||
773 | |||
774 | return TX_CONTINUE; | ||
775 | } | ||
776 | |||
777 | static ieee80211_tx_result | ||
758 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) | 778 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
759 | { | 779 | { |
760 | int i; | 780 | int i; |
@@ -788,6 +808,7 @@ static ieee80211_tx_handler ieee80211_tx_handlers[] = | |||
788 | ieee80211_tx_h_fragment, | 808 | ieee80211_tx_h_fragment, |
789 | /* handlers after fragment must be aware of tx info fragmentation! */ | 809 | /* handlers after fragment must be aware of tx info fragmentation! */ |
790 | ieee80211_tx_h_encrypt, | 810 | ieee80211_tx_h_encrypt, |
811 | ieee80211_tx_h_calculate_duration, | ||
791 | ieee80211_tx_h_stats, | 812 | ieee80211_tx_h_stats, |
792 | NULL | 813 | NULL |
793 | }; | 814 | }; |
@@ -1083,13 +1104,46 @@ static int __ieee80211_tx(struct ieee80211_local *local, struct sk_buff *skb, | |||
1083 | return IEEE80211_TX_OK; | 1104 | return IEEE80211_TX_OK; |
1084 | } | 1105 | } |
1085 | 1106 | ||
1107 | /* | ||
1108 | * Invoke TX handlers, return 0 on success and non-zero if the | ||
1109 | * frame was dropped or queued. | ||
1110 | */ | ||
1111 | static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | ||
1112 | { | ||
1113 | struct ieee80211_local *local = tx->local; | ||
1114 | struct sk_buff *skb = tx->skb; | ||
1115 | ieee80211_tx_handler *handler; | ||
1116 | ieee80211_tx_result res = TX_DROP; | ||
1117 | int i; | ||
1118 | |||
1119 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { | ||
1120 | res = (*handler)(tx); | ||
1121 | if (res != TX_CONTINUE) | ||
1122 | break; | ||
1123 | } | ||
1124 | |||
1125 | if (unlikely(res == TX_DROP)) { | ||
1126 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
1127 | dev_kfree_skb(skb); | ||
1128 | for (i = 0; i < tx->num_extra_frag; i++) | ||
1129 | if (tx->extra_frag[i]) | ||
1130 | dev_kfree_skb(tx->extra_frag[i]); | ||
1131 | kfree(tx->extra_frag); | ||
1132 | return -1; | ||
1133 | } else if (unlikely(res == TX_QUEUED)) { | ||
1134 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
1135 | return -1; | ||
1136 | } | ||
1137 | |||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1086 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | 1141 | static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) |
1087 | { | 1142 | { |
1088 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1143 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1089 | struct sta_info *sta; | 1144 | struct sta_info *sta; |
1090 | ieee80211_tx_handler *handler; | ||
1091 | struct ieee80211_tx_data tx; | 1145 | struct ieee80211_tx_data tx; |
1092 | ieee80211_tx_result res = TX_DROP, res_prepare; | 1146 | ieee80211_tx_result res_prepare; |
1093 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1147 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1094 | int ret, i; | 1148 | int ret, i; |
1095 | u16 queue; | 1149 | u16 queue; |
@@ -1118,44 +1172,8 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb) | |||
1118 | tx.channel = local->hw.conf.channel; | 1172 | tx.channel = local->hw.conf.channel; |
1119 | info->band = tx.channel->band; | 1173 | info->band = tx.channel->band; |
1120 | 1174 | ||
1121 | for (handler = ieee80211_tx_handlers; *handler != NULL; | 1175 | if (invoke_tx_handlers(&tx)) |
1122 | handler++) { | 1176 | goto out; |
1123 | res = (*handler)(&tx); | ||
1124 | if (res != TX_CONTINUE) | ||
1125 | break; | ||
1126 | } | ||
1127 | |||
1128 | if (WARN_ON(tx.skb != skb)) | ||
1129 | goto drop; | ||
1130 | |||
1131 | if (unlikely(res == TX_DROP)) { | ||
1132 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
1133 | goto drop; | ||
1134 | } | ||
1135 | |||
1136 | if (unlikely(res == TX_QUEUED)) { | ||
1137 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
1138 | rcu_read_unlock(); | ||
1139 | return 0; | ||
1140 | } | ||
1141 | |||
1142 | if (tx.extra_frag) { | ||
1143 | for (i = 0; i < tx.num_extra_frag; i++) { | ||
1144 | int next_len, dur; | ||
1145 | struct ieee80211_hdr *hdr = | ||
1146 | (struct ieee80211_hdr *) | ||
1147 | tx.extra_frag[i]->data; | ||
1148 | |||
1149 | if (i + 1 < tx.num_extra_frag) { | ||
1150 | next_len = tx.extra_frag[i + 1]->len; | ||
1151 | } else { | ||
1152 | next_len = 0; | ||
1153 | tx.rate_idx = tx.last_frag_rate_idx; | ||
1154 | } | ||
1155 | dur = ieee80211_duration(&tx, 0, next_len); | ||
1156 | hdr->duration_id = cpu_to_le16(dur); | ||
1157 | } | ||
1158 | } | ||
1159 | 1177 | ||
1160 | retry: | 1178 | retry: |
1161 | ret = __ieee80211_tx(local, skb, &tx); | 1179 | ret = __ieee80211_tx(local, skb, &tx); |
@@ -1198,6 +1216,7 @@ retry: | |||
1198 | store->last_frag_rate_ctrl_probe = | 1216 | store->last_frag_rate_ctrl_probe = |
1199 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); | 1217 | !!(tx.flags & IEEE80211_TX_PROBE_LAST_FRAG); |
1200 | } | 1218 | } |
1219 | out: | ||
1201 | rcu_read_unlock(); | 1220 | rcu_read_unlock(); |
1202 | return 0; | 1221 | return 0; |
1203 | 1222 | ||
@@ -1379,7 +1398,8 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1379 | struct ieee80211_tx_info *info; | 1398 | struct ieee80211_tx_info *info; |
1380 | struct ieee80211_sub_if_data *sdata; | 1399 | struct ieee80211_sub_if_data *sdata; |
1381 | int ret = 1, head_need; | 1400 | int ret = 1, head_need; |
1382 | u16 ethertype, hdrlen, meshhdrlen = 0, fc; | 1401 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1402 | __le16 fc; | ||
1383 | struct ieee80211_hdr hdr; | 1403 | struct ieee80211_hdr hdr; |
1384 | struct ieee80211s_hdr mesh_hdr; | 1404 | struct ieee80211s_hdr mesh_hdr; |
1385 | const u8 *encaps_data; | 1405 | const u8 *encaps_data; |
@@ -1402,12 +1422,12 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1402 | /* convert Ethernet header to proper 802.11 header (based on | 1422 | /* convert Ethernet header to proper 802.11 header (based on |
1403 | * operation mode) */ | 1423 | * operation mode) */ |
1404 | ethertype = (skb->data[12] << 8) | skb->data[13]; | 1424 | ethertype = (skb->data[12] << 8) | skb->data[13]; |
1405 | fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; | 1425 | fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA); |
1406 | 1426 | ||
1407 | switch (sdata->vif.type) { | 1427 | switch (sdata->vif.type) { |
1408 | case IEEE80211_IF_TYPE_AP: | 1428 | case IEEE80211_IF_TYPE_AP: |
1409 | case IEEE80211_IF_TYPE_VLAN: | 1429 | case IEEE80211_IF_TYPE_VLAN: |
1410 | fc |= IEEE80211_FCTL_FROMDS; | 1430 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
1411 | /* DA BSSID SA */ | 1431 | /* DA BSSID SA */ |
1412 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1432 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1413 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1433 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
@@ -1415,7 +1435,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1415 | hdrlen = 24; | 1435 | hdrlen = 24; |
1416 | break; | 1436 | break; |
1417 | case IEEE80211_IF_TYPE_WDS: | 1437 | case IEEE80211_IF_TYPE_WDS: |
1418 | fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; | 1438 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1419 | /* RA TA DA SA */ | 1439 | /* RA TA DA SA */ |
1420 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); | 1440 | memcpy(hdr.addr1, sdata->u.wds.remote_addr, ETH_ALEN); |
1421 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1441 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
@@ -1425,7 +1445,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1425 | break; | 1445 | break; |
1426 | #ifdef CONFIG_MAC80211_MESH | 1446 | #ifdef CONFIG_MAC80211_MESH |
1427 | case IEEE80211_IF_TYPE_MESH_POINT: | 1447 | case IEEE80211_IF_TYPE_MESH_POINT: |
1428 | fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; | 1448 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1429 | /* RA TA DA SA */ | 1449 | /* RA TA DA SA */ |
1430 | if (is_multicast_ether_addr(skb->data)) | 1450 | if (is_multicast_ether_addr(skb->data)) |
1431 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1451 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1455,7 +1475,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1455 | break; | 1475 | break; |
1456 | #endif | 1476 | #endif |
1457 | case IEEE80211_IF_TYPE_STA: | 1477 | case IEEE80211_IF_TYPE_STA: |
1458 | fc |= IEEE80211_FCTL_TODS; | 1478 | fc |= cpu_to_le16(IEEE80211_FCTL_TODS); |
1459 | /* BSSID SA DA */ | 1479 | /* BSSID SA DA */ |
1460 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); | 1480 | memcpy(hdr.addr1, sdata->u.sta.bssid, ETH_ALEN); |
1461 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1481 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -1490,7 +1510,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1490 | /* receiver and we are QoS enabled, use a QoS type frame */ | 1510 | /* receiver and we are QoS enabled, use a QoS type frame */ |
1491 | if (sta_flags & WLAN_STA_WME && | 1511 | if (sta_flags & WLAN_STA_WME && |
1492 | ieee80211_num_regular_queues(&local->hw) >= 4) { | 1512 | ieee80211_num_regular_queues(&local->hw) >= 4) { |
1493 | fc |= IEEE80211_STYPE_QOS_DATA; | 1513 | fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA); |
1494 | hdrlen += 2; | 1514 | hdrlen += 2; |
1495 | } | 1515 | } |
1496 | 1516 | ||
@@ -1518,7 +1538,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1518 | goto fail; | 1538 | goto fail; |
1519 | } | 1539 | } |
1520 | 1540 | ||
1521 | hdr.frame_control = cpu_to_le16(fc); | 1541 | hdr.frame_control = fc; |
1522 | hdr.duration_id = 0; | 1542 | hdr.duration_id = 0; |
1523 | hdr.seq_ctrl = 0; | 1543 | hdr.seq_ctrl = 0; |
1524 | 1544 | ||
@@ -1587,7 +1607,7 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1587 | h_pos += meshhdrlen; | 1607 | h_pos += meshhdrlen; |
1588 | } | 1608 | } |
1589 | 1609 | ||
1590 | if (fc & IEEE80211_STYPE_QOS_DATA) { | 1610 | if (ieee80211_is_data_qos(fc)) { |
1591 | __le16 *qos_control; | 1611 | __le16 *qos_control; |
1592 | 1612 | ||
1593 | qos_control = (__le16*) skb_push(skb, 2); | 1613 | qos_control = (__le16*) skb_push(skb, 2); |
@@ -1845,8 +1865,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1845 | mgmt = (struct ieee80211_mgmt *) | 1865 | mgmt = (struct ieee80211_mgmt *) |
1846 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1866 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1847 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1867 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1848 | mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, | 1868 | mgmt->frame_control = |
1849 | IEEE80211_STYPE_BEACON); | 1869 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
1850 | memset(mgmt->da, 0xff, ETH_ALEN); | 1870 | memset(mgmt->da, 0xff, ETH_ALEN); |
1851 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1871 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
1852 | /* BSSID is left zeroed, wildcard value */ | 1872 | /* BSSID is left zeroed, wildcard value */ |
@@ -1914,10 +1934,9 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1914 | struct ieee80211_rts *rts) | 1934 | struct ieee80211_rts *rts) |
1915 | { | 1935 | { |
1916 | const struct ieee80211_hdr *hdr = frame; | 1936 | const struct ieee80211_hdr *hdr = frame; |
1917 | u16 fctl; | ||
1918 | 1937 | ||
1919 | fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS; | 1938 | rts->frame_control = |
1920 | rts->frame_control = cpu_to_le16(fctl); | 1939 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); |
1921 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, | 1940 | rts->duration = ieee80211_rts_duration(hw, vif, frame_len, |
1922 | frame_txctl); | 1941 | frame_txctl); |
1923 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); | 1942 | memcpy(rts->ra, hdr->addr1, sizeof(rts->ra)); |
@@ -1931,10 +1950,9 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1931 | struct ieee80211_cts *cts) | 1950 | struct ieee80211_cts *cts) |
1932 | { | 1951 | { |
1933 | const struct ieee80211_hdr *hdr = frame; | 1952 | const struct ieee80211_hdr *hdr = frame; |
1934 | u16 fctl; | ||
1935 | 1953 | ||
1936 | fctl = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS; | 1954 | cts->frame_control = |
1937 | cts->frame_control = cpu_to_le16(fctl); | 1955 | cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS); |
1938 | cts->duration = ieee80211_ctstoself_duration(hw, vif, | 1956 | cts->duration = ieee80211_ctstoself_duration(hw, vif, |
1939 | frame_len, frame_txctl); | 1957 | frame_len, frame_txctl); |
1940 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); | 1958 | memcpy(cts->ra, hdr->addr1, sizeof(cts->ra)); |
@@ -1948,9 +1966,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
1948 | struct ieee80211_local *local = hw_to_local(hw); | 1966 | struct ieee80211_local *local = hw_to_local(hw); |
1949 | struct sk_buff *skb = NULL; | 1967 | struct sk_buff *skb = NULL; |
1950 | struct sta_info *sta; | 1968 | struct sta_info *sta; |
1951 | ieee80211_tx_handler *handler; | ||
1952 | struct ieee80211_tx_data tx; | 1969 | struct ieee80211_tx_data tx; |
1953 | ieee80211_tx_result res = TX_DROP; | ||
1954 | struct net_device *bdev; | 1970 | struct net_device *bdev; |
1955 | struct ieee80211_sub_if_data *sdata; | 1971 | struct ieee80211_sub_if_data *sdata; |
1956 | struct ieee80211_if_ap *bss = NULL; | 1972 | struct ieee80211_if_ap *bss = NULL; |
@@ -2001,25 +2017,9 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2001 | tx.channel = local->hw.conf.channel; | 2017 | tx.channel = local->hw.conf.channel; |
2002 | info->band = tx.channel->band; | 2018 | info->band = tx.channel->band; |
2003 | 2019 | ||
2004 | for (handler = ieee80211_tx_handlers; *handler != NULL; handler++) { | 2020 | if (invoke_tx_handlers(&tx)) |
2005 | res = (*handler)(&tx); | ||
2006 | if (res == TX_DROP || res == TX_QUEUED) | ||
2007 | break; | ||
2008 | } | ||
2009 | |||
2010 | if (WARN_ON(tx.skb != skb)) | ||
2011 | res = TX_DROP; | ||
2012 | |||
2013 | if (res == TX_DROP) { | ||
2014 | I802_DEBUG_INC(local->tx_handlers_drop); | ||
2015 | dev_kfree_skb(skb); | ||
2016 | skb = NULL; | 2021 | skb = NULL; |
2017 | } else if (res == TX_QUEUED) { | 2022 | out: |
2018 | I802_DEBUG_INC(local->tx_handlers_queued); | ||
2019 | skb = NULL; | ||
2020 | } | ||
2021 | |||
2022 | out: | ||
2023 | rcu_read_unlock(); | 2023 | rcu_read_unlock(); |
2024 | 2024 | ||
2025 | return skb; | 2025 | return skb; |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index e7b6344c900a..35b664d00e23 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -84,20 +84,17 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, | |||
84 | struct sk_buff *skb, | 84 | struct sk_buff *skb, |
85 | struct ieee80211_key *key) | 85 | struct ieee80211_key *key) |
86 | { | 86 | { |
87 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 87 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
88 | u16 fc; | 88 | unsigned int hdrlen; |
89 | int hdrlen; | ||
90 | u8 *newhdr; | 89 | u8 *newhdr; |
91 | 90 | ||
92 | fc = le16_to_cpu(hdr->frame_control); | 91 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); |
93 | fc |= IEEE80211_FCTL_PROTECTED; | ||
94 | hdr->frame_control = cpu_to_le16(fc); | ||
95 | 92 | ||
96 | if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || | 93 | if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || |
97 | skb_headroom(skb) < WEP_IV_LEN)) | 94 | skb_headroom(skb) < WEP_IV_LEN)) |
98 | return NULL; | 95 | return NULL; |
99 | 96 | ||
100 | hdrlen = ieee80211_get_hdrlen(fc); | 97 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
101 | newhdr = skb_push(skb, WEP_IV_LEN); | 98 | newhdr = skb_push(skb, WEP_IV_LEN); |
102 | memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); | 99 | memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); |
103 | ieee80211_wep_get_iv(local, key, newhdr + hdrlen); | 100 | ieee80211_wep_get_iv(local, key, newhdr + hdrlen); |
@@ -109,12 +106,10 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, | |||
109 | struct sk_buff *skb, | 106 | struct sk_buff *skb, |
110 | struct ieee80211_key *key) | 107 | struct ieee80211_key *key) |
111 | { | 108 | { |
112 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 109 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
113 | u16 fc; | 110 | unsigned int hdrlen; |
114 | int hdrlen; | ||
115 | 111 | ||
116 | fc = le16_to_cpu(hdr->frame_control); | 112 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
117 | hdrlen = ieee80211_get_hdrlen(fc); | ||
118 | memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); | 113 | memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); |
119 | skb_pull(skb, WEP_IV_LEN); | 114 | skb_pull(skb, WEP_IV_LEN); |
120 | } | 115 | } |
@@ -224,17 +219,15 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
224 | u32 klen; | 219 | u32 klen; |
225 | u8 *rc4key; | 220 | u8 *rc4key; |
226 | u8 keyidx; | 221 | u8 keyidx; |
227 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 222 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
228 | u16 fc; | 223 | unsigned int hdrlen; |
229 | int hdrlen; | ||
230 | size_t len; | 224 | size_t len; |
231 | int ret = 0; | 225 | int ret = 0; |
232 | 226 | ||
233 | fc = le16_to_cpu(hdr->frame_control); | 227 | if (!ieee80211_has_protected(hdr->frame_control)) |
234 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
235 | return -1; | 228 | return -1; |
236 | 229 | ||
237 | hdrlen = ieee80211_get_hdrlen(fc); | 230 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
238 | 231 | ||
239 | if (skb->len < 8 + hdrlen) | 232 | if (skb->len < 8 + hdrlen) |
240 | return -1; | 233 | return -1; |
@@ -281,17 +274,15 @@ int ieee80211_wep_decrypt(struct ieee80211_local *local, struct sk_buff *skb, | |||
281 | 274 | ||
282 | u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | 275 | u8 * ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) |
283 | { | 276 | { |
284 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 277 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
285 | u16 fc; | 278 | unsigned int hdrlen; |
286 | int hdrlen; | ||
287 | u8 *ivpos; | 279 | u8 *ivpos; |
288 | u32 iv; | 280 | u32 iv; |
289 | 281 | ||
290 | fc = le16_to_cpu(hdr->frame_control); | 282 | if (!ieee80211_has_protected(hdr->frame_control)) |
291 | if (!(fc & IEEE80211_FCTL_PROTECTED)) | ||
292 | return NULL; | 283 | return NULL; |
293 | 284 | ||
294 | hdrlen = ieee80211_get_hdrlen(fc); | 285 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
295 | ivpos = skb->data + hdrlen; | 286 | ivpos = skb->data + hdrlen; |
296 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; | 287 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; |
297 | 288 | ||
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5af3862e7191..df0531c28141 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -135,7 +135,39 @@ static int ieee80211_ioctl_giwname(struct net_device *dev, | |||
135 | struct iw_request_info *info, | 135 | struct iw_request_info *info, |
136 | char *name, char *extra) | 136 | char *name, char *extra) |
137 | { | 137 | { |
138 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
139 | struct ieee80211_supported_band *sband; | ||
140 | u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0; | ||
141 | |||
142 | |||
143 | sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ]; | ||
144 | if (sband) { | ||
145 | is_a = 1; | ||
146 | is_ht |= sband->ht_info.ht_supported; | ||
147 | } | ||
148 | |||
149 | sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ]; | ||
150 | if (sband) { | ||
151 | int i; | ||
152 | /* Check for mandatory rates */ | ||
153 | for (i = 0; i < sband->n_bitrates; i++) { | ||
154 | if (sband->bitrates[i].bitrate == 10) | ||
155 | is_b = 1; | ||
156 | if (sband->bitrates[i].bitrate == 60) | ||
157 | is_g = 1; | ||
158 | } | ||
159 | is_ht |= sband->ht_info.ht_supported; | ||
160 | } | ||
161 | |||
138 | strcpy(name, "IEEE 802.11"); | 162 | strcpy(name, "IEEE 802.11"); |
163 | if (is_a) | ||
164 | strcat(name, "a"); | ||
165 | if (is_b) | ||
166 | strcat(name, "b"); | ||
167 | if (is_g) | ||
168 | strcat(name, "g"); | ||
169 | if (is_ht) | ||
170 | strcat(name, "n"); | ||
139 | 171 | ||
140 | return 0; | 172 | return 0; |
141 | } | 173 | } |
@@ -567,7 +599,7 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev, | |||
567 | if (local->sta_sw_scanning || local->sta_hw_scanning) | 599 | if (local->sta_sw_scanning || local->sta_hw_scanning) |
568 | return -EAGAIN; | 600 | return -EAGAIN; |
569 | 601 | ||
570 | res = ieee80211_sta_scan_results(dev, extra, data->length); | 602 | res = ieee80211_sta_scan_results(dev, info, extra, data->length); |
571 | if (res >= 0) { | 603 | if (res >= 0) { |
572 | data->length = res; | 604 | data->length = res; |
573 | return 0; | 605 | return 0; |
@@ -721,6 +753,9 @@ static int ieee80211_ioctl_siwrts(struct net_device *dev, | |||
721 | 753 | ||
722 | if (rts->disabled) | 754 | if (rts->disabled) |
723 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | 755 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; |
756 | else if (!rts->fixed) | ||
757 | /* if the rts value is not fixed, then take default */ | ||
758 | local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; | ||
724 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) | 759 | else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD) |
725 | return -EINVAL; | 760 | return -EINVAL; |
726 | else | 761 | else |
@@ -949,6 +984,19 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev, | |||
949 | erq->length = sdata->keys[idx]->conf.keylen; | 984 | erq->length = sdata->keys[idx]->conf.keylen; |
950 | erq->flags |= IW_ENCODE_ENABLED; | 985 | erq->flags |= IW_ENCODE_ENABLED; |
951 | 986 | ||
987 | if (sdata->vif.type == IEEE80211_IF_TYPE_STA) { | ||
988 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | ||
989 | switch (ifsta->auth_alg) { | ||
990 | case WLAN_AUTH_OPEN: | ||
991 | case WLAN_AUTH_LEAP: | ||
992 | erq->flags |= IW_ENCODE_OPEN; | ||
993 | break; | ||
994 | case WLAN_AUTH_SHARED_KEY: | ||
995 | erq->flags |= IW_ENCODE_RESTRICTED; | ||
996 | break; | ||
997 | } | ||
998 | } | ||
999 | |||
952 | return 0; | 1000 | return 0; |
953 | } | 1001 | } |
954 | 1002 | ||
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 345e10e9b313..f809761fbfb5 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -49,7 +49,7 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, | |||
49 | ieee80211_tx_result | 49 | ieee80211_tx_result |
50 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | 50 | ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) |
51 | { | 51 | { |
52 | u8 *data, *sa, *da, *key, *mic, qos_tid; | 52 | u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset; |
53 | size_t data_len; | 53 | size_t data_len; |
54 | u16 fc; | 54 | u16 fc; |
55 | struct sk_buff *skb = tx->skb; | 55 | struct sk_buff *skb = tx->skb; |
@@ -88,8 +88,12 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
88 | #else | 88 | #else |
89 | authenticator = 1; | 89 | authenticator = 1; |
90 | #endif | 90 | #endif |
91 | key = &tx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_TX_MIC_KEY : | 91 | /* At this point we know we're using ALG_TKIP. To get the MIC key |
92 | ALG_TKIP_TEMP_AUTH_RX_MIC_KEY]; | 92 | * we now will rely on the offset from the ieee80211_key_conf::key */ |
93 | key_offset = authenticator ? | ||
94 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY : | ||
95 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | ||
96 | key = &tx->key->conf.key[key_offset]; | ||
93 | mic = skb_put(skb, MICHAEL_MIC_LEN); | 97 | mic = skb_put(skb, MICHAEL_MIC_LEN); |
94 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 98 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); |
95 | 99 | ||
@@ -100,7 +104,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) | |||
100 | ieee80211_rx_result | 104 | ieee80211_rx_result |
101 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | 105 | ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) |
102 | { | 106 | { |
103 | u8 *data, *sa, *da, *key = NULL, qos_tid; | 107 | u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset; |
104 | size_t data_len; | 108 | size_t data_len; |
105 | u16 fc; | 109 | u16 fc; |
106 | u8 mic[MICHAEL_MIC_LEN]; | 110 | u8 mic[MICHAEL_MIC_LEN]; |
@@ -131,8 +135,12 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
131 | #else | 135 | #else |
132 | authenticator = 1; | 136 | authenticator = 1; |
133 | #endif | 137 | #endif |
134 | key = &rx->key->conf.key[authenticator ? ALG_TKIP_TEMP_AUTH_RX_MIC_KEY : | 138 | /* At this point we know we're using ALG_TKIP. To get the MIC key |
135 | ALG_TKIP_TEMP_AUTH_TX_MIC_KEY]; | 139 | * we now will rely on the offset from the ieee80211_key_conf::key */ |
140 | key_offset = authenticator ? | ||
141 | NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : | ||
142 | NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | ||
143 | key = &rx->key->conf.key[key_offset]; | ||
136 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); | 144 | michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); |
137 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { | 145 | if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { |
138 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 146 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |