PERFORCE change 80472 for review

Sam Leffler sam at FreeBSD.org
Mon Jul 18 19:10:48 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=80472

Change 80472 by sam at sam_ebb on 2005/07/18 19:10:11

	o fixup get scan results
	o convert get sta table to use an interator
	o change M_WAITOK usage to M_NOWAIT since it appears that
	  it'll be a while before we resolve the issue with drivers
	  holding their lock over ioctl requests

Affected files ...

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

Differences ...

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

@@ -349,7 +349,7 @@
 	int error;
 
 	if (ireq->i_len < sizeof(struct scanreq))
-		return -EFAULT;
+		return EFAULT;
 
 	error = 0;
 	req.space = 0;
@@ -361,13 +361,14 @@
 		void *p;
 
 		space = req.space;
-		MALLOC(p, void *, space, M_TEMP, M_WAITOK);
+		/* XXX M_WAITOK after driver lock released */
+		MALLOC(p, void *, space, M_TEMP, M_NOWAIT);
 		if (p == NULL)
-			return -ENOMEM;
+			return ENOMEM;
 		req.sr = p;
 		ieee80211_scan_iterate(ic, get_scan_result, &req);
 		ireq->i_len = space - req.space;
-		error = copyout(ireq->i_data, p, ireq->i_len);
+		error = copyout(p, ireq->i_data, ireq->i_len);
 		FREE(p, M_TEMP);
 	} else
 		ireq->i_len = 0;
@@ -375,20 +376,59 @@
 	return error;
 }
 
+struct stainforeq {
+	struct ieee80211com *ic;
+	struct ieee80211req_sta_info *si;
+	size_t	space;
+};
+
+static size_t
+sta_space(const struct ieee80211_node *ni, size_t *ielen)
+{
+	*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];
+	if (ni->ni_ath_ie != NULL)
+		*ielen += 2+ni->ni_ath_ie[1];
+	return roundup(sizeof(struct ieee80211req_sta_info) + *ielen,
+		      sizeof(u_int32_t));
+}
+
+static void
+get_sta_space(void *arg, struct ieee80211_node *ni)
+{
+	struct stainforeq *req = arg;
+	struct ieee80211com *ic = ni->ni_ic;
+	size_t ielen;
+
+	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+	    ni->ni_associd == 0)	/* only associated stations */
+		return;
+	req->space += sta_space(ni, &ielen);
+}
+
 static void
-get_sta_info(struct ieee80211req_sta_info *si, const struct ieee80211_node *ni)
+get_sta_info(void *arg, struct ieee80211_node *ni)
 {
+	struct stainforeq *req = arg;
 	struct ieee80211com *ic = ni->ni_ic;
+	struct ieee80211req_sta_info *si;
+	size_t ielen, len;
+	u_int8_t *cp;
 
-	si->isi_ie_len = 0;
-	if (ni->ni_wpa_ie != NULL)
-		si->isi_ie_len += 2+ni->ni_wpa_ie[1];
-	if (ni->ni_wme_ie != NULL)
-		si->isi_ie_len += 2+ni->ni_wme_ie[1];
-	if (ni->ni_ath_ie != NULL)
-		si->isi_ie_len += 2+ni->ni_ath_ie[1];
-	si->isi_len = sizeof(*si) + si->isi_ie_len, sizeof(u_int32_t);
-	si->isi_len = roundup(si->isi_len, sizeof(u_int32_t));
+	if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+	    ni->ni_associd == 0)	/* only associated stations */
+		return;
+	if (ni->ni_chan == IEEE80211_CHAN_ANYC)	/* XXX bogus entry */
+		return;
+	len = sta_space(ni, &ielen);
+	if (len > req->space)
+		return;
+	si = req->si;
+	si->isi_len = len;
+	si->isi_ie_len = ielen;
 	si->isi_freq = ni->ni_chan->ic_freq;
 	si->isi_flags = ni->ni_chan->ic_flags;
 	si->isi_state = ni->ni_flags;
@@ -402,6 +442,7 @@
 		si->isi_nrates = 15;
 	memcpy(si->isi_rates, ni->ni_rates.rs_rates, si->isi_nrates);
 	si->isi_txrate = ni->ni_txrate;
+	si->isi_ie_len = ielen;
 	si->isi_associd = ni->ni_associd;
 	si->isi_txpower = ni->ni_txpower;
 	si->isi_vlan = ni->ni_vlan;
@@ -412,59 +453,64 @@
 		si->isi_txseqs[0] = ni->ni_txseqs[0];
 		si->isi_rxseqs[0] = ni->ni_rxseqs[0];
 	}
-	if (ic->ic_opmode == IEEE80211_M_IBSS || ni->ni_associd != 0)
+	/* NB: leave all cases in case we relax ni_associd == 0 check */
+	if (ieee80211_node_is_authorized(ni))
 		si->isi_inact = ic->ic_inact_run;
-	else if (ieee80211_node_is_authorized(ni))
+	else if (ni->ni_associd != 0)
 		si->isi_inact = ic->ic_inact_auth;
 	else
 		si->isi_inact = ic->ic_inact_init;
 	si->isi_inact = (si->isi_inact - ni->ni_inact) * IEEE80211_INACT_WAIT;
+
+	cp = (u_int8_t *)(si+1);
+	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];
+	}
+	if (ni->ni_ath_ie != NULL) {
+		memcpy(cp, ni->ni_ath_ie, 2+ni->ni_ath_ie[1]);
+		cp += 2+ni->ni_ath_ie[1];
+	}
+
+	req->si = (struct ieee80211req_sta_info *)(((u_int8_t *)si) + len);
+	req->space -= len;
 }
 
 static int
 ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq)
 {
-	union {
-		struct ieee80211req_sta_info info;
-		char data[512];		/* XXX shrink? */
-	} u;
-	struct ieee80211req_sta_info *si = &u.info;
-	struct ieee80211_node_table *nt;
-	struct ieee80211_node *ni;
-	int error, space;
-	u_int8_t *p, *cp;
+	struct stainforeq req;
+	int error;
+
+	if (ireq->i_len < sizeof(struct stainforeq))
+		return EFAULT;
 
-	nt = &ic->ic_sta;
-	p = ireq->i_data;
-	space = ireq->i_len;
 	error = 0;
-	/* XXX locking */
-	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
-		get_sta_info(si, ni);
-		if (si->isi_len > sizeof(u))
-			continue;		/* XXX */
-		if (space < si->isi_len)
-			break;
-		cp = (u_int8_t *)(si+1);
-		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];
-		}
-		if (ni->ni_ath_ie != NULL) {
-			memcpy(cp, ni->ni_ath_ie, 2+ni->ni_ath_ie[1]);
-			cp += 2+ni->ni_ath_ie[1];
-		}
-		error = copyout(si, p, si->isi_len);
-		if (error)
-			break;
-		p += si->isi_len;
-		space -= si->isi_len;
-	}
-	ireq->i_len -= space;
+	req.space = 0;
+	ieee80211_iterate_nodes(&ic->ic_sta, get_sta_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);
+		if (p == NULL)
+			return ENOMEM;
+		req.si = p;
+		ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &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;
 }
 
@@ -824,7 +870,8 @@
 	if (ireq->i_len > IEEE80211_MAX_OPT_IE)
 		return EINVAL;
 	/* NB: data.length is validated by the wireless extensions code */
-	MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_WAITOK);
+	/* XXX M_WAITOK after driver lock released */
+	MALLOC(ie, void *, ireq->i_len, M_DEVBUF, M_NOWAIT);
 	if (ie == NULL)
 		return ENOMEM;
 	error = copyin(ireq->i_data, ie, ireq->i_len);


More information about the p4-projects mailing list