On Tue, Mar 08, 2022 at 03:55:48PM +0100, Stefan Sperling wrote:
> On Mon, Mar 07, 2022 at 03:04:06PM -0700, Theo de Raadt wrote:
> > > For now, the structs are identical so the code copying data out is
> > > kept simple.
> > 
> > I think this is unwise, and you should write the field-by-field copying
> > function at the same time, otherwise this is just asking for trouble.
> > You really cannot wait until an intentional change.
> 
> Sure, here it is.

On second thought, avoiding the malloc/free dance is better.
The struct is still small enough to fit on the stack.

diff refs/heads/master refs/heads/statsreq
blob - 85d795d745eb21fd218056c2f3faf7fbc2c7fe49
blob + 62938001ed22fc133a0c98e27ef5690c978e21f3
--- sys/net80211/ieee80211_ioctl.c
+++ sys/net80211/ieee80211_ioctl.c
@@ -55,6 +55,8 @@ void   ieee80211_node2req(struct ieee80211com *,
            const struct ieee80211_node *, struct ieee80211_nodereq *);
 void    ieee80211_req2node(struct ieee80211com *,
            const struct ieee80211_nodereq *, struct ieee80211_node *);
+void ieee80211_stats2req(struct ieee80211_statsreq *,
+           struct ieee80211_stats *);
 
 void
 ieee80211_node2req(struct ieee80211com *ic, const struct ieee80211_node *ni,
@@ -180,6 +182,89 @@ ieee80211_req2node(struct ieee80211com *ic, const stru
 }
 
 void
+ieee80211_stats2req(struct ieee80211_statsreq *req,
+    struct ieee80211_stats *stats)
+{
+       memset(req, 0, sizeof(*req));
+
+       req->is_rx_badversion = stats->is_rx_badversion;
+       req->is_rx_tooshort = stats->is_rx_tooshort;
+       req->is_rx_wrongbss = stats->is_rx_wrongbss;
+       req->is_rx_dup = stats->is_rx_dup;
+       req->is_rx_wrongdir = stats->is_rx_wrongdir;
+       req->is_rx_mcastecho = stats->is_rx_mcastecho;
+       req->is_rx_notassoc = stats->is_rx_notassoc;
+       req->is_rx_nowep = stats->is_rx_nowep;
+       req->is_rx_unencrypted = stats->is_rx_unencrypted;
+       req->is_rx_wepfail = stats->is_rx_wepfail;
+       req->is_rx_decap = stats->is_rx_decap;
+       req->is_rx_mgtdiscard = stats->is_rx_mgtdiscard;
+       req->is_rx_ctl = stats->is_rx_ctl;
+       req->is_rx_rstoobig = stats->is_rx_rstoobig;
+       req->is_rx_elem_missing = stats->is_rx_elem_missing;
+       req->is_rx_elem_toobig = stats->is_rx_elem_toobig;
+       req->is_rx_elem_toosmall = stats->is_rx_elem_toosmall;
+       req->is_rx_badchan = stats->is_rx_badchan;
+       req->is_rx_chanmismatch = stats->is_rx_chanmismatch;
+       req->is_rx_nodealloc = stats->is_rx_nodealloc;
+       req->is_rx_ssidmismatch = stats->is_rx_ssidmismatch;
+       req->is_rx_auth_unsupported = stats->is_rx_auth_unsupported;
+       req->is_rx_auth_fail = stats->is_rx_auth_fail;
+       req->is_rx_assoc_bss = stats->is_rx_assoc_bss;
+       req->is_rx_assoc_notauth = stats->is_rx_assoc_notauth;
+       req->is_rx_assoc_capmismatch = stats->is_rx_assoc_capmismatch;
+       req->is_rx_assoc_norate = stats->is_rx_assoc_norate;
+       req->is_rx_deauth = stats->is_rx_deauth;
+       req->is_rx_disassoc = stats->is_rx_disassoc;
+       req->is_rx_badsubtype = stats->is_rx_badsubtype;
+       req->is_rx_nombuf = stats->is_rx_nombuf;
+       req->is_rx_decryptcrc = stats->is_rx_decryptcrc;
+       req->is_rx_ahdemo_mgt = stats->is_rx_ahdemo_mgt;
+       req->is_rx_bad_auth = stats->is_rx_bad_auth;
+       req->is_tx_nombuf = stats->is_tx_nombuf;
+       req->is_tx_nonode = stats->is_tx_nonode;
+       req->is_tx_unknownmgt = stats->is_tx_unknownmgt;
+       req->is_scan_active = stats->is_scan_active;
+       req->is_scan_passive = stats->is_scan_passive;
+       req->is_node_timeout = stats->is_node_timeout;
+       req->is_crypto_nomem = stats->is_crypto_nomem;
+       req->is_rx_assoc_badrsnie = stats->is_rx_assoc_badrsnie;
+       req->is_rx_unauth = stats->is_rx_unauth;
+       req->is_tx_noauth = stats->is_tx_noauth;
+       req->is_rx_eapol_key = stats->is_rx_eapol_key;
+       req->is_rx_eapol_replay = stats->is_rx_eapol_replay;
+       req->is_rx_eapol_badmic = stats->is_rx_eapol_badmic;
+       req->is_rx_remmicfail = stats->is_rx_remmicfail;
+       req->is_rx_locmicfail = stats->is_rx_locmicfail;
+       req->is_tkip_replays = stats->is_tkip_replays;
+       req->is_tkip_icv_errs = stats->is_tkip_icv_errs;
+       req->is_ccmp_replays = stats->is_ccmp_replays;
+       req->is_ccmp_dec_errs = stats->is_ccmp_dec_errs;
+       req->is_cmac_replays = stats->is_cmac_replays;
+       req->is_cmac_icv_errs = stats->is_cmac_icv_errs;
+       req->is_pbac_errs = stats->is_pbac_errs;
+       req->is_ht_nego_no_mandatory_mcs = stats->is_ht_nego_no_mandatory_mcs;
+       req->is_ht_nego_no_basic_mcs = stats->is_ht_nego_no_basic_mcs;
+       req->is_ht_nego_bad_crypto = stats->is_ht_nego_bad_crypto;
+       req->is_ht_prot_change = stats->is_ht_prot_change;
+       req->is_ht_rx_ba_agreements = stats->is_ht_rx_ba_agreements;
+       req->is_ht_tx_ba_agreements = stats->is_ht_tx_ba_agreements;
+       req->is_ht_rx_frame_below_ba_winstart =
+           stats->is_ht_rx_frame_below_ba_winstart;
+       req->is_ht_rx_frame_above_ba_winend =
+           stats->is_ht_rx_frame_above_ba_winend;
+       req->is_ht_rx_ba_window_slide = stats->is_ht_rx_ba_window_slide;
+       req->is_ht_rx_ba_window_jump = stats->is_ht_rx_ba_window_jump;
+       req->is_ht_rx_ba_no_buf = stats->is_ht_rx_ba_no_buf;
+       req->is_ht_rx_ba_frame_lost = stats->is_ht_rx_ba_frame_lost;
+       req->is_ht_rx_ba_window_gap_timeout =
+           stats->is_ht_rx_ba_window_gap_timeout;
+       req->is_ht_rx_ba_timeout = stats->is_ht_rx_ba_timeout;
+       req->is_ht_tx_ba_timeout = stats->is_ht_tx_ba_timeout;
+}
+
+
+void
 ieee80211_disable_wep(struct ieee80211com *ic)
 {
        struct ieee80211_key *k;
@@ -471,6 +556,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t
        struct ieee80211_node *ni;
        struct ieee80211_chaninfo chaninfo;
        struct ieee80211_chanreq_all *allchans;
+       struct ieee80211_statsreq statsreq;
        u_int32_t flags;
 
        switch (cmd) {
@@ -810,17 +896,10 @@ 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
+               ieee80211_stats2req(&statsreq, &ic->ic_stats);
+               error = copyout(&statsreq, ifr->ifr_data, sizeof(statsreq));
                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