aboutsummaryrefslogtreecommitdiff
path: root/sys/net80211/ieee80211_ioctl.c
diff options
context:
space:
mode:
authorAndriy Voskoboinyk <avos@FreeBSD.org>2017-03-03 01:06:27 +0000
committerAndriy Voskoboinyk <avos@FreeBSD.org>2017-03-03 01:06:27 +0000
commitdfabbaa0e030669f8ccddb4d52e85e96e8fcf39c (patch)
tree65068da874772f9a391680aaaf06aa2ce6fcfc40 /sys/net80211/ieee80211_ioctl.c
parent0132c9cd4ac9a4cf86ff858e22cab39fc446ba93 (diff)
downloadsrc-dfabbaa0e030669f8ccddb4d52e85e96e8fcf39c.tar.gz
src-dfabbaa0e030669f8ccddb4d52e85e96e8fcf39c.zip
net80211: fix ieee80211_htrateset setup, return EINVAL for an unsupported
ucast/mcast/mgmt HT rate. - Init global ieee80211_htrateset only once; neither ic_htcaps nor ic_txstream is changed when device is attached; - Move global ieee80211_htrateset structure to ieee80211com; there was a possible data race when more than 1 wireless device is used simultaneously; - Discard unsupported rates in ieee80211_ioctl_settxparams(); otherwise, an unsupported value may break connectivity (actually, 'ifconfig wlan0 ucastrate 8' for RTL8188EU results in immediate disconnect + infinite 'device timeout's after it). Tested with: - Intel 6205, STA mode. - RTL8821AU, STA mode. Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D9871
Notes
Notes: svn path=/head/; revision=314575
Diffstat (limited to 'sys/net80211/ieee80211_ioctl.c')
-rw-r--r--sys/net80211/ieee80211_ioctl.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 613eb84a05ef..9939ca34bb89 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -2226,13 +2226,19 @@ checkrate(const struct ieee80211_rateset *rs, int rate)
}
static int
-checkmcs(int mcs)
+checkmcs(const struct ieee80211_htrateset *rs, int mcs)
{
+ int rate_val = IEEE80211_RV(mcs);
+ int i;
+
if (mcs == IEEE80211_FIXED_RATE_NONE)
return 1;
if ((mcs & IEEE80211_RATE_MCS) == 0) /* MCS always have 0x80 set */
return 0;
- return (mcs & 0x7f) <= 31; /* XXX could search ht rate set */
+ for (i = 0; i < rs->rs_nrates; i++)
+ if (IEEE80211_RV(rs->rs_rates[i]) == rate_val)
+ return 1;
+ return 0;
}
static int
@@ -2242,6 +2248,7 @@ ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_txparams_req parms; /* XXX stack use? */
struct ieee80211_txparam *src, *dst;
+ const struct ieee80211_htrateset *rs_ht;
const struct ieee80211_rateset *rs;
int error, mode, changed, is11n, nmodes;
@@ -2260,23 +2267,24 @@ ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
src = &parms.params[mode];
dst = &vap->iv_txparms[mode];
rs = &ic->ic_sup_rates[mode]; /* NB: 11n maps to legacy */
+ rs_ht = &ic->ic_sup_htrates;
is11n = (mode == IEEE80211_MODE_11NA ||
mode == IEEE80211_MODE_11NG);
if (src->ucastrate != dst->ucastrate) {
if (!checkrate(rs, src->ucastrate) &&
- (!is11n || !checkmcs(src->ucastrate)))
+ (!is11n || !checkmcs(rs_ht, src->ucastrate)))
return EINVAL;
changed++;
}
if (src->mcastrate != dst->mcastrate) {
if (!checkrate(rs, src->mcastrate) &&
- (!is11n || !checkmcs(src->mcastrate)))
+ (!is11n || !checkmcs(rs_ht, src->mcastrate)))
return EINVAL;
changed++;
}
if (src->mgmtrate != dst->mgmtrate) {
if (!checkrate(rs, src->mgmtrate) &&
- (!is11n || !checkmcs(src->mgmtrate)))
+ (!is11n || !checkmcs(rs_ht, src->mgmtrate)))
return EINVAL;
changed++;
}