/* libpcap.c
*
- * $Id: libpcap.c,v 1.81 2002/08/07 06:59:49 guy Exp $
+ * $Id: libpcap.c,v 1.101 2003/12/03 22:40:39 guy Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.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.
* using them are foreign, and we don't hazard a guess as to which
* platform they came from; we could, I guess, choose the most likely
* platform).
+ *
+ * Note: if you need a new encapsulation type for libpcap files, do
+ * *N*O*T* use *ANY* of the values listed here! I.e., do *NOT*
+ * add a new encapsulation type by changing an existing entry;
+ * leave the existing entries alone.
+ *
+ * Instead, send mail to tcpdump-workers@tcpdump.org, asking for a new
+ * DLT_ value, and specifying the purpose of the new value. When you
+ * get the new DLT_ value, use that numerical value in the "dlt_value"
+ * field of "pcap_to_wtap_map[]".
*/
static const struct {
{ 106, WTAP_ENCAP_LINUX_ATM_CLIP },
{ 107, WTAP_ENCAP_FRELAY }, /* Frame Relay */
{ 108, WTAP_ENCAP_NULL }, /* OpenBSD loopback */
-#if 0
{ 109, WTAP_ENCAP_ENC }, /* OpenBSD IPSEC enc */
+#if 0
{ 110, WTAP_ENCAP_LANE_802_3 },/* ATM LANE 802.3 */
{ 111, WTAP_ENCAP_HIPPI }, /* NetBSD HIPPI */
#endif
{ 118, WTAP_ENCAP_CISCO_IOS },
{ 119, WTAP_ENCAP_PRISM_HEADER }, /* Prism monitor mode hdr */
{ 121, WTAP_ENCAP_HHDLC }, /* HiPath HDLC */
- { 123, WTAP_ENCAP_ATM_SNIFFER }, /* SunATM */
+ { 122, WTAP_ENCAP_IP_OVER_FC }, /* RFC 2625 IP-over-FC */
+ { 123, WTAP_ENCAP_ATM_PDUS }, /* SunATM */
+ { 127, WTAP_ENCAP_WLAN_HEADER }, /* 802.11 plus WLAN header */
+ { 128, WTAP_ENCAP_TZSP }, /* Tazmen Sniffer Protocol */
+ { 129, WTAP_ENCAP_ARCNET_LINUX },
+
+ /*
+ * Values 130 thorugh 137 are reserved for use in Juniper
+ * hardware.
+ *
+ * 138 is reserved for Apple IP-over-IEEE 1394.
+ */
+
+ { 140, WTAP_ENCAP_MTP2 },
+ { 141, WTAP_ENCAP_MTP3 },
+
+ /*
+ * To repeat:
+ *
+ * If you need a new encapsulation type for libpcap files, do
+ * *N*O*T* use *ANY* of the values listed here! I.e., do *NOT*
+ * add a new encapsulation type by changing an existing entry;
+ * leave the existing entries alone.
+ *
+ * Instead, send mail to tcpdump-workers@tcpdump.org, asking for
+ * a new DLT_ value, and specifying the purpose of the new value.
+ * When you get the new DLT_ value, use that numerical value in
+ * the "dlt_value" field of "pcap_to_wtap_map[]".
+ */
/*
* The following are entries for libpcap type values that have
#if defined(DLT_ATM_RFC1483) && (DLT_ATM_RFC1483 == 13)
{ 13, WTAP_ENCAP_ATM_RFC1483 },
#elif defined(DLT_ENC) && (DLT_ENC == 13)
- /* Put entry for DLT_ENC here */
+ { 13, WTAP_ENCAP_ENC },
#endif
/*
* defined with the value 17.
*/
#if !defined(DLT_LANE8023) || (DLT_LANE8023 != 17)
- { 17, WTAP_ENCAP_PFLOG },
+ { 17, WTAP_ENCAP_OLD_PFLOG },
#endif
/*
* purpose - hopefully nobody will do so in the future.
*/
{ 19, WTAP_ENCAP_LINUX_ATM_CLIP },
+
+ /*
+ * To repeat:
+ *
+ * If you need a new encapsulation type for libpcap files, do
+ * *N*O*T* use *ANY* of the values listed here! I.e., do *NOT*
+ * add a new encapsulation type by changing an existing entry;
+ * leave the existing entries alone.
+ *
+ * Instead, send mail to tcpdump-workers@tcpdump.org, asking for
+ * a new DLT_ value, and specifying the purpose of the new value.
+ * When you get the new DLT_ value, use that numerical value in
+ * the "dlt_value" field of "pcap_to_wtap_map[]".
+ */
+
};
#define NUM_PCAP_ENCAPS (sizeof pcap_to_wtap_map / sizeof pcap_to_wtap_map[0])
* FDDI 15
*
* which correspond to DLT_IEEE802 (used for Token Ring),
- * DLT_PPP, and DLT_SLIP_BSDOS, respectively. We shall
- * assume that if the minor version number is 2, and
- * the network type is 6, 9, or 15, that it's AIX libpcap.
+ * DLT_PPP, and DLT_SLIP_BSDOS, respectively. The ifType value
+ * for a loopback interface is 24, which currently isn't
+ * used by any version of libpcap I know about (and, as
+ * tcpdump.org are assigning DLT_ values above 100, and
+ * NetBSD started assigning values starting at 50, and
+ * the values chosen by other libpcaps appear to stop at
+ * 19, it's probably not going to be used by any libpcap
+ * in the future).
+ *
+ * We shall assume that if the minor version number is 2, and
+ * the network type is 6, 9, 15, or 24, that it's AIX libpcap.
*
* I'm assuming those older versions of libpcap didn't
* use DLT_IEEE802 for Token Ring, and didn't use DLT_SLIP_BSDOS
hdr.network = 10; /* DLT_FDDI, FDDI */
aix = TRUE;
break;
+
+ case 24:
+ hdr.network = 0; /* DLT_NULL, loopback */
+ aix = TRUE;
+ break;
}
}
file_encap = wtap_pcap_encap_to_wtap_encap(hdr.network);
wth->file_encap = file_encap;
wth->snapshot_length = hdr.snaplen;
+ /* In file format version 2.3, the order of the "incl_len" and
+ "orig_len" fields in the per-packet header was reversed,
+ in order to match the BPF header layout.
+
+ Therefore, in files with versions prior to that, we must swap
+ those two fields.
+
+ 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 in version 2.3 files
+ as well.
+
+ In addition, DG/UX's tcpdump uses version 543.0, and writes
+ the two fields in the pre-2.3 order. */
+ switch (hdr.version_major) {
+
+ case 2:
+ if (hdr.version_minor < 3)
+ wth->capture.pcap->lengths_swapped = SWAPPED;
+ else if (hdr.version_minor == 3)
+ wth->capture.pcap->lengths_swapped = MAYBE_SWAPPED;
+ else
+ wth->capture.pcap->lengths_swapped = NOT_SWAPPED;
+ break;
+
+ case 543:
+ wth->capture.pcap->lengths_swapped = SWAPPED;
+ break;
+
+ default:
+ wth->capture.pcap->lengths_swapped = NOT_SWAPPED;
+ break;
+ }
+
/*
* Is this AIX format?
*/
guint packet_size;
guint orig_size;
int bytes_read;
+ char fddi_padding[3];
bytes_read = libpcap_read_header(wth, err, &hdr, FALSE);
if (bytes_read == -1) {
packet_size = hdr.hdr.incl_len;
orig_size = hdr.hdr.orig_len;
+ /*
+ * AIX appears to put 3 bytes of padding in front of FDDI
+ * frames; strip that crap off.
+ */
+ if (wth->file_type == WTAP_FILE_PCAP_AIX &&
+ (wth->file_encap == WTAP_ENCAP_FDDI ||
+ wth->file_encap == WTAP_ENCAP_FDDI_BITSWAPPED)) {
+ /*
+ * The packet size is really a record size and includes
+ * the padding.
+ */
+ packet_size -= 3;
+ orig_size -= 3;
+ wth->data_offset += 3;
+
+ /*
+ * Read the padding.
+ */
+ if (!libpcap_read_rec_data(wth->fh, fddi_padding, 3, err))
+ return FALSE; /* Read error */
+ }
+
*data_offset = wth->data_offset;
/*
* the VCI; read them and generate the pseudo-header from
* them.
*/
- if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER) {
+ switch (wth->file_encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
if (packet_size < sizeof (struct sunatm_hdr)) {
/*
* Uh-oh, the packet isn't big enough to even
orig_size -= sizeof (struct sunatm_hdr);
packet_size -= sizeof (struct sunatm_hdr);
wth->data_offset += sizeof (struct sunatm_hdr);
+ break;
+
+ case WTAP_ENCAP_ETHERNET:
+ /*
+ * We don't know whether there's an FCS in this frame or not.
+ */
+ wth->pseudo_header.eth.fcs_len = -1;
+ break;
}
buffer_assure_space(wth->frame_buffer, packet_size);
* If this is ATM LANE traffic, try to guess what type of LANE
* traffic it is based on the packet contents.
*/
- if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER &&
+ if (wth->file_encap == WTAP_ENCAP_ATM_PDUS &&
wth->pseudo_header.atm.type == TRAF_LANE) {
atm_guess_lane_type(buffer_start_ptr(wth->frame_buffer),
wth->phdr.caplen, &wth->pseudo_header);
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
- if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER) {
+ switch (wth->file_encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
if (!libpcap_read_atm_pseudoheader(wth->random_fh, pseudo_header,
err)) {
/* Read error */
return FALSE;
}
+ break;
+
+ case WTAP_ENCAP_ETHERNET:
+ /*
+ * We don't know whether there's an FCS in this frame or not.
+ */
+ pseudo_header->eth.fcs_len = -1;
+ break;
}
/*
* If this is ATM LANE traffic, try to guess what type of LANE
* traffic it is based on the packet contents.
*/
- if (wth->file_encap == WTAP_ENCAP_ATM_SNIFFER &&
+ if (wth->file_encap == WTAP_ENCAP_ATM_PDUS &&
pseudo_header->atm.type == TRAF_LANE)
atm_guess_lane_type(pd, length, pseudo_header);
return TRUE;
static void
adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
{
+ guint32 temp;
+
if (wth->capture.pcap->byte_swapped) {
/* Byte-swap the record header fields. */
hdr->ts_sec = BSWAP32(hdr->ts_sec);
if (wth->file_type == WTAP_FILE_PCAP_AIX)
hdr->ts_usec = hdr->ts_usec/1000;
- /* In file format version 2.3, the "incl_len" and "orig_len" fields
- were swapped, in order to match the BPF header layout.
+ /* Swap the "incl_len" and "orig_len" fields, if necessary. */
+ switch (wth->capture.pcap->lengths_swapped) {
- 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;
+ case NOT_SWAPPED:
+ break;
+ case MAYBE_SWAPPED:
+ if (hdr->incl_len <= hdr->orig_len) {
+ /*
+ * The captured length is <= the actual length,
+ * so presumably they weren't swapped.
+ */
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case SWAPPED:
temp = hdr->orig_len;
hdr->orig_len = hdr->incl_len;
hdr->incl_len = temp;
+ break;
}
}
pseudo_header->atm.vpi = vpi;
pseudo_header->atm.vci = vci;
- pseudo_header->atm.channel = (atm_phdr->flags & 0x80) ? 1 : 0;
+ pseudo_header->atm.channel = (atm_phdr->flags & 0x80) ? 0 : 1;
/* We don't have this information */
+ pseudo_header->atm.flags = 0;
pseudo_header->atm.cells = 0;
pseudo_header->atm.aal5t_u2u = 0;
pseudo_header->atm.aal5t_len = 0;
{
unsigned int i;
- /*
- * Special-case WTAP_ENCAP_FDDI and WTAP_ENCAP_FDDI_BITSWAPPED;
- * both of them get mapped to DLT_FDDI (even though that may
- * mean that the bit order in the FDDI MAC addresses is wrong;
- * so it goes - libpcap format doesn't record the byte order,
- * so that's not fixable).
- */
- if (encap == WTAP_ENCAP_FDDI || encap == WTAP_ENCAP_FDDI_BITSWAPPED)
+ switch (encap) {
+
+ case WTAP_ENCAP_FDDI:
+ case WTAP_ENCAP_FDDI_BITSWAPPED:
+ /*
+ * Special-case WTAP_ENCAP_FDDI and
+ * WTAP_ENCAP_FDDI_BITSWAPPED; both of them get mapped
+ * to DLT_FDDI (even though that may mean that the bit
+ * order in the FDDI MAC addresses is wrong; so it goes
+ * - libpcap format doesn't record the byte order,
+ * so that's not fixable).
+ */
return 10; /* that's DLT_FDDI */
+
+ case WTAP_ENCAP_PPP_WITH_PHDR:
+ /*
+ * Also special-case PPP and Frame Relay with direction
+ * bits; map them to PPP and Frame Relay, even though
+ * that means that the direction of the packet is lost.
+ */
+ return 9;
+
+ case WTAP_ENCAP_FRELAY_WITH_PHDR:
+ return 107;
+ }
+
for (i = 0; i < NUM_PCAP_ENCAPS; i++) {
if (pcap_to_wtap_map[i].wtap_encap_value == encap)
return pcap_to_wtap_map[i].dlt_value;
* the VCI; read them and generate the pseudo-header from
* them.
*/
- if (linktype == WTAP_ENCAP_ATM_SNIFFER) {
+ if (linktype == WTAP_ENCAP_ATM_PDUS) {
if (whdr->caplen < sizeof (struct sunatm_hdr)) {
/*
* Uh-oh, the packet isn't big enough to even
*err = WTAP_ERR_BAD_RECORD;
return NULL;
}
- libpcap_get_atm_pseudoheader((struct sunatm_hdr *)pd,
+ libpcap_get_atm_pseudoheader((const struct sunatm_hdr *)pd,
pseudo_header);
/*
struct sunatm_hdr atm_hdr;
int atm_hdrsize;
- if (wdh->encap == WTAP_ENCAP_ATM_SNIFFER)
+ if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
atm_hdrsize = sizeof (struct sunatm_hdr);
else
atm_hdrsize = 0;
}
wdh->bytes_dumped += hdr_size;
- if (wdh->encap == WTAP_ENCAP_ATM_SNIFFER) {
+ if (wdh->encap == WTAP_ENCAP_ATM_PDUS) {
/*
* Write the ATM header.
*/
atm_hdr.flags =
- (pseudo_header->atm.channel != 0) ? 0x80 : 0x00;
+ (pseudo_header->atm.channel == 0) ? 0x80 : 0x00;
switch (pseudo_header->atm.aal) {
case AAL_SIGNALLING: