diff options
author | Tobias Klauser <tklauser@distanz.ch> | 2014-08-14 18:30:56 +0200 |
---|---|---|
committer | Tobias Klauser <tklauser@distanz.ch> | 2014-08-14 18:38:51 +0200 |
commit | 6f7131bae7f31ebc39c1e6a044c46b18d7267a30 (patch) | |
tree | d91d540ad7e813ed8e069bc770dc77e14870d835 | |
parent | d1eef162252faf60b2acb19a1df70c1a5e13ecd2 (diff) |
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 <luke@geekempire.com>
Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rw-r--r-- | ring.h | 4 | ||||
-rw-r--r-- | ring_rx.c | 53 |
2 files changed, 45 insertions, 12 deletions
@@ -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) @@ -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); } |