diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 85 |
1 files changed, 72 insertions, 13 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a5dba67bbe0b..4ff52d0aaf9c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -30,11 +30,13 @@ | |||
30 | #include "rate.h" | 30 | #include "rate.h" |
31 | #include "led.h" | 31 | #include "led.h" |
32 | 32 | ||
33 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | 33 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) |
34 | #define IEEE80211_AUTH_MAX_TRIES 3 | 34 | #define IEEE80211_AUTH_TIMEOUT_SHORT (HZ / 10) |
35 | #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) | 35 | #define IEEE80211_AUTH_MAX_TRIES 3 |
36 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | 36 | #define IEEE80211_AUTH_WAIT_ASSOC (HZ * 5) |
37 | #define IEEE80211_ASSOC_MAX_TRIES 3 | 37 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) |
38 | #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10) | ||
39 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
38 | 40 | ||
39 | static int max_nullfunc_tries = 2; | 41 | static int max_nullfunc_tries = 2; |
40 | module_param(max_nullfunc_tries, int, 0644); | 42 | module_param(max_nullfunc_tries, int, 0644); |
@@ -644,6 +646,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
644 | drv_mgd_prepare_tx(local, sdata); | 646 | drv_mgd_prepare_tx(local, sdata); |
645 | 647 | ||
646 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 648 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
649 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
650 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
651 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
647 | ieee80211_tx_skb(sdata, skb); | 652 | ieee80211_tx_skb(sdata, skb); |
648 | } | 653 | } |
649 | 654 | ||
@@ -1707,7 +1712,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1707 | ssid_len = ssid[1]; | 1712 | ssid_len = ssid[1]; |
1708 | 1713 | ||
1709 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | 1714 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, |
1710 | 0, (u32) -1, true, false, | 1715 | 0, (u32) -1, true, 0, |
1711 | ifmgd->associated->channel, false); | 1716 | ifmgd->associated->channel, false); |
1712 | rcu_read_unlock(); | 1717 | rcu_read_unlock(); |
1713 | } | 1718 | } |
@@ -1937,9 +1942,11 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1937 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | 1942 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, |
1938 | struct ieee80211_mgmt *mgmt, size_t len) | 1943 | struct ieee80211_mgmt *mgmt, size_t len) |
1939 | { | 1944 | { |
1945 | struct ieee80211_local *local = sdata->local; | ||
1940 | struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; | 1946 | struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; |
1941 | u8 *pos; | 1947 | u8 *pos; |
1942 | struct ieee802_11_elems elems; | 1948 | struct ieee802_11_elems elems; |
1949 | u32 tx_flags = 0; | ||
1943 | 1950 | ||
1944 | pos = mgmt->u.auth.variable; | 1951 | pos = mgmt->u.auth.variable; |
1945 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | 1952 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); |
@@ -1947,11 +1954,14 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | |||
1947 | return; | 1954 | return; |
1948 | auth_data->expected_transaction = 4; | 1955 | auth_data->expected_transaction = 4; |
1949 | drv_mgd_prepare_tx(sdata->local, sdata); | 1956 | drv_mgd_prepare_tx(sdata->local, sdata); |
1957 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
1958 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
1959 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
1950 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0, | 1960 | ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0, |
1951 | elems.challenge - 2, elems.challenge_len + 2, | 1961 | elems.challenge - 2, elems.challenge_len + 2, |
1952 | auth_data->bss->bssid, auth_data->bss->bssid, | 1962 | auth_data->bss->bssid, auth_data->bss->bssid, |
1953 | auth_data->key, auth_data->key_len, | 1963 | auth_data->key, auth_data->key_len, |
1954 | auth_data->key_idx); | 1964 | auth_data->key_idx, tx_flags); |
1955 | } | 1965 | } |
1956 | 1966 | ||
1957 | static enum rx_mgmt_action __must_check | 1967 | static enum rx_mgmt_action __must_check |
@@ -2869,12 +2879,17 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2869 | struct ieee80211_local *local = sdata->local; | 2879 | struct ieee80211_local *local = sdata->local; |
2870 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2880 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2871 | struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; | 2881 | struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data; |
2882 | u32 tx_flags = 0; | ||
2872 | 2883 | ||
2873 | lockdep_assert_held(&ifmgd->mtx); | 2884 | lockdep_assert_held(&ifmgd->mtx); |
2874 | 2885 | ||
2875 | if (WARN_ON_ONCE(!auth_data)) | 2886 | if (WARN_ON_ONCE(!auth_data)) |
2876 | return -EINVAL; | 2887 | return -EINVAL; |
2877 | 2888 | ||
2889 | if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) | ||
2890 | tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||
2891 | IEEE80211_TX_INTFL_MLME_CONN_TX; | ||
2892 | |||
2878 | auth_data->tries++; | 2893 | auth_data->tries++; |
2879 | 2894 | ||
2880 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { | 2895 | if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { |
@@ -2911,7 +2926,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2911 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, | 2926 | ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, |
2912 | auth_data->data, auth_data->data_len, | 2927 | auth_data->data, auth_data->data_len, |
2913 | auth_data->bss->bssid, | 2928 | auth_data->bss->bssid, |
2914 | auth_data->bss->bssid, NULL, 0, 0); | 2929 | auth_data->bss->bssid, NULL, 0, 0, |
2930 | tx_flags); | ||
2915 | } else { | 2931 | } else { |
2916 | const u8 *ssidie; | 2932 | const u8 *ssidie; |
2917 | 2933 | ||
@@ -2930,13 +2946,15 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2930 | * will not answer to direct packet in unassociated state. | 2946 | * will not answer to direct packet in unassociated state. |
2931 | */ | 2947 | */ |
2932 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 2948 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
2933 | NULL, 0, (u32) -1, true, false, | 2949 | NULL, 0, (u32) -1, true, tx_flags, |
2934 | auth_data->bss->channel, false); | 2950 | auth_data->bss->channel, false); |
2935 | rcu_read_unlock(); | 2951 | rcu_read_unlock(); |
2936 | } | 2952 | } |
2937 | 2953 | ||
2938 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 2954 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { |
2939 | run_again(ifmgd, auth_data->timeout); | 2955 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
2956 | run_again(ifmgd, auth_data->timeout); | ||
2957 | } | ||
2940 | 2958 | ||
2941 | return 0; | 2959 | return 0; |
2942 | } | 2960 | } |
@@ -2967,12 +2985,26 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) | |||
2967 | IEEE80211_ASSOC_MAX_TRIES); | 2985 | IEEE80211_ASSOC_MAX_TRIES); |
2968 | ieee80211_send_assoc(sdata); | 2986 | ieee80211_send_assoc(sdata); |
2969 | 2987 | ||
2970 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 2988 | if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { |
2971 | run_again(&sdata->u.mgd, assoc_data->timeout); | 2989 | assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
2990 | run_again(&sdata->u.mgd, assoc_data->timeout); | ||
2991 | } | ||
2972 | 2992 | ||
2973 | return 0; | 2993 | return 0; |
2974 | } | 2994 | } |
2975 | 2995 | ||
2996 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | ||
2997 | __le16 fc, bool acked) | ||
2998 | { | ||
2999 | struct ieee80211_local *local = sdata->local; | ||
3000 | |||
3001 | sdata->u.mgd.status_fc = fc; | ||
3002 | sdata->u.mgd.status_acked = acked; | ||
3003 | sdata->u.mgd.status_received = true; | ||
3004 | |||
3005 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
3006 | } | ||
3007 | |||
2976 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | 3008 | void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) |
2977 | { | 3009 | { |
2978 | struct ieee80211_local *local = sdata->local; | 3010 | struct ieee80211_local *local = sdata->local; |
@@ -2980,6 +3012,33 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
2980 | 3012 | ||
2981 | mutex_lock(&ifmgd->mtx); | 3013 | mutex_lock(&ifmgd->mtx); |
2982 | 3014 | ||
3015 | if (ifmgd->status_received) { | ||
3016 | __le16 fc = ifmgd->status_fc; | ||
3017 | bool status_acked = ifmgd->status_acked; | ||
3018 | |||
3019 | ifmgd->status_received = false; | ||
3020 | if (ifmgd->auth_data && | ||
3021 | (ieee80211_is_probe_req(fc) || ieee80211_is_auth(fc))) { | ||
3022 | if (status_acked) { | ||
3023 | ifmgd->auth_data->timeout = | ||
3024 | jiffies + IEEE80211_AUTH_TIMEOUT_SHORT; | ||
3025 | run_again(ifmgd, ifmgd->auth_data->timeout); | ||
3026 | } else { | ||
3027 | ifmgd->auth_data->timeout = jiffies - 1; | ||
3028 | } | ||
3029 | } else if (ifmgd->assoc_data && | ||
3030 | (ieee80211_is_assoc_req(fc) || | ||
3031 | ieee80211_is_reassoc_req(fc))) { | ||
3032 | if (status_acked) { | ||
3033 | ifmgd->assoc_data->timeout = | ||
3034 | jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT; | ||
3035 | run_again(ifmgd, ifmgd->assoc_data->timeout); | ||
3036 | } else { | ||
3037 | ifmgd->assoc_data->timeout = jiffies - 1; | ||
3038 | } | ||
3039 | } | ||
3040 | } | ||
3041 | |||
2983 | if (ifmgd->auth_data && | 3042 | if (ifmgd->auth_data && |
2984 | time_after(jiffies, ifmgd->auth_data->timeout)) { | 3043 | time_after(jiffies, ifmgd->auth_data->timeout)) { |
2985 | if (ifmgd->auth_data->done) { | 3044 | if (ifmgd->auth_data->done) { |