From 92c725cafb37067291022d3e9d05b9cbf4624b6e Mon Sep 17 00:00:00 2001 From: Jiri Novak Date: Fri, 16 Dec 2016 11:49:56 +0100 Subject: [PATCH] SIP/SDP, RTP: Dissectors shows information about ED-137 related states of radio in info column/VoIP call flow Based on EUROCAE ED-137B specification: ED-137B, Part 1: RADIO, INTEROPERABILITY STANDARDS FOR VOIP ATM COMPONENTS https://boutique.eurocae.net/eshop/catalog/index.php Bug: 13252 Change-Id: Ifab1aaf47e3405fcd46309167237f11ce2d7e2ff Reviewed-on: https://code.wireshark.org/review/19302 Petri-Dish: Michael Mann Tested-by: Petri Dish Buildbot Reviewed-by: Michael Mann --- epan/dissectors/packet-rtp.c | 55 +++++++++++++++++++++++++++- epan/dissectors/packet-rtp.h | 2 + epan/dissectors/packet-sdp.c | 71 +++++++++++++++++++++++++++++++++--- ui/rtp_stream.h | 1 + ui/voip_calls.c | 21 ++++++++++- 5 files changed, 142 insertions(+), 8 deletions(-) diff --git a/epan/dissectors/packet-rtp.c b/epan/dissectors/packet-rtp.c index 4bec497f39..6bfc9fa561 100644 --- a/epan/dissectors/packet-rtp.c +++ b/epan/dissectors/packet-rtp.c @@ -2106,6 +2106,8 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ rtp_info->info_setup_frame_num = 0; rtp_info->info_payload_type_str = NULL; rtp_info->info_payload_rate = 0; + rtp_info->info_is_ed137 = FALSE; + rtp_info->info_ed137_info = NULL; /* * Do we have all the data? @@ -2308,7 +2310,7 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ pinfo, rtp_hext_tree); } else { - if ( !(dissector_try_uint(rtp_hdr_ext_dissector_table, hdr_extension_id, newtvb, pinfo, rtp_hext_tree)) ) { + if ( !(dissector_try_uint_new(rtp_hdr_ext_dissector_table, hdr_extension_id, newtvb, pinfo, rtp_hext_tree, FALSE, rtp_info)) ) { unsigned int hdrext_offset; hdrext_offset = offset; @@ -2468,10 +2470,16 @@ dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_ return offset; } +/* We do not need to allocate/free strings */ +static char *ed137_ptt_only = "PTT"; +static char *ed137_squ_only = "SQU"; +static char *ed137_ptt_and_squ = "PTT+SQU"; + static int dissect_rtp_hdr_ext_ed137(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ ) { unsigned int hdr_extension_len; + struct _rtp_info *rtp_info=(struct _rtp_info *)data; hdr_extension_len = tvb_reported_length(tvb)/4; @@ -2480,7 +2488,10 @@ dissect_rtp_hdr_ext_ed137(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v unsigned int offset = 0; unsigned int hdrext_offset = 0; unsigned int i; + gboolean ed137_ptt = FALSE; + gboolean ed137_squ = FALSE; + rtp_info->info_is_ed137 = TRUE; if ( tree ) { proto_item *ti; ti = proto_tree_add_item(tree, hf_rtp_hdr_ed137s, tvb, offset, hdr_extension_len * 4, ENC_NA); @@ -2493,9 +2504,28 @@ dissect_rtp_hdr_ext_ed137(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, v if (RTP_ED137_ptt_mask(ext_value)) { col_append_str(pinfo->cinfo, COL_INFO, ", PTT"); + ed137_ptt = TRUE; } if (RTP_ED137_squ_mask(ext_value)) { col_append_str(pinfo->cinfo, COL_INFO, ", SQU"); + ed137_squ = TRUE; + } + + /* Map PTT/SQU bits to string */ + if (rtp_info != NULL) { + if (ed137_ptt) { + if (ed137_squ) { + rtp_info->info_ed137_info = ed137_ptt_and_squ; + } else { + rtp_info->info_ed137_info = ed137_ptt_only; + } + } else { + if (ed137_squ) { + rtp_info->info_ed137_info = ed137_squ_only; + } else { + rtp_info->info_ed137_info = NULL; + } + } } ti2 = proto_tree_add_item(rtp_hext_tree, hf_rtp_hdr_ed137, tvb, hdrext_offset, 4, ENC_NA); @@ -2561,6 +2591,7 @@ static int dissect_rtp_hdr_ext_ed137a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ ) { unsigned int hdr_extension_len; + struct _rtp_info *rtp_info=(struct _rtp_info *)data; hdr_extension_len = tvb_reported_length(tvb)/4; @@ -2569,7 +2600,10 @@ dissect_rtp_hdr_ext_ed137a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned int offset = 0; unsigned int hdrext_offset = 0; unsigned int i; + gboolean ed137_ptt = FALSE; + gboolean ed137_squ = FALSE; + rtp_info->info_is_ed137 = TRUE; if ( tree ) { proto_item *ti; ti = proto_tree_add_item(tree, hf_rtp_hdr_ed137s, tvb, offset, hdr_extension_len * 4, ENC_NA); @@ -2582,9 +2616,28 @@ dissect_rtp_hdr_ext_ed137a(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, if (RTP_ED137A_ptt_mask(ext_value)) { col_append_str(pinfo->cinfo, COL_INFO, ", PTT"); + ed137_ptt = TRUE; } if (RTP_ED137A_squ_mask(ext_value)) { col_append_str(pinfo->cinfo, COL_INFO, ", SQU"); + ed137_squ = TRUE; + } + + /* Map PTT/SQU bits to string */ + if (rtp_info != NULL) { + if (ed137_ptt) { + if (ed137_squ) { + rtp_info->info_ed137_info = ed137_ptt_and_squ; + } else { + rtp_info->info_ed137_info = ed137_ptt_only; + } + } else { + if (ed137_squ) { + rtp_info->info_ed137_info = ed137_squ_only; + } else { + rtp_info->info_ed137_info = NULL; + } + } } ti2 = proto_tree_add_item(rtp_hext_tree, hf_rtp_hdr_ed137a, tvb, hdrext_offset, 4, ENC_NA); diff --git a/epan/dissectors/packet-rtp.h b/epan/dissectors/packet-rtp.h index c14d0f2173..18a726fcad 100644 --- a/epan/dissectors/packet-rtp.h +++ b/epan/dissectors/packet-rtp.h @@ -49,6 +49,8 @@ struct _rtp_info { const guint8* info_data; /* pointer to raw rtp data */ const gchar *info_payload_type_str; gint info_payload_rate; + gboolean info_is_ed137; + const gchar *info_ed137_info; /* * info_data: pointer to raw rtp data = header + payload incl. padding. * That should be safe because the "epan_dissect_t" constructed for the packet diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c index 3c22b45de2..0e89645daf 100644 --- a/epan/dissectors/packet-sdp.c +++ b/epan/dissectors/packet-sdp.c @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -302,6 +303,13 @@ typedef struct { Note: wmem_file_scope, needs manual dealloc. */ } session_info_t; +/* Structure for private data to hold ED137 related values */ +typedef struct sdp_data_t { + char *ed137_type; /* Radio session type */ + char *ed137_txrxmode; /* Tx/Rx mode */ + char *ed137_fid; /* Frequency ID */ +} sdp_data_t; + /* here lie the debugging dumper functions */ #ifdef DEBUG_CONVERSATION @@ -1529,6 +1537,9 @@ typedef struct { #define SDP_CRYPTO 5 #define SDP_SPRTMAP 6 #define SDP_CANDIDATE 7 +#define SDP_ED137_TYPE 8 +#define SDP_ED137_TXRXMODE 9 +#define SDP_ED137_FID 10 static const sdp_names_t sdp_media_attribute_names[] = { { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */ @@ -1539,6 +1550,9 @@ static const sdp_names_t sdp_media_attribute_names[] = { { "crypto"}, /* 5 */ { "sprt"}, /* 6 */ { "candidate" }, /* 7 */ + { "type" }, /* 8 */ + { "txrxmode" }, /* 9 */ + { "fid" }, /* 10 */ }; static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len) @@ -1557,7 +1571,8 @@ static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len) static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length, transport_info_t *transport_info, session_info_t *session_info, - media_description_t *media_desc) + media_description_t *media_desc, + sdp_data_t *sdp_data) { proto_tree *sdp_media_attribute_tree, *parameter_item; proto_item *fmtp_item, *media_format_item, *parameter_tree; @@ -1998,6 +2013,24 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto case SDP_CANDIDATE: dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree, tvb, offset); break; + case SDP_ED137_TYPE: + /* Remember the value and add it to tree */ + sdp_data->ed137_type = attribute_value; + proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, + tvb, offset, -1, ENC_UTF_8|ENC_NA); + break; + case SDP_ED137_TXRXMODE: + /* Remember the value and add it to tree */ + sdp_data->ed137_txrxmode = attribute_value; + proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, + tvb, offset, -1, ENC_UTF_8|ENC_NA); + break; + case SDP_ED137_FID: + /* Remember the value and add it to tree */ + sdp_data->ed137_fid = attribute_value; + proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, + tvb, offset, -1, ENC_UTF_8|ENC_NA); + break; default: /* No special treatment for values of this attribute type, just add as one item. */ proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, @@ -2010,7 +2043,8 @@ static void call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length, transport_info_t *transport_info, session_info_t *session_info, - media_description_t *media_desc) + media_description_t *media_desc, + sdp_data_t *sdp_data) { if (hf == hf_owner) { dissect_sdp_owner(tvb, ti); @@ -2031,7 +2065,7 @@ call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, } else if (hf == hf_media) { dissect_sdp_media(tvb, pinfo, ti, media_desc); } else if (hf == hf_media_attribute) { - dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, session_info, media_desc); + dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, session_info, media_desc, sdp_data); } } @@ -2221,6 +2255,7 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex transport_info_t* transport_info = NULL; media_description_t *media_desc = NULL; session_info_t session_info; + sdp_data_t sdp_data; DPRINT2(("-------------------- setup_sdp_transport -------------------")); @@ -2230,6 +2265,8 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex return; } + memset(&sdp_data, 0, sizeof(sdp_data)); + if (request_frame != 0) transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame ); if (transport_info == NULL) { @@ -2332,7 +2369,8 @@ setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type ex hf, NULL, linelen-tokenoffset, transport_info, in_media_description ? NULL : &session_info, - media_desc); + media_desc, + &sdp_data); DENDENT(); } @@ -2394,6 +2432,7 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) guchar type, delim; int datalen, tokenoffset, hf = -1; char *string; + sdp_data_t sdp_data; transport_info_t local_transport_info; transport_info_t* transport_info = NULL; @@ -2407,6 +2446,8 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) sdp_pi = wmem_new(wmem_packet_scope(), sdp_packet_info); sdp_pi->summary_str[0] = '\0'; + memset(&sdp_data, 0, sizeof(sdp_data)); + if (!pinfo->fd->flags.visited) { transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->num ); @@ -2567,11 +2608,31 @@ dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) hf, sub_ti, linelen-tokenoffset, &local_transport_info, in_media_description ? NULL : &session_info, - in_media_description ? media_desc : NULL); + in_media_description ? media_desc : NULL, + &sdp_data); offset = next_offset; } + if (NULL != sdp_data.ed137_fid) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_fid); + if (strlen(sdp_pi->summary_str)) + g_strlcat(sdp_pi->summary_str, " ", 50); + g_strlcat(sdp_pi->summary_str, sdp_data.ed137_fid, 50); + } + if (NULL != sdp_data.ed137_txrxmode) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_txrxmode); + if (strlen(sdp_pi->summary_str)) + g_strlcat(sdp_pi->summary_str, " ", 50); + g_strlcat(sdp_pi->summary_str, sdp_data.ed137_txrxmode, 50); + } + if (NULL != sdp_data.ed137_type) { + col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_type); + if (strlen(sdp_pi->summary_str)) + g_strlcat(sdp_pi->summary_str, " ", 50); + g_strlcat(sdp_pi->summary_str, sdp_data.ed137_type, 50); + } + /* Done parsing media description, no more need for the session-level details. */ rtp_dyn_payload_free(session_info.rtp_dyn_payload); session_info.rtp_dyn_payload = NULL; diff --git a/ui/rtp_stream.h b/ui/rtp_stream.h index f4b46dd63f..602dce5c41 100644 --- a/ui/rtp_stream.h +++ b/ui/rtp_stream.h @@ -76,6 +76,7 @@ typedef struct _rtp_stream_info { tap_rtp_stat_t rtp_stats; /**< here goes the RTP statistics info */ gboolean problem; /**< if the streams had wrong sequence numbers or wrong timestamps */ + gchar *ed137_info; } rtp_stream_info_t; /** tapping modes */ diff --git a/ui/voip_calls.c b/ui/voip_calls.c index 609ead9fba..d376afcb9b 100644 --- a/ui/voip_calls.c +++ b/ui/voip_calls.c @@ -305,6 +305,7 @@ voip_calls_reset_all_taps(voip_calls_tapinfo_t *tapinfo) { strinfo = (rtp_stream_info_t *)list->data; wmem_free(NULL, strinfo->payload_type_name); + wmem_free(NULL, strinfo->ed137_info); list = g_list_next(list); } g_list_free(tapinfo->rtp_stream_list); @@ -620,6 +621,14 @@ rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void c this is to show multiple payload changes in the Graph for example for DTMF RFC2833 */ if ( tmp_listinfo->payload_type != rtp_info->info_payload_type ) { tmp_listinfo->end_stream = TRUE; + } else if ( ( ( tmp_listinfo->ed137_info == NULL ) && (rtp_info->info_ed137_info != NULL) ) || + ( ( tmp_listinfo->ed137_info != NULL ) && (rtp_info->info_ed137_info == NULL) ) || + ( ( tmp_listinfo->ed137_info != NULL ) && (rtp_info->info_ed137_info != NULL) && + ( 0!=strcmp(tmp_listinfo->ed137_info, rtp_info->info_ed137_info) ) + ) + ) { + /* if ed137_info has changed, create new stream */ + tmp_listinfo->end_stream = TRUE; } else { strinfo = (rtp_stream_info_t*)(list->data); break; @@ -660,6 +669,11 @@ rtp_packet(void *tap_offset_ptr, packet_info *pinfo, epan_dissect_t *edt, void c strinfo->setup_frame_number = rtp_info->info_setup_frame_num; strinfo->call_num = -1; strinfo->rtp_event = -1; + if (rtp_info->info_ed137_info != NULL) { + strinfo->ed137_info = wmem_strdup(NULL, rtp_info->info_ed137_info); + } else { + strinfo->ed137_info = NULL; + } tapinfo->rtp_stream_list = g_list_prepend(tapinfo->rtp_stream_list, strinfo); } @@ -726,11 +740,14 @@ rtp_draw(void *tap_offset_ptr) new_gai->port_src = rtp_listinfo->src_port; new_gai->port_dst = rtp_listinfo->dest_port; duration = (guint32)(nstime_to_msec(&rtp_listinfo->stop_rel_time) - nstime_to_msec(&rtp_listinfo->start_rel_time)); - new_gai->frame_label = g_strdup_printf("%s (%s) %s", + new_gai->frame_label = g_strdup_printf("%s (%s) %s%s%s", (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->payload_type_name, (rtp_listinfo->rtp_event == -1)? - "":val_to_str_ext_const(rtp_listinfo->rtp_event, &rtp_event_type_values_ext, "Unknown RTP Event")); + "":val_to_str_ext_const(rtp_listinfo->rtp_event, &rtp_event_type_values_ext, "Unknown RTP Event"), + (rtp_listinfo->ed137_info!=NULL?" ":""), + (rtp_listinfo->ed137_info!=NULL?rtp_listinfo->ed137_info:"") + ); new_gai->comment = g_strdup_printf(comment_fmt, (rtp_listinfo->is_srtp)?"SRTP":"RTP", rtp_listinfo->packet_count, duration/1000,(duration%1000), rtp_listinfo->ssrc);