From 6f7131bae7f31ebc39c1e6a044c46b18d7267a30 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 14 Aug 2014 18:30:56 +0200 Subject: [PATCH] netsniff-ng: Protect all access to tpacket v3 structs and constants (this time for real) Commit 0fab564a98d1 ("netsniff-ng: Properly wrap usage of all tpacket v3 structs") took care of protecting _some_ tpacket v3 structures with compile error when building with !HAVE_TPACKET3 (reported by Mike Reeves): > CC ring_rx.c > ring_rx.c: In function 'setup_rx_ring_layout': > ring_rx.c:124: warning: implicit declaration of function 'set_sockopt_tpacket_v3' > ring_rx.c: In function 'sock_rx_net_stats': > ring_rx.c:194: error: field 'k3' has incomplete type > make: *** [netsniff-ng/ring_rx.o] Error 1 Many thanks to Mike for helping me sort out these problems. Reported-by: Mike Reeves Signed-off-by: Tobias Klauser --- ring.h | 4 ++++ ring_rx.c | 53 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/ring.h b/ring.h index 3b02c760..afc8b086 100644 --- a/ring.h +++ b/ring.h @@ -145,6 +145,10 @@ static inline void set_sockopt_tpacket_v3(int sock) { __set_sockopt_tpacket(sock, TPACKET_V3); } +#else +static inline void set_sockopt_tpacket_v3(int sock __maybe_unused) +{ +} #endif static inline int get_sockopt_tpacket(int sock) diff --git a/ring_rx.c b/ring_rx.c index 6f130ee1..8ad64d16 100644 --- a/ring_rx.c +++ b/ring_rx.c @@ -21,6 +21,10 @@ #include "ring_rx.h" #include "built_in.h" +/* + * tpacket v3 data structures and constants are not available for older kernel + * versions which only support tpacket v2, thus we need protect access to them. + */ #ifdef HAVE_TPACKET3 static inline bool is_tpacket_v3(int sock) { @@ -54,6 +58,24 @@ static inline size_t rx_ring_get_size(struct ring *ring, bool v3) { return v3 ? ring->layout3.tp_block_size : ring->layout.tp_frame_size; } + +static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3) +{ + int ret; + union { + struct tpacket_stats k2; + struct tpacket_stats_v3 k3; + } stats; + socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2); + + memset(&stats, 0, sizeof(stats)); + ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen); + if (ret == 0) { + *packets = stats.k3.tp_packets; + *drops = stats.k3.tp_drops; + } + return ret; +} #else static inline bool is_tpacket_v3(int sock __maybe_unused) { @@ -78,6 +100,21 @@ static inline size_t rx_ring_get_size(struct ring *ring, bool v3 __maybe_unused) { return ring->layout.tp_frame_size; } + +static int get_rx_net_stats(int sock, uint64_t *packets, uint64_t *drops, bool v3 __maybe_unused) +{ + int ret; + struct tpacket_stats stats; + socklen_t slen = sizeof(stats); + + memset(&stats, 0, sizeof(stats)); + ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen); + if (ret == 0) { + *packets = stats.tp_packets; + *drops = stats.tp_drops; + } + return ret; +} #endif /* HAVE_TPACKET3 */ void destroy_rx_ring(int sock, struct ring *ring) @@ -188,24 +225,16 @@ void ring_rx_setup(struct ring *ring, int sock, size_t size, int ifindex, void sock_rx_net_stats(int sock, unsigned long seen) { int ret; + uint64_t packets, drops; bool v3 = is_tpacket_v3(sock); - union { - struct tpacket_stats k2; - struct tpacket_stats_v3 k3; - } stats; - socklen_t slen = v3 ? sizeof(stats.k3) : sizeof(stats.k2); - - memset(&stats, 0, sizeof(stats)); - ret = getsockopt(sock, SOL_PACKET, PACKET_STATISTICS, &stats, &slen); - if (ret > -1) { - uint64_t packets = stats.k3.tp_packets; - uint64_t drops = stats.k3.tp_drops; + ret = get_rx_net_stats(sock, &packets, &drops, v3); + if (ret == 0) { printf("\r%12"PRIu64" packets incoming (%"PRIu64" unread on exit)\n", v3 ? (uint64_t)seen : packets, v3 ? packets - seen : 0); printf("\r%12"PRIu64" packets passed filter\n", packets - drops); printf("\r%12"PRIu64" packets failed filter (out of space)\n", drops); - if (stats.k3.tp_packets > 0) + if (packets > 0) printf("\r%12.4lf%% packet droprate\n", (1.0 * drops / packets) * 100.0); } -- 2.11.4.GIT