Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Dec 2006 07:35:07 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 112271 for review
Message-ID:  <200612290735.kBT7Z7QM074840@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=112271

Change 112271 by sam@sam_ebb on 2006/12/29 07:34:08

	bring compat code into the new world order

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#61 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#61 (text+ko) ====

@@ -260,6 +260,7 @@
 	return error;
 }
 
+#define COMPAT_FREEBSD6
 #ifdef COMPAT_FREEBSD6
 #define	IEEE80211_IOC_SCAN_RESULTS_OLD	24
 
@@ -281,86 +282,120 @@
 	/* variable length SSID followed by IE data */
 };
 
+struct oscanreq {
+	struct scan_result_old *sr;
+	size_t space;
+};
+
+static size_t
+old_scan_space(const struct ieee80211_scan_entry *se, int *ielen)
+{
+	size_t len;
+
+	*ielen = 0;
+	if (se->se_wpa_ie != NULL)
+		*ielen += 2+se->se_wpa_ie[1];
+	if (se->se_wme_ie != NULL)
+		*ielen += 2+se->se_wme_ie[1];
+	/*
+	 * NB: ie's can be no more than 255 bytes and the max 802.11
+	 * packet is <3Kbytes so we are sure this doesn't overflow
+	 * 16-bits; if this is a concern we can drop the ie's.
+	 */
+	len = sizeof(struct scan_result_old) + se->se_ssid[1] + *ielen;
+	return roundup(len, sizeof(u_int32_t));
+}
+
 static void
-old_get_scan_result(struct scan_result_old *sr,
-	const struct ieee80211_node *ni)
+old_get_scan_space(void *arg, const struct ieee80211_scan_entry *se)
+{
+	struct oscanreq *req = arg;
+	int ielen;
+
+	req->space += old_scan_space(se, &ielen);
+}
+
+static void
+old_get_scan_result(void *arg, const struct ieee80211_scan_entry *se)
 {
-	struct ieee80211com *ic = ni->ni_ic;
-	u_int ielen;
+	struct oscanreq *req = arg;
+	struct scan_result_old *sr;
+	int ielen, len, nr, nxr;
+	u_int8_t *cp;
+
+	len = old_scan_space(se, &ielen);
+	if (len > req->space)
+		return;
 
+	sr = req->sr;
 	memset(sr, 0, sizeof(*sr));
-	sr->isr_ssid_len = ni->ni_esslen;
-	ielen = 0;
-	if (ni->ni_wpa_ie != NULL)
-		ielen += 2+ni->ni_wpa_ie[1];
-	if (ni->ni_wme_ie != NULL)
-		ielen += 2+ni->ni_wme_ie[1];
+	sr->isr_ssid_len = se->se_ssid[1];
 	/* NB: beware of overflow, isr_ie_len is 8 bits */
 	sr->isr_ie_len = (ielen > 255 ? 0 : ielen);
-	sr->isr_len = sizeof(*sr) + sr->isr_ssid_len + sr->isr_ie_len;
-	sr->isr_len = roundup(sr->isr_len, sizeof(u_int32_t));
-	if (ni->ni_chan != IEEE80211_CHAN_ANYC) {
-		sr->isr_freq = ni->ni_chan->ic_freq;
-		sr->isr_flags = ni->ni_chan->ic_flags;
+	sr->isr_len = len;
+	sr->isr_freq = se->se_chan->ic_freq;
+	sr->isr_flags = se->se_chan->ic_flags;
+	sr->isr_rssi = se->se_rssi;
+	sr->isr_noise = se->se_noise;
+	sr->isr_intval = se->se_intval;
+	sr->isr_capinfo = se->se_capinfo;
+	sr->isr_erp = se->se_erp;
+	IEEE80211_ADDR_COPY(sr->isr_bssid, se->se_bssid);
+	nr = min(se->se_rates[1], IEEE80211_RATE_MAXSIZE);
+	memcpy(sr->isr_rates, se->se_rates+2, nr);
+	nxr = min(se->se_xrates[1], IEEE80211_RATE_MAXSIZE - nr);
+	memcpy(sr->isr_rates+nr, se->se_xrates+2, nxr);
+	sr->isr_nrates = nr + nxr;
+
+	cp = (u_int8_t *)(sr+1);
+	memcpy(cp, se->se_ssid+2, sr->isr_ssid_len);
+	cp += sr->isr_ssid_len;
+	if (sr->isr_ie_len) {
+		if (se->se_wpa_ie != NULL) {
+			memcpy(cp, se->se_wpa_ie, 2+se->se_wpa_ie[1]);
+			cp += 2+se->se_wpa_ie[1];
+		}
+		if (se->se_wme_ie != NULL) {
+			memcpy(cp, se->se_wme_ie, 2+se->se_wme_ie[1]);
+			cp += 2+se->se_wme_ie[1];
+		}
 	}
-	sr->isr_rssi = ic->ic_node_getrssi(ni);
-	sr->isr_intval = ni->ni_intval;
-	sr->isr_capinfo = ni->ni_capinfo;
-	sr->isr_erp = ni->ni_erp;
-	IEEE80211_ADDR_COPY(sr->isr_bssid, ni->ni_bssid);
-	sr->isr_nrates = ni->ni_rates.rs_nrates;
-	if (sr->isr_nrates > 15)
-		sr->isr_nrates = 15;
-	memcpy(sr->isr_rates, ni->ni_rates.rs_rates, sr->isr_nrates);
+
+	req->space -= len;
+	req->sr = (struct scan_result_old *)(((u_int8_t *)sr) + len);
 }
 
 static int
 old_getscanresults(struct ieee80211com *ic, struct ieee80211req *ireq)
 {
-	union {
-		struct scan_result_old res;
-		char data[512];		/* XXX shrink? */
-	} u;
-	struct scan_result_old *sr = &u.res;
-	struct ieee80211_node_table *nt;
-	struct ieee80211_node *ni;
-	int error, space;
-	u_int8_t *p, *cp;
+	struct oscanreq req;
+	int error;
+
+	if (ireq->i_len < sizeof(struct scan_result_old))
+		return EFAULT;
 
-	p = ireq->i_data;
-	space = ireq->i_len;
 	error = 0;
-	/* XXX locking */
-	nt =  &ic->ic_scan;
-	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
-		/* NB: skip pre-scan node state */ 
-		if (ni->ni_chan == IEEE80211_CHAN_ANYC)
-			continue;
-		old_get_scan_result(sr, ni);
-		if (sr->isr_len > sizeof(u))
-			continue;		/* XXX */
-		if (space < sr->isr_len)
-			break;
-		cp = (u_int8_t *)(sr+1);
-		memcpy(cp, ni->ni_essid, ni->ni_esslen);
-		cp += ni->ni_esslen;
-		if (sr->isr_ie_len) {
-			if (ni->ni_wpa_ie != NULL) {
-				memcpy(cp, ni->ni_wpa_ie, 2+ni->ni_wpa_ie[1]);
-				cp += 2+ni->ni_wpa_ie[1];
-			}
-			if (ni->ni_wme_ie != NULL) {
-				memcpy(cp, ni->ni_wme_ie, 2+ni->ni_wme_ie[1]);
-				cp += 2+ni->ni_wme_ie[1];
-			}
-		}
-		error = copyout(sr, p, sr->isr_len);
-		if (error)
-			break;
-		p += sr->isr_len;
-		space -= sr->isr_len;
-	}
-	ireq->i_len -= space;
+	req.space = 0;
+	ieee80211_scan_iterate(ic, old_get_scan_space, &req);
+	if (req.space > ireq->i_len)
+		req.space = ireq->i_len;
+	if (req.space > 0) {
+		size_t space;
+		void *p;
+
+		space = req.space;
+		/* XXX M_WAITOK after driver lock released */
+		MALLOC(p, void *, space, M_TEMP, M_NOWAIT | M_ZERO);
+		if (p == NULL)
+			return ENOMEM;
+		req.sr = p;
+		ieee80211_scan_iterate(ic, old_get_scan_result, &req);
+		ireq->i_len = space - req.space;
+		error = copyout(p, ireq->i_data, ireq->i_len);
+		FREE(p, M_TEMP);
+	} else
+		ireq->i_len = 0;
+
 	return error;
 }
 #endif /* COMPAT_FREEBSD6 */
@@ -970,6 +1005,11 @@
 	case IEEE80211_IOC_WPAIE2:
 		error = ieee80211_ioctl_getwpaie(ic, ireq, ireq->i_type);
 		break;
+#ifdef COMPAT_FREEBSD6
+	case IEEE80211_IOC_SCAN_RESULTS_OLD:
+		error = old_getscanresults(ic, ireq);
+		break;
+#endif
 	case IEEE80211_IOC_SCAN_RESULTS:
 		error = ieee80211_ioctl_getscanresults(ic, ireq);
 		break;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200612290735.kBT7Z7QM074840>