svn commit: r187493 - user/sam/wifi/sys/net80211
Sam Leffler
sam at FreeBSD.org
Tue Jan 20 14:06:08 PST 2009
Author: sam
Date: Tue Jan 20 22:06:07 2009
New Revision: 187493
URL: http://svn.freebsd.org/changeset/base/187493
Log:
Change ioctl's that pass channel lists in/out to handle variable-size
arrays instead of a fixed (compile-time) value. We do this in a way
that maintains binary compatibility.
Modified:
user/sam/wifi/sys/net80211/ieee80211_ioctl.c
user/sam/wifi/sys/net80211/ieee80211_ioctl.h
Modified: user/sam/wifi/sys/net80211/ieee80211_ioctl.c
==============================================================================
--- user/sam/wifi/sys/net80211/ieee80211_ioctl.c Tue Jan 20 22:04:30 2009 (r187492)
+++ user/sam/wifi/sys/net80211/ieee80211_ioctl.c Tue Jan 20 22:06:07 2009 (r187493)
@@ -695,21 +695,27 @@ ieee80211_ioctl_getdevcaps(struct ieee80
{
struct ieee80211_devcaps_req *dc;
struct ieee80211req_chaninfo *ci;
- int error;
+ int maxchans, error;
- if (ireq->i_len != sizeof(struct ieee80211_devcaps_req))
- return EINVAL;
- dc = (struct ieee80211_devcaps_req *) malloc(
- sizeof(struct ieee80211_devcaps_req), M_TEMP, M_NOWAIT | M_ZERO);
+ maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) /
+ sizeof(struct ieee80211_channel));
+ /* NB: require 1 so we know ic_nchans is accessible */
+ if (maxchans < 1)
+ return EINVAL;
+ /* constrain max request size, 2K channels is ~24Kbytes */
+ if (maxchans > 2048)
+ maxchans = 2048;
+ dc = (struct ieee80211_devcaps_req *)
+ malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO);
if (dc == NULL)
return ENOMEM;
dc->dc_drivercaps = ic->ic_caps;
dc->dc_cryptocaps = ic->ic_cryptocaps;
dc->dc_htcaps = ic->ic_htcaps;
ci = &dc->dc_chaninfo;
- ic->ic_getradiocaps(ic, &ci->ic_nchans, ci->ic_chans);
+ ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans);
ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
- error = copyout(dc, ireq->i_data, sizeof(*dc));
+ error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
free(dc, M_TEMP);
return error;
}
@@ -1992,17 +1998,34 @@ ieee80211_ioctl_setregdomain(struct ieee
const struct ieee80211req *ireq)
{
struct ieee80211_regdomain_req *reg;
- int error;
+ int nchans, error;
- if (ireq->i_len != sizeof(struct ieee80211_regdomain_req))
+ nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) /
+ sizeof(struct ieee80211_channel));
+ if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
+ "%s: bad # chans, i_len %d nchans %d\n", __func__,
+ ireq->i_len, nchans);
return EINVAL;
- reg = (struct ieee80211_regdomain_req *) malloc(
- sizeof(struct ieee80211_regdomain_req), M_TEMP, M_NOWAIT);
- if (reg == NULL)
+ }
+ reg = (struct ieee80211_regdomain_req *)
+ malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT);
+ if (reg == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
+ "%s: no memory, nchans %d\n", __func__, nchans);
return ENOMEM;
- error = copyin(ireq->i_data, reg, sizeof(*reg));
- if (error == 0)
- error = ieee80211_setregdomain(vap, reg);
+ }
+ error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans));
+ if (error == 0) {
+ /* NB: validate inline channel count against storage size */
+ if (reg->chaninfo.ic_nchans != nchans) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
+ "%s: chan cnt mismatch, %d != %d\n", __func__,
+ reg->chaninfo.ic_nchans, nchans);
+ error = EINVAL;
+ } else
+ error = ieee80211_setregdomain(vap, reg);
+ }
free(reg, M_TEMP);
return (error == 0 ? ENETRESET : error);
Modified: user/sam/wifi/sys/net80211/ieee80211_ioctl.h
==============================================================================
--- user/sam/wifi/sys/net80211/ieee80211_ioctl.h Tue Jan 20 22:04:30 2009 (r187492)
+++ user/sam/wifi/sys/net80211/ieee80211_ioctl.h Tue Jan 20 22:06:07 2009 (r187493)
@@ -313,8 +313,13 @@ struct ieee80211req_chanlist {
*/
struct ieee80211req_chaninfo {
u_int ic_nchans;
- struct ieee80211_channel ic_chans[IEEE80211_CHAN_MAX];
+ struct ieee80211_channel ic_chans[1]; /* NB: variable length */
};
+#define IEEE80211_CHANINFO_SIZE(_nchan) \
+ (sizeof(struct ieee80211req_chaninfo) + \
+ (((_nchan)-1) * sizeof(struct ieee80211_channel)))
+#define IEEE80211_CHANINFO_SPACE(_ci) \
+ IEEE80211_CHANINFO_SIZE((_ci)->ic_nchans)
/*
* Retrieve the WPA/RSN information element for an associated station.
@@ -463,6 +468,11 @@ struct ieee80211_regdomain_req {
struct ieee80211_regdomain rd;
struct ieee80211req_chaninfo chaninfo;
};
+#define IEEE80211_REGDOMAIN_SIZE(_nchan) \
+ (sizeof(struct ieee80211_regdomain_req) + \
+ (((_nchan)-1) * sizeof(struct ieee80211_channel)))
+#define IEEE80211_REGDOMAIN_SPACE(_req) \
+ IEEE80211_REGDOMAIN_SIZE((_req)->chaninfo.ic_nchans)
/*
* Get driver capabilities. Driver, hardware crypto, and
@@ -475,6 +485,11 @@ struct ieee80211_devcaps_req {
uint32_t dc_htcaps; /* HT/802.11n support */
struct ieee80211req_chaninfo dc_chaninfo;
};
+#define IEEE80211_DEVCAPS_SIZE(_nchan) \
+ (sizeof(struct ieee80211_devcaps_req) + \
+ (((_nchan)-1) * sizeof(struct ieee80211_channel)))
+#define IEEE80211_DEVCAPS_SPACE(_dc) \
+ IEEE80211_DEVCAPS_SIZE((_dc)->dc_chaninfo.ic_nchans)
struct ieee80211_chanswitch_req {
struct ieee80211_channel csa_chan; /* new channel */
More information about the svn-src-user
mailing list