From Francesco Fusco:

Endace ERFII (extension header) support.

svn path=/trunk/; revision=26287
This commit is contained in:
Anders Broman 2008-09-29 16:20:24 +00:00
parent 3a26e89362
commit 637761d295
6 changed files with 394 additions and 22 deletions

View File

@ -31,6 +31,8 @@
#include <glib.h>
#include <epan/packet.h>
#include <epan/expert.h>
/*
#include "wiretap/atm.h"
*/
@ -42,7 +44,10 @@
static int proto_erf = -1;
static int hf_erf_ts = -1;
static int hf_erf_types = -1;
static int hf_erf_type = -1;
static int hf_erf_ehdr = -1;
static int hf_erf_ehdr_t = -1;
static int hf_erf_flags = -1;
static int hf_erf_flags_cap = -1;
static int hf_erf_flags_vlen = -1;
@ -55,6 +60,33 @@ static int hf_erf_rlen = -1;
static int hf_erf_lctr = -1;
static int hf_erf_wlen = -1;
/* Classification extension header */
/* InterceptID extension header */
static int hf_erf_ehdr_int_res1 = -1;
static int hf_erf_ehdr_int_id = -1;
static int hf_erf_ehdr_int_res2 = -1;
/* Raw Link extension header */
static int hf_erf_ehdr_raw_link_res = -1;
static int hf_erf_ehdr_raw_link_seqnum = -1;
static int hf_erf_ehdr_raw_link_rate = -1;
static int hf_erf_ehdr_raw_link_type = -1;
/* Classification extension header */
static int hf_erf_ehdr_class_flags = -1;
static int hf_erf_ehdr_class_flags_sh = -1;
static int hf_erf_ehdr_class_flags_shm = -1;
static int hf_erf_ehdr_class_flags_res1 = -1;
static int hf_erf_ehdr_class_flags_user = -1;
static int hf_erf_ehdr_class_flags_res2 = -1;
static int hf_erf_ehdr_class_flags_drop = -1;
static int hf_erf_ehdr_class_flags_str = -1;
static int hf_erf_ehdr_class_seqnum = -1;
/* Unknown extension header */
static int hf_erf_ehdr_unk = -1;
/* MC HDLC Header */
static int hf_erf_mc_hdlc_cn = -1;
static int hf_erf_mc_hdlc_res1 = -1;
@ -131,6 +163,7 @@ static int hf_erf_eth_res1 = -1;
/* Initialize the subtree pointers */
static gint ett_erf = -1;
static gint ett_erf_pseudo_hdr = -1;
static gint ett_erf_types = -1;
static gint ett_erf_flags = -1;
static gint ett_erf_mc_hdlc = -1;
static gint ett_erf_mc_raw = -1;
@ -143,6 +176,10 @@ static gint ett_erf_eth = -1;
/* Default subdissector, display raw hex data */
static dissector_handle_t data_handle;
/* IPv4 and IPv6 subdissectors */
static dissector_handle_t ipv4_handle;
static dissector_handle_t ipv6_handle;
static dissector_handle_t infiniband_handle;
typedef enum {
@ -168,6 +205,15 @@ static dissector_handle_t atm_untruncated_handle;
static gboolean erf_ethfcs = TRUE;
static dissector_handle_t ethwithfcs_handle, ethwithoutfcs_handle;
/* Classification */
#define EHDR_CLASS_SH_MASK 0x800000
#define EHDR_CLASS_SHM_MASK 0x400000
#define EHDR_CLASS_RES1_MASK 0x300000
#define EHDR_CLASS_USER_MASK 0x0FFFF0
#define EHDR_CLASS_RES2_MASK 0x08
#define EHDR_CLASS_DROP_MASK 0x04
#define EHDR_CLASS_STER_MASK 0x03
/* Header for ATM trafic identification */
#define ATM_HDR_LENGTH 4
@ -267,9 +313,38 @@ static const value_string erf_type_vals[] = {
{ ERF_TYPE_AAL2,"AAL2"},
{ ERF_TYPE_PAD,"PAD"},
{ ERF_TYPE_INFINIBAND, "INFINIBAND"},
{ ERF_TYPE_IPV4, "IPV4"},
{ ERF_TYPE_IPV6, "IPV6"},
{ ERF_TYPE_RAW_LINK, "RAW_LINK"},
{0, NULL}
};
/* Extended headers type defines */
static const value_string ehdr_type_vals[] = {
{ EXT_HDR_TYPE_CLASSIFICATION, "Classification"},
{ EXT_HDR_TYPE_INTERCEPTID, "InterceptID"},
{ EXT_HDR_TYPE_RAW_LINK, "Raw Link"},
{ 0, NULL }
};
static const value_string raw_link_types[] = {
{ 0x00, "sonet"},
{ 0x01, "sdh"},
{ 0, NULL },
};
static const value_string raw_link_rates[] = {
{ 0x00, "reserved"},
{ 0x01, "oc3/stm1"},
{ 0x02, "oc12/stm4"},
{ 0x03, "oc48/stm16"},
{ 0x04, "oc192/stm64"},
{ 0, NULL },
};
/* Copy of atm_guess_traffic_type from atm.c in /wiretap */
static void
erf_atm_guess_lane_type(const guint8 *pd, guint len,
@ -374,6 +449,90 @@ erf_atm_guess_traffic_type(const guint8 *pd, guint len,
}
}
static void
dissect_classification_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
{
proto_item *int_item= NULL, *flags_item = NULL;
proto_tree *int_tree = NULL, *flags_tree = NULL;
guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
guint32 value = hdr >> 32;
if (pseudo_hdr_tree){
int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Classification");
int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED(int_item);
proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
flags_item=proto_tree_add_uint(int_tree, hf_erf_ehdr_class_flags, tvb, 0, 0, value & 0xFFFFFF);
flags_tree = proto_item_add_subtree(flags_item, hf_erf_ehdr_class_flags);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_sh, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_shm, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res1, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_user, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_res2, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_drop, tvb, 0, 0, value);
proto_tree_add_uint(flags_tree, hf_erf_ehdr_class_flags_str, tvb, 0, 0, value);
proto_tree_add_uint(int_tree, hf_erf_ehdr_class_seqnum, tvb, 0, 0, (guint32)hdr);
}
}
static void
dissect_intercept_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
{
proto_item *int_item= NULL;
proto_tree *int_tree = NULL;
guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
if (pseudo_hdr_tree){
int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "InterceptID");
int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED(int_item);
proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
proto_tree_add_uint(int_tree, hf_erf_ehdr_int_res1, tvb, 0, 0, (guint8)((hdr >> 48) & 0xFF));
proto_tree_add_uint(int_tree, hf_erf_ehdr_int_id, tvb, 0, 0, (guint16)((hdr >> 32 ) & 0xFFFF));
proto_tree_add_uint(int_tree, hf_erf_ehdr_int_res2, tvb, 0, 0, (guint32)hdr);
}
}
static void
dissect_raw_link_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
{
proto_item *int_item= NULL;
proto_tree *int_tree = NULL;
guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
if (pseudo_hdr_tree){
int_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Raw Link");
int_tree = proto_item_add_subtree(int_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED(int_item);
proto_tree_add_uint(int_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_res , tvb, 0, 0, (guint32)((hdr >> 32) & 0xFFFFFF));
proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_seqnum , tvb, 0, 0, (guint32)((hdr >> 16) & 0xffff));
proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_rate, tvb, 0, 0, (guint32)((hdr >> 8) & 0x00ff));
proto_tree_add_uint(int_tree, hf_erf_ehdr_raw_link_type, tvb, 0, 0, (guint32)(hdr & 0x00ff));
}
}
static void
dissect_unknown_ex_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pseudo_hdr_tree, int idx)
{
proto_item *unk_item= NULL;
proto_tree *unk_tree = NULL;
guint64 hdr = pinfo->pseudo_header->erf.ehdr_list[idx].ehdr;
if (pseudo_hdr_tree){
unk_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Unknown");
unk_tree = proto_item_add_subtree(unk_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED(unk_item);
proto_tree_add_uint(unk_tree, hf_erf_ehdr_t , tvb, 0, 0, (guint8)((hdr >> 56) & 0x7F));
proto_tree_add_uint64(unk_tree, hf_erf_ehdr_unk, tvb, 0, 0, hdr);
}
}
static void
dissect_mc_hdlc_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -554,15 +713,22 @@ static void
dissect_erf_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *pi;
proto_item *pseudo_hdr_item = NULL, *flags_item = NULL;
proto_tree *pseudo_hdr_tree = NULL, *flags_tree = NULL;
proto_item *pseudo_hdr_item = NULL, *flags_item = NULL, *types_item = NULL;
proto_tree *pseudo_hdr_tree = NULL, *flags_tree = NULL, *types_tree = NULL;
pseudo_hdr_item = proto_tree_add_text(tree, tvb, 0, 0, "ERF Header");
pseudo_hdr_tree = proto_item_add_subtree(pseudo_hdr_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED( pseudo_hdr_item);
pi=proto_tree_add_uint64(pseudo_hdr_tree, hf_erf_ts, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.ts);
pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_type, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
types_item = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "Header type");
PROTO_ITEM_SET_GENERATED(types_item);
types_tree = proto_item_add_subtree(types_item, ett_erf_types);
pi=proto_tree_add_uint(types_tree, hf_erf_type, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
pi=proto_tree_add_uint(types_tree, hf_erf_ehdr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.type);
flags_item=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_flags, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.flags);
flags_tree = proto_item_add_subtree(flags_item, ett_erf_flags);
@ -575,9 +741,54 @@ dissect_erf_pseudo_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_rlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.rlen);
pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_lctr, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.lctr);
if (pinfo->pseudo_header->erf.phdr.lctr > 0)
expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "Packet loss occurred between previous and current packet");
pi=proto_tree_add_uint(pseudo_hdr_tree, hf_erf_wlen, tvb, 0, 0, pinfo->pseudo_header->erf.phdr.wlen);
}
static void
dissect_erf_pseudo_extension_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_item *pi;
proto_item *pseudo_hdr_item = NULL;
proto_tree *pseudo_hdr_tree = NULL;
guint8 type;
guint8 has_more = pinfo->pseudo_header->erf.phdr.type & 0x80;
int i = 0;
int max = sizeof(pinfo->pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
pseudo_hdr_item = proto_tree_add_text(tree, tvb, 0, 0, "ERF Extension Headers");
pseudo_hdr_tree = proto_item_add_subtree(pseudo_hdr_item, ett_erf_pseudo_hdr);
PROTO_ITEM_SET_GENERATED(pseudo_hdr_item);
while(has_more && i < max){
type = (guint8) (pinfo->pseudo_header->erf.ehdr_list[i].ehdr >> 56);
switch(type & 0x7f){
case EXT_HDR_TYPE_CLASSIFICATION:
dissect_classification_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
break;
case EXT_HDR_TYPE_INTERCEPTID:
dissect_intercept_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
break;
case EXT_HDR_TYPE_RAW_LINK:
dissect_raw_link_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
break;
default:
dissect_unknown_ex_header(tvb, pinfo, pseudo_hdr_tree, i);
break;
}
has_more = type & 0x80;
i++;
}
if (has_more){
pi = proto_tree_add_text(pseudo_hdr_tree, tvb, 0, 0, "More extension header present");
expert_add_info_format(pinfo, pi, PI_SEQUENCE, PI_WARN, "Some of the extension headers are not shown");
}
}
static void
dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
@ -592,7 +803,7 @@ dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
guint8 first_byte;
tvbuff_t *new_tvb;
erf_type=pinfo->pseudo_header->erf.phdr.type;
erf_type=pinfo->pseudo_header->erf.phdr.type & 0x7F;
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ERF");
@ -607,6 +818,9 @@ dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
erf_tree = proto_item_add_subtree(erf_item, ett_erf);
dissect_erf_pseudo_header(tvb, pinfo, erf_tree);
if (pinfo->pseudo_header->erf.phdr.type & 0x80){
dissect_erf_pseudo_extension_header(tvb, pinfo, erf_tree);
}
}
flags = pinfo->pseudo_header->erf.phdr.flags;
@ -624,6 +838,24 @@ dissect_erf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
switch(erf_type) {
case ERF_TYPE_RAW_LINK:
call_dissector(data_handle, tvb, pinfo, erf_tree);
break;
case ERF_TYPE_IPV4:
if (ipv4_handle)
call_dissector(ipv4_handle, tvb, pinfo, erf_tree);
else
call_dissector(data_handle, tvb, pinfo, erf_tree);
break;
case ERF_TYPE_IPV6:
if (ipv6_handle)
call_dissector(ipv6_handle, tvb, pinfo, erf_tree);
else
call_dissector(data_handle, tvb, pinfo, erf_tree);
break;
case ERF_TYPE_INFINIBAND:
if (infiniband_handle)
call_dissector(infiniband_handle, tvb, pinfo, erf_tree);
@ -815,7 +1047,9 @@ proto_register_erf(void)
static hf_register_info hf[] = {
/* ERF Header */
{ &hf_erf_ts, { "Timestamp", "erf.ts", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL } },
{ &hf_erf_type, { "type", "erf.type", FT_UINT8, BASE_DEC, VALS(erf_type_vals), 0x0, "", HFILL } },
{ &hf_erf_types, { "types", "erf.types", FT_UINT8, BASE_DEC, NULL, 0xFF, "", HFILL } },
{ &hf_erf_type, { "type", "erf.types.type", FT_UINT8, BASE_DEC, VALS(erf_type_vals), 0x7F, "", HFILL } },
{ &hf_erf_ehdr, { "Extension header present", "erf.types.ext_header", FT_UINT8, BASE_DEC, NULL, 0x80, "", HFILL } },
{ &hf_erf_flags,{ "flags", "erf.flags", FT_UINT8, BASE_DEC, NULL, 0xFF, "", HFILL } },
{ &hf_erf_flags_cap,{ "capture interface", "erf.flags.cap", FT_UINT8, BASE_DEC, NULL, 0x03, "", HFILL } },
{ &hf_erf_flags_vlen,{ "varying record length", "erf.flags.vlen", FT_UINT8, BASE_DEC, NULL, 0x04, "", HFILL } },
@ -826,7 +1060,34 @@ proto_register_erf(void)
{ &hf_erf_rlen, { "record length", "erf.rlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_lctr, { "loss counter", "erf.lctr", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_wlen, { "wire length", "erf.wlen", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_t, { "Extension Type", "erf.ehdr.types", FT_UINT8, BASE_DEC, VALS(ehdr_type_vals), 0x0, "", HFILL } },
/* Intercept ID Extension Header */
{ &hf_erf_ehdr_int_res1, { "Reserved", "erf.ehdr.int.res1", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_int_id, { "Intercept ID", "erf.ehdr.int.intid", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_int_res2, { "Reserved", "erf.ehdr.int.res2", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
/* Raw Link Extension Header */
{ &hf_erf_ehdr_raw_link_res, { "Reserved", "erf.ehdr.raw.res", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_raw_link_seqnum, { "Sequence number", "erf.ehdr.raw.seqnum", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_raw_link_rate, { "Rate", "erf.ehdr.raw.rate", FT_UINT8, BASE_DEC, VALS(raw_link_rates), 0x0, "", HFILL } },
{ &hf_erf_ehdr_raw_link_type, { "Link Type", "erf.ehdr.raw.link_type", FT_UINT8, BASE_DEC, VALS(raw_link_types), 0x0, "", HFILL } },
/* Classification Extension Header */
{ &hf_erf_ehdr_class_flags, { "Flags", "erf.ehdr.class.flags", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
{ &hf_erf_ehdr_class_flags_sh, { "Search hit", "erf.ehdr.class.flags.sh", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SH_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_shm, { "Multiple search hits", "erf.ehdr.class.flags.shm", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_SHM_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_res1, { "Reserved", "erf.ehdr.class.flags.res1", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_RES1_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_user, { "User classification", "erf.ehdr.class.flags.user", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_USER_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_res2, { "Reserved", "erf.ehdr.class.flags.res2", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_RES2_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_drop, { "Drop Steering Bit", "erf.ehdr.class.flags.drop", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_DROP_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_flags_str, { "Stream Steering Bits", "erf.ehdr.class.flags.str", FT_UINT32, BASE_DEC, NULL, EHDR_CLASS_STER_MASK, "", HFILL } },
{ &hf_erf_ehdr_class_seqnum, { "Sequence number", "erf.ehdr.class.seqnum", FT_UINT32, BASE_DEC, NULL, 0x0, "", HFILL } },
/* Unknown Extension Header */
{ &hf_erf_ehdr_unk, { "Data", "erf.ehdr.unknown.data", FT_UINT64, BASE_HEX, NULL, 0x0, "", HFILL } },
/* MC HDLC Header */
{ &hf_erf_mc_hdlc_cn, { "connection number", "erf.mchdlc.cn", FT_UINT16, BASE_DEC, NULL, MC_HDLC_CN_MASK, "", HFILL } },
{ &hf_erf_mc_hdlc_res1, { "reserved", "erf.mchdlc.res1", FT_UINT16, BASE_DEC, NULL, MC_HDLC_RES1_MASK, "", HFILL } },
@ -905,6 +1166,7 @@ proto_register_erf(void)
static gint *ett[] = {
&ett_erf,
&ett_erf_pseudo_hdr,
&ett_erf_types,
&ett_erf_flags,
&ett_erf_mc_hdlc,
&ett_erf_mc_raw,
@ -971,6 +1233,11 @@ proto_reg_handoff_erf(void)
/* Dissector called to dump raw data, or unknown protocol */
data_handle = find_dissector("data");
/* Get handle for IP dissectors) */
ipv4_handle = find_dissector("ip");
ipv6_handle = find_dissector("ipv6");
/* Get handle for Infiniband dissector */
infiniband_handle = find_dissector("infiniband");

View File

@ -24,6 +24,10 @@
#ifndef __PACKET_ERF_H_
#define __PACKET_ERF_H_
#define EXT_HDR_TYPE_CLASSIFICATION 3
#define EXT_HDR_TYPE_INTERCEPTID 4
#define EXT_HDR_TYPE_RAW_LINK 5
void proto_reg_handoff_erf(void);
void proto_register_erf(void);

View File

@ -84,6 +84,8 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info _U_)
guint16 eth_hdr;
guint32 packet_size;
guint16 rlen,wlen;
guint64 erf_ext_header;
guint8 type;
size_t r;
gchar * buffer;
@ -142,7 +144,7 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info _U_)
}
/* Skip PAD records, timestamps may not be set */
if (header.type == ERF_TYPE_PAD) {
if ((header.type & 0x7F) == ERF_TYPE_PAD) {
if (file_seek(wth->fh, packet_size, SEEK_CUR, err) == -1) {
return -1;
}
@ -151,12 +153,12 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info _U_)
/* fail on invalid record type, decreasing timestamps or non-zero pad-bits */
/* Not all types within this range are decoded, but it is a first filter */
if (header.type == 0 || header.type > ERF_TYPE_MAX ) {
if ((header.type & 0x7F) == 0 || (header.type & 0x7F) > ERF_TYPE_MAX ) {
return 0;
}
/* The ERF_TYPE_MAX is the PAD record, but the last used type is ERF_TYPE_INFINIBAND */
if (header.type > ERF_TYPE_INFINIBAND) {
/* The ERF_TYPE_MAX is the PAD record, but the last used type is ERF_TYPE_RAW_LINK */
if ((header.type & 0x7F) > ERF_TYPE_RAW_LINK) {
return 0;
}
@ -174,8 +176,20 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info _U_)
memcpy(&prevts, &ts, sizeof(prevts));
/* Read over the extension headers */
type = header.type;
while (type & 0x80){
if (file_read(&erf_ext_header, 1, sizeof(erf_ext_header),wth->fh) != sizeof(erf_ext_header)) {
*err = file_error(wth->fh);
return -1;
}
packet_size -= sizeof(erf_ext_header);
memcpy(&type, &erf_ext_header, sizeof(type));
}
/* Read over MC or ETH subheader */
switch(header.type) {
switch(header.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
case ERF_TYPE_MC_RAW:
case ERF_TYPE_MC_ATM:
@ -298,7 +312,12 @@ static int erf_read_header(FILE_T fh,
guint32 *packet_size)
{
guint32 mc_hdr;
guint8 erf_exhdr[8];
guint64 erf_exhdr_sw;
guint8 type = 0;
guint16 eth_hdr,skiplen=0;
int i = 0 , max = sizeof(pseudo_header->erf.ehdr_list)/sizeof(struct erf_ehdr);
;
wtap_file_read_expected_bytes(erf_header, sizeof(*erf_header), fh, err);
if (bytes_read != NULL) {
@ -339,8 +358,25 @@ static int erf_read_header(FILE_T fh,
pseudo_header->erf.phdr.lctr = g_ntohs(erf_header->lctr);
pseudo_header->erf.phdr.wlen = g_ntohs(erf_header->wlen);
switch (erf_header->type) {
/* Copy the ERF extension header into the pseudo header */
type = erf_header->type;
while (type & 0x80){
wtap_file_read_expected_bytes(&erf_exhdr, sizeof(erf_exhdr), fh, err);
if (bytes_read != NULL)
*bytes_read += sizeof(erf_exhdr);
*packet_size -= sizeof(erf_exhdr);
skiplen += sizeof(erf_exhdr);
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));
type = erf_exhdr[0];
i++;
}
switch (erf_header->type & 0x7F) {
case ERF_TYPE_IPV4:
case ERF_TYPE_IPV6:
case ERF_TYPE_RAW_LINK:
case ERF_TYPE_INFINIBAND:
/***
if (phdr != NULL) {
@ -366,7 +402,7 @@ static int erf_read_header(FILE_T fh,
if (bytes_read != NULL)
*bytes_read += sizeof(eth_hdr);
*packet_size -= sizeof(eth_hdr);
skiplen = sizeof(eth_hdr);
skiplen += sizeof(eth_hdr);
pseudo_header->erf.subhdr.eth_hdr = g_htons(eth_hdr);
break;
@ -381,7 +417,7 @@ static int erf_read_header(FILE_T fh,
if (bytes_read != NULL)
*bytes_read += sizeof(mc_hdr);
*packet_size -= sizeof(mc_hdr);
skiplen = sizeof(mc_hdr);
skiplen += sizeof(mc_hdr);
pseudo_header->erf.subhdr.mc_hdr = g_htonl(mc_hdr);
break;

View File

@ -59,6 +59,9 @@
#define ERF_TYPE_COLOR_MC_HDLC_POS 17
#define ERF_TYPE_AAL2 18
#define ERF_TYPE_INFINIBAND 21
#define ERF_TYPE_IPV4 22
#define ERF_TYPE_IPV6 23
#define ERF_TYPE_RAW_LINK 24
#define ERF_TYPE_PAD 48

View File

@ -166,6 +166,8 @@ 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,
@ -620,6 +622,7 @@ static libpcap_try_t libpcap_try(wtap *wth, int *err)
* pcaprec_ss990915_hdr is the largest header type.
*/
struct pcaprec_ss990915_hdr first_rec_hdr, second_rec_hdr;
/*
* Attempt to read the first record's header.
@ -990,16 +993,27 @@ static gboolean libpcap_read(wtap *wth, int *err, gchar **err_info,
packet_size -= sizeof(struct erf_phdr);
wth->data_offset += sizeof(struct erf_phdr);
if (!libpcap_read_erf_subheader(wth->fh, &wth->pseudo_header,
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:
@ -1079,7 +1093,6 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
int *err, gchar **err_info)
{
guint size;
if (file_seek(wth->random_fh, seek_off, SEEK_SET, err) == -1)
return FALSE;
@ -1173,9 +1186,17 @@ libpcap_seek_read(wtap *wth, gint64 seek_off,
case WTAP_ENCAP_ERF:
if (!libpcap_read_erf_pseudoheader(wth->random_fh, NULL, pseudo_header,
err, err_info)) {
/* Read error */
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)) {
@ -1710,7 +1731,7 @@ libpcap_get_erf_subheader(const guint8 *erf_subhdr,
union wtap_pseudo_header *pseudo_header, guint * psize)
{
*psize=0;
switch(pseudo_header->erf.phdr.type) {
switch(pseudo_header->erf.phdr.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
case ERF_TYPE_MC_RAW:
case ERF_TYPE_MC_ATM:
@ -1736,6 +1757,41 @@ libpcap_get_erf_subheader(const guint8 *erf_subhdr,
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
@ -1748,7 +1804,7 @@ libpcap_read_erf_subheader(FILE_T fh, union wtap_pseudo_header *pseudo_header,
int bytes_read;
*psize=0;
switch(pseudo_header->erf.phdr.type) {
switch(pseudo_header->erf.phdr.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
case ERF_TYPE_MC_RAW:
case ERF_TYPE_MC_ATM:
@ -1983,7 +2039,8 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
case WTAP_ENCAP_ERF:
hdrsize = sizeof (struct erf_phdr);
switch(pseudo_header->erf.phdr.type) {
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:
@ -2251,7 +2308,7 @@ static gboolean libpcap_dump(wtap_dumper *wdh,
phtons(&erf_hdr[14], pseudo_header->erf.phdr.wlen);
size = sizeof(struct erf_phdr);
switch(pseudo_header->erf.phdr.type) {
switch(pseudo_header->erf.phdr.type & 0x7F) {
case ERF_TYPE_MC_HDLC:
case ERF_TYPE_MC_RAW:
case ERF_TYPE_MC_ATM:

View File

@ -648,12 +648,17 @@ struct erf_phdr {
guint16 wlen;
};
struct erf_ehdr {
guint64 ehdr;
};
/*
* ERF pseudo header with optional subheader
* (Multichannel or Ethernet)
*/
struct erf_mc_phdr {
struct erf_phdr phdr;
struct erf_ehdr ehdr_list[8];
union
{
guint16 eth_hdr;