PERFORCE change 112271 for review
Sam Leffler
sam at FreeBSD.org
Fri Dec 29 04:15:54 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=112271
Change 112271 by sam at 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;
More information about the p4-projects
mailing list