aboutsummaryrefslogtreecommitdiff
path: root/contrib/libpcap/sf-pcap.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/sf-pcap.c')
-rw-r--r--contrib/libpcap/sf-pcap.c150
1 files changed, 114 insertions, 36 deletions
diff --git a/contrib/libpcap/sf-pcap.c b/contrib/libpcap/sf-pcap.c
index 4294933129dc..659480b44d82 100644
--- a/contrib/libpcap/sf-pcap.c
+++ b/contrib/libpcap/sf-pcap.c
@@ -28,9 +28,7 @@
* dependent values so we can print the dump file on any architecture.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <pcap-types.h>
#ifdef _WIN32
@@ -90,7 +88,7 @@
#define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd
/*
- * Navtel Communcations' format, with nanosecond timestamps,
+ * Navtel Communications' format, with nanosecond timestamps,
* as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
*/
#define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d
@@ -102,16 +100,79 @@
#define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
/*
- * Mechanism for storing information about a capture in the upper
- * 6 bits of a linktype value in a capture file.
+ * This is a timeval as stored in a savefile.
+ * It has to use the same types everywhere, independent of the actual
+ * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some
+ * platforms and 64-bit tv_sec values on other platforms, and writing
+ * out native `struct timeval' values would mean files could only be
+ * read on systems with the same tv_sec size as the system on which
+ * the file was written.
+ *
+ * THe fields are unsigned, as that's what the pcap draft specification
+ * says they are. (That gives pcap a 68-year Y2.038K reprieve, although
+ * in 2106 it runs out for good. pcapng doesn't have that problem,
+ * unless you pick a *really* high time stamp precision.)
+ */
+
+struct pcap_timeval {
+ bpf_u_int32 tv_sec; /* seconds */
+ bpf_u_int32 tv_usec; /* microseconds */
+};
+
+/*
+ * This is a `pcap_pkthdr' as actually stored in a savefile.
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure),
+ * and do not make the time stamp anything other than seconds and
+ * microseconds (e.g., seconds and nanoseconds). Instead:
+ *
+ * introduce a new structure for the new format;
+ *
+ * send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ * a new magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed record
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old record header as well as files with the new record header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes by forking the branch at
+ *
+ * https://github.com/the-tcpdump-group/libpcap/tree/master
*
- * LT_LINKTYPE_EXT(x) extracts the additional information.
+ * and issuing a pull request, so that future versions of libpcap and
+ * programs that use it (such as tcpdump) will be able to read your new
+ * capture file format.
+ */
+
+struct pcap_sf_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) */
+};
+
+/*
+ * How a `pcap_pkthdr' is actually stored in savefiles written
+ * by some patched versions of libpcap (e.g. the ones in Red
+ * Hat Linux 6.1 and 6.2).
*
- * The rest of the bits are for a value describing the link-layer
- * value. LT_LINKTYPE(x) extracts that value.
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ * Instead, introduce a new structure, as per the above.
*/
-#define LT_LINKTYPE(x) ((x) & 0x03FFFFFF)
-#define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000)
+
+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;
+};
static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
@@ -196,7 +257,7 @@ pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
sizeof(hdr) - sizeof(hdr.magic), fp);
if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
errno, "error reading dump file");
} else {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
@@ -242,6 +303,17 @@ pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
}
/*
+ * Check the main reserved field.
+ */
+ if (LT_RESERVED1(hdr.linktype) != 0) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "savefile linktype reserved field not zero (0x%08x)",
+ LT_RESERVED1(hdr.linktype));
+ *err = 1;
+ return NULL;
+ }
+
+ /*
* OK, this is a good pcap file.
* Allocate a pcap_t for it.
*/
@@ -256,7 +328,7 @@ pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
p->version_minor = hdr.version_minor;
p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
- p->snapshot = pcap_adjust_snapshot(p->linktype, hdr.snaplen);
+ p->snapshot = pcapint_adjust_snapshot(p->linktype, hdr.snaplen);
p->next_packet_op = pcap_next_packet;
@@ -414,7 +486,7 @@ pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
return (NULL);
}
- p->cleanup_op = sf_cleanup;
+ p->cleanup_op = pcapint_sf_cleanup;
return (p);
}
@@ -461,7 +533,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
if (amt_read != ps->hdrsize) {
if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "error reading dump file");
return (-1);
} else {
@@ -586,7 +658,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
* However, perhaps some versions of libpcap failed to
* set the snapshot length correctly in the file header
* or the per-packet header, or perhaps this is a
- * corrupted safefile or a savefile built/modified by a
+ * corrupted savefile or a savefile built/modified by a
* fuzz tester, so we check anyway. We grow the buffer
* to be big enough for the snapshot length, read up
* to the snapshot length, discard the rest of the
@@ -615,7 +687,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
amt_read = fread(p->buffer, 1, p->snapshot, fp);
if (amt_read != (bpf_u_int32)p->snapshot) {
if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(p->errbuf,
+ pcapint_fmt_errmsg_for_errno(p->errbuf,
PCAP_ERRBUF_SIZE, errno,
"error reading dump file");
} else {
@@ -646,7 +718,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
bytes_read += amt_read;
if (amt_read != bytes_to_read) {
if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(p->errbuf,
+ pcapint_fmt_errmsg_for_errno(p->errbuf,
PCAP_ERRBUF_SIZE, errno,
"error reading dump file");
} else {
@@ -698,7 +770,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
amt_read = fread(p->buffer, 1, hdr->caplen, fp);
if (amt_read != hdr->caplen) {
if (ferror(fp)) {
- pcap_fmt_errmsg_for_errno(p->errbuf,
+ pcapint_fmt_errmsg_for_errno(p->errbuf,
PCAP_ERRBUF_SIZE, errno,
"error reading dump file");
} else {
@@ -711,7 +783,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
}
*data = p->buffer;
- pcap_post_process(p->linktype, p->swapped, hdr, *data);
+ pcapint_post_process(p->linktype, p->swapped, hdr, *data);
return (1);
}
@@ -727,9 +799,8 @@ sf_write_header(pcap_t *p, FILE *fp, int linktype, int snaplen)
/*
* https://www.tcpdump.org/manpages/pcap-savefile.5.txt states:
- * thiszone: 4-byte time zone offset; this is always 0.
- * sigfigs: 4-byte number giving the accuracy of time stamps
- * in the file; this is always 0.
+ * thiszone (Reserved1): 4-byte not used - SHOULD be filled with 0
+ * sigfigs (Reserved2): 4-byte not used - SHOULD be filled with 0
*/
hdr.thiszone = 0;
hdr.sigfigs = 0;
@@ -772,10 +843,17 @@ pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
return;
/*
* Better not try writing pcap files after
- * 2038-01-19 03:14:07 UTC; switch to pcapng.
+ * 2106-02-07 06:28:15 UTC; switch to pcapng.
+ * (And better not try writing pcap files with time stamps
+ * that predate 1970-01-01 00:00:00 UTC; that's not supported.
+ * You could try using pcapng with the if_tsoffset field in
+ * the IDB for the interface(s) with packets with those time
+ * stamps, but you may also have to get a link-layer type for
+ * IBM Bisync or whatever link layer even older forms
+ * of computer communication used.)
*/
- sf_hdr.ts.tv_sec = (bpf_int32)h->ts.tv_sec;
- sf_hdr.ts.tv_usec = (bpf_int32)h->ts.tv_usec;
+ sf_hdr.ts.tv_sec = (bpf_u_int32)h->ts.tv_sec;
+ sf_hdr.ts.tv_usec = (bpf_u_int32)h->ts.tv_usec;
sf_hdr.caplen = h->caplen;
sf_hdr.len = h->len;
/*
@@ -809,7 +887,7 @@ pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
setvbuf(f, NULL, _IONBF, 0);
#endif
if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't write to %s", fname);
if (f != stdout)
(void)fclose(f);
@@ -861,9 +939,9 @@ pcap_dump_open(pcap_t *p, const char *fname)
* required on Windows, as the file is a binary file
* and must be written in binary mode.
*/
- f = charset_fopen(fname, "wb");
+ f = pcapint_charset_fopen(fname, "wb");
if (f == NULL) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "%s", fname);
return (NULL);
}
@@ -884,14 +962,14 @@ pcap_dump_hopen(pcap_t *p, intptr_t osfd)
fd = _open_osfhandle(osfd, _O_APPEND);
if (fd < 0) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "_open_osfhandle");
return NULL;
}
file = _fdopen(fd, "wb");
if (file == NULL) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "_fdopen");
_close(fd);
return NULL;
@@ -961,9 +1039,9 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
* even though it does nothing. It's required on Windows, as the
* file is a binary file and must be read in binary mode.
*/
- f = charset_fopen(fname, "ab+");
+ f = pcapint_charset_fopen(fname, "ab+");
if (f == NULL) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "%s", fname);
return (NULL);
}
@@ -981,7 +1059,7 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
* compliant systems or on Windows.
*/
if (fseek(f, 0, SEEK_SET) == -1) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't seek to the beginning of %s", fname);
(void)fclose(f);
return (NULL);
@@ -989,7 +1067,7 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
amt_read = fread(&ph, 1, sizeof (ph), f);
if (amt_read != sizeof (ph)) {
if (ferror(f)) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "%s", fname);
(void)fclose(f);
return (NULL);
@@ -1097,7 +1175,7 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
* A header isn't present; attempt to write it.
*/
if (sf_write_header(p, f, linktype, p->snapshot) == -1) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't write to %s", fname);
(void)fclose(f);
return (NULL);
@@ -1112,7 +1190,7 @@ pcap_dump_open_append(pcap_t *p, const char *fname)
* are done at the end of the file in that mode.
*/
if (fseek(f, 0, SEEK_END) == -1) {
- pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
errno, "Can't seek to the end of %s", fname);
(void)fclose(f);
return (NULL);