svn commit: r187869 - projects/vap7/sys/net80211

Sam Leffler sam at FreeBSD.org
Wed Jan 28 13:23:41 PST 2009


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 */


More information about the svn-src-projects mailing list