SAToP: Add optional RTP header handling

This commit is contained in:
Jaap Keuter 2023-10-03 06:07:56 +00:00 committed by Alexis La Goutte
parent 46a7f4c17f
commit c38e6ecbf6
1 changed files with 106 additions and 36 deletions

View File

@ -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,24 +88,6 @@ void dissect_pw_satop(tvbuff_t * tvb_original
,PAY_LIKE_OCTET_ALIGNED_T1
} payload_properties;
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) */
{
proto_item *item;
item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small,
"PW packet size (%d) is too small to carry sensible information"
,(int)packet_size);
col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
return;
}
switch (demux)
{
case PWC_DEMUX_MPLS:
@ -111,18 +103,79 @@ void dissect_pw_satop(tvbuff_t * tvb_original
return;
}
packet_size = tvb_reported_length_remaining(tvb_original, 0);
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);
expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small,
"PW packet size (%d) is too small to carry sensible information"
,(int)packet_size);
col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
return;
}
switch (demux)
{
case PWC_DEMUX_MPLS:
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);
}