diff options
author | sam <sam@FreeBSD.org> | 2006-08-10 06:04:00 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2006-08-10 06:04:00 +0000 |
commit | f478fb33440a58df160e9e0fdb46d32c71ba7ede (patch) | |
tree | 5d9451f537fe86a6d4c48d5f8a0bc88d1276c9d5 /sys/net80211 | |
parent | 3e268c1af8db8bbe81f51070edda54056ad65176 (diff) | |
download | FreeBSD-src-f478fb33440a58df160e9e0fdb46d32c71ba7ede.zip FreeBSD-src-f478fb33440a58df160e9e0fdb46d32c71ba7ede.tar.gz |
More statistics fixups:
o change rssi to be signed in ieee80211_nodestats
o add noise floor in ieee80211_nodestats (use an implicit hole to
preserve layout); return it as zero until we can update the api's
so the driver can provide noise floor data
o add a bandaid so IEEE80211_IOC_STA_STATS works for sta mode; when
all nodes are in the station table this will no longer be needed
o fix braino in IEEE80211_IOC_STA_INFO implementation; was supposed
to take a mac address and return info for that sta or all stations
if ff:ff:ff:ff:ff was supplied--but somehow this didn't get implemented;
implement the intended semantics and leave a compat shim at the old
ioctl number for the previous api
Reviewed by: mlaier
MFC after: 3 weeks
Diffstat (limited to 'sys/net80211')
-rw-r--r-- | sys/net80211/ieee80211_ioctl.c | 86 | ||||
-rw-r--r-- | sys/net80211/ieee80211_ioctl.h | 8 |
2 files changed, 76 insertions, 18 deletions
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index 3bb41b4..db619e3 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -960,8 +960,12 @@ ieee80211_ioctl_getstastats(struct ieee80211com *ic, struct ieee80211req *ireq) if (error != 0) return error; ni = ieee80211_find_node(&ic->ic_sta, macaddr); - if (ni == NULL) - return EINVAL; /* XXX */ + if (ni == NULL) { + /* XXX special-case sta-mode until bss is node in ic_sta */ + if (ic->ic_opmode != IEEE80211_M_STA) + return ENOENT; + ni = ieee80211_ref_node(ic->ic_bss); + } if (ireq->i_len > sizeof(struct ieee80211req_sta_stats)) ireq->i_len = sizeof(struct ieee80211req_sta_stats); /* NB: copy out only the statistics */ @@ -1251,6 +1255,7 @@ get_sta_info(void *arg, struct ieee80211_node *ni) si->isi_state = ni->ni_flags; si->isi_authmode = ni->ni_authmode; si->isi_rssi = ic->ic_node_getrssi(ni); + si->isi_noise = 0; /* XXX */ si->isi_capinfo = ni->ni_capinfo; si->isi_erp = ni->ni_erp; IEEE80211_ADDR_COPY(si->isi_macaddr, ni->ni_macaddr); @@ -1293,40 +1298,86 @@ get_sta_info(void *arg, struct ieee80211_node *ni) } static int -ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) +getstainfo_common(struct ieee80211com *ic, struct ieee80211req *ireq, + struct ieee80211_node *ni, int off) { struct stainforeq req; + size_t space; + void *p; int error; - if (ireq->i_len < sizeof(struct stainforeq)) - return EFAULT; - error = 0; req.space = 0; - ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); + if (ni == NULL) + ieee80211_iterate_nodes(&ic->ic_sta, get_sta_space, &req); + else + get_sta_space(&req, ni); 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; + if (p == NULL) { + error = ENOMEM; + goto bad; + } req.si = p; - ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); + if (ni == NULL) + ieee80211_iterate_nodes(&ic->ic_sta, get_sta_info, &req); + else + get_sta_info(&req, ni); ireq->i_len = space - req.space; - error = copyout(p, ireq->i_data, ireq->i_len); + error = copyout(p, (u_int8_t *) ireq->i_data+off, ireq->i_len); FREE(p, M_TEMP); } else ireq->i_len = 0; - +bad: + if (ni != NULL) + ieee80211_free_node(ni); return error; } static int +ieee80211_ioctl_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + u_int8_t macaddr[IEEE80211_ADDR_LEN]; + const int off = __offsetof(struct ieee80211req_sta_req, info); + struct ieee80211_node *ni; + int error; + + if (ireq->i_len < sizeof(struct ieee80211req_sta_req)) + return EFAULT; + error = copyin(ireq->i_data, macaddr, IEEE80211_ADDR_LEN); + if (error != 0) + return error; + if (IEEE80211_ADDR_EQ(macaddr, ic->ic_ifp->if_broadcastaddr)) { + ni = NULL; + } else { + ni = ieee80211_find_node(&ic->ic_sta, macaddr); + if (ni == NULL) { + /* XXX special-case sta-mode until bss is in ic_sta */ + if (ic->ic_opmode != IEEE80211_M_STA) + return EINVAL; /* XXX */ + ni = ieee80211_ref_node(ic->ic_bss); + } + } + return getstainfo_common(ic, ireq, ni, off); +} + +#ifdef COMPAT_FREEBSD6 +#define IEEE80211_IOC_STA_INFO_OLD 45 + +static int +old_getstainfo(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + if (ireq->i_len < sizeof(struct ieee80211req_sta_info)) + return EFAULT; + return getstainfo_common(ic, ireq, NULL, 0); +} +#endif /* COMPAT_FREEBSD6 */ + +static int ieee80211_ioctl_getstatxpow(struct ieee80211com *ic, struct ieee80211req *ireq) { struct ieee80211_node *ni; @@ -1611,6 +1662,11 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re case IEEE80211_IOC_STA_TXPOW: error = ieee80211_ioctl_getstatxpow(ic, ireq); break; +#ifdef COMPAT_FREEBSD6 + case IEEE80211_IOC_STA_INFO_OLD: + error = old_getstainfo(ic, ireq); + break; +#endif case IEEE80211_IOC_STA_INFO: error = ieee80211_ioctl_getstainfo(ic, ireq); break; diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index a76630a..7200f5a 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -42,7 +42,7 @@ #include <net80211/ieee80211_crypto.h> /* - * Per/node (station) statistics available when operating as an AP. + * Per/node (station) statistics. */ struct ieee80211_nodestats { u_int32_t ns_rx_data; /* rx data frames */ @@ -311,7 +311,7 @@ struct ieee80211req_sta_info { u_int16_t isi_flags; /* channel flags */ u_int16_t isi_state; /* state flags */ u_int8_t isi_authmode; /* authentication algorithm */ - u_int8_t isi_rssi; + int8_t isi_rssi; /* receive signal strength */ u_int8_t isi_capinfo; /* capabilities */ u_int8_t isi_erp; /* ERP element */ u_int8_t isi_macaddr[IEEE80211_ADDR_LEN]; @@ -319,6 +319,7 @@ struct ieee80211req_sta_info { /* negotiated rates */ u_int8_t isi_rates[IEEE80211_RATE_MAXSIZE]; u_int8_t isi_txrate; /* index to isi_rates[] */ + int8_t isi_noise; /* noise floor */ u_int16_t isi_ie_len; /* IE length */ u_int16_t isi_associd; /* assoc response */ u_int16_t isi_txpower; /* current tx power */ @@ -433,7 +434,7 @@ struct ieee80211req { #define IEEE80211_IOC_CHANINFO 42 /* channel info list */ #define IEEE80211_IOC_TXPOWMAX 43 /* max tx power for channel */ #define IEEE80211_IOC_STA_TXPOW 44 /* per-station tx power limit */ -#define IEEE80211_IOC_STA_INFO 45 /* station/neighbor info */ +/* 45 was IEEE80211_IOC_STA_INFO */ #define IEEE80211_IOC_WME_CWMIN 46 /* WME: ECWmin */ #define IEEE80211_IOC_WME_CWMAX 47 /* WME: ECWmax */ #define IEEE80211_IOC_WME_AIFS 48 /* WME: AIFSN */ @@ -450,6 +451,7 @@ struct ieee80211req { #define IEEE80211_IOC_BURST 75 /* packet bursting */ #define IEEE80211_IOC_SCAN_RESULTS 76 /* get scan results */ #define IEEE80211_IOC_BMISSTHRESHOLD 77 /* beacon miss threshold */ +#define IEEE80211_IOC_STA_INFO 78 /* station/neighbor info */ /* * Scan result data returned for IEEE80211_IOC_SCAN_RESULTS. |