#include <errno.h>
#include "wtap-int.h"
#include "file_wrappers.h"
+#include "atm.h"
#include "erf.h"
+#include "pcap-encap.h"
#include "pcap-common.h"
/*
{ 127, WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP }, /* 802.11 plus radiotap WLAN header */
{ 128, WTAP_ENCAP_TZSP }, /* Tazmen Sniffer Protocol */
{ 129, WTAP_ENCAP_ARCNET_LINUX },
- { 130, WTAP_ENCAP_JUNIPER_MLPPP }, /* Juniper MLPPP on ML-, LS-, AS- PICs */
- { 131, WTAP_ENCAP_JUNIPER_MLFR }, /* Juniper MLFR (FRF.15) on ML-, LS-, AS- PICs */
- { 133, WTAP_ENCAP_JUNIPER_GGSN},
+ { 130, WTAP_ENCAP_JUNIPER_MLPPP }, /* Juniper MLPPP on ML-, LS-, AS- PICs */
+ { 131, WTAP_ENCAP_JUNIPER_MLFR }, /* Juniper MLFR (FRF.15) on ML-, LS-, AS- PICs */
+ { 133, WTAP_ENCAP_JUNIPER_GGSN},
/*
* Values 132-134, 136 not listed here are reserved for use
* in Juniper hardware.
* but it is used for some Linux IP filtering (ipfilter?).
*/
- /* Ethernet PPPoE frames captured on a service PIC */
- { 167, WTAP_ENCAP_JUNIPER_PPPOE },
+ /* Ethernet PPPoE frames captured on a service PIC */
+ { 167, WTAP_ENCAP_JUNIPER_PPPOE },
/*
* 168 is reserved for more Juniper private-chassis-
{ 177, WTAP_ENCAP_LINUX_LAPD },
- /* Ethernet frames prepended with meta-information */
- { 178, WTAP_ENCAP_JUNIPER_ETHER },
- /* PPP frames prepended with meta-information */
- { 179, WTAP_ENCAP_JUNIPER_PPP },
- /* Frame-Relay frames prepended with meta-information */
- { 180, WTAP_ENCAP_JUNIPER_FRELAY },
- /* C-HDLC frames prepended with meta-information */
- { 181, WTAP_ENCAP_JUNIPER_CHDLC },
- /* VOIP Frames prepended with meta-information */
- { 183, WTAP_ENCAP_JUNIPER_VP },
+ /* Ethernet frames prepended with meta-information */
+ { 178, WTAP_ENCAP_JUNIPER_ETHER },
+ /* PPP frames prepended with meta-information */
+ { 179, WTAP_ENCAP_JUNIPER_PPP },
+ /* Frame-Relay frames prepended with meta-information */
+ { 180, WTAP_ENCAP_JUNIPER_FRELAY },
+ /* C-HDLC frames prepended with meta-information */
+ { 181, WTAP_ENCAP_JUNIPER_CHDLC },
+ /* VOIP Frames prepended with meta-information */
+ { 183, WTAP_ENCAP_JUNIPER_VP },
/* raw USB packets */
{ 186, WTAP_ENCAP_USB },
/* Bluetooth HCI UART transport (part H:4) frames, like hcidump */
{ 189, WTAP_ENCAP_USB_LINUX },
/* CAN 2.0b frame */
{ 190, WTAP_ENCAP_CAN20B },
- /* Per-Packet Information header */
- { 192, WTAP_ENCAP_PPI },
+ /* Per-Packet Information header */
+ { 192, WTAP_ENCAP_PPI },
/* IEEE 802.15.4 Wireless PAN */
{ 195, WTAP_ENCAP_IEEE802_15_4 },
/* SITA File Encapsulation */
- { 196, WTAP_ENCAP_SITA },
+ { 196, WTAP_ENCAP_SITA },
/* Endace Record File Encapsulation */
- { 197, WTAP_ENCAP_ERF },
+ { 197, WTAP_ENCAP_ERF },
/* IPMB */
{ 199, WTAP_ENCAP_IPMB },
/* Bluetooth HCI UART transport (part H:4) frames, like hcidump */
{ 201, WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR },
+ /* LAPD frame */
+ { 203, WTAP_ENCAP_LAPD },
+ /* PPP with pseudoheader */
{ 204, WTAP_ENCAP_PPP_WITH_PHDR },
/* IPMB/I2C */
{ 209, WTAP_ENCAP_I2C },
/* USB packets with padded Linux-specified header */
{ 220, WTAP_ENCAP_USB_LINUX_MMAPPED },
/* Fibre Channel FC-2 frame */
- { 224, WTAP_ENCAP_FIBRE_CHANNEL_FC2 },
+ { 224, WTAP_ENCAP_FIBRE_CHANNEL_FC2 },
/* Fibre Channel FC-2 frame with Delimiter */
- { 225, WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS },
- /* Solaris DLPI */
- { 226, WTAP_ENCAP_IPNET },
-
+ { 225, WTAP_ENCAP_FIBRE_CHANNEL_FC2_WITH_FRAME_DELIMS },
+ /* Solaris IPNET */
+ { 226, WTAP_ENCAP_IPNET },
/* SocketCAN frame */
- { 227, WTAP_ENCAP_SOCKETCAN },
+ { 227, WTAP_ENCAP_SOCKETCAN },
+ /* Raw IPv4 */
+ { 228, WTAP_ENCAP_RAW_IP4 },
+ /* Raw IPv6 */
+ { 229, WTAP_ENCAP_RAW_IP6 },
+ /* IEEE 802.15.4 Wireless PAN no fcs */
+ { 230, WTAP_ENCAP_IEEE802_15_4_NOFCS },
+ /* DVB-CI (Common Interface) */
+ { 235, WTAP_ENCAP_DVBCI },
+ /* MUX27010 */
+ { 236, WTAP_ENCAP_MUX27010 },
+ /* netANALYZER pseudo-header followed by Ethernet with CRC */
+ { 240, WTAP_ENCAP_NETANALYZER },
+ /* netANALYZER pseudo-header in transparent mode */
+ { 241, WTAP_ENCAP_NETANALYZER_TRANSPARENT },
+ /* IP-over-Infiniband, as specified by RFC 4391 section 6 */
+ { 242, WTAP_ENCAP_IP_OVER_IB },
+ /* ISO/IEC 13818-1 MPEG2-TS packets */
+ { 243, WTAP_ENCAP_MPEG_2_TS },
/*
* To repeat:
static gboolean
pcap_read_sunatm_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
guint8 atm_phdr[SUNATM_LEN];
int bytes_read;
guint16 vci;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(atm_phdr, 1, SUNATM_LEN, fh);
+ bytes_read = file_read(atm_phdr, SUNATM_LEN, fh);
if (bytes_read != SUNATM_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
static gboolean
pcap_read_nokiaatm_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
guint8 atm_phdr[NOKIAATM_LEN];
int bytes_read;
guint16 vci;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(atm_phdr, 1, NOKIAATM_LEN, fh);
+ bytes_read = file_read(atm_phdr, NOKIAATM_LEN, fh);
if (bytes_read != NOKIAATM_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(irda_phdr, 1, IRDA_SLL_LEN, fh);
+ bytes_read = file_read(irda_phdr, IRDA_SLL_LEN, fh);
if (bytes_read != IRDA_SLL_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
if (pntohs(&irda_phdr[IRDA_SLL_PROTOCOL_OFFSET]) != 0x0017) {
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
if (err_info != NULL)
*err_info = g_strdup("libpcap: IrDA capture has a packet with an invalid sll_protocol field");
return FALSE;
}
static gboolean
-pcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+pcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
guint8 mtp2_hdr[MTP2_HDR_LEN];
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(mtp2_hdr, 1, MTP2_HDR_LEN, fh);
+ bytes_read = file_read(mtp2_hdr, MTP2_HDR_LEN, fh);
if (bytes_read != MTP2_HDR_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(lapd_phdr, 1, LAPD_SLL_LEN, fh);
+ bytes_read = file_read(lapd_phdr, LAPD_SLL_LEN, fh);
if (bytes_read != LAPD_SLL_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
if (pntohs(&lapd_phdr[LAPD_SLL_PROTOCOL_OFFSET]) != ETH_P_LAPD) {
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
if (err_info != NULL)
*err_info = g_strdup("libpcap: LAPD capture has a packet with an invalid sll_protocol field");
return FALSE;
}
static gboolean
-pcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+pcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
guint8 sita_phdr[SITA_HDR_LEN];
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(sita_phdr, 1, SITA_HDR_LEN, fh);
+ bytes_read = file_read(sita_phdr, SITA_HDR_LEN, fh);
if (bytes_read != SITA_HDR_LEN) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
- pseudo_header->sita.flags = sita_phdr[SITA_FLAGS_OFFSET];
- pseudo_header->sita.signals = sita_phdr[SITA_SIGNALS_OFFSET];
- pseudo_header->sita.errors1 = sita_phdr[SITA_ERRORS1_OFFSET];
- pseudo_header->sita.errors2 = sita_phdr[SITA_ERRORS2_OFFSET];
- pseudo_header->sita.proto = sita_phdr[SITA_PROTO_OFFSET];
+ pseudo_header->sita.sita_flags = sita_phdr[SITA_FLAGS_OFFSET];
+ pseudo_header->sita.sita_signals = sita_phdr[SITA_SIGNALS_OFFSET];
+ pseudo_header->sita.sita_errors1 = sita_phdr[SITA_ERRORS1_OFFSET];
+ pseudo_header->sita.sita_errors2 = sita_phdr[SITA_ERRORS2_OFFSET];
+ pseudo_header->sita.sita_proto = sita_phdr[SITA_PROTO_OFFSET];
return TRUE;
}
-static gboolean
-pcap_read_linux_usb_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, gboolean byte_swapped, int *err)
-{
- int bytes_read;
+/*
+ * When not using the memory-mapped interface to capture USB events,
+ * code that reads those events can use the MON_IOCX_GET ioctl to
+ * read a 48-byte header consisting of a "struct linux_usb_phdr", as
+ * defined below, followed immediately by one of:
+ *
+ * 8 bytes of a "struct usb_device_setup_hdr", if "setup_flag"
+ * in the preceding "struct linux_usb_phdr" is 0;
+ *
+ * in Linux 2.6.30 or later, 8 bytes of a "struct iso_rec", if
+ * this is an isochronous transfer;
+ *
+ * 8 bytes of junk, otherwise.
+ *
+ * In Linux 2.6.31 and later, it can also use the MON_IOCX_GETX ioctl
+ * to read a 64-byte header; that header consists of the 48 bytes
+ * above, followed immediately by 16 bytes of a "struct linux_usb_phdr_ext",
+ * as defined below.
+ *
+ * In Linux 2.6.21 and later, there's a memory-mapped interface to
+ * capture USB events. In that interface, the events in the memory-mapped
+ * buffer have a 64-byte header, followed immediately by the data.
+ * In Linux 2.6.21 through 2.6.30.x, the 64-byte header is the 48-byte
+ * header described above, followed by 16 bytes of zeroes; in Linux
+ * 2.6.31 and later, the 64-byte header is the 64-byte header described
+ * above.
+ *
+ * See linux/Documentation/usb/usbmon.txt and libpcap/pcap/usb.h for details.
+ *
+ * With WTAP_ENCAP_USB_LINUX, packets have the 48-byte header; with
+ * WTAP_ENCAP_USB_LINUX_MMAPPED, they have the 64-byte header. There
+ * is no indication of whether the header has the "struct iso_rec", or
+ * whether the last 16 bytes of a 64-byte header are all zeros or are
+ * a "struct linux_usb_phdr_ext".
+ */
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&pseudo_header->linux_usb, 1,
- sizeof (struct linux_usb_phdr), fh);
- if (bytes_read != sizeof (struct linux_usb_phdr)) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
+/*
+ * URB transfer_type values
+ */
+#define URB_ISOCHRONOUS 0x0
+#define URB_INTERRUPT 0x1
+#define URB_CONTROL 0x2
+#define URB_BULK 0x3
+
+/*
+ * Information from the URB for Isochronous transfers.
+ *
+ * This structure is 8 bytes long.
+ */
+struct iso_rec {
+ gint32 error_count;
+ gint32 numdesc;
+};
+
+/*
+ * Header prepended by Linux kernel to each USB event.
+ *
+ * (Setup flag is '-', 'D', 'Z', or 0. Data flag is '<', '>', 'Z', or 0.)
+ *
+ * The values are in *host* byte order.
+ */
+struct linux_usb_phdr {
+ guint64 id; /* urb id, to link submission and completion events */
+ guint8 event_type; /* Submit ('S'), Completed ('C'), Error ('E') */
+ guint8 transfer_type; /* ISO (0), Intr, Control, Bulk (3) */
+ guint8 endpoint_number; /* Endpoint number (0-15) and transfer direction */
+ guint8 device_address; /* 0-127 */
+ guint16 bus_id;
+ gint8 setup_flag; /* 0, if the urb setup header is meaningful */
+ gint8 data_flag; /* 0, if urb data is present */
+ gint64 ts_sec;
+ gint32 ts_usec;
+ gint32 status;
+ guint32 urb_len; /* whole len of urb this event refers to */
+ guint32 data_len; /* amount of urb data really present in this event */
+
+ /*
+ * Packet-type-dependent data.
+ * USB setup information of setup_flag is true.
+ * Otherwise, some isochronous transfer information.
+ */
+ union {
+ guint8 data[8];
+ struct iso_rec iso;
+ } s;
+
+ /*
+ * This data is provided by Linux 2.6.31 and later kernels.
+ *
+ * For WTAP_ENCAP_USB_LINUX, it's not in the pseudo-header, so
+ * the pseudo-header is always 48 bytes long, including the
+ * packet-type-dependent data.
+ *
+ * For WTAP_ENCAP_USB_LINUX_MMAPPED, the pseudo-header is always
+ * 64 bytes long, with the packet-type-dependent data preceding
+ * these last 16 bytes. In pre-2.6.31 kernels, it's zero padding;
+ * in 2.6.31 and later, it's the following data.
+ */
+ gint32 interval; /* only for Interrupt and Isochronous events */
+ gint32 start_frame; /* for Isochronous */
+ guint32 xfer_flags; /* copy of URB's transfer_flags */
+ guint32 ndesc; /* actual number of isochronous descriptors */
+};
+
+struct linux_usb_isodesc {
+ gint32 iso_status;
+ guint32 iso_off;
+ guint32 iso_len;
+ guint32 _pad;
+};
+
+/*
+ * USB setup header as defined in USB specification
+ * See usb_20.pdf, Chapter 9.3 'USB Device Requests' for details.
+ * http://www.usb.org/developers/docs/usb_20_122909-2.zip
+ *
+ * This structure is 8 bytes long.
+ */
+struct usb_device_setup_hdr {
+ gint8 bmRequestType;
+ guint8 bRequest;
+ guint16 wValue;
+ guint16 wIndex;
+ guint16 wLength;
+};
+
+
+/*
+ * Offset of the *end* of a field within a particular structure.
+ */
+#define END_OFFSETOF(basep, fieldp) \
+ (((char *)(void *)(fieldp)) - ((char *)(void *)(basep)) + \
+ sizeof(*fieldp))
+
+static void
+pcap_process_linux_usb_pseudoheader(guint packet_size, gboolean byte_swapped,
+ gboolean header_len_64_bytes, guint8 *pd)
+{
+ struct linux_usb_phdr *phdr;
+ struct linux_usb_isodesc *pisodesc;
+ gint32 iso_numdesc, i;
if (byte_swapped) {
- pseudo_header->linux_usb.id = GUINT64_SWAP_LE_BE(pseudo_header->linux_usb.id);
- pseudo_header->linux_usb.bus_id = GUINT16_SWAP_LE_BE(pseudo_header->linux_usb.bus_id);
- pseudo_header->linux_usb.ts_sec = GUINT64_SWAP_LE_BE(pseudo_header->linux_usb.ts_sec);
- pseudo_header->linux_usb.ts_usec = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.ts_usec);
- pseudo_header->linux_usb.status = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.status);
- pseudo_header->linux_usb.urb_len = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.urb_len);
- pseudo_header->linux_usb.data_len = GUINT32_SWAP_LE_BE(pseudo_header->linux_usb.data_len);
- }
+ /*
+ * Greasy hack, but we never directly direference any of
+ * the fields in *phdr, we just get offsets of and
+ * addresses of its members, so it's safe.
+ */
+ phdr = (struct linux_usb_phdr *)(void *)pd;
+
+ if (packet_size < END_OFFSETOF(phdr, &phdr->id))
+ return;
+ PBSWAP64((guint8 *)&phdr->id);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->bus_id))
+ return;
+ PBSWAP16((guint8 *)&phdr->bus_id);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->ts_sec))
+ return;
+ PBSWAP64((guint8 *)&phdr->ts_sec);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->ts_usec))
+ return;
+ PBSWAP32((guint8 *)&phdr->ts_usec);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->status))
+ return;
+ PBSWAP32((guint8 *)&phdr->status);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->urb_len))
+ return;
+ PBSWAP32((guint8 *)&phdr->urb_len);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->data_len))
+ return;
+ PBSWAP32((guint8 *)&phdr->data_len);
+
+ if (phdr->transfer_type == URB_ISOCHRONOUS) {
+ if (packet_size < END_OFFSETOF(phdr, &phdr->s.iso.error_count))
+ return;
+ PBSWAP32((guint8 *)&phdr->s.iso.error_count);
+
+ if (packet_size < END_OFFSETOF(phdr, &phdr->s.iso.numdesc))
+ return;
+ PBSWAP32((guint8 *)&phdr->s.iso.numdesc);
- return TRUE;
+ }
+
+ if (header_len_64_bytes) {
+ /*
+ * This is either the "version 1" header, with
+ * 16 bytes of additional fields at the end, or
+ * a "version 0" header from a memory-mapped
+ * capture, with 16 bytes of zeroed-out padding
+ * at the end. Byte swap them as if this were
+ * a "version 1" header.
+ *
+ * Yes, the first argument to END_OFFSETOF() should
+ * be phdr, not phdr_ext; we want the offset of
+ * the additional fields from the beginning of
+ * the packet.
+ */
+ if (packet_size < END_OFFSETOF(phdr, &phdr->interval))
+ return;
+ PBSWAP32((guint8 *)&phdr->interval);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->start_frame))
+ return;
+ PBSWAP32((guint8 *)&phdr->start_frame);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->xfer_flags))
+ return;
+ PBSWAP32((guint8 *)&phdr->xfer_flags);
+ if (packet_size < END_OFFSETOF(phdr, &phdr->ndesc))
+ return;
+ PBSWAP32((guint8 *)&phdr->ndesc);
+ }
+
+ if (phdr->transfer_type == URB_ISOCHRONOUS) {
+ /* swap the values in struct linux_usb_isodesc */
+
+ /*
+ * See previous "Greasy hack" comment.
+ */
+ if (header_len_64_bytes) {
+ pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 64);
+ } else {
+ pisodesc = (struct linux_usb_isodesc*)(void *)(pd + 48);
+ }
+ iso_numdesc = phdr->s.iso.numdesc;
+ for (i = 0; i < iso_numdesc; i++) {
+ /* always check if we have enough data from the
+ * beginnig of the packet (phdr)
+ */
+ if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_status))
+ return;
+ PBSWAP32((guint8 *)&pisodesc->iso_status);
+ if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_off))
+ return;
+ PBSWAP32((guint8 *)&pisodesc->iso_off);
+ if (packet_size < END_OFFSETOF(phdr, &pisodesc->iso_len))
+ return;
+ PBSWAP32((guint8 *)&pisodesc->iso_len);
+ if (packet_size < END_OFFSETOF(phdr, &pisodesc->_pad))
+ return;
+ PBSWAP32((guint8 *)&pisodesc->_pad);
+
+ pisodesc++;
+ }
+ }
+ }
}
static gboolean
pcap_read_bt_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
int bytes_read;
struct libpcap_bt_phdr phdr;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&phdr, 1,
+ bytes_read = file_read(&phdr,
sizeof (struct libpcap_bt_phdr), fh);
if (bytes_read != sizeof (struct libpcap_bt_phdr)) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
static gboolean
pcap_read_ppp_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
int bytes_read;
struct libpcap_ppp_phdr phdr;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&phdr, 1,
+ bytes_read = file_read(&phdr,
sizeof (struct libpcap_ppp_phdr), fh);
if (bytes_read != sizeof (struct libpcap_ppp_phdr)) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
static gboolean
pcap_read_erf_pseudoheader(FILE_T fh, struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+ union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
guint8 erf_hdr[sizeof(struct erf_phdr)];
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(erf_hdr, 1, sizeof(struct erf_phdr), fh);
+ bytes_read = file_read(erf_hdr, sizeof(struct erf_phdr), fh);
if (bytes_read != sizeof(struct erf_phdr)) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
*/
static gboolean
pcap_read_erf_exheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info _U_, guint * psize)
+ int *err, gchar **err_info, guint * psize)
{
int bytes_read = 0;
guint8 erf_exhdr[8];
guint64 erf_exhdr_sw;
int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
- guint8 type = pseudo_header->erf.phdr.type;
+ guint8 type;
*psize = 0;
if (pseudo_header->erf.phdr.type & 0x80){
do{
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(erf_exhdr, 1, 8, fh);
+ bytes_read = file_read(erf_exhdr, 8, fh);
if (bytes_read != 8 ) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
type = erf_exhdr[0];
- erf_exhdr_sw = pntohll((guint64*) &(erf_exhdr[0]));
+ erf_exhdr_sw = pntohll(erf_exhdr);
if (i < max)
memcpy(&pseudo_header->erf.ehdr_list[i].ehdr, &erf_exhdr_sw, sizeof(erf_exhdr_sw));
*psize += 8;
*/
static gboolean
pcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info _U_, guint * psize)
+ int *err, gchar **err_info, guint * psize)
{
guint8 erf_subhdr[sizeof(union erf_subhdr)];
int bytes_read;
case ERF_TYPE_COLOR_MC_HDLC_POS:
/* Extract the Multi Channel header to include it in the pseudo header part */
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(erf_subhdr, 1, sizeof(erf_mc_header_t), fh);
+ bytes_read = file_read(erf_subhdr, sizeof(erf_mc_header_t), fh);
if (bytes_read != sizeof(erf_mc_header_t) ) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
case ERF_TYPE_DSM_COLOR_ETH:
/* Extract the Ethernet additional header to include it in the pseudo header part */
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(erf_subhdr, 1, sizeof(erf_eth_header_t), fh);
+ bytes_read = file_read(erf_subhdr, sizeof(erf_eth_header_t), fh);
if (bytes_read != sizeof(erf_eth_header_t) ) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
static gboolean
-pcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+pcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
struct i2c_file_hdr i2c_hdr;
int bytes_read;
errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&i2c_hdr, 1, sizeof (i2c_hdr), fh);
+ bytes_read = file_read(&i2c_hdr, sizeof (i2c_hdr), fh);
if (bytes_read != sizeof (i2c_hdr)) {
- *err = file_error(fh);
+ *err = file_error(fh, err_info);
if (*err == 0)
*err = WTAP_ERR_SHORT_READ;
return FALSE;
}
int
-pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap, gboolean bytes_swapped, guint packet_size,
- gboolean check_packet_size, struct wtap_pkthdr *phdr,
+pcap_process_pseudo_header(FILE_T fh, int file_type, int wtap_encap,
+ guint packet_size, gboolean check_packet_size, struct wtap_pkthdr *phdr,
union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
{
int phdr_len = 0;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: Nokia IPSO ATM file has a %u-byte packet, too small to have even an ATM pseudo-header",
packet_size);
return -1;
}
if (!pcap_read_nokiaatm_pseudoheader(fh,
- pseudo_header, err))
+ pseudo_header, err, err_info))
return -1; /* Read error */
phdr_len = NOKIAATM_LEN;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: SunATM file has a %u-byte packet, too small to have even an ATM pseudo-header",
packet_size);
return -1;
}
if (!pcap_read_sunatm_pseudoheader(fh,
- pseudo_header, err))
+ pseudo_header, err, err_info))
return -1; /* Read error */
phdr_len = SUNATM_LEN;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: IrDA file has a %u-byte packet, too small to have even an IrDA pseudo-header",
packet_size);
return -1;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: MTP2 file has a %u-byte packet, too small to have even an MTP2 pseudo-header",
packet_size);
return -1;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: LAPD file has a %u-byte packet, too small to have even a LAPD pseudo-header",
packet_size);
return -1;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: SITA file has a %u-byte packet, too small to have even a SITA pseudo-header",
packet_size);
return -1;
phdr_len = SITA_HDR_LEN;
break;
- case WTAP_ENCAP_USB_LINUX:
- case WTAP_ENCAP_USB_LINUX_MMAPPED:
- if (check_packet_size &&
- packet_size < sizeof (struct linux_usb_phdr)) {
- /*
- * Uh-oh, the packet isn't big enough to even
- * have a pseudo-header.
- */
- *err = WTAP_ERR_BAD_RECORD;
- *err_info = g_strdup_printf("pcap: Linux USB file has a %u-byte packet, too small to have even a Linux USB pseudo-header",
- packet_size);
- return -1;
- }
- if (!pcap_read_linux_usb_pseudoheader(fh,
- pseudo_header, bytes_swapped, err))
- return -1; /* Read error */
-
- phdr_len = (int)sizeof (struct linux_usb_phdr);
- break;
-
case WTAP_ENCAP_BLUETOOTH_H4:
/* We don't have pseudoheader, so just pretend we received everything. */
pseudo_header->p2p.sent = FALSE;
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
- *err_info = g_strdup_printf("pcap: lipcap bluetooth file has a %u-byte packet, too small to have even a pseudo-header",
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcap: libpcap bluetooth file has a %u-byte packet, too small to have even a pseudo-header",
packet_size);
return -1;
}
if (!pcap_read_bt_pseudoheader(fh,
- pseudo_header, err))
+ pseudo_header, err, err_info))
return -1; /* Read error */
phdr_len = (int)sizeof (struct libpcap_bt_phdr);
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
- *err_info = g_strdup_printf("pcap: lipcap ppp file has a %u-byte packet, too small to have even a pseudo-header",
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcap: libpcap ppp file has a %u-byte packet, too small to have even a pseudo-header",
packet_size);
return -1;
}
if (!pcap_read_ppp_pseudoheader(fh,
- pseudo_header, err))
+ pseudo_header, err, err_info))
return -1; /* Read error */
phdr_len = (int)sizeof (struct libpcap_ppp_phdr);
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: ERF file has a %u-byte packet, too small to have even an ERF pseudo-header",
packet_size);
return -1;
return -1; /* Read error */
phdr_len += size;
+
+ if (check_packet_size &&
+ packet_size < (guint)phdr_len) {
+ /*
+ * Uh-oh, the packet isn't big enough for the pseudo-
+ * header.
+ */
+ *err = WTAP_ERR_BAD_FILE;
+ *err_info = g_strdup_printf("pcap: ERF file has a %u-byte packet, too small for a pseudo-header with ex- and sub-headers (%d)",
+ packet_size, phdr_len);
+ return -1;
+ }
break;
case WTAP_ENCAP_I2C:
* Uh-oh, the packet isn't big enough to even
* have a pseudo-header.
*/
- *err = WTAP_ERR_BAD_RECORD;
+ *err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("pcap: I2C file has a %u-byte packet, too small to have even a I2C pseudo-header",
packet_size);
return -1;
return phdr_len;
}
+void
+pcap_read_post_process(int file_type, int wtap_encap,
+ union wtap_pseudo_header *pseudo_header,
+ guint8 *pd, guint packet_size, gboolean bytes_swapped, int fcs_len)
+{
+ switch (wtap_encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
+ if (file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ *
+ * Guess the traffic type based on the packet
+ * contents.
+ */
+ atm_guess_traffic_type(pd, packet_size, 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, packet_size,
+ pseudo_header);
+ }
+ break;
+
+ case WTAP_ENCAP_ETHERNET:
+ pseudo_header->eth.fcs_len = fcs_len;
+ break;
+
+ case WTAP_ENCAP_USB_LINUX:
+ pcap_process_linux_usb_pseudoheader(packet_size,
+ bytes_swapped, FALSE, pd);
+ break;
+
+ case WTAP_ENCAP_USB_LINUX_MMAPPED:
+ pcap_process_linux_usb_pseudoheader(packet_size,
+ bytes_swapped, TRUE, pd);
+ break;
+
+ case WTAP_ENCAP_NETANALYZER:
+ /*
+ * Not strictly necessary, as the netANALYZER
+ * dissector calls the "Ethernet with FCS"
+ * dissector, but we might as well set it.
+ */
+ pseudo_header->eth.fcs_len = 4;
+ break;
+
+ default:
+ break;
+ }
+}
+
int
pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header)
{
hdrsize = SITA_HDR_LEN;
break;
- case WTAP_ENCAP_USB_LINUX:
- case WTAP_ENCAP_USB_LINUX_MMAPPED:
- hdrsize = (int)sizeof (struct linux_usb_phdr);
- break;
-
case WTAP_ENCAP_ERF:
hdrsize = (int)sizeof (struct erf_phdr);
- if (pseudo_header->erf.phdr.type & 0x80)
- hdrsize += 8;
switch (pseudo_header->erf.phdr.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
default:
break;
}
+
+ /*
+ * Add in the lengths of the extension headers.
+ */
+ if (pseudo_header->erf.phdr.type & 0x80) {
+ int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
+ guint8 erf_exhdr[8];
+ guint8 type;
+
+ do {
+ phtonll(erf_exhdr, pseudo_header->erf.ehdr_list[i].ehdr);
+ type = erf_exhdr[0];
+ hdrsize += 8;
+ i++;
+ } while (type & 0x80 && i < max);
+ }
break;
case WTAP_ENCAP_I2C:
struct i2c_file_hdr i2c_hdr;
struct libpcap_bt_phdr bt_hdr;
struct libpcap_ppp_phdr ppp_hdr;
- size_t nwritten;
size_t size;
switch (encap) {
}
atm_hdr[SUNATM_VPI] = (guint8)pseudo_header->atm.vpi;
phtons(&atm_hdr[SUNATM_VCI], pseudo_header->atm.vci);
- nwritten = wtap_dump_file_write(wdh, atm_hdr, sizeof(atm_hdr));
- if (nwritten != sizeof(atm_hdr)) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, atm_hdr, sizeof(atm_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(atm_hdr);
break;
phtons(&irda_hdr[IRDA_SLL_PKTTYPE_OFFSET],
pseudo_header->irda.pkttype);
phtons(&irda_hdr[IRDA_SLL_PROTOCOL_OFFSET], 0x0017);
- nwritten = wtap_dump_file_write(wdh, irda_hdr, sizeof(irda_hdr));
- if (nwritten != sizeof(irda_hdr)) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, irda_hdr, sizeof(irda_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(irda_hdr);
break;
mtp2_hdr[MTP2_ANNEX_A_USED_OFFSET] = pseudo_header->mtp2.annex_a_used;
phtons(&mtp2_hdr[MTP2_LINK_NUMBER_OFFSET],
pseudo_header->mtp2.link_number);
- nwritten = wtap_dump_file_write(wdh, mtp2_hdr, sizeof(mtp2_hdr));
- if (nwritten != sizeof(mtp2_hdr)) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, mtp2_hdr, sizeof(mtp2_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(mtp2_hdr);
break;
phtons(&lapd_hdr[LAPD_SLL_PROTOCOL_OFFSET], ETH_P_LAPD);
lapd_hdr[LAPD_SLL_ADDR_OFFSET + 0] =
pseudo_header->lapd.we_network?0x01:0x00;
- nwritten = fwrite(&lapd_hdr, 1, sizeof(lapd_hdr), wdh->fh);
- if (nwritten != sizeof(lapd_hdr)) {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, lapd_hdr, sizeof(lapd_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(lapd_hdr);
break;
* Write the SITA header.
*/
memset(&sita_hdr, 0, sizeof(sita_hdr));
- sita_hdr[SITA_FLAGS_OFFSET] = pseudo_header->sita.flags;
- sita_hdr[SITA_SIGNALS_OFFSET] = pseudo_header->sita.signals;
- sita_hdr[SITA_ERRORS1_OFFSET] = pseudo_header->sita.errors1;
- sita_hdr[SITA_ERRORS2_OFFSET] = pseudo_header->sita.errors2;
- sita_hdr[SITA_PROTO_OFFSET] = pseudo_header->sita.proto;
- nwritten = fwrite(&sita_hdr, 1, sizeof(sita_hdr), wdh->fh);
- if (nwritten != sizeof(sita_hdr)) {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ sita_hdr[SITA_FLAGS_OFFSET] = pseudo_header->sita.sita_flags;
+ sita_hdr[SITA_SIGNALS_OFFSET] = pseudo_header->sita.sita_signals;
+ sita_hdr[SITA_ERRORS1_OFFSET] = pseudo_header->sita.sita_errors1;
+ sita_hdr[SITA_ERRORS2_OFFSET] = pseudo_header->sita.sita_errors2;
+ sita_hdr[SITA_PROTO_OFFSET] = pseudo_header->sita.sita_proto;
+ if (!wtap_dump_file_write(wdh, sita_hdr, sizeof(sita_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(sita_hdr);
break;
- case WTAP_ENCAP_USB_LINUX:
- case WTAP_ENCAP_USB_LINUX_MMAPPED:
- /*
- * Write out the pseudo-header; it has the same format
- * as the Linux USB header, and that header is supposed
- * to be written in the host byte order of the machine
- * writing the file.
- */
- nwritten = fwrite(&pseudo_header->linux_usb, 1,
- sizeof(pseudo_header->linux_usb), wdh->fh);
- if (nwritten != sizeof(pseudo_header->linux_usb)) {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof(lapd_hdr);
- break;
-
case WTAP_ENCAP_ERF:
- /*
+ /*
* Write the ERF header.
*/
memset(&erf_hdr, 0, sizeof(erf_hdr));
- pletonll(&erf_hdr[0], pseudo_header->erf.phdr.ts);
+ phtolell(&erf_hdr[0], pseudo_header->erf.phdr.ts);
erf_hdr[8] = pseudo_header->erf.phdr.type;
erf_hdr[9] = pseudo_header->erf.phdr.flags;
phtons(&erf_hdr[10], pseudo_header->erf.phdr.rlen);
default:
break;
}
- nwritten = wtap_dump_file_write(wdh, erf_hdr, size);
- if (nwritten != (guint) size) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, erf_hdr, size, err))
return FALSE;
- }
wdh->bytes_dumped += size;
+
+ /*
+ * Now write out the extension headers.
+ */
+ if (pseudo_header->erf.phdr.type & 0x80) {
+ int i = 0, max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
+ guint8 erf_exhdr[8];
+ guint8 type;
+
+ do {
+ phtonll(erf_exhdr, pseudo_header->erf.ehdr_list[i].ehdr);
+ type = erf_exhdr[0];
+ if (!wtap_dump_file_write(wdh, erf_exhdr, 8, err))
+ return FALSE;
+ wdh->bytes_dumped += 8;
+ i++;
+ } while (type & 0x80 && i < max);
+ }
break;
case WTAP_ENCAP_I2C:
i2c_hdr.bus = pseudo_header->i2c.bus |
(pseudo_header->i2c.is_event ? 0x80 : 0x00);
phtonl((guint8 *)&i2c_hdr.flags, pseudo_header->i2c.flags);
- nwritten = fwrite(&i2c_hdr, 1, sizeof(i2c_hdr), wdh->fh);
- if (nwritten != sizeof(i2c_hdr)) {
- if (nwritten == 0 && ferror(wdh->fh))
- *err = errno;
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, &i2c_hdr, sizeof(i2c_hdr), err))
return FALSE;
- }
wdh->bytes_dumped += sizeof(i2c_hdr);
break;
case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
bt_hdr.direction = GUINT32_TO_BE(pseudo_header->p2p.sent ? LIBPCAP_BT_PHDR_SENT : LIBPCAP_BT_PHDR_RECV);
- nwritten = wtap_dump_file_write(wdh, &bt_hdr, sizeof bt_hdr);
- if (nwritten != sizeof bt_hdr) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, &bt_hdr, sizeof bt_hdr, err))
return FALSE;
- }
wdh->bytes_dumped += sizeof bt_hdr;
break;
case WTAP_ENCAP_PPP_WITH_PHDR:
ppp_hdr.direction = (pseudo_header->p2p.sent ? LIBPCAP_PPP_PHDR_SENT : LIBPCAP_PPP_PHDR_RECV);
- nwritten = wtap_dump_file_write(wdh, &ppp_hdr, sizeof ppp_hdr);
- if (nwritten != sizeof ppp_hdr) {
- if (nwritten == 0 && wtap_dump_file_ferror(wdh))
- *err = wtap_dump_file_ferror(wdh);
- else
- *err = WTAP_ERR_SHORT_WRITE;
+ if (!wtap_dump_file_write(wdh, &ppp_hdr, sizeof ppp_hdr, err))
return FALSE;
- }
wdh->bytes_dumped += sizeof ppp_hdr;
break;
}