aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-sdp.c
diff options
context:
space:
mode:
authoreasonweii <sharkhw@huawei.com>2022-05-18 11:35:52 +0800
committerA Wireshark GitLab Utility <gerald+gitlab-utility@wireshark.org>2022-05-18 08:29:37 +0000
commit148f5905afd7e51c8dc15ff202bf40b192f6a924 (patch)
tree1694e2b4ed3163dbafb3902f2edca2dbd9443a2d /epan/dissectors/packet-sdp.c
parent44433d3c9c2f45e0ba19b6012f73eeb42608e852 (diff)
SDP: Minor Refactoring by Extract Method
Extract Method for multiple message of SDP Media Attribute to simplify things and Make processes clearer. dissect_sdp_media_attribute_rtpmap dissect_sdp_media_attribute_fmtp dissect_sdp_media_attribute_path dissect_sdp_media_attribute_h248_item dissect_sdp_media_attribute_crypto The original function remain unchanged.
Diffstat (limited to 'epan/dissectors/packet-sdp.c')
-rw-r--r--epan/dissectors/packet-sdp.c843
1 files changed, 444 insertions, 399 deletions
diff --git a/epan/dissectors/packet-sdp.c b/epan/dissectors/packet-sdp.c
index fb0716e42c..165b4a4b52 100644
--- a/epan/dissectors/packet-sdp.c
+++ b/epan/dissectors/packet-sdp.c
@@ -1605,31 +1605,454 @@ static const string_string media_format_str_types[] = {
{ 0, NULL }
};
+static void
+dissect_sdp_media_attribute_rtpmap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int length,
+ transport_info_t *transport_info, session_info_t *session_info,
+ media_description_t *media_desc, int offset)
+{
+ gint next_offset, tokenlen;
+ const guint8 *payload_type;
+ proto_item *pi;
+ guint8 pt;
+
+ next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+
+ if (next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item_ret_string(tree, hf_media_format, tvb,
+ offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &payload_type);
+
+ offset = next_offset + 1;
+
+ next_offset = tvb_find_guint8(tvb, offset, -1, '/');
+
+ if (next_offset == -1) {
+ return;
+ }
+
+ tokenlen = next_offset - offset;
+
+ proto_tree_add_item(tree, hf_media_encoding_name, tvb,
+ offset, tokenlen, ENC_UTF_8);
+
+ if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) {
+ return; /* Invalid */
+ }
+
+ /* String is file scope allocated because transport_info is connection related */
+ transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
+
+ next_offset = next_offset + 1;
+ offset = next_offset;
+ while (length-1 >= next_offset) {
+ if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
+ break;
+ next_offset++;
+ }
+ tokenlen = next_offset - offset;
+ pi = proto_tree_add_item(tree, hf_media_sample_rate, tvb,
+ offset, tokenlen, ENC_UTF_8);
+ transport_info->sample_rate[pt] = 0;
+ if (!ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA),
+ NULL, &transport_info->sample_rate[pt])) {
+ expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate);
+ } else if (!strcmp(transport_info->encoding_name[pt], "G722")) {
+ // The reported sampling rate is 8000, but the actual value is
+ // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2
+ proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)");
+ }
+ /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
+ For example:
+
+ a=rtpmap:101 G726-32/8000
+ m=audio 49170 RTP/AVP 0 97
+ a=rtpmap:97 telephone-event/8000
+ m=audio 49172 RTP/AVP 97 101
+ a=rtpmap:97 G726-24/8000
+
+ The Media attributes ("a="s) after the "m=" only apply for that "m=".
+ If there is an "a=" before the first "m=", that attribute applies for
+ all the session (all the "m="s).
+ */
+
+ if (session_info) {
+ /* If this "a=" appear before any "m=", we add it to the session
+ * info, these will be added later to all media (via
+ * sdp_new_media_description).
+ */
+ rtp_dyn_payload_insert(session_info->rtp_dyn_payload,
+ pt,
+ transport_info->encoding_name[pt],
+ transport_info->sample_rate[pt]);
+ } else if (media_desc) {
+ /* if the "a=" is after an "m=", only apply to this "m=" */
+ rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload,
+ pt,
+ transport_info->encoding_name[pt],
+ transport_info->sample_rate[pt]);
+ }
+}
+
+static void
+dissect_sdp_media_attribute_fmtp(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ transport_info_t *transport_info, int offset)
+{
+ gint next_offset, tokenlen;
+ proto_item *fmtp_item, *media_format_item;
+ const guint8 *payload_type;
+ const guint8 *media_format_str;
+ proto_tree *fmtp_tree;
+ gboolean has_more_pars = TRUE;
+ /* Reading the Format parameter(fmtp) */
+ guint8 media_format;
+
+ if (tree == NULL) {
+ return;
+ }
+ /* Skip leading space, if any */
+ offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
+ /* Media format extends to the next space */
+ next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
+
+ if (next_offset == -1)
+ return;
+
+ tokenlen = next_offset - offset;
+
+ media_format_item = proto_tree_add_item_ret_string(tree, hf_media_format, tvb,
+ offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool, &payload_type);
+
+ /* Append encoding name to format if known */
+ payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1);
+ media_format = 0;
+ if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) {
+
+ proto_item_append_text(media_format_item, " [%s]",
+ media_format_str);
+ } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) {
+ if (media_format) {
+ proto_item_append_text(media_format_item, " [%s]",
+ transport_info->encoding_name[media_format]);
+ }
+ } else {
+ expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format);
+ return;
+ }
+
+
+#if 0 /* XXX: ?? */
+ payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);
+#endif
+ /* Move offset past the payload type */
+ offset = next_offset + 1;
+
+ while (has_more_pars == TRUE) {
+ next_offset = tvb_find_guint8(tvb, offset, -1, ';');
+ offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
+
+ if (next_offset == -1) {
+ has_more_pars = FALSE;
+ next_offset= tvb_captured_length(tvb);
+ }
+
+ /* There are at least 2 - add the first parameter */
+ tokenlen = next_offset - offset;
+ fmtp_item = proto_tree_add_item(tree, hf_media_format_specific_parameter, tvb,
+ offset, tokenlen, ENC_UTF_8);
+
+ fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
+
+ decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
+ transport_info->encoding_name[media_format]);
+
+ /* Move offset past "; " and onto firts char */
+ offset = next_offset + 1;
+ }
+}
+
+static void
+dissect_sdp_media_attribute_path(packet_info *pinfo, tvbuff_t *tvb, guint8 *attribute_value,
+ media_description_t *media_desc, const char *msrp_res, int offset)
+{
+ /* msrp attributes that contain address needed for conversation */
+ /* RFC 4975
+ * path = path-label ":" path-list
+ * path-label = "path"
+ * path-list= MSRP-URI *(SP MSRP-URI)
+ * MSRP-URI = msrp-scheme "://" authority
+ * ["/" session-id] ";" transport *( ";" URI-parameter)
+ * ; authority as defined in RFC3986
+ *
+ * msrp-scheme = "msrp" / "msrps"
+ * RFC 3986
+ * The authority component is preceded by a double slash ("//") and is terminated by
+ * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
+ * the end of the URI.
+ */
+
+ /* Check for "msrp://" */
+ if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle &&
+ media_desc && media_desc->proto == SDP_PROTO_MSRP) {
+ int address_offset, port_offset, port_end_offset;
+
+ /* Address starts here */
+ address_offset = offset + (int)strlen(msrp_res);
+
+ /* Port is after next ':' */
+ port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
+ /* Check if port is present if not skipp */
+ if (port_offset!= -1) {
+ /* Port ends with '/' */
+ port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
+ if (port_end_offset == -1) {
+ /* No "/" look for the ";" */
+ port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');
+ }
+ /* Attempt to convert address */
+ guint32 msrp_ipaddr;
+ guint16 msrp_port_number;
+ if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA),
+ &msrp_ipaddr)) {
+ /* Get port number */
+ if (ws_strtou16(tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1,
+ port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) {
+ /* Port and address are usable, store for later use in
+ * complete_descriptions (overrides the "c=" address). */
+ alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr);
+ media_desc->media_attr.msrp.port_number = msrp_port_number;
+ }
+ }
+ }
+ }
+}
+
+static void
+dissect_sdp_media_attribute_h248_item(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ guint8 *attribute_value, const char *msrp_res)
+{
+ const char *h324ext_h223lcparm = "h324ext/h223lcparm";
+ tvbuff_t *h245_tvb;
+
+ if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
+ /* A.5.1.3 H.223 Logical channel parameters
+ * This property indicates the H.245
+ * H223LogicalChannelsParameters structure encoded by applying the PER specified in
+ * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
+ * in ITU-T Rec. H.248.15 is used.
+ */
+ gint len;
+ asn1_ctx_t actx;
+
+ len = (gint)strlen(attribute_value);
+ h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
+ /* arbitrary maximum length */
+ /* should go through a handle, however, the two h245 entry
+ points are different, one is over tpkt and the other is raw
+ */
+ if (h245_tvb) {
+ asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
+ dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
+ tree,hf_SDPh223LogicalChannelParameters);
+ }
+ }
+}
+
+static void
+dissect_sdp_media_attribute_crypto(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
+ transport_info_t *transport_info, int offset)
+{
+ /* https://tools.ietf.org/html/rfc4568
+ * 9.1. Generic "Crypto" Attribute Grammar
+ *
+ * The ABNF grammar for the crypto attribute is defined below:
+ *
+ * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
+ * *(1*WSP session-param)
+ *
+ * tag = 1*9DIGIT
+ * crypto-suite = 1*(ALPHA / DIGIT / "_")
+ *
+ * key-params = key-param *(";" key-param)
+ * key-param = key-method ":" key-info
+ * key-method = "inline" / key-method-ext
+ * key-method-ext = 1*(ALPHA / DIGIT / "_")
+ * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
+ * ; except semi-colon
+ * session-param = 1*(VCHAR) ; visible (printing) characters
+ *
+ * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
+ *
+ */
+ gint next_offset, tokenlen;
+ proto_tree *parameter_item;
+ proto_item *parameter_tree;
+ guint32 crypto_tag;
+ gboolean crypto_tag_valid;
+ gboolean has_more_pars = TRUE;
+ guint8 master_key_length = 0, master_salt_length = 0;
+ gboolean mki_len_valid;
+ proto_item *pi;
+
+ /* We are at the first colon */
+ /* tag */
+ tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
+ if (tokenlen == 0)
+ return;
+ crypto_tag_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset,
+ tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag);
+ pi = proto_tree_add_uint(tree, hf_sdp_crypto_tag, tvb, offset, tokenlen, crypto_tag);
+ if (!crypto_tag_valid)
+ expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag);
+ offset = next_offset + 1;
+
+ /* crypto-suite */
+ tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
+ if (tokenlen == 0)
+ return;
+ parameter_item = proto_tree_add_item(tree, hf_sdp_crypto_crypto_suite, tvb, offset, tokenlen, ENC_UTF_8);
+ if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
+
+ /* XXX This may only work in simple cases */
+ if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
+ transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
+ transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
+ /* number of octets used for the Auth Tag in the RTP payload */
+ transport_info->auth_tag_len = 10;
+ }
+ master_key_length = 16; /* 128 bits = 16 octets */
+ master_salt_length = 14; /* 112 bits = 14 octets */
+ } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
+ /* XXX This may only work in simple cases */
+ if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
+ transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
+ transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
+ /* number of octets used for the Auth Tag in the RTP payload */
+ transport_info->auth_tag_len = 4;
+ }
+ master_key_length = 16; /* 128 bits = 16 octets */
+ master_salt_length = 14; /* 112 bits = 14 octets */
+ } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
+ if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
+ /* XXX This may only work in simple cases */
+ transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
+ transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
+ /* number of octets used for the Auth Tag in the RTP payload */
+ transport_info->auth_tag_len = 10;
+ }
+ master_key_length = 16; /* 128 bits = 16 octets */
+ master_salt_length = 14; /* 112 bits = 14 octets */
+ }
+ offset = next_offset + 1;
+
+ /* key-params */
+ while (has_more_pars == TRUE) {
+ int param_end_offset;
+ tvbuff_t *key_salt_tvb;
+ gchar *data_p = NULL;
+
+ param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
+ if (param_end_offset == -1) {
+ has_more_pars = FALSE;
+ param_end_offset = tvb_captured_length(tvb);
+ }
+ /* key-method or key-method-ext */
+ next_offset = tvb_find_guint8(tvb, offset, -1, ':');
+ if (next_offset == -1) {
+ expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
+ break;
+ }
+
+ if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
+ parameter_tree = proto_tree_add_subtree(tree, tvb, offset,param_end_offset-offset,
+ ett_sdp_crypto_key_parameters, NULL, "Key parameters");
+ /* XXX only for SRTP? */
+ /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
+ offset = next_offset +1;
+ next_offset = tvb_find_guint8(tvb, offset, -1, '|');
+ if (next_offset == -1) {
+ tokenlen = param_end_offset - offset;
+ } else {
+ tokenlen = next_offset - offset;
+ }
+ data_p = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
+ key_salt_tvb = base64_to_tvb(tvb, data_p);
+ add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
+ if (master_key_length != 0) {
+ proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA);
+ proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
+ key_salt_tvb, 0, master_key_length, ENC_NA);
+ proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
+ key_salt_tvb, master_key_length, master_salt_length, ENC_NA);
+ } else {
+ proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA);
+ }
+
+ /* ["|" lifetime] ["|" mki] are optional */
+ if (next_offset != -1) {
+ offset = next_offset + 1;
+ next_offset = tvb_find_guint8(tvb, offset, -1, '|');
+ if (next_offset == -1) {
+ if (next_offset < param_end_offset){
+ next_offset = param_end_offset;
+ }
+ }
+ if (next_offset != -1) {
+ /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
+ tvb, offset, tokenlen, ENC_UTF_8);
+ offset = next_offset + 1;
+ }
+ /* mki = mki-value ":" mki-length
+ *
+ * mki-value = 1*DIGIT
+ */
+ if (offset>param_end_offset) {
+ next_offset = -1;
+ } else {
+ next_offset = tvb_find_guint8(tvb, offset, -1, ':');
+ }
+ if (next_offset != -1) {
+ tokenlen = next_offset - offset;
+ proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8);
+ offset = next_offset + 1;
+
+ /* mki-length = 1*3DIGIT ; range 1..128. */
+ next_offset = param_end_offset;
+ tokenlen = next_offset - offset;
+
+ /* This will not work if more than one parameter */
+ /* number of octets used for the MKI in the RTP payload */
+ mki_len_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen,
+ ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len);
+ pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
+ tvb, offset, tokenlen, ENC_UTF_8);
+ if (!mki_len_valid)
+ expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length);
+ }
+ }
+ offset = param_end_offset;
+ } else {
+ break;
+ }
+ }
+}
+
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,
sdp_data_t *sdp_data)
{
- proto_tree *sdp_media_attribute_tree, *parameter_item;
- proto_item *fmtp_item, *media_format_item, *parameter_tree;
- proto_tree *fmtp_tree;
+ proto_tree *sdp_media_attribute_tree;
proto_item *pi;
- gint offset, next_offset, tokenlen, colon_offset;
- /*??guint8 *field_name;*/
- const guint8 *payload_type;
- const guint8 *media_format_str;
+ gint offset, tokenlen, colon_offset;
guint8 *attribute_value;
- guint8 pt;
gint sdp_media_attrbute_code;
const char *msrp_res = "msrp://";
- const char *h324ext_h223lcparm = "h324ext/h223lcparm";
- gboolean has_more_pars = TRUE;
- tvbuff_t *h245_tvb;
- guint8 master_key_length = 0, master_salt_length = 0;
- guint32 crypto_tag;
- gboolean crypto_tag_valid;
- gboolean mki_len_valid;
offset = 0;
@@ -1670,399 +2093,21 @@ static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto
switch (sdp_media_attrbute_code) {
case SDP_RTPMAP:
/* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
- next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
-
- if (next_offset == -1)
- return;
-
- tokenlen = next_offset - offset;
-
- proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb,
- offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &payload_type);
-
- offset = next_offset + 1;
-
- next_offset = tvb_find_guint8(tvb, offset, -1, '/');
-
- if (next_offset == -1) {
- return;
- }
-
- tokenlen = next_offset - offset;
-
- proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
- offset, tokenlen, ENC_UTF_8);
-
- if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) {
- return; /* Invalid */
- }
-
- /* String is file scope allocated because transport_info is connection related */
- transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
-
- next_offset = next_offset + 1;
- offset = next_offset;
- while (length-1 >= next_offset) {
- if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
- break;
- next_offset++;
- }
- tokenlen = next_offset - offset;
- pi = proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
- offset, tokenlen, ENC_UTF_8);
- transport_info->sample_rate[pt] = 0;
- if (!ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA),
- NULL, &transport_info->sample_rate[pt])) {
- expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate);
- } else if (!strcmp(transport_info->encoding_name[pt], "G722")) {
- // The reported sampling rate is 8000, but the actual value is
- // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2
- proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)");
- }
- /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
- For example:
-
- a=rtpmap:101 G726-32/8000
- m=audio 49170 RTP/AVP 0 97
- a=rtpmap:97 telephone-event/8000
- m=audio 49172 RTP/AVP 97 101
- a=rtpmap:97 G726-24/8000
-
- The Media attributes ("a="s) after the "m=" only apply for that "m=".
- If there is an "a=" before the first "m=", that attribute applies for
- all the session (all the "m="s).
- */
-
- if (session_info) {
- /* If this "a=" appear before any "m=", we add it to the session
- * info, these will be added later to all media (via
- * sdp_new_media_description).
- */
- rtp_dyn_payload_insert(session_info->rtp_dyn_payload,
- pt,
- transport_info->encoding_name[pt],
- transport_info->sample_rate[pt]);
- } else if (media_desc) {
- /* if the "a=" is after an "m=", only apply to this "m=" */
- rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload,
- pt,
- transport_info->encoding_name[pt],
- transport_info->sample_rate[pt]);
- }
+ dissect_sdp_media_attribute_rtpmap(sdp_media_attribute_tree, pinfo, tvb, length, transport_info,
+ session_info, media_desc, offset);
break;
case SDP_FMTP:
- if (sdp_media_attribute_tree) {
- guint8 media_format;
- /* Reading the Format parameter(fmtp) */
- /* Skip leading space, if any */
- offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
- /* Media format extends to the next space */
- next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
-
- if (next_offset == -1)
- return;
-
- tokenlen = next_offset - offset;
-
- media_format_item = proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb,
- offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool, &payload_type);
-
- /* Append encoding name to format if known */
- payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1);
- media_format = 0;
- if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) {
-
- proto_item_append_text(media_format_item, " [%s]",
- media_format_str);
- } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) {
- if (media_format) {
- proto_item_append_text(media_format_item, " [%s]",
- transport_info->encoding_name[media_format]);
- }
- } else {
- expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format);
- return;
- }
-
-
-#if 0 /* XXX: ?? */
- payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);
-#endif
- /* Move offset past the payload type */
- offset = next_offset + 1;
-
- while (has_more_pars == TRUE) {
- next_offset = tvb_find_guint8(tvb, offset, -1, ';');
- offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
-
- if (next_offset == -1) {
- has_more_pars = FALSE;
- next_offset= tvb_captured_length(tvb);
- }
-
- /* There are at least 2 - add the first parameter */
- tokenlen = next_offset - offset;
- fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
- hf_media_format_specific_parameter, tvb,
- offset, tokenlen, ENC_UTF_8);
-
- fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
-
- decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
- transport_info->encoding_name[media_format]);
-
- /* Move offset past "; " and onto firts char */
- offset = next_offset + 1;
- }
- }
+ dissect_sdp_media_attribute_fmtp(sdp_media_attribute_tree, pinfo, tvb, transport_info, offset);
break;
case SDP_PATH:
- /* msrp attributes that contain address needed for conversation */
- /* RFC 4975
- * path = path-label ":" path-list
- * path-label = "path"
- * path-list= MSRP-URI *(SP MSRP-URI)
- * MSRP-URI = msrp-scheme "://" authority
- * ["/" session-id] ";" transport *( ";" URI-parameter)
- * ; authority as defined in RFC3986
- *
- * msrp-scheme = "msrp" / "msrps"
- * RFC 3986
- * The authority component is preceded by a double slash ("//") and is terminated by
- * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
- * the end of the URI.
- */
-
- /* Check for "msrp://" */
- if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle &&
- media_desc && media_desc->proto == SDP_PROTO_MSRP) {
- int address_offset, port_offset, port_end_offset;
-
- /* Address starts here */
- address_offset = offset + (int)strlen(msrp_res);
-
- /* Port is after next ':' */
- port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
- /* Check if port is present if not skipp */
- if (port_offset!= -1) {
- /* Port ends with '/' */
- port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
- if (port_end_offset == -1) {
- /* No "/" look for the ";" */
- port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');
- }
- /* Attempt to convert address */
- guint32 msrp_ipaddr;
- guint16 msrp_port_number;
- if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA),
- &msrp_ipaddr)) {
- /* Get port number */
- if (ws_strtou16(tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1,
- port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) {
- /* Port and address are usable, store for later use in
- * complete_descriptions (overrides the "c=" address). */
- alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr);
- media_desc->media_attr.msrp.port_number = msrp_port_number;
- }
- }
- }
- }
+ dissect_sdp_media_attribute_path(pinfo, tvb, attribute_value, media_desc, msrp_res, offset);
break;
case SDP_H248_ITEM:
/* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
- if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
- /* A.5.1.3 H.223 Logical channel parameters
- * This property indicates the H.245
- * H223LogicalChannelsParameters structure encoded by applying the PER specified in
- * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
- * in ITU-T Rec. H.248.15 is used.
- */
- gint len;
- asn1_ctx_t actx;
-
- len = (gint)strlen(attribute_value);
- h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
- /* arbitrary maximum length */
- /* should go through a handle, however, the two h245 entry
- points are different, one is over tpkt and the other is raw
- */
- if (h245_tvb) {
- asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
- dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
- sdp_media_attribute_tree,
- hf_SDPh223LogicalChannelParameters);
- }
- }
+ dissect_sdp_media_attribute_h248_item(sdp_media_attribute_tree, pinfo, tvb, attribute_value, msrp_res);
break;
case SDP_CRYPTO:
- /* https://tools.ietf.org/html/rfc4568
- * 9.1. Generic "Crypto" Attribute Grammar
- *
- * The ABNF grammar for the crypto attribute is defined below:
- *
- * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
- * *(1*WSP session-param)
- *
- * tag = 1*9DIGIT
- * crypto-suite = 1*(ALPHA / DIGIT / "_")
- *
- * key-params = key-param *(";" key-param)
- * key-param = key-method ":" key-info
- * key-method = "inline" / key-method-ext
- * key-method-ext = 1*(ALPHA / DIGIT / "_")
- * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
- * ; except semi-colon
- * session-param = 1*(VCHAR) ; visible (printing) characters
- *
- * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
- *
- */
-
- /* We are at the first colon */
- /* tag */
- tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset);
- if (tokenlen == 0)
- return;
- crypto_tag_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset,
- tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag);
- pi = proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen,
- crypto_tag);
- if (!crypto_tag_valid)
- expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag);
- offset = next_offset + 1;
-
- /* crypto-suite */
- tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset);
- if (tokenlen == 0)
- return;
- parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite,
- tvb, offset, tokenlen, ENC_UTF_8);
- if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
-
- /* XXX This may only work in simple cases */
- if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
- transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
- transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
- /* number of octets used for the Auth Tag in the RTP payload */
- transport_info->auth_tag_len = 10;
- }
- master_key_length = 16; /* 128 bits = 16 octets */
- master_salt_length = 14; /* 112 bits = 14 octets */
- } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
- /* XXX This may only work in simple cases */
- if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
- transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
- transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
- /* number of octets used for the Auth Tag in the RTP payload */
- transport_info->auth_tag_len = 4;
- }
- master_key_length = 16; /* 128 bits = 16 octets */
- master_salt_length = 14; /* 112 bits = 14 octets */
- } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
- if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
- /* XXX This may only work in simple cases */
- transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
- transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
- /* number of octets used for the Auth Tag in the RTP payload */
- transport_info->auth_tag_len = 10;
- }
- master_key_length = 16; /* 128 bits = 16 octets */
- master_salt_length = 14; /* 112 bits = 14 octets */
- }
- offset = next_offset + 1;
-
- /* key-params */
- while (has_more_pars == TRUE) {
- int param_end_offset;
- tvbuff_t *key_salt_tvb;
- gchar *data_p = NULL;
-
- param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
- if (param_end_offset == -1) {
- has_more_pars = FALSE;
- param_end_offset = tvb_captured_length(tvb);
- }
- /* key-method or key-method-ext */
- next_offset = tvb_find_guint8(tvb, offset, -1, ':');
- if (next_offset == -1) {
- expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
- break;
- }
-
- if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
- parameter_tree = proto_tree_add_subtree(sdp_media_attribute_tree, tvb, offset,
- param_end_offset-offset, ett_sdp_crypto_key_parameters, NULL, "Key parameters");
- /* XXX only for SRTP? */
- /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
- offset = next_offset +1;
- next_offset = tvb_find_guint8(tvb, offset, -1, '|');
- if (next_offset == -1) {
- tokenlen = param_end_offset - offset;
- } else {
- tokenlen = next_offset - offset;
- }
- data_p = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
- key_salt_tvb = base64_to_tvb(tvb, data_p);
- add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
- if (master_key_length != 0) {
- proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA);
- proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
- key_salt_tvb, 0, master_key_length, ENC_NA);
- proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
- key_salt_tvb, master_key_length, master_salt_length, ENC_NA);
- } else {
- proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA);
- }
-
- /* ["|" lifetime] ["|" mki] are optional */
- if (next_offset != -1) {
- offset = next_offset + 1;
- next_offset = tvb_find_guint8(tvb, offset, -1, '|');
- if (next_offset == -1) {
- if (next_offset < param_end_offset){
- next_offset = param_end_offset;
- }
- }
- if (next_offset != -1) {
- /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
- tokenlen = next_offset - offset;
- proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
- tvb, offset, tokenlen, ENC_UTF_8);
- offset = next_offset + 1;
- }
- /* mki = mki-value ":" mki-length
- *
- * mki-value = 1*DIGIT
- */
- if (offset>param_end_offset) {
- next_offset = -1;
- } else {
- next_offset = tvb_find_guint8(tvb, offset, -1, ':');
- }
- if (next_offset != -1) {
- tokenlen = next_offset - offset;
- proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8);
- offset = next_offset + 1;
-
- /* mki-length = 1*3DIGIT ; range 1..128. */
- next_offset = param_end_offset;
- tokenlen = next_offset - offset;
-
- /* This will not work if more than one parameter */
- /* number of octets used for the MKI in the RTP payload */
- mki_len_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen,
- ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len);
- pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
- tvb, offset, tokenlen, ENC_UTF_8);
- if (!mki_len_valid)
- expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length);
- }
- }
- offset = param_end_offset;
- } else {
- break;
- }
- }
+ dissect_sdp_media_attribute_crypto(sdp_media_attribute_tree, pinfo, tvb, transport_info, offset);
break;
case SDP_CANDIDATE:
dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree, pinfo, tvb, offset);