aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorGuy Harris <guy@alum.mit.edu>2009-04-27 19:39:06 +0000
committerGuy Harris <guy@alum.mit.edu>2009-04-27 19:39:06 +0000
commita60cae69353514af4c23f3a5dfcb480bf19da69f (patch)
tree20f85d8a286e1a149c9d7634d7cbb214d9f3b0b8 /wiretap
parentc1e9d8244b998a77c5074312459cc1736aab7f15 (diff)
Move pseudo-header routines from libpcap.c to pcap-common.c, for use
with pcap-NG files. svn path=/trunk/; revision=28184
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/libpcap.c1348
-rw-r--r--wiretap/pcap-common.c1056
-rw-r--r--wiretap/pcap-common.h10
3 files changed, 1089 insertions, 1325 deletions
diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c
index d4343ab06f..9668fd104f 100644
--- a/wiretap/libpcap.c
+++ b/wiretap/libpcap.c
@@ -31,83 +31,9 @@
#include "file_wrappers.h"
#include "buffer.h"
#include "atm.h"
-#include "erf.h"
#include "pcap-common.h"
#include "libpcap.h"
-/*
- * Various pseudo-headers that appear at the beginning of packet data.
- *
- * We represent them as sets of offsets, as they might not be aligned on
- * an appropriate structure boundary in the buffer, and as that makes them
- * independent of the way the compiler might align fields.
- */
-
-/*
- * The link-layer header on SunATM packets.
- */
-#define SUNATM_FLAGS 0 /* destination and traffic type - 1 byte */
-#define SUNATM_VPI 1 /* VPI - 1 byte */
-#define SUNATM_VCI 2 /* VCI - 2 bytes */
-#define SUNATM_LEN 4 /* length of the header */
-
-/*
- * The link-layer header on Nokia IPSO ATM packets.
- */
-#define NOKIAATM_FLAGS 0 /* destination - 1 byte */
-#define NOKIAATM_VPI 1 /* VPI - 1 byte */
-#define NOKIAATM_VCI 2 /* VCI - 2 bytes */
-#define NOKIAATM_LEN 4 /* length of the header */
-
-/*
- * The fake link-layer header of IrDA packets as introduced by Jean Tourrilhes
- * to libpcap.
- */
-#define IRDA_SLL_PKTTYPE_OFFSET 0 /* packet type - 2 bytes */
-/* 12 unused bytes */
-#define IRDA_SLL_PROTOCOL_OFFSET 14 /* protocol, should be ETH_P_LAPD - 2 bytes */
-#define IRDA_SLL_LEN 16 /* length of the header */
-
-/*
- * A header containing additional MTP information.
- */
-#define MTP2_SENT_OFFSET 0 /* 1 byte */
-#define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */
-#define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */
-#define MTP2_HDR_LEN 4 /* length of the header */
-
-/*
- * A header containing additional SITA WAN information.
- */
-#define SITA_FLAGS_OFFSET 0 /* 1 byte */
-#define SITA_SIGNALS_OFFSET 1 /* 1 byte */
-#define SITA_ERRORS1_OFFSET 2 /* 1 byte */
-#define SITA_ERRORS2_OFFSET 3 /* 1 byte */
-#define SITA_PROTO_OFFSET 4 /* 1 byte */
-#define SITA_HDR_LEN 5 /* length of the header */
-
-/*
- * The fake link-layer header of LAPD packets.
- */
-#ifndef ETH_P_LAPD
-#define ETH_P_LAPD 0x0030
-#endif
-
-#define LAPD_SLL_PKTTYPE_OFFSET 0 /* packet type - 2 bytes */
-#define LAPD_SLL_HATYPE_OFFSET 2 /* hardware address type - 2 bytes */
-#define LAPD_SLL_HALEN_OFFSET 4 /* hardware address length - 2 bytes */
-#define LAPD_SLL_ADDR_OFFSET 6 /* address - 8 bytes */
-#define LAPD_SLL_PROTOCOL_OFFSET 14 /* protocol, should be ETH_P_LAPD - 2 bytes */
-#define LAPD_SLL_LEN 16 /* length of the header */
-
-/*
- * I2C link-layer on-disk format
- */
-struct i2c_file_hdr {
- guint8 bus;
- guint8 flags[4];
-};
-
/* See source to the "libpcap" library for information on the "libpcap"
file format. */
@@ -132,46 +58,6 @@ static gboolean libpcap_seek_read(wtap *wth, gint64 seek_off,
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_sunatm_pseudoheader(const guint8 *atm_phdr,
- union wtap_pseudo_header *pseudo_header);
-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 guint8 *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_get_mtp2_pseudoheader(const guint8 *mtp2_hdr,
- union wtap_pseudo_header *pseudo_header);
-static gboolean libpcap_read_mtp2_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static gboolean libpcap_get_sita_pseudoheader(const guint8 *sita_phdr,
- union wtap_pseudo_header *pseudo_header);
-static gboolean libpcap_read_sita_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static gboolean libpcap_get_lapd_pseudoheader(const guint8 *lapd_phdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static gboolean libpcap_read_lapd_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static gboolean libpcap_read_linux_usb_pseudoheader(wtap *wth, FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err);
-static gboolean libpcap_read_bt_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err);
-static gboolean libpcap_get_erf_pseudoheader(const guint8 *erf_hdr, struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header);
-static gboolean libpcap_read_erf_pseudoheader(FILE_T fh, struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info);
-static gboolean libpcap_get_erf_subheader(const guint8 *erf_subhdr,
- union wtap_pseudo_header *pseudo_header, guint * size);
-static gboolean libpcap_read_erf_subheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_, guint * size);
-static gboolean libpcap_read_erf_exheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_, guint * size);
-static gboolean libpcap_get_i2c_pseudoheader(const struct i2c_file_hdr *i2c_hdr,
- union wtap_pseudo_header *pseudo_header);
-static gboolean libpcap_read_i2c_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);
@@ -709,9 +595,10 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
{
struct pcaprec_ss990915_hdr hdr;
guint packet_size;
- guint orig_size, size;
+ guint orig_size;
int bytes_read;
guchar fddi_padding[3];
+ int phdr_len;
bytes_read = libpcap_read_header(wth, err, err_info, &hdr);
if (bytes_read == -1) {
@@ -749,303 +636,17 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
*data_offset = wth->data_offset;
+ phdr_len = pcap_process_pseudo_header(wth, wth->fh, packet_size,
+ &wth->phdr, &wth->pseudo_header, err, err_info);
+ if (phdr_len < 0)
+ return FALSE; /* error */
+
/*
- * If this is an ATM packet, the first four bytes are the
- * direction of the packet (transmit/receive), the VPI, and
- * the VCI; read them and generate the pseudo-header from
- * them.
+ * Don't count any pseudo-header as part of the packet.
*/
- switch (wth->file_encap) {
-
- case WTAP_ENCAP_ATM_PDUS:
- if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
- /*
- * Nokia IPSO ATM.
- */
- if (packet_size < NOKIAATM_LEN) {
- /*
- * 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 -= NOKIAATM_LEN;
- packet_size -= NOKIAATM_LEN;
- wth->data_offset += NOKIAATM_LEN;
- } else {
- /*
- * SunATM.
- */
- if (packet_size < SUNATM_LEN) {
- /*
- * 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 -= SUNATM_LEN;
- packet_size -= SUNATM_LEN;
- wth->data_offset += SUNATM_LEN;
- }
- 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_RADIOTAP:
- 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;
- wth->pseudo_header.ieee_802_11.channel = 0;
- wth->pseudo_header.ieee_802_11.data_rate = 0;
- wth->pseudo_header.ieee_802_11.signal_level = 0;
- break;
-
- case WTAP_ENCAP_IRDA:
- if (packet_size < IRDA_SLL_LEN) {
- /*
- * 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: IrDA file has a %u-byte packet, too small to have even an IrDA pseudo-header\n",
- packet_size);
- return FALSE;
- }
- 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 -= IRDA_SLL_LEN;
- packet_size -= IRDA_SLL_LEN;
- wth->data_offset += IRDA_SLL_LEN;
- break;
-
- case WTAP_ENCAP_MTP2_WITH_PHDR:
- if (packet_size < MTP2_HDR_LEN) {
- /*
- * 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: MTP2 file has a %u-byte packet, too small to have even an MTP2 pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_mtp2_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 -= MTP2_HDR_LEN;
- packet_size -= MTP2_HDR_LEN;
- wth->data_offset += MTP2_HDR_LEN;
- break;
-
- case WTAP_ENCAP_LINUX_LAPD:
- if (packet_size < LAPD_SLL_LEN) {
- /*
- * 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: LAPD file has a %u-byte packet, too small to have even a LAPD pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_lapd_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 -= LAPD_SLL_LEN;
- packet_size -= LAPD_SLL_LEN;
- wth->data_offset += LAPD_SLL_LEN;
- break;
-
- case WTAP_ENCAP_SITA:
- if (packet_size < SITA_HDR_LEN) {
- /*
- * 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: SITA file has a %u-byte packet, too small to have even a SITA pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_sita_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 -= SITA_HDR_LEN;
- packet_size -= SITA_HDR_LEN;
- wth->data_offset += SITA_HDR_LEN;
- break;
-
- case WTAP_ENCAP_USB_LINUX:
- case WTAP_ENCAP_USB_LINUX_MMAPPED:
- if (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("libpcap: Linux USB file has a %u-byte packet, too small to have even a Linux USB pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_linux_usb_pseudoheader(wth, wth->fh,
- &wth->pseudo_header, err))
- return FALSE; /* Read error */
-
- /*
- * Don't count the pseudo-header as part of the packet.
- */
- orig_size -= (guint)sizeof (struct linux_usb_phdr);
- packet_size -= (guint)sizeof (struct linux_usb_phdr);
- wth->data_offset += sizeof (struct linux_usb_phdr);
- break;
-
- case WTAP_ENCAP_BLUETOOTH_H4:
- /* We don't have pseudoheader, so just pretend we received everything. */
- wth->pseudo_header.p2p.sent = FALSE;
- break;
-
- case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
- if (packet_size < 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("libpcap: lipcap bluetooth file has a %u-byte packet, too small to have even a pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_bt_pseudoheader(wth->fh,
- &wth->pseudo_header, err))
- return FALSE; /* Read error */
-
- /*
- * Don't count the pseudo-header as part of the packet.
- */
- orig_size -= (guint)sizeof (struct libpcap_bt_phdr);
- packet_size -= (guint)sizeof (struct libpcap_bt_phdr);
- wth->data_offset += sizeof (struct libpcap_bt_phdr);
- break;
-
- case WTAP_ENCAP_ERF:
- if (packet_size < sizeof(struct erf_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("libpcap: ERF file has a %u-byte packet, too small to have even an ERF pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_erf_pseudoheader(wth->fh, &wth->phdr, &wth->pseudo_header,
- err, err_info))
- return FALSE; /* Read error */
-
- /*
- * Don't count the pseudo-header as part of the packet.
- */
- orig_size -= (guint)sizeof(struct erf_phdr);
- packet_size -= (guint)sizeof(struct erf_phdr);
- wth->data_offset += sizeof(struct erf_phdr);
-
- if (!libpcap_read_erf_exheader(wth->fh, &wth->pseudo_header,
- err, err_info, &size))
- return FALSE; /* Read error */
-
- /* Do not count also the extension headers as part of the packet */
- orig_size -= size;
- packet_size -= size;
- wth->data_offset += size;
-
- if (!libpcap_read_erf_subheader(wth->fh, &wth->pseudo_header,
- err, err_info, &size)){
- return FALSE; /* Read error */
- }
-
- /*
- * Don't count the optional mc-header as part of the packet.
- */
- orig_size -= size;
- packet_size -= size;
- wth->data_offset += size;
-
- break;
-
- case WTAP_ENCAP_I2C:
- if (packet_size < sizeof (struct i2c_file_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: I2C file has a %u-byte packet, too small to have even a I2C pseudo-header\n",
- packet_size);
- return FALSE;
- }
- if (!libpcap_read_i2c_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 -= (guint)sizeof (struct i2c_file_hdr);
- packet_size -= (guint)sizeof (struct i2c_file_hdr);
- wth->data_offset += sizeof (struct i2c_file_hdr);
- break;
-
- }
+ orig_size -= phdr_len;
+ packet_size -= phdr_len;
+ wth->data_offset += phdr_len;
buffer_assure_space(wth->frame_buffer, packet_size);
if (!libpcap_read_rec_data(wth->fh, buffer_start_ptr(wth->frame_buffer),
@@ -1098,133 +699,15 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
union wtap_pseudo_header *pseudo_header, guchar *pd, int length,
int *err, gchar **err_info)
{
- guint size;
+ int phdr_len;
+
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
- switch (wth->file_encap) {
-
- case WTAP_ENCAP_ATM_PDUS:
- 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;
-
- 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;
-
- case WTAP_ENCAP_IEEE_802_11:
- case WTAP_ENCAP_PRISM_HEADER:
- case WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP:
- 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;
-
- case WTAP_ENCAP_MTP2_WITH_PHDR:
- if (!libpcap_read_mtp2_pseudoheader(wth->random_fh, pseudo_header,
- err, err_info)) {
- /* Read error */
- return FALSE;
- }
- break;
-
- case WTAP_ENCAP_LINUX_LAPD:
- if (!libpcap_read_lapd_pseudoheader(wth->random_fh, pseudo_header,
- err, err_info)) {
- /* Read error */
- return FALSE;
- }
- break;
-
- case WTAP_ENCAP_SITA:
- if (!libpcap_read_sita_pseudoheader(wth->random_fh, pseudo_header,
- err, err_info)) {
- /* Read error */
- return FALSE;
- }
- break;
-
- case WTAP_ENCAP_USB_LINUX:
- case WTAP_ENCAP_USB_LINUX_MMAPPED:
- if (!libpcap_read_linux_usb_pseudoheader(wth, wth->random_fh,
- pseudo_header, err))
- return FALSE; /* Read error */
- break;
-
- case WTAP_ENCAP_BLUETOOTH_H4:
- /* We don't have pseudoheader, so just pretend we received everything. */
- wth->pseudo_header.p2p.sent = FALSE;
- break;
-
- case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
- if (!libpcap_read_bt_pseudoheader(wth->random_fh,
- pseudo_header, err))
- return FALSE; /* Read error */
- break;
-
- case WTAP_ENCAP_ERF:
- if (!libpcap_read_erf_pseudoheader(wth->random_fh, NULL, pseudo_header,
- err, err_info)) {
- return FALSE;
- }
-
- /* check the optional Extension header */
- if (!libpcap_read_erf_exheader(wth->random_fh, pseudo_header,
- err, err_info, &size)){
-
- /* Read error */
- return FALSE;
- }
-
- /* check the optional Multi Channel header */
- if (!libpcap_read_erf_subheader(wth->random_fh, pseudo_header,
- err, err_info, &size)) {
- /* Read error */
- return FALSE;
- }
- break;
-
- case WTAP_ENCAP_I2C:
- if (!libpcap_read_i2c_pseudoheader(wth->random_fh, pseudo_header,
- err, err_info)) {
- /* Read error */
- return FALSE;
- }
- break;
- }
+ phdr_len = pcap_process_pseudo_header(wth, wth->random_fh, length,
+ NULL, pseudo_header, err, err_info);
+ if (phdr_len < 0)
+ return FALSE; /* error */
/*
* Read the packet data.
@@ -1376,515 +859,6 @@ adjust_header(wtap *wth, struct pcaprec_hdr *hdr)
}
}
-static void
-libpcap_get_sunatm_pseudoheader(const guint8 *atm_phdr,
- union wtap_pseudo_header *pseudo_header)
-{
- guint8 vpi;
- guint16 vci;
-
- vpi = atm_phdr[SUNATM_VPI];
- vci = pntohs(&atm_phdr[SUNATM_VCI]);
-
- switch (atm_phdr[SUNATM_FLAGS] & 0x0F) {
-
- case 0x01: /* LANE */
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_LANE;
- break;
-
- case 0x02: /* RFC 1483 LLC multiplexed traffic */
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_LLCMX;
- break;
-
- case 0x05: /* ILMI */
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_ILMI;
- break;
-
- case 0x06: /* Q.2931 */
- pseudo_header->atm.aal = AAL_SIGNALLING;
- pseudo_header->atm.type = TRAF_UNKNOWN;
- break;
-
- case 0x03: /* MARS (RFC 2022) */
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_UNKNOWN;
- break;
-
- case 0x04: /* IFMP (Ipsilon Flow Management Protocol; see RFC 1954) */
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_UNKNOWN; /* XXX - TRAF_IPSILON? */
- break;
-
- default:
- /*
- * Assume it's AAL5, unless it's VPI 0 and VCI 5, in which
- * case assume it's AAL_SIGNALLING; we know nothing more
- * about it.
- *
- * XXX - is this necessary? Or are we guaranteed that
- * all signalling traffic has a type of 0x06?
- *
- * XXX - is this guaranteed to be AAL5? Or, if the type is
- * 0x00 ("raw"), might it be non-AAL5 traffic?
- */
- if (vpi == 0 && vci == 5)
- pseudo_header->atm.aal = AAL_SIGNALLING;
- else
- pseudo_header->atm.aal = AAL_5;
- pseudo_header->atm.type = TRAF_UNKNOWN;
- break;
- }
- pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
-
- pseudo_header->atm.vpi = vpi;
- pseudo_header->atm.vci = vci;
- pseudo_header->atm.channel = (atm_phdr[SUNATM_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;
-}
-
-static gboolean
-libpcap_read_sunatm_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
-{
- guint8 atm_phdr[SUNATM_LEN];
- int bytes_read;
-
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(atm_phdr, 1, SUNATM_LEN, fh);
- if (bytes_read != SUNATM_LEN) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- 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)
-{
- guint8 atm_phdr[NOKIAATM_LEN];
- int bytes_read;
- guint8 vpi;
- guint16 vci;
-
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(atm_phdr, 1, NOKIAATM_LEN, fh);
- if (bytes_read != NOKIAATM_LEN) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- vpi = atm_phdr[NOKIAATM_VPI];
- vci = pntohs(&atm_phdr[NOKIAATM_VCI]);
-
- pseudo_header->atm.vpi = vpi;
- pseudo_header->atm.vci = vci;
- pseudo_header->atm.channel = (atm_phdr[NOKIAATM_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 guint8 *irda_phdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
-{
- if (pntohs(&irda_phdr[IRDA_SLL_PROTOCOL_OFFSET]) != 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[IRDA_SLL_PKTTYPE_OFFSET]);
-
- return TRUE;
-}
-
-static gboolean
-libpcap_read_irda_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info)
-{
- guint8 irda_phdr[IRDA_SLL_LEN];
- int bytes_read;
-
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(irda_phdr, 1, IRDA_SLL_LEN, fh);
- if (bytes_read != IRDA_SLL_LEN) {
- *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_get_mtp2_pseudoheader(const guint8 *mtp2_hdr, union wtap_pseudo_header *pseudo_header)
-{
- pseudo_header->mtp2.sent = mtp2_hdr[MTP2_SENT_OFFSET];
- pseudo_header->mtp2.annex_a_used = mtp2_hdr[MTP2_ANNEX_A_USED_OFFSET];
- pseudo_header->mtp2.link_number = pntohs(&mtp2_hdr[MTP2_LINK_NUMBER_OFFSET]);
-
- return TRUE;
-}
-
-static gboolean
-libpcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
-{
- 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);
- if (bytes_read != MTP2_HDR_LEN) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- return libpcap_get_mtp2_pseudoheader(mtp2_hdr, pseudo_header);
-
-}
-
-static gboolean
-libpcap_get_lapd_pseudoheader(const guint8 *lapd_phdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info)
-{
- if (pntohs(&lapd_phdr[LAPD_SLL_PROTOCOL_OFFSET]) != ETH_P_LAPD) {
- *err = WTAP_ERR_BAD_RECORD;
- if (err_info != NULL)
- *err_info = g_strdup("libpcap: LAPD capture has a packet with an invalid sll_protocol field\n");
- return FALSE;
- }
-
- pseudo_header->lapd.pkttype = pntohs(&lapd_phdr[LAPD_SLL_PKTTYPE_OFFSET]);
- pseudo_header->lapd.we_network = !!lapd_phdr[LAPD_SLL_ADDR_OFFSET+0];
-
- return TRUE;
-}
-
-static gboolean
-libpcap_read_lapd_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info)
-{
- guint8 lapd_phdr[LAPD_SLL_LEN];
- int bytes_read;
-
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(lapd_phdr, 1, LAPD_SLL_LEN, fh);
- if (bytes_read != LAPD_SLL_LEN) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- return libpcap_get_lapd_pseudoheader(lapd_phdr, pseudo_header, err,
- err_info);
-}
-
-static gboolean
-libpcap_get_sita_pseudoheader(const guint8 *sita_phdr,
- union wtap_pseudo_header *pseudo_header)
-{
- 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];
- return TRUE;
-}
-
-static gboolean
-libpcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
-{
- 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);
- if (bytes_read != SITA_HDR_LEN) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- return libpcap_get_sita_pseudoheader(sita_phdr, pseudo_header);
-}
-
-static void
-libpcap_swap_linux_usb_pseudoheader(struct linux_usb_phdr *phdr)
-{
- phdr->id = GUINT64_SWAP_LE_BE(phdr->id);
- phdr->bus_id = GUINT16_SWAP_LE_BE(phdr->bus_id);
- phdr->ts_sec = GUINT64_SWAP_LE_BE(phdr->ts_sec);
- phdr->ts_usec = GUINT32_SWAP_LE_BE(phdr->ts_usec);
- phdr->status = GUINT32_SWAP_LE_BE(phdr->status);
- phdr->urb_len = GUINT32_SWAP_LE_BE(phdr->urb_len);
- phdr->data_len = GUINT32_SWAP_LE_BE(phdr->data_len);
-}
-
-static gboolean
-libpcap_read_linux_usb_pseudoheader(wtap *wth, FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
-{
- int bytes_read;
-
- 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;
- }
- if (wth->capture.pcap->byte_swapped)
- libpcap_swap_linux_usb_pseudoheader(&pseudo_header->linux_usb);
- return TRUE;
-}
-
-static gboolean
-libpcap_read_bt_pseudoheader(FILE_T fh,
- union wtap_pseudo_header *pseudo_header, int *err)
-{
- int bytes_read;
- struct libpcap_bt_phdr phdr;
-
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(&phdr, 1,
- sizeof (struct libpcap_bt_phdr), fh);
- if (bytes_read != sizeof (struct libpcap_bt_phdr)) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- pseudo_header->p2p.sent = ((g_ntohl(phdr.direction) & 0x1) == 0)? TRUE: FALSE;
- return TRUE;
-}
-
-
-static gboolean
-libpcap_get_erf_pseudoheader(const guint8 *erf_hdr, struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header)
-{
- pseudo_header->erf.phdr.ts = pletohll(&erf_hdr[0]); /* timestamp */
- pseudo_header->erf.phdr.type = erf_hdr[8];
- pseudo_header->erf.phdr.flags = erf_hdr[9];
- pseudo_header->erf.phdr.rlen = pntohs(&erf_hdr[10]);
- pseudo_header->erf.phdr.lctr = pntohs(&erf_hdr[12]);
- pseudo_header->erf.phdr.wlen = pntohs(&erf_hdr[14]);
-
- /* The high 32 bits of the timestamp contain the integer number of seconds
- * while the lower 32 bits contain the binary fraction of the second.
- * This allows an ultimate resolution of 1/(2^32) seconds, or approximately 233 picoseconds */
- if (whdr) {
- guint64 ts = pseudo_header->erf.phdr.ts;
- whdr->ts.secs = (guint32) (ts >> 32);
- ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000);
- ts += (ts & 0x80000000) << 1; /* rounding */
- whdr->ts.nsecs = ((guint32) (ts >> 32));
- if ( whdr->ts.nsecs >= 1000000000) {
- whdr->ts.nsecs -= 1000000000;
- whdr->ts.secs += 1;
- }
- }
- return TRUE;
-}
-
-static gboolean
-libpcap_read_erf_pseudoheader(FILE_T fh, struct wtap_pkthdr *whdr,
- union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
-{
- 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);
- if (bytes_read != sizeof(struct erf_phdr)) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- return libpcap_get_erf_pseudoheader(erf_hdr, whdr, pseudo_header);
-}
-
-static gboolean
-libpcap_get_erf_subheader(const guint8 *erf_subhdr,
- union wtap_pseudo_header *pseudo_header, guint * psize)
-{
- *psize=0;
- switch(pseudo_header->erf.phdr.type & 0x7F) {
- case ERF_TYPE_MC_HDLC:
- case ERF_TYPE_MC_RAW:
- case ERF_TYPE_MC_ATM:
- case ERF_TYPE_MC_RAW_CHANNEL:
- case ERF_TYPE_MC_AAL5:
- case ERF_TYPE_MC_AAL2:
- case ERF_TYPE_COLOR_MC_HDLC_POS:
- /* Extract the Multi Channel header to include it in the pseudo header part */
- pseudo_header->erf.subhdr.mc_hdr = pntohl(&erf_subhdr[0]);
- *psize = sizeof(erf_mc_header_t);
- break;
- case ERF_TYPE_ETH:
- case ERF_TYPE_COLOR_ETH:
- case ERF_TYPE_DSM_COLOR_ETH:
- /* Extract the Ethernet additional header to include it in the pseudo header part */
- pseudo_header->erf.subhdr.eth_hdr = pntohs(&erf_subhdr[0]);
- *psize = sizeof(erf_eth_header_t);
- break;
- default:
- /* No optional pseudo header for this ERF type */
- break;
- }
- return TRUE;
-}
-
-/*
- * If the type of record given in the pseudo header indicate the presence of an extension
- * header then, read all the extension headers
- */
-static gboolean
-libpcap_read_erf_exheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info _U_, 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;
- *psize = 0;
- if (pseudo_header->erf.phdr.type & 0x80){
- do{
- errno = WTAP_ERR_CANT_READ;
- bytes_read = file_read(erf_exhdr, 1, 8, fh);
- if (bytes_read != 8 ) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- type = erf_exhdr[0];
- erf_exhdr_sw = pntohll((guint64*) &(erf_exhdr[0]));
- if (i < max)
- memcpy(&pseudo_header->erf.ehdr_list[i].ehdr, &erf_exhdr_sw, sizeof(erf_exhdr_sw));
- *psize += 8;
- i++;
- } while (type & 0x80);
- }
- return TRUE;
-}
-
-/*
- * If the type of record given in the pseudo header indicate the precense of a subheader
- * then, read this optional subheader
- */
-static gboolean
-libpcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
- int *err, gchar **err_info _U_, guint * psize)
-{
- guint8 erf_subhdr[sizeof(union erf_subhdr)];
- int bytes_read;
-
- *psize=0;
- switch(pseudo_header->erf.phdr.type & 0x7F) {
- case ERF_TYPE_MC_HDLC:
- case ERF_TYPE_MC_RAW:
- case ERF_TYPE_MC_ATM:
- case ERF_TYPE_MC_RAW_CHANNEL:
- case ERF_TYPE_MC_AAL5:
- case ERF_TYPE_MC_AAL2:
- 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);
- if (bytes_read != sizeof(erf_mc_header_t) ) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- *psize = sizeof(erf_mc_header_t);
- break;
- case ERF_TYPE_ETH:
- case ERF_TYPE_COLOR_ETH:
- 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);
- if (bytes_read != sizeof(erf_eth_header_t) ) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
- *psize = sizeof(erf_eth_header_t);
- break;
- default:
- /* No optional pseudo header for this ERF type */
- break;
- }
- return libpcap_get_erf_subheader(erf_subhdr, pseudo_header, psize);
-}
-
-static gboolean
-libpcap_get_i2c_pseudoheader(const struct i2c_file_hdr *i2c_hdr, union wtap_pseudo_header *pseudo_header)
-{
- pseudo_header->i2c.is_event = i2c_hdr->bus & 0x80 ? 1 : 0;
- pseudo_header->i2c.bus = i2c_hdr->bus & 0x7f;
- pseudo_header->i2c.flags = pntohl(&i2c_hdr->flags);
-
- return TRUE;
-}
-
-static gboolean
-libpcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
-{
- 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);
- if (bytes_read != sizeof (i2c_hdr)) {
- *err = file_error(fh);
- if (*err == 0)
- *err = WTAP_ERR_SHORT_READ;
- return FALSE;
- }
-
- return libpcap_get_i2c_pseudoheader(&i2c_hdr, pseudo_header);
-
-}
-
static gboolean
libpcap_read_rec_data(FILE_T fh, guchar *pd, int length, int *err)
{
@@ -2008,79 +982,15 @@ gboolean libpcap_dump_open(wtap_dumper *wdh, gboolean cant_seek _U_, int *err)
Returns TRUE on success, FALSE on failure. */
static gboolean libpcap_dump(wtap_dumper *wdh,
const struct wtap_pkthdr *phdr,
- const union wtap_pseudo_header *pseudo_header _U_,
+ const union wtap_pseudo_header *pseudo_header,
const guchar *pd, int *err)
{
struct pcaprec_ss990915_hdr rec_hdr;
size_t hdr_size;
size_t nwritten;
- guint8 atm_hdr[SUNATM_LEN];
- guint8 irda_hdr[IRDA_SLL_LEN];
- guint8 lapd_hdr[LAPD_SLL_LEN];
- guint8 mtp2_hdr[MTP2_HDR_LEN];
- guint8 sita_hdr[SITA_HDR_LEN];
- guint8 erf_hdr[ sizeof(struct erf_mc_phdr)];
- struct i2c_file_hdr i2c_hdr;
- int hdrsize, size;
-
- switch (wdh->encap) {
-
- case WTAP_ENCAP_ATM_PDUS:
- hdrsize = SUNATM_LEN;
- break;
-
- case WTAP_ENCAP_IRDA:
- hdrsize = IRDA_SLL_LEN;
- break;
-
- case WTAP_ENCAP_MTP2_WITH_PHDR:
- hdrsize = MTP2_HDR_LEN;
- break;
-
- case WTAP_ENCAP_LINUX_LAPD:
- hdrsize = LAPD_SLL_LEN;
- break;
-
- case WTAP_ENCAP_SITA:
- 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:
- case ERF_TYPE_MC_RAW:
- case ERF_TYPE_MC_ATM:
- case ERF_TYPE_MC_RAW_CHANNEL:
- case ERF_TYPE_MC_AAL5:
- case ERF_TYPE_MC_AAL2:
- case ERF_TYPE_COLOR_MC_HDLC_POS:
- hdrsize += (int)sizeof(struct erf_mc_hdr);
- break;
- case ERF_TYPE_ETH:
- case ERF_TYPE_COLOR_ETH:
- case ERF_TYPE_DSM_COLOR_ETH:
- hdrsize += (int)sizeof(struct erf_eth_hdr);
- break;
- default:
- break;
- }
- break;
-
- case WTAP_ENCAP_I2C:
- hdrsize = (int)sizeof (struct i2c_file_hdr);
- break;
+ int phdrsize;
- default:
- hdrsize = 0;
- break;
- }
+ phdrsize = pcap_get_phdr_size(wdh->encap, pseudo_header);
rec_hdr.hdr.ts_sec = (guint32) phdr->ts.secs;
if(wdh->tsprecision == WTAP_FILE_TSPREC_NSEC) {
@@ -2088,8 +998,8 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
} else {
rec_hdr.hdr.ts_usec = phdr->ts.nsecs / 1000;
}
- rec_hdr.hdr.incl_len = phdr->caplen + hdrsize;
- rec_hdr.hdr.orig_len = phdr->len + hdrsize;
+ rec_hdr.hdr.incl_len = phdr->caplen + phdrsize;
+ rec_hdr.hdr.orig_len = phdr->len + phdrsize;
switch (wdh->file_type) {
case WTAP_FILE_PCAP:
@@ -2160,218 +1070,8 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
}
wdh->bytes_dumped += hdr_size;
- switch (wdh->encap) {
-
- case WTAP_ENCAP_ATM_PDUS:
- /*
- * Write the ATM header.
- */
- atm_hdr[SUNATM_FLAGS] =
- (pseudo_header->atm.channel == 0) ? 0x80 : 0x00;
- switch (pseudo_header->atm.aal) {
-
- case AAL_SIGNALLING:
- /* Q.2931 */
- atm_hdr[SUNATM_FLAGS] |= 0x06;
- break;
-
- case AAL_5:
- switch (pseudo_header->atm.type) {
-
- case TRAF_LANE:
- /* LANE */
- atm_hdr[SUNATM_FLAGS] |= 0x01;
- break;
-
- case TRAF_LLCMX:
- /* RFC 1483 LLC multiplexed traffic */
- atm_hdr[SUNATM_FLAGS] |= 0x02;
- break;
-
- case TRAF_ILMI:
- /* ILMI */
- atm_hdr[SUNATM_FLAGS] |= 0x05;
- break;
- }
- break;
- }
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof atm_hdr;
- break;
-
- case WTAP_ENCAP_IRDA:
- /*
- * Write the IrDA header.
- */
- memset(irda_hdr, 0, sizeof(irda_hdr));
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof(irda_hdr);
- break;
-
- case WTAP_ENCAP_MTP2_WITH_PHDR:
- /*
- * Write the MTP2 header.
- */
- memset(&mtp2_hdr, 0, sizeof(mtp2_hdr));
- mtp2_hdr[MTP2_SENT_OFFSET] = pseudo_header->mtp2.sent;
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof(mtp2_hdr);
- break;
-
- case WTAP_ENCAP_LINUX_LAPD:
- /*
- * Write the LAPD header.
- */
- memset(&lapd_hdr, 0, sizeof(lapd_hdr));
- phtons(&lapd_hdr[LAPD_SLL_PKTTYPE_OFFSET],
- pseudo_header->lapd.pkttype);
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof(lapd_hdr);
- break;
-
- case WTAP_ENCAP_SITA:
- /*
- * 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;
- 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);
- 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);
- phtons(&erf_hdr[12], pseudo_header->erf.phdr.lctr);
- phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
- size = sizeof(struct erf_phdr);
-
- switch(pseudo_header->erf.phdr.type & 0x7F) {
- case ERF_TYPE_MC_HDLC:
- case ERF_TYPE_MC_RAW:
- case ERF_TYPE_MC_ATM:
- case ERF_TYPE_MC_RAW_CHANNEL:
- case ERF_TYPE_MC_AAL5:
- case ERF_TYPE_MC_AAL2:
- case ERF_TYPE_COLOR_MC_HDLC_POS:
- phtonl(&erf_hdr[16], pseudo_header->erf.subhdr.mc_hdr);
- size += (int)sizeof(struct erf_mc_hdr);
- break;
- case ERF_TYPE_ETH:
- case ERF_TYPE_COLOR_ETH:
- case ERF_TYPE_DSM_COLOR_ETH:
- phtons(&erf_hdr[16], pseudo_header->erf.subhdr.eth_hdr);
- size += (int)sizeof(struct erf_eth_hdr);
- break;
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += size;
- break;
-
- case WTAP_ENCAP_I2C:
- /*
- * Write the I2C header.
- */
- memset(&i2c_hdr, 0, sizeof(i2c_hdr));
- 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;
- return FALSE;
- }
- wdh->bytes_dumped += sizeof(i2c_hdr);
- break;
- }
+ if (!pcap_write_phdr(wdh, pseudo_header, err))
+ return FALSE;
nwritten = wtap_dump_file_write(wdh, pd, phdr->caplen);
if (nwritten != phdr->caplen) {
diff --git a/wiretap/pcap-common.c b/wiretap/pcap-common.c
index ed145ebc1d..ee571701cf 100644
--- a/wiretap/pcap-common.c
+++ b/wiretap/pcap-common.c
@@ -24,7 +24,16 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-#include "wtap.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "wtap-int.h"
+#include "file_wrappers.h"
+#include "erf.h"
#include "pcap-common.h"
/*
@@ -613,3 +622,1048 @@ wtap_wtap_encap_to_pcap_encap(int encap)
}
return -1;
}
+
+/*
+ * Various pseudo-headers that appear at the beginning of packet data.
+ *
+ * We represent them as sets of offsets, as they might not be aligned on
+ * an appropriate structure boundary in the buffer, and as that makes them
+ * independent of the way the compiler might align fields.
+ */
+
+/*
+ * The link-layer header on SunATM packets.
+ */
+#define SUNATM_FLAGS 0 /* destination and traffic type - 1 byte */
+#define SUNATM_VPI 1 /* VPI - 1 byte */
+#define SUNATM_VCI 2 /* VCI - 2 bytes */
+#define SUNATM_LEN 4 /* length of the header */
+
+/*
+ * The link-layer header on Nokia IPSO ATM packets.
+ */
+#define NOKIAATM_FLAGS 0 /* destination - 1 byte */
+#define NOKIAATM_VPI 1 /* VPI - 1 byte */
+#define NOKIAATM_VCI 2 /* VCI - 2 bytes */
+#define NOKIAATM_LEN 4 /* length of the header */
+
+/*
+ * The fake link-layer header of IrDA packets as introduced by Jean Tourrilhes
+ * to libpcap.
+ */
+#define IRDA_SLL_PKTTYPE_OFFSET 0 /* packet type - 2 bytes */
+/* 12 unused bytes */
+#define IRDA_SLL_PROTOCOL_OFFSET 14 /* protocol, should be ETH_P_LAPD - 2 bytes */
+#define IRDA_SLL_LEN 16 /* length of the header */
+
+/*
+ * A header containing additional MTP information.
+ */
+#define MTP2_SENT_OFFSET 0 /* 1 byte */
+#define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */
+#define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */
+#define MTP2_HDR_LEN 4 /* length of the header */
+
+/*
+ * A header containing additional SITA WAN information.
+ */
+#define SITA_FLAGS_OFFSET 0 /* 1 byte */
+#define SITA_SIGNALS_OFFSET 1 /* 1 byte */
+#define SITA_ERRORS1_OFFSET 2 /* 1 byte */
+#define SITA_ERRORS2_OFFSET 3 /* 1 byte */
+#define SITA_PROTO_OFFSET 4 /* 1 byte */
+#define SITA_HDR_LEN 5 /* length of the header */
+
+/*
+ * The fake link-layer header of LAPD packets.
+ */
+#ifndef ETH_P_LAPD
+#define ETH_P_LAPD 0x0030
+#endif
+
+#define LAPD_SLL_PKTTYPE_OFFSET 0 /* packet type - 2 bytes */
+#define LAPD_SLL_HATYPE_OFFSET 2 /* hardware address type - 2 bytes */
+#define LAPD_SLL_HALEN_OFFSET 4 /* hardware address length - 2 bytes */
+#define LAPD_SLL_ADDR_OFFSET 6 /* address - 8 bytes */
+#define LAPD_SLL_PROTOCOL_OFFSET 14 /* protocol, should be ETH_P_LAPD - 2 bytes */
+#define LAPD_SLL_LEN 16 /* length of the header */
+
+/*
+ * I2C link-layer on-disk format
+ */
+struct i2c_file_hdr {
+ guint8 bus;
+ guint8 flags[4];
+};
+
+static gboolean
+pcap_read_sunatm_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
+{
+ guint8 atm_phdr[SUNATM_LEN];
+ int bytes_read;
+ guint8 vpi;
+ guint16 vci;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(atm_phdr, 1, SUNATM_LEN, fh);
+ if (bytes_read != SUNATM_LEN) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ vpi = atm_phdr[SUNATM_VPI];
+ vci = pntohs(&atm_phdr[SUNATM_VCI]);
+
+ switch (atm_phdr[SUNATM_FLAGS] & 0x0F) {
+
+ case 0x01: /* LANE */
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_LANE;
+ break;
+
+ case 0x02: /* RFC 1483 LLC multiplexed traffic */
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_LLCMX;
+ break;
+
+ case 0x05: /* ILMI */
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_ILMI;
+ break;
+
+ case 0x06: /* Q.2931 */
+ pseudo_header->atm.aal = AAL_SIGNALLING;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ break;
+
+ case 0x03: /* MARS (RFC 2022) */
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ break;
+
+ case 0x04: /* IFMP (Ipsilon Flow Management Protocol; see RFC 1954) */
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_UNKNOWN; /* XXX - TRAF_IPSILON? */
+ break;
+
+ default:
+ /*
+ * Assume it's AAL5, unless it's VPI 0 and VCI 5, in which
+ * case assume it's AAL_SIGNALLING; we know nothing more
+ * about it.
+ *
+ * XXX - is this necessary? Or are we guaranteed that
+ * all signalling traffic has a type of 0x06?
+ *
+ * XXX - is this guaranteed to be AAL5? Or, if the type is
+ * 0x00 ("raw"), might it be non-AAL5 traffic?
+ */
+ if (vpi == 0 && vci == 5)
+ pseudo_header->atm.aal = AAL_SIGNALLING;
+ else
+ pseudo_header->atm.aal = AAL_5;
+ pseudo_header->atm.type = TRAF_UNKNOWN;
+ break;
+ }
+ pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
+
+ pseudo_header->atm.vpi = vpi;
+ pseudo_header->atm.vci = vci;
+ pseudo_header->atm.channel = (atm_phdr[SUNATM_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
+pcap_read_nokiaatm_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
+{
+ guint8 atm_phdr[NOKIAATM_LEN];
+ int bytes_read;
+ guint8 vpi;
+ guint16 vci;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(atm_phdr, 1, NOKIAATM_LEN, fh);
+ if (bytes_read != NOKIAATM_LEN) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ vpi = atm_phdr[NOKIAATM_VPI];
+ vci = pntohs(&atm_phdr[NOKIAATM_VCI]);
+
+ pseudo_header->atm.vpi = vpi;
+ pseudo_header->atm.vci = vci;
+ pseudo_header->atm.channel = (atm_phdr[NOKIAATM_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
+pcap_read_irda_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info)
+{
+ guint8 irda_phdr[IRDA_SLL_LEN];
+ int bytes_read;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(irda_phdr, 1, IRDA_SLL_LEN, fh);
+ if (bytes_read != IRDA_SLL_LEN) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ if (pntohs(&irda_phdr[IRDA_SLL_PROTOCOL_OFFSET]) != 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[IRDA_SLL_PKTTYPE_OFFSET]);
+
+ return TRUE;
+}
+
+static gboolean
+pcap_read_mtp2_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+{
+ 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);
+ if (bytes_read != MTP2_HDR_LEN) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ pseudo_header->mtp2.sent = mtp2_hdr[MTP2_SENT_OFFSET];
+ pseudo_header->mtp2.annex_a_used = mtp2_hdr[MTP2_ANNEX_A_USED_OFFSET];
+ pseudo_header->mtp2.link_number = pntohs(&mtp2_hdr[MTP2_LINK_NUMBER_OFFSET]);
+
+ return TRUE;
+}
+
+static gboolean
+pcap_read_lapd_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info)
+{
+ guint8 lapd_phdr[LAPD_SLL_LEN];
+ int bytes_read;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(lapd_phdr, 1, LAPD_SLL_LEN, fh);
+ if (bytes_read != LAPD_SLL_LEN) {
+ *err = file_error(fh);
+ 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;
+ if (err_info != NULL)
+ *err_info = g_strdup("libpcap: LAPD capture has a packet with an invalid sll_protocol field\n");
+ return FALSE;
+ }
+
+ pseudo_header->lapd.pkttype = pntohs(&lapd_phdr[LAPD_SLL_PKTTYPE_OFFSET]);
+ pseudo_header->lapd.we_network = !!lapd_phdr[LAPD_SLL_ADDR_OFFSET+0];
+
+ return TRUE;
+}
+
+static gboolean
+pcap_read_sita_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+{
+ 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);
+ if (bytes_read != SITA_HDR_LEN) {
+ *err = file_error(fh);
+ 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];
+
+ return TRUE;
+}
+
+static gboolean
+pcap_read_linux_usb_pseudoheader(wtap *wth, FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
+{
+ int bytes_read;
+
+ 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;
+ }
+
+ if (wth->capture.pcap->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);
+ }
+
+ return TRUE;
+}
+
+static gboolean
+pcap_read_bt_pseudoheader(FILE_T fh,
+ union wtap_pseudo_header *pseudo_header, int *err)
+{
+ int bytes_read;
+ struct libpcap_bt_phdr phdr;
+
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(&phdr, 1,
+ sizeof (struct libpcap_bt_phdr), fh);
+ if (bytes_read != sizeof (struct libpcap_bt_phdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+ pseudo_header->p2p.sent = ((g_ntohl(phdr.direction) & 0x1) == 0)? TRUE: FALSE;
+ return TRUE;
+}
+
+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_)
+{
+ 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);
+ if (bytes_read != sizeof(struct erf_phdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+ pseudo_header->erf.phdr.ts = pletohll(&erf_hdr[0]); /* timestamp */
+ pseudo_header->erf.phdr.type = erf_hdr[8];
+ pseudo_header->erf.phdr.flags = erf_hdr[9];
+ pseudo_header->erf.phdr.rlen = pntohs(&erf_hdr[10]);
+ pseudo_header->erf.phdr.lctr = pntohs(&erf_hdr[12]);
+ pseudo_header->erf.phdr.wlen = pntohs(&erf_hdr[14]);
+
+ /* The high 32 bits of the timestamp contain the integer number of seconds
+ * while the lower 32 bits contain the binary fraction of the second.
+ * This allows an ultimate resolution of 1/(2^32) seconds, or approximately 233 picoseconds */
+ if (whdr) {
+ guint64 ts = pseudo_header->erf.phdr.ts;
+ whdr->ts.secs = (guint32) (ts >> 32);
+ ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000);
+ ts += (ts & 0x80000000) << 1; /* rounding */
+ whdr->ts.nsecs = ((guint32) (ts >> 32));
+ if ( whdr->ts.nsecs >= 1000000000) {
+ whdr->ts.nsecs -= 1000000000;
+ whdr->ts.secs += 1;
+ }
+ }
+ return TRUE;
+}
+
+/*
+ * If the type of record given in the pseudo header indicate the presence of an extension
+ * header then, read all the extension headers
+ */
+static gboolean
+pcap_read_erf_exheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info _U_, 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;
+ *psize = 0;
+ if (pseudo_header->erf.phdr.type & 0x80){
+ do{
+ errno = WTAP_ERR_CANT_READ;
+ bytes_read = file_read(erf_exhdr, 1, 8, fh);
+ if (bytes_read != 8 ) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+ type = erf_exhdr[0];
+ erf_exhdr_sw = pntohll((guint64*) &(erf_exhdr[0]));
+ if (i < max)
+ memcpy(&pseudo_header->erf.ehdr_list[i].ehdr, &erf_exhdr_sw, sizeof(erf_exhdr_sw));
+ *psize += 8;
+ i++;
+ } while (type & 0x80);
+ }
+ return TRUE;
+}
+
+/*
+ * If the type of record given in the pseudo header indicate the precense of a subheader
+ * then, read this optional subheader
+ */
+static gboolean
+pcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info _U_, guint * psize)
+{
+ guint8 erf_subhdr[sizeof(union erf_subhdr)];
+ int bytes_read;
+
+ *psize=0;
+ switch(pseudo_header->erf.phdr.type & 0x7F) {
+ case ERF_TYPE_MC_HDLC:
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_ATM:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_MC_AAL5:
+ case ERF_TYPE_MC_AAL2:
+ 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);
+ if (bytes_read != sizeof(erf_mc_header_t) ) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+ pseudo_header->erf.subhdr.mc_hdr = pntohl(&erf_subhdr[0]);
+ *psize = sizeof(erf_mc_header_t);
+ break;
+ case ERF_TYPE_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ 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);
+ if (bytes_read != sizeof(erf_eth_header_t) ) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+ pseudo_header->erf.subhdr.eth_hdr = pntohs(&erf_subhdr[0]);
+ *psize = sizeof(erf_eth_header_t);
+ break;
+ default:
+ /* No optional pseudo header for this ERF type */
+ break;
+ }
+ return TRUE;
+}
+
+static gboolean
+pcap_read_i2c_pseudoheader(FILE_T fh, union wtap_pseudo_header *pseudo_header, int *err, gchar **err_info _U_)
+{
+ 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);
+ if (bytes_read != sizeof (i2c_hdr)) {
+ *err = file_error(fh);
+ if (*err == 0)
+ *err = WTAP_ERR_SHORT_READ;
+ return FALSE;
+ }
+
+ pseudo_header->i2c.is_event = i2c_hdr.bus & 0x80 ? 1 : 0;
+ pseudo_header->i2c.bus = i2c_hdr.bus & 0x7f;
+ pseudo_header->i2c.flags = pntohl(&i2c_hdr.flags);
+
+ return TRUE;
+}
+
+int
+pcap_process_pseudo_header(wtap *wth, FILE_T fh, guint packet_size,
+ struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info)
+{
+ int phdr_len = 0;
+ guint size;
+
+ switch (wth->file_encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
+ if (wth->file_type == WTAP_FILE_PCAP_NOKIA) {
+ /*
+ * Nokia IPSO ATM.
+ */
+ if (packet_size < NOKIAATM_LEN) {
+ /*
+ * 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: Nokia IPSO ATM file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_nokiaatm_pseudoheader(fh,
+ pseudo_header, err))
+ return -1; /* Read error */
+
+ phdr_len = NOKIAATM_LEN;
+ } else {
+ /*
+ * SunATM.
+ */
+ if (packet_size < SUNATM_LEN) {
+ /*
+ * 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: SunATM file has a %u-byte packet, too small to have even an ATM pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_sunatm_pseudoheader(fh,
+ pseudo_header, err))
+ return -1; /* Read error */
+
+ phdr_len = SUNATM_LEN;
+ }
+ 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;
+
+ case WTAP_ENCAP_IEEE_802_11:
+ case WTAP_ENCAP_PRISM_HEADER:
+ case WTAP_ENCAP_IEEE_802_11_WLAN_RADIOTAP:
+ 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;
+ pseudo_header->ieee_802_11.channel = 0;
+ pseudo_header->ieee_802_11.data_rate = 0;
+ pseudo_header->ieee_802_11.signal_level = 0;
+ break;
+
+ case WTAP_ENCAP_IRDA:
+ if (packet_size < IRDA_SLL_LEN) {
+ /*
+ * 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: IrDA file has a %u-byte packet, too small to have even an IrDA pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_irda_pseudoheader(fh, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ phdr_len = IRDA_SLL_LEN;
+ break;
+
+ case WTAP_ENCAP_MTP2_WITH_PHDR:
+ if (packet_size < MTP2_HDR_LEN) {
+ /*
+ * 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: MTP2 file has a %u-byte packet, too small to have even an MTP2 pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_mtp2_pseudoheader(fh, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ phdr_len = MTP2_HDR_LEN;
+ break;
+
+ case WTAP_ENCAP_LINUX_LAPD:
+ if (packet_size < LAPD_SLL_LEN) {
+ /*
+ * 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: LAPD file has a %u-byte packet, too small to have even a LAPD pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_lapd_pseudoheader(fh, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ phdr_len = LAPD_SLL_LEN;
+ break;
+
+ case WTAP_ENCAP_SITA:
+ if (packet_size < SITA_HDR_LEN) {
+ /*
+ * 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: SITA file has a %u-byte packet, too small to have even a SITA pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_sita_pseudoheader(fh, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ phdr_len = SITA_HDR_LEN;
+ break;
+
+ case WTAP_ENCAP_USB_LINUX:
+ case WTAP_ENCAP_USB_LINUX_MMAPPED:
+ if (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\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_linux_usb_pseudoheader(wth, fh,
+ pseudo_header, 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;
+ break;
+
+ case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
+ if (packet_size < 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 bluetooth file has a %u-byte packet, too small to have even a pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_bt_pseudoheader(fh,
+ pseudo_header, err))
+ return -1; /* Read error */
+
+ phdr_len = (int)sizeof (struct libpcap_bt_phdr);
+ break;
+
+ case WTAP_ENCAP_ERF:
+ if (packet_size < sizeof(struct erf_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: ERF file has a %u-byte packet, too small to have even an ERF pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+
+ if (!pcap_read_erf_pseudoheader(fh, phdr, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ phdr_len = (int)sizeof(struct erf_phdr);
+
+ /* check the optional Extension header */
+ if (!pcap_read_erf_exheader(fh, pseudo_header, err, err_info,
+ &size))
+ return -1; /* Read error */
+
+ phdr_len += size;
+
+ /* check the optional Multi Channel header */
+ if (!pcap_read_erf_subheader(fh, pseudo_header, err, err_info,
+ &size))
+ return -1; /* Read error */
+
+ phdr_len += size;
+ break;
+
+ case WTAP_ENCAP_I2C:
+ if (packet_size < sizeof (struct i2c_file_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("pcap: I2C file has a %u-byte packet, too small to have even a I2C pseudo-header\n",
+ packet_size);
+ return -1;
+ }
+ if (!pcap_read_i2c_pseudoheader(fh, pseudo_header,
+ err, err_info))
+ return -1; /* Read error */
+
+ /*
+ * Don't count the pseudo-header as part of the packet.
+ */
+ phdr_len = (int)sizeof (struct i2c_file_hdr);
+ break;
+ }
+
+ return phdr_len;
+}
+
+int
+pcap_get_phdr_size(int encap, const union wtap_pseudo_header *pseudo_header)
+{
+ int hdrsize;
+
+ switch (encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
+ hdrsize = SUNATM_LEN;
+ break;
+
+ case WTAP_ENCAP_IRDA:
+ hdrsize = IRDA_SLL_LEN;
+ break;
+
+ case WTAP_ENCAP_MTP2_WITH_PHDR:
+ hdrsize = MTP2_HDR_LEN;
+ break;
+
+ case WTAP_ENCAP_LINUX_LAPD:
+ hdrsize = LAPD_SLL_LEN;
+ break;
+
+ case WTAP_ENCAP_SITA:
+ 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:
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_ATM:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_MC_AAL5:
+ case ERF_TYPE_MC_AAL2:
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ hdrsize += (int)sizeof(struct erf_mc_hdr);
+ break;
+
+ case ERF_TYPE_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ hdrsize += (int)sizeof(struct erf_eth_hdr);
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ case WTAP_ENCAP_I2C:
+ hdrsize = (int)sizeof (struct i2c_file_hdr);
+ break;
+
+ default:
+ hdrsize = 0;
+ break;
+ }
+
+ return hdrsize;
+}
+
+gboolean
+pcap_write_phdr(wtap_dumper *wdh, const union wtap_pseudo_header *pseudo_header,
+ int *err)
+{
+ guint8 atm_hdr[SUNATM_LEN];
+ guint8 irda_hdr[IRDA_SLL_LEN];
+ guint8 lapd_hdr[LAPD_SLL_LEN];
+ guint8 mtp2_hdr[MTP2_HDR_LEN];
+ guint8 sita_hdr[SITA_HDR_LEN];
+ guint8 erf_hdr[ sizeof(struct erf_mc_phdr)];
+ struct i2c_file_hdr i2c_hdr;
+ size_t nwritten;
+ size_t size;
+
+ switch (wdh->encap) {
+
+ case WTAP_ENCAP_ATM_PDUS:
+ /*
+ * Write the ATM header.
+ */
+ atm_hdr[SUNATM_FLAGS] =
+ (pseudo_header->atm.channel == 0) ? 0x80 : 0x00;
+ switch (pseudo_header->atm.aal) {
+
+ case AAL_SIGNALLING:
+ /* Q.2931 */
+ atm_hdr[SUNATM_FLAGS] |= 0x06;
+ break;
+
+ case AAL_5:
+ switch (pseudo_header->atm.type) {
+
+ case TRAF_LANE:
+ /* LANE */
+ atm_hdr[SUNATM_FLAGS] |= 0x01;
+ break;
+
+ case TRAF_LLCMX:
+ /* RFC 1483 LLC multiplexed traffic */
+ atm_hdr[SUNATM_FLAGS] |= 0x02;
+ break;
+
+ case TRAF_ILMI:
+ /* ILMI */
+ atm_hdr[SUNATM_FLAGS] |= 0x05;
+ break;
+ }
+ break;
+ }
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(atm_hdr);
+ break;
+
+ case WTAP_ENCAP_IRDA:
+ /*
+ * Write the IrDA header.
+ */
+ memset(irda_hdr, 0, sizeof(irda_hdr));
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(irda_hdr);
+ break;
+
+ case WTAP_ENCAP_MTP2_WITH_PHDR:
+ /*
+ * Write the MTP2 header.
+ */
+ memset(&mtp2_hdr, 0, sizeof(mtp2_hdr));
+ mtp2_hdr[MTP2_SENT_OFFSET] = pseudo_header->mtp2.sent;
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(mtp2_hdr);
+ break;
+
+ case WTAP_ENCAP_LINUX_LAPD:
+ /*
+ * Write the LAPD header.
+ */
+ memset(&lapd_hdr, 0, sizeof(lapd_hdr));
+ phtons(&lapd_hdr[LAPD_SLL_PKTTYPE_OFFSET],
+ pseudo_header->lapd.pkttype);
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(lapd_hdr);
+ break;
+
+ case WTAP_ENCAP_SITA:
+ /*
+ * 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;
+ 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);
+ 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);
+ phtons(&erf_hdr[12], pseudo_header->erf.phdr.lctr);
+ phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
+ size = sizeof(struct erf_phdr);
+
+ switch(pseudo_header->erf.phdr.type & 0x7F) {
+ case ERF_TYPE_MC_HDLC:
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_ATM:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_MC_AAL5:
+ case ERF_TYPE_MC_AAL2:
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ phtonl(&erf_hdr[16], pseudo_header->erf.subhdr.mc_hdr);
+ size += (int)sizeof(struct erf_mc_hdr);
+ break;
+ case ERF_TYPE_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ phtons(&erf_hdr[16], pseudo_header->erf.subhdr.eth_hdr);
+ size += (int)sizeof(struct erf_eth_hdr);
+ break;
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += size;
+ break;
+
+ case WTAP_ENCAP_I2C:
+ /*
+ * Write the I2C header.
+ */
+ memset(&i2c_hdr, 0, sizeof(i2c_hdr));
+ 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;
+ return FALSE;
+ }
+ wdh->bytes_dumped += sizeof(i2c_hdr);
+ break;
+ }
+
+ return TRUE;
+}
diff --git a/wiretap/pcap-common.h b/wiretap/pcap-common.h
index efe11c476d..2df92014b6 100644
--- a/wiretap/pcap-common.h
+++ b/wiretap/pcap-common.h
@@ -32,3 +32,13 @@ struct encap_map {
extern const struct encap_map pcap_to_wtap_map[];
extern int wtap_wtap_encap_to_pcap_encap(int encap);
+
+extern int pcap_process_pseudo_header(wtap *wth, FILE_T fh, guint packet_size,
+ struct wtap_pkthdr *phdr, union wtap_pseudo_header *pseudo_header,
+ int *err, gchar **err_info);
+
+extern int pcap_get_phdr_size(int encap,
+ const union wtap_pseudo_header *pseudo_header);
+
+extern gboolean pcap_write_phdr(wtap_dumper *wdh,
+ const union wtap_pseudo_header *pseudo_header, int *err);