net80211(4): validate supplied roam:rate values from ifconfig(8)

MFC after:	4 days
This commit is contained in:
Andriy Voskoboinyk 2019-02-06 13:01:21 +00:00
parent 64d41eddd7
commit 545619f3f2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=343837

View File

@ -2203,18 +2203,6 @@ ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
return (error == 0 ? ENETRESET : error);
}
static int
ieee80211_ioctl_setroam(struct ieee80211vap *vap,
const struct ieee80211req *ireq)
{
if (ireq->i_len != sizeof(vap->iv_roamparms))
return EINVAL;
/* XXX validate params */
/* XXX? ENETRESET to push to device? */
return copyin(ireq->i_data, vap->iv_roamparms,
sizeof(vap->iv_roamparms));
}
static int
checkrate(const struct ieee80211_rateset *rs, int rate)
{
@ -2244,6 +2232,73 @@ checkmcs(const struct ieee80211_htrateset *rs, int mcs)
return 0;
}
static int
ieee80211_ioctl_setroam(struct ieee80211vap *vap,
const struct ieee80211req *ireq)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_roamparams_req *parms;
struct ieee80211_roamparam *src, *dst;
const struct ieee80211_htrateset *rs_ht;
const struct ieee80211_rateset *rs;
int changed, error, mode, is11n, nmodes;
if (ireq->i_len != sizeof(vap->iv_roamparms))
return EINVAL;
parms = IEEE80211_MALLOC(sizeof(*parms), M_TEMP,
IEEE80211_M_NOWAIT | IEEE80211_M_ZERO);
if (parms == NULL)
return ENOMEM;
error = copyin(ireq->i_data, parms, ireq->i_len);
if (error != 0)
goto fail;
changed = 0;
nmodes = IEEE80211_MODE_MAX;
/* validate parameters and check if anything changed */
for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
if (isclr(ic->ic_modecaps, mode))
continue;
src = &parms->params[mode];
dst = &vap->iv_roamparms[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);
/* XXX TODO: 11ac */
if (src->rate != dst->rate) {
if (!checkrate(rs, src->rate) &&
(!is11n || !checkmcs(rs_ht, src->rate))) {
error = EINVAL;
goto fail;
}
changed++;
}
if (src->rssi != dst->rssi)
changed++;
}
if (changed) {
/*
* Copy new parameters in place and notify the
* driver so it can push state to the device.
*/
/* XXX locking? */
for (mode = IEEE80211_MODE_11A; mode < nmodes; mode++) {
if (isset(ic->ic_modecaps, mode))
vap->iv_roamparms[mode] = parms->params[mode];
}
if (vap->iv_roaming == IEEE80211_ROAMING_DEVICE)
error = ERESTART;
}
fail: IEEE80211_FREE(parms, M_TEMP);
return error;
}
static int
ieee80211_ioctl_settxparams(struct ieee80211vap *vap,
const struct ieee80211req *ireq)