summaryrefslogtreecommitdiff
path: root/netsniff-ng.c
diff options
context:
space:
mode:
authorPaolo Abeni <pabeni@redhat.com>2016-07-21 15:25:27 +0200
committerTobias Klauser <tklauser@distanz.ch>2016-07-21 15:39:05 +0200
commit81f8c546d90b7615e0e6a6777445b10b4263d598 (patch)
tree41b697375caac65a0312cb662bc6f147716d46c0 /netsniff-ng.c
parent20f72d2b68969f75b0a116e49b133363d4b6fb9a (diff)
netsniff-ng: Skip duplicated packets on loopback device
When sniffing on the loopback device, each packet will be seen twice, once per direction. To avoid duplicates, explicitly skip OUTGOING packets received from loopback, if no packet_type filter is explicitly set. Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
Diffstat (limited to 'netsniff-ng.c')
-rw-r--r--netsniff-ng.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/netsniff-ng.c b/netsniff-ng.c
index 8d22151..4cfabc1 100644
--- a/netsniff-ng.c
+++ b/netsniff-ng.c
@@ -55,7 +55,7 @@ enum dump_mode {
struct ctx {
char *device_in, *device_out, *device_trans, *filter, *prefix;
- int cpu, rfraw, dump, print_mode, dump_dir, packet_type;
+ int cpu, rfraw, dump, print_mode, dump_dir, packet_type, lo_ifindex;
unsigned long kpull, dump_interval, tx_bytes, tx_packets;
size_t reserve_size;
bool randomize, promiscuous, enforce, jumbo, dump_bpf, hwtimestamp, verbose;
@@ -410,6 +410,18 @@ out:
printf("\r%12lu sec, %lu usec in total\n", diff.tv_sec, diff.tv_usec);
}
+static inline bool skip_packet(struct ctx *ctx, struct sockaddr_ll *sll)
+{
+ if (ctx->packet_type != -1)
+ return ctx->packet_type != sll->sll_pkttype;
+
+ /* when receving from the loopback device, each packet is seen twice,
+ * so drop the outgoing ones to avoid duplicates
+ */
+ return (sll->sll_ifindex == ctx->lo_ifindex) &&
+ (sll->sll_pkttype == PACKET_OUTGOING);
+}
+
static void receive_to_xmit(struct ctx *ctx)
{
short ifflags = 0;
@@ -470,9 +482,8 @@ static void receive_to_xmit(struct ctx *ctx)
ctx->pkts_seen++;
- if (ctx->packet_type != -1)
- if (ctx->packet_type != hdr_in->s_ll.sll_pkttype)
- goto next;
+ if (skip_packet(ctx, &hdr_in->s_ll))
+ goto next;
hdr_out = tx_ring.frames[it_out].iov_base;
out = ((uint8_t *) hdr_out) + TPACKET2_HDRLEN - sizeof(struct sockaddr_ll);
@@ -942,9 +953,8 @@ static void walk_t3_block(struct block_desc *pbd, struct ctx *ctx,
uint8_t *packet = ((uint8_t *) hdr + hdr->tp_mac);
pcap_pkthdr_t phdr;
- if (ctx->packet_type != -1)
- if (ctx->packet_type != sll->sll_pkttype)
- goto next;
+ if (skip_packet(ctx, sll))
+ goto next;
ctx->pkts_seen++;
@@ -1071,9 +1081,8 @@ static void recv_only_or_dump(struct ctx *ctx)
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;
+ if (skip_packet(ctx, &hdr->s_ll))
+ goto next;
ctx->pkts_seen++;
@@ -1523,6 +1532,9 @@ int main(int argc, char **argv)
if (!ctx.device_in)
ctx.device_in = xstrdup("any");
+ if (!strcmp(ctx.device_in, "any") || !strcmp(ctx.device_in, "lo"))
+ ctx.lo_ifindex = device_ifindex("lo");
+
register_signal(SIGINT, signal_handler);
register_signal(SIGQUIT, signal_handler);
register_signal(SIGTERM, signal_handler);