I received a pcap file from someone containing kuznetzov's pcap format. According to "upstream" libpcap[0] this format uses struct pcap_sf_patched_pkthdr, which is: struct pcap_sf_patched_pkthdr { struct pcap_timeval ts; /* time stamp */ bpf_u_int32 caplen; /* length of portion present */ bpf_u_int32 len; /* length of this packet (off wire) */ int index; unsigned short protocol; unsigned char pkt_type; };
So compared to a normal pkthdr this adds[1]: - index: interface index - protocol: ethernet packet type - pkt_type: broadcast/multicast/etc. indication I don't think this information is particularly useful per say, so why not just skip the 8 bytes and continue business as usual? No public header change and allows me read the dump. OK? martijn@ [0] https://www.tcpdump.org/ [1] https://wiki.wireshark.org/Development/LibpcapFileFormat#modified-pcap Index: usr.sbin/tcpdump/privsep.h =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/privsep.h,v retrieving revision 1.12 diff -u -p -r1.12 privsep.h --- usr.sbin/tcpdump/privsep.h 18 Mar 2019 00:09:22 -0000 1.12 +++ usr.sbin/tcpdump/privsep.h 1 Dec 2022 19:53:47 -0000 @@ -19,8 +19,6 @@ #include <pcap-int.h> -#define TCPDUMP_MAGIC 0xa1b2c3d4 - enum cmd_types { PRIV_OPEN_BPF, /* open a bpf descriptor */ PRIV_OPEN_DUMP, /* open dump file for reading */ Index: usr.sbin/tcpdump/privsep_pcap.c =================================================================== RCS file: /cvs/src/usr.sbin/tcpdump/privsep_pcap.c,v retrieving revision 1.25 diff -u -p -r1.25 privsep_pcap.c --- usr.sbin/tcpdump/privsep_pcap.c 28 Jun 2019 13:32:51 -0000 1.25 +++ usr.sbin/tcpdump/privsep_pcap.c 1 Dec 2022 19:53:47 -0000 @@ -334,6 +334,7 @@ priv_pcap_live(const char *dev, int slen static void swap_hdr(struct pcap_file_header *hp) { + hp->magic = swap32(hp->magic); hp->version_major = swap16(hp->version_major); hp->version_minor = swap16(hp->version_minor); hp->thiszone = swap32(hp->thiszone); @@ -390,20 +391,25 @@ priv_pcap_offline(const char *fname, cha goto bad; } - if (hdr.magic != TCPDUMP_MAGIC) { - if (swap32(hdr.magic) != TCPDUMP_MAGIC) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, - "bad dump file format"); - goto bad; - } + switch (hdr.magic) { + case TCPDUMP_MAGIC: + case TCPDUMP_MAGIC_KUZNETZOV: + break; + case swap32(TCPDUMP_MAGIC): + case swap32(TCPDUMP_MAGIC_KUZNETZOV): p->sf.swapped = 1; swap_hdr(&hdr); + break; + default: + snprintf(errbuf, PCAP_ERRBUF_SIZE, "bad dump file format"); + goto bad; } if (hdr.version_major < PCAP_VERSION_MAJOR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic file format"); goto bad; } + p->sf.magic = hdr.magic; p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; p->linktype = hdr.linktype; Index: lib/libpcap/pcap-int.h =================================================================== RCS file: /cvs/src/lib/libpcap/pcap-int.h,v retrieving revision 1.14 diff -u -p -r1.14 pcap-int.h --- lib/libpcap/pcap-int.h 5 Apr 2018 03:47:27 -0000 1.14 +++ lib/libpcap/pcap-int.h 1 Dec 2022 19:53:47 -0000 @@ -51,6 +51,9 @@ struct pcap_opt { int immediate; /* immediate mode - deliver packets as soon as they arrive */ }; +#define TCPDUMP_MAGIC 0xa1b2c3d4 +#define TCPDUMP_MAGIC_KUZNETZOV 0xa1b2cd34 + /* * Savefile */ @@ -59,6 +62,7 @@ struct pcap_sf { int swapped; int version_major; int version_minor; + uint32_t magic; u_char *base; }; Index: lib/libpcap/savefile.c =================================================================== RCS file: /cvs/src/lib/libpcap/savefile.c,v retrieving revision 1.17 diff -u -p -r1.17 savefile.c --- lib/libpcap/savefile.c 27 May 2020 04:24:01 -0000 1.17 +++ lib/libpcap/savefile.c 1 Dec 2022 19:53:47 -0000 @@ -45,8 +45,6 @@ #include "pcap-int.h" -#define TCPDUMP_MAGIC 0xa1b2c3d4 - /* * We use the "receiver-makes-right" approach to byte order, * because time is at a premium when we are writing the file. @@ -90,6 +88,7 @@ sf_write_header(FILE *fp, int linktype, static void swap_hdr(struct pcap_file_header *hp) { + hp->magic = SWAPLONG(hp->magic); hp->version_major = SWAPSHORT(hp->version_major); hp->version_minor = SWAPSHORT(hp->version_minor); hp->thiszone = SWAPLONG(hp->thiszone); @@ -145,19 +144,24 @@ pcap_fopen_offline(FILE *fp, char *errbu pcap_strerror(errno)); goto bad; } - if (hdr.magic != TCPDUMP_MAGIC) { - if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, - "bad dump file format"); - goto bad; - } + switch (hdr.magic) { + case TCPDUMP_MAGIC: + case TCPDUMP_MAGIC_KUZNETZOV: + break; + case swap32(TCPDUMP_MAGIC): + case swap32(TCPDUMP_MAGIC_KUZNETZOV): p->sf.swapped = 1; swap_hdr(&hdr); + break; + default: + snprintf(errbuf, PCAP_ERRBUF_SIZE, "bad dump file format"); + goto bad; } if (hdr.version_major < PCAP_VERSION_MAJOR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic file format"); goto bad; } + p->sf.magic = hdr.magic; p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; p->linktype = hdr.linktype; @@ -217,6 +221,11 @@ sf_next_packet(pcap_t *p, struct pcap_pk if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) { /* probably an EOF, though could be a truncated packet */ return (1); + } + if (p->sf.magic == TCPDUMP_MAGIC_KUZNETZOV) { + /* The kuznetzov header doesn't contain anything interesting */ + if (fseek(fp, 8, SEEK_CUR) == -1) + return (1); } if (p->sf.swapped) {