Different link types get different printers. But until now, different
link types would get the same pcap dumper. This is mostly fine, except
for on LOOP-type interfaces, which have raw layer 3 packets. On these,
the first four bytes of the packet represent the AF family, which the
pcap data format doesn't care for. So, trying to open the result in
Wireshark is gibberish. This patch makes packet dumping act like packet
printing, which certain link types special cased. In this case,
LOOP-type packets get the first four bytes shaved off.
---
 usr.sbin/tcpdump/interface.h  |  1 +
 usr.sbin/tcpdump/print-null.c |  9 +++++++++
 usr.sbin/tcpdump/tcpdump.c    | 19 ++++++++++++++++++-
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git usr.sbin/tcpdump/interface.h usr.sbin/tcpdump/interface.h
index 602be405723..147036f7d1e 100644
--- usr.sbin/tcpdump/interface.h
+++ usr.sbin/tcpdump/interface.h
@@ -249,6 +249,7 @@ extern void nfsreply_print(const u_char *, u_int, const 
u_char *);
 extern void nfsreq_print(const u_char *, u_int, const u_char *);
 extern void ns_print(const u_char *, u_int, int);
 extern void ntp_print(const u_char *, u_int);
+extern void loop_if_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
 extern void loop_if_print(u_char *, const struct pcap_pkthdr *, const u_char 
*);
 extern void null_if_print(u_char *, const struct pcap_pkthdr *, const u_char 
*);
 extern void ospf_print(const u_char *, u_int, const u_char *);
diff --git usr.sbin/tcpdump/print-null.c usr.sbin/tcpdump/print-null.c
index f90f5e9030c..94457532c90 100644
--- usr.sbin/tcpdump/print-null.c
+++ usr.sbin/tcpdump/print-null.c
@@ -96,6 +96,15 @@ null_print(const u_char *p, const struct ip *ip, u_int 
length)
        }
 }
 
+void
+loop_if_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
+{
+       struct pcap_pkthdr h_mod = *h;
+       h_mod.caplen -= sizeof(u_int);
+       h_mod.len -= sizeof(u_int);
+       pcap_dump(user, &h_mod, p + sizeof(u_int));
+}
+
 void
 loop_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p)
 {
diff --git usr.sbin/tcpdump/tcpdump.c usr.sbin/tcpdump/tcpdump.c
index bbdba4d4c48..40323870ed9 100644
--- usr.sbin/tcpdump/tcpdump.c
+++ usr.sbin/tcpdump/tcpdump.c
@@ -110,6 +110,23 @@ struct printer {
 #define DLT_ATM_RFC1483 11
 #endif
 
+static struct printer dumpers[] = {
+       { loop_if_dump,                 DLT_LOOP },
+       { NULL,                         0 },
+};
+
+static pcap_handler
+lookup_dumper(int type)
+{
+       struct printer *p;
+
+       for (p = dumpers; p->f; ++p) {
+               if (type == p->type)
+                       return p->f;
+       }
+       return pcap_dump;
+}
+
 static struct printer printers[] = {
        { ether_if_print,               DLT_EN10MB },
        { ether_if_print,               DLT_IEEE802 },
@@ -507,7 +524,7 @@ main(int argc, char **argv)
                        fflush(fp);
                        setvbuf(fp, NULL, _IONBF, 0);
                }
-               printer = pcap_dump;
+               printer = lookup_dumper(pcap_datalink(pd));
                pcap_userdata = (u_char *)p;
        } else {
                printer = lookup_printer(pcap_datalink(pd));
-- 
2.29.1

Reply via email to