Date: Mon, 18 Jul 2005 19:10:46 GMT From: Sam Leffler <sam@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 80472 for review Message-ID: <200507181910.j6IJAkKh071741@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=80472 Change 80472 by sam@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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200507181910.j6IJAkKh071741>