summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Klauser <tklauser@distanz.ch>2014-05-26 15:10:33 +0200
committerTobias Klauser <tklauser@distanz.ch>2014-08-14 08:48:15 +0200
commit97e6f994785ce5f3f486f8eddb62df964119d121 (patch)
treed8452eb956ec0eb98b13c0a931dd5abce71c3400
parentfa32dcaddab2363cb01acc81bddf7dc3d42ab5b1 (diff)
netsniff-ng: Restore tpacket v2 capturing
Some older systems (e.g. RHEL 6) don't have tpacket v3 available, but only tpacket v2. However, since commit d8cdc6a ("ring: netsniff-ng: migrate capture only to TPACKET_V3") we solely rely on tpacket v3 for capturing packets. This patch restores the possibility to capture using tpacket v2. For now this is just a fallback if the configure script doesn't detect tpacket v3 (and thus HAVE_TPACKET3 isn't set). Thus, on most modern systems this shouldn't change anything and they will continue using tpacket v3. For now this fix contains quite a bit of ugly #ifdefery which should be cleaned up in the future. Fixes #76 Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
-rwxr-xr-xconfigure1
-rw-r--r--dissector.h8
-rw-r--r--netsniff-ng.c72
-rw-r--r--pcap_io.h2
-rw-r--r--ring.h12
-rw-r--r--ring_rx.c17
-rw-r--r--ring_rx.h10
7 files changed, 109 insertions, 13 deletions
diff --git a/configure b/configure
index d9cebff..1ac21be 100755
--- a/configure
+++ b/configure
@@ -206,7 +206,6 @@ EOF
if [ ! -x $TMPDIR/tpacketv3test ] ; then
echo "[NO]"
MISSING_DEFS=1
- tools_remove "netsniff-ng"
else
echo "[YES]"
HAVE_TPACKET3=1
diff --git a/dissector.h b/dissector.h
index f4963c9..c78ea48 100644
--- a/dissector.h
+++ b/dissector.h
@@ -77,15 +77,15 @@ static inline void __show_frame_hdr(uint8_t *packet, size_t len, int linktype,
tprintf("%s %s %u",
packet_types[pkttype] ? : "?",
if_indextoname(s_ll->sll_ifindex, tmp) ? : "?",
- v3 ? hdr.h3->tp_len : hdr.h2->tp_len);
+ tpacket_uhdr(hdr, tp_len, v3));
break;
default:
tprintf("%s %s %u %us.%uns %s\n",
packet_types[pkttype] ? : "?",
if_indextoname(s_ll->sll_ifindex, tmp) ? : "?",
- v3 ? hdr.h3->tp_len : hdr.h2->tp_len,
- v3 ? hdr.h3->tp_sec : hdr.h2->tp_sec,
- v3 ? hdr.h3->tp_nsec : hdr.h2->tp_nsec,
+ tpacket_uhdr(hdr, tp_len, v3),
+ tpacket_uhdr(hdr, tp_sec, v3),
+ tpacket_uhdr(hdr, tp_nsec, v3),
v3 ? "" : __show_ts_source(hdr.h2->tp_status));
break;
}
diff --git a/netsniff-ng.c b/netsniff-ng.c
index af36d5c..984f9ca 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -790,6 +790,7 @@ static void print_pcap_file_stats(int sock, struct ctx *ctx)
}
}
+#ifdef HAVE_TPACKET3
static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx,
int sock, int *fd, unsigned long *frame_count)
{
@@ -856,6 +857,7 @@ next:
}
}
}
+#endif /* HAVE_TPACKET3 */
static void recv_only_or_dump(struct ctx *ctx)
{
@@ -867,8 +869,10 @@ static void recv_only_or_dump(struct ctx *ctx)
struct pollfd rx_poll;
struct sock_fprog bpf_ops;
struct timeval start, end, diff;
- struct block_desc *pbd;
unsigned long frame_count = 0;
+#ifdef HAVE_TPACKET3
+ struct block_desc *pbd;
+#endif
sock = pf_socket();
@@ -939,6 +943,7 @@ static void recv_only_or_dump(struct ctx *ctx)
bug_on(gettimeofday(&start, NULL));
while (likely(sigint == 0)) {
+#ifdef HAVE_TPACKET3
while (user_may_pull_from_rx_block((pbd = (void *)
rx_ring.frames[it].iov_base))) {
walk_t3_block(pbd, ctx, sock, &fd, &frame_count);
@@ -949,6 +954,71 @@ static void recv_only_or_dump(struct ctx *ctx)
if (unlikely(sigint == 1))
break;
}
+#else
+ while (user_may_pull_from_rx(rx_ring.frames[it].iov_base)) {
+ struct frame_map *hdr = rx_ring.frames[it].iov_base;
+ uint8_t *packet = ((uint8_t *) hdr) + hdr->tp_h.tp_mac;
+ pcap_pkthdr_t phdr;
+
+ if (ctx->packet_type != -1)
+ if (ctx->packet_type != hdr->s_ll.sll_pkttype)
+ goto next;
+
+ frame_count++;
+
+ if (unlikely(ring_frame_size(&rx_ring) < hdr->tp_h.tp_snaplen)) {
+ /* XXX: silently ignore for now. We used to
+ * report them with sock_rx_net_stats() */
+ goto next;
+ }
+
+ if (dump_to_pcap(ctx)) {
+ tpacket_hdr_to_pcap_pkthdr(&hdr->tp_h, &hdr->s_ll, &phdr, ctx->magic);
+
+ ret = __pcap_io->write_pcap(fd, &phdr, ctx->magic, packet,
+ pcap_get_length(&phdr, ctx->magic));
+ if (unlikely(ret != (int) pcap_get_total_length(&phdr, ctx->magic)))
+ panic("Write error to pcap!\n");
+ }
+
+ show_frame_hdr(hdr, ctx->print_mode);
+
+ dissector_entry_point(packet, hdr->tp_h.tp_snaplen,
+ ctx->link_type, ctx->print_mode);
+
+ if (frame_count_max != 0) {
+ if (unlikely(frame_count >= frame_count_max)) {
+ sigint = 1;
+ break;
+ }
+ }
+
+next:
+ kernel_may_pull_from_rx(&hdr->tp_h);
+ it = (it + 1) % rx_ring.layout.tp_frame_nr;
+
+ if (unlikely(sigint == 1))
+ break;
+
+ if (dump_to_pcap(ctx)) {
+ if (ctx->dump_mode == DUMP_INTERVAL_SIZE) {
+ interval += hdr->tp_h.tp_snaplen;
+ if (interval > ctx->dump_interval) {
+ next_dump = true;
+ interval = 0;
+ }
+ }
+
+ if (next_dump) {
+ fd = next_multi_pcap_file(ctx, fd);
+ next_dump = false;
+
+ if (unlikely(ctx->verbose))
+ print_pcap_file_stats(sock, ctx);
+ }
+ }
+ }
+#endif /* HAVE_TPACKET3 */
ret = poll(&rx_poll, 1, -1);
if (unlikely(ret < 0)) {
diff --git a/pcap_io.h b/pcap_io.h
index 061c214..529cde0 100644
--- a/pcap_io.h
+++ b/pcap_io.h
@@ -416,6 +416,7 @@ static inline void tpacket_hdr_to_pcap_pkthdr(struct tpacket2_hdr *thdr,
thdr->tp_status, sll, phdr, type);
}
+#ifdef HAVE_TPACKET3
static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
struct sockaddr_ll *sll,
pcap_pkthdr_t *phdr,
@@ -425,6 +426,7 @@ static inline void tpacket3_hdr_to_pcap_pkthdr(struct tpacket3_hdr *thdr,
thdr->tp_snaplen, thdr->tp_len,
0, sll, phdr, type);
}
+#endif
static inline void pcap_pkthdr_to_tpacket_hdr(pcap_pkthdr_t *phdr,
enum pcap_type type,
diff --git a/ring.h b/ring.h
index acf5d59..3b02c76 100644
--- a/ring.h
+++ b/ring.h
@@ -35,6 +35,14 @@ union tpacket_uhdr {
void *raw;
};
+#ifdef HAVE_TPACKET3
+#define tpacket_uhdr(hdr, member, v3) \
+ ((v3) ? ((hdr).h3)->member : ((hdr).h2)->member)
+#else
+#define tpacket_uhdr(hdr, member, v3) \
+ (((hdr).h2)->member)
+#endif /* HAVE_TPACKET3 */
+
struct frame_map {
struct tpacket2_hdr tp_h __aligned_tpacket;
struct sockaddr_ll s_ll __align_tpacket(sizeof(struct tpacket2_hdr));
@@ -132,12 +140,12 @@ static inline void set_sockopt_tpacket_v2(int sock)
__set_sockopt_tpacket(sock, TPACKET_V2);
}
+#ifdef HAVE_TPACKET3
static inline void set_sockopt_tpacket_v3(int sock)
{
-#ifdef HAVE_TPACKET3
__set_sockopt_tpacket(sock, TPACKET_V3);
-#endif
}
+#endif
static inline int get_sockopt_tpacket(int sock)
{
diff --git a/ring_rx.c b/ring_rx.c
index 7a3d21d..1b8dd23 100644
--- a/ring_rx.c
+++ b/ring_rx.c
@@ -58,6 +58,8 @@ static void setup_rx_ring_layout(int sock, struct ring *ring, size_t size,
ring->layout.tp_frame_nr = ring->layout.tp_block_size /
ring->layout.tp_frame_size *
ring->layout.tp_block_nr;
+
+#ifdef HAVE_TPACKET3
if (v3) {
/* Pass out, if this will ever change and we do crap on it! */
build_bug_on(offsetof(struct tpacket_req, tp_frame_nr) !=
@@ -70,6 +72,9 @@ static void setup_rx_ring_layout(int sock, struct ring *ring, size_t size,
ring->layout3.tp_feature_req_word = 0;
set_sockopt_tpacket_v3(sock);
+#else
+ if (0) {
+#endif /* HAVE_TPACKET3 */
} else {
set_sockopt_tpacket_v2(sock);
}
@@ -80,11 +85,17 @@ static void setup_rx_ring_layout(int sock, struct ring *ring, size_t size,
static void create_rx_ring(int sock, struct ring *ring, bool verbose)
{
int ret;
+#ifdef HAVE_TPACKET3
bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
+ size_t layout_size = v3 ? sizeof(ring->layout3) : sizeof(ring->layout);
+#else
+ bool v3 = false;
+ size_t layout_size = sizeof(ring->layout);
+#endif /* HAVE_TPACKET3 */
retry:
ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, &ring->raw,
- v3 ? sizeof(ring->layout3) : sizeof(ring->layout));
+ layout_size);
if (errno == ENOMEM && ring->layout.tp_block_nr > 1) {
ring->layout.tp_block_nr >>= 1;
@@ -115,11 +126,15 @@ static void alloc_rx_ring_frames(int sock, struct ring *ring)
{
int num;
size_t size;
+#if HAVE_TPACKET3
bool v3 = get_sockopt_tpacket(sock) == TPACKET_V3;
if (v3) {
num = ring->layout3.tp_block_nr;
size = ring->layout3.tp_block_size;
+#else
+ if (0) {
+#endif /* HAVE_TPACKET3 */
} else {
num = ring->layout.tp_frame_nr;
size = ring->layout.tp_frame_size;
diff --git a/ring_rx.h b/ring_rx.h
index 02c65bc..60a0eeb 100644
--- a/ring_rx.h
+++ b/ring_rx.h
@@ -22,19 +22,21 @@ static inline int user_may_pull_from_rx(struct tpacket2_hdr *hdr)
return ((hdr->tp_status & TP_STATUS_USER) == TP_STATUS_USER);
}
-static inline int user_may_pull_from_rx_block(struct block_desc *pbd)
+static inline void kernel_may_pull_from_rx(struct tpacket2_hdr *hdr)
{
- return ((pbd->h1.block_status & TP_STATUS_USER) == TP_STATUS_USER);
+ hdr->tp_status = TP_STATUS_KERNEL;
}
-static inline void kernel_may_pull_from_rx(struct tpacket2_hdr *hdr)
+#ifdef HAVE_TPACKET3
+static inline int user_may_pull_from_rx_block(struct block_desc *pbd)
{
- hdr->tp_status = TP_STATUS_KERNEL;
+ return ((pbd->h1.block_status & TP_STATUS_USER) == TP_STATUS_USER);
}
static inline void kernel_may_pull_from_rx_block(struct block_desc *pbd)
{
pbd->h1.block_status = TP_STATUS_KERNEL;
}
+#endif /* HAVE_TPACKETV3 */
#endif /* RX_RING_H */