From Francesco Fondelli: fixes up issue 1) and 3) described in the bug report https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7089

svn path=/trunk/; revision=42112
This commit is contained in:
Anders Broman 2012-04-17 20:49:56 +00:00
parent 4a530904f8
commit 3a95e4cd8b
2 changed files with 233 additions and 184 deletions

View File

@ -544,6 +544,8 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
proto_item *ti;
tvbuff_t *next_tvb;
struct mplsinfo mplsinfo;
int found = 0;
guint8 first_nibble;
col_set_str(pinfo->cinfo, COL_PROTOCOL, "MPLS");
@ -606,61 +608,85 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
return;
}
else
g_strlcpy(PW_ACH,"PW Associated Channel Header",50);
g_strlcpy(PW_ACH,"PW Associated Channel Header",50);
if (bos) break;
}
first_nibble = (tvb_get_guint8(tvb, offset) >> 4) & 0x0F;
next_tvb = tvb_new_subset_remaining(tvb, offset);
if ( !dissector_try_uint(mpls_subdissector_table, label, next_tvb, pinfo, tree))
{
switch ( mpls_default_payload )
{
case MDD_PW_SATOP:
call_dissector(dissector_pw_satop, next_tvb, pinfo, tree);
break;
case MDD_PW_CESOPSN:
call_dissector(dissector_pw_cesopsn, next_tvb, pinfo, tree);
break;
case MDD_PW_ETH_HEUR:
call_dissector(dissector_pw_eth_heuristic, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_FR_DLCI:
call_dissector(dissector_pw_fr, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_HDLC_NOCW_FRPORT:
call_dissector(dissector_pw_hdlc_nocw_fr, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP:
call_dissector(dissector_pw_hdlc_nocw_hdlc_ppp,next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ETH_CW:
call_dissector(dissector_pw_eth_cw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ETH_NOCW:
call_dissector(dissector_pw_eth_nocw, next_tvb, pinfo, tree);
break;
case MDD_ITDM:
call_dissector(dissector_itdm, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_N1_CW:
call_dissector(dissector_mpls_pw_atm_n1_cw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_N1_NOCW:
call_dissector(dissector_mpls_pw_atm_n1_nocw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_11_OR_AAL5_PDU:
call_dissector(dissector_mpls_pw_atm_11_aal5pdu, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_AAL5_SDU:
call_dissector(dissector_mpls_pw_atm_aal5_sdu, next_tvb, pinfo, tree);
break;
default: /*fallthrough*/
case MDD_MPLS_PW_GENERIC:
dissect_pw_mcw(next_tvb, pinfo, tree);
break;
}
/* 1) explicit label-to-dissector binding ? */
found = dissector_try_uint(mpls_subdissector_table, label,
next_tvb, pinfo, tree);
if (found)
return;
/* 2) use the 1st nibble logic (see BCP 4928, RFC 4385 and 5586) */
if (first_nibble == 4) {
call_dissector(dissector_ip, next_tvb, pinfo, tree);
return;
} else if (first_nibble == 6) {
call_dissector(dissector_ipv6, next_tvb, pinfo, tree);
return;
} else if (first_nibble == 1) {
dissect_pw_ach(next_tvb, pinfo, tree);
return;
} else if (first_nibble == 0) {
/*
* FF: it should be a PW with a CW but... it's not
* guaranteed (e.g. an Ethernet PW w/o CW and a DA MAC
* address like 00:xx:xx:xx:xx:xx). So, let the user and
* eventually any further PW heuristics decide.
*/
}
/* 3) use the mpls_default_payload info from user */
switch (mpls_default_payload) {
case MDD_PW_SATOP:
call_dissector(dissector_pw_satop, next_tvb, pinfo, tree);
break;
case MDD_PW_CESOPSN:
call_dissector(dissector_pw_cesopsn, next_tvb, pinfo, tree);
break;
case MDD_PW_ETH_HEUR:
call_dissector(dissector_pw_eth_heuristic, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_FR_DLCI:
call_dissector(dissector_pw_fr, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_HDLC_NOCW_FRPORT:
call_dissector(dissector_pw_hdlc_nocw_fr, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_HDLC_NOCW_HDLC_PPP:
call_dissector(dissector_pw_hdlc_nocw_hdlc_ppp,next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ETH_CW:
call_dissector(dissector_pw_eth_cw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ETH_NOCW:
call_dissector(dissector_pw_eth_nocw, next_tvb, pinfo, tree);
break;
case MDD_ITDM:
call_dissector(dissector_itdm, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_N1_CW:
call_dissector(dissector_mpls_pw_atm_n1_cw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_N1_NOCW:
call_dissector(dissector_mpls_pw_atm_n1_nocw, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_11_OR_AAL5_PDU:
call_dissector(dissector_mpls_pw_atm_11_aal5pdu, next_tvb, pinfo, tree);
break;
case MDD_MPLS_PW_ATM_AAL5_SDU:
call_dissector(dissector_mpls_pw_atm_aal5_sdu, next_tvb, pinfo, tree);
break;
default: /* fallthrough */
case MDD_MPLS_PW_GENERIC:
dissect_pw_mcw(next_tvb, pinfo, tree);
break;
}
}

View File

@ -1,5 +1,5 @@
/* packet-pw-eth.c
* Routines for ethernet PW dissection: it should be conform to RFC 4448.
* Routines for ethernet PW dissection: it should conform to RFC 4448.
*
* Copyright 2008 _FF_
*
@ -54,75 +54,80 @@ static dissector_handle_t pw_eth_handle_nocw;
static void
dissect_pw_eth_cw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *pw_eth_tree = NULL;
proto_item *ti = NULL;
tvbuff_t *next_tvb = NULL;
guint16 sequence_number = 0;
proto_tree *pw_eth_tree = NULL;
proto_item *ti = NULL;
tvbuff_t *next_tvb = NULL;
guint16 sequence_number = 0;
if (tvb_reported_length_remaining(tvb, 0) < 4) {
if (tree)
proto_tree_add_text(tree, tvb, 0, -1,
"Error processing Message");
return;
}
if (tvb_reported_length_remaining(tvb, 0) < 4) {
if (tree)
proto_tree_add_text(tree, tvb, 0, -1,
"Error processing Message");
return;
}
if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
return;
if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
return;
sequence_number = tvb_get_ntohs(tvb, 2);
if (tree) {
ti = proto_tree_add_boolean(tree, hf_pw_eth_cw,
tvb, 0, 0, TRUE);
PROTO_ITEM_SET_HIDDEN(ti);
ti = proto_tree_add_item(tree, proto_pw_eth_cw,
tvb, 0, 4, ENC_NA);
pw_eth_tree = proto_item_add_subtree(ti, ett_pw_eth);
if (pw_eth_tree == NULL)
return;
proto_tree_add_uint_format(pw_eth_tree,
hf_pw_eth_cw_sequence_number,
tvb, 2, 2, sequence_number,
"Sequence Number: %d",
sequence_number);
}
next_tvb = tvb_new_subset_remaining(tvb, 4);
{
/*
* When Ethernet frames being decoded, pinfo->ethertype is extracted
* from the top-level Ethernet frame. Dissection of Ethernet PW payload
* overwrites this value as the same dissector is invoked again.
* This may lead to undesired behavior (like disappearance of "Link"
* tab from the "Decode as" menu).
*
* Let's save/restore ethertype. --ATA
*
* XXX it looks that more pinfo members (or even the whole pinfo)
* XXX should be saved/restored in PW cases. Multilayer encapsulations,
* XXX like ethernet/mpls/ethernet-pw/ip/vlan, may lead to undesired
* XXX changes if pinfo->ipproto, ptype etc.
*/
guint32 etype_save = pinfo->ethertype;
call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
pinfo->ethertype = etype_save;
}
sequence_number = tvb_get_ntohs(tvb, 2);
if (tree) {
ti = proto_tree_add_boolean(tree, hf_pw_eth_cw,
tvb, 0, 0, TRUE);
PROTO_ITEM_SET_HIDDEN(ti);
ti = proto_tree_add_item(tree, proto_pw_eth_cw,
tvb, 0, 4, ENC_NA);
pw_eth_tree = proto_item_add_subtree(ti, ett_pw_eth);
if (pw_eth_tree == NULL)
return;
proto_tree_add_uint_format(pw_eth_tree,
hf_pw_eth_cw_sequence_number,
tvb, 2, 2, sequence_number,
"Sequence Number: %d",
sequence_number);
}
next_tvb = tvb_new_subset_remaining(tvb, 4);
{
/*
* When Ethernet frames being decoded, pinfo->ethertype is extracted
* from the top-level Ethernet frame. Dissection of Ethernet PW payload
* overwrites this value as the same dissector is invoked again.
* This may lead to undesired behavior (like disappearance of "Link"
* tab from the "Decode as" menu).
*
* Let's save/restore ethertype. --ATA
*
* XXX it looks that more pinfo members (or even the whole pinfo)
* XXX should be saved/restored in PW cases. Multilayer encapsulations,
* XXX like ethernet/mpls/ethernet-pw/ip/vlan, may lead to undesired
* XXX changes if pinfo->ipproto, ptype etc.
*/
guint32 etype_save = pinfo->ethertype;
call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
pinfo->ethertype = etype_save;
}
}
static void
dissect_pw_eth_nocw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
tvbuff_t *next_tvb = NULL;
proto_item *ti = NULL;
tvbuff_t *next_tvb = NULL;
proto_item *ti = NULL;
if (tree) {
ti = proto_tree_add_boolean(tree, hf_pw_eth, tvb, 0, 0, TRUE);
PROTO_ITEM_SET_HIDDEN(ti);
}
next_tvb = tvb_new_subset_remaining(tvb, 0);
{
guint32 etype_save = pinfo->ethertype;
call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
pinfo->ethertype = etype_save;
}
if (tree) {
ti = proto_tree_add_boolean(tree, hf_pw_eth, tvb, 0, 0, TRUE);
PROTO_ITEM_SET_HIDDEN(ti);
}
next_tvb = tvb_new_subset_remaining(tvb, 0);
{
guint32 etype_save = pinfo->ethertype;
call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
pinfo->ethertype = etype_save;
}
}
/*
@ -132,101 +137,119 @@ dissect_pw_eth_nocw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
static gboolean
looks_like_plain_eth(tvbuff_t *tvb _U_)
{
const gchar *manuf_name_da = NULL;
const gchar *manuf_name_sa = NULL;
if (tvb_reported_length_remaining(tvb, 0) < 14) {
return FALSE;
}
manuf_name_da = tvb_get_manuf_name_if_known(tvb, 0);
manuf_name_sa = tvb_get_manuf_name_if_known(tvb, 6);
if (manuf_name_da && manuf_name_sa) {
return TRUE;
}
const gchar *manuf_name_da = NULL;
const gchar *manuf_name_sa = NULL;
if (tvb_reported_length_remaining(tvb, 0) < 14) {
return FALSE;
}
manuf_name_da = tvb_get_manuf_name_if_known(tvb, 0);
manuf_name_sa = tvb_get_manuf_name_if_known(tvb, 6);
if (manuf_name_da && manuf_name_sa) {
return TRUE;
}
return FALSE;
}
static void
dissect_pw_eth_heuristic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
if (looks_like_plain_eth(tvb)) {
call_dissector(pw_eth_handle_nocw, tvb, pinfo, tree);
} else {
call_dissector(pw_eth_handle_cw, tvb, pinfo, tree);
}
guint8 first_nibble = (tvb_get_guint8(tvb, 0) >> 4) & 0x0F;
if (looks_like_plain_eth(tvb)) {
call_dissector(pw_eth_handle_nocw, tvb, pinfo, tree);
}
if (first_nibble == 0)
call_dissector(pw_eth_handle_cw, tvb, pinfo, tree);
else
call_dissector(pw_eth_handle_nocw, tvb, pinfo, tree);
}
void
proto_register_pw_eth(void)
{
static hf_register_info hf[] = {
{
&hf_pw_eth,
{
"PW (ethernet)",
"pweth", FT_BOOLEAN,
BASE_NONE, NULL, 0x0, NULL, HFILL
}
},
{
&hf_pw_eth_cw,
{
"PW Control Word (ethernet)",
"pweth.cw", FT_BOOLEAN,
BASE_NONE, NULL, 0x0, NULL, HFILL
}
},
{
&hf_pw_eth_cw_sequence_number,
{
"PW sequence number (ethernet)",
"pweth.cw.sequence_number", FT_UINT16,
BASE_DEC, NULL, 0x0, NULL, HFILL
}
}
};
static hf_register_info hf[] = {
{
&hf_pw_eth,
{
"PW (ethernet)",
"pweth", FT_BOOLEAN,
BASE_NONE, NULL, 0x0, NULL, HFILL
}
},
{
&hf_pw_eth_cw,
{
"PW Control Word (ethernet)",
"pweth.cw", FT_BOOLEAN,
BASE_NONE, NULL, 0x0, NULL, HFILL
}
},
{
&hf_pw_eth_cw_sequence_number,
{
"PW sequence number (ethernet)",
"pweth.cw.sequence_number", FT_UINT16,
BASE_DEC, NULL, 0x0, NULL, HFILL
}
}
};
static gint *ett[] = {
&ett_pw_eth
};
static gint *ett[] = {
&ett_pw_eth
};
proto_pw_eth_cw =
proto_register_protocol("PW Ethernet Control Word",
"Ethernet PW (with CW)",
"pwethcw");
proto_pw_eth_nocw =
proto_register_protocol("Ethernet PW (no CW)", /* not displayed */
"Ethernet PW (no CW)",
"pwethnocw");
proto_pw_eth_heuristic =
proto_register_protocol("Ethernet PW (CW heuristic)", /* not disp. */
"Ethernet PW (CW heuristic)",
"pwethheuristic");
proto_register_field_array(proto_pw_eth_cw, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("pw_eth_cw", dissect_pw_eth_cw, proto_pw_eth_cw);
register_dissector("pw_eth_nocw", dissect_pw_eth_nocw,
proto_pw_eth_nocw);
register_dissector("pw_eth_heuristic", dissect_pw_eth_heuristic,
proto_pw_eth_heuristic);
proto_pw_eth_cw =
proto_register_protocol("PW Ethernet Control Word",
"Ethernet PW (with CW)",
"pwethcw");
proto_pw_eth_nocw =
proto_register_protocol("Ethernet PW (no CW)", /* not displayed */
"Ethernet PW (no CW)",
"pwethnocw");
proto_pw_eth_heuristic =
proto_register_protocol("Ethernet PW (CW heuristic)", /* not disp. */
"Ethernet PW (CW heuristic)",
"pwethheuristic");
proto_register_field_array(proto_pw_eth_cw, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
register_dissector("pw_eth_cw", dissect_pw_eth_cw, proto_pw_eth_cw);
register_dissector("pw_eth_nocw", dissect_pw_eth_nocw,
proto_pw_eth_nocw);
register_dissector("pw_eth_heuristic", dissect_pw_eth_heuristic,
proto_pw_eth_heuristic);
}
void
proto_reg_handoff_pw_eth(void)
{
dissector_handle_t pw_eth_handle_heuristic;
dissector_handle_t pw_eth_handle_heuristic;
eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
eth_withoutfcs_handle = find_dissector("eth_withoutfcs");
pw_eth_handle_cw = find_dissector("pw_eth_cw");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_cw);
pw_eth_handle_cw = find_dissector("pw_eth_cw");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_cw);
pw_eth_handle_nocw = find_dissector("pw_eth_nocw");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_nocw);
pw_eth_handle_nocw = find_dissector("pw_eth_nocw");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_nocw);
pw_eth_handle_heuristic = find_dissector("pw_eth_heuristic");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_heuristic);
pw_eth_handle_heuristic = find_dissector("pw_eth_heuristic");
dissector_add_uint("mpls.label", LABEL_INVALID, pw_eth_handle_heuristic);
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/