mac80211: use IW_AUTH_PRIVACY_INVOKED rather than IW_AUTH_KEY_MGMT
authorJohannes Berg <johannes@sipsolutions.net>
Sat, 3 Nov 2007 13:11:10 +0000 (13:11 +0000)
committerDavid S. Miller <davem@sunset.davemloft.net>
Sun, 11 Nov 2007 06:01:25 +0000 (22:01 -0800)
In the long bug-hunt for why dynamic WEP networks didn't work it
turned out that mac80211 incorrectly uses IW_AUTH_KEY_MGMT while
it should use IW_AUTH_PRIVACY_INVOKED to determine whether to
associate to protected networks or not.

This patch changes the behaviour to be that way and clarifies the
existing code.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Cc: Jouni Malinen <j@w1.fi>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/ieee80211_i.h
net/mac80211/ieee80211_ioctl.c
net/mac80211/ieee80211_sta.c

index 4b4ed2a5803c46f8e86ae550f9431fb4044e2a34..b4e32ab3664db1d8ea3a4cec7d76684a0d902cbf 100644 (file)
@@ -230,6 +230,7 @@ struct ieee80211_if_vlan {
 #define IEEE80211_STA_AUTO_SSID_SEL    BIT(10)
 #define IEEE80211_STA_AUTO_BSSID_SEL   BIT(11)
 #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
+#define IEEE80211_STA_PRIVACY_INVOKED  BIT(13)
 struct ieee80211_if_sta {
        enum {
                IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
@@ -259,7 +260,6 @@ struct ieee80211_if_sta {
        unsigned long request;
        struct sk_buff_head skb_queue;
 
-       int key_management_enabled;
        unsigned long last_probe;
 
 #define IEEE80211_AUTH_ALG_OPEN BIT(0)
index 3645660a364a411e4a6718543e6ae93984e1c0b4..7027eed4d4ae3a374fff7439110e80d44069a8fb 100644 (file)
@@ -926,19 +926,21 @@ static int ieee80211_ioctl_siwauth(struct net_device *dev,
        case IW_AUTH_CIPHER_GROUP:
        case IW_AUTH_WPA_ENABLED:
        case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-       case IW_AUTH_PRIVACY_INVOKED:
-               break;
        case IW_AUTH_KEY_MGMT:
+               break;
+       case IW_AUTH_PRIVACY_INVOKED:
                if (sdata->type != IEEE80211_IF_TYPE_STA)
                        ret = -EINVAL;
                else {
+                       sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
                        /*
-                        * Key management was set by wpa_supplicant,
-                        * we only need this to associate to a network
-                        * that has privacy enabled regardless of not
-                        * having a key.
+                        * Privacy invoked by wpa_supplicant, store the
+                        * value and allow associating to a protected
+                        * network without having a key up front.
                         */
-                       sdata->u.sta.key_management_enabled = !!data->value;
+                       if (data->value)
+                               sdata->u.sta.flags |=
+                                       IEEE80211_STA_PRIVACY_INVOKED;
                }
                break;
        case IW_AUTH_80211_AUTH_ALG:
index fda0e06453e85bc5f8d00867170dd41d17e9e65c..2079e988fc56f256a7f655b2e541d7538ecb2169 100644 (file)
@@ -704,10 +704,11 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
 {
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sta_bss *bss;
-       int res = 0;
+       int bss_privacy;
+       int wep_privacy;
+       int privacy_invoked;
 
-       if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) ||
-           ifsta->key_management_enabled)
+       if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
                return 0;
 
        bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
@@ -715,13 +716,16 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
        if (!bss)
                return 0;
 
-       if (ieee80211_sta_wep_configured(dev) !=
-           !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
-               res = 1;
+       bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
+       wep_privacy = !!ieee80211_sta_wep_configured(dev);
+       privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
 
        ieee80211_rx_bss_put(dev, bss);
 
-       return res;
+       if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
+               return 0;
+
+       return 1;
 }