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