2 * netsniff-ng - the packet sniffing beast
3 * Copyright 2009, 2010 Daniel Borkmann.
4 * Copyright 2014, 2015 Tobias Klauser.
5 * Subject to the GPL, version 2.
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <arpa/inet.h>
17 #include <linux/if_ether.h>
25 * tpacket v3 data structures and constants are not available for older kernel
26 * versions which only support tpacket v2, thus we need protect access to them.
29 static inline bool is_tpacket_v3(int sock
)
31 return get_sockopt_tpacket(sock
) == TPACKET_V3
;
34 static inline size_t get_ring_layout_size(struct ring
*ring
, bool v3
)
36 return v3
? sizeof(ring
->layout3
) : sizeof(ring
->layout
);
39 static inline void setup_rx_ring_layout_v3(struct ring
*ring
)
41 /* Pass out, if this will ever change and we do crap on it! */
42 build_bug_on(offsetof(struct tpacket_req
, tp_frame_nr
) !=
43 offsetof(struct tpacket_req3
, tp_frame_nr
) &&
44 sizeof(struct tpacket_req
) !=
45 offsetof(struct tpacket_req3
, tp_retire_blk_tov
));
47 ring
->layout3
.tp_retire_blk_tov
= 100; /* 0: let kernel decide */
48 ring
->layout3
.tp_sizeof_priv
= 0;
49 ring
->layout3
.tp_feature_req_word
= 0;
52 static inline int rx_ring_get_num(struct ring
*ring
, bool v3
)
54 return v3
? ring
->layout3
.tp_block_nr
: ring
->layout
.tp_frame_nr
;
57 static inline size_t rx_ring_get_size(struct ring
*ring
, bool v3
)
59 return v3
? ring
->layout3
.tp_block_size
: ring
->layout
.tp_frame_size
;
62 int get_rx_net_stats(int sock
, uint64_t *packets
, uint64_t *drops
, bool v3
)
66 struct tpacket_stats k2
;
67 struct tpacket_stats_v3 k3
;
69 socklen_t slen
= v3
? sizeof(stats
.k3
) : sizeof(stats
.k2
);
71 memset(&stats
, 0, sizeof(stats
));
72 ret
= getsockopt(sock
, SOL_PACKET
, PACKET_STATISTICS
, &stats
, &slen
);
74 *packets
= stats
.k3
.tp_packets
;
75 *drops
= stats
.k3
.tp_drops
;
80 static inline bool is_tpacket_v3(int sock __maybe_unused
)
85 static inline size_t get_ring_layout_size(struct ring
*ring
, bool v3 __maybe_unused
)
87 return sizeof(ring
->layout
);
90 static inline void setup_rx_ring_layout_v3(struct ring
*ring __maybe_unused
)
94 static inline size_t rx_ring_get_num(struct ring
*ring
, bool v3 __maybe_unused
)
96 return ring
->layout
.tp_frame_nr
;
99 static inline size_t rx_ring_get_size(struct ring
*ring
, bool v3 __maybe_unused
)
101 return ring
->layout
.tp_frame_size
;
104 int get_rx_net_stats(int sock
, uint64_t *packets
, uint64_t *drops
,
105 bool v3 __maybe_unused
)
108 struct tpacket_stats stats
;
109 socklen_t slen
= sizeof(stats
);
111 memset(&stats
, 0, sizeof(stats
));
112 ret
= getsockopt(sock
, SOL_PACKET
, PACKET_STATISTICS
, &stats
, &slen
);
114 *packets
= stats
.tp_packets
;
115 *drops
= stats
.tp_drops
;
119 #endif /* HAVE_TPACKET3 */
121 void destroy_rx_ring(int sock
, struct ring
*ring
)
124 bool v3
= is_tpacket_v3(sock
);
126 munmap(ring
->mm_space
, ring
->mm_len
);
131 /* In general, this is freed during close(2) anyway. */
135 memset(&ring
->layout
, 0, sizeof(ring
->layout
));
136 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_RX_RING
, &ring
->layout
,
137 sizeof(ring
->layout
));
139 panic("Cannot destroy the RX_RING: %s!\n", strerror(errno
));
142 static void setup_rx_ring_layout(int sock
, struct ring
*ring
, size_t size
,
143 bool jumbo_support
, bool v3
)
145 setup_ring_layout_generic(ring
, size
, jumbo_support
);
148 setup_rx_ring_layout_v3(ring
);
149 set_sockopt_tpacket_v3(sock
);
151 set_sockopt_tpacket_v2(sock
);
154 ring_verify_layout(ring
);
157 static void create_rx_ring(int sock
, struct ring
*ring
, bool verbose
)
160 bool v3
= is_tpacket_v3(sock
);
161 size_t layout_size
= get_ring_layout_size(ring
, v3
);
164 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_RX_RING
, &ring
->raw
,
167 if (errno
== ENOMEM
&& ring
->layout
.tp_block_nr
> 1) {
168 shrink_ring_layout_generic(ring
);
172 panic("Cannot allocate RX_RING!\n");
174 ring
->mm_len
= (size_t) ring
->layout
.tp_block_size
* ring
->layout
.tp_block_nr
;
178 printf("RX,V2: %.2Lf MiB, %u Frames, each %u Byte allocated\n",
179 (long double) ring
->mm_len
/ (1 << 20),
180 ring
->layout
.tp_frame_nr
, ring
->layout
.tp_frame_size
);
182 printf("RX,V3: %.2Lf MiB, %u Blocks, each %u Byte allocated\n",
183 (long double) ring
->mm_len
/ (1 << 20),
184 ring
->layout
.tp_block_nr
, ring
->layout
.tp_block_size
);
189 static void alloc_rx_ring_frames(int sock
, struct ring
*ring
)
191 bool v3
= is_tpacket_v3(sock
);
193 alloc_ring_frames_generic(ring
, rx_ring_get_num(ring
, v3
),
194 rx_ring_get_size(ring
, v3
));
197 static void join_fanout_group(int sock
, uint32_t fanout_group
, uint32_t fanout_type
)
199 uint32_t fanout_opt
= 0;
202 if (fanout_group
== 0)
205 #if defined(PACKET_FANOUT)
206 fanout_opt
= (fanout_group
& 0xffff) | (fanout_type
<< 16);
208 ret
= setsockopt(sock
, SOL_PACKET
, PACKET_FANOUT
, &fanout_opt
,
211 panic("Cannot set fanout ring mode!\n");
213 panic("fanout ring mode is not available!\n");
217 void ring_rx_setup(struct ring
*ring
, int sock
, size_t size
, int ifindex
,
218 struct pollfd
*poll
, bool v3
, bool jumbo_support
,
219 bool verbose
, uint32_t fanout_group
, uint32_t fanout_type
)
221 memset(ring
, 0, sizeof(*ring
));
222 setup_rx_ring_layout(sock
, ring
, size
, jumbo_support
, v3
);
223 create_rx_ring(sock
, ring
, verbose
);
224 mmap_ring_generic(sock
, ring
);
225 alloc_rx_ring_frames(sock
, ring
);
226 bind_ring_generic(sock
, ring
, ifindex
, false);
227 join_fanout_group(sock
, fanout_group
, fanout_type
);
228 prepare_polling(sock
, poll
);