forked from osmocom/wireshark
From Francesco Fusco:
Endace ERFII (extension header) support. svn path=/trunk/; revision=26287
This commit is contained in:
parent
3a26e89362
commit
637761d295
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue