|
@@ -3955,6 +3955,55 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (info->attrs[NL80211_ATTR_BSS_BASIC_RATES]) {
|
|
|
+ u8 *rates =
|
|
|
+ nla_data(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
|
|
|
+ int n_rates =
|
|
|
+ nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
|
|
|
+ struct ieee80211_supported_band *sband =
|
|
|
+ wiphy->bands[ibss.channel->band];
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ if (n_rates == 0) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < n_rates; i++) {
|
|
|
+ int rate = (rates[i] & 0x7f) * 5;
|
|
|
+ bool found = false;
|
|
|
+
|
|
|
+ for (j = 0; j < sband->n_bitrates; j++) {
|
|
|
+ if (sband->bitrates[j].bitrate == rate) {
|
|
|
+ found = true;
|
|
|
+ ibss.basic_rates |= BIT(j);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!found) {
|
|
|
+ err = -EINVAL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * If no rates were explicitly configured,
|
|
|
+ * use the mandatory rate set for 11b or
|
|
|
+ * 11a for maximum compatibility.
|
|
|
+ */
|
|
|
+ struct ieee80211_supported_band *sband =
|
|
|
+ wiphy->bands[ibss.channel->band];
|
|
|
+ int j;
|
|
|
+ u32 flag = ibss.channel->band == IEEE80211_BAND_5GHZ ?
|
|
|
+ IEEE80211_RATE_MANDATORY_A :
|
|
|
+ IEEE80211_RATE_MANDATORY_B;
|
|
|
+
|
|
|
+ for (j = 0; j < sband->n_bitrates; j++) {
|
|
|
+ if (sband->bitrates[j].flags & flag)
|
|
|
+ ibss.basic_rates |= BIT(j);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
|
|
|
|
|
|
out:
|