diff options
-rw-r--r-- | include/net/cfg80211.h | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 49 |
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 | */ |
814 | struct cfg80211_ibss_params { | 815 | struct 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 | ||
3960 | out: | 4009 | out: |