/* libpcap.c
*
- * $Id: libpcap.c,v 1.99 2003/10/24 10:52:04 sahlberg Exp $
+ * $Id: libpcap.c,v 1.119 2004/03/23 01:02:41 guy Exp $
*
* Wiretap Library
* Copyright (c) 1998 by Gilbert Ramirez <gram@alumni.rice.edu>
#include "config.h"
#endif
+#ifdef HAVE_PCAP_H
+#include <pcap.h>
+#endif
+
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
#include "wtap-int.h"
#include "file_wrappers.h"
# ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
# endif
-#include <pcap.h>
#include "wtap-capture.h"
#endif
/*
- * The link-layer header on ATM packets.
+ * The link-layer header on SunATM packets.
*/
struct sunatm_hdr {
guint8 flags; /* destination and traffic type */
guint16 vci; /* VCI */
};
+/*
+ * The link-layer header on Nokia IPSO ATM packets.
+ */
+struct nokiaatm_hdr {
+ guint8 flags; /* destination */
+ guint8 vpi; /* VPI */
+ guint16 vci; /* VCI */
+};
+
+/*
+ * The fake link-layer header of IrDA packets as introduced by Jean Tourrilhes
+ * to libpcap.
+ */
+struct irda_sll_hdr {
+ guint16 sll_pkttype; /* packet type */
+ guint8 unused[12]; /* usused SLL header fields */
+ guint16 sll_protocol; /* protocol, should be 0x0017 */
+};
+
/* See source to the "libpcap" library for information on the "libpcap"
file format. */
} libpcap_try_t;
static libpcap_try_t libpcap_try(wtap *wth, int *err);
-static gboolean libpcap_read(wtap *wth, int *err, long *data_offset);
+static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
+ long *data_offset);
static gboolean libpcap_seek_read(wtap *wth, long seek_off,
- union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err);
-static int libpcap_read_header(wtap *wth, int *err,
- struct pcaprec_ss990915_hdr *hdr, gboolean silent);
+ union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
+ int *err, gchar **err_info);
+static int libpcap_read_header(wtap *wth, int *err, gchar **err_info,
+ struct pcaprec_ss990915_hdr *hdr);
static void adjust_header(wtap *wth, struct pcaprec_hdr *hdr);
-static void libpcap_get_atm_pseudoheader(const struct sunatm_hdr *atm_phdr,
+static void libpcap_get_sunatm_pseudoheader(const struct sunatm_hdr *atm_phdr,
union wtap_pseudo_header *pseudo_header);
-static gboolean libpcap_read_atm_pseudoheader(FILE_T fh,
+static gboolean libpcap_read_sunatm_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err);
+static gboolean libpcap_read_nokiaatm_pseudoheader(FILE_T fh,
union wtap_pseudo_header *pseudo_header, int *err);
+static gboolean libpcap_get_irda_pseudoheader(const struct irda_sll_hdr *irda_phdr,
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
+static gboolean libpcap_read_irda_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
static gboolean libpcap_read_rec_data(FILE_T fh, guchar *pd, int length,
int *err);
static void libpcap_close(wtap *wth);
*/
{ 50, WTAP_ENCAP_PPP },
+ /*
+ * Apparently used by the Axent Raptor firewall (now Symantec
+ * Enterprise Firewall).
+ * Thanks, Axent, for not reserving that type with tcpdump.org
+ * and not telling anybody about it.
+ */
+ { 99, WTAP_ENCAP_SYMANTEC },
+
/*
* These are the values that libpcap 0.5 and later use in
* capture file headers, in an attempt to work around the
{ 121, WTAP_ENCAP_HHDLC }, /* HiPath HDLC */
{ 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 */
+ { 127, WTAP_ENCAP_IEEE_802_11_WLAN_BSD }, /* 802.11 plus BSD WLAN header */
{ 128, WTAP_ENCAP_TZSP }, /* Tazmen Sniffer Protocol */
{ 129, WTAP_ENCAP_ARCNET_LINUX },
/*
- * Values 130 thorugh 137 are reserved for use in Juniper
+ * Values 130 through 137 are reserved for use in Juniper
* hardware.
- *
- * 138 is reserved for Apple IP-over-IEEE 1394.
+ */
+
+ { 138, WTAP_ENCAP_APPLE_IP_OVER_IEEE1394 },
+ /* Apple IP-over-IEEE 1394 */
+
+ /* 139 is reserved for SS7 */
+
+ { 140, WTAP_ENCAP_MTP2 },
+ { 141, WTAP_ENCAP_MTP3 },
+ { 143, WTAP_ENCAP_DOCSIS },
+ { 144, WTAP_ENCAP_IRDA }, /* IrDA capture */
+
+ /* Reserved for private use. */
+ { 147, WTAP_ENCAP_USER0 },
+ { 148, WTAP_ENCAP_USER1 },
+ { 149, WTAP_ENCAP_USER2 },
+ { 150, WTAP_ENCAP_USER3 },
+ { 151, WTAP_ENCAP_USER4 },
+ { 152, WTAP_ENCAP_USER5 },
+ { 153, WTAP_ENCAP_USER6 },
+ { 154, WTAP_ENCAP_USER7 },
+ { 155, WTAP_ENCAP_USER8 },
+ { 156, WTAP_ENCAP_USER9 },
+ { 157, WTAP_ENCAP_USER10 },
+ { 158, WTAP_ENCAP_USER11 },
+ { 159, WTAP_ENCAP_USER12 },
+ { 160, WTAP_ENCAP_USER13 },
+ { 161, WTAP_ENCAP_USER14 },
+ { 162, WTAP_ENCAP_USER15 },
+
+ { 163, WTAP_ENCAP_IEEE_802_11_WLAN_AVS }, /* 802.11 plus AVS WLAN header */
+
+ /*
+ * 164 is reserved for Juniper-private chassis-internal
+ * meta-information such as QoS profiles, etc..
*/
/*
}
-int libpcap_open(wtap *wth, int *err)
+int libpcap_open(wtap *wth, int *err, gchar **err_info)
{
int bytes_read;
guint32 magic;
}
if (hdr.version_major < 2) {
/* We only support version 2.0 and later. */
- g_message("pcap: major version %u unsupported",
- hdr.version_major);
*err = WTAP_ERR_UNSUPPORTED;
+ *err_info = g_strdup_printf("pcap: major version %u unsupported",
+ hdr.version_major);
return -1;
}
break;
}
}
+
+ /*
+ * We treat a DLT_ value of 13 specially - it appears that in
+ * Nokia libpcap format, it's some form of ATM with what I
+ * suspect is a pseudo-header (even though Nokia's IPSO is
+ * based on FreeBSD, which #defines DLT_SLIP_BSDOS as 13).
+ *
+ * We don't yet know whether this is a Nokia capture, so if
+ * "wtap_pcap_encap_to_wtap_encap()" returned WTAP_ENCAP_UNKNOWN
+ * but "hdr.network" is 13, we don't treat that as an error yet.
+ */
file_encap = wtap_pcap_encap_to_wtap_encap(hdr.network);
- if (file_encap == WTAP_ENCAP_UNKNOWN) {
- g_message("pcap: network type %u unknown or unsupported",
- hdr.network);
+ if (file_encap == WTAP_ENCAP_UNKNOWN && hdr.network != 13) {
*err = WTAP_ERR_UNSUPPORTED_ENCAP;
+ *err_info = g_strdup_printf("pcap: network type %u unknown or unsupported",
+ hdr.network);
return -1;
}
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?
*/
}
}
+ if (hdr.network == 13) {
+ /*
+ * OK, if this was a Nokia capture, make it
+ * WTAP_ENCAP_ATM_PDUS, otherwise return
+ * an error.
+ */
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA)
+ wth->file_encap = WTAP_ENCAP_ATM_PDUS;
+ else {
+ *err = WTAP_ERR_UNSUPPORTED_ENCAP;
+ *err_info = g_strdup_printf("pcap: network type %u unknown or unsupported",
+ hdr.network);
+ return -1;
+ }
+ }
+
return 1;
}
/*
* Attempt to read the first record's header.
*/
- if (libpcap_read_header(wth, err, &first_rec_hdr, TRUE) == -1) {
+ if (libpcap_read_header(wth, err, NULL, &first_rec_hdr) == -1) {
if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
/*
* EOF or short read - assume the file is in this
/*
* Now attempt to read the second record's header.
*/
- if (libpcap_read_header(wth, err, &second_rec_hdr, TRUE) == -1) {
+ if (libpcap_read_header(wth, err, NULL, &second_rec_hdr) == -1) {
if (*err == 0 || *err == WTAP_ERR_SHORT_READ) {
/*
* EOF or short read - assume the file is in this
}
/* Read the next packet */
-static gboolean libpcap_read(wtap *wth, int *err, long *data_offset)
+static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
+ long *data_offset)
{
struct pcaprec_ss990915_hdr hdr;
guint packet_size;
guint orig_size;
int bytes_read;
- char fddi_padding[3];
+ guchar fddi_padding[3];
- bytes_read = libpcap_read_header(wth, err, &hdr, FALSE);
+ bytes_read = libpcap_read_header(wth, err, err_info, &hdr);
if (bytes_read == -1) {
/*
* We failed to read the header.
switch (wth->file_encap) {
case WTAP_ENCAP_ATM_PDUS:
- if (packet_size < sizeof (struct sunatm_hdr)) {
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ */
+ if (packet_size < sizeof (struct nokiaatm_hdr)) {
+ /*
+ * Uh-oh, the packet isn't big enough to even
+ * have a pseudo-header.
+ */
+ *err = WTAP_ERR_BAD_RECORD;
+ *err_info = g_strdup_printf("libpcap: Nokia IPSO ATM file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
+ packet_size);
+ return FALSE;
+ }
+ if (!libpcap_read_nokiaatm_pseudoheader(wth->fh,
+ &wth->pseudo_header, err))
+ return FALSE; /* Read error */
+
+ /*
+ * Don't count the pseudo-header as part of the
+ * packet.
+ */
+ orig_size -= sizeof (struct nokiaatm_hdr);
+ packet_size -= sizeof (struct nokiaatm_hdr);
+ wth->data_offset += sizeof (struct nokiaatm_hdr);
+ } else {
+ /*
+ * SunATM.
+ */
+ if (packet_size < sizeof (struct sunatm_hdr)) {
+ /*
+ * Uh-oh, the packet isn't big enough to even
+ * have a pseudo-header.
+ */
+ *err = WTAP_ERR_BAD_RECORD;
+ *err_info = g_strdup_printf("libpcap: SunATM file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
+ packet_size);
+ return FALSE;
+ }
+ if (!libpcap_read_sunatm_pseudoheader(wth->fh,
+ &wth->pseudo_header, err))
+ return FALSE; /* Read error */
+
+ /*
+ * Don't count the pseudo-header as part of the
+ * packet.
+ */
+ 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;
+
+ case WTAP_ENCAP_IEEE_802_11:
+ case WTAP_ENCAP_PRISM_HEADER:
+ case WTAP_ENCAP_IEEE_802_11_WLAN_BSD:
+ case WTAP_ENCAP_IEEE_802_11_WLAN_AVS:
+ /*
+ * We don't know whether there's an FCS in this frame or not.
+ * XXX - are there any OSes where the capture mechanism
+ * supplies an FCS?
+ */
+ wth->pseudo_header.ieee_802_11.fcs_len = -1;
+ break;
+
+ case WTAP_ENCAP_IRDA:
+ if (packet_size < sizeof (struct irda_sll_hdr)) {
/*
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- g_message("libpcap: SunATM file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
- packet_size);
*err = WTAP_ERR_BAD_RECORD;
+ *err_info = g_strdup_printf("libpcap: IrDA file has a %u-byte packet, too small to have even an IrDA pseudo-header\n",
+ packet_size);
return FALSE;
}
- if (!libpcap_read_atm_pseudoheader(wth->fh, &wth->pseudo_header,
- err))
+ if (!libpcap_read_irda_pseudoheader(wth->fh, &wth->pseudo_header,
+ err, err_info))
return FALSE; /* Read error */
/*
* Don't count the pseudo-header as part of the packet.
*/
- 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;
+ orig_size -= sizeof (struct irda_sll_hdr);
+ packet_size -= sizeof (struct irda_sll_hdr);
+ wth->data_offset += sizeof (struct irda_sll_hdr);
break;
}
wth->phdr.ts.tv_usec = hdr.hdr.ts_usec;
wth->phdr.caplen = packet_size;
wth->phdr.len = orig_size;
- wth->phdr.pkt_encap = wth->file_encap;
- /*
- * 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_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 (wth->file_encap == WTAP_ENCAP_ATM_PDUS) {
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ *
+ * Guess the traffic type based on the packet
+ * contents.
+ */
+ atm_guess_traffic_type(buffer_start_ptr(wth->frame_buffer),
+ wth->phdr.caplen, &wth->pseudo_header);
+ } else {
+ /*
+ * SunATM.
+ *
+ * If this is ATM LANE traffic, try to guess what
+ * type of LANE traffic it is based on the packet
+ * contents.
+ */
+ if (wth->pseudo_header.atm.type == TRAF_LANE) {
+ atm_guess_lane_type(buffer_start_ptr(wth->frame_buffer),
+ wth->phdr.caplen, &wth->pseudo_header);
+ }
+ }
}
return TRUE;
static gboolean
libpcap_seek_read(wtap *wth, long seek_off,
- union wtap_pseudo_header *pseudo_header, guchar *pd, int length, int *err)
+ union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
+ int *err, gchar **err_info)
{
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
switch (wth->file_encap) {
case WTAP_ENCAP_ATM_PDUS:
- if (!libpcap_read_atm_pseudoheader(wth->random_fh, pseudo_header,
- err)) {
- /* Read error */
- return FALSE;
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ */
+ if (!libpcap_read_nokiaatm_pseudoheader(wth->random_fh,
+ pseudo_header, err)) {
+ /* Read error */
+ return FALSE;
+ }
+ } else {
+ /*
+ * SunATM.
+ */
+ if (!libpcap_read_sunatm_pseudoheader(wth->random_fh,
+ pseudo_header, err)) {
+ /* Read error */
+ return FALSE;
+ }
}
break;
*/
pseudo_header->eth.fcs_len = -1;
break;
+
+ case WTAP_ENCAP_IEEE_802_11:
+ case WTAP_ENCAP_PRISM_HEADER:
+ case WTAP_ENCAP_IEEE_802_11_WLAN_BSD:
+ case WTAP_ENCAP_IEEE_802_11_WLAN_AVS:
+ /*
+ * We don't know whether there's an FCS in this frame or not.
+ * XXX - are there any OSes where the capture mechanism
+ * supplies an FCS?
+ */
+ pseudo_header->ieee_802_11.fcs_len = -1;
+ break;
+
+ case WTAP_ENCAP_IRDA:
+ if (!libpcap_read_irda_pseudoheader(wth->random_fh, pseudo_header,
+ err, err_info)) {
+ /* Read error */
+ return FALSE;
+ }
+ break;
}
/*
if (!libpcap_read_rec_data(wth->random_fh, pd, length, err))
return FALSE; /* failed */
- /*
- * 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_PDUS &&
- pseudo_header->atm.type == TRAF_LANE)
- atm_guess_lane_type(pd, length, pseudo_header);
+ if (wth->file_encap == WTAP_ENCAP_ATM_PDUS) {
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ *
+ * Guess the traffic type based on the packet
+ * contents.
+ */
+ atm_guess_traffic_type(pd, length, pseudo_header);
+ } else {
+ /*
+ * SunATM.
+ *
+ * If this is ATM LANE traffic, try to guess what
+ * type of LANE traffic it is based on the packet
+ * contents.
+ */
+ if (pseudo_header->atm.type == TRAF_LANE)
+ atm_guess_lane_type(pd, length, pseudo_header);
+ }
+ }
return TRUE;
}
-/* Read the header of the next packet; if "silent" is TRUE, don't complain
- to the console, as we're testing to see if the file appears to be of a
- particular type.
+/* Read the header of the next packet.
Return -1 on an error, or the number of bytes of header read on success. */
-static int libpcap_read_header(wtap *wth, int *err,
- struct pcaprec_ss990915_hdr *hdr, gboolean silent)
+static int libpcap_read_header(wtap *wth, int *err, gchar **err_info,
+ struct pcaprec_ss990915_hdr *hdr)
{
int bytes_to_read, bytes_read;
* this is can tell when it's not the type we're guessing
* it is.
*/
- if (!silent) {
- g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
+ *err = WTAP_ERR_BAD_RECORD;
+ if (err_info != NULL) {
+ *err_info = g_strdup_printf("pcap: File has %u-byte packet, bigger than maximum of %u",
hdr->hdr.incl_len, WTAP_MAX_PACKET_SIZE);
}
- *err = WTAP_ERR_BAD_RECORD;
return -1;
}
* this is can tell when it's not the type we're guessing
* it is.
*/
- if (!silent) {
- g_message("pcap: File has %u-byte packet, bigger than maximum of %u",
+ *err = WTAP_ERR_BAD_RECORD;
+ if (err_info != NULL) {
+ *err_info = g_strdup_printf("pcap: File has %u-byte packet, bigger than maximum of %u",
hdr->hdr.orig_len, WTAP_MAX_PACKET_SIZE);
}
- *err = WTAP_ERR_BAD_RECORD;
return -1;
}
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;
- temp = hdr->orig_len;
- hdr->orig_len = hdr->incl_len;
- hdr->incl_len = temp;
- }
- /* DG/UX use v 543.0 and also swap these fields */
- if(wth->capture.pcap->version_major == 543 &&
- wth->capture.pcap->version_minor == 0){
- guint32 temp;
+ 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;
}
}
static void
-libpcap_get_atm_pseudoheader(const struct sunatm_hdr *atm_phdr,
+libpcap_get_sunatm_pseudoheader(const struct sunatm_hdr *atm_phdr,
union wtap_pseudo_header *pseudo_header)
{
guint8 vpi;
vpi = atm_phdr->vpi;
vci = pntohs(&atm_phdr->vci);
- /*
- * The lower 4 bits of the first byte of the header indicate
- * the type of traffic, as per the "atmioctl.h" header in
- * SunATM.
- */
switch (atm_phdr->flags & 0x0F) {
case 0x01: /* LANE */
}
static gboolean
-libpcap_read_atm_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err)
+libpcap_read_sunatm_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
{
struct sunatm_hdr atm_phdr;
int bytes_read;
return FALSE;
}
- libpcap_get_atm_pseudoheader(&atm_phdr, pseudo_header);
+ libpcap_get_sunatm_pseudoheader(&atm_phdr, pseudo_header);
return TRUE;
}
+static gboolean
+libpcap_read_nokiaatm_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
+{
+ struct nokiaatm_hdr atm_phdr;
+ int bytes_read;
+ guint8 vpi;
+ guint16 vci;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(&atm_phdr, 1, sizeof (struct nokiaatm_hdr), fh);
+ if (bytes_read != sizeof (struct nokiaatm_hdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ vpi = atm_phdr.vpi;
+ vci = pntohs(&atm_phdr.vci);
+
+ pseudo_header->atm.vpi = vpi;
+ pseudo_header->atm.vci = vci;
+ 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;
+ pseudo_header->atm.aal5t_chksum = 0;
+
+ return TRUE;
+}
+
+static gboolean
+libpcap_get_irda_pseudoheader(const struct irda_sll_hdr *irda_phdr,
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
+{
+ if (pntohs(&irda_phdr->sll_protocol) != 0x0017) {
+ *err = WTAP_ERR_BAD_RECORD;
+ if (err_info != NULL)
+ *err_info = g_strdup("libpcap: IrDA capture has a packet with an invalid sll_protocol field\n");
+ return FALSE;
+ }
+
+ pseudo_header->irda.pkttype = pntohs(&irda_phdr->sll_pkttype);
+
+ return TRUE;
+}
+
+static gboolean
+libpcap_read_irda_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info)
+{
+ struct irda_sll_hdr irda_phdr;
+ int bytes_read;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(&irda_phdr, 1, sizeof (struct irda_sll_hdr), fh);
+ if (bytes_read != sizeof (struct irda_sll_hdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ return libpcap_get_irda_pseudoheader(&irda_phdr, pseudo_header, err,
+ err_info);
+}
+
static gboolean
libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
{
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.
+ * Also special-case PPP with direction bits; map it to
+ * PPP, even though that means that the direction of the
+ * packet is lost.
*/
return 9;
case WTAP_ENCAP_FRELAY_WITH_PHDR:
+ /*
+ * Do the same with Frame Relay.
+ */
return 107;
+
+ case WTAP_ENCAP_IEEE_802_11_WITH_RADIO:
+ /*
+ * Map this to DLT_IEEE802_11, for now, even though
+ * that means the radio information will be lost.
+ * Once tcpdump support for the BSD radiotap header
+ * is sufficiently widespread, we should probably
+ * use that, instead - although we should probably
+ * ultimately just have WTAP_ENCAP_IEEE_802_11
+ * as the only Wiretap encapsulation for 802.11,
+ * and have the pseudo-header include a radiotap-style
+ * list of attributes. If we do that, though, we
+ * should probably bypass the regular Wiretap code
+ * when writing out packets during a capture, and just
+ * do the equivalent of a libpcap write (unfortunately,
+ * libpcap doesn't have an "open dump by file descriptor"
+ * function, so we can't just use "pcap_dump()"), so
+ * that we don't spend cycles mapping from libpcap to
+ * Wiretap and then back to libpcap. (There are other
+ * reasons to do that, e.g. to handle AIX libpcap better.)
+ */
+ return 105;
}
for (i = 0; i < NUM_PCAP_ENCAPS; i++) {
*err = WTAP_ERR_BAD_RECORD;
return NULL;
}
- libpcap_get_atm_pseudoheader((const struct sunatm_hdr *)pd,
+ libpcap_get_sunatm_pseudoheader((const struct sunatm_hdr *)pd,
pseudo_header);
/*
if (pseudo_header->atm.type == TRAF_LANE)
atm_guess_lane_type(pd, whdr->caplen, pseudo_header);
}
+ else if (linktype == WTAP_ENCAP_IRDA) {
+ if (whdr->caplen < sizeof (struct irda_sll_hdr)) {
+ /*
+ * Uh-oh, the packet isn't big enough to even
+ * have a pseudo-header.
+ */
+ g_message("libpcap: IrDA capture has a %u-byte packet, too small to have even an IrDA pseudo-header\n",
+ whdr->caplen);
+ *err = WTAP_ERR_BAD_RECORD;
+ return NULL;
+ }
+ if (!libpcap_get_irda_pseudoheader((const struct irda_sll_hdr *)pd,
+ pseudo_header, err, NULL))
+ return NULL;
+
+ /*
+ * Don't count the pseudo-header as part of the packet.
+ */
+ whdr->len -= sizeof (struct irda_sll_hdr);
+ whdr->caplen -= sizeof (struct irda_sll_hdr);
+ pd += sizeof (struct irda_sll_hdr);
+ }
return pd;
}
#endif
size_t hdr_size;
size_t nwritten;
struct sunatm_hdr atm_hdr;
- int atm_hdrsize;
+ struct irda_sll_hdr irda_hdr;
+ int hdrsize;
if (wdh->encap == WTAP_ENCAP_ATM_PDUS)
- atm_hdrsize = sizeof (struct sunatm_hdr);
+ hdrsize = sizeof (struct sunatm_hdr);
+ else if (wdh->encap == WTAP_ENCAP_IRDA)
+ hdrsize = sizeof (struct irda_sll_hdr);
else
- atm_hdrsize = 0;
+ hdrsize = 0;
rec_hdr.hdr.ts_sec = phdr->ts.tv_sec;
rec_hdr.hdr.ts_usec = phdr->ts.tv_usec;
- rec_hdr.hdr.incl_len = phdr->caplen + atm_hdrsize;
- rec_hdr.hdr.orig_len = phdr->len + atm_hdrsize;
+ rec_hdr.hdr.incl_len = phdr->caplen + hdrsize;
+ rec_hdr.hdr.orig_len = phdr->len + hdrsize;
switch (wdh->file_type) {
case WTAP_FILE_PCAP:
}
break;
}
- atm_hdr.vpi = pseudo_header->atm.vpi;
+ atm_hdr.vpi = (guint8) pseudo_header->atm.vpi;
atm_hdr.vci = phtons(&pseudo_header->atm.vci);
nwritten = fwrite(&atm_hdr, 1, sizeof atm_hdr, wdh->fh);
if (nwritten != sizeof atm_hdr) {
}
wdh->bytes_dumped += sizeof atm_hdr;
}
+ else if (wdh->encap == WTAP_ENCAP_IRDA) {
+ /*
+ * Write the IrDA header.
+ */
+ memset(&irda_hdr, 0, sizeof(irda_hdr));
+ irda_hdr.sll_pkttype = phtons(&pseudo_header->irda.pkttype);
+ irda_hdr.sll_protocol = g_htons(0x0017);
+ nwritten = fwrite(&irda_hdr, 1, sizeof(irda_hdr), wdh->fh);
+ if (nwritten != sizeof(irda_hdr)) {
+ if (nwritten == 0 && ferror(wdh->fh))
+ *err = errno;
+ else
+ *err = WTAP_ERR_SHORT_WRITE;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(irda_hdr);
+ }
nwritten = fwrite(pd, 1, phdr->caplen, wdh->fh);
if (nwritten != phdr->caplen) {