forked from osmocom/wireshark
Add in a gross heuristic that attempts to detect files with the version
of the "libpcap" patch that changes the per-packet header but not the magic number - it seems to work on at least one capture file I tried it on. Give the modified "libpcap" format a WTAP_FILE type of its own (so that, in the future, we could support writing captures out in that format, possibly). svn path=/trunk/; revision=987
This commit is contained in:
parent
148d0c865a
commit
d49b158b49
|
@ -1,6 +1,6 @@
|
|||
/* libpcap.c
|
||||
*
|
||||
* $Id: libpcap.c,v 1.22 1999/11/06 08:42:00 guy Exp $
|
||||
* $Id: libpcap.c,v 1.23 1999/11/06 10:31:47 guy Exp $
|
||||
*
|
||||
* Wiretap Library
|
||||
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
|
||||
|
@ -41,17 +41,17 @@
|
|||
PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
|
||||
is a byte-swapped version of that.
|
||||
|
||||
PCAP_MUTANT_MAGIC is for Alexey Kuznetsov's modified "libpcap"
|
||||
PCAP_MODIFIED_MAGIC is for Alexey Kuznetsov's modified "libpcap"
|
||||
format, as generated on Linux systems that have a "libpcap" with
|
||||
his patches, at
|
||||
|
||||
http://ftp.sunet.se/pub/os/Linux/ip-routing/lbl-tools/
|
||||
|
||||
applied; PCAP_SWAPPED_MUTANT_MAGIC is the byte-swapped version. */
|
||||
applied; PCAP_SWAPPED_MODIFIED_MAGIC is the byte-swapped version. */
|
||||
#define PCAP_MAGIC 0xa1b2c3d4
|
||||
#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
|
||||
#define PCAP_MUTANT_MAGIC 0xa1b2cd34
|
||||
#define PCAP_SWAPPED_MUTANT_MAGIC 0x34cdb2a1
|
||||
#define PCAP_MODIFIED_MAGIC 0xa1b2cd34
|
||||
#define PCAP_SWAPPED_MODIFIED_MAGIC 0x34cdb2a1
|
||||
|
||||
/* Macros to byte-swap 32-bit and 16-bit quantities. */
|
||||
#define BSWAP32(x) \
|
||||
|
@ -87,7 +87,7 @@ struct pcaprec_hdr {
|
|||
};
|
||||
|
||||
/* "libpcap" record header for Alexey's patched version. */
|
||||
struct pcaprec_mutant_hdr {
|
||||
struct pcaprec_modified_hdr {
|
||||
struct pcaprec_hdr hdr; /* the regular header */
|
||||
guint32 ifindex; /* index, in *capturing* machine's list of
|
||||
interfaces, of the interface on which this
|
||||
|
@ -97,6 +97,7 @@ struct pcaprec_mutant_hdr {
|
|||
};
|
||||
|
||||
static int libpcap_read(wtap *wth, int *err);
|
||||
static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr);
|
||||
static int libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
|
||||
const u_char *pd, int *err);
|
||||
static int libpcap_dump_close(wtap_dumper *wdh, int *err);
|
||||
|
@ -164,8 +165,10 @@ int libpcap_open(wtap *wth, int *err)
|
|||
int bytes_read;
|
||||
guint32 magic;
|
||||
struct pcap_hdr hdr;
|
||||
gboolean byte_swapped = FALSE;
|
||||
gboolean mutant = FALSE;
|
||||
gboolean byte_swapped;
|
||||
gboolean modified;
|
||||
struct pcaprec_hdr first_rec_hdr;
|
||||
struct pcaprec_hdr second_rec_hdr;
|
||||
|
||||
/* Read in the number that should be at the start of a "libpcap" file */
|
||||
file_seek(wth->fh, 0, SEEK_SET);
|
||||
|
@ -185,28 +188,28 @@ int libpcap_open(wtap *wth, int *err)
|
|||
case PCAP_MAGIC:
|
||||
/* Host that wrote it has our byte order. */
|
||||
byte_swapped = FALSE;
|
||||
mutant = FALSE;
|
||||
modified = FALSE;
|
||||
break;
|
||||
|
||||
case PCAP_MUTANT_MAGIC:
|
||||
case PCAP_MODIFIED_MAGIC:
|
||||
/* Host that wrote it has our byte order, but was running
|
||||
a program using the patched "libpcap". */
|
||||
byte_swapped = FALSE;
|
||||
mutant = TRUE;
|
||||
modified = TRUE;
|
||||
break;
|
||||
|
||||
case PCAP_SWAPPED_MAGIC:
|
||||
/* Host that wrote it has a byte order opposite to ours. */
|
||||
byte_swapped = TRUE;
|
||||
mutant = FALSE;
|
||||
modified = FALSE;
|
||||
break;
|
||||
|
||||
case PCAP_SWAPPED_MUTANT_MAGIC:
|
||||
case PCAP_SWAPPED_MODIFIED_MAGIC:
|
||||
/* Host that wrote it out has a byte order opposite to
|
||||
ours, and was running a program using the patched
|
||||
"libpcap". */
|
||||
byte_swapped = TRUE;
|
||||
mutant = TRUE;
|
||||
modified = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -248,15 +251,112 @@ int libpcap_open(wtap *wth, int *err)
|
|||
}
|
||||
|
||||
/* This is a libpcap file */
|
||||
wth->file_type = WTAP_FILE_PCAP;
|
||||
wth->file_type = modified ? WTAP_FILE_PCAP_MODIFIED : WTAP_FILE_PCAP;
|
||||
wth->capture.pcap = g_malloc(sizeof(libpcap_t));
|
||||
wth->capture.pcap->byte_swapped = byte_swapped;
|
||||
wth->capture.pcap->mutant = mutant;
|
||||
wth->capture.pcap->modified = modified;
|
||||
wth->capture.pcap->version_major = hdr.version_major;
|
||||
wth->capture.pcap->version_minor = hdr.version_minor;
|
||||
wth->subtype_read = libpcap_read;
|
||||
wth->file_encap = pcap_encap[hdr.network];
|
||||
wth->snapshot_length = hdr.snaplen;
|
||||
|
||||
/*
|
||||
* Is this a capture file with the non-modified magic number?
|
||||
*/
|
||||
if (!wth->capture.pcap->modified) {
|
||||
/*
|
||||
* Yes. Let's look at the header for the first record,
|
||||
* and see if, interpreting it as a non-modified header,
|
||||
* the position where it says the header for the
|
||||
* *second* record is contains a corrupted header.
|
||||
*
|
||||
* If so, this may be a modified capture file with a
|
||||
* non-modified magic number - in some versions of
|
||||
* Alexey's patches, the packet header format was
|
||||
* changed but the magic number wasn't, and, alas,
|
||||
* Red Hat appear to have picked up one of those
|
||||
* patches for RH 6.1, meaning RH 6.1 has a "tcpdump"
|
||||
* that writes out files that can't be read by any software
|
||||
* that expects non-modified headers if the magic number isn't
|
||||
* the modified magic number (e.g., any normal version of
|
||||
* "tcpdump", and Ethereal if we don't do this gross
|
||||
* heuristic).
|
||||
*/
|
||||
bytes_read = file_read(&first_rec_hdr, 1,
|
||||
sizeof first_rec_hdr, wth->fh);
|
||||
if (bytes_read != sizeof first_rec_hdr) {
|
||||
*err = file_error(wth->fh);
|
||||
if (*err != 0)
|
||||
return -1; /* failed to read it */
|
||||
|
||||
/*
|
||||
* Short read - assume the file isn't modified,
|
||||
* and put the seek pointer back. The attempt
|
||||
* to read the first packet will presumably get
|
||||
* the same short read.
|
||||
*/
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
adjust_header(wth, &first_rec_hdr);
|
||||
|
||||
if (first_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
|
||||
/*
|
||||
* The first record is bogus, so this is probably
|
||||
* a corrupt file. Assume the file isn't modified,
|
||||
* and put the seek pointer back. The attempt
|
||||
* to read the first packet will probably get
|
||||
* the same bogus length.
|
||||
*/
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
file_seek(wth->fh,
|
||||
wth->data_offset + sizeof first_rec_hdr + first_rec_hdr.incl_len,
|
||||
SEEK_SET);
|
||||
bytes_read = file_read(&second_rec_hdr, 1,
|
||||
sizeof second_rec_hdr, wth->fh);
|
||||
|
||||
/*
|
||||
* OK, does the next packet's header look sane?
|
||||
*/
|
||||
if (bytes_read != sizeof second_rec_hdr) {
|
||||
*err = file_error(wth->fh);
|
||||
if (*err != 0)
|
||||
return -1; /* failed to read it */
|
||||
|
||||
/*
|
||||
* Short read - assume the file isn't modified,
|
||||
* and put the seek pointer back. The attempt
|
||||
* to read the second packet will presumably get
|
||||
* the same short read error.
|
||||
*/
|
||||
goto give_up;
|
||||
}
|
||||
|
||||
adjust_header(wth, &second_rec_hdr);
|
||||
if (second_rec_hdr.incl_len > WTAP_MAX_PACKET_SIZE) {
|
||||
/*
|
||||
* Oh, dear. Maybe it's a Capture File
|
||||
* From Hell, and what looks like the
|
||||
* "header" of the next packet is actually
|
||||
* random junk from the middle of a packet.
|
||||
* Try treating it as a modified file;
|
||||
* if that doesn't work, it probably *is*
|
||||
* a corrupt file.
|
||||
*/
|
||||
wth->file_type = WTAP_FILE_PCAP_MODIFIED;
|
||||
wth->capture.pcap->modified = TRUE;
|
||||
}
|
||||
|
||||
give_up:
|
||||
/*
|
||||
* Restore the seek pointer.
|
||||
*/
|
||||
file_seek(wth->fh, wth->data_offset, SEEK_SET);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -265,12 +365,13 @@ static int libpcap_read(wtap *wth, int *err)
|
|||
{
|
||||
guint packet_size;
|
||||
int bytes_to_read, bytes_read;
|
||||
struct pcaprec_mutant_hdr hdr;
|
||||
struct pcaprec_modified_hdr hdr;
|
||||
int data_offset;
|
||||
|
||||
/* Read record header. */
|
||||
errno = WTAP_ERR_CANT_READ;
|
||||
bytes_to_read = wth->capture.pcap->mutant ? sizeof hdr : sizeof hdr.hdr;
|
||||
bytes_to_read = wth->capture.pcap->modified ?
|
||||
sizeof hdr : sizeof hdr.hdr;
|
||||
bytes_read = file_read(&hdr, 1, bytes_to_read, wth->fh);
|
||||
if (bytes_read != bytes_to_read) {
|
||||
*err = file_error(wth->fh);
|
||||
|
@ -284,32 +385,7 @@ static int libpcap_read(wtap *wth, int *err)
|
|||
}
|
||||
wth->data_offset += bytes_read;
|
||||
|
||||
if (wth->capture.pcap->byte_swapped) {
|
||||
/* Byte-swap the record header fields. */
|
||||
hdr.hdr.ts_sec = BSWAP32(hdr.hdr.ts_sec);
|
||||
hdr.hdr.ts_usec = BSWAP32(hdr.hdr.ts_usec);
|
||||
hdr.hdr.incl_len = BSWAP32(hdr.hdr.incl_len);
|
||||
hdr.hdr.orig_len = BSWAP32(hdr.hdr.orig_len);
|
||||
}
|
||||
|
||||
/* In file format version 2.3, the "incl_len" and "orig_len" fields
|
||||
were swapped, in order to match the BPF header layout.
|
||||
|
||||
Unfortunately, some files were, according to a comment in the
|
||||
"libpcap" source, written with version 2.3 in their headers
|
||||
but without the interchanged fields, so if "incl_len" is
|
||||
greater than "orig_len" - which would make no sense - we
|
||||
assume that we need to swap them. */
|
||||
if (wth->capture.pcap->version_major == 2 &&
|
||||
(wth->capture.pcap->version_minor < 3 ||
|
||||
(wth->capture.pcap->version_minor == 3 &&
|
||||
hdr.hdr.incl_len > hdr.hdr.orig_len))) {
|
||||
guint32 temp;
|
||||
|
||||
temp = hdr.hdr.orig_len;
|
||||
hdr.hdr.orig_len = hdr.hdr.incl_len;
|
||||
hdr.hdr.incl_len = temp;
|
||||
}
|
||||
adjust_header(wth, &hdr.hdr);
|
||||
|
||||
packet_size = hdr.hdr.incl_len;
|
||||
if (packet_size > WTAP_MAX_PACKET_SIZE) {
|
||||
|
@ -346,6 +422,37 @@ static int libpcap_read(wtap *wth, int *err)
|
|||
return data_offset;
|
||||
}
|
||||
|
||||
static void
|
||||
adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
|
||||
{
|
||||
if (wth->capture.pcap->byte_swapped) {
|
||||
/* Byte-swap the record header fields. */
|
||||
hdr->ts_sec = BSWAP32(hdr->ts_sec);
|
||||
hdr->ts_usec = BSWAP32(hdr->ts_usec);
|
||||
hdr->incl_len = BSWAP32(hdr->incl_len);
|
||||
hdr->orig_len = BSWAP32(hdr->orig_len);
|
||||
}
|
||||
|
||||
/* In file format version 2.3, the "incl_len" and "orig_len" fields
|
||||
were swapped, in order to match the BPF header layout.
|
||||
|
||||
Unfortunately, some files were, according to a comment in the
|
||||
"libpcap" source, written with version 2.3 in their headers
|
||||
but without the interchanged fields, so if "incl_len" is
|
||||
greater than "orig_len" - which would make no sense - we
|
||||
assume that we need to swap them. */
|
||||
if (wth->capture.pcap->version_major == 2 &&
|
||||
(wth->capture.pcap->version_minor < 3 ||
|
||||
(wth->capture.pcap->version_minor == 3 &&
|
||||
hdr->incl_len > hdr->orig_len))) {
|
||||
guint32 temp;
|
||||
|
||||
temp = hdr->orig_len;
|
||||
hdr->orig_len = hdr->incl_len;
|
||||
hdr->incl_len = temp;
|
||||
}
|
||||
}
|
||||
|
||||
int wtap_pcap_encap_to_wtap_encap(int encap)
|
||||
{
|
||||
if (encap < 0 || encap >= NUM_PCAP_ENCAPS)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* wtap.c
|
||||
*
|
||||
* $Id: wtap.c,v 1.27 1999/10/31 17:46:10 gram Exp $
|
||||
* $Id: wtap.c,v 1.28 1999/11/06 10:31:45 guy Exp $
|
||||
*
|
||||
* Wiretap Library
|
||||
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
|
||||
|
@ -66,6 +66,9 @@ const char *wtap_file_type_string(wtap *wth)
|
|||
case WTAP_FILE_PCAP:
|
||||
return "pcap";
|
||||
|
||||
case WTAP_FILE_PCAP_MODIFIED:
|
||||
return "pcap-modified";
|
||||
|
||||
case WTAP_FILE_LANALYZER:
|
||||
return "Novell LANalyzer";
|
||||
|
||||
|
@ -161,6 +164,7 @@ void wtap_close(wtap *wth)
|
|||
* But for now this will work. */
|
||||
switch(wth->file_type) {
|
||||
case WTAP_FILE_PCAP:
|
||||
case WTAP_FILE_PCAP_MODIFIED:
|
||||
g_free(wth->capture.pcap);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* wtap.h
|
||||
*
|
||||
* $Id: wtap.h,v 1.47 1999/11/06 08:42:01 guy Exp $
|
||||
* $Id: wtap.h,v 1.48 1999/11/06 10:31:46 guy Exp $
|
||||
*
|
||||
* Wiretap Library
|
||||
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
|
||||
|
@ -101,8 +101,9 @@
|
|||
#define WTAP_FILE_UNKNOWN 0
|
||||
#define WTAP_FILE_WTAP 1
|
||||
#define WTAP_FILE_PCAP 2
|
||||
#define WTAP_FILE_LANALYZER 3
|
||||
#define WTAP_FILE_NGSNIFFER 4
|
||||
#define WTAP_FILE_PCAP_MODIFIED 3
|
||||
#define WTAP_FILE_LANALYZER 4
|
||||
#define WTAP_FILE_NGSNIFFER 5
|
||||
#define WTAP_FILE_SNOOP 6
|
||||
#define WTAP_FILE_IPTRACE 7
|
||||
#define WTAP_FILE_NETMON_1_x 8
|
||||
|
@ -160,7 +161,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
gboolean byte_swapped;
|
||||
gboolean mutant;
|
||||
gboolean modified;
|
||||
guint16 version_major;
|
||||
guint16 version_minor;
|
||||
} libpcap_t;
|
||||
|
|
Loading…
Reference in New Issue