From c38e6ecbf6d5e637070453cbfca49b3b104f0094 Mon Sep 17 00:00:00 2001 From: Jaap Keuter Date: Tue, 3 Oct 2023 06:07:56 +0000 Subject: SAToP: Add optional RTP header handling --- epan/dissectors/packet-pw-satop.c | 126 +++++++++++++++++++++++++++++--------- 1 file changed, 98 insertions(+), 28 deletions(-) (limited to 'epan/dissectors/packet-pw-satop.c') diff --git a/epan/dissectors/packet-pw-satop.c b/epan/dissectors/packet-pw-satop.c index 6cfe7f7768..1c81483713 100644 --- a/epan/dissectors/packet-pw-satop.c +++ b/epan/dissectors/packet-pw-satop.c @@ -14,7 +14,6 @@ * 14.08.2009 added: support for IP/UDP demultiplexing * Not supported yet: * - Decoding of PW payload - * - Optional RTP Headers (RFC3550) */ #include "config.h" @@ -24,6 +23,9 @@ #include "packet-mpls.h" #include "packet-pw-common.h" +#include "packet-rtp.h" + +#define SIZEOF_RTP 12 void proto_register_pw_satop(void); void proto_reg_handoff_pw_satop(void); @@ -53,9 +55,12 @@ static dissector_handle_t pw_padding_handle; static dissector_handle_t pw_satop_udp_handle; static dissector_handle_t pw_satop_mpls_handle; +const char pwc_longname_pw_satop[] = "SAToP"; +static const char shortname[] = "SAToP"; -const char pwc_longname_pw_satop[] = "SAToP (no RTP support)"; -static const char shortname[] = "SAToP (no RTP)"; +/* Preferences */ +static gboolean pref_has_rtp_header = FALSE; +static gboolean pref_heuristic_rtp_header = TRUE; static @@ -64,11 +69,16 @@ void dissect_pw_satop(tvbuff_t * tvb_original ,proto_tree * tree ,pwc_demux_type_t demux) { - const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/ + int min_packet_size_this_dissector = PWC_SIZEOF_CW; + int encaps_size; gint packet_size; + gint rtp_header_offset; + gint cw_offset; gint payload_size; gint padding_size; int properties; + guint16 sn; + gboolean has_rtp_header; enum { PAY_NO_IDEA = 0 @@ -78,13 +88,27 @@ void dissect_pw_satop(tvbuff_t * tvb_original ,PAY_LIKE_OCTET_ALIGNED_T1 } payload_properties; + switch (demux) + { + case PWC_DEMUX_MPLS: + if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree)) + { + return; + } + break; + case PWC_DEMUX_UDP: + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + return; + } + packet_size = tvb_reported_length_remaining(tvb_original, 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 (pref_has_rtp_header) { + min_packet_size_this_dissector += SIZEOF_RTP; + } + + if (packet_size < min_packet_size_this_dissector) { proto_item *item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); @@ -99,30 +123,59 @@ void dissect_pw_satop(tvbuff_t * tvb_original switch (demux) { case PWC_DEMUX_MPLS: - if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree)) - { - return; - } + rtp_header_offset = PWC_SIZEOF_CW; + sn = tvb_get_guint16(tvb_original, 2, ENC_BIG_ENDIAN); break; case PWC_DEMUX_UDP: + rtp_header_offset = 0; + sn = tvb_get_guint16(tvb_original, SIZEOF_RTP + 2, ENC_BIG_ENDIAN); break; default: DISSECTOR_ASSERT_NOT_REACHED(); return; } + if ((pref_has_rtp_header) || + ((pref_heuristic_rtp_header) && + /* Check for RTP version 2, the other fields must be zero */ + (tvb_get_guint8(tvb_original, rtp_header_offset) == 0x80) && + /* Check the marker is zero. Unfortnately PT is not always from the dynamic range */ + ((tvb_get_guint8(tvb_original, rtp_header_offset + 1) & 0x80) == 0) && + /* The sequence numbers from cw and RTP header must match */ + (tvb_get_ntohs(tvb_original, rtp_header_offset + 2) == sn))) + { + switch (demux) + { + case PWC_DEMUX_MPLS: + cw_offset = 0; + break; + case PWC_DEMUX_UDP: + cw_offset = SIZEOF_RTP; + break; + default: + DISSECTOR_ASSERT_NOT_REACHED(); + return; + } + encaps_size = PWC_SIZEOF_CW + SIZEOF_RTP; + has_rtp_header = TRUE; + } else { + cw_offset = 0; + encaps_size = PWC_SIZEOF_CW; + has_rtp_header = FALSE; + } + /* check how "good" is this packet */ - /* also decide payload length from packet size and CW */ + /* also decide payload length from packet size, CW and optional RTP header */ properties = 0; - if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/)) + if (0 != (tvb_get_guint8(tvb_original, cw_offset) & 0xf0 /*bits03*/)) { properties |= PWC_CW_BAD_BITS03; } - if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/)) + if (0 != (tvb_get_guint8(tvb_original, cw_offset) & 0x03 /*rsv*/)) { properties |= PWC_CW_BAD_RSV; } - if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/)) + if (0 != (tvb_get_guint8(tvb_original, cw_offset + 1) & 0xc0 /*frag*/)) { properties |= PWC_CW_BAD_FRAG; } @@ -142,7 +195,7 @@ void dissect_pw_satop(tvbuff_t * tvb_original int cw_len; gint payload_size_from_packet; - cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f; + cw_len = tvb_get_guint8(tvb_original, cw_offset + 1) & 0x3f; payload_size_from_packet = packet_size - encaps_size; if (cw_len != 0) { @@ -186,7 +239,7 @@ void dissect_pw_satop(tvbuff_t * tvb_original * not blame packets with bad payload (including "bad" or "strange" SIZE of * payload) when L bit is set. */ - if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/)) + if (0 == (tvb_get_guint8(tvb_original, cw_offset) & 0x08 /*L bit*/)) { properties |= PWC_PAY_SIZE_BAD; } @@ -240,17 +293,22 @@ void dissect_pw_satop(tvbuff_t * tvb_original { proto_item* item; item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA); - pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE); - pwc_item_append_text_n_items(item,(int)payload_size,"octet"); + pwc_item_append_cw(item, tvb_get_ntohl(tvb_original, cw_offset), TRUE); + pwc_item_append_text_n_items(item, (int)payload_size, "octet"); { proto_tree* tree2; tree2 = proto_item_add_subtree(item, ett_pw_satop); + if (has_rtp_header && demux == PWC_DEMUX_UDP) + { + dissect_rtp_shim_header(tvb_original, 0, pinfo, tree2, NULL); + } + { tvbuff_t* tvb; proto_item* item2; - tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW); + tvb = tvb_new_subset_length(tvb_original, cw_offset, PWC_SIZEOF_CW); item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA); - pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0),FALSE); + pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0), FALSE); { proto_tree* tree3; tree3 = proto_item_add_subtree(item2, ett_pw_satop); @@ -262,8 +320,8 @@ void dissect_pw_satop(tvbuff_t * tvb_original expert_add_info(pinfo, item3, &ei_cw_bits03); } - proto_tree_add_item(tree3, hf_cw_l , tvb, 0, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(tree3, hf_cw_r , tvb, 0, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree3, hf_cw_l, tvb, 0, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(tree3, hf_cw_r, tvb, 0, 1, ENC_BIG_ENDIAN); item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN); if (properties & PWC_CW_BAD_RSV) @@ -301,6 +359,11 @@ void dissect_pw_satop(tvbuff_t * tvb_original } } } + + if (has_rtp_header && demux != PWC_DEMUX_UDP) + { + dissect_rtp_shim_header(tvb_original, PWC_SIZEOF_CW, pinfo, tree2, NULL); + } } /* payload */ @@ -321,9 +384,9 @@ void dissect_pw_satop(tvbuff_t * tvb_original { proto_item* item2; tvbuff_t* tvb; - tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size); + tvb = tvb_new_subset_length(tvb_original, encaps_size, payload_size); item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA); - pwc_item_append_text_n_items(item2,(int)payload_size,"octet"); + pwc_item_append_text_n_items(item2, (int)payload_size, "octet"); { proto_tree* tree3; const char* s; @@ -443,6 +506,8 @@ void proto_register_pw_satop(void) { &ei_payload_size_invalid, { "pwsatop.payload.size_invalid", PI_MALFORMED, PI_ERROR, "Bad Length: too small", EXPFILL }}, { &ei_payload_size_invalid_undecoded, { "pwsatop.payload.undecoded", PI_UNDECODED, PI_NOTE, "SAToP payload: omitted to conserve bandwidth", EXPFILL }}, }; + + module_t *pwsatop_module; expert_module_t* expert_pwsatop; proto = proto_register_protocol(pwc_longname_pw_satop, shortname, "pwsatopcw"); @@ -450,6 +515,11 @@ void proto_register_pw_satop(void) proto_register_subtree_array(ett_array, array_length(ett_array)); expert_pwsatop = expert_register_protocol(proto); expert_register_field_array(expert_pwsatop, ei, array_length(ei)); + pwsatop_module = prefs_register_protocol(proto, NULL); + prefs_register_bool_preference(pwsatop_module, "rtp_header", "RTP header in SAToP header", + "Whether or not the RTP header is present in the SAToP header.", &pref_has_rtp_header); + prefs_register_bool_preference(pwsatop_module, "rtp_header_heuristic", "Try to find RTP header in SAToP header", + "Heuristically determine if an RTP header is present in the SAToP header.", &pref_heuristic_rtp_header); pw_satop_mpls_handle = register_dissector("pw_satop_mpls", dissect_pw_satop_mpls, proto); pw_satop_udp_handle = register_dissector("pw_satop_udp", dissect_pw_satop_udp, proto); } -- cgit v1.2.3