aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnders Broman <anders.broman@ericsson.com>2009-06-29 19:24:14 +0000
committerAnders Broman <anders.broman@ericsson.com>2009-06-29 19:24:14 +0000
commita98ce52e800e19c9920a69f6519ff728a0122d06 (patch)
tree36b9053c7004578238521b8d0194f95c171c44e9
parenta539aa732c522c40d888d6274997fda01b6cd6f8 (diff)
From Artem Tamazov:
Added: PW ATM 1:1, AAL5 SDU, AAL5 PDU support + BFD fix + PW ATM OAM fix svn path=/trunk/; revision=28881
-rw-r--r--epan/dissectors/Makefile.common1
-rw-r--r--epan/dissectors/packet-atm.c234
-rw-r--r--epan/dissectors/packet-atm.h4
-rw-r--r--epan/dissectors/packet-bfd.c1
-rw-r--r--epan/dissectors/packet-mpls.c176
-rw-r--r--epan/dissectors/packet-pw-atm.c2418
-rw-r--r--epan/dissectors/packet-pw-atm.h101
-rw-r--r--epan/dissectors/packet-pw-cesopsn.c26
-rw-r--r--epan/dissectors/packet-pw-common.c72
-rw-r--r--epan/dissectors/packet-pw-common.h18
-rw-r--r--epan/dissectors/packet-pw-satop.c28
-rw-r--r--epan/packet_info.h22
12 files changed, 2410 insertions, 691 deletions
diff --git a/epan/dissectors/Makefile.common b/epan/dissectors/Makefile.common
index 59a9cbdb06..092b939398 100644
--- a/epan/dissectors/Makefile.common
+++ b/epan/dissectors/Makefile.common
@@ -1151,6 +1151,7 @@ DISSECTOR_INCLUDES = \
packet-ppi.h \
packet-ppp.h \
packet-pres.h \
+ packet-pw-atm.h \
packet-pw-common.h \
packet-q931.h \
packet-q932.h \
diff --git a/epan/dissectors/packet-atm.c b/epan/dissectors/packet-atm.c
index e4585a1479..cc301de2b0 100644
--- a/epan/dissectors/packet-atm.c
+++ b/epan/dissectors/packet-atm.c
@@ -39,6 +39,7 @@
#include "packet-tr.h"
#include "packet-llc.h"
#include "prefs.h"
+#include "packet-pw-atm.h"
static int proto_atm = -1;
static int hf_atm_aal = -1;
@@ -50,7 +51,6 @@ static int proto_ilmi = -1;
static int proto_aal1 = -1;
static int proto_aal3_4 = -1;
static int proto_oamaal = -1;
-static int proto_atm_4717 = -1;
static gint ett_atm = -1;
static gint ett_atm_lane = -1;
@@ -934,6 +934,13 @@ dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvbuff_t *next_tvb;
guint32 crc;
guint32 calc_crc;
+ /*
+ * ATM dissector is used as "sub-dissector" for ATM pseudowires.
+ * In such cases, pinfo->private_data is used to pass info from/to
+ * PW dissector to ATM dissector. For decoding normal ATM traffic
+ * private_data should be NULL.
+ */
+ gboolean pseudowire_mode = (NULL != pinfo->private_data);
/*
* This is reassembled traffic, so the cell headers are missing;
@@ -965,20 +972,21 @@ dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
}
}
- proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
+ if (!pseudowire_mode) {
+ proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 0,
pinfo->pseudo_header->atm.vpi);
- proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
+ proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 0, 0,
pinfo->pseudo_header->atm.vci);
- /* Also show vpi/vci in info column */
- if (check_col(pinfo->cinfo, COL_INFO))
- {
+ /* Also show vpi/vci in info column */
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
col_append_fstr(pinfo->cinfo, COL_INFO, " VPI=%u, VCI=%u",
pinfo->pseudo_header->atm.vpi,
pinfo->pseudo_header->atm.vci);
+ }
}
-
next_tvb = tvb;
if (truncated) {
/*
@@ -1120,7 +1128,13 @@ dissect_reassembled_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb_memcpy(next_tvb, octet, 0, sizeof(octet));
decoded = TRUE;
- if ((pntohs(octet) & 0xff) == PPP_IP)
+ if (octet[0] == 0xaa
+ && octet[1] == 0xaa
+ && octet[2] == 0x03) /* LLC SNAP as per RFC2684 */
+ {
+ call_dissector(llc_handle, next_tvb, pinfo, tree);
+ }
+ else if ((pntohs(octet) & 0xff) == PPP_IP)
{
call_dissector(ppp_handle, next_tvb, pinfo, tree);
}
@@ -1413,13 +1427,14 @@ get_header_err(const guint8 *cell_header)
return UNCORRECTIBLE_ERROR;
}
-static const value_string pt_vals[] = {
+const value_string atm_pt_vals[] = {
{ 0, "User data cell, congestion not experienced, SDU-type = 0" },
{ 1, "User data cell, congestion not experienced, SDU-type = 1" },
{ 2, "User data cell, congestion experienced, SDU-type = 0" },
{ 3, "User data cell, congestion experienced, SDU-type = 1" },
{ 4, "Segment OAM F5 flow related cell" },
{ 5, "End-to-end OAM F5 flow related cell" },
+ { 6, "VC resource management cell" },
{ 0, NULL }
};
@@ -1522,6 +1537,19 @@ static const value_string ft_ad_vals[] = {
{ 0, NULL }
};
+
+/*
+ * Check for OAM cells.
+ * OAM F4 is VCI 3 or 4 and PT 0X0.
+ * OAM F5 is PT 10X.
+ */
+gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt)
+{
+ return (((vci == 3 || vci == 4) && ((pt & 0x5) == 0))
+ || ((pt & 0x6) == 0x4));
+}
+
+
static void
dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *atm_tree, guint aal, gboolean nni,
@@ -1540,8 +1568,10 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
gint length;
guint16 crc10;
tvbuff_t *next_tvb;
+ const pwatm_private_data_t * pwpd = pinfo->private_data;
- if (!nni) {
+ if (NULL == pwpd) {
+ if (!nni) {
/*
* FF: ITU-T I.361 (Section 2.2) defines the cell header format
* and encoding at UNI reference point as:
@@ -1565,7 +1595,7 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
octet = tvb_get_guint8(tvb, 1);
vpi |= octet >> 4;
proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
- } else {
+ } else {
/*
* FF: ITU-T I.361 (Section 2.3) defines the cell header format
* and encoding at NNI reference point as:
@@ -1588,21 +1618,21 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
octet = tvb_get_guint8(tvb, 1);
vpi |= (octet & 0xF0) >> 4;
proto_tree_add_uint(atm_tree, hf_atm_vpi, tvb, 0, 2, vpi);
- }
+ }
- vci = (octet & 0x0F) << 12;
- octet = tvb_get_guint8(tvb, 2);
- vci |= octet << 4;
- octet = tvb_get_guint8(tvb, 3);
- vci |= octet >> 4;
- proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
- pt = (octet >> 1) & 0x7;
- proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
- val_to_str(pt, pt_vals, "Unknown (%u)"));
- proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
+ vci = (octet & 0x0F) << 12;
+ octet = tvb_get_guint8(tvb, 2);
+ vci |= octet << 4;
+ octet = tvb_get_guint8(tvb, 3);
+ vci |= octet >> 4;
+ proto_tree_add_uint(atm_tree, hf_atm_vci, tvb, 1, 3, vci);
+ pt = (octet >> 1) & 0x7;
+ proto_tree_add_text(atm_tree, tvb, 3, 1, "Payload Type: %s",
+ val_to_str(pt, atm_pt_vals, "Unknown (%u)"));
+ proto_tree_add_text(atm_tree, tvb, 3, 1, "Cell Loss Priority: %s",
(octet & 0x01) ? "Low priority" : "High priority");
-
- if (!crc_stripped) {
+
+ if (!crc_stripped) {
/*
* FF: parse the Header Error Check (HEC).
*/
@@ -1617,13 +1647,22 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
else
proto_item_append_text(ti, " (error in bit %d)", err);
offset = 5;
- } else {
+ } else {
/*
* FF: in some encapsulation modes (e.g. RFC 4717, ATM N-to-One
* Cell Mode) the Header Error Check (HEC) field is stripped.
* So we do nothing here.
*/
offset = 4;
+ }
+ }
+ else
+ {
+ offset = 0; /* For PWs. Header is decoded by PW dissector.*/
+ pwpd = pinfo->private_data;
+ vpi = pwpd->vpi;
+ vci = pwpd->vci;
+ pt = pwpd->pti;
}
/*
@@ -1632,13 +1671,9 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
* Wiretap got from the file?
*/
if (aal == AAL_USER) {
- /*
- * OAM F4 is VCI 3 or 4 and PT 0X0.
- * OAM F5 is PT 10X.
- */
- if (((vci == 3 || vci == 4) && ((pt & 0x5) == 0)) ||
- ((pt & 0x6) == 0x4))
- aal = AAL_OAMCELL;
+ if (atm_is_oam_cell(vci,pt)) {
+ aal = AAL_OAMCELL;
+ }
}
switch (aal) {
@@ -1706,16 +1741,22 @@ dissect_atm_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
case AAL_OAMCELL:
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
- if (check_col(pinfo->cinfo, COL_INFO))
- col_clear(pinfo->cinfo, COL_INFO);
+ if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
+ {
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OAM AAL");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
+ }
ti = proto_tree_add_item(tree, proto_oamaal, tvb, offset, -1, FALSE);
aal_tree = proto_item_add_subtree(ti, ett_oamaal);
octet = tvb_get_guint8(tvb, offset);
- if (check_col(pinfo->cinfo, COL_INFO))
- col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
+ if (NULL == pwpd || pwpd->enable_fill_columns_by_atm_dissector)
+ {
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s",
val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
+ }
proto_tree_add_text(aal_tree, tvb, offset, 1, "OAM Type: %s",
val_to_str(octet >> 4, oam_type_vals, "Unknown (%u)"));
switch (octet >> 4) {
@@ -1767,6 +1808,7 @@ dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
{
proto_tree *atm_tree = NULL;
proto_item *atm_ti = NULL;
+ gboolean pseudowire_mode = (NULL != pinfo->private_data);
if ( pinfo->pseudo_header->atm.aal == AAL_5 &&
pinfo->pseudo_header->atm.type == TRAF_LANE &&
@@ -1777,23 +1819,25 @@ dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
- switch (pinfo->pseudo_header->atm.channel) {
+ if (!pseudowire_mode) {
+ switch (pinfo->pseudo_header->atm.channel) {
- case 0:
- /* Traffic from DTE to DCE. */
- if (check_col(pinfo->cinfo, COL_RES_DL_DST))
- col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
- if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
- col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
- break;
+ case 0:
+ /* Traffic from DTE to DCE. */
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
+ break;
- case 1:
- /* Traffic from DCE to DTE. */
- if (check_col(pinfo->cinfo, COL_RES_DL_DST))
- col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
- if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
- col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
- break;
+ case 1:
+ /* Traffic from DCE to DTE. */
+ if (check_col(pinfo->cinfo, COL_RES_DL_DST))
+ col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
+ if (check_col(pinfo->cinfo, COL_RES_DL_SRC))
+ col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
+ break;
+ }
}
if (check_col(pinfo->cinfo, COL_INFO)) {
@@ -1812,23 +1856,25 @@ dissect_atm_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
- switch (pinfo->pseudo_header->atm.channel) {
+ if (!pseudowire_mode) {
+ switch (pinfo->pseudo_header->atm.channel) {
- case 0:
- /* Traffic from DTE to DCE. */
- proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
- break;
+ case 0:
+ /* Traffic from DTE to DCE. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DTE->DCE");
+ break;
- case 1:
- /* Traffic from DCE to DTE. */
- proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
- break;
+ case 1:
+ /* Traffic from DCE to DTE. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: DCE->DTE");
+ break;
- default:
- /* Sniffers shouldn't provide anything other than 0 or 1. */
- proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
+ default:
+ /* Sniffers shouldn't provide anything other than 0 or 1. */
+ proto_tree_add_text(atm_tree, tvb, 0, 0, "Channel: %u",
pinfo->pseudo_header->atm.channel);
- break;
+ break;
+ }
}
proto_tree_add_uint_format_value(atm_tree, hf_atm_aal, tvb, 0, 0,
@@ -1865,59 +1911,21 @@ dissect_atm_oam_cell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
proto_tree *atm_tree = NULL;
proto_item *atm_ti = NULL;
+ gboolean pseudowire_mode = (NULL != pinfo->private_data);
if (check_col(pinfo->cinfo, COL_PROTOCOL))
col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
- if (tree) {
- atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
- atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
+ if (!pseudowire_mode) {
+ if (tree) {
+ atm_ti = proto_tree_add_protocol_format(tree, proto_atm, tvb, 0, 0, "ATM");
+ atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
+ }
}
dissect_atm_cell(tvb, pinfo, tree, atm_tree, AAL_OAMCELL, FALSE, FALSE);
}
-/*
- * FF: this dissector is called directly from packet-pw-atm.c.
- * it checks pinfo->pw_atm_encap_type, pinfo->pw_atm_flags
- * in order to gather information about the used encapsulation
- * format (defined in RFC 4717). The result (i.e. protocol tree
- * and cinfo) of this dissector should look like, as close as
- * possible, to the legacy one (i.e. dissect_atm_[untruncated|oam_cell]).
- */
-static void
-dissect_atm_4717(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- proto_tree *atm_tree = NULL;
- proto_item *atm_ti = NULL;
-
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATM");
-
- if (tree) {
- atm_ti = proto_tree_add_protocol_format(tree,
- proto_atm,
- tvb, 0, 0, "ATM");
- atm_tree = proto_item_add_subtree(atm_ti, ett_atm);
- }
-
- switch (pinfo->pw_atm_encap_type) {
- case 1: /* ATM N-to-One Cell Mode */
- if (check_col(pinfo->cinfo, COL_INFO)) {
- col_add_str(pinfo->cinfo, COL_INFO, "Unknown AAL");
- col_append_fstr(pinfo->cinfo, COL_INFO,
- " (%u cell%s)",
- pinfo->pw_atm_ncells,
- pinfo->pw_atm_ncells == 1 ? "" : "s");
- }
- proto_item_set_len(atm_ti, 4);
- dissect_atm_cell(tvb, pinfo, tree, atm_tree,
- AAL_UNKNOWN, TRUE, TRUE);
- break;
- default:
- break;
- }
-}
void
proto_register_atm(void)
@@ -1971,8 +1979,8 @@ proto_register_atm(void)
register_dissector("lane", dissect_lane, proto_atm_lane);
register_dissector("atm_untruncated", dissect_atm_untruncated, proto_atm);
+ register_dissector("atm_truncated", dissect_atm, proto_atm);
register_dissector("atm_oam_cell", dissect_atm_oam_cell, proto_oamaal);
- register_dissector("atm_4717", dissect_atm_4717, proto_atm_4717);
atm_module = prefs_register_protocol ( proto_atm, NULL );
prefs_register_bool_preference ( atm_module, "dissect_lane_as_sscop", "Dissect LANE as SSCOP",
@@ -1983,7 +1991,7 @@ proto_register_atm(void)
void
proto_reg_handoff_atm(void)
{
- dissector_handle_t atm_handle, atm_untruncated_handle, atm_4717_handle;
+ dissector_handle_t atm_handle, atm_untruncated_handle;
/*
* Get handles for the Ethernet, Token Ring, Frame Relay, LLC,
@@ -2009,6 +2017,4 @@ proto_reg_handoff_atm(void)
proto_atm);
dissector_add("wtap_encap", WTAP_ENCAP_ATM_PDUS_UNTRUNCATED,
atm_untruncated_handle);
-
- atm_4717_handle = create_dissector_handle(dissect_atm_4717, proto_atm);
}
diff --git a/epan/dissectors/packet-atm.h b/epan/dissectors/packet-atm.h
index 2c6f04213a..466d54972a 100644
--- a/epan/dissectors/packet-atm.h
+++ b/epan/dissectors/packet-atm.h
@@ -27,4 +27,8 @@
void capture_atm(const union wtap_pseudo_header *, const guchar *, int,
packet_counts *);
+gboolean atm_is_oam_cell(const guint16 vci, const guint8 pt); /*For pw-atm dissector*/
+
+extern const value_string atm_pt_vals[]; /*For pw-atm dissector*/
+
#endif
diff --git a/epan/dissectors/packet-bfd.c b/epan/dissectors/packet-bfd.c
index 2b82c4237e..7d564a26ac 100644
--- a/epan/dissectors/packet-bfd.c
+++ b/epan/dissectors/packet-bfd.c
@@ -685,6 +685,7 @@ void proto_register_bfd(void)
proto_bfd = proto_register_protocol("Bidirectional Forwarding Detection Control Message",
"BFD Control",
"bfd");
+ register_dissector("bfd", dissect_bfd_control, proto_bfd);
/* Required function calls to register the header fields and subtrees used */
proto_register_field_array(proto_bfd, hf, array_length(hf));
diff --git a/epan/dissectors/packet-mpls.c b/epan/dissectors/packet-mpls.c
index 024fbe0d4f..6d77b1e803 100644
--- a/epan/dissectors/packet-mpls.c
+++ b/epan/dissectors/packet-mpls.c
@@ -58,6 +58,7 @@
#include <epan/addr_resolv.h>
#include "packet-ppp.h"
#include "packet-mpls.h"
+#include "packet-pw-common.h"
static gint proto_mpls = -1;
static gint proto_pw_ach = -1;
@@ -92,6 +93,7 @@ enum mpls_filter_keys {
static dissector_handle_t dissector_data;
static dissector_handle_t dissector_ipv6;
static dissector_handle_t dissector_ip;
+static dissector_handle_t dissector_bfd;
static dissector_handle_t dissector_pw_eth_heuristic;
static dissector_handle_t dissector_pw_fr;
static dissector_handle_t dissector_pw_hdlc_nocw_fr;
@@ -100,6 +102,10 @@ static dissector_handle_t dissector_pw_eth_cw;
static dissector_handle_t dissector_pw_eth_nocw;
static dissector_handle_t dissector_pw_satop;
static dissector_handle_t dissector_itdm;
+static dissector_handle_t dissector_mpls_pw_atm_n1_cw;
+static dissector_handle_t dissector_mpls_pw_atm_n1_nocw;
+static dissector_handle_t dissector_mpls_pw_atm_11_aal5pdu;
+static dissector_handle_t dissector_mpls_pw_atm_aal5_sdu;
static dissector_handle_t dissector_pw_cesopsn;
enum mpls_default_dissector_t {
@@ -113,6 +119,10 @@ enum mpls_default_dissector_t {
,MDD_MPLS_PW_ETH_NOCW
,MDD_MPLS_PW_GENERIC
,MDD_ITDM
+ ,MDD_MPLS_PW_ATM_N1_CW
+ ,MDD_MPLS_PW_ATM_N1_NOCW
+ ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
+ ,MDD_MPLS_PW_ATM_AAL5_SDU
};
/* TODO the content of mpls_default_payload menu
@@ -123,12 +133,12 @@ enum mpls_default_dissector_t {
static enum_val_t mpls_default_payload_defs[] = {
{
"pw satop"
- ,"SAToP (no RTP support)"
+ ,pwc_longname_pw_satop
,MDD_PW_SATOP
},
{
"pw cesopsn"
- ,"CESoPSN basic NxDS0 mode (no RTP support)"
+ ,pwc_longname_pw_cesopsn
,MDD_PW_CESOPSN
},
{
@@ -172,6 +182,26 @@ static enum_val_t mpls_default_payload_defs[] = {
,MDD_ITDM
},
{
+ "mpls pw atm n_to_one cw"
+ ,pwc_longname_pw_atm_n1_cw
+ ,MDD_MPLS_PW_ATM_N1_CW
+ },
+ {
+ "mpls pw atm n_to_one no_cw"
+ ,pwc_longname_pw_atm_n1_nocw
+ ,MDD_MPLS_PW_ATM_N1_NOCW
+ },
+ {
+ "mpls pw atm one_to_one or aal5_pdu"
+ ,pwc_longname_pw_atm_11_or_aal5_pdu
+ ,MDD_MPLS_PW_ATM_11_OR_AAL5_PDU
+ },
+ {
+ "mpls pw atm aal5_sdu"
+ ,pwc_longname_pw_atm_aal5_sdu
+ ,MDD_MPLS_PW_ATM_AAL5_SDU
+ },
+ {
NULL
,NULL
,-1
@@ -181,6 +211,9 @@ static enum_val_t mpls_default_payload_defs[] = {
static int mpls_filter[MPLSF_MAX];
static gint mpls_default_payload = 0;
+static gboolean mpls_pref_pwac_all_as_bfd_xipv4 = FALSE;
+static gboolean mpls_pref_pwac_0x0_as_bfd = FALSE;
+static gboolean mpls_pref_pwac_try_ppp = TRUE;
static int hf_mpls_1st_nibble = -1;
@@ -236,6 +269,60 @@ static const value_string oam_defect_type_vals[] = {
{0, NULL }
};
+#if 0 /*not used yet*/
+/*
+ * MPLS PW types
+ * http://www.iana.org/assignments/pwe3-parameters
+ */
+static const value_string mpls_pw_types[] = {
+ { 0x0001, "Frame Relay DLCI ( Martini Mode )" },
+ { 0x0002, "ATM AAL5 SDU VCC transport" },
+ { 0x0003, "ATM transparent cell transport" },
+ { 0x0004, "Ethernet Tagged Mode" },
+ { 0x0005, "Ethernet" },
+ { 0x0006, "HDLC" },
+ { 0x0007, "PPP" },
+ { 0x0008, "SONET/SDH Circuit Emulation Service Over MPLS" },
+ { 0x0009, "ATM n-to-one VCC cell transport" },
+ { 0x000A, "ATM n-to-one VPC cell transport" },
+ { 0x000B, "IP Layer2 Transport" },
+ { 0x000C, "ATM one-to-one VCC Cell Mode" },
+ { 0x000D, "ATM one-to-one VPC Cell Mode" },
+ { 0x000E, "ATM AAL5 PDU VCC transport" },
+ { 0x000F, "Frame-Relay Port mode" },
+ { 0x0010, "SONET/SDH Circuit Emulation over Packet" },
+ { 0x0011, "Structure-agnostic E1 over Packet" },
+ { 0x0012, "Structure-agnostic T1 (DS1) over Packet" },
+ { 0x0013, "Structure-agnostic E3 over Packet" },
+ { 0x0014, "Structure-agnostic T3 (DS3) over Packet" },
+ { 0x0015, "CESoPSN basic mode" },
+ { 0x0016, "TDMoIP AAL1 Mode" },
+ { 0x0017, "CESoPSN TDM with CAS" },
+ { 0x0018, "TDMoIP AAL2 Mode" },
+ { 0x0019, "Frame Relay DLCI" },
+ { 0x001A, "ROHC Transport Header-compressed Packets" },/*[RFC4995][RFC4901]*/
+ { 0x001B, "ECRTP Transport Header-compressed Packets" },/*[RFC3545][RFC4901]*/
+ { 0x001C, "IPHC Transport Header-compressed Packets" },/*[RFC2507][RFC4901]*/
+ { 0x001D, "cRTP Transport Header-compressed Packets" },/*[RFC2508][RFC4901]*/
+ { 0x001E, "ATM VP Virtual Trunk" },/*[MFA9]*/
+ { 0x001F, "Reserved" },/*[Bryant] 2008-04-17*/
+ { 0, NULL }
+};
+#endif
+
+/*
+ * MPLS PW Associated Channel Types
+ * as per http://www.iana.org/assignments/pwe3-parameters
+ * and http://tools.ietf.org/html/draft-ietf-pwe3-vccv-bfd-05 clause 3.2
+ */
+static const value_string mpls_pwac_types[] = {
+ { 0x0007, "BFD Control, PW-ACH-encapsulated (BFD Without IP/UDP Headers)" },
+ { 0x0021, "IPv4 packet" },
+ { 0x0057, "IPv6 packet" },
+ { 0, NULL }
+};
+
+
static dissector_table_t ppp_subdissector_table;
static dissector_table_t mpls_subdissector_table;
@@ -289,20 +376,49 @@ dissect_pw_ach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
tvb, 0, 1, ver, "Version: %d", ver);
ti = proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_res,
tvb, 1, 1, res, "Reserved: 0x%02x", res);
- PROTO_ITEM_SET_HIDDEN(ti);
if (res != 0)
proto_tree_add_text(mpls_pw_ach_tree, tvb, 1, 1,
"Error: this byte is reserved and must be 0");
+ else
+ PROTO_ITEM_SET_HIDDEN(ti);
proto_tree_add_uint_format(mpls_pw_ach_tree, hf_mpls_pw_ach_channel_type,
tvb, 2, 2, channel_type,
"Channel Type: %s (0x%04x)",
- val_to_str(channel_type, ppp_vals, "Unknown"),
+ val_to_str(channel_type, mpls_pwac_types, "Unknown"),
channel_type);
}
next_tvb = tvb_new_subset(tvb, 4, -1, -1);
- if (!dissector_try_port(ppp_subdissector_table, channel_type,
+
+ if (0x21 == channel_type /*IPv4, RFC4385 clause 6.*/)
+ {
+ call_dissector(dissector_ip, next_tvb, pinfo, tree);
+ }
+ else if (0x7 == channel_type /*PWACH-encapsulated BFD, draft-ietf-pwe3-vccv-bfd-05 3.2*/
+ || mpls_pref_pwac_all_as_bfd_xipv4)
+ {
+ call_dissector(dissector_bfd, next_tvb, pinfo, tree);
+ }
+ else if (0x57 == channel_type /*IPv6, RFC4385 clause 6.*/)
+ {
+ call_dissector(dissector_ipv6, next_tvb, pinfo, tree);
+ }
+ else if (0x0 == channel_type && mpls_pref_pwac_0x0_as_bfd)
+ {
+ call_dissector(dissector_bfd, next_tvb, pinfo, tree);
+ }
+ else if (mpls_pref_pwac_try_ppp)
+ {
+ /* XXX perhaps this code should be reconsidered */
+ /* non-standard extension, therefore controlled by option*/
+ /* appeared in revision 10862 from Carlos M. Pignataro */
+ if (!dissector_try_port(ppp_subdissector_table, channel_type,
next_tvb, pinfo, tree)) {
call_dissector(dissector_data, next_tvb, pinfo, tree);
+ }
+ }
+ else
+ {
+ call_dissector(dissector_data, next_tvb, pinfo, tree);
}
}
@@ -683,8 +799,20 @@ dissect_mpls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
case MDD_ITDM:
call_dissector(dissector_itdm, next_tvb, pinfo, tree);
break;
- default: /*fallthrough*/
- case MDD_MPLS_PW_GENERIC:
+ 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;
}
@@ -806,6 +934,35 @@ proto_register_mpls(void)
&mpls_default_payload,
mpls_default_payload_defs,
FALSE );
+ prefs_register_bool_preference(module_mpls
+ ,"mplspref.pwac_0x0_as_bfd"
+ ,"Assume PWAC Channel Type 0x0 is raw BFD"
+ ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
+ " when VCCV carries PW-ACH-encapsulated BFD (i.e., BFD without IP/UDP Headers, or \"raw\" BFD)"
+ "\n\n"
+ "Legacy or buggy devices may not comply to this and use Channel Type 0x0 for BFD."
+ " Enable this preference to decode such BFD traffic."
+ " Disable for standard behavior of PWAC dissector (default)."
+ ,&mpls_pref_pwac_0x0_as_bfd);
+ prefs_register_bool_preference(module_mpls
+ ,"mplspref.pwac_all_as_bfd_xip"
+ ,"Assume that all PWAC Channel Types (except 0x21) are raw BFD"
+ ,"draft-ietf-pwe3-vccv-bfd-05 states that PWAC Channel Type 0x07 must be used"
+ " when VCCV carries PW-ACH-encapsulated BFD (i.e., \"raw\" BFD)"
+ "\n\n"
+ "Legacy or buggy devices may not comply to this and use voluntary Channel Type for BFD."
+ " Enable this preference to decode all PWAC Channel Types as raw BFD,"
+ " except Channel Type 0x21 (IPv4)."
+ " Disable for standard behavior of PWAC dissector (default)."
+ ,&mpls_pref_pwac_all_as_bfd_xipv4);
+ prefs_register_bool_preference(module_mpls
+ ,"mplspref.pwac_try_ppp"
+ ,"As a last resort, try to decode PWAC payloads as PPP traffic"
+ ,"Legacy devices may use MPLS PW Associated Channel for PPP traffic."
+ "\n\n"
+ "Enable this preference to allow PWAC dissector to try PPP,"
+ " if no other suitable dissector found (default)."
+ ,&mpls_pref_pwac_try_ppp);
}
void
@@ -836,6 +993,7 @@ proto_reg_handoff_mpls(void)
dissector_data = find_dissector("data");
dissector_ipv6 = find_dissector("ipv6");
dissector_ip = find_dissector("ip");
+ dissector_bfd = find_dissector("bfd");
dissector_pw_eth_heuristic = find_dissector("pw_eth_heuristic");
dissector_pw_fr = find_dissector("pw_fr");
dissector_pw_hdlc_nocw_fr = find_dissector("pw_hdlc_nocw_fr");
@@ -844,6 +1002,10 @@ proto_reg_handoff_mpls(void)
dissector_pw_eth_nocw = find_dissector("pw_eth_nocw");
dissector_pw_satop = find_dissector("pw_satop");
dissector_itdm = find_dissector("itdm");
+ dissector_mpls_pw_atm_n1_cw = find_dissector("mpls_pw_atm_n1_cw");
+ dissector_mpls_pw_atm_n1_nocw = find_dissector("mpls_pw_atm_n1_nocw");
+ dissector_mpls_pw_atm_11_aal5pdu= find_dissector("mpls_pw_atm_11_or_aal5_pdu");
+ dissector_mpls_pw_atm_aal5_sdu = find_dissector("mpls_pw_atm_aal5_sdu");
dissector_pw_cesopsn = find_dissector("pw_cesopsn");
initialized = TRUE;
diff --git a/epan/dissectors/packet-pw-atm.c b/epan/dissectors/packet-pw-atm.c
index c281b70dd5..bec5e81966 100644
--- a/epan/dissectors/packet-pw-atm.c
+++ b/epan/dissectors/packet-pw-atm.c
@@ -1,9 +1,10 @@
/* packet-pw-atm.c
* Routines for ATM PW dissection: it should be conform to RFC 4717.
*
- * Copyright 2009 _FF_
+ * Copyright 2009 _FF_, _ATA_
*
* Francesco Fondelli <francesco dot fondelli, gmail dot com>
+ * Artem Tamazov <artem [dot] tamazov [at] tellabs [dot] com>
*
* $Id$
*
@@ -30,15 +31,9 @@
DONE:
- ATM N-to-One Cell Mode (with CW)
- ATM N-to-One Cell Mode (no CW)
- TODO:
- ATM One-to-One Cell Mode
- ATM AAL5 SDU Mode
- ATM AAL5 PDU Mode
-
- Please pick an item from the TODO list, move code out of #if 0
- (see below) and implement a dissector for the given encapsulation
- mode. The N-to-One Cell Mode is the only mandatory encap
- mode. One-to-One/SDU/PDU modes are optional.
*/
#ifdef HAVE_CONFIG_H
@@ -50,541 +45,1968 @@
#include <string.h>
#include <glib.h>
#include <epan/packet.h>
+#include <epan/expert.h>
+#include <epan/prefs.h>
+#include <wiretap/wtap.h> /*for atm pseudo header*/
#include "packet-mpls.h"
+#include "packet-atm.h"
+#include "packet-pw-atm.h"
+#include "packet-pw-common.h"
-static gint proto_pw_atm_n2o_cw = -1;
-static gint proto_pw_atm_n2o_nocw = -1;
-#if 0
-static gint proto_pw_atm_o2o_cw = -1;
-static gint proto_pw_atm_o2o_nocw = -1;
-static gint proto_pw_atm_aal5_pdu_cw = -1;
-static gint proto_pw_atm_aal5_pdu_nocw = -1;
-static gint proto_pw_atm_aal5_sdu_cw = -1;
-static gint proto_pw_atm_aal5_sdu_nocw = -1;
-#endif
+static gint proto_n1_nocw = -1;
+static gint proto_n1_cw = -1;
+static gint proto_11_or_aal5_pdu = -1;
+static gint proto_aal5_sdu = -1;
+/* subordinate dissectors: */
+static gint proto_control_word = -1;
+static gint proto_cell_header = -1;
+static gint proto_cell = -1;
-static gint ett_pw_atm = -1;
-
-static int hf_pw_atm_n2o_cw = -1;
-static int hf_pw_atm_n2o_cw_flags = -1;
-static int hf_pw_atm_n2o_cw_length = -1;
-static int hf_pw_atm_n2o_cw_sequence_number = -1;
-static int hf_pw_atm_n2o_nocw = -1;
-#if 0
-static int hf_pw_atm_o2o_cw = -1;
-static int hf_pw_atm_o2o_cw_sequence_number = -1;
-static int hf_pw_atm_o2o_cw_flags = -1;
-static int hf_pw_atm_o2o_cw_flags_m = -1;
-static int hf_pw_atm_o2o_cw_flags_v = -1;
-static int hf_pw_atm_o2o_cw_flags_res = -1;
-static int hf_pw_atm_o2o_cw_flags_pti = -1;
-static int hf_pw_atm_o2o_cw_flags_c = -1;
-static int hf_pw_atm_o2o_nocw = -1;
-static int hf_pw_atm_aal5_pdu_cw = -1;
-static int hf_pw_atm_aal5_pdu_cw_sequence_number = -1;
-static int hf_pw_atm_aal5_pdu_nocw = -1;
-static int hf_pw_atm_aal5_sdu_cw = -1;
-static int hf_pw_atm_aal5_sdu_cw_sequence_number = -1;
-static int hf_pw_atm_aal5_sdu_nocw = -1;
-#endif
+static gint ett_encaps = -1;
+static gint ett_cw = -1;
+static gint ett_cell_header = -1;
+static gint ett_cell = -1;
+
+static int hf_pw_type_n1_cw = -1;
+static int hf_pw_type_n1_nocw = -1;
+static int hf_pw_type_11_vcc = -1;
+static int hf_pw_type_11_vpc = -1;
+static int hf_pw_type_aal5_sdu = -1;
+static int hf_pw_type_aal5_pdu = -1;
+
+static int hf_cell_h_vpi = -1;
+static int hf_cell_h_vci = -1;
+static int hf_cell_h_pti = -1;
+static int hf_cell_h_clp = -1;
+static int hf_cell_h_m = -1;
+static int hf_cell_h_v = -1;
+static int hf_cell_h_rsv = -1;
+static int hf_aal5_pdu_rsv = -1;
+static int hf_aal5_pdu_u = -1;
+static int hf_aal5_pdu_e = -1;
+
+static int hf_cw_bits03 = -1;
+static int hf_pref_cw_rsv = -1;
+static int hf_generic_cw_rsv = -1;
+static int hf_pref_cw_flags = -1;
+static int hf_pref_cw_a5s_t = -1;
+static int hf_pref_cw_a5s_e = -1;
+static int hf_pref_cw_a5s_c = -1;
+static int hf_pref_cw_a5s_u = -1;
+static int hf_pref_cw_len = -1;
+static int hf_pref_cw_rsvlen = -1;
+static int hf_cw_seq = -1;
+static int hf_n1_cw_ncells = -1;
+static int hf_n1_nocw_ncells = -1;
+static int hf_11_ncells = -1;
+static int hf_gen_cw_atmbyte = -1;
+static int hf_cell_payload_len = -1;
+
+static dissector_handle_t dh_cell;
+static dissector_handle_t dh_cell_header;
+static dissector_handle_t dh_control_word;
+static dissector_handle_t dh_atm_truncated;
+static dissector_handle_t dh_atm_untruncated;
+static dissector_handle_t dh_atm_oam_cell;
+static dissector_handle_t dh_padding;
+static dissector_handle_t dh_data;
+
+#define PTI_IS_ADMIN(pti) ((pti) == 4 || (pti) == 5 || (pti) == 6) /*see atm_pt_vals[]*/
+
+#define MODE_11(mode) (PWATM_MODE_11_VCC == (mode) || PWATM_MODE_11_VPC == (mode))
+#define MODE_N1(mode) (PWATM_MODE_N1_NOCW == (mode)|| PWATM_MODE_N1_CW == (mode))
+#define MODE_11_OR_AAL5_PDU(mode) (MODE_11(mode) || PWATM_MODE_AAL5_PDU == (mode))
+
+#define VALUE_SELECTOR_VPC_VCC_PDU(mode,val_vpc,val_vcc,val_pdu)\
+ ((PWATM_MODE_11_VPC == (mode)) \
+ ? (val_vpc) \
+ : ((PWATM_MODE_11_VCC == (mode)) \
+ ? (val_vcc) \
+ : ((PWATM_MODE_AAL5_PDU == (mode)) \
+ ? (val_pdu) \
+ : 0 \
+ ) \
+ ) \
+ )
+
+#define UPDATE_CUMULATIVE_VALUE(cumulative_val,new_val)\
+ do\
+ {\
+ if (-2 >= (cumulative_val))\
+ {\
+ }\
+ else if (-1 == (cumulative_val))\
+ {\
+ (cumulative_val) = (new_val);\
+ }\
+ else if ((new_val) != (cumulative_val))\
+ {\
+ (cumulative_val) = -2;\
+ }\
+ }\
+ while(0)
+
+#define SIZEOF_ATM_CELL_PAYLOAD 48
+#define SIZEOF_N1_PW_CELL_HEADER 4
+#define SIZEOF_11_VCC_PW_CELL_HEADER 1
+#define SIZEOF_11_VPC_PW_CELL_HEADER 3
+#define SIZEOF_N1_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_N1_PW_CELL_HEADER)
+#define SIZEOF_11_VCC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VCC_PW_CELL_HEADER)
+#define SIZEOF_11_VPC_PW_CELL (SIZEOF_ATM_CELL_PAYLOAD+SIZEOF_11_VPC_PW_CELL_HEADER)
+
+const char pwc_longname_pw_atm_n1_cw[] = "MPLS PW ATM N-to-One encapsulation, with CW";
+const char pwc_longname_pw_atm_n1_nocw[] = "MPLS PW ATM N-to-One encapsulation, no CW";
+const char pwc_longname_pw_atm_11_or_aal5_pdu[] = "MPLS PW ATM One-to-One or AAL5 PDU encapsulation";
+const char pwc_longname_pw_atm_aal5_sdu[] = "MPLS PW ATM AAL5 CPCS-SDU mode encapsulation";
-static dissector_handle_t data_h;
-static dissector_handle_t atm_h;
+static const char longname_pw_atm_11_vcc[] = "MPLS PW ATM One-to-One VCC Cell Transport";
+static const char longname_pw_atm_11_vpc[] = "MPLS PW ATM One-to-One VPC Cell Transport";
+static const char longname_pw_atm_aal5_pdu[] = "MPLS PW ATM AAL5 PDU encapsulation";
-/* ATM One-to-One Cell Mode bits in "ATM Specific" CW field */
-#define PW_ATM_O2O_CW_M 0x80
-#define PW_ATM_O2O_CW_V 0x40
-#define PW_ATM_O2O_CW_RES 0x30
-#define PW_ATM_O2O_CW_PTI 0x0E
-#define PW_ATM_O2O_CW_C 0x01
+static const char shortname_n1_cw[] = "MPLS PW ATM N:1 CW";
+static const char shortname_n1_nocw[] = "MPLS PW ATM N:1 no CW";
+static const char shortname_11_or_aal5_pdu[] = "MPLS PW ATM 1:1 / AAL5 PDU";
+static const char shortname_11_vpc[] = "MPLS PW ATM 1:1 VPC";
+static const char shortname_11_vcc[] = "MPLS PW ATM 1:1 VCC";
+static const char shortname_aal5_sdu[] = "MPLS PW ATM AAL5 SDU";
+static const char shortname_aal5_pdu[] = "MPLS PW ATM AAL5 PDU";
-static void
-dissect_pw_atm_n2o_cw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+/*
+ * These options are needed to support Nokia AXE and stuff alike.
+ * Note that these options will affect PW type auto-guessing, if such heuristic
+ * implemented in the future.
+ */
+static gboolean pref_n1_cw_allow_cw_length_nonzero = FALSE;
+static gboolean pref_n1_cw_extend_cw_length_with_rsvd = FALSE;
+static gboolean pref_aal5_sdu_allow_cw_length_nonzero = FALSE;
+static gboolean pref_aal5_sdu_extend_cw_length_with_rsvd= FALSE;
+
+
+static
+int pw_cell_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
{
- proto_tree *pw_atm_tree = NULL;
- proto_item *ti = NULL;
- tvbuff_t *next_tvb = NULL;
- guint16 sequence_number = 0;
- guint8 flags = 0;
- guint8 length = 0;
- guint16 ncells = 0;
- guint16 remains = 0;
- guint16 i = 0;
-
- if (tvb_reported_length_remaining(tvb, 0) < 4) {
- if (tree)
- proto_tree_add_text(tree, tvb, 0, -1,
- "Error processing Message");
- return;
- }
-
- if (tree) {
- ti = proto_tree_add_boolean(tree, hf_pw_atm_n2o_cw,
- tvb, 0, 0, TRUE);
- PROTO_ITEM_SET_HIDDEN(ti);
- ti = proto_tree_add_item(tree, proto_pw_atm_n2o_cw,
- tvb, 0, 4, FALSE);
- pw_atm_tree = proto_item_add_subtree(ti, ett_pw_atm);
- if (pw_atm_tree == NULL)
- return;
-
- flags = tvb_get_guint8(tvb, 0) & 0x0F;
- proto_tree_add_uint_format(
- pw_atm_tree,
- hf_pw_atm_n2o_cw_flags,
- tvb, 0, 1, flags,
- "Flags: 0x%02x",
- flags);
-
- length = tvb_get_guint8(tvb, 1) & 0x3F;
- proto_tree_add_uint_format(
- pw_atm_tree,
- hf_pw_atm_n2o_cw_length,
- tvb, 1, 1, length,
- "Length: %u",
- flags);
-
- sequence_number = tvb_get_ntohs(tvb, 2);
- proto_tree_add_uint_format(
- pw_atm_tree,
- hf_pw_atm_n2o_cw_sequence_number,
- tvb, 2, 2, sequence_number,
- "Sequence Number: %u",
- sequence_number);
- }
-
- /* FF: pass info to the ATM dissector, see packet_info.h for details */
- pinfo->pw_atm_encap_type = 1;
-
- /*
- * FF: RFC 4717: "The number of cells encapsulated in a particular
- * frame can be inferred by the frame length" but "if the control
- * word is used, then the flag and length bits in the control word
- * are not used [and must be set to 0]" so... no reported_length in
- * tvb_new_subset().
- */
- ncells = tvb_length_remaining(tvb, 4) / 52;
- pinfo->pw_atm_ncells = ncells;
- remains = tvb_length_remaining(tvb, 4) % 52;
-
- for (i = 0; i < ncells; i++) {
- next_tvb = tvb_new_subset(tvb,
- 4 + (i * 52),
- 52,
- -1);
- call_dissector(atm_h, next_tvb, pinfo, tree);
- }
-
- /*
- * FF: RFC 4717 "if the pseudowire traverses a network link that
- * requires a minimum frame size, with a minimum frame size of 64
- * octets, then such links will apply padding to the pseudowire PDU
- * to reach its minimum frame size" or this is a malformed PDU,
- * anyway...
- */
- if (remains) {
- next_tvb = tvb_new_subset(tvb,
- 4 + (i * 52),
- remains,
- -1);
- call_dissector(data_h, next_tvb, pinfo, tree);
- }
+ switch(mode)
+ {
+ case PWATM_MODE_N1_NOCW:
+ case PWATM_MODE_N1_CW:
+ return SIZEOF_N1_PW_CELL;
+ case PWATM_MODE_11_VCC:
+ return SIZEOF_11_VCC_PW_CELL;
+ case PWATM_MODE_11_VPC:
+ return SIZEOF_11_VPC_PW_CELL;
+ case PWATM_MODE_AAL5_PDU:
+ /* AAL5 PDU size is n*48 bytes */
+ return SIZEOF_ATM_CELL_PAYLOAD;
+ case PWATM_MODE_AAL5_SDU:
+ if (PWATM_SUBMODE_ADMIN_CELL == submode)
+ {
+ return SIZEOF_N1_PW_CELL; /*n:1 encapsulation is used for admin cells*/
+ }
+ else
+ {
+ DISSECTOR_ASSERT_NOT_REACHED();
+ return 0;
+ }
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ return 0;
+ }
}
-static void
-dissect_pw_atm_n2o_nocw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static
+int pw_cell_header_size(const pwatm_mode_t mode, const pwatm_submode_t submode)
{
- proto_item *ti = NULL;
- tvbuff_t *next_tvb = NULL;
- guint16 ncells = 0;
- guint16 remains = 0;
- guint16 i = 0;
-
- /*
- * FF: all comments in dissect_pw_atm_n2o_cw() apply here
- * as well, thus not repeated.
- */
-
- if (tvb_reported_length_remaining(tvb, 0) < 52) {
- if (tree)
- proto_tree_add_text(tree, tvb, 0, -1,
- "Error processing Message");
- return;
- }
-
- if (tree) {
- ti = proto_tree_add_boolean(tree, hf_pw_atm_n2o_nocw,
- tvb, 0, 0, TRUE);
- PROTO_ITEM_SET_HIDDEN(ti);
- }
-
- pinfo->pw_atm_encap_type = 1;
- ncells = tvb_length_remaining(tvb, 0) / 52;
- pinfo->pw_atm_ncells = ncells;
- remains = tvb_length_remaining(tvb, 0) % 52;
-
- for (i = 0; i < ncells; i++) {
- next_tvb = tvb_new_subset(tvb,
- (i * 52),
- 52,
- -1);
- call_dissector(atm_h, next_tvb, pinfo, tree);
- }
-
- if (remains) {
- next_tvb = tvb_new_subset(tvb,
- (i * 52),
- remains,
- -1);
- call_dissector(data_h, next_tvb, pinfo, tree);
- }
+ switch(mode)
+ {
+ case PWATM_MODE_N1_NOCW:
+ case PWATM_MODE_N1_CW:
+ return SIZEOF_N1_PW_CELL_HEADER;
+ case PWATM_MODE_11_VCC:
+ return SIZEOF_11_VCC_PW_CELL_HEADER;
+ case PWATM_MODE_11_VPC:
+ return SIZEOF_11_VPC_PW_CELL_HEADER;
+ case PWATM_MODE_AAL5_SDU:
+ if (PWATM_SUBMODE_ADMIN_CELL == submode)
+ {
+ return SIZEOF_N1_PW_CELL_HEADER; /*n:1 encapsulation is used for admin cells*/
+ }
+ else
+ {
+ DISSECTOR_ASSERT_NOT_REACHED();
+ return 0;
+ }
+ case PWATM_MODE_AAL5_PDU: /*not applicable*/
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ return 0;
+ }
}
-#if 0
-static void
-dissect_pw_atm_o2o_cw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+static
+int number_of_cells(const pwatm_mode_t mode
+ ,const pwatm_submode_t submode
+ ,const gint payload_size
+ ,gint* const remainder_size)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ int cells;
+ assert(payload_size >= 0);
+ assert(remainder_size != NULL);
+
+ switch(mode)
+ {
+ case PWATM_MODE_N1_NOCW:
+ case PWATM_MODE_N1_CW:
+ case PWATM_MODE_11_VCC:
+ case PWATM_MODE_11_VPC:
+ case PWATM_MODE_AAL5_PDU:
+ cells = payload_size / pw_cell_size(mode,submode);
+ *remainder_size = payload_size - (cells * pw_cell_size(mode,submode));
+ return cells;
+ case PWATM_MODE_AAL5_SDU:
+ if (PWATM_SUBMODE_ADMIN_CELL == submode)
+ {
+ cells = payload_size / pw_cell_size(mode,submode);
+ if (cells > 1) cells = 1; /*max. 1 admin cell may be present in aal5 sdu mode */
+ *remainder_size = payload_size - (cells * pw_cell_size(mode,submode));
+ return cells;
+ }
+ else
+ {
+ /*not applicable*/
+ }
+ /*fallthrough*/
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ *remainder_size = payload_size;
+ return 0;
+ }
+
}
-static void
-dissect_pw_atm_o2o_nocw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+
+static
+void col_append_pw_info(packet_info * pinfo
+ ,const int payload_size
+ ,const int cells
+ ,const int padding_size)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ pwatm_private_data_t* pd;
+ assert(pinfo != NULL);
+
+ pd = pinfo->private_data;
+ assert(pd != NULL);
+
+ if (pd->props & PWC_ANYOF_CW_BAD)
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, "CW:Bad");
+ }
+
+ if (pd->props & PWC_PAY_SIZE_BAD)
+ {
+ if (pd->props & PWC_ANYOF_CW_BAD)
+ {
+ col_append_str(pinfo->cinfo, COL_INFO, ", ");
+ }
+ col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%d byte%s"
+ ,(int)payload_size
+ ,plurality(payload_size,"","s"));
+ }
+
+ if (pd->props == 0) /*omit "atm cells" etc if something is wrong*/
+ {
+ /* number of cells may be not known */
+ if (cells >=0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, "%d ATM cell%s"
+ ,cells
+ ,plurality(cells,"","s"));
+ /*
+ * Display ATM-specific attributes which are the same
+ * across all the cells in the pw packet.
+ * Meanings of values:
+ * (-1) unknown - not displayed,
+ * (-2) "not the same in all cells" - not displayed
+ * positive values - ok, displayed
+ */
+ if (pd->cumulative.vpi >= 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", VPI:%.4d", pd->cumulative.vpi);
+ if (pd->cumulative.vci >= 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", VCI:%.5d", pd->cumulative.vci);
+ if (pd->cumulative.pti >= 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", PTI:%.1d", pd->cumulative.pti);
+ if (pd->cumulative.clp >= 0)
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", CLP:%.1d", pd->cumulative.clp);
+ }
+
+ if (padding_size != 0)
+ {
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding"
+ ,(int)padding_size);
+ }
}
+
+static
+void prepare_pseudo_header_atm(
+ union wtap_pseudo_header * const ph,
+ const pwatm_private_data_t * const pdata,
+ const unsigned aal)
+{
+ assert(NULL != pdata);
+ assert(NULL != ph);
+
+ memset(ph,0,sizeof(*ph)); /* it is OK to clear unknown values */
+ ph->atm.flags = 0; /* status flags */
+ ph->atm.aal = aal;
+ ph->atm.type = TRAF_UNKNOWN;
+ ph->atm.subtype = TRAF_ST_UNKNOWN;
+ ph->atm.vpi = (pdata->vpi >= 0) ? pdata->vpi : 0 /*unknown*/;
+ ph->atm.vci = (pdata->vci >= 0) ? pdata->vci : 0 /*unknown*/;
+ ph->atm.aal2_cid = 0; /*not applicable*//* channel id */
+ ph->atm.channel = 0; /*unknown*//* link: 0 for DTE->DCE, 1 for DCE->DTE */
+ ph->atm.cells = 0; /*zero indicates that we do not have trailer info*/
+ /*user-to-user indicator & CPI*/
+ ph->atm.aal5t_u2u = 0; /* all bits unknown except lsb of UU */
+ if (pdata->aal5_sdu_frame_relay_cr_bit)
+ { /* Let's give Frame Relay C/R bit to ATM dissector.*/
+ ph->atm.aal5t_u2u |= (1<<8); /*UU octet is at << 8 in aal5t_u2u*/
+ }
+ ph->atm.aal5t_len = 0; /*unknown*//* length of the packet from trailer*/
+ ph->atm.aal5t_chksum = 0; /*unknown*//* checksum for AAL5 packet from trailer */
+ return;
+}
-static void
-dissect_pw_atm_aal5_pdu_cw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+
+static
+void dissect_payload_and_padding(
+ tvbuff_t * tvb
+ ,packet_info * pinfo
+ ,proto_tree * tree
+ ,const gint payload_size
+ ,const gint padding_size)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ int dissected;
+ tvbuff_t* tvb_2;
+ pwatm_private_data_t* pd;
+
+ assert(NULL != pinfo);
+ pd = pinfo->private_data;
+ assert(NULL != pd);
+
+ for(dissected = 0, pd->pw_cell_number = 0;
+ payload_size > dissected;
+ ++(pd->pw_cell_number))
+ {
+ tvb_2 = tvb_new_subset(tvb,dissected,-1,-1);
+ dissected += call_dissector(dh_cell_header, tvb_2, pinfo, tree);
+
+ tvb_2 = tvb_new_subset(tvb,dissected,-1,-1);
+
+ /*dissect as oam for specific vci/pti, just like atm dissector does*/
+ if (pd->vci >= 0 && pd->pti >=0)
+ {
+ if (atm_is_oam_cell(pd->vci,pd->pti))
+ {
+ pd->cell_mode_oam = TRUE;
+ }
+ }
+
+ if (pd->cell_mode_oam)
+ {
+ union wtap_pseudo_header* pseudo_header_save;
+ union wtap_pseudo_header ph;
+ tvbuff_t* tvb_3;
+ int bytes_to_dissect;
+ /* prepare buffer for old-style dissector */
+ /* oam cell is always 48 bytes, but payload_size maybe too small */
+ if ((payload_size - dissected) >= SIZEOF_ATM_CELL_PAYLOAD)
+ bytes_to_dissect = SIZEOF_ATM_CELL_PAYLOAD;
+ else
+ bytes_to_dissect = (payload_size - dissected);
+ tvb_3 = tvb_new_subset(tvb_2,0,bytes_to_dissect,-1);
+ /*aal5_sdu: disable filling columns after 1st (valid) oam cell*/
+ if (pd->mode == PWATM_MODE_AAL5_SDU && pd->pw_cell_number > 0)
+ {
+ pd->enable_fill_columns_by_atm_dissector = FALSE;
+ }
+ /* save & prepare new pseudo header for atm aal5 decoding */
+ pseudo_header_save = pinfo->pseudo_header;
+ pinfo->pseudo_header = &ph;
+ prepare_pseudo_header_atm(&ph,pd,AAL_OAMCELL);
+
+ call_dissector(dh_atm_oam_cell, tvb_3, pinfo, tree);
+ dissected += bytes_to_dissect;
+ /* restore pseudo header */
+ pinfo->pseudo_header = pseudo_header_save;
+ }
+ else
+ {
+ dissected += call_dissector(dh_cell, tvb_2, pinfo, tree);
+ }
+ }
+
+ if (padding_size != 0)
+ {
+ tvbuff_t* tvb_2;
+ tvb_2 = tvb_new_subset(tvb
+ ,(tvb_reported_length_remaining(tvb, 0) - padding_size)
+ ,-1
+ ,-1);
+ call_dissector(dh_padding, tvb_2, pinfo, tree);
+ }
+ return;
}
-static void
-dissect_pw_atm_aal5_pdu_nocw(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree)
+static
+gboolean too_small_packet_or_notpw(tvbuff_t * tvb
+ ,packet_info * pinfo
+ ,proto_tree * tree
+ ,const int proto_handler
+ ,const char * const proto_name_column)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ gint packet_size;
+ packet_size = tvb_reported_length_remaining(tvb, 0);
+ /*
+ * FIXME
+ * "4" below should be replaced by something like "min_packet_size_this_dissector"
+ * Also call to dissect_try_cw_first_nibble() should be moved before this block
+ */
+ if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
+ {
+ if (tree)
+ {
+ proto_item *item;
+ item = proto_tree_add_item(tree, proto_handler, tvb, 0, -1, FALSE);
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
+ "PW packet size (%d) is too small to carry sensible information"
+ ,(int)packet_size);
+ }
+ /* represent problems in the Packet List pane */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_set_str(pinfo->cinfo, COL_INFO,
+ "Malformed: PW packet is too small");
+ }
+ return TRUE;
+ }
+ if (dissect_try_cw_first_nibble(tvb, pinfo, tree))
+ {
+ return TRUE;
+ }
+ return FALSE;
}
-static void
-dissect_pw_atm_aal5_sdu_cw(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+
+/*
+ * NOTE. RFC describes ATM-specific byte in a cumbersome way.
+ * It is a part of CW, but at the same time, it must be repeated
+ * with each cell, _except_ first.
+ *
+ * Alternatively, ATM-specific byte may be considered as part of
+ * PW payload (i.e., as part of pw atm cell header), so we can say that
+ * it is being repeated with each cell.
+ *
+ * This dissector is written according to the latter consideration.
+ */
+static
+void dissect_11_or_aal5_pdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ const char *proto_name_column;
+ const char *proto_name_tree = NULL;
+ gint payload_size;
+ int cells;
+ pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
+ void * pd_save = pinfo->private_data;
+ pinfo->private_data = &pd;
+
+ proto_name_column = &shortname_11_or_aal5_pdu[0];
+ if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_11_or_aal5_pdu,proto_name_column))
+ {
+ return;
+ }
+ pd.packet_size = tvb_reported_length_remaining(tvb, 0);
+
+ /*
+ * Guess encapsulation mode according to M & V bits from the 3rd byte of CW.
+ * Also adjust protocol name strings.
+ */
+ {
+ guint8 third_byte;
+ third_byte = tvb_get_guint8(tvb, 3);
+ if (0 == (third_byte & 0x80 /*generic_cw.m*/))
+ { /*1:1 modes*/
+ if (0 != (third_byte & 0x40 /*generic_cw.v*/))
+ {
+ pd.mode = PWATM_MODE_11_VPC;
+ proto_name_column = &shortname_11_vpc[0];
+ proto_name_tree = &longname_pw_atm_11_vpc[0];
+ }
+ else
+ {
+ pd.mode = PWATM_MODE_11_VCC;
+ proto_name_column = &shortname_11_vcc[0];
+ proto_name_tree = &longname_pw_atm_11_vcc[0];
+ }
+ }
+ else
+ {
+ pd.mode = PWATM_MODE_AAL5_PDU;
+ proto_name_column = &shortname_aal5_pdu[0];
+ proto_name_tree = &longname_pw_atm_aal5_pdu[0];
+ }
+ }
+
+
+ /* check how "good" is this packet */
+ pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
+ if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
+ {
+ pd.props |= PWC_CW_BAD_BITS03;
+ }
+ if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*generic_cw.rsvd*/))
+ {
+ pd.props |= PWC_CW_BAD_RSV;
+ }
+
+ /*
+ * Do not dissect and validate atm-specific byte (3rd byte of CW).
+ * It will be dissected/validated as pw cell header.
+ */
+
+ /*
+ * Decide about payload length and padding.
+ *
+ * Is padding allowed?
+ * eth header length == 14
+ * mpls label length == 4
+ * cw length == 4
+ * min payload length == 48
+ * => 14 + 4 + 4 + 48 == 70
+ * => 70 >= 64
+ * => no padding allowed
+ */
+ if (MODE_11(pd.mode))
+ {
+ gint bad_padding_size;
+ payload_size = pd.packet_size - (PWC_SIZEOF_CW-1);
+ cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
+ if (0 == cells || 0 != bad_padding_size)
+ {
+ pd.props |= PWC_PAY_SIZE_BAD;
+ }
+ }
+ else
+ { /*aal5_pdu mode*/
+ gint bad_padding_size;
+ payload_size = pd.packet_size - PWC_SIZEOF_CW;
+ cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
+ /* at least 1 cell must be present in the packet in this mode*/
+ if (1 > cells || 0 != bad_padding_size)
+ {
+ pd.props |= PWC_PAY_SIZE_BAD;
+ }
+ cells = -1; /*this value not needed anymore, suppress pinting of it*/
+ }
+
+ if (PWATM_MODE_AAL5_PDU == pd.mode)
+ {
+ /* sub-dissectors _may_ overwrite columns in aal5_pdu mode */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_pw_info(pinfo, payload_size, cells, 0);
+ }
+ }
+
+ if (tree)
+ {
+ proto_item* item;
+ item = proto_tree_add_item(tree, proto_11_or_aal5_pdu, tvb, 0, -1, FALSE);
+ /*overwrite heading line*/
+ proto_item_set_text(item, proto_name_tree, 0/*-warn gcc 3.4.4*/);
+ pwc_item_append_text_n_items(item,cells,"good ATM cell");
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett_encaps);
+ {
+ proto_item* item;
+ item = proto_tree_add_boolean(tree
+ ,VALUE_SELECTOR_VPC_VCC_PDU(pd.mode
+ ,hf_pw_type_11_vpc
+ ,hf_pw_type_11_vcc
+ ,hf_pw_type_aal5_pdu)
+ ,tvb, 0, 0, TRUE);
+ PROTO_ITEM_SET_GENERATED(item);
+ if (MODE_11(pd.mode))
+ {
+ item = proto_tree_add_int(tree, hf_11_ncells, tvb, 0, 0, cells);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+ }
+ if (pd.props & PWC_PAY_SIZE_BAD)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"PW payload size (%d) must be <> 0 and multiple of %d"
+ ,(int)payload_size,pw_cell_size(pd.mode,pd.submode));
+ if (payload_size != 0 && MODE_11(pd.mode))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_NOTE,
+ "PW ATM cell [%.3d] is broken",(int)cells);
+ }
+ }
+ }
+
+ {
+ tvbuff_t* tvb_2;
+ tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
+ call_dissector(dh_control_word, tvb_2, pinfo, tree);
+
+ tvb_2 = tvb_new_subset(tvb, (PWC_SIZEOF_CW-1), -1, -1);
+ if (MODE_11(pd.mode))
+ {
+ dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,0);
+ }
+ else
+ { /*aal5_pdu mode*/
+ if (payload_size != 0)
+ {
+ tvbuff_t* tvb_3;
+ union wtap_pseudo_header* pseudo_header_save;
+ union wtap_pseudo_header ph;
+
+ tvb_3 = tvb_new_subset(tvb_2, 1, -1, -1);
+ /* prepare pseudo header for atm aal5 decoding */
+ pseudo_header_save = pinfo->pseudo_header;
+ pinfo->pseudo_header = &ph;
+ prepare_pseudo_header_atm(&ph,&pd,AAL_5);
+ call_dissector(dh_atm_untruncated, tvb_3, pinfo, tree);
+ /* restore pseudo header */
+ pinfo->pseudo_header = pseudo_header_save;
+ }
+ }
+ }
+
+ if (MODE_11(pd.mode))
+ {
+ /* overwrite everything written by sub-dissectors in 1:1 modes*/
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ }
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_pw_info(pinfo, payload_size, cells, 0);
+ }
+ }
+
+ pinfo->private_data = pd_save;
+ return;
}
-static void
-dissect_pw_atm_aal5_sdu_nocw(tvbuff_t *tvb, packet_info *pinfo,
- proto_tree *tree)
+
+static
+void dissect_aal5_sdu(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
- (void)tvb;
- (void)pinfo;
- (void)tree;
+ const char *proto_name_column;
+ gint payload_size;
+ gint padding_size;
+ int cells;
+ pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
+ void * pd_save = pinfo->private_data;
+
+ pinfo->private_data = &pd;
+ pd.mode = PWATM_MODE_AAL5_SDU;
+
+ proto_name_column = &shortname_aal5_sdu[0];
+ if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_aal5_sdu,proto_name_column))
+ {
+ return;
+ }
+ pd.packet_size = tvb_reported_length_remaining(tvb, 0);
+
+ /* check how "good" is this packet */
+ /* also decide payload length from packet size and CW */
+ if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
+ {
+ pd.props |= PWC_CW_BAD_BITS03;
+ }
+
+ pd.submode = PWATM_SUBMODE_DEFAULT;
+ if (0 != (tvb_get_guint8(tvb, 0) & 0x08 /*preferred_cw.T*/))
+ {
+ pd.submode = PWATM_SUBMODE_ADMIN_CELL;
+ }
+
+ if (! pref_aal5_sdu_extend_cw_length_with_rsvd)
+ {
+ if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
+ {
+ pd.props |= PWC_CW_BAD_RSV;
+ }
+ }
+ {
+ /* RFC4717:
+ * [ If the packet's length (defined as the length of the layer 2 payload
+ * plus the length of the control word) is less than 64 bytes, the
+ * length field MUST be set to the packet's length. Otherwise, the
+ * length field MUST be set to zero... Note that the length field
+ * is not used in the N-to-one mode and MUST be set to 0. ]
+ *
+ * Also we allow some "extensions"conducted by pref_xxx.
+ */
+ gint payload_size_from_packet;
+ int cw_len; /*length field from cw*/
+
+ payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
+ if (pref_aal5_sdu_extend_cw_length_with_rsvd)
+ {
+ cw_len = tvb_get_guint8(tvb, 1) & 0xff;
+ }
+ else
+ {
+ cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
+ }
+
+ /*
+ * Initial assumptions: no padding,
+ * payload size derived from psn packet size.
+ */
+ payload_size = payload_size_from_packet;
+ padding_size = 0;
+
+ if (0 == cw_len)
+ {
+ /*keep initial assumptions*/
+ }
+ else if (!pref_aal5_sdu_allow_cw_length_nonzero
+ && PWATM_SUBMODE_ADMIN_CELL == pd.submode)
+ {
+ /*
+ * The "allow CW.Length != 0" option affects
+ * ATM admin cell submode only, because this submode
+ * is equal to N:1 encapsulation.
+ * CW.Length !=0 is always OK for normal (AAL5 payload) submode.
+ */
+ pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
+ }
+ else
+ {
+ gint payload_size_from_cw;
+ payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
+ if (payload_size_from_cw <= 0)
+ {
+ pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
+ }
+ else if (payload_size_from_cw > payload_size_from_packet)
+ {
+ pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
+ }
+ else
+ {
+
+ payload_size = payload_size_from_cw;
+ padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
+ if (padding_size != 0)
+ {
+ /*
+ * Padding is not allowed in ATM admin cell submode only,
+ * because this submode is equal to N:1 encapsulation.
+ * Padding is OK for normal (AAL5 payload) submode.
+ */
+ if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
+ {
+ pd.props |= PWC_CW_BAD_PADDING_NE_0;
+ /*restore sizes*/
+ payload_size = payload_size_from_packet;
+ padding_size = 0;
+ }
+ }
+ }
+ }
+
+ if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
+ {
+ gint bad_padding_size;
+ cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
+ /* only one atm admin cell is allowed in the packet in this mode*/
+ if (1 != cells || 0 != bad_padding_size)
+ {
+ pd.props |= PWC_PAY_SIZE_BAD;
+ }
+ }
+ else
+ {
+ cells = -1; /*unknown*/
+ /* Any size is allowed for AAL5 SDU payload */
+ }
+ }
+
+ /* fill columns in Packet List */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
+ {
+ col_append_str(pinfo->cinfo, COL_PROTOCOL, ", OAM cell");
+ }
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_pw_info(pinfo, payload_size, cells, padding_size);
+ }
+
+ if (tree)
+ {
+ proto_item* item;
+ item = proto_tree_add_item(tree, proto_aal5_sdu, tvb, 0, -1, FALSE);
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett_encaps);
+ {
+ item = proto_tree_add_boolean(tree, hf_pw_type_aal5_sdu, tvb, 0, 0, TRUE);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+ if (pd.props & PWC_PAY_SIZE_BAD)
+ {
+ DISSECTOR_ASSERT(PWATM_SUBMODE_ADMIN_CELL == pd.submode);
+ expert_add_info_format(pinfo, item, PI_MALFORMED ,PI_ERROR
+ ,"In ATM admin cell mode,"
+ " PW payload size (%d) must be == %d (exactly 1 admin cell)"
+ ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
+ }
+ }
+
+ {
+ tvbuff_t* tvb_2;
+ tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
+ call_dissector(dh_control_word, tvb_2, pinfo, tree);
+
+ tvb_2 = tvb_new_subset(tvb, PWC_SIZEOF_CW, -1, -1);
+ if (PWATM_SUBMODE_ADMIN_CELL == pd.submode)
+ {
+ dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,padding_size);
+ }
+ else /*AAL5 payload*/
+ {
+ if (payload_size != 0)
+ {
+ tvbuff_t* tvb_3;
+ union wtap_pseudo_header* pseudo_header_save;
+ union wtap_pseudo_header ph;
+
+ tvb_3 = tvb_new_subset(tvb_2, 0, payload_size, payload_size);
+ /* prepare pseudo header for atm aal5 decoding */
+ pseudo_header_save = pinfo->pseudo_header;
+ pinfo->pseudo_header = &ph;
+ prepare_pseudo_header_atm(&ph,&pd,AAL_5);
+ call_dissector(dh_atm_truncated, tvb_3, pinfo, tree); /* no PAD and trailer */
+ /* restore pseudo header */
+ pinfo->pseudo_header = pseudo_header_save;
+ }
+ if (padding_size != 0)
+ {
+ tvbuff_t* tvb_3;
+ tvb_3 = tvb_new_subset(tvb_2, payload_size, padding_size, -1);
+ call_dissector(dh_padding, tvb_3, pinfo, tree);
+ }
+ }
+ }
+
+ pinfo->private_data = pd_save;
+ return;
}
-#endif
-void
-proto_register_pw_atm(void)
+
+static
+void dissect_n1_cw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
- static hf_register_info hf[] = {
- /* FF: general */
- {
- &hf_pw_atm_n2o_cw,
- {
- "ATM PW, N-to-one Cell Mode (with CW)",
- "pw_atm_n2o_cw", FT_BOOLEAN,
- BASE_NONE, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_n2o_nocw,
- {
- "ATM PW, N-to-one Cell Mode (no CW)",
- "pw_atm_n2o_nocw", FT_BOOLEAN,
- BASE_NONE, NULL, 0x0, NULL, HFILL
- }
- },
-#if 0
- {
- &hf_pw_atm_o2o_cw,
- {
- "ATM PW, One-to-one Cell Mode (with CW)",
- "pw_atm_o2o_cw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_nocw,
- {
- "ATM PW, One-to-one Cell Mode (no CW)",
- "pw_atm_o2o_nocw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_aal5_pdu_cw,
- {
- "ATM PW, AAL5 PDU Frame Mode (with CW)",
- "pw_atm_aal5_pdu_cw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_aal5_pdu_nocw,
- {
- "ATM PW, AAL5 PDU Frame Mode (no CW)",
- "pw_atm_aal5_pdu_nocw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_aal5_sdu_cw,
- {
- "ATM PW, AAL5 SDU Frame Mode (with CW)",
- "pw_atm_aal5_sdu_cw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_aal5_sdu_nocw,
- {
- "ATM PW, AAL5 SDU Frame Mode (no CW)",
- "pw_atm_aal5_sdu_nocw", FT_BOOLEAN,
- 0, NULL, 0x0, NULL, HFILL
- }
- },
- /* FF: ATM One-to-one Cell Mode Control Word fields */
- {
- &hf_pw_atm_o2o_cw_sequence_number,
- {
- "ATM One-to-one Cell Mode sequence number",
- "pw_atm_o2o_cw_sequence_number", FT_UINT16,
- BASE_DEC, NULL, 0x0, NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_cw_flags,
- {
- "ATM One-to-one Cell Mode flags",
- "pw_atm_o2o_cw_flags", FT_UINT8,
- BASE_HEX, NULL, 0x0, NULL, HFILL
- }
-
- },
- {
- &hf_pw_atm_o2o_cw_flags_m,
- {
- "M (transport mode) bit",
- "pw_atm_o2o_cw_flags_m", FT_BOOLEAN,
- 8, TFS(&flags_set_truth), PW_ATM_O2O_CW_M,
- NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_cw_flags_v,
- {
- "V (VCI present) bit",
- "pw_atm_o2o_cw_flags_v", FT_BOOLEAN,
- 8, TFS(&flags_set_truth), PW_ATM_O2O_CW_V,
- NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_cw_flags_res,
- {
- "Reserved bits",
- "pw_atm_o2o_cw_flags_res", FT_BOOLEAN,
- 8, TFS(&flags_set_truth), PW_ATM_O2O_CW_RES,
- NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_cw_flags_pti,
- {
- "PTI bits",
- "pw_atm_o2o_cw_flags_pti", FT_BOOLEAN,
- 8, TFS(&flags_set_truth), PW_ATM_O2O_CW_PTI,
- NULL, HFILL
- }
- },
- {
- &hf_pw_atm_o2o_cw_flags_c,
- {
- "C (CLP) bit",
- "pw_atm_o2o_cw_flags_c", FT_BOOLEAN,
- 8, TFS(&flags_set_truth), PW_ATM_O2O_CW_C,
- NULL, HFILL
- }
- },
- /* FF: AAL5 PDU Frame Mode Control Word fields */
- {
- &hf_pw_atm_aal5_pdu_cw_sequence_number,
- {
- "AAL5 PDU Frame Mode sequence number",
- "pw_atm_aal5_pdu_cw_sequence_number",
- FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL
- }
- },
- /* FF: AAL5 SDU Frame Mode Control Word fields */
- {
- &hf_pw_atm_aal5_sdu_cw_sequence_number,
- {
- "AAL5 SDU Frame Mode sequence number",
- "pw_atm_aal5_sdu_cw_sequence_number",
- FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL
- }
- },
-#endif
- /* FF: ATM N-to-one Cell Mode Control Word fields */
- {
- &hf_pw_atm_n2o_cw_flags,
- {
- "ATM N-to-one Cell Mode flags",
- "pw_atm_n2o_cw_flags", FT_UINT8,
- BASE_HEX, NULL, 0x0, NULL, HFILL
- }
-
- },
- {
- &hf_pw_atm_n2o_cw_length,
- {
- "ATM N-to-one Cell Mode flags",
- "pw_atm_n2o_cw_length", FT_UINT8,
- BASE_HEX, NULL, 0x0, NULL, HFILL
- }
-
- },
- {
- &hf_pw_atm_n2o_cw_sequence_number,
- {
- "ATM N-to-one Cell Mode sequence number",
- "pw_atm_n2o_cw_sequence_number", FT_UINT16,
- BASE_DEC, NULL, 0x0, NULL, HFILL
- }
- },
- };
-
- static gint *ett[] = {
- &ett_pw_atm
- };
-
- proto_pw_atm_n2o_cw =
- proto_register_protocol("ATM PW, N-to-one Cell Mode Control Word",
- "ATM PW, N-to-one Cell Mode (with CW)",
- "pw_atm_n2o_cw");
- proto_pw_atm_n2o_nocw =
- proto_register_protocol("ATM PW, N-to-one Cell Mode (no CW)",
- "ATM PW, N-to-one Cell Mode (no CW)",
- "pw_atm_n2o_nocw");
-#if 0
- proto_pw_atm_o2o_cw =
- proto_register_protocol("ATM PW, One-to-one Cell Mode Control Word",
- "ATM PW, One-to-one Cell Mode (with CW)",
- "pw_atm_o2o_cw");
- proto_pw_atm_o2o_nocw =
- proto_register_protocol("ATM PW, One-to-one Cell Mode (no CW)",
- "ATM PW, One-to-one Cell Mode (no CW)",
- "pw_atm_o2o_nocw");
- proto_pw_atm_aal5_pdu_cw =
- proto_register_protocol("ATM PW, AAL5 PDU Frame Mode Control Word",
- "ATM PW, AAL5 PDU Frame Mode (with CW)",
- "pw_atm_aal5_pdu_cw");
- proto_pw_atm_aal5_pdu_nocw =
- proto_register_protocol("ATM PW, AAL5 PDU Frame Mode (no CW)",
- "ATM PW, AAL5 PDU Frame Mode (no CW)",
- "pw_atm_aal5_pdu_nocw");
- proto_pw_atm_aal5_sdu_cw =
- proto_register_protocol("ATM PW, AAL5 SDU Frame Mode Control Word",
- "ATM PW, AAL5 SDU Frame Mode (with CW)",
- "pw_atm_aal5_sdu_cw");
- proto_pw_atm_aal5_sdu_nocw =
- proto_register_protocol("ATM PW, AAL5 SDU Frame Mode (no CW)",
- "ATM PW, AAL5 SDU Frame Mode (no CW)",
- "pw_atm_aal5_sdu_nocw");
-#endif
+ const char *proto_name_column;
+ gint payload_size;
+ gint padding_size;
+ int cells;
+ pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
+ void * pd_save = pinfo->private_data;
- proto_register_field_array(proto_pw_atm_n2o_cw, hf, array_length(hf));
- proto_register_subtree_array(ett, array_length(ett));
-
- register_dissector("pw_atm_n2o_cw",
- dissect_pw_atm_n2o_cw,
- proto_pw_atm_n2o_cw);
- register_dissector("pw_atm_n2o_nocw",
- dissect_pw_atm_n2o_nocw,
- proto_pw_atm_n2o_nocw);
-#if 0
- register_dissector("pw_atm_o2o_cw",
- dissect_pw_atm_o2o_cw,
- proto_pw_atm_o2o_cw);
- register_dissector("pw_atm_o2o_nocw",
- dissect_pw_atm_o2o_nocw,
- proto_pw_atm_o2o_nocw);
- register_dissector("pw_atm_aal5_pdu_cw",
- dissect_pw_atm_aal5_pdu_cw,
- proto_pw_atm_aal5_pdu_cw);
- register_dissector("pw_atm_aal5_pdu_nocw",
- dissect_pw_atm_aal5_pdu_nocw,
- proto_pw_atm_aal5_pdu_nocw);
- register_dissector("pw_atm_aal5_sdu_cw",
- dissect_pw_atm_aal5_sdu_cw,
- proto_pw_atm_aal5_sdu_cw);
- register_dissector("pw_atm_aal5_sdu_nocw",
- dissect_pw_atm_aal5_sdu_nocw,
- proto_pw_atm_aal5_sdu_nocw);
-#endif
+ pinfo->private_data = &pd;
+ pd.mode = PWATM_MODE_N1_CW;
+
+ proto_name_column = &shortname_n1_cw[0];
+ if (too_small_packet_or_notpw(tvb,pinfo,tree,proto_n1_cw,proto_name_column))
+ {
+ return;
+ }
+ pd.packet_size = tvb_reported_length_remaining(tvb, 0);
+
+ /* check how "good" is this packet */
+ /* also decide payload length from packet size and CW */
+ pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
+ if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
+ {
+ pd.props |= PWC_CW_BAD_BITS03;
+ }
+ if (0 != (tvb_get_guint8(tvb, 0) & 0x0f /*preferred_cw.flags*/))
+ {
+ pd.props |= PWC_CW_BAD_FLAGS;
+ }
+ if (! pref_n1_cw_extend_cw_length_with_rsvd)
+ {
+ if (0 != (tvb_get_guint8(tvb, 1) & 0xc0 /*preferred_cw.rsvd*/))
+ {
+ pd.props |= PWC_CW_BAD_RSV;
+ }
+ }
+ {
+ /* RFC4717:
+ * [ If the packet's length (defined as the length of the layer 2 payload
+ * plus the length of the control word) is less than 64 bytes, the
+ * length field MUST be set to the packet's length. Otherwise, the
+ * length field MUST be set to zero... Note that the length field
+ * is not used in the N-to-one mode and MUST be set to 0. ]
+ *
+ * Also we allow some "extensions"conducted by pref_xxx.
+ */
+ gint payload_size_from_packet;
+ int cw_len; /*length field from cw*/
+
+ payload_size_from_packet = pd.packet_size - PWC_SIZEOF_CW;
+ if (pref_n1_cw_extend_cw_length_with_rsvd)
+ {
+ cw_len = tvb_get_guint8(tvb, 1) & 0xff;
+ }
+ else
+ {
+ cw_len = tvb_get_guint8(tvb, 1) & 0x3f;
+ }
+
+ /*
+ * Initial assumptions: no padding,
+ * payload size derived from psn packet size.
+ */
+ payload_size = payload_size_from_packet;
+ padding_size = 0;
+
+ if (0 == cw_len)
+ {
+ /*keep initial assumptions*/
+ }
+ else if (!pref_n1_cw_allow_cw_length_nonzero)
+ {
+ pd.props |= PWC_CW_BAD_LEN_MUST_BE_0;
+ }
+ else
+ {
+ gint payload_size_from_cw;
+ payload_size_from_cw = cw_len - PWC_SIZEOF_CW;
+ if (payload_size_from_cw <= 0)
+ {
+ pd.props |= PWC_CW_BAD_PAYLEN_LE_0;
+ }
+ else if (payload_size_from_cw > payload_size_from_packet)
+ {
+ pd.props |= PWC_CW_BAD_PAYLEN_GT_PACKET;
+ }
+ else
+ {
+
+ payload_size = payload_size_from_cw;
+ padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
+ if (padding_size != 0)
+ {
+ pd.props |= PWC_CW_BAD_PADDING_NE_0;
+ /*restore sizes*/
+ payload_size = payload_size_from_packet;
+ padding_size = 0;
+ }
+ }
+ }
+ {
+ gint bad_padding_size;
+ cells = number_of_cells(pd.mode,pd.submode,payload_size,&bad_padding_size);
+ if (0 == cells || 0 != bad_padding_size)
+ {
+ pd.props |= PWC_PAY_SIZE_BAD;
+ }
+ }
+ }
+
+ if (tree)
+ {
+ proto_item* item;
+ item = proto_tree_add_item(tree, proto_n1_cw, tvb, 0, -1, FALSE);
+ pwc_item_append_text_n_items(item,cells,"good ATM cell");
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett_encaps);
+ {
+ proto_item* item;
+ item = proto_tree_add_boolean(tree, hf_pw_type_n1_cw, tvb, 0, 0, TRUE);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_int(tree, hf_n1_cw_ncells, tvb, 0, 0, cells);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+ if (pd.props & PWC_PAY_SIZE_BAD)
+ {
+ if (payload_size != 0)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
+ "PW ATM cell [%.3d] is broken",(int)cells);
+ }
+ expert_add_info_format(pinfo, item, PI_MALFORMED
+ , (payload_size == 0) ? PI_ERROR : PI_NOTE
+ ,"PW payload size (%d) must be <>0 and multiple of %d"
+ ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
+ }
+ }
+
+ {
+ tvbuff_t* tvb_2;
+ tvb_2 = tvb_new_subset(tvb, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
+ call_dissector(dh_control_word, tvb_2, pinfo, tree);
+
+ tvb_2 = tvb_new_subset(tvb, PWC_SIZEOF_CW, -1, -1);
+ dissect_payload_and_padding(tvb_2,pinfo,tree,payload_size,padding_size);
+ }
+
+ /* fill columns in Packet List */
+ /* overwrite everything written by sub-dissectors */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ }
+
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_pw_info(pinfo, payload_size, cells, padding_size);
+ }
+
+ pinfo->private_data = pd_save;
+ return;
}
-void
-proto_reg_handoff_pw_atm(void)
+
+static
+void dissect_n1_nocw(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
- dissector_handle_t pw_atm_n2o_cw_h;
- dissector_handle_t pw_atm_n2o_nocw_h;
-#if 0
- dissector_handle_t pw_atm_o2o_cw_h;
- dissector_handle_t pw_atm_o2o_nocw_h;
- dissector_handle_t pw_atm_aal5_pdu_cw_h;
- dissector_handle_t pw_atm_aal5_pdu_nocw_h;
- dissector_handle_t pw_atm_aal5_sdu_cw_h;
- dissector_handle_t pw_atm_aal5_sdu_nocw_h;
-#endif
+ const char *proto_name_column = &shortname_n1_nocw[0];
+ gint payload_size;
+ int cells;
+ pwatm_private_data_t pd = PWATM_PRIVATE_DATA_T_INITIALIZER;
+ void * pd_save = pinfo->private_data;
- pw_atm_n2o_cw_h = find_dissector("pw_atm_n2o_cw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_n2o_cw_h);
+ pinfo->private_data = &pd;
+ pd.mode = PWATM_MODE_N1_NOCW;
+ pd.packet_size = tvb_reported_length_remaining(tvb, 0);
- pw_atm_n2o_nocw_h = find_dissector("pw_atm_n2o_nocw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_n2o_nocw_h);
-#if 0
- pw_atm_o2o_cw_h = find_dissector("pw_atm_o2o_cw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_o2o_cw_h);
+ /* check how "good" is this packet */
+ /* also decide payload length from packet size */
+ pd.props = PWC_PACKET_PROPERTIES_T_INITIALIZER;
+ payload_size = pd.packet_size;
+ {
+ gint bad_padding_size;
+ cells = number_of_cells(pd.mode,pd.submode,pd.packet_size,&bad_padding_size);
+ if (cells == 0 || bad_padding_size != 0)
+ {
+ pd.props |= PWC_PAY_SIZE_BAD;
+ }
+ }
- pw_atm_o2o_nocw_h = find_dissector("pw_atm_o2o_nocw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_o2o_nocw_h);
+ if (tree)
+ {
+ proto_item* item;
+ item = proto_tree_add_item(tree, proto_n1_nocw, tvb, 0, -1, FALSE);
+ pwc_item_append_text_n_items(item,cells,"ATM cell");
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett_encaps);
+ {
+ proto_item* item;
+ item = proto_tree_add_boolean(tree, hf_pw_type_n1_nocw, tvb, 0, 0, TRUE);
+ PROTO_ITEM_SET_GENERATED(item);
+ item = proto_tree_add_int(tree, hf_n1_nocw_ncells, tvb, 0, 0, cells);
+ PROTO_ITEM_SET_GENERATED(item);
+ }
+ }
+ if (pd.props & PWC_PAY_SIZE_BAD)
+ {
+ if (payload_size != 0)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
+ "Last PW ATM cell [%.3d] is broken",(int)cells);
+ }
+ expert_add_info_format(pinfo, item, PI_MALFORMED
+ , (payload_size == 0) ? PI_ERROR : PI_NOTE
+ ,"PW payload size (%d) must be <>0 and multiple of %d"
+ ,(int)payload_size,(int)SIZEOF_N1_PW_CELL);
+ }
+ }
+
+ dissect_payload_and_padding(tvb,pinfo,tree,payload_size,0);
+
+ /* fill columns in Packet List */
+ /* overwrite everything written by sub-dissectors */
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, proto_name_column);
+ }
- pw_atm_aal5_pdu_cw_h = find_dissector("pw_atm_aal5_pdu_cw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_aal5_pdu_cw_h);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ {
+ col_clear(pinfo->cinfo, COL_INFO);
+ col_append_pw_info(pinfo, payload_size, cells, 0);
+ }
- pw_atm_aal5_pdu_nocw_h = find_dissector("pw_atm_aal5_pdu_nocw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_aal5_pdu_nocw_h);
+ pinfo->private_data = pd_save;
+ return;
+}
- pw_atm_aal5_sdu_cw_h = find_dissector("pw_atm_aal5_sdu_cw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_aal5_sdu_cw_h);
- pw_atm_aal5_sdu_nocw_h = find_dissector("pw_atm_aal5_sdu_nocw");
- dissector_add("mpls.label", LABEL_INVALID, pw_atm_aal5_sdu_nocw_h);
-#endif
+static
+void proto_item_append_text_cwb3_fields(proto_item * item, const pwatm_private_data_t * const pd)
+{
+ if (NULL == item) return;
+ assert(NULL != pd);
+ if (pd->cwb3.m >= 0)
+ proto_item_append_text(item, "M:%.1u " , (unsigned)(pd->cwb3.m));
+ if (pd->cwb3.v >= 0)
+ proto_item_append_text(item, "V:%.1u " , (unsigned)(pd->cwb3.v));
+ if (pd->cwb3.rsv >= 0)
+ proto_item_append_text(item, "RSV:%.1u ", (unsigned)(pd->cwb3.rsv));
+ if (pd->cwb3.u >= 0)
+ proto_item_append_text(item, "U:%.1u " , (unsigned)(pd->cwb3.u));
+ if (pd->cwb3.e >= 0)
+ proto_item_append_text(item, "EFCI:%.1u ",(unsigned)(pd->cwb3.e));
+ if (pd->cwb3.clp >= 0)
+ proto_item_append_text(item, "CLP:%.1u ", (unsigned)(pd->cwb3.clp));
+ return;
+}
+
+
+static
+void dissect_control_word(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ pwatm_private_data_t* pd;
+ pd = pinfo->private_data;
+ assert(pd != NULL);
+
+ /*
+ * NB: do not touch columns -- keep info from previous dissector
+ */
+
+ {
+ gint size;
+ size = tvb_reported_length_remaining(tvb, 0);
+ if (size < PWC_SIZEOF_CW)
+ {
+ if (tree)
+ {
+ proto_item *item;
+ item = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, FALSE);
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
+ "Packet (size: %d) is too small to carry MPLS PW Control Word"
+ ,(int)size);
+ }
+ return;
+ }
+ }
+
+ if (tree)
+ {
+ proto_item* item_top;
+ item_top = proto_tree_add_item(tree, proto_control_word, tvb, 0, -1, FALSE);
+ pwc_item_append_cw(item_top,tvb_get_ntohl(tvb, 0),FALSE);
+
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item_top, ett_cw);
+ {
+ proto_item* item;
+ /* bits 0..3 */
+ item = proto_tree_add_item(tree, hf_cw_bits03, tvb, 0, 1, FALSE);
+ if (pd->props & PWC_CW_BAD_BITS03)
+ {
+ /* add item to tree (and show it) only if its value is wrong*/
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bits 0..3 of Control Word must be 0");
+ }
+ else
+ {
+ PROTO_ITEM_SET_HIDDEN(item); /* show only in error cases */
+ }
+
+ /* flags */
+ if (MODE_N1(pd->mode))
+ {
+ item = proto_tree_add_item(tree, hf_pref_cw_flags, tvb, 0, 1, FALSE);
+ if (pd->props & PWC_CW_BAD_FLAGS)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Flags must be 0 for PW ATM N:1 encapsulation");
+ }
+ }
+ if (pd->mode == PWATM_MODE_AAL5_SDU)
+ {
+ item = proto_tree_add_item(tree, hf_pref_cw_a5s_t, tvb, 0, 1, FALSE);
+ item = proto_tree_add_item(tree, hf_pref_cw_a5s_e, tvb, 0, 1, FALSE);
+ item = proto_tree_add_item(tree, hf_pref_cw_a5s_c, tvb, 0, 1, FALSE);
+ item = proto_tree_add_item(tree, hf_pref_cw_a5s_u, tvb, 0, 1, FALSE);
+ /*
+ * rfc4717: [When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]
+ * traffic is being transported, the CPCS-UU Least Significant Bit
+ * (LSB) of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit.
+ * The ingress router, PE1, SHOULD copy this bit to the U bit of the
+ * control word. The egress router, PE2, SHOULD copy the U bit to
+ * the CPCS-UU Least Significant Bit (LSB) of the AAL5 CPCS PDU.]
+ *
+ * Let's remember this bit (and then transfer it to ATM dissector).
+ */
+ pd->aal5_sdu_frame_relay_cr_bit =
+ (0 == (tvb_get_guint8(tvb, 0) & 0x01 /*preferred_cw.U*/))
+ ? FALSE : TRUE;
+ }
+
+ /* reserved bits */
+ if (MODE_11_OR_AAL5_PDU(pd->mode)
+ || (MODE_N1(pd->mode) && !pref_n1_cw_extend_cw_length_with_rsvd)
+ /* for N:1 add RSV only if it is NOT used in length */
+ || ((pd->mode == PWATM_MODE_AAL5_SDU) && !pref_aal5_sdu_extend_cw_length_with_rsvd)
+ /* for AAl5 SDU add RSV only if it is NOT used in length */)
+ {
+ if (MODE_11_OR_AAL5_PDU(pd->mode))
+ {
+ item = proto_tree_add_item(tree
+ ,hf_generic_cw_rsv, tvb, 0, 1, FALSE);
+ }
+ else
+ { /*preferred cw*/
+ item = proto_tree_add_item(tree
+ ,hf_pref_cw_rsv, tvb, 1, 1, FALSE);
+ }
+
+ if (pd->props & PWC_CW_BAD_RSV)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Reserved bits in Control Word must be 0");
+ }
+ else
+ {
+ PROTO_ITEM_SET_HIDDEN(item); /*...and show only in error cases */
+ }
+ }
+
+ /* length */
+ if (MODE_N1(pd->mode)
+ || (PWATM_MODE_AAL5_SDU == pd->mode))
+ {
+ {
+ int hf_len = hf_pref_cw_len;
+ if (MODE_N1(pd->mode))
+ {
+ if (pref_n1_cw_extend_cw_length_with_rsvd)
+ hf_len = hf_pref_cw_rsvlen;
+ }
+ else /*PW_MODE_AAL5_SDU*/
+ {
+ if (pref_aal5_sdu_extend_cw_length_with_rsvd)
+ hf_len = hf_pref_cw_rsvlen;
+ }
+ item = proto_tree_add_item(tree, hf_len, tvb, 1, 1, FALSE);
+ }
+ if (pd->props & PWC_CW_BAD_LEN_MUST_BE_0)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bad Length: must be 0 for this encapsulation");
+ }
+ if (pd->props & PWC_CW_BAD_PAYLEN_LE_0)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bad Length: too small, must be >= %d"
+ ,(int)(PWC_SIZEOF_CW+SIZEOF_N1_PW_CELL));
+ }
+ if (pd->props & PWC_CW_BAD_PAYLEN_GT_PACKET)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bad Length: must be <= than PSN packet size (%d)"
+ ,(int)pd->packet_size);
+ }
+ if (pd->props & PWC_CW_BAD_PADDING_NE_0)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bad Length: must be == PSN packet size (%d), no padding allowed"
+ ,(int)pd->packet_size);
+ }
+ }
+
+ /* sequence number */
+ (void)proto_tree_add_item(tree, hf_cw_seq, tvb
+ ,MODE_11_OR_AAL5_PDU(pd->mode) ? 1 : 2, 2, FALSE);
+
+ /* atm-specific byte */
+ if (MODE_11(pd->mode))
+ {
+ (void) proto_tree_add_item(tree, hf_gen_cw_atmbyte, tvb, 3, 1, FALSE);
+ /*
+ * no need to highlight item in the tree, therefore
+ * expert_add_info_format() is not used here.
+ */
+ item = proto_tree_add_text(tree,tvb,3,1
+ ,"ATM-specific byte of CW is fully dissected below as %s%s"
+ ,(PWATM_MODE_11_VPC == pd->mode) ? "a part of " : ""
+ ,"PW ATM Cell Header [000]");
+ PROTO_ITEM_SET_GENERATED(item);
+ /*
+ * Note: if atm-specific byte contains something wrong
+ * (e.g. non-zero RSV or inadequate V), CW is not
+ * marked as "bad".
+ */
+ }
+
+ /*3rd byte of CW*/
+ if (PWATM_MODE_AAL5_PDU == pd->mode)
+ {
+ tvbuff_t* tvb_2;
+ tvb_2 = tvb_new_subset(tvb, (PWC_SIZEOF_CW-1), -1, -1);
+ call_dissector(dh_cell_header, tvb_2, pinfo, tree);
+ proto_item_append_text(item_top,", ");
+ proto_item_append_text_cwb3_fields(item_top,pd);
+ }
+ }
+ }
+ }
+ return;
+}
+
+
+/*
+ * This function is also used to dissect 3rd byte of CW in AAL5 PDU mode.
+ */
+static
+int dissect_cell_header(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ pwatm_private_data_t * pd;
+ gboolean is_enough_data;
+ int dissect_size;
+
+ pd = pinfo->private_data;
+ assert (NULL != pd);
+ pd->vpi = pd->vci = pd->pti = -1;
+ pd->cwb3.clp = pd->cwb3.m = pd->cwb3.v = pd->cwb3.rsv = pd->cwb3.u = pd->cwb3.e = -1;
+
+ if (PWATM_MODE_AAL5_PDU == pd->mode)
+ {
+ if (tvb_reported_length_remaining(tvb, 0) < 1)
+ {
+ is_enough_data = FALSE;
+ dissect_size = 0;
+ }
+ else
+ {
+ is_enough_data = TRUE;
+ dissect_size = 1;
+ }
+ }
+ else
+ {
+ gint size;
+ size = tvb_reported_length_remaining(tvb, 0);
+
+ if (size < pw_cell_header_size(pd->mode,pd->submode))
+ {
+ is_enough_data = FALSE;
+ dissect_size = size;
+ }
+ else
+ {
+ is_enough_data = TRUE;
+ dissect_size = pw_cell_header_size(pd->mode,pd->submode);
+ }
+ }
+
+ /*
+ * NB: do not touch columns -- keep info from previous dissector
+ */
+
+ /* Collect info for upper-level dissectors regardless of
+ * the presence of the tree
+ */
+ if (is_enough_data)
+ {
+ guint8 tmp8;
+ switch (pd->mode)
+ {
+ case PWATM_MODE_AAL5_SDU:
+ DISSECTOR_ASSERT(pd->submode == PWATM_SUBMODE_ADMIN_CELL);
+ /*fallthrough for ATM admin cell submode only*/
+ case PWATM_MODE_N1_CW:
+ case PWATM_MODE_N1_NOCW:
+ pd->vpi = (tvb_get_ntohs (tvb, 0) >> 4);
+ pd->vci = (tvb_get_ntoh24(tvb, 1) >> 4) & 0xffff;
+ tmp8 = (tvb_get_guint8(tvb, 3));
+ pd->pti = (tmp8 >> 1) & 0x07;
+ pd->cwb3.clp = (tmp8 >> 0) & 0x01;
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.vpi,pd->vpi);
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci,pd->vci);
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti,pd->pti);
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
+ /*
+ * OAM cell mode is always used for aal5_sdu/admin_cell mode,
+ * even if pti indicates user cell.
+ */
+ pd->cell_mode_oam =
+ (pd->mode == PWATM_MODE_AAL5_SDU && pd->submode == PWATM_SUBMODE_ADMIN_CELL)
+ || PTI_IS_ADMIN(pd->pti);
+ break;
+ case PWATM_MODE_11_VPC:
+ pd->vci = tvb_get_ntohs(tvb, 1);
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.vci,pd->vci);
+ /*fallthrough*/
+ case PWATM_MODE_11_VCC:
+ tmp8 = (tvb_get_guint8(tvb, 0));
+ pd->cwb3.m = (tmp8 >> 7) & 0x1;
+ pd->cwb3.v = (tmp8 >> 6) & 0x1;
+ pd->cwb3.rsv = (tmp8 >> 4) & 0x3;
+ pd->pti = (tmp8 >> 1) & 0x7;
+ pd->cwb3.clp = (tmp8 >> 0) & 0x1;
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.pti,pd->pti);
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
+ /*
+ * OAM cell mode is possible if packet contains atm cell (m == 0).
+ */
+ pd->cell_mode_oam = PTI_IS_ADMIN(pd->pti) && (pd->cwb3.m == 0);
+ break;
+ case PWATM_MODE_AAL5_PDU:
+ tmp8 = (tvb_get_guint8(tvb, 0));
+ pd->cwb3.m = (tmp8 >> 7) & 0x1;
+ pd->cwb3.v = (tmp8 >> 6) & 0x1;
+ pd->cwb3.rsv = (tmp8 >> 3) & 0x7;
+ pd->cwb3.u = (tmp8 >> 2) & 0x1;
+ pd->cwb3.e = (tmp8 >> 1) & 0x1;
+ pd->cwb3.clp = (tmp8 >> 0) & 0x1;
+ UPDATE_CUMULATIVE_VALUE(pd->cumulative.clp,pd->cwb3.clp);
+ break;
+ default:
+ DISSECTOR_ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ if (tree)
+ {
+ proto_item* item;
+
+ item = proto_tree_add_item(tree, proto_cell_header, tvb
+ ,0
+ ,dissect_size
+ ,FALSE);
+ if (PWATM_MODE_AAL5_PDU == pd->mode)
+ {
+ proto_item_set_text(item, "Third byte of Control Word"); /*overwrite heading line*/
+ /* cwb3 fileds are appended to CW heading line, not here */
+ }
+ else
+ {
+ proto_item_append_text(item," [%.3d]",pd->pw_cell_number);
+ proto_item_append_text(item,", ");
+ if (pd->vpi >= 0)
+ proto_item_append_text(item, "VPI:%.4u ", (unsigned)(pd->vpi));
+ if (pd->vci >= 0)
+ proto_item_append_text(item, "VCI:%.5u ", (unsigned)(pd->vci));
+ if (pd->pti >= 0)
+ proto_item_append_text(item, "PTI:%.1u ", (unsigned)(pd->pti));
+ proto_item_append_text_cwb3_fields(item,pd);
+ }
+
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett_cell_header);
+ if (is_enough_data)
+ {
+ proto_item* item;
+ if (MODE_N1(pd->mode)
+ || (pd->mode == PWATM_MODE_AAL5_SDU && pd->submode == PWATM_SUBMODE_ADMIN_CELL))
+ {
+ (void) proto_tree_add_uint(tree, hf_cell_h_vpi, tvb, 0, 2, (unsigned)pd->vpi);
+ (void) proto_tree_add_uint(tree, hf_cell_h_vci, tvb, 1, 3, (unsigned)pd->vci);
+
+ item = proto_tree_add_item(tree, hf_cell_h_pti, tvb, 3, 1, FALSE);
+ if (NULL == match_strval(pd->pti,atm_pt_vals))
+ {
+ expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN,
+ "Unknown value of PTI field (%d) in the ATM cell header",
+ pd->pti);
+ }
+ else if (pd->mode == PWATM_MODE_AAL5_SDU && !PTI_IS_ADMIN(pd->pti))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
+ "ATM admin cell is transerred;"
+ " PTI field (%d) should be 4, 5 or 6.",
+ pd->pti);
+ }
+
+ (void) proto_tree_add_item(tree, hf_cell_h_clp, tvb, 3, 1, FALSE);
+ }
+ else if (MODE_11_OR_AAL5_PDU(pd->mode))
+ {
+ item = proto_tree_add_item(tree, hf_cell_h_m , tvb, 0, 1, FALSE);
+ if ((0 != pd->cwb3.m) && MODE_11(pd->mode))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"1:1 mode:"
+ " M bit must be 0 to distinguish from AAL5 PDU mode");
+ }
+
+ item = proto_tree_add_item(tree, hf_cell_h_v , tvb, 0, 1, FALSE);
+ if ((0 == pd->cwb3.v) && (PWATM_MODE_11_VPC == pd->mode))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"1:1 VPC mode:"
+ " V bit must be 1 to indicate that VCI is present");
+ }
+ if ((0 != pd->cwb3.v) && (PWATM_MODE_11_VCC == pd->mode))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"1:1 VCC mode:"
+ " V bit must be 0 to indicate that VCI is absent");
+ }
+ if ((0 != pd->cwb3.v) && (PWATM_MODE_AAL5_PDU == pd->mode))
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"AAL5 PDU mode:"
+ " V bit must be 0 to indicate that VCI is absent");
+ }
+
+ item = proto_tree_add_item(tree
+ ,(PWATM_MODE_AAL5_PDU == pd->mode)
+ ? hf_aal5_pdu_rsv
+ : hf_cell_h_rsv
+ ,tvb, 0, 1, FALSE);
+ if (0 != pd->cwb3.rsv)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Reserved bits in the 3rd byte of CW must be 0");
+ }
+ else
+ {
+ PROTO_ITEM_SET_HIDDEN(item); /*...and show only in error cases */
+ }
+
+ if (MODE_11(pd->mode))
+ {
+ item = proto_tree_add_item(tree, hf_cell_h_pti, tvb, 0, 1, FALSE);
+ if (NULL == match_strval(pd->pti,atm_pt_vals))
+ {
+ expert_add_info_format(pinfo, item, PI_UNDECODED, PI_WARN,
+ "Unknown value of PTI field (%d) in the atm-specific byte"
+ ,pd->pti);
+ }
+ }
+ else
+ {
+ (void) proto_tree_add_item(tree, hf_aal5_pdu_u, tvb, 0, 1, FALSE);
+ (void) proto_tree_add_item(tree, hf_aal5_pdu_e, tvb, 0, 1, FALSE);
+ }
+
+ (void) proto_tree_add_item(tree, hf_cell_h_clp, tvb, 0, 1, FALSE);
+
+ if (PWATM_MODE_11_VPC == pd->mode)
+ {
+ (void) proto_tree_add_uint(tree, hf_cell_h_vci, tvb, 1, 2
+ ,(unsigned)pd->vci);
+ }
+ }
+ else
+ {
+ DISSECTOR_ASSERT_NOT_REACHED();
+ }
+ }
+ else
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Not enough data (size: %d), impossible to decode"
+ ,(int)dissect_size);
+ }
+ }
+ }
+ return dissect_size;
+}
+
+
+static
+int dissect_cell(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ gboolean is_enough_data;
+ int dissect_size;
+
+ {
+ gint size;
+ size = tvb_reported_length_remaining(tvb, 0);
+ if (size < SIZEOF_ATM_CELL_PAYLOAD)
+ {
+ is_enough_data = FALSE;
+ dissect_size = size;
+ }
+ else
+ {
+ is_enough_data = TRUE;
+ dissect_size = SIZEOF_ATM_CELL_PAYLOAD;
+ }
+ }
+
+ /*
+ * NB: do not touch columns -- keep info from previous dissector
+ */
+
+ if (tree)
+ {
+ proto_item* item;
+ item = proto_tree_add_item(tree, proto_cell, tvb, 0, dissect_size, FALSE);
+ {
+ pwatm_private_data_t * pd;
+ pd = pinfo->private_data;
+ if (NULL != pd)
+ {
+ proto_item_append_text(item," [%.3d]",pd->pw_cell_number);
+ }
+ }
+ pwc_item_append_text_n_items(item,dissect_size,"byte");
+ if (!is_enough_data)
+ {
+ expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
+ ,"Bad length of cell payload: must be == %d"
+ ,(int)SIZEOF_ATM_CELL_PAYLOAD);
+ }
+
+ {
+ proto_tree* tree;
+ tvbuff_t* tvb_d;
+ tree = proto_item_add_subtree(item, ett_cell);
+ tvb_d = tvb_new_subset(tvb, 0, dissect_size, -1);
+ call_dissector(dh_data, tvb_d, pinfo, tree);
+ item = proto_tree_add_int(tree, hf_cell_payload_len, tvb, 0, 0, dissect_size);
+ PROTO_ITEM_SET_HIDDEN(item);
+ }
+ }
+ return dissect_size;
+}
+
+
+void proto_register_pw_atm_ata(void)
+{
+ static const value_string clp_vals[] = {
+ { 0, "High priority" },
+ { 1, "Low priority" },
+ { 0, NULL }
+ };
+ static const value_string m_vals[] = {
+ { 0, "ATM cell" },
+ { 1, "AAL5 payload" },
+ { 0, NULL }
+ };
+ static const value_string u_vals[] = {
+ { 0, "This frame does not contain the last cell of AAL5 PDU" },
+ { 1, "This frame contains the last cell of AAL5 PDU" },
+ { 0, NULL }
+ };
+ static const value_string e_vals[] = {
+ { 0, "Congestion is not experienced" },
+ { 1, "Congestion is experienced for one or more ATM AAL5 cells" },
+ { 0, NULL }
+ };
+ static hf_register_info hfa_cell_header[] = {
+ { &hf_cell_h_vpi ,{"VPI" ,"atm.vpi"
+ ,FT_UINT16 ,BASE_DEC ,NULL ,0
+ ,NULL ,HFILL }}
+ ,{ &hf_cell_h_vci ,{"VCI" ,"atm.vci"
+ ,FT_UINT16 ,BASE_DEC ,NULL ,0
+ ,NULL ,HFILL }}
+ ,{ &hf_cell_h_pti ,{"Payload Type" ,"atm.pti"
+ ,FT_UINT8 ,BASE_DEC ,VALS(atm_pt_vals),0x0e
+ ,"The 3-bit Payload Type Identifier (PTI) incorporates ATM Layer"
+ " PTI coding of the cell. These bits are set to the value of the"
+ " PTI of the encapsulated ATM cell."
+ ,HFILL }}
+ ,{ &hf_cell_h_clp ,{"Cell Loss Priority" ,"atm.clp"
+ ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x01
+ ,"The Cell Loss Priority (CLP) field indicates CLP value"
+ " of the encapsulated cell."
+ ,HFILL }}
+ ,{ &hf_cell_h_m ,{"Transport Mode" ,"atm.pw_control_byte.m"
+ ,FT_UINT8 ,BASE_DEC ,VALS(m_vals) ,0x80
+ ,"Bit (M) of the control byte indicates whether the packet"
+ " contains an ATM cell or a frame payload. If set to 0,"
+ " the packet contains an ATM cell. If set to 1, the PDU"
+ " contains an AAL5 payload."
+ ,HFILL }}
+ ,{ &hf_cell_h_v ,{"VCI Present" ,"atm.pw_control_byte.v"
+ ,FT_BOOLEAN ,8 ,TFS(&tfs_yes_no),0x40
+ ,"Bit (V) of the control byte indicates whether the VCI field"
+ " is present in the packet. If set to 1, the VCI field is present"
+ " for the cell. If set to 0, no VCI field is present."
+ ,HFILL }}
+ ,{ &hf_cell_h_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0x30
+ ,"The reserved bits should be set to 0 at the transmitter and"
+ " ignored upon reception."
+ ,HFILL }}
+ ,{ &hf_aal5_pdu_rsv ,{"Reserved bits" ,"atm.pw_control_byte.rsv"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0x38
+ ,"The reserved bits should be set to 0 at the transmitter and"
+ " ignored upon reception."
+ ,HFILL }}
+ ,{ &hf_aal5_pdu_u ,{"U bit" ,"atm.pw_control_byte.u"
+ ,FT_UINT8 ,BASE_DEC ,VALS(u_vals) ,0x04
+ ,"Indicates whether this frame contains the last cell of"
+ " an AAL5 PDU and represents the value of the ATM User-to-User"
+ " bit for the last ATM cell of the PSN frame. Note: The ATM"
+ " User-to-User bit is the least significant bit of the PTI"
+ " in the ATM header."
+ ,HFILL }}
+ ,{ &hf_aal5_pdu_e ,{"EFCI" ,"atm.pw_control_byte.efci"
+ ,FT_UINT8 ,BASE_DEC ,VALS(e_vals) ,0x02
+ ,"EFCI is set to the EFCI state of the last cell of the"
+ " AAL5 PDU or AAL5 fragment. Note: The EFCI state is"
+ " indicated in the middle bit of each ATM cell's PTI."
+ ,HFILL }}
+ };
+static hf_register_info hfa_cell[] = {
+ {&hf_cell_payload_len ,{"Length" ,"atm.cell.len"
+ ,FT_INT32 ,BASE_DEC ,NULL ,0
+ ,NULL ,HFILL }}
+ };
+
+ #define HF_INITIALIZER_NCELLS(hf_handle)\
+ {&(hf_handle) ,{"Number of good encapsulated cells","pw.atm.cells"\
+ ,FT_INT32 ,BASE_DEC ,NULL ,0\
+ ,NULL ,HFILL }}
+
+ #define HF_INITIALIZER_PWTYPE(hf_handle,name)\
+ { &hf_handle ,{name ,name\
+ ,FT_BOOLEAN ,0 ,NULL ,0x0\
+ ,"Identifies type of ATM PW. May be used for filtering.",HFILL}}
+
+
+ static hf_register_info hfa_n1_nocw[] = {
+ HF_INITIALIZER_NCELLS(hf_n1_nocw_ncells)
+ ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_nocw,"pw.type.atm.n1nocw")
+ };
+
+ static hf_register_info hfa_n1_cw[] = {
+ HF_INITIALIZER_NCELLS(hf_n1_cw_ncells)
+ ,HF_INITIALIZER_PWTYPE(hf_pw_type_n1_cw,"pw.type.atm.n1cw")
+ };
+
+ static hf_register_info hfa_11_aal5pdu[] = {
+ HF_INITIALIZER_NCELLS(hf_11_ncells)
+ ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vcc,"pw.type.atm.11vcc")
+ ,HF_INITIALIZER_PWTYPE(hf_pw_type_11_vpc,"pw.type.atm.11vpc")
+ ,HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_pdu,"pw.type.atm.aal5pdu")
+ };
+
+ static hf_register_info hfa_aal5_sdu[] = {
+ HF_INITIALIZER_PWTYPE(hf_pw_type_aal5_sdu,"pw.type.atm.aal5sdu")
+ };
+
+ static const value_string a5s_t_vals[] = {
+ { 0, "AAL5 payload" },
+ { 1, "ATM admin cell" },
+ { 0, NULL }
+ };
+
+ static const value_string a5s_e_vals[] = {
+ { 0, "No congestion" },
+ { 1, "Congestion experienced" },
+ { 0, NULL }
+ };
+
+ static hf_register_info hfa_cw[] = {
+ { &hf_cw_bits03 ,{"Bits 0 to 3" ,"pw.cw.bits03"
+ ,FT_UINT8 ,BASE_HEX ,NULL ,0xf0
+ ,NULL ,HFILL }}
+ ,{ &hf_pref_cw_flags ,{"Flags" ,"pw.cw.flags"
+ ,FT_UINT8 ,BASE_HEX ,NULL ,0x0f
+ ,NULL ,HFILL }}
+ ,{ &hf_pref_cw_a5s_t ,{"Payload type" ,"atm.pt"
+ ,FT_UINT8 ,BASE_DEC ,VALS(a5s_t_vals),0x08
+ ,"Bit (T) of the control word indicates whether the packet contains"
+ " an ATM admin cell or an AAL5 payload. If T = 1, the packet"
+ " contains an ATM admin cell, encapsulated according to the N:1"
+ " cell relay encapsulation. If not set, the PDU"
+ " contains an AAL5 payload."
+ ,HFILL }}
+ ,{ &hf_pref_cw_a5s_e ,{"EFCI bit" ,"atm.efci"
+ ,FT_UINT8 ,BASE_DEC ,VALS(a5s_e_vals),0x04
+ ,"The ingress router sets this bit to 1 if the EFCI bit"
+ " of the final cell of those that transported the AAL5 CPCS-SDU is"
+ " set to 1, or if the EFCI bit of the single ATM cell to be"
+ " transported in the packet is set to 1. Otherwise, this bit"
+ " is set to 0."
+ ,HFILL }}
+ ,{ &hf_pref_cw_a5s_c ,{"CLP bit" ,"atm.clp"
+ ,FT_UINT8 ,BASE_DEC ,VALS(clp_vals) ,0x02
+ ,"The ingress router sets this bit to 1 if the CLP bit"
+ " of any of the ATM cells that transported the AAL5 CPCS-SDU is set"
+ " to 1, or if the CLP bit of the single ATM cell to be transported"
+ " in the packet is set to 1. Otherwise this bit is set to 0."
+ ,HFILL }}
+ ,{ &hf_pref_cw_a5s_u ,{"U bit (Command/Response)" ,"pw.cw.aal5sdu.u"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0x01
+ ,"When FRF.8.1 Frame Relay/ATM PVC Service Interworking [RFC3916]"
+ " traffic is being transported, the Least-Significant Bit of CPCS-UU"
+ " of the AAL5 CPCS-PDU may contain the Frame Relay C/R bit."
+ " The ingress router copies this bit here."
+ ,HFILL }}
+ ,{ &hf_pref_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0xc0
+ ,NULL ,HFILL }}
+ ,{ &hf_generic_cw_rsv ,{"Reserved bits" ,"pw.cw.rsv"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0x0f
+ ,NULL ,HFILL }}
+ ,{ &hf_pref_cw_len ,{"Length" ,"pw.cw.length"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0x3f
+ ,NULL ,HFILL }}
+ ,{ &hf_pref_cw_rsvlen ,{"Length (extended)" ,"pw.cw.length"
+ ,FT_UINT8 ,BASE_DEC ,NULL ,0xff
+ ,NULL ,HFILL }}
+ ,{ &hf_cw_seq ,{"Sequence number" ,"pw.cw.seqno"
+ ,FT_UINT16 ,BASE_DEC ,NULL ,0
+ ,NULL ,HFILL }}
+ ,{ &hf_gen_cw_atmbyte ,{"ATM-specific byte" ,"pw.cw.3rd_byte"
+ ,FT_UINT8 ,BASE_HEX ,NULL ,0xFF
+ ,NULL ,HFILL }}
+ };
+ static gint *ett_array[] = {
+ &ett_encaps
+ ,&ett_cw
+ ,&ett_cell_header
+ ,&ett_cell
+ };
+
+ proto_n1_cw =
+ proto_register_protocol(pwc_longname_pw_atm_n1_cw
+ ,shortname_n1_cw
+ ,"mplspwatmn1cw");
+ proto_11_or_aal5_pdu =
+ proto_register_protocol(pwc_longname_pw_atm_11_or_aal5_pdu
+ ,shortname_11_or_aal5_pdu
+ ,"mplspwatm11_or_aal5pdu");
+ proto_aal5_sdu =
+ proto_register_protocol(pwc_longname_pw_atm_aal5_sdu
+ ,shortname_aal5_sdu
+ ,"mplspwatmaal5sdu");
+ proto_n1_nocw =
+ proto_register_protocol(pwc_longname_pw_atm_n1_nocw
+ ,shortname_n1_nocw
+ ,"mplspwatmn1nocw");
+ proto_control_word =
+ proto_register_protocol("MPLS PW ATM Control Word"
+ ,"MPLS PW ATM Control Word"
+ ,"mplspwatmcontrolword");
+ proto_cell_header =
+ proto_register_protocol("MPLS PW ATM Cell Header"
+ ,"MPLS PW ATM Cell Header"
+ ,"mplspwatmcellheader");
+ proto_cell =
+ proto_register_protocol("ATM Cell"
+ ,"ATM Cell"
+ ,"mplspwatmcell");
+
+ proto_register_field_array( proto_cell ,hfa_cell ,array_length(hfa_cell));
+ proto_register_field_array( proto_cell_header ,hfa_cell_header,array_length(hfa_cell_header));
+ proto_register_field_array( proto_control_word ,hfa_cw ,array_length(hfa_cw));
+ proto_register_field_array( proto_n1_nocw ,hfa_n1_nocw ,array_length(hfa_n1_nocw));
+ proto_register_field_array( proto_n1_cw ,hfa_n1_cw ,array_length(hfa_n1_cw));
+ proto_register_field_array( proto_11_or_aal5_pdu ,hfa_11_aal5pdu ,array_length(hfa_11_aal5pdu));
+ proto_register_field_array( proto_aal5_sdu ,hfa_aal5_sdu ,array_length(hfa_aal5_sdu));
+
+ proto_register_subtree_array(ett_array, array_length(ett_array));
+
+ register_dissector("mpls_pw_atm_aal5_sdu" ,dissect_aal5_sdu ,proto_aal5_sdu);
+ register_dissector("mpls_pw_atm_11_or_aal5_pdu" ,dissect_11_or_aal5_pdu ,proto_11_or_aal5_pdu);
+ register_dissector("mpls_pw_atm_n1_cw" ,dissect_n1_cw ,proto_n1_cw);
+ register_dissector("mpls_pw_atm_n1_nocw" ,dissect_n1_nocw ,proto_n1_nocw);
+ register_dissector("mpls_pw_atm_control_word" ,dissect_control_word ,proto_control_word);
+ new_register_dissector("mpls_pw_atm_cell" ,dissect_cell ,proto_cell);
+ new_register_dissector("mpls_pw_atm_cell_header",dissect_cell_header ,proto_cell_header);
+ {
+ static const char description_allow_cw_length_nonzero[] =
+ "Enable to allow non-zero Length in Control Word."
+ " This may be needed to correctly decode traffic from some legacy devices"
+ " which generate non-zero Length even if there is no padding in the packet."
+ " Note that Length should have proper value (dissector checks this anyway)."
+ "\n\n"
+ "Disable to blame all packets with CW.Length <> 0. This conforms to RFC4717."
+ ;
+ static const char description_extend_cw_length_with_rsvd[] =
+ "Enable to use reserved bits (8..9) of Control Word as an extension of CW.Length."
+ " This may be needed to correctly decode traffic from some legacy devices"
+ " which uses reserved bits as extension of Length"
+ "\n\n"
+ "Disable to blame all packets with CW.Reserved <> 0. This conforms to RFC4717."
+ ;
+ module_t * module_n1_cw;
+ module_t * module_aal5_sdu;
+
+ module_n1_cw = prefs_register_protocol(proto_n1_cw,NULL);
+ prefs_register_bool_preference(module_n1_cw
+ ,"allow_cw_length_nonzero"
+ ,"Allow CW.Length <> 0"
+ ,&description_allow_cw_length_nonzero[0]
+ ,&pref_n1_cw_allow_cw_length_nonzero);
+ prefs_register_bool_preference(module_n1_cw
+ ,"extend_cw_length_with_rsvd"
+ ,"Use CW.Reserved as extension of CW.Length"
+ ,&description_extend_cw_length_with_rsvd[0]
+ ,&pref_n1_cw_extend_cw_length_with_rsvd);
+
+ module_aal5_sdu = prefs_register_protocol(proto_aal5_sdu,NULL);
+ prefs_register_bool_preference(module_aal5_sdu
+ ,"allow_cw_length_nonzero_aal5"
+ ,"Allow CW.Length <> 0"
+ ,&description_allow_cw_length_nonzero[0]
+ ,&pref_aal5_sdu_allow_cw_length_nonzero);
+ prefs_register_bool_preference(module_aal5_sdu
+ ,"extend_cw_length_with_rsvd_aal5"
+ ,"Use CW.Reserved as extension of CW.Length"
+ ,&description_extend_cw_length_with_rsvd[0]
+ ,&pref_aal5_sdu_extend_cw_length_with_rsvd);
+ }
+}
+
+
+void proto_reg_handoff_pw_atm_ata(void)
+{
+ dissector_handle_t h;
+ h = find_dissector("mpls_pw_atm_n1_cw");
+ dissector_add( "mpls.label", LABEL_INVALID, h );
+ h = find_dissector("mpls_pw_atm_n1_nocw");
+ dissector_add( "mpls.label", LABEL_INVALID, h );
+ h = find_dissector("mpls_pw_atm_11_or_aal5_pdu");
+ dissector_add( "mpls.label", LABEL_INVALID, h );
+ h = find_dissector("mpls_pw_atm_aal5_sdu");
+ dissector_add( "mpls.label", LABEL_INVALID, h );
- data_h = find_dissector("data");
- atm_h = find_dissector("atm_4717");
+ dh_cell = find_dissector("mpls_pw_atm_cell");
+ dh_cell_header = find_dissector("mpls_pw_atm_cell_header");
+ dh_control_word = find_dissector("mpls_pw_atm_control_word");
+ dh_atm_truncated = find_dissector("atm_truncated");
+ dh_atm_untruncated = find_dissector("atm_untruncated");
+ dh_atm_oam_cell = find_dissector("atm_oam_cell");
+ dh_padding = find_dissector("pw_padding");
+ dh_data = find_dissector("data");
}
diff --git a/epan/dissectors/packet-pw-atm.h b/epan/dissectors/packet-pw-atm.h
new file mode 100644
index 0000000000..d1b0346b25
--- /dev/null
+++ b/epan/dissectors/packet-pw-atm.h
@@ -0,0 +1,101 @@
+/* packet-pw-atm.h
+ * Interface of pw-atm module
+ * Copyright 2009, Artem Tamazov <artem.tamazov@tellabs.com>
+ *
+ * $Id$
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PACKET_PW_ATM_H
+#define PACKET_PW_ATM_H
+
+#include "packet-pw-common.h"
+
+typedef enum {
+ PWATM_MODE_UNKNOWN = 0
+ ,PWATM_MODE_N1_NOCW
+ ,PWATM_MODE_N1_CW
+ ,PWATM_MODE_11_VCC
+ ,PWATM_MODE_11_VPC
+ ,PWATM_MODE_AAL5_SDU
+ ,PWATM_MODE_AAL5_PDU
+} pwatm_mode_t;
+
+typedef enum {
+ PWATM_SUBMODE_DEFAULT = 0
+ ,PWATM_SUBMODE_ADMIN_CELL /*used in aal5_sdu dissector only*/
+} pwatm_submode_t;
+
+typedef struct {
+ int pw_cell_number;
+ pwc_packet_properties_t props;
+ gint packet_size;
+ pwatm_mode_t mode;
+ pwatm_submode_t submode;
+ struct {
+ /*
+ * ATM-specific attributes which remain the same
+ * across all the cells in the pw packet. Values are filled
+ * by sub-dissectors and read by upper-level dissector.
+ * Meanings of values:
+ * (-1) - value is unknown
+ * (-2) - value is different among cells
+ * positive - value is the same in all cells
+ * Machinery is implemented in the UPDATE_CUMULATIVE_VALUE macro.
+ */
+ gint32 vpi;
+ gint32 vci;
+ gint32 clp;
+ gint32 pti;
+ } cumulative;
+ gint32 vpi; /*-1 if unknown*/
+ gint32 vci; /*-1 if unknown*/
+ gint32 pti; /*-1 if unknown*/
+ struct {
+ /*
+ * Some fields from 3rd byte of CW. Filled by cell_header dissector.
+ * In in AAL5 PDU mode, this allows control_word dissector to print
+ * these values in the CW heading line in the tree.
+ * Meanings of values:
+ * (-1) - value is unknown
+ */
+ gint32 m;
+ gint32 v;
+ gint32 rsv;
+ gint32 u;
+ gint32 e;
+ gint32 clp;
+ } cwb3;
+ gboolean aal5_sdu_frame_relay_cr_bit; /*see rfc4717 10.1*/
+ gboolean cell_mode_oam; /*atm admin cell*/
+ gboolean enable_fill_columns_by_atm_dissector;
+} pwatm_private_data_t;
+
+
+#define PWATM_PRIVATE_DATA_T_INITIALIZER { \
+ 0, PWC_PACKET_PROPERTIES_T_INITIALIZER, 0 \
+ ,PWATM_MODE_UNKNOWN, PWATM_SUBMODE_DEFAULT \
+ ,{-1, -1, -1, -1 } \
+ ,-1, -1, -1 \
+ ,{-1, -1, -1, -1, -1, -1 } \
+ ,FALSE, FALSE, TRUE \
+ }
+
+#endif /*PACKET_PW_ATM_H*/
diff --git a/epan/dissectors/packet-pw-cesopsn.c b/epan/dissectors/packet-pw-cesopsn.c
index e8656adb1a..be77883010 100644
--- a/epan/dissectors/packet-pw-cesopsn.c
+++ b/epan/dissectors/packet-pw-cesopsn.c
@@ -56,12 +56,12 @@ static int hf_cw_frg = -1;
static int hf_cw_len = -1;
static int hf_cw_seq = -1;
static int hf_payload = -1;
-static int hf_padding = -1;
-static int hf_padding_f = -1;
+static int hf_payload_l = -1;
static dissector_handle_t data_handle;
+static dissector_handle_t pw_padding_handle;
-static const char pwc_longname_pw_cesopsn[] = "CESoPSN basic NxDS0 mode (no RTP support)";
+const char pwc_longname_pw_cesopsn[] = "CESoPSN basic NxDS0 mode (no RTP support)";
static const char shortname[] = "CESoPSN basic (no RTP)";
static const value_string vals_cw_lm[] = {
@@ -121,7 +121,7 @@ static void dissect_pw_cesopsn( tvbuff_t * tvb_original, packet_info * pinfo, pr
/* check how "good" is this packet */
/* also decide payload length from packet size and CW */
- properties = 0;
+ properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
{
properties |= PWC_CW_BAD_BITS03;
@@ -188,7 +188,7 @@ static void dissect_pw_cesopsn( tvbuff_t * tvb_original, packet_info * pinfo, pr
{
guint8 cw_lm;
cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
- if (!pwc_value_listed_in_vals(cw_lm, vals_cw_lm))
+ if (NULL == match_strval(cw_lm, vals_cw_lm))
{
properties |= PWC_CW_SUSPECT_LM;
}
@@ -348,6 +348,9 @@ static void dissect_pw_cesopsn( tvbuff_t * tvb_original, packet_info * pinfo, pr
}
tree = proto_item_add_subtree(item, ett);
call_dissector(data_handle, tvb, pinfo, tree);
+ item = proto_tree_add_int(tree, hf_payload_l, tvb, 0, 0
+ ,(int)payload_size); /* allow filtering */
+ PROTO_ITEM_SET_HIDDEN(item);
}
}
@@ -357,12 +360,9 @@ static void dissect_pw_cesopsn( tvbuff_t * tvb_original, packet_info * pinfo, pr
proto_tree* tree;
tree = proto_item_add_subtree(item, ett);
{
- proto_item* item;
tvbuff_t* tvb;
tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
- item = proto_tree_add_item(tree, hf_padding, tvb, 0, -1, FALSE);
- pwc_item_append_text_n_items(item,(int)padding_size,"octet");
- call_dissector(data_handle, tvb, pinfo, tree);
+ call_dissector(pw_padding_handle, tvb, pinfo, tree);
}
}
}
@@ -396,11 +396,8 @@ void proto_register_pw_cesopsn(void)
,{&hf_payload ,{"TDM payload" ,"pwcesopsn.payload"
,FT_BYTES ,BASE_NONE ,NULL
,0 ,NULL ,HFILL }}
- ,{&hf_padding ,{"Padding" ,"pwcesopsn.padding"
- ,FT_BYTES ,BASE_NONE ,NULL
- ,0 ,NULL ,HFILL }}
- ,{&hf_padding_f ,{"Padding (formatted)" ,""
- ,FT_BYTES ,BASE_NONE ,NULL
+ ,{&hf_payload_l ,{"TDM payload length" ,"pwcesopsn.payload.len"
+ ,FT_INT32 ,BASE_DEC ,NULL
,0 ,NULL ,HFILL }}
};
@@ -420,6 +417,7 @@ void proto_reg_handoff_pw_cesopsn(void)
dissector_handle_t h;
h = find_dissector("pw_cesopsn");
data_handle = find_dissector("data");
+ pw_padding_handle = find_dissector("pw_padding");
dissector_add("mpls.label", LABEL_INVALID, h);
return;
}
diff --git a/epan/dissectors/packet-pw-common.c b/epan/dissectors/packet-pw-common.c
index 21f88ef016..e879e02e41 100644
--- a/epan/dissectors/packet-pw-common.c
+++ b/epan/dissectors/packet-pw-common.c
@@ -28,6 +28,7 @@
#endif
#include <string.h>
+#include <epan/packet.h>
#include "packet-pw-common.h"
static const char string_ok[] = "Ok";
@@ -57,22 +58,6 @@ pwc_vals_cw_frag[] = {
};
-int pwc_value_listed_in_vals(const guint32 val, const value_string * vals)
-{
- if (NULL != vals)
- {
- while (vals->strptr != NULL)
- {
- if (val == vals->value)
- {
- return (1==1);
- }
- ++vals;
- }
- }
- return 0;
-}
-
void pwc_item_append_cw(proto_item* item, const guint32 cw, const gboolean append_text)
{
if (item != NULL)
@@ -90,8 +75,61 @@ void pwc_item_append_cw(proto_item* item, const guint32 cw, const gboolean appen
void pwc_item_append_text_n_items(proto_item* item, const int n, const char * const item_text)
{
assert(item != 0);
- proto_item_append_text(item, ", %d %s%s", n, item_text, plurality(n,"","s"));
+ if (n >=0)
+ {
+ proto_item_append_text(item, ", %d %s%s", n, item_text, plurality(n,"","s"));
+ }
+ return;
+}
+
+
+static gint proto_pw_padding = -1;
+static gint ett = -1;
+static int hf_padding_len = -1;
+static dissector_handle_t dh_data;
+
+static
+void dissect_pw_padding(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
+{
+ /* do not touch columns */
+ if (tree)
+ {
+ gint size;
+ proto_item* item;
+ size = tvb_reported_length_remaining(tvb, 0);
+ item = proto_tree_add_item(tree, proto_pw_padding, tvb, 0, -1, FALSE);
+ pwc_item_append_text_n_items(item,size,"byte");
+ {
+ proto_tree* tree;
+ tree = proto_item_add_subtree(item, ett);
+ call_dissector(dh_data, tvb, pinfo, tree);
+ item = proto_tree_add_int(tree, hf_padding_len, tvb, 0, 0, size);
+ PROTO_ITEM_SET_HIDDEN(item); /*allow filtering*/
+ }
+ }
+ return;
+}
+
+void proto_register_pw_padding(void)
+{
+ static hf_register_info hfpadding[] = {
+ {&hf_padding_len ,{"Length" ,"pw.padding.len"
+ ,FT_INT32 ,BASE_DEC ,NULL ,0
+ ,NULL ,HFILL }}
+ };
+ static gint *ett_array[] = {
+ &ett
+ };
+ proto_pw_padding = proto_register_protocol("Pseudowire Padding","PW Padding","pwpadding");
+ proto_register_field_array(proto_pw_padding, hfpadding, array_length(hfpadding));
+ proto_register_subtree_array(ett_array, array_length(ett_array));
+ register_dissector("pw_padding", dissect_pw_padding, proto_pw_padding);
return;
}
+void proto_reg_handoff_pw_padding(void)
+{
+ dh_data = find_dissector("data");
+ return;
+}
diff --git a/epan/dissectors/packet-pw-common.h b/epan/dissectors/packet-pw-common.h
index 81f6b99a73..bf8b99060b 100644
--- a/epan/dissectors/packet-pw-common.h
+++ b/epan/dissectors/packet-pw-common.h
@@ -31,6 +31,13 @@
#define PWC_SIZEOF_CW 4
+extern const char pwc_longname_pw_satop[];
+extern const char pwc_longname_pw_cesopsn[];
+extern const char pwc_longname_pw_atm_n1_cw[];
+extern const char pwc_longname_pw_atm_n1_nocw[];
+extern const char pwc_longname_pw_atm_11_or_aal5_pdu[];
+extern const char pwc_longname_pw_atm_aal5_sdu[];
+
extern const value_string pwc_vals_cw_l_bit[];
extern const value_string pwc_vals_cw_r_bit[];
extern const value_string pwc_vals_cw_frag[];
@@ -42,19 +49,26 @@ typedef enum {
,PWC_CW_BAD_LEN_MUST_BE_0 = 1 << 3
,PWC_CW_BAD_FRAG = 1 << 4
,PWC_CW_BAD_RSV = 1 << 5
+ ,PWC_CW_BAD_FLAGS = 1 << 8
+ ,PWC_CW_BAD_PAYLEN_LE_0 = 1 << 9
+ ,PWC_CW_BAD_PADDING_NE_0 = 1 << 10
,PWC_ANYOF_CW_BAD = PWC_CW_BAD_BITS03
+ PWC_CW_BAD_PAYLEN_LT_0
+ PWC_CW_BAD_PAYLEN_GT_PACKET
+ PWC_CW_BAD_LEN_MUST_BE_0
+ PWC_CW_BAD_FRAG
+ PWC_CW_BAD_RSV
+ + PWC_CW_BAD_FLAGS
+ + PWC_CW_BAD_PAYLEN_LE_0
+ + PWC_CW_BAD_PADDING_NE_0
,PWC_CW_SUSPECT_LM = 1 << 6
,PWC_ANYOF_CW_SUSPECT = PWC_CW_SUSPECT_LM
,PWC_PAY_SIZE_BAD = 1 << 7
-} pwc_packet_properties_t;
+}
+pwc_packet_properties_t;
+#define PWC_PACKET_PROPERTIES_T_INITIALIZER 0
extern void pwc_item_append_cw(proto_item* item, const guint32 cw, const gboolean append_text);
extern void pwc_item_append_text_n_items(proto_item* item, const int n, const char * const item_text);
-extern int pwc_value_listed_in_vals(const guint32 val, const value_string * vals);
#endif
diff --git a/epan/dissectors/packet-pw-satop.c b/epan/dissectors/packet-pw-satop.c
index 65eacb6a9b..5db068eb1f 100644
--- a/epan/dissectors/packet-pw-satop.c
+++ b/epan/dissectors/packet-pw-satop.c
@@ -56,12 +56,12 @@ static int hf_cw_frg = -1;
static int hf_cw_len = -1;
static int hf_cw_seq = -1;
static int hf_payload = -1;
-static int hf_padding = -1;
-static int hf_padding_f = -1;
+static int hf_payload_l = -1;
static dissector_handle_t data_handle;
+static dissector_handle_t pw_padding_handle;
-static const char pwc_longname_pw_satop[] = "SAToP (no RTP support)";
+const char pwc_longname_pw_satop[] = "SAToP (no RTP support)";
static const char shortname[] = "SAToP (no RTP)";
@@ -80,7 +80,7 @@ static void dissect_pw_satop(tvbuff_t * tvb_original, packet_info * pinfo, proto
,PAY_LIKE_OCTET_ALIGNED_T1
} payload_properties;
- properties = 0;
+ properties = PWC_PACKET_PROPERTIES_T_INITIALIZER;
payload_properties = PAY_NO_IDEA;
packet_size = tvb_reported_length_remaining(tvb_original, 0);
/*
@@ -364,6 +364,9 @@ static void dissect_pw_satop(tvbuff_t * tvb_original, packet_info * pinfo, proto
proto_item_append_text(item, "%s", s);
tree = proto_item_add_subtree(item, ett);
call_dissector(data_handle, tvb, pinfo, tree);
+ item = proto_tree_add_int(tree, hf_payload_l, tvb, 0, 0
+ ,(int)payload_size); /* allow filtering */
+ PROTO_ITEM_SET_HIDDEN(item);
}
}
}
@@ -374,16 +377,9 @@ static void dissect_pw_satop(tvbuff_t * tvb_original, packet_info * pinfo, proto
proto_tree* tree;
tree = proto_item_add_subtree(item, ett);
{
- proto_item* item;
tvbuff_t* tvb;
tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
- item = proto_tree_add_item(tree, hf_padding, tvb, 0, -1, FALSE);
- pwc_item_append_text_n_items(item,(int)padding_size,"octet");
- {
- proto_tree* tree;
- tree = proto_item_add_subtree(item, ett);
- call_dissector(data_handle, tvb, pinfo, tree);
- }
+ call_dissector(pw_padding_handle, tvb, pinfo, tree);
}
}
}
@@ -421,11 +417,8 @@ void proto_register_pw_satop(void)
,{&hf_payload ,{"TDM payload" ,"pwsatop.payload"
,FT_BYTES ,BASE_NONE ,NULL
,0 ,NULL ,HFILL }}
- ,{&hf_padding ,{"Padding" ,"pwsatop.padding"
- ,FT_BYTES ,BASE_NONE ,NULL
- ,0 ,NULL ,HFILL }}
- ,{&hf_padding_f ,{"Padding (formatted)" ,""
- ,FT_BYTES ,BASE_NONE ,NULL
+ ,{&hf_payload_l ,{"TDM payload length" ,"pwsatop.payload.len"
+ ,FT_INT32 ,BASE_DEC ,NULL
,0 ,NULL ,HFILL }}
};
@@ -445,5 +438,6 @@ void proto_reg_handoff_pw_satop(void)
dissector_handle_t h;
h = find_dissector("pw_satop");
data_handle = find_dissector("data");
+ pw_padding_handle = find_dissector("pw_padding");
dissector_add("mpls.label", LABEL_INVALID, h);
}
diff --git a/epan/packet_info.h b/epan/packet_info.h
index 394167badf..f5da1e1c54 100644
--- a/epan/packet_info.h
+++ b/epan/packet_info.h
@@ -187,28 +187,6 @@ typedef struct _packet_info {
struct _sccp_msg_info_t* sccp_info;
guint16 clnp_srcref; /* clnp/cotp source reference (can't use srcport, this would confuse tpkt) */
guint16 clnp_dstref; /* clnp/cotp destination reference (can't use dstport, this would confuse tpkt) */
- guint8 pw_atm_encap_type; /* FF: RFC 4717 is devilish, it describes many
- * different types of ATM->PW encapsulation.
- * None of which can correctly be interpreted by
- * the packet-atm.c dissector. Thus I have to
- * pass some info from packet-pw-atm.c to packet-
- * -atm.c, and augment/change packet-atm.c
- * dissector.
- *
- * 0: RFC4717::Sec. 9, ATM One-to-One Cell Mode
- * 1: RFC4717::Sec. 8, ATM N-to-One Cell Mode
- * 2: RFC4717::Sec. 10, ATM AAL5 CPCS-SDU Mode
- * 3: RFC4717::Sec. 11, ATM AAL5 PDU Frame Mode
- */
- guint16 pw_atm_flags; /* FF: all flags defined in RFC4717 compacted in a
- * single guint16.
- *
- * T, E, C, U, M, V, PTI, C flag name
- * 9 8 7 6 5 4 321 0 position
- */
- guint16 pw_atm_ncells; /* FF: number of cells fitted in a single
- * PW frame.
- */
guint16 zbee_cluster_id; /* ZigBee cluster ID, an application-specific message identifier that
* happens to be included in the transport (APS) layer header.