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 <pab...@redhat.com>
---
 netsniff-ng.c | 32 ++++++++++++++++++++++----------
 1 file 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);
-- 
1.8.3.1

-- 
You received this message because you are subscribed to the Google Groups 
"netsniff-ng" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to netsniff-ng+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to