Merge branch 'fixes-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
[sfrench/cifs-2.6.git] / net / mac80211 / ieee80211_sta.c
index db81aef6177a948471d7d1f19ae9143ec88ad1c5..015b3f879aa921f41c0d11a52a632c39be407852 100644 (file)
@@ -108,14 +108,11 @@ struct ieee802_11_elems {
        u8 wmm_param_len;
 };
 
-enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 };
-
-static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
-                                           struct ieee802_11_elems *elems)
+static void ieee802_11_parse_elems(u8 *start, size_t len,
+                                  struct ieee802_11_elems *elems)
 {
        size_t left = len;
        u8 *pos = start;
-       int unknown = 0;
 
        memset(elems, 0, sizeof(*elems));
 
@@ -126,15 +123,8 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
                elen = *pos++;
                left -= 2;
 
-               if (elen > left) {
-#if 0
-                       if (net_ratelimit())
-                               printk(KERN_DEBUG "IEEE 802.11 element parse "
-                                      "failed (id=%d elen=%d left=%d)\n",
-                                      id, elen, left);
-#endif
-                       return ParseFailed;
-               }
+               if (elen > left)
+                       return;
 
                switch (id) {
                case WLAN_EID_SSID:
@@ -201,28 +191,15 @@ static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
                        elems->ext_supp_rates_len = elen;
                        break;
                default:
-#if 0
-                       printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
-                                     "unknown element (id=%d elen=%d)\n",
-                                     id, elen);
-#endif
-                       unknown++;
                        break;
                }
 
                left -= elen;
                pos += elen;
        }
-
-       /* Do not trigger error if left == 1 as Apple Airport base stations
-        * send AssocResps that are one spurious byte too long. */
-
-       return unknown ? ParseUnknown : ParseOK;
 }
 
 
-
-
 static int ecw2cw(int ecw)
 {
        int cw = 1;
@@ -727,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,
@@ -738,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;
 }
 
 
@@ -931,12 +912,7 @@ static void ieee80211_auth_challenge(struct net_device *dev,
 
        printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
        pos = mgmt->u.auth.variable;
-       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
-           == ParseFailed) {
-               printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
-                      dev->name);
-               return;
-       }
+       ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
        if (!elems.challenge) {
                printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
                       "frame\n", dev->name);
@@ -1212,7 +1188,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
        printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x "
               "status=%d aid=%d)\n",
               dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa),
-              capab_info, status_code, aid & ~(BIT(15) | BIT(14)));
+              capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14))));
 
        if (status_code != WLAN_STATUS_SUCCESS) {
                printk(KERN_DEBUG "%s: AP denied association (code=%d)\n",
@@ -1230,12 +1206,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
        aid &= ~(BIT(15) | BIT(14));
 
        pos = mgmt->u.assoc_resp.variable;
-       if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
-           == ParseFailed) {
-               printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
-                      dev->name);
-               return;
-       }
+       ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
 
        if (!elems.supp_rates) {
                printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
@@ -1459,7 +1430,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
        struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee802_11_elems elems;
        size_t baselen;
-       int channel, invalid = 0, clen;
+       int channel, clen;
        struct ieee80211_sta_bss *bss;
        struct sta_info *sta;
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -1505,9 +1476,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
 #endif /* CONFIG_MAC80211_IBSS_DEBUG */
        }
 
-       if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
-                                  &elems) == ParseFailed)
-               invalid = 1;
+       ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
 
        if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
            memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
@@ -1724,9 +1693,7 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
        if (baselen > len)
                return;
 
-       if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
-                                  &elems) == ParseFailed)
-               return;
+       ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
 
        if (elems.erp_info && elems.erp_info_len >= 1)
                ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
@@ -2035,7 +2002,10 @@ void ieee80211_sta_work(struct work_struct *work)
        if (ifsta->state != IEEE80211_AUTHENTICATE &&
            ifsta->state != IEEE80211_ASSOCIATE &&
            test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request)) {
-               ieee80211_sta_start_scan(dev, NULL, 0);
+               if (ifsta->scan_ssid_len)
+                       ieee80211_sta_start_scan(dev, ifsta->scan_ssid, ifsta->scan_ssid_len);
+               else
+                       ieee80211_sta_start_scan(dev, NULL, 0);
                return;
        }
 
@@ -2133,7 +2103,8 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
 {
        int tmp, hidden_ssid;
 
-       if (!memcmp(ifsta->ssid, ssid, ssid_len))
+       if (ssid_len == ifsta->ssid_len &&
+           !memcmp(ifsta->ssid, ssid, ssid_len))
                return 1;
 
        if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
@@ -2904,6 +2875,9 @@ int ieee80211_sta_req_scan(struct net_device *dev, u8 *ssid, size_t ssid_len)
                return -EBUSY;
        }
 
+       ifsta->scan_ssid_len = ssid_len;
+       if (ssid_len)
+               memcpy(ifsta->scan_ssid, ssid, ssid_len);
        set_bit(IEEE80211_STA_REQ_SCAN, &ifsta->request);
        queue_work(local->hw.workqueue, &ifsta->work);
        return 0;