aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h2
-rw-r--r--net/mac80211/ibss.c4
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/wireless/nl80211.c49
4 files changed, 56 insertions, 1 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 22ab9d88cf4a..64374f4cb7c6 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -810,6 +810,7 @@ struct cfg80211_disassoc_request {
810 * @beacon_interval: beacon interval to use 810 * @beacon_interval: beacon interval to use
811 * @privacy: this is a protected network, keys will be configured 811 * @privacy: this is a protected network, keys will be configured
812 * after joining 812 * after joining
813 * @basic_rates: bitmap of basic rates to use when creating the IBSS
813 */ 814 */
814struct cfg80211_ibss_params { 815struct cfg80211_ibss_params {
815 u8 *ssid; 816 u8 *ssid;
@@ -818,6 +819,7 @@ struct cfg80211_ibss_params {
818 u8 *ie; 819 u8 *ie;
819 u8 ssid_len, ie_len; 820 u8 ssid_len, ie_len;
820 u16 beacon_interval; 821 u16 beacon_interval;
822 u32 basic_rates;
821 bool channel_fixed; 823 bool channel_fixed;
822 bool privacy; 824 bool privacy;
823}; 825};
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index bfd7286488c7..9f4e64ed8b83 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -172,6 +172,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
172 rcu_assign_pointer(ifibss->presp, skb); 172 rcu_assign_pointer(ifibss->presp, skb);
173 173
174 sdata->vif.bss_conf.beacon_int = beacon_int; 174 sdata->vif.bss_conf.beacon_int = beacon_int;
175 sdata->vif.bss_conf.basic_rates = basic_rates;
175 bss_change = BSS_CHANGED_BEACON_INT; 176 bss_change = BSS_CHANGED_BEACON_INT;
176 bss_change |= ieee80211_reset_erp_info(sdata); 177 bss_change |= ieee80211_reset_erp_info(sdata);
177 bss_change |= BSS_CHANGED_BSSID; 178 bss_change |= BSS_CHANGED_BSSID;
@@ -529,7 +530,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
529 sdata->drop_unencrypted = 0; 530 sdata->drop_unencrypted = 0;
530 531
531 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, 532 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
532 ifibss->channel, 3, /* first two are basic */ 533 ifibss->channel, ifibss->basic_rates,
533 capability, 0); 534 capability, 0);
534} 535}
535 536
@@ -859,6 +860,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
859 sdata->u.ibss.fixed_bssid = false; 860 sdata->u.ibss.fixed_bssid = false;
860 861
861 sdata->u.ibss.privacy = params->privacy; 862 sdata->u.ibss.privacy = params->privacy;
863 sdata->u.ibss.basic_rates = params->basic_rates;
862 864
863 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 865 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
864 866
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9d753a02a2e4..c3c2be3f8a2c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -387,6 +387,8 @@ struct ieee80211_if_ibss {
387 unsigned long request; 387 unsigned long request;
388 unsigned long last_scan_completed; 388 unsigned long last_scan_completed;
389 389
390 u32 basic_rates;
391
390 bool timer_running; 392 bool timer_running;
391 393
392 bool fixed_bssid; 394 bool fixed_bssid;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c65e67e9231c..41529aca794c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3955,6 +3955,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
3955 } 3955 }
3956 } 3956 }
3957 3957
3958 if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
3959 u8 *rates =
3960 nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
3961 int n_rates =
3962 nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
3963 struct ieee80211_supported_band *sband =
3964 wiphy->bands[ibss.channel->band];
3965 int i, j;
3966
3967 if (n_rates == 0) {
3968 err = -EINVAL;
3969 goto out;
3970 }
3971
3972 for (i = 0; i < n_rates; i++) {
3973 int rate = (rates[i] & 0x7f) * 5;
3974 bool found = false;
3975
3976 for (j = 0; j < sband->n_bitrates; j++) {
3977 if (sband->bitrates[j].bitrate == rate) {
3978 found = true;
3979 ibss.basic_rates |= BIT(j);
3980 break;
3981 }
3982 }
3983 if (!found) {
3984 err = -EINVAL;
3985 goto out;
3986 }
3987 }
3988 } else {
3989 /*
3990 * If no rates were explicitly configured,
3991 * use the mandatory rate set for 11b or
3992 * 11a for maximum compatibility.
3993 */
3994 struct ieee80211_supported_band *sband =
3995 wiphy->bands[ibss.channel->band];
3996 int j;
3997 u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
3998 IEEE80211_RATE_MANDATORY_A :
3999 IEEE80211_RATE_MANDATORY_B;
4000
4001 for (j = 0; j < sband->n_bitrates; j++) {
4002 if (sband->bitrates[j].flags & flag)
4003 ibss.basic_rates |= BIT(j);
4004 }
4005 }
4006
3958 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys); 4007 err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
3959 4008
3960out: 4009out: