]> err.no Git - linux-2.6/blobdiff - net/mac80211/wext.c
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6] / net / mac80211 / wext.c
index 457ebf9e85ae6dcfd9bf40313a888c882feebee5..1babb979fe001da43506c47e54be9922fc3460d9 100644 (file)
@@ -95,6 +95,13 @@ static int ieee80211_set_encryption(struct net_device *dev, u8 *sta_addr,
                        }
                }
 
+               if (alg == ALG_WEP &&
+                       key_len != LEN_WEP40 && key_len != LEN_WEP104) {
+                       ieee80211_key_free(key);
+                       err = -EINVAL;
+                       goto out_unlock;
+               }
+
                ieee80211_key_link(key, sdata, sta);
 
                if (set_tx_key || (!sta && !sdata->default_key && key))
@@ -135,7 +142,39 @@ static int ieee80211_ioctl_giwname(struct net_device *dev,
                                   struct iw_request_info *info,
                                   char *name, char *extra)
 {
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_supported_band *sband;
+       u8 is_ht = 0, is_a = 0, is_b = 0, is_g = 0;
+
+
+       sband = local->hw.wiphy->bands[IEEE80211_BAND_5GHZ];
+       if (sband) {
+               is_a = 1;
+               is_ht |= sband->ht_info.ht_supported;
+       }
+
+       sband = local->hw.wiphy->bands[IEEE80211_BAND_2GHZ];
+       if (sband) {
+               int i;
+               /* Check for mandatory rates */
+               for (i = 0; i < sband->n_bitrates; i++) {
+                       if (sband->bitrates[i].bitrate == 10)
+                               is_b = 1;
+                       if (sband->bitrates[i].bitrate == 60)
+                               is_g = 1;
+               }
+               is_ht |= sband->ht_info.ht_supported;
+       }
+
        strcpy(name, "IEEE 802.11");
+       if (is_a)
+               strcat(name, "a");
+       if (is_b)
+               strcat(name, "b");
+       if (is_g)
+               strcat(name, "g");
+       if (is_ht)
+               strcat(name, "n");
 
        return 0;
 }
@@ -169,14 +208,26 @@ static int ieee80211_ioctl_giwrange(struct net_device *dev,
        range->num_encoding_sizes = 2;
        range->max_encoding_tokens = NUM_DEFAULT_KEYS;
 
-       range->max_qual.qual = local->hw.max_signal;
-       range->max_qual.level = local->hw.max_rssi;
-       range->max_qual.noise = local->hw.max_noise;
+       if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC ||
+           local->hw.flags & IEEE80211_HW_SIGNAL_DB)
+               range->max_qual.level = local->hw.max_signal;
+       else if  (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+               range->max_qual.level = -110;
+       else
+               range->max_qual.level = 0;
+
+       if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
+               range->max_qual.noise = -110;
+       else
+               range->max_qual.noise = 0;
+
+       range->max_qual.qual = 100;
        range->max_qual.updated = local->wstats_flags;
 
-       range->avg_qual.qual = local->hw.max_signal/2;
-       range->avg_qual.level = 0;
-       range->avg_qual.noise = 0;
+       range->avg_qual.qual = 50;
+       /* not always true but better than nothing */
+       range->avg_qual.level = range->max_qual.level / 2;
+       range->avg_qual.noise = range->max_qual.noise / 2;
        range->avg_qual.updated = local->wstats_flags;
 
        range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
@@ -290,14 +341,22 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev,
        return 0;
 }
 
-int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz)
+int ieee80211_set_freq(struct net_device *dev, int freqMHz)
 {
        int ret = -EINVAL;
        struct ieee80211_channel *chan;
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
 
        if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
+               if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+                   chan->flags & IEEE80211_CHAN_NO_IBSS) {
+                       printk(KERN_DEBUG "%s: IBSS not allowed on frequency "
+                               "%d MHz\n", dev->name, chan->center_freq);
+                       return ret;
+               }
                local->oper_channel = chan;
 
                if (local->sta_sw_scanning || local->sta_hw_scanning)
@@ -315,7 +374,6 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_freq *freq, char *extra)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
@@ -329,14 +387,14 @@ static int ieee80211_ioctl_siwfreq(struct net_device *dev,
                                        IEEE80211_STA_AUTO_CHANNEL_SEL;
                        return 0;
                } else
-                       return ieee80211_set_freq(local,
+                       return ieee80211_set_freq(dev,
                                ieee80211_channel_to_frequency(freq->m));
        } else {
                int i, div = 1000000;
                for (i = 0; i < freq->e; i++)
                        div /= 10;
                if (div > 0)
-                       return ieee80211_set_freq(local, freq->m / div);
+                       return ieee80211_set_freq(dev, freq->m / div);
                else
                        return -EINVAL;
        }
@@ -489,9 +547,15 @@ static int ieee80211_ioctl_giwap(struct net_device *dev,
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
            sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
-               ap_addr->sa_family = ARPHRD_ETHER;
-               memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
-               return 0;
+               if (sdata->u.sta.state == IEEE80211_ASSOCIATED ||
+                   sdata->u.sta.state == IEEE80211_IBSS_JOINED) {
+                       ap_addr->sa_family = ARPHRD_ETHER;
+                       memcpy(&ap_addr->sa_data, sdata->u.sta.bssid, ETH_ALEN);
+                       return 0;
+               } else {
+                       memset(&ap_addr->sa_data, 0, ETH_ALEN);
+                       return 0;
+               }
        } else if (sdata->vif.type == IEEE80211_IF_TYPE_WDS) {
                ap_addr->sa_family = ARPHRD_ETHER;
                memcpy(&ap_addr->sa_data, sdata->u.wds.remote_addr, ETH_ALEN);
@@ -542,7 +606,7 @@ static int ieee80211_ioctl_giwscan(struct net_device *dev,
        if (local->sta_sw_scanning || local->sta_hw_scanning)
                return -EAGAIN;
 
-       res = ieee80211_sta_scan_results(dev, extra, data->length);
+       res = ieee80211_sta_scan_results(dev, info, extra, data->length);
        if (res >= 0) {
                data->length = res;
                return 0;
@@ -696,6 +760,9 @@ static int ieee80211_ioctl_siwrts(struct net_device *dev,
 
        if (rts->disabled)
                local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
+       else if (!rts->fixed)
+               /* if the rts value is not fixed, then take default */
+               local->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD;
        else if (rts->value < 0 || rts->value > IEEE80211_MAX_RTS_THRESHOLD)
                return -EINVAL;
        else
@@ -924,6 +991,19 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev,
        erq->length = sdata->keys[idx]->conf.keylen;
        erq->flags |= IW_ENCODE_ENABLED;
 
+       if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+               struct ieee80211_if_sta *ifsta = &sdata->u.sta;
+               switch (ifsta->auth_alg) {
+               case WLAN_AUTH_OPEN:
+               case WLAN_AUTH_LEAP:
+                       erq->flags |= IW_ENCODE_OPEN;
+                       break;
+               case WLAN_AUTH_SHARED_KEY:
+                       erq->flags |= IW_ENCODE_RESTRICTED;
+                       break;
+               }
+       }
+
        return 0;
 }
 
@@ -995,8 +1075,8 @@ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev
                wstats->qual.noise = 0;
                wstats->qual.updated = IW_QUAL_ALL_INVALID;
        } else {
-               wstats->qual.level = sta->last_rssi;
-               wstats->qual.qual = sta->last_signal;
+               wstats->qual.level = sta->last_signal;
+               wstats->qual.qual = sta->last_qual;
                wstats->qual.noise = sta->last_noise;
                wstats->qual.updated = local->wstats_flags;
        }