There is another net80211 ioctl which shares a struct between kernel
and userland: struct ieee80211_stats shown by the netstat -W command.

While it is trivial to recompile netstat when this struct is changed,
giving the kernel a separate struct type would allow us to add, change,
or remove counters in the kernel without impacting userland immediately.
Is this worth it?

For now, the structs are identical so the code copying data out is
kept simple.

The struct is quite large and we could probably get rid of some of these
counters without losing useful debugging information, but that is a
separate problem.

Warning: This diff seems to overflow miniroot71.img on amd64,
breaking 'make release' builds without further changes.

diff 7f506de28f9813c0e2213a45686e27166679219e 
64e5109ffcdce254aca22d4a8a40991e792c0738
blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49
blob + a3a734d32123ff96870e24efeb30651bfd0b50be
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -810,17 +810,11 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
                                break;
                }
                break;
-#if 0
-       case SIOCG80211ZSTATS:
-#endif
        case SIOCG80211STATS:
                ifr = (struct ifreq *)data;
                error = copyout(&ic->ic_stats, ifr->ifr_data,
-                   sizeof(ic->ic_stats));
-#if 0
-               if (cmd == SIOCG80211ZSTATS)
-                       memset(&ic->ic_stats, 0, sizeof(ic->ic_stats));
-#endif
+                   MIN(sizeof(struct ieee80211_statsreq),
+                       sizeof(struct ieee80211_stats)));
                break;
        case SIOCS80211TXPOWER:
                if ((error = suser(curproc)) != 0)
blob - 65e93c23da2d86c0ad259f77b7c9affc85d9038b
blob + fa95ad15b809e16868e2eba4dba66568b5a66cfe
--- sys/net80211/ieee80211_ioctl.h
+++ sys/net80211/ieee80211_ioctl.h
@@ -37,8 +37,8 @@
  * IEEE 802.11 ioctls.
  */
 
-/* per-interface statistics */
-struct ieee80211_stats {
+/* per-interface statistics, corresponds to struct ieee80211_stats */
+struct ieee80211_statsreq {
        u_int32_t       is_rx_badversion;       /* rx frame with bad version */
        u_int32_t       is_rx_tooshort;         /* rx frame too short */
        u_int32_t       is_rx_wrongbss;         /* rx from wrong bssid */
blob - 161853a629887a1aa997480d605d4febd66dd2db
blob + d8845bfc6aa1331110ca22ec949a00932645907e
--- sys/net80211/ieee80211_var.h
+++ sys/net80211/ieee80211_var.h
@@ -214,6 +214,81 @@ struct ieee80211_defrag {
 
 struct ieee80211_node_switch_bss_arg;
 
+/* per-interface statistics */
+struct ieee80211_stats {
+       u_int32_t       is_rx_badversion;       /* rx frame with bad version */
+       u_int32_t       is_rx_tooshort;         /* rx frame too short */
+       u_int32_t       is_rx_wrongbss;         /* rx from wrong bssid */
+       u_int32_t       is_rx_dup;              /* rx discard 'cuz dup */
+       u_int32_t       is_rx_wrongdir;         /* rx w/ wrong direction */
+       u_int32_t       is_rx_mcastecho;        /* rx discard 'cuz mcast echo */
+       u_int32_t       is_rx_notassoc;         /* rx discard 'cuz sta !assoc */
+       u_int32_t       is_rx_nowep;            /* rx w/ wep but wep !config */
+       u_int32_t       is_rx_unencrypted;      /* rx w/o wep but wep config */
+       u_int32_t       is_rx_wepfail;          /* rx wep processing failed */
+       u_int32_t       is_rx_decap;            /* rx decapsulation failed */
+       u_int32_t       is_rx_mgtdiscard;       /* rx discard mgt frames */
+       u_int32_t       is_rx_ctl;              /* rx discard ctrl frames */
+       u_int32_t       is_rx_rstoobig;         /* rx rate set truncated */
+       u_int32_t       is_rx_elem_missing;     /* rx required element missing*/
+       u_int32_t       is_rx_elem_toobig;      /* rx element too big */
+       u_int32_t       is_rx_elem_toosmall;    /* rx element too small */
+       u_int32_t       is_rx_badchan;          /* rx frame w/ invalid chan */
+       u_int32_t       is_rx_chanmismatch;     /* rx frame chan mismatch */
+       u_int32_t       is_rx_nodealloc;        /* rx frame dropped */
+       u_int32_t       is_rx_ssidmismatch;     /* rx frame ssid mismatch  */
+       u_int32_t       is_rx_auth_unsupported; /* rx w/ unsupported auth alg */
+       u_int32_t       is_rx_auth_fail;        /* rx sta auth failure */
+       u_int32_t       is_rx_assoc_bss;        /* rx assoc from wrong bssid */
+       u_int32_t       is_rx_assoc_notauth;    /* rx assoc w/o auth */
+       u_int32_t       is_rx_assoc_capmismatch;/* rx assoc w/ cap mismatch */
+       u_int32_t       is_rx_assoc_norate;     /* rx assoc w/ no rate match */
+       u_int32_t       is_rx_deauth;           /* rx deauthentication */
+       u_int32_t       is_rx_disassoc;         /* rx disassociation */
+       u_int32_t       is_rx_badsubtype;       /* rx frame w/ unknown subtype*/
+       u_int32_t       is_rx_nombuf;           /* rx failed for lack of mbuf */
+       u_int32_t       is_rx_decryptcrc;       /* rx decrypt failed on crc */
+       u_int32_t       is_rx_ahdemo_mgt;       /* rx discard ahdemo mgt frame*/
+       u_int32_t       is_rx_bad_auth;         /* rx bad auth request */
+       u_int32_t       is_tx_nombuf;           /* tx failed for lack of mbuf */
+       u_int32_t       is_tx_nonode;           /* tx failed for no node */
+       u_int32_t       is_tx_unknownmgt;       /* tx of unknown mgt frame */
+       u_int32_t       is_scan_active;         /* active scans started */
+       u_int32_t       is_scan_passive;        /* passive scans started */
+       u_int32_t       is_node_timeout;        /* nodes timed out inactivity */
+       u_int32_t       is_crypto_nomem;        /* no memory for crypto ctx */
+       u_int32_t       is_rx_assoc_badrsnie;   /* rx assoc w/ bad RSN IE */
+       u_int32_t       is_rx_unauth;           /* rx port not valid */
+       u_int32_t       is_tx_noauth;           /* tx port not valid */
+       u_int32_t       is_rx_eapol_key;        /* rx eapol-key frames */
+       u_int32_t       is_rx_eapol_replay;     /* rx replayed eapol frames */
+       u_int32_t       is_rx_eapol_badmic;     /* rx eapol frames w/ bad mic */
+       u_int32_t       is_rx_remmicfail;       /* rx tkip remote mic fails */
+       u_int32_t       is_rx_locmicfail;       /* rx tkip local mic fails */
+       u_int32_t       is_tkip_replays;
+       u_int32_t       is_tkip_icv_errs;
+       u_int32_t       is_ccmp_replays;
+       u_int32_t       is_ccmp_dec_errs;
+       u_int32_t       is_cmac_replays;
+       u_int32_t       is_cmac_icv_errs;
+       u_int32_t       is_pbac_errs;
+       u_int32_t       is_ht_nego_no_mandatory_mcs;
+       u_int32_t       is_ht_nego_no_basic_mcs;
+       u_int32_t       is_ht_nego_bad_crypto;
+       u_int32_t       is_ht_prot_change;
+       u_int32_t       is_ht_rx_ba_agreements;
+       u_int32_t       is_ht_tx_ba_agreements;
+       u_int32_t       is_ht_rx_frame_below_ba_winstart;
+       u_int32_t       is_ht_rx_frame_above_ba_winend;
+       u_int32_t       is_ht_rx_ba_window_slide;
+       u_int32_t       is_ht_rx_ba_window_jump;
+       u_int32_t       is_ht_rx_ba_no_buf;
+       u_int32_t       is_ht_rx_ba_frame_lost;
+       u_int32_t       is_ht_rx_ba_window_gap_timeout;
+       u_int32_t       is_ht_rx_ba_timeout;
+       u_int32_t       is_ht_tx_ba_timeout;
+};
+
 struct ieee80211com {
        struct arpcom           ic_ac;
        LIST_ENTRY(ieee80211com) ic_list;       /* chain of all ieee80211com */
blob - de136e4dd7a5da0f5a38c7de42fd2d646592fcd8
blob + e2076ffeae43eb877108e997828b5481bef0a4e7
--- usr.bin/netstat/net80211.c
+++ usr.bin/netstat/net80211.c
@@ -41,7 +41,7 @@ void
 net80211_ifstats(char *ifname)
 {
        struct ifreq ifr;
-       struct ieee80211_stats stats;
+       struct ieee80211_statsreq stats;
        int s;
 
 #define        p(f, m) printf(m, (unsigned long)stats.f, plural(stats.f))

Reply via email to