aboutsummaryrefslogtreecommitdiffstats
path: root/wiretap
diff options
context:
space:
mode:
authorguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2007-06-08 17:06:13 +0000
committerguy <guy@f5534014-38df-0310-8fa8-9805f1628bb7>2007-06-08 17:06:13 +0000
commit409c68bc5ac7004bd3b39258c9cec1a9623c9ccd (patch)
treeeb62f6806c1674cf6744f2834c6f33a04e4c03ff /wiretap
parent599f4c30d8b185b5830f8b674d962c120c1b52af (diff)
From Stephen Donnelly of Endace:
The code for reading ERF files has not been significantly updated since 2004. This patch brings it up to date with a number of changes. 1) Increase number of decodable ERF types from 7 to 12. This covers newer DAG card models and firmware updates. 2) Fix timestamp conversion. Was calculating only microsecond precision, now displaying with nanosecond resolution. Hardware precision is 7.5 to 30 ns depending on model. 3) Allow the user to specify HDLC encapsulation as 'chdlc', 'ppp_serial', 'frelay' or 'mtp2'. This is needed because the ERF HDLC capture formats do not include information on what protocol is used at the next level. This is currently done via an environment variable 'ERF_HDLC_ENCAP' and is analagous to the existing 'ERF_ATM_ENCAP' variable. If the user does not specify an HDLC encapsulation it tries to guess, and falls back to MTP2 for backwards compatibility with Florent's existing behaviour. I know environment variables are ugly, suggestions are welcome. 4) When reading HDLC captures as MTP2, use WTAP_ENCAP_MTP2_WITH_PHDR rather than WTAP_ENCAP_MTP2. This allows us to put the 'Multi-Channel ERF' record 'channel number' field into the MTP2 pseudo header > 'link_number' field. This is then displayed in Frame information, and can be filtered on. (Would be nice if it could be made a display column?) Because the ERF record does not specify whether Annex A is used or not, we pass MTP2_ANNEX_A_USED_UNKNOWN and allow the existing user preference to decide. Move the MTP2_ANNEX_A_ definitions into Wiretap, make the annex_a_used field a guint8, and change MTP2_ANNEX_A_USED_UNKNOWN to 2 so it fits in a guint8. (This means that if you can save an ERF MTP2 file as a libpcap file, the pseudo-header will have MTP2_ANNEX_A_USED_UNKNOWN in it.) git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@22067 f5534014-38df-0310-8fa8-9805f1628bb7
Diffstat (limited to 'wiretap')
-rw-r--r--wiretap/erf.c152
-rw-r--r--wiretap/erf.h36
-rw-r--r--wiretap/file_access.c2
-rw-r--r--wiretap/wtap-int.h2
-rw-r--r--wiretap/wtap.h4
5 files changed, 158 insertions, 38 deletions
diff --git a/wiretap/erf.c b/wiretap/erf.c
index a9bfb95246..b6c9c6444a 100644
--- a/wiretap/erf.c
+++ b/wiretap/erf.c
@@ -88,8 +88,8 @@ int erf_open(wtap *wth, int *err, gchar **err_info _U_)
char *s;
guint32 records_for_erf_check = RECORDS_FOR_ERF_CHECK;
guint32 atm_encap = WTAP_ENCAP_ATM_PDUS;
+ guint32 hdlc_encap = WTAP_ENCAP_UNKNOWN;
gboolean is_rawatm = FALSE;
- gboolean is_ppp = FALSE;
int common_type = 0;
erf_timestamp_t prevts;
@@ -108,6 +108,22 @@ int erf_open(wtap *wth, int *err, gchar **err_info _U_)
}
}
+ if ((s = getenv("ERF_HDLC_ENCAP")) != NULL) {
+ if (!strcmp(s, "chdlc")) {
+ hdlc_encap = WTAP_ENCAP_CHDLC;
+ } else
+ if (!strcmp(s, "ppp_serial")) {
+ hdlc_encap = WTAP_ENCAP_PPP;
+ } else
+ if (!strcmp(s, "frelay")) {
+ hdlc_encap = WTAP_ENCAP_FRELAY;
+ } else
+ if (!strcmp(s, "mtp2")) {
+ hdlc_encap = WTAP_ENCAP_MTP2_WITH_PHDR;
+ }
+ }
+
+
/* number of records to scan before deciding if this really is ERF (dflt=3) */
if ((s = getenv("ERF_RECORDS_TO_CHECK")) != NULL) {
if ((n = atoi(s)) > 0 && n < 101) {
@@ -136,11 +152,19 @@ int erf_open(wtap *wth, int *err, gchar **err_info _U_)
packet_size = g_ntohs(header.rlen) - sizeof(header);
/* fail on invalid record type, decreasing timestamps or non-zero pad-bits */
- /* Only header type up to Multi Channel HDLC are taken into account in this software version */
- if (header.type == 0 || header.type > TYPE_MC_HDLC ) {
+ /* Not all types within this range are decoded, but it is a first filter */
+ if (header.type == 0 || header.type > TYPE_MAX ) {
return 0;
}
+ /* Skip PAD records, timestamps may not be set */
+ if (header.type == TYPE_PAD) {
+ if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) {
+ return -1;
+ }
+ continue;
+ }
+
if ((ts = pletohll(&header.ts)) < prevts) {
/* reassembled AAL5 records may not be in time order, so allow 1 sec fudge */
if (header.type != TYPE_AAL5 || ((prevts-ts)>>32) > 1) {
@@ -156,15 +180,46 @@ int erf_open(wtap *wth, int *err, gchar **err_info _U_)
common_type = -1;
}
- if (header.type == TYPE_HDLC_POS && !is_ppp) {
+ /* Read over MC header */
+ if ( (header.type == TYPE_MC_HDLC) ||
+ (header.type == TYPE_MC_RAW) ||
+ (header.type == TYPE_MC_ATM) ||
+ (header.type == TYPE_MC_RAW_CHANNEL) ||
+ (header.type == TYPE_MC_AAL5) ||
+ (header.type == TYPE_MC_AAL2) ||
+ (header.type == TYPE_COLOR_MC_HDLC_POS) ) {
+ guint32 mc_hdr;
+ if (file_read(&mc_hdr,1,sizeof(mc_hdr),wth->fh) != sizeof(mc_hdr)) {
+ *err = file_error(wth->fh);
+ }
+ packet_size -= sizeof(mc_hdr);
+ }
+
+ /* Try to guess hdlc type if user didn't specify */
+ if ( ( (header.type == TYPE_HDLC_POS) ||
+ (header.type == TYPE_MC_HDLC) ||
+ (header.type == TYPE_COLOR_HDLC_POS) ||
+ (header.type == TYPE_COLOR_MC_HDLC_POS) ) &&
+ hdlc_encap == WTAP_ENCAP_UNKNOWN) {
guint16 chdlc_hdr;
if (file_read(&chdlc_hdr,1,sizeof(chdlc_hdr),wth->fh) != sizeof(chdlc_hdr)) {
*err = file_error(wth->fh);
}
packet_size -= sizeof(chdlc_hdr);
+
+ /* Looks like PPP in HDLC-like framing*/
if (g_ntohs(chdlc_hdr) == 0xff03) {
- is_ppp = TRUE;
+ hdlc_encap = WTAP_ENCAP_PPP;
}
+ /* Looks like Cisco HDLC */
+ else if (g_ntohs(chdlc_hdr) == 0x0f00) {
+ hdlc_encap = WTAP_ENCAP_CHDLC;
+ }
+ /* How to guess between FRELAY and MTP2?
+ * For now be backward compatible with Florent's
+ * established behaviour */
+ else
+ hdlc_encap = WTAP_ENCAP_MTP2_WITH_PHDR;
}
if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) {
@@ -182,7 +237,7 @@ int erf_open(wtap *wth, int *err, gchar **err_info _U_)
wth->file_type = WTAP_FILE_ERF;
wth->snapshot_length = 0; /* not available in header, only in frame */
wth->capture.erf = g_malloc(sizeof(erf_t));
- wth->capture.erf->is_ppp = is_ppp;
+ wth->capture.erf->hdlc_encap = hdlc_encap;
if (common_type == TYPE_AAL5) {
wth->capture.erf->atm_encap = WTAP_ENCAP_ATM_PDUS_UNTRUNCATED;
wth->capture.erf->is_rawatm = FALSE;
@@ -220,13 +275,15 @@ static gboolean erf_read(wtap *wth, int *err, gchar **err_info,
*data_offset = wth->data_offset;
- if (!erf_read_header(
- wth->fh,
- &wth->phdr, &wth->pseudo_header, &erf_header, wth->capture.erf,
- err, err_info, &bytes_read, &packet_size)) {
- return FALSE;
- }
- wth->data_offset += bytes_read;
+ do {
+ if (!erf_read_header(
+ wth->fh,
+ &wth->phdr, &wth->pseudo_header, &erf_header, wth->capture.erf,
+ err, err_info, &bytes_read, &packet_size)) {
+ return FALSE;
+ }
+ wth->data_offset += bytes_read;
+ } while ( erf_header.type == TYPE_PAD );
buffer_assure_space(wth->frame_buffer, packet_size+(wth->capture.erf->is_rawatm?(sizeof(atm_hdr_t)+1):0));
@@ -297,6 +354,7 @@ static int erf_read_header(
guint32 *packet_size)
{
guint32 rec_size, skip;
+ guint32 mc_hdr;
wtap_file_read_expected_bytes(erf_header, sizeof(*erf_header), fh, err);
if (bytes_read != NULL) {
@@ -305,6 +363,7 @@ static int erf_read_header(
rec_size = g_ntohs(erf_header->rlen);
*packet_size = rec_size - sizeof(*erf_header);
+
skip = 0; /* # bytes of payload to ignore */
if (*packet_size > WTAP_MAX_PACKET_SIZE) {
@@ -322,21 +381,41 @@ static int erf_read_header(
guint64 ts = pletohll(&erf_header->ts);
phdr->ts.secs = (long) (ts >> 32);
- ts = ((ts & 0xffffffff) * 1000 * 1000);
+ ts = ((ts & 0xffffffff) * 1000 * 1000 * 1000);
ts += (ts & 0x80000000) << 1; /* rounding */
- phdr->ts.nsecs = ((long) (ts >> 32)) * 1000;
+ phdr->ts.nsecs = ((long) (ts >> 32));
if (phdr->ts.nsecs >= 1000000000) {
phdr->ts.nsecs -= 1000000000;
phdr->ts.secs += 1;
}
}
+ /* Save off the ERF MC header if persent */
+ switch (erf_header->type) {
+ case TYPE_MC_HDLC:
+ case TYPE_MC_RAW:
+ case TYPE_MC_ATM:
+ case TYPE_MC_RAW_CHANNEL:
+ case TYPE_MC_AAL5:
+ case TYPE_MC_AAL2:
+ case TYPE_COLOR_MC_HDLC_POS:
+ wtap_file_read_expected_bytes(&mc_hdr, sizeof(mc_hdr), fh, err);
+ if (bytes_read != NULL) {
+ *bytes_read += sizeof(mc_hdr);
+ }
+ *packet_size -= sizeof(mc_hdr);
+
+ mc_hdr = g_ntohl(mc_hdr);
+ }
+
switch (erf_header->type) {
case TYPE_ATM:
case TYPE_AAL5:
+ case TYPE_MC_ATM:
+ case TYPE_MC_AAL5:
if (phdr != NULL) {
- if (erf_header->type == TYPE_AAL5) {
+ if ( (erf_header->type == TYPE_AAL5) || (erf_header->type == TYPE_MC_AAL5) ) {
phdr->caplen = phdr->len = *packet_size - sizeof(atm_hdr_t);
} else {
phdr->caplen = ATM_SLEN(erf_header, NULL);
@@ -371,14 +450,20 @@ static int erf_read_header(
skip = 4;
}
break;
+
case TYPE_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_DSM_COLOR_ETH:
if (phdr != NULL) {
phdr->caplen = ETHERNET_SLEN(erf_header, erf);
phdr->len = ETHERNET_WLEN(erf_header, erf);
}
skip = 2;
break;
+
case TYPE_HDLC_POS:
+ case TYPE_COLOR_HDLC_POS:
+ case TYPE_DSM_COLOR_HDLC_POS:
if (phdr != NULL) {
phdr->caplen = HDLC_SLEN(erf_header, erf);
phdr->len = HDLC_WLEN(erf_header, erf);
@@ -386,15 +471,22 @@ static int erf_read_header(
memset(&pseudo_header->p2p, 0, sizeof(pseudo_header->p2p));
pseudo_header->p2p.sent = ((erf_header->flags & 0x01) ? TRUE : FALSE);
break;
+
case TYPE_MC_HDLC:
+ case TYPE_COLOR_MC_HDLC_POS:
if (phdr != NULL) {
- phdr->caplen = MC_HDLC_SLEN(erf_header, erf);
- phdr->len = MC_HDLC_WLEN(erf_header, erf);
+ phdr->caplen = MC_HDLC_SLEN(erf_header, erf);
+ phdr->len = MC_HDLC_WLEN(erf_header, erf);
}
- /* Skip the MC header, so the first data to dissect will be the MTP2 header */
- skip = 4;
- memset(&pseudo_header->mtp2, 0, sizeof(pseudo_header->mtp2));
+ /* create mtp2 pseudo header.
+ * Currently blank, but lets insert the ERF MC channel id into
+ * the mtp2.link_number.
+ */
+ pseudo_header->mtp2.link_number = mc_hdr&0x1ff;
+ pseudo_header->mtp2.annex_a_used = MTP2_ANNEX_A_USED_UNKNOWN;
+ pseudo_header->mtp2.sent = 0;
break;
+
default:
*err = WTAP_ERR_UNSUPPORTED_ENCAP;
*err_info = g_strdup_printf("erf: unknown record encapsulation %u",
@@ -426,16 +518,23 @@ static int erf_encap_to_wtap_encap(erf_t *erf, guint8 erf_encap)
switch (erf_encap) {
case TYPE_ATM:
case TYPE_AAL5:
+ case TYPE_MC_ATM:
+ case TYPE_MC_AAL5:
+ case TYPE_MC_AAL2:
+ case TYPE_AAL2:
wtap_encap = erf->atm_encap;
break;
case TYPE_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_DSM_COLOR_ETH:
wtap_encap = WTAP_ENCAP_ETHERNET;
break;
case TYPE_HDLC_POS:
- wtap_encap = (erf->is_ppp ? WTAP_ENCAP_PPP : WTAP_ENCAP_CHDLC);
- break;
case TYPE_MC_HDLC:
- wtap_encap = WTAP_ENCAP_MTP2;
+ case TYPE_COLOR_HDLC_POS:
+ case TYPE_DSM_COLOR_HDLC_POS:
+ case TYPE_COLOR_MC_HDLC_POS:
+ wtap_encap = (erf->hdlc_encap ? erf->hdlc_encap : WTAP_ENCAP_MTP2_WITH_PHDR);
break;
default:
break;
@@ -447,7 +546,9 @@ static int erf_encap_to_wtap_encap(erf_t *erf, guint8 erf_encap)
static void erf_set_pseudo_header(
guint8 type, erf_t *erf, guchar *pd, int length, union wtap_pseudo_header *pseudo_header)
{
- if (type == TYPE_ETH) {
+ if ( (type == TYPE_ETH) ||
+ (type == TYPE_COLOR_ETH) ||
+ (type == TYPE_DSM_COLOR_ETH) ) {
/*
* We don't know whether there's an FCS in this frame or not.
*/
@@ -464,4 +565,5 @@ static void erf_set_pseudo_header(
pseudo_header->atm.type = TRAF_UNKNOWN;
pseudo_header->atm.subtype = TRAF_ST_UNKNOWN;
}
+ /* mtp2 pseudo header is created in erf_read_header() */
}
diff --git a/wiretap/erf.h b/wiretap/erf.h
index ed7ade992a..5a9a4d592e 100644
--- a/wiretap/erf.h
+++ b/wiretap/erf.h
@@ -39,16 +39,30 @@
#define __W_ERF_H__
/* Record type defines */
-#define TYPE_LEGACY 0
-#define TYPE_HDLC_POS 1
-#define TYPE_ETH 2
-#define TYPE_ATM 3
-#define TYPE_AAL5 4
-#define TYPE_MC_HDLC 5
-#define TYPE_MC_RAW 6
-#define TYPE_MC_ATM 7
-#define TYPE_MC_AAL2 9
-#define TYPE_MC_AAL5 12
+#define TYPE_LEGACY 0
+#define TYPE_HDLC_POS 1
+#define TYPE_ETH 2
+#define TYPE_ATM 3
+#define TYPE_AAL5 4
+#define TYPE_MC_HDLC 5
+#define TYPE_MC_RAW 6
+#define TYPE_MC_ATM 7
+#define TYPE_MC_RAW_CHANNEL 8
+#define TYPE_MC_AAL5 9
+#define TYPE_COLOR_HDLC_POS 10
+#define TYPE_COLOR_ETH 11
+#define TYPE_MC_AAL2 12
+#define TYPE_IP_COUNTER 13
+#define TYPE_TCP_FLOW_COUNTER 14
+#define TYPE_DSM_COLOR_HDLC_POS 15
+#define TYPE_DSM_COLOR_ETH 16
+#define TYPE_COLOR_MC_HDLC_POS 17
+#define TYPE_AAL2 18
+
+#define TYPE_PAD 48
+
+#define TYPE_MIN 1 /* sanity checking */
+#define TYPE_MAX 48 /* sanity checking */
/*
* The timestamp is 64bit unsigned fixed point little-endian value with
@@ -100,7 +114,7 @@ typedef struct erf_record {
* Size of MC_HDLC payload
*/
#define MC_HDLC_WLEN(h, e) (g_htons((h)->wlen))
-#define MC_HDLC_SLEN(h, e) min(HDLC_WLEN(h, e), g_htons((h)->rlen) - sizeof(*(h)) )
+#define MC_HDLC_SLEN(h, e) min(MC_HDLC_WLEN(h, e), g_htons((h)->rlen) - sizeof(*(h)) )
int erf_open(wtap *wth, int *err, gchar **err_info);
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 431b47c47e..1d27d3df41 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -447,7 +447,7 @@ static const struct file_type_info dump_open_table_base[] = {
NULL, NULL},
/* WTAP_FILE_ERF */
- { "Endace DAG capture", "erf", "*.erf", ".erf", FALSE,
+ { "Endace ERF capture", "erf", "*.erf", ".erf", FALSE,
NULL, NULL },
/* WTAP_FILE_EYESDN */
diff --git a/wiretap/wtap-int.h b/wiretap/wtap-int.h
index 15e1310b5c..01ab9025c6 100644
--- a/wiretap/wtap-int.h
+++ b/wiretap/wtap-int.h
@@ -138,8 +138,8 @@ typedef struct {
typedef struct {
guint32 atm_encap;
+ guint32 hdlc_encap;
gboolean is_rawatm;
- gboolean is_ppp;
} erf_t;
typedef struct _k12_t k12_t;
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index cd19bf909b..8922e461e4 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -498,6 +498,10 @@ struct nettl_phdr {
/* Packet "pseudo-header" for MTP2 files. */
+#define MTP2_ANNEX_A_NOT_USED 0
+#define MTP2_ANNEX_A_USED 1
+#define MTP2_ANNEX_A_USED_UNKNOWN 2
+
struct mtp2_phdr {
guint8 sent;
guint8 annex_a_used;