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) {