From owner-svn-src-projects@FreeBSD.ORG Wed Jan 28 21:23:41 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F3DA9106567F; Wed, 28 Jan 2009 21:23:40 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E12538FC36; Wed, 28 Jan 2009 21:23:40 +0000 (UTC) (envelope-from sam@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0SLNe1o033802; Wed, 28 Jan 2009 21:23:40 GMT (envelope-from sam@svn.freebsd.org) Received: (from sam@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0SLNefP033800; Wed, 28 Jan 2009 21:23:40 GMT (envelope-from sam@svn.freebsd.org) Message-Id: <200901282123.n0SLNefP033800@svn.freebsd.org> From: Sam Leffler Date: Wed, 28 Jan 2009 21:23:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187869 - projects/vap7/sys/net80211 X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Jan 2009 21:23:41 -0000 Author: sam Date: Wed Jan 28 21:23:40 2009 New Revision: 187869 URL: http://svn.freebsd.org/changeset/base/187869 Log: merge r187801: remove assumptions about the max # channels in ioctl's merge r187060: add missing break Modified: projects/vap7/sys/net80211/ (props changed) projects/vap7/sys/net80211/ieee80211_ioctl.c projects/vap7/sys/net80211/ieee80211_ioctl.h Modified: projects/vap7/sys/net80211/ieee80211_ioctl.c ============================================================================== --- projects/vap7/sys/net80211/ieee80211_ioctl.c Wed Jan 28 21:19:59 2009 (r187868) +++ projects/vap7/sys/net80211/ieee80211_ioctl.c Wed Jan 28 21:23:40 2009 (r187869) @@ -695,23 +695,29 @@ 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, IEEE80211_CHAN_MAX, &ci->ic_nchans, ci->ic_chans); + ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans); KASSERT(ci->ic_nchans <= maxchans, ("nchans %d maxchans %d", ci->ic_nchans, maxchans)); 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; } @@ -1567,17 +1573,21 @@ static __noinline int ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq) { struct ieee80211com *ic = vap->iv_ic; - struct ieee80211req_chanlist list; - u_char chanlist[IEEE80211_CHAN_BYTES]; - int i, nchan, error; + uint8_t *chanlist, *list; + int i, nchan, maxchan, error; - if (ireq->i_len != sizeof(list)) - return EINVAL; - error = copyin(ireq->i_data, &list, sizeof(list)); + if (ireq->i_len > sizeof(ic->ic_chan_active)) + ireq->i_len = sizeof(ic->ic_chan_active); + list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP, + M_NOWAIT | M_ZERO); + if (list == NULL) + return ENOMEM; + error = copyin(ireq->i_data, list, ireq->i_len); if (error) return error; - memset(chanlist, 0, sizeof(chanlist)); nchan = 0; + chanlist = list + ireq->i_len; /* NB: zero'd already */ + maxchan = ireq->i_len * NBBY; for (i = 0; i < ic->ic_nchans; i++) { const struct ieee80211_channel *c = &ic->ic_channels[i]; /* @@ -1585,7 +1595,7 @@ ieee80211_ioctl_setchanlist(struct ieee8 * available channels so users can do things like specify * 1-255 to get all available channels. */ - if (isset(list.ic_channels, c->ic_ieee)) { + if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) { setbit(chanlist, c->ic_ieee); nchan++; } @@ -1595,8 +1605,9 @@ ieee80211_ioctl_setchanlist(struct ieee8 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */ isclr(chanlist, ic->ic_bsschan->ic_ieee)) ic->ic_bsschan = IEEE80211_CHAN_ANYC; - memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active)); + memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES); ieee80211_scan_flush(vap); + free(list, M_TEMP); return ENETRESET; } @@ -1994,17 +2005,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); @@ -2698,6 +2726,7 @@ ieee80211_ioctl_set80211(struct ieee8021 break; case 3: if ((vap->iv_caps & IEEE80211_C_WPA) != IEEE80211_C_WPA) + return EOPNOTSUPP; flags |= IEEE80211_F_WPA1 | IEEE80211_F_WPA2; break; default: /* Can't set any -> error */ Modified: projects/vap7/sys/net80211/ieee80211_ioctl.h ============================================================================== --- projects/vap7/sys/net80211/ieee80211_ioctl.h Wed Jan 28 21:19:59 2009 (r187868) +++ projects/vap7/sys/net80211/ieee80211_ioctl.h Wed Jan 28 21:23:40 2009 (r187869) @@ -299,13 +299,13 @@ struct ieee80211req_maclist { }; /* - * Set the active channel list. Note this list is - * intersected with the available channel list in - * calculating the set of channels actually used in - * scanning. + * Set the active channel list by IEEE channel #: each channel + * to be marked active is set in a bit vector. Note this list is + * intersected with the available channel list in calculating + * the set of channels actually used in scanning. */ struct ieee80211req_chanlist { - uint8_t ic_channels[IEEE80211_CHAN_BYTES]; + uint8_t ic_channels[32]; /* NB: can be variable length */ }; /* @@ -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 */