1998-11-15 05:29:17 +00:00
|
|
|
/* libpcap.c
|
|
|
|
*
|
1999-12-04 09:38:38 +00:00
|
|
|
* $Id: libpcap.c,v 1.26 1999/12/04 09:38:37 guy Exp $
|
1998-11-15 05:29:17 +00:00
|
|
|
*
|
|
|
|
* Wiretap Library
|
|
|
|
* Copyright (c) 1998 by Gilbert Ramirez <gram@verdict.uthscsa.edu>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
*/
|
1999-07-13 02:53:26 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
1998-11-15 05:29:17 +00:00
|
|
|
#include "wtap.h"
|
1999-09-24 05:49:53 +00:00
|
|
|
#include "file.h"
|
1999-03-01 18:57:07 +00:00
|
|
|
#include "buffer.h"
|
1998-11-15 05:29:17 +00:00
|
|
|
#include "libpcap.h"
|
|
|
|
|
|
|
|
/* See source to the "libpcap" library for information on the "libpcap"
|
|
|
|
file format. */
|
|
|
|
|
|
|
|
/* Magic numbers in "libpcap" files.
|
|
|
|
|
|
|
|
"libpcap" file records are written in the byte order of the host that
|
|
|
|
writes them, and the reader is expected to fix this up.
|
|
|
|
|
|
|
|
PCAP_MAGIC is the magic number, in host byte order; PCAP_SWAPPED_MAGIC
|
1999-11-06 08:42:01 +00:00
|
|
|
is a byte-swapped version of that.
|
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
PCAP_MODIFIED_MAGIC is for Alexey Kuznetsov's modified "libpcap"
|
1999-11-06 08:42:01 +00:00
|
|
|
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/
|
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
applied; PCAP_SWAPPED_MODIFIED_MAGIC is the byte-swapped version. */
|
1999-11-06 08:42:01 +00:00
|
|
|
#define PCAP_MAGIC 0xa1b2c3d4
|
|
|
|
#define PCAP_SWAPPED_MAGIC 0xd4c3b2a1
|
1999-11-06 10:31:47 +00:00
|
|
|
#define PCAP_MODIFIED_MAGIC 0xa1b2cd34
|
|
|
|
#define PCAP_SWAPPED_MODIFIED_MAGIC 0x34cdb2a1
|
1998-11-15 05:29:17 +00:00
|
|
|
|
|
|
|
/* Macros to byte-swap 32-bit and 16-bit quantities. */
|
|
|
|
#define BSWAP32(x) \
|
|
|
|
((((x)&0xFF000000)>>24) | \
|
|
|
|
(((x)&0x00FF0000)>>8) | \
|
|
|
|
(((x)&0x0000FF00)<<8) | \
|
|
|
|
(((x)&0x000000FF)<<24))
|
|
|
|
#define BSWAP16(x) \
|
|
|
|
((((x)&0xFF00)>>8) | \
|
|
|
|
(((x)&0x00FF)<<8))
|
|
|
|
|
Add a new Wiretap encapsulation type WTAP_ENCAP_FDDI_BITSWAPPED, meaning
"FDDI with the MAC addresses bit-swapped"; whether the MAC addresses are
bit-swapped is a property of the machine on which the capture was taken,
not of the machine on which the capture is being read - right now, none
of the capture file formats we read indicate whether FDDI MAC addresses
are bit-swapped, but this does let us treat non-"libpcap" captures as
being bit-swapped or not bit-swapped independent of the machine on which
they're being read (and of the machine on which they were captured, but
I have the impression they're bit-swapped on most platforms), and allows
us to, if, as, and when we implement packet capture in Wiretap, mark
packets in a capture file written in Wiretap-native format based on the
machine on which they are captured (assuming the rule "Ultrix, Alpha,
and BSD/OS are the only platforms that don't bit-swap", or some other
compile-time rule, gets the right answer, or that some platform has
drivers that can tell us whether the addresses are bit-swapped).
(NOTE: if, for any of the capture file formats used only on one
platform, FDDI MAC addresses aren't bit-swapped, the code to read that
capture file format should be fixed to flag them as not bit-swapped.)
Use the encapsulation type to decide whether to bit-swap addresses in
"dissect_fddi()".
svn path=/trunk/; revision=557
1999-08-24 03:19:34 +00:00
|
|
|
/* On some systems, the FDDI MAC addresses are bit-swapped. */
|
1999-08-31 22:36:20 +00:00
|
|
|
#if !defined(ultrix) && !defined(__alpha) && !defined(__bsdi__)
|
Add a new Wiretap encapsulation type WTAP_ENCAP_FDDI_BITSWAPPED, meaning
"FDDI with the MAC addresses bit-swapped"; whether the MAC addresses are
bit-swapped is a property of the machine on which the capture was taken,
not of the machine on which the capture is being read - right now, none
of the capture file formats we read indicate whether FDDI MAC addresses
are bit-swapped, but this does let us treat non-"libpcap" captures as
being bit-swapped or not bit-swapped independent of the machine on which
they're being read (and of the machine on which they were captured, but
I have the impression they're bit-swapped on most platforms), and allows
us to, if, as, and when we implement packet capture in Wiretap, mark
packets in a capture file written in Wiretap-native format based on the
machine on which they are captured (assuming the rule "Ultrix, Alpha,
and BSD/OS are the only platforms that don't bit-swap", or some other
compile-time rule, gets the right answer, or that some platform has
drivers that can tell us whether the addresses are bit-swapped).
(NOTE: if, for any of the capture file formats used only on one
platform, FDDI MAC addresses aren't bit-swapped, the code to read that
capture file format should be fixed to flag them as not bit-swapped.)
Use the encapsulation type to decide whether to bit-swap addresses in
"dissect_fddi()".
svn path=/trunk/; revision=557
1999-08-24 03:19:34 +00:00
|
|
|
#define BIT_SWAPPED_MAC_ADDRS
|
|
|
|
#endif
|
|
|
|
|
1998-11-15 05:29:17 +00:00
|
|
|
/* "libpcap" file header (minus magic number). */
|
|
|
|
struct pcap_hdr {
|
|
|
|
guint16 version_major; /* major version number */
|
|
|
|
guint16 version_minor; /* minor version number */
|
|
|
|
gint32 thiszone; /* GMT to local correction */
|
|
|
|
guint32 sigfigs; /* accuracy of timestamps */
|
|
|
|
guint32 snaplen; /* max length of captured packets, in octets */
|
|
|
|
guint32 network; /* data link type */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* "libpcap" record header. */
|
|
|
|
struct pcaprec_hdr {
|
|
|
|
guint32 ts_sec; /* timestamp seconds */
|
|
|
|
guint32 ts_usec; /* timestamp microseconds */
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
guint32 incl_len; /* number of octets of packet saved in file */
|
1998-11-15 05:29:17 +00:00
|
|
|
guint32 orig_len; /* actual length of packet */
|
|
|
|
};
|
|
|
|
|
1999-11-06 08:42:01 +00:00
|
|
|
/* "libpcap" record header for Alexey's patched version. */
|
1999-11-06 10:31:47 +00:00
|
|
|
struct pcaprec_modified_hdr {
|
1999-11-06 08:42:01 +00:00
|
|
|
struct pcaprec_hdr hdr; /* the regular header */
|
|
|
|
guint32 ifindex; /* index, in *capturing* machine's list of
|
|
|
|
interfaces, of the interface on which this
|
|
|
|
packet came in. */
|
|
|
|
guint16 protocol; /* Ethernet packet type */
|
|
|
|
guint8 pkt_type; /* broadcast/multicast/etc. indication */
|
|
|
|
};
|
|
|
|
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
static int libpcap_read(wtap *wth, int *err);
|
1999-11-06 10:31:47 +00:00
|
|
|
static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr);
|
1999-12-04 05:14:39 +00:00
|
|
|
static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
|
1999-08-18 04:41:20 +00:00
|
|
|
const u_char *pd, int *err);
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
/*
|
1999-08-22 19:08:40 +00:00
|
|
|
* XXX - this is a bit of a mess. OpenBSD, and perhaps NetBSD, and
|
|
|
|
* BSD/OS have different DLT_ codes from FreeBSD (and from the LBL
|
|
|
|
* BPF code), and, at least in some cases, from each other.
|
1999-08-22 02:29:40 +00:00
|
|
|
* For now, we simply treat those type values with different
|
|
|
|
* meanings on different platforms, except for DLT_RAW, as "unknown";
|
|
|
|
* this means you won't be able to capture from a network using those
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
* types in Ethereal (and that capturing from the loopback interface
|
1999-08-22 02:29:40 +00:00
|
|
|
* won't necessarily work right on OpenBSD, either, as it uses
|
|
|
|
* DLT_LOOP, which is the same as DLT_RAW on other platforms).
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
*
|
|
|
|
* Does anybody know what BSD/OS uses as DLT_ types for SLIP and
|
|
|
|
* PPP? The LBL code, and the OpenBSD code, appear to disagree....
|
|
|
|
*
|
|
|
|
* Nothing in FreeBSD appears to use DLT_RAW, so it's not clear what
|
1999-08-22 02:29:40 +00:00
|
|
|
* link-layer header or fake header appears for DLT_RAW. If it's
|
|
|
|
* completely unused, or if it behaves the same way OpenBSD DLT_LOOP
|
|
|
|
* behaves, i.e. it puts an address family in *network* byte order
|
|
|
|
* (as opposed to the *host* byte order that DLT_NULL uses on FreeBSD),
|
|
|
|
* then we should just make it WTAP_ENCAP_NULL, which we treat in
|
|
|
|
* such a fashion as to cause it to work with DLT_LOOP headers.
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
*/
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
static const int pcap_encap[] = {
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
WTAP_ENCAP_NULL, /* null encapsulation */
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
WTAP_ENCAP_ETHERNET,
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
WTAP_ENCAP_UNKNOWN, /* 3Mb experimental Ethernet */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* Amateur Radio AX.25 */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* Proteon ProNET Token Ring */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* Chaos */
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
WTAP_ENCAP_TR, /* IEEE 802 Networks - assume token ring */
|
|
|
|
WTAP_ENCAP_ARCNET,
|
|
|
|
WTAP_ENCAP_SLIP,
|
|
|
|
WTAP_ENCAP_PPP,
|
Add a new Wiretap encapsulation type WTAP_ENCAP_FDDI_BITSWAPPED, meaning
"FDDI with the MAC addresses bit-swapped"; whether the MAC addresses are
bit-swapped is a property of the machine on which the capture was taken,
not of the machine on which the capture is being read - right now, none
of the capture file formats we read indicate whether FDDI MAC addresses
are bit-swapped, but this does let us treat non-"libpcap" captures as
being bit-swapped or not bit-swapped independent of the machine on which
they're being read (and of the machine on which they were captured, but
I have the impression they're bit-swapped on most platforms), and allows
us to, if, as, and when we implement packet capture in Wiretap, mark
packets in a capture file written in Wiretap-native format based on the
machine on which they are captured (assuming the rule "Ultrix, Alpha,
and BSD/OS are the only platforms that don't bit-swap", or some other
compile-time rule, gets the right answer, or that some platform has
drivers that can tell us whether the addresses are bit-swapped).
(NOTE: if, for any of the capture file formats used only on one
platform, FDDI MAC addresses aren't bit-swapped, the code to read that
capture file format should be fixed to flag them as not bit-swapped.)
Use the encapsulation type to decide whether to bit-swap addresses in
"dissect_fddi()".
svn path=/trunk/; revision=557
1999-08-24 03:19:34 +00:00
|
|
|
#ifdef BIT_SWAPPED_MAC_ADDRS
|
|
|
|
WTAP_ENCAP_FDDI_BITSWAPPED,
|
|
|
|
#else
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
WTAP_ENCAP_FDDI,
|
Add a new Wiretap encapsulation type WTAP_ENCAP_FDDI_BITSWAPPED, meaning
"FDDI with the MAC addresses bit-swapped"; whether the MAC addresses are
bit-swapped is a property of the machine on which the capture was taken,
not of the machine on which the capture is being read - right now, none
of the capture file formats we read indicate whether FDDI MAC addresses
are bit-swapped, but this does let us treat non-"libpcap" captures as
being bit-swapped or not bit-swapped independent of the machine on which
they're being read (and of the machine on which they were captured, but
I have the impression they're bit-swapped on most platforms), and allows
us to, if, as, and when we implement packet capture in Wiretap, mark
packets in a capture file written in Wiretap-native format based on the
machine on which they are captured (assuming the rule "Ultrix, Alpha,
and BSD/OS are the only platforms that don't bit-swap", or some other
compile-time rule, gets the right answer, or that some platform has
drivers that can tell us whether the addresses are bit-swapped).
(NOTE: if, for any of the capture file formats used only on one
platform, FDDI MAC addresses aren't bit-swapped, the code to read that
capture file format should be fixed to flag them as not bit-swapped.)
Use the encapsulation type to decide whether to bit-swap addresses in
"dissect_fddi()".
svn path=/trunk/; revision=557
1999-08-24 03:19:34 +00:00
|
|
|
#endif
|
1999-08-22 19:08:40 +00:00
|
|
|
WTAP_ENCAP_ATM_RFC1483, /* or, on BSD/OS, Frame Relay */
|
|
|
|
WTAP_ENCAP_RAW_IP, /* or, on OpenBSD, DLT_LOOP, and on BSD/OS,
|
|
|
|
Cisco HDLC */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* In LBL BPF and FreeBSD, BSD/OS SLIP;
|
|
|
|
on OpenBSD, DLT_ENC; on BSD/OS,
|
|
|
|
DLT_ATM_RFC1483 */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* In LBL BPF and FreeBSD, BSD/OS PPP;
|
|
|
|
on OpenBSD and BSD/OS, DLT_RAW */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* In OpenBSD and BSD/OS, BSD/OS SLIP,
|
|
|
|
but the BSD/OS header says "internal
|
|
|
|
to libpcap", whatever that means */
|
|
|
|
WTAP_ENCAP_UNKNOWN, /* In OpenBSD and BSD/OS, BSD/OS PPP,
|
|
|
|
but the BSD/OS header says "internal
|
|
|
|
to libpcap", whatever that means */
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
WTAP_ENCAP_UNKNOWN,
|
|
|
|
WTAP_ENCAP_UNKNOWN,
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
WTAP_ENCAP_LINUX_ATM_CLIP
|
|
|
|
};
|
|
|
|
#define NUM_PCAP_ENCAPS (sizeof pcap_encap / sizeof pcap_encap[0])
|
|
|
|
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
int libpcap_open(wtap *wth, int *err)
|
1998-11-15 05:29:17 +00:00
|
|
|
{
|
|
|
|
int bytes_read;
|
|
|
|
guint32 magic;
|
|
|
|
struct pcap_hdr hdr;
|
1999-11-06 10:31:47 +00:00
|
|
|
gboolean byte_swapped;
|
|
|
|
gboolean modified;
|
|
|
|
struct pcaprec_hdr first_rec_hdr;
|
|
|
|
struct pcaprec_hdr second_rec_hdr;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
|
|
|
/* Read in the number that should be at the start of a "libpcap" file */
|
1999-09-22 01:26:50 +00:00
|
|
|
file_seek(wth->fh, 0, SEEK_SET);
|
1999-08-28 01:19:45 +00:00
|
|
|
wth->data_offset = 0;
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
errno = WTAP_ERR_CANT_READ;
|
1999-09-22 01:26:50 +00:00
|
|
|
bytes_read = file_read(&magic, 1, sizeof magic, wth->fh);
|
1998-11-15 05:29:17 +00:00
|
|
|
if (bytes_read != sizeof magic) {
|
1999-10-05 07:06:08 +00:00
|
|
|
*err = file_error(wth->fh);
|
|
|
|
if (*err != 0)
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
1999-08-28 01:19:45 +00:00
|
|
|
wth->data_offset += sizeof magic;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
1999-11-06 08:42:01 +00:00
|
|
|
switch (magic) {
|
|
|
|
|
|
|
|
case PCAP_MAGIC:
|
|
|
|
/* Host that wrote it has our byte order. */
|
|
|
|
byte_swapped = FALSE;
|
1999-11-06 10:31:47 +00:00
|
|
|
modified = FALSE;
|
1999-11-06 08:42:01 +00:00
|
|
|
break;
|
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
case PCAP_MODIFIED_MAGIC:
|
1999-11-06 08:42:01 +00:00
|
|
|
/* Host that wrote it has our byte order, but was running
|
|
|
|
a program using the patched "libpcap". */
|
|
|
|
byte_swapped = FALSE;
|
1999-11-06 10:31:47 +00:00
|
|
|
modified = TRUE;
|
1999-11-06 08:42:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case PCAP_SWAPPED_MAGIC:
|
1998-11-15 05:29:17 +00:00
|
|
|
/* Host that wrote it has a byte order opposite to ours. */
|
1999-11-06 08:42:01 +00:00
|
|
|
byte_swapped = TRUE;
|
1999-11-06 10:31:47 +00:00
|
|
|
modified = FALSE;
|
1999-11-06 08:42:01 +00:00
|
|
|
break;
|
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
case PCAP_SWAPPED_MODIFIED_MAGIC:
|
1999-11-06 08:42:01 +00:00
|
|
|
/* Host that wrote it out has a byte order opposite to
|
|
|
|
ours, and was running a program using the patched
|
|
|
|
"libpcap". */
|
|
|
|
byte_swapped = TRUE;
|
1999-11-06 10:31:47 +00:00
|
|
|
modified = TRUE;
|
1999-11-06 08:42:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
/* Not a "libpcap" type we know about. */
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
return 0;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the rest of the header. */
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
errno = WTAP_ERR_CANT_READ;
|
1999-09-22 01:26:50 +00:00
|
|
|
bytes_read = file_read(&hdr, 1, sizeof hdr, wth->fh);
|
1998-11-15 05:29:17 +00:00
|
|
|
if (bytes_read != sizeof hdr) {
|
1999-10-05 07:06:08 +00:00
|
|
|
*err = file_error(wth->fh);
|
|
|
|
if (*err != 0)
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
return -1;
|
|
|
|
return 0;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
1999-08-28 01:19:45 +00:00
|
|
|
wth->data_offset += sizeof hdr;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
|
|
|
if (byte_swapped) {
|
|
|
|
/* Byte-swap the header fields about which we care. */
|
|
|
|
hdr.version_major = BSWAP16(hdr.version_major);
|
|
|
|
hdr.version_minor = BSWAP16(hdr.version_minor);
|
|
|
|
hdr.snaplen = BSWAP32(hdr.snaplen);
|
|
|
|
hdr.network = BSWAP32(hdr.network);
|
|
|
|
}
|
|
|
|
if (hdr.version_major < 2) {
|
|
|
|
/* We only support version 2.0 and later. */
|
1999-08-22 02:29:40 +00:00
|
|
|
g_message("pcap: major version %u unsupported",
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
hdr.version_major);
|
|
|
|
*err = WTAP_ERR_UNSUPPORTED;
|
|
|
|
return -1;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
if (hdr.network >= NUM_PCAP_ENCAPS
|
|
|
|
|| pcap_encap[hdr.network] == WTAP_ENCAP_UNKNOWN) {
|
1999-08-22 02:29:40 +00:00
|
|
|
g_message("pcap: network type %u unknown or unsupported",
|
|
|
|
hdr.network);
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
*err = WTAP_ERR_UNSUPPORTED;
|
|
|
|
return -1;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* This is a libpcap file */
|
1999-11-06 10:31:47 +00:00
|
|
|
wth->file_type = modified ? WTAP_FILE_PCAP_MODIFIED : WTAP_FILE_PCAP;
|
1998-11-15 05:29:17 +00:00
|
|
|
wth->capture.pcap = g_malloc(sizeof(libpcap_t));
|
|
|
|
wth->capture.pcap->byte_swapped = byte_swapped;
|
1999-11-06 10:31:47 +00:00
|
|
|
wth->capture.pcap->modified = modified;
|
1998-11-15 05:29:17 +00:00
|
|
|
wth->capture.pcap->version_major = hdr.version_major;
|
|
|
|
wth->capture.pcap->version_minor = hdr.version_minor;
|
|
|
|
wth->subtype_read = libpcap_read;
|
1999-03-01 18:57:07 +00:00
|
|
|
wth->file_encap = pcap_encap[hdr.network];
|
1998-11-15 05:29:17 +00:00
|
|
|
wth->snapshot_length = hdr.snaplen;
|
1999-11-06 10:31:47 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
return 1;
|
1998-11-15 05:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Read the next packet */
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
static int libpcap_read(wtap *wth, int *err)
|
1998-11-15 05:29:17 +00:00
|
|
|
{
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
guint packet_size;
|
1999-11-06 08:42:01 +00:00
|
|
|
int bytes_to_read, bytes_read;
|
1999-11-06 10:31:47 +00:00
|
|
|
struct pcaprec_modified_hdr hdr;
|
1998-11-15 05:29:17 +00:00
|
|
|
int data_offset;
|
|
|
|
|
|
|
|
/* Read record header. */
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
errno = WTAP_ERR_CANT_READ;
|
1999-11-06 10:31:47 +00:00
|
|
|
bytes_to_read = wth->capture.pcap->modified ?
|
|
|
|
sizeof hdr : sizeof hdr.hdr;
|
1999-11-06 08:42:01 +00:00
|
|
|
bytes_read = file_read(&hdr, 1, bytes_to_read, wth->fh);
|
|
|
|
if (bytes_read != bytes_to_read) {
|
1999-10-05 07:06:08 +00:00
|
|
|
*err = file_error(wth->fh);
|
|
|
|
if (*err != 0)
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
return -1;
|
1998-11-15 05:29:17 +00:00
|
|
|
if (bytes_read != 0) {
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
*err = WTAP_ERR_SHORT_READ;
|
1998-11-15 05:29:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
1999-11-06 08:42:01 +00:00
|
|
|
wth->data_offset += bytes_read;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
adjust_header(wth, &hdr.hdr);
|
1998-11-15 05:29:17 +00:00
|
|
|
|
1999-11-06 08:42:01 +00:00
|
|
|
packet_size = hdr.hdr.incl_len;
|
DLT_NULL, from "libpcap", means different things on different platforms
and in different capture files; throw in some heuristics to try to
figure out whether the 4-byte header is:
1) PPP-over-HDLC (some version of ISDN4BSD?);
2) big-endian AF_ value (BSD on big-endian platforms);
3) little-endian AF_ value (BSD on little-endian platforms);
4) two octets of 0 followed by an Ethernet type (Linux, at least
on little-endian platforms, as mutated by "libpcap").
Make a separate Wiretap encapsulation type, WTAP_ENCAP_NULL,
corresponding to DLT_NULL.
Have the PPP code dissect the frame if it's PPP-over-HDLC, and have
"ethertype()" dissect the Ethernet type and the rest of the packet if
it's a Linux-style header; dissect it ourselves only if it's an AF_
value.
Have Wiretap impose a maximum packet size of 65535 bytes, so that it
fails more gracefully when handed a corrupt "libpcap" capture file
(other capture file formats with more than a 16-bit capture length
field, if any, will have that check added later), and put that size in
"wtap.h" and have Ethereal use it as its notion of a maximum packet
size.
Have Ethereal put up a "this file appears to be damaged or corrupt"
message box if Wiretap returns a WTAP_ERR_BAD_RECORD error when opening
or reading a capture file.
Include loopback interfaces in the list of interfaces offered by the
"Capture" dialog box, but put them at the end of the list so that it
doesn't default to a loopback interface unless there are no other
interfaces. Also, don't require that an interface in the list have an
IP address associated with it, and only put one entry in the list for a
given interface (SIOCGIFCONF returns one entry per interface *address*,
not per *interface* - and even if you were to use only IP addresses, an
interface could conceivably have more than one IP address).
Exclusively use Wiretap encapsulation types internally, even when
capturing; don't use DLT_ types.
svn path=/trunk/; revision=540
1999-08-22 00:47:56 +00:00
|
|
|
if (packet_size > WTAP_MAX_PACKET_SIZE) {
|
|
|
|
/*
|
|
|
|
* Probably a corrupt capture file; don't blow up trying
|
|
|
|
* to allocate space for an immensely-large packet.
|
|
|
|
*/
|
|
|
|
g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
|
|
|
|
packet_size, WTAP_MAX_PACKET_SIZE);
|
|
|
|
*err = WTAP_ERR_BAD_RECORD;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
1999-03-01 18:57:07 +00:00
|
|
|
buffer_assure_space(wth->frame_buffer, packet_size);
|
1999-08-28 01:19:45 +00:00
|
|
|
data_offset = wth->data_offset;
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
errno = WTAP_ERR_CANT_READ;
|
1999-09-22 01:26:50 +00:00
|
|
|
bytes_read = file_read(buffer_start_ptr(wth->frame_buffer), 1,
|
1998-11-15 05:29:17 +00:00
|
|
|
packet_size, wth->fh);
|
|
|
|
|
|
|
|
if (bytes_read != packet_size) {
|
1999-10-05 07:06:08 +00:00
|
|
|
*err = file_error(wth->fh);
|
|
|
|
if (*err == 0)
|
Have the per-capture-file-type open routines "wtap_open_offline()" calls
return 1 on success, -1 if they got an error, and 0 if the file isn't of
the type that file is checking for, and supply an error code if they
return -1; have "wtap_open_offline()" use that error code. Also, have
the per-capture-file-type open routines treat errors accessing the file
as errors, and return -1, rather than just returning 0 so that we try
another file type.
Have the per-capture-file-type read routines "wtap_loop()" calls return
-1 and supply an error code on error (and not, as they did in some
cases, call "g_error()" and abort), and have "wtap_loop()", if the read
routine returned an error, return FALSE (and pass an error-code-pointer
argument onto the read routines, so they fill it in), and return TRUE on
success.
Add some new error codes for them to return.
Now that "wtap_loop()" can return a success/failure indication and an
error code, in "read_cap_file()" put up a message box if we get an error
reading the file, and return the error code.
Handle the additional errors we can get when opening a capture file.
If the attempt to open a capture file succeeds, but the attempt to read
it fails, don't treat that as a complete failure - we may have managed
to read some of the capture file, and we should display what we managed
to read.
svn path=/trunk/; revision=516
1999-08-19 05:31:38 +00:00
|
|
|
*err = WTAP_ERR_SHORT_READ;
|
1998-11-15 05:29:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
1999-08-28 01:19:45 +00:00
|
|
|
wth->data_offset += packet_size;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
1999-11-06 08:42:01 +00:00
|
|
|
wth->phdr.ts.tv_sec = hdr.hdr.ts_sec;
|
|
|
|
wth->phdr.ts.tv_usec = hdr.hdr.ts_usec;
|
1998-11-15 05:29:17 +00:00
|
|
|
wth->phdr.caplen = packet_size;
|
1999-11-06 08:42:01 +00:00
|
|
|
wth->phdr.len = hdr.hdr.orig_len;
|
1999-03-01 18:57:07 +00:00
|
|
|
wth->phdr.pkt_encap = wth->file_encap;
|
1998-11-15 05:29:17 +00:00
|
|
|
|
|
|
|
return data_offset;
|
|
|
|
}
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
|
1999-11-06 10:31:47 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
int wtap_pcap_encap_to_wtap_encap(int encap)
|
|
|
|
{
|
|
|
|
if (encap < 0 || encap >= NUM_PCAP_ENCAPS)
|
1999-08-18 17:08:47 +00:00
|
|
|
return WTAP_ENCAP_UNKNOWN;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
return pcap_encap[encap];
|
|
|
|
}
|
|
|
|
|
1999-12-04 08:32:14 +00:00
|
|
|
static const int wtap_encap[] = {
|
|
|
|
-1, /* WTAP_ENCAP_UNKNOWN -> unsupported */
|
|
|
|
1, /* WTAP_ENCAP_ETHERNET -> DLT_EN10MB */
|
|
|
|
6, /* WTAP_ENCAP_TR -> DLT_IEEE802 */
|
|
|
|
8, /* WTAP_ENCAP_SLIP -> DLT_SLIP */
|
|
|
|
9, /* WTAP_ENCAP_PPP -> DLT_PPP */
|
|
|
|
10, /* WTAP_ENCAP_FDDI -> DLT_FDDI */
|
|
|
|
10, /* WTAP_ENCAP_FDDI_BITSWAPPED -> DLT_FDDI */
|
|
|
|
12, /* WTAP_ENCAP_RAW_IP -> DLT_RAW */
|
|
|
|
7, /* WTAP_ENCAP_ARCNET -> DLT_ARCNET */
|
|
|
|
11, /* WTAP_ENCAP_ATM_RFC1483 -> DLT_ATM_RFC1483 */
|
|
|
|
19, /* WTAP_ENCAP_LINUX_ATM_CLIP */
|
|
|
|
-1, /* WTAP_ENCAP_LAPB -> unsupported*/
|
|
|
|
-1, /* WTAP_ENCAP_ATM_SNIFFER -> unsupported */
|
|
|
|
0 /* WTAP_ENCAP_NULL -> DLT_NULL */
|
|
|
|
};
|
|
|
|
#define NUM_WTAP_ENCAPS (sizeof wtap_encap / sizeof wtap_encap[0])
|
|
|
|
|
|
|
|
/* Returns 0 if we could write the specified encapsulation type,
|
|
|
|
an error indication otherwise. */
|
1999-12-04 09:38:38 +00:00
|
|
|
int libpcap_dump_can_write_encap(int filetype, int encap)
|
1999-12-04 08:32:14 +00:00
|
|
|
{
|
|
|
|
/* Per-packet encapsulations aren't supported. */
|
|
|
|
if (encap == WTAP_ENCAP_PER_PACKET)
|
|
|
|
return WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED;
|
|
|
|
|
|
|
|
if (encap < 0 || encap >= NUM_WTAP_ENCAPS || wtap_encap[encap] == -1)
|
|
|
|
return WTAP_ERR_UNSUPPORTED_ENCAP;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1999-12-04 05:14:39 +00:00
|
|
|
/* Returns TRUE on success, FALSE on failure; sets "*err" to an error code on
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
failure */
|
1999-12-04 05:14:39 +00:00
|
|
|
gboolean libpcap_dump_open(wtap_dumper *wdh, int *err)
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
{
|
|
|
|
static const guint32 pcap_magic = PCAP_MAGIC;
|
|
|
|
struct pcap_hdr file_hdr;
|
|
|
|
int nwritten;
|
|
|
|
|
|
|
|
/* This is a libpcap file */
|
|
|
|
wdh->subtype_write = libpcap_dump;
|
1999-12-04 08:32:14 +00:00
|
|
|
wdh->subtype_close = NULL;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
|
|
|
|
/* Write the file header. */
|
1999-09-23 05:00:59 +00:00
|
|
|
nwritten = fwrite(&pcap_magic, 1, sizeof pcap_magic, wdh->fh);
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
if (nwritten != sizeof pcap_magic) {
|
|
|
|
if (nwritten < 0)
|
|
|
|
*err = errno;
|
|
|
|
else
|
|
|
|
*err = WTAP_ERR_SHORT_WRITE;
|
1999-12-04 05:14:39 +00:00
|
|
|
return FALSE;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* current "libpcap" format is 2.4 */
|
|
|
|
file_hdr.version_major = 2;
|
|
|
|
file_hdr.version_minor = 4;
|
|
|
|
file_hdr.thiszone = 0; /* XXX - current offset? */
|
|
|
|
file_hdr.sigfigs = 0; /* unknown, but also apparently unused */
|
|
|
|
file_hdr.snaplen = wdh->snaplen;
|
|
|
|
file_hdr.network = wtap_encap[wdh->encap];
|
1999-09-23 05:00:59 +00:00
|
|
|
nwritten = fwrite(&file_hdr, 1, sizeof file_hdr, wdh->fh);
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
if (nwritten != sizeof file_hdr) {
|
|
|
|
if (nwritten < 0)
|
|
|
|
*err = errno;
|
|
|
|
else
|
|
|
|
*err = WTAP_ERR_SHORT_WRITE;
|
1999-12-04 05:14:39 +00:00
|
|
|
return FALSE;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
}
|
|
|
|
|
1999-12-04 05:14:39 +00:00
|
|
|
return TRUE;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Write a record for a packet to a dump file.
|
1999-12-04 05:14:39 +00:00
|
|
|
Returns TRUE on success, FALSE on failure. */
|
|
|
|
static gboolean libpcap_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr,
|
1999-08-18 04:41:20 +00:00
|
|
|
const u_char *pd, int *err)
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
{
|
|
|
|
struct pcaprec_hdr rec_hdr;
|
|
|
|
int nwritten;
|
|
|
|
|
|
|
|
rec_hdr.ts_sec = phdr->ts.tv_sec;
|
|
|
|
rec_hdr.ts_usec = phdr->ts.tv_usec;
|
|
|
|
rec_hdr.incl_len = phdr->caplen;
|
|
|
|
rec_hdr.orig_len = phdr->len;
|
1999-09-23 05:00:59 +00:00
|
|
|
nwritten = fwrite(&rec_hdr, 1, sizeof rec_hdr, wdh->fh);
|
1999-08-18 04:41:20 +00:00
|
|
|
if (nwritten != sizeof rec_hdr) {
|
|
|
|
if (nwritten < 0)
|
|
|
|
*err = errno;
|
|
|
|
else
|
|
|
|
*err = WTAP_ERR_SHORT_WRITE;
|
1999-12-04 05:14:39 +00:00
|
|
|
return FALSE;
|
1999-08-18 04:41:20 +00:00
|
|
|
}
|
1999-09-23 05:00:59 +00:00
|
|
|
nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
|
1999-08-18 04:41:20 +00:00
|
|
|
if (nwritten != phdr->caplen) {
|
|
|
|
if (nwritten < 0)
|
|
|
|
*err = errno;
|
|
|
|
else
|
|
|
|
*err = WTAP_ERR_SHORT_WRITE;
|
1999-12-04 05:14:39 +00:00
|
|
|
return FALSE;
|
1999-08-18 04:41:20 +00:00
|
|
|
}
|
1999-12-04 05:14:39 +00:00
|
|
|
return TRUE;
|
Add to Wiretap the ability to write capture files; for now, it can only
write them in "libpcap" format, but the mechanism can have other formats
added.
When creating the temporary file for a capture, use "create_tempfile()",
to close a security hole opened by the fact that "tempnam()" creates a
temporary file, but doesn't open it, and we open the file with the name
it gives us - somebody could remove the file and plant a link to some
file, and, if as may well be the case when Ethereal is capturing
packets, it's running as "root", that means we write a capture on top of
that file.... (The aforementioned changes to Wiretap let you open a
capture file for writing given an file descriptor, "fdopen()"-style,
which this change requires.)
svn path=/trunk/; revision=509
1999-08-18 04:17:38 +00:00
|
|
|
}
|