1 /* packet-sdp.c 2 * Routines for SDP packet disassembly (RFC 2327) 3 * 4 * Jason Lango <jal@netapp.com> 5 * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu> 6 * 7 * Wireshark - Network traffic analyzer 8 * By Gerald Combs <gerald@wireshark.org> 9 * Copyright 1998 Gerald Combs 10 * 11 * SPDX-License-Identifier: GPL-2.0-or-later 12 * Ref https://www.ietf.org/rfc/rfc4566 13 */ 14 15 #include "config.h" 16 17 #include <epan/packet.h> 18 #include <epan/exceptions.h> 19 #include <epan/asn1.h> 20 #include <epan/prefs.h> 21 #include <epan/expert.h> 22 #include <epan/tap.h> 23 #include <epan/rtp_pt.h> 24 #include <epan/show_exception.h> 25 #include <epan/addr_resolv.h> 26 #include <epan/proto_data.h> 27 #include <epan/conversation.h> 28 29 #include <wsutil/strtoi.h> 30 #include <wsutil/str_util.h> 31 32 #include "packet-http.h" 33 #include "packet-sdp.h" 34 35 /* un-comment the following as well as this line in conversation.c, to enable debug printing */ 36 /* #define DEBUG_CONVERSATION */ 37 #include "conversation_debug.h" 38 39 #include "packet-rtp.h" 40 41 #include "packet-rtcp.h" 42 #include "packet-t38.h" 43 #include "packet-msrp.h" 44 #include "packet-sprt.h" 45 #include "packet-h245.h" 46 #include "packet-h264.h" 47 #include "packet-h265.h" 48 #include "packet-mp4ves.h" 49 50 void proto_register_sdp(void); 51 void proto_reg_handoff_sdp(void); 52 53 static dissector_handle_t sdp_handle; 54 static dissector_handle_t rtcp_handle; 55 static dissector_handle_t sprt_handle; 56 static dissector_handle_t msrp_handle; 57 static dissector_handle_t h264_handle; 58 static dissector_handle_t h265_handle; 59 static dissector_handle_t mp4ves_config_handle; 60 61 static int sdp_tap = -1; 62 63 static int proto_sdp = -1; 64 static int proto_sprt = -1; 65 66 static const char* UNKNOWN_ENCODING = "Unknown"; 67 static wmem_tree_t *sdp_transport_reqs = NULL; 68 static wmem_tree_t *sdp_transport_rsps = NULL; 69 70 /* preference globals */ 71 static gboolean global_sdp_establish_conversation = TRUE; 72 73 /* Top level fields */ 74 static int hf_protocol_version = -1; 75 static int hf_owner = -1; 76 static int hf_session_name = -1; 77 static int hf_session_info = -1; 78 static int hf_uri = -1; 79 static int hf_email = -1; 80 static int hf_phone = -1; 81 static int hf_connection_info = -1; 82 static int hf_bandwidth = -1; 83 static int hf_timezone = -1; 84 static int hf_encryption_key = -1; 85 static int hf_session_attribute = -1; 86 static int hf_media_attribute = -1; 87 static int hf_time = -1; 88 static int hf_repeat_time = -1; 89 static int hf_media = -1; 90 static int hf_media_title = -1; 91 static int hf_unknown = -1; 92 static int hf_invalid = -1; 93 static int hf_ipbcp_version = -1; 94 static int hf_ipbcp_type = -1; 95 96 /* hf_owner subfields*/ 97 static int hf_owner_username = -1; 98 static int hf_owner_sessionid = -1; 99 static int hf_owner_version = -1; 100 static int hf_owner_network_type = -1; 101 static int hf_owner_address_type = -1; 102 static int hf_owner_address = -1; 103 104 /* hf_connection_info subfields */ 105 static int hf_connection_info_network_type = -1; 106 static int hf_connection_info_address_type = -1; 107 static int hf_connection_info_connection_address = -1; 108 static int hf_connection_info_ttl = -1; 109 static int hf_connection_info_num_addr = -1; 110 111 /* hf_bandwidth subfields */ 112 static int hf_bandwidth_modifier = -1; 113 static int hf_bandwidth_value = -1; 114 115 /* hf_time subfields */ 116 static int hf_time_start = -1; 117 static int hf_time_stop = -1; 118 119 /* hf_repeat_time subfield */ 120 static int hf_repeat_time_interval = -1; 121 static int hf_repeat_time_duration = -1; 122 static int hf_repeat_time_offset = -1; 123 124 /* hf_timezone subfields */ 125 static int hf_timezone_time = -1; 126 static int hf_timezone_offset = -1; 127 128 /* hf_encryption_key subfields */ 129 static int hf_encryption_key_type = -1; 130 static int hf_encryption_key_data = -1; 131 132 /* hf_session_attribute subfields */ 133 static int hf_session_attribute_field = -1; 134 static int hf_session_attribute_value = -1; 135 136 /* hf_media subfields */ 137 static int hf_media_media = -1; 138 static int hf_media_port = -1; 139 static int hf_media_port_string = -1; 140 static int hf_media_portcount = -1; 141 static int hf_media_proto = -1; 142 static int hf_media_format = -1; 143 144 /* hf_session_attribute subfields */ 145 static int hf_media_attribute_field = -1; 146 static int hf_media_attribute_value = -1; 147 static int hf_media_encoding_name = -1; 148 static int hf_media_sample_rate = -1; 149 static int hf_media_format_specific_parameter = -1; 150 static int hf_sdp_fmtp_mpeg4_profile_level_id = -1; 151 static int hf_sdp_fmtp_h263_profile = -1; 152 static int hf_sdp_fmtp_h263_level = -1; 153 static int hf_sdp_h264_packetization_mode = -1; 154 static int hf_SDPh223LogicalChannelParameters = -1; 155 156 /* hf_session_attribute hf_media_attribute subfields */ 157 static int hf_key_mgmt_att_value = -1; 158 static int hf_key_mgmt_prtcl_id = -1; 159 static int hf_key_mgmt_data = -1; 160 161 static int hf_sdp_crypto_tag = -1; 162 static int hf_sdp_crypto_crypto_suite = -1; 163 static int hf_sdp_crypto_master_key = -1; 164 static int hf_sdp_crypto_master_salt = -1; 165 static int hf_sdp_crypto_lifetime = -1; 166 static int hf_sdp_crypto_mki = -1; 167 static int hf_sdp_crypto_mki_length = -1; 168 169 /* a=candidate subfields */ 170 static int hf_ice_candidate_foundation = -1; 171 static int hf_ice_candidate_componentid = -1; 172 static int hf_ice_candidate_transport = -1; 173 static int hf_ice_candidate_priority = -1; 174 static int hf_ice_candidate_address = -1; 175 static int hf_ice_candidate_port = -1; 176 static int hf_ice_candidate_type = -1; 177 178 /* Generated from convert_proto_tree_add_text.pl */ 179 static int hf_sdp_nal_unit_2_string = -1; 180 static int hf_sdp_key_and_salt = -1; 181 static int hf_sdp_nal_unit_1_string = -1; 182 static int hf_sdp_data = -1; 183 184 /* trees */ 185 static int ett_sdp = -1; 186 static int ett_sdp_owner = -1; 187 static int ett_sdp_connection_info = -1; 188 static int ett_sdp_bandwidth = -1; 189 static int ett_sdp_time = -1; 190 static int ett_sdp_repeat_time = -1; 191 static int ett_sdp_timezone = -1; 192 static int ett_sdp_encryption_key = -1; 193 static int ett_sdp_session_attribute = -1; 194 static int ett_sdp_media = -1; 195 static int ett_sdp_media_attribute = -1; 196 static int ett_sdp_fmtp = -1; 197 static int ett_sdp_key_mgmt = -1; 198 static int ett_sdp_crypto_key_parameters = -1; 199 200 static expert_field ei_sdp_invalid_key_param = EI_INIT; 201 static expert_field ei_sdp_invalid_line_equal = EI_INIT; 202 static expert_field ei_sdp_invalid_line_fields = EI_INIT; 203 static expert_field ei_sdp_invalid_line_space = EI_INIT; 204 static expert_field ei_sdp_invalid_conversion = EI_INIT; 205 static expert_field ei_sdp_invalid_media_port = EI_INIT; 206 static expert_field ei_sdp_invalid_sample_rate = EI_INIT; 207 static expert_field ei_sdp_invalid_media_format = EI_INIT; 208 static expert_field ei_sdp_invalid_crypto_tag = EI_INIT; 209 static expert_field ei_sdp_invalid_crypto_mki_length = EI_INIT; 210 211 /* patterns used for tvb_ws_mempbrk_pattern_guint8 */ 212 static ws_mempbrk_pattern pbrk_digits; 213 static ws_mempbrk_pattern pbrk_alpha; 214 215 typedef enum { 216 SDP_PROTO_UNKNOWN = 0, 217 SDP_PROTO_RTP, 218 SDP_PROTO_SRTP, 219 SDP_PROTO_T38, 220 SDP_PROTO_MSRP, 221 SDP_PROTO_SPRT, 222 } transport_proto_t; 223 224 225 #define SDP_MAX_RTP_CHANNELS 4 226 #define SDP_MAX_RTP_PAYLOAD_TYPES 20 227 #define SDP_NO_OF_PT 128 228 /* 229 * All parameters specific to one media description ("m="). 230 */ 231 typedef struct { 232 gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES]; 233 gint8 pt_count; 234 rtp_dyn_payload_t *rtp_dyn_payload; 235 gboolean set_rtp; 236 } transport_media_pt_t; 237 238 /* 239 * Store data extracted from one Media Description section of a SDP. Memory is 240 * allocated in wmem_file_scope(). 241 */ 242 typedef struct { 243 transport_proto_t proto; /**< Protocol, parsed from "m=" line. */ 244 guint32 media_types; /**< Whether "m=video" or others */ 245 gboolean bundled; /**< "m=" lines are "bundled", that is, all on same port */ 246 guint16 media_port; /**< Port number, parsed from "m=" line. */ 247 guint16 control_port; /**< Port number, parsed from "a=rtcp" or "a=rtcp-mux" line. */ 248 address conn_addr; /**< The address from the "c=" line (default 249 from session level, possibly overridden at 250 the media level). */ 251 transport_media_pt_t media; /**< Information about payload numbers for this media. */ 252 253 /* 254 * Media-level only attributes. 255 */ 256 union { 257 struct { 258 address ipaddr; 259 guint16 port_number; 260 } msrp; /**< MSRP transport info, parsed from "a=label:" */ 261 } media_attr; 262 } media_description_t; 263 264 /* 265 * Information parsed from one or two (offer/answer) SDPs that is stored in the 266 * conversation. The contents are allocated within wmem_file_scope(). 267 */ 268 typedef struct { 269 enum sdp_exchange_type sdp_status; 270 char *encoding_name[SDP_NO_OF_PT]; 271 int sample_rate[SDP_NO_OF_PT]; 272 273 /* Data parsed from "m=" */ 274 wmem_array_t *media_descriptions; /* array of media_description_t */ 275 276 /* SRTP related info XXX note currently we only handle one crypto line in the SDP 277 * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of 278 * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector 279 * and the SDP dissector just provide the relevant data. 280 * YES! packet-sdp.c should be about SDP parsing... SDP *state* needs to be maintained by upper 281 * protocols, because each one has different rules/semantics. 282 */ 283 guint encryption_algorithm; 284 guint auth_algorithm; 285 guint mki_len; /* number of octets used for the MKI in the RTP payload */ 286 guint auth_tag_len; /* number of octets used for the Auth Tag in the RTP payload */ 287 } transport_info_t; 288 289 /* 290 * Information about the session description. These are accumulated while 291 * parsing the session description and will be applied to the media description. 292 * Memory scope can be pinfo->pool since the contents are no longer 293 * needed once they are processed into transport_info_t (via 294 * complete_descriptions). 295 */ 296 typedef struct { 297 address conn_addr; /**< Parsed from "c=" line. */ 298 rtp_dyn_payload_t *rtp_dyn_payload; /**< Parsed from "a=rtpmap:" line. 299 Note: wmem_file_scope, needs manual dealloc. */ 300 } session_info_t; 301 302 /* Structure for private data to hold ED137 related values */ 303 typedef struct sdp_data_t { 304 char *ed137_type; /* Radio session type */ 305 char *ed137_txrxmode; /* Tx/Rx mode */ 306 char *ed137_fid; /* Frequency ID */ 307 } sdp_data_t; 308 309 310 /* here lie the debugging dumper functions */ 311 #ifdef DEBUG_CONVERSATION 312 static void sdp_dump_transport_media(const transport_media_pt_t* media) { 313 int i; 314 int count; 315 DPRINT2(("transport_media contents:")); 316 DINDENT(); 317 if (!media) { 318 DPRINT2(("null transport_media_pt_t*")); 319 DENDENT(); 320 return; 321 } 322 count = (int)media->pt_count; 323 DPRINT2(("pt_count=%d",count)); 324 DINDENT(); 325 for (i=0; i < count; i++) { 326 DPRINT2(("pt=%d", media->pt[i])); 327 } 328 DENDENT(); 329 DPRINT2(("rtp_dyn_payload hashtable=%s", media->rtp_dyn_payload ? "YES" : "NO")); 330 if (media->rtp_dyn_payload) { 331 rtp_dump_dyn_payload(media->rtp_dyn_payload); 332 } 333 DPRINT2(("set_rtp=%s", media->set_rtp ? "TRUE" : "FALSE")); 334 DENDENT(); 335 } 336 337 static const value_string sdp_exchange_type_vs[] = { 338 { SDP_EXCHANGE_OFFER, "SDP_EXCHANGE_OFFER" }, 339 { SDP_EXCHANGE_ANSWER_ACCEPT, "SDP_EXCHANGE_ANSWER_ACCEPT" }, 340 { SDP_EXCHANGE_ANSWER_REJECT, "SDP_EXCHANGE_ANSWER_REJECT" }, 341 { 0, NULL } 342 }; 343 344 static void sdp_dump_transport_info(const transport_info_t* info) { 345 int i; 346 int count; 347 DPRINT2(("transport_info contents:")); 348 DINDENT(); 349 if (!info) { 350 DPRINT2(("null transport_info_t*")); 351 DENDENT(); 352 return; 353 } 354 DPRINT2(("sdp_status=%s", 355 val_to_str(info->sdp_status, sdp_exchange_type_vs, "SDP_EXCHANGE_UNKNOWN"))); 356 DPRINT2(("payload type contents:")); 357 DINDENT(); 358 for (i=0; i < SDP_NO_OF_PT; i++) { 359 /* don't print out unknown encodings */ 360 if (info->encoding_name[i] && 361 strcmp(UNKNOWN_ENCODING,info->encoding_name[i]) != 0) { 362 DPRINT2(("payload type #%d:",i)); 363 DINDENT(); 364 DPRINT2(("encoding_name=%s", info->encoding_name[i])); 365 DPRINT2(("sample_rate=%d", info->sample_rate[i])); 366 DENDENT(); 367 } 368 } 369 DENDENT(); 370 count = wmem_array_get_count(info->media_descriptions); 371 DPRINT2(("media_count=%d", count)); 372 DPRINT2(("rtp channels:")); 373 DINDENT(); 374 for (i=0; i < count; i++) { 375 media_description_t *media_desc = (media_description_t *)wmem_array_index(info->media_descriptions, i); 376 DPRINT2(("channel #%d:",i)); 377 DINDENT(); 378 DPRINT2(("conn_addr=%s", address_to_str(pinfo->pool, &(media_desc->conn_addr)))); 379 DPRINT2(("media_port=%d", media_desc->media_port)); 380 DPRINT2(("proto=%d", media_desc->proto)); 381 sdp_dump_transport_media(&(media_desc->media)); 382 DENDENT(); 383 } 384 DENDENT(); 385 DPRINT2(("encryption_algorithm=%u", info->encryption_algorithm)); 386 DPRINT2(("auth_algorithm=%u", info->auth_algorithm)); 387 if (info->encryption_algorithm || info->auth_algorithm) { 388 DPRINT2(("mki_len=%u", info->mki_len)); 389 if (info->auth_algorithm) { 390 DPRINT2(("auth_tag_len=%u", info->auth_tag_len)); 391 } 392 } 393 DENDENT(); 394 } 395 396 #endif /* DEBUG_CONVERSATION */ 397 398 399 /* key-mgmt dissector 400 * IANA registry: 401 * http://www.iana.org/assignments/sdp-parameters 402 */ 403 static dissector_table_t key_mgmt_dissector_table; 404 405 /* Finds next token (sequence of non-space chars) in tvb from given offset. 406 * The returned value is the token length, or 0 if none found. 407 * The offset is changed to be the starting offset, in case there were one or more 408 * spaces at the beginning. (this will also add expert info in such a case) 409 * The next_offset is set to the next found space after the token, or -1 if the 410 * end of line is hit or no token found. 411 * If this is the last token in the line, tokenlen will not be 0, but next_offset 412 * will be -1. 413 * 414 * The optional param, if TRUE, means no expert error will be issued if no token 415 * is found; if FALSE then a expert error will be issued if no token is found. 416 * 417 * This function expects to be given a tvb of only one line, and does no error 418 * checking of its given arguments. 419 */ 420 static inline gint 421 find_next_optional_token_in_line(tvbuff_t *tvb, proto_tree *tree, 422 gint *offset, gint *next_offset, 423 const gboolean optional) 424 { 425 gint tokenlen = 0; 426 gint next_off = -1; 427 gint off = *offset; 428 429 if (tvb_offset_exists(tvb, off)) { 430 while (tokenlen == 0) { 431 next_off = tvb_find_guint8(tvb, off, -1, ' '); 432 if (next_off == -1) { 433 tokenlen = tvb_captured_length_remaining(tvb, off); 434 break; /* Nothing more left */ 435 } 436 437 tokenlen = next_off - off; 438 439 if (tokenlen == 0) { 440 /* two spaces in a row - illegal, but we'll keep dissecting */ 441 proto_tree_add_expert(tree, NULL, &ei_sdp_invalid_line_space, tvb, off-1, 2); 442 off = next_off + 1; 443 } 444 } 445 } 446 447 if (!optional && tokenlen == 0) { 448 proto_tree_add_expert(tree, NULL, &ei_sdp_invalid_line_fields, tvb, 0, -1); 449 } 450 451 *next_offset = next_off; 452 *offset = off; 453 return tokenlen; 454 } 455 456 /* Same as above, but always issues an expert error if a token is not found. */ 457 static inline gint 458 find_next_token_in_line(tvbuff_t *tvb, proto_tree *tree, gint *offset, gint *next_offset) 459 { 460 return find_next_optional_token_in_line(tvb, tree, offset, next_offset, FALSE); 461 } 462 463 /* Convert the protocol from the "m=" line to something we understand. */ 464 static transport_proto_t 465 parse_sdp_media_protocol(const char *media_proto) 466 { 467 /* Sorted according to the "proto" registry at 468 * https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml#sdp-parameters-2 */ 469 const struct { 470 const char *proto_name; 471 transport_proto_t proto; 472 } protocols[] = { 473 { "RTP/AVP", SDP_PROTO_RTP }, /* RFC 4566 */ 474 { "udptl", SDP_PROTO_T38 }, /* ITU-T T.38, example in Annex E */ 475 { "UDPTL", SDP_PROTO_T38 }, /* Note: IANA registry contains lower case */ 476 { "RTP/AVPF", SDP_PROTO_RTP }, /* RFC 4585 */ 477 { "RTP/SAVP", SDP_PROTO_SRTP }, /* RFC 3711 */ 478 { "RTP/SAVPF", SDP_PROTO_SRTP }, /* RFC 5124 */ 479 { "UDP/TLS/RTP/SAVP", SDP_PROTO_SRTP }, /* RFC 5764 */ 480 { "UDP/TLS/RTP/SAVPF", SDP_PROTO_SRTP }, /* RFC 5764 */ 481 { "msrp/tcp", SDP_PROTO_MSRP }, /* Not in IANA, where is this from? */ 482 { "UDPSPRT", SDP_PROTO_SPRT }, /* Not in IANA, but draft-rajeshkumar-avt-v150-registration-00 */ 483 { "udpsprt", SDP_PROTO_SPRT }, /* lowercase per section E.1.1 of ITU-T V.150.1 */ 484 }; 485 486 for (guint i = 0; i < G_N_ELEMENTS(protocols); i++) { 487 if (!strcmp(protocols[i].proto_name, media_proto)) { 488 return protocols[i].proto; 489 } 490 } 491 492 return SDP_PROTO_UNKNOWN; 493 } 494 495 /* Parses the parts from "c=" into address structures. */ 496 static void 497 parse_sdp_connection_address(const guint8 *connection_type, const char *connection_address, 498 wmem_allocator_t *allocator, address *conn_addr) 499 { 500 if (strcmp(connection_type, "IP4") == 0) { 501 guint32 ip4_addr; 502 503 if (str_to_ip(connection_address, &ip4_addr)) { 504 /* connection_address could be converted to a valid ipv4 address*/ 505 alloc_address_wmem(allocator, conn_addr, AT_IPv4, 4, &ip4_addr); 506 } 507 } else if (strcmp(connection_type, "IP6") == 0) { 508 ws_in6_addr ip6_addr; 509 510 if (str_to_ip6(connection_address, &ip6_addr)) { 511 /* connection_address could be converted to a valid ipv6 address*/ 512 alloc_address_wmem(allocator, conn_addr, AT_IPv6, 16, &ip6_addr); 513 } 514 } 515 } 516 517 /** 518 * Starts a new media description. If there are too many media descriptions, 519 * no new media description is started and NULL is returned. 520 */ 521 static media_description_t * 522 sdp_new_media_description(wmem_array_t *media_descriptions, session_info_t *session_info) 523 { 524 media_description_t empty_desc; 525 media_description_t *media_desc; 526 527 /* Limit number to avoid consuming excess memory. */ 528 if (wmem_array_get_count(media_descriptions) >= SDP_MAX_RTP_CHANNELS) { 529 DPRINT(("Too many media descriptions (more than %d), returning NULL!", 530 wmem_array_get_count(media_descriptions))); 531 return NULL; 532 } 533 534 memset(&empty_desc, 0, sizeof(media_description_t)); 535 wmem_array_append_one(media_descriptions, empty_desc); 536 media_desc = (media_description_t *) wmem_array_index(media_descriptions, 537 wmem_array_get_count(media_descriptions) - 1); 538 539 /* XXX does it make sense making media_desc->media.pt a wmem array? */ 540 541 /* If "c=" is given at the session level, copy it to the media description. 542 * It will be overridden as needed. */ 543 if (session_info->conn_addr.type != AT_NONE) { 544 copy_address_wmem(wmem_file_scope(), &media_desc->conn_addr, &session_info->conn_addr); 545 } 546 547 /* If "a=rtpmap:" was set on the session level, copy them to media level. */ 548 media_desc->media.rtp_dyn_payload = 549 rtp_dyn_payload_dup(session_info->rtp_dyn_payload); 550 551 return media_desc; 552 } 553 554 /* Remove information about media descriptions which are unused. These appeared 555 * in the "a=rtpmap:" (and maybe even in the payload types part of "m="?), but 556 * are not used (port is zero or it was not assigned to RTP dissector). */ 557 static void 558 clean_unused_media_descriptions(wmem_array_t *descs) 559 { 560 for (guint i = 0; i < wmem_array_get_count(descs); i++) { 561 media_description_t *media_desc = (media_description_t *)wmem_array_index(descs, i); 562 563 /* If not assigned to subdissector, clear the unused information. */ 564 if (!media_desc->media.set_rtp) { 565 rtp_dyn_payload_free(media_desc->media.rtp_dyn_payload); 566 media_desc->media.rtp_dyn_payload = NULL; 567 } 568 } 569 } 570 571 572 /* Subdissector functions */ 573 static void 574 dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) { 575 proto_tree *sdp_owner_tree; 576 gint offset, next_offset, tokenlen; 577 578 offset = 0; 579 580 sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner); 581 582 /* Find the username */ 583 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset); 584 if (tokenlen == 0) 585 return; 586 587 proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen, 588 ENC_UTF_8|ENC_NA); 589 offset = next_offset + 1; 590 591 /* Find the session id */ 592 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset); 593 if (tokenlen == 0) 594 return; 595 596 proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset, 597 tokenlen, ENC_UTF_8|ENC_NA); 598 offset = next_offset + 1; 599 600 /* Find the version */ 601 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset); 602 if (tokenlen == 0) 603 return; 604 605 proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen, 606 ENC_UTF_8|ENC_NA); 607 offset = next_offset + 1; 608 609 /* Find the network type */ 610 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset); 611 if (tokenlen == 0) 612 return; 613 614 proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset, 615 tokenlen, ENC_UTF_8|ENC_NA); 616 offset = next_offset + 1; 617 618 /* Find the address type */ 619 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset); 620 if (tokenlen == 0) 621 return; 622 623 proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset, 624 tokenlen, ENC_UTF_8|ENC_NA); 625 offset = next_offset + 1; 626 627 /* Find the address */ 628 proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_UTF_8|ENC_NA); 629 } 630 631 /* 632 * XXX - this can leak memory if an exception is thrown after we've fetched 633 * a string. 634 */ 635 static void 636 dissect_sdp_connection_info(packet_info *pinfo, tvbuff_t *tvb, proto_item* ti, session_info_t *session_info, media_description_t *media_desc) 637 { 638 proto_tree *sdp_connection_info_tree; 639 gint offset, next_offset, tokenlen; 640 const guint8 *connection_type, *connection_address; 641 642 offset = 0; 643 644 sdp_connection_info_tree = proto_item_add_subtree(ti, 645 ett_sdp_connection_info); 646 647 /* Find the network type */ 648 tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset); 649 if (tokenlen == 0) 650 return; 651 652 proto_tree_add_item(sdp_connection_info_tree, 653 hf_connection_info_network_type, tvb, offset, tokenlen, 654 ENC_UTF_8|ENC_NA); 655 offset = next_offset + 1; 656 657 /* Find the address type */ 658 tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset); 659 if (tokenlen == 0) 660 return; 661 662 /* Save connection address type */ 663 proto_tree_add_item_ret_string(sdp_connection_info_tree, 664 hf_connection_info_address_type, tvb, offset, tokenlen, 665 ENC_UTF_8|ENC_NA, pinfo->pool, &connection_type); 666 DPRINT(("parsed connection line type=%s", connection_type)); 667 offset = next_offset + 1; 668 669 /* Find the connection address */ 670 /* XXX - what if there's a <number of addresses> value? */ 671 next_offset = tvb_find_guint8(tvb, offset, -1, '/'); 672 if (next_offset == -1) { 673 tokenlen = -1; /* end of tvbuff */ 674 /* Save connection address */ 675 connection_address = tvb_get_string_enc(pinfo->pool, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_UTF_8|ENC_NA); 676 } else { 677 tokenlen = next_offset - offset; 678 /* Save connection address */ 679 connection_address = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 680 } 681 682 DPRINT(("parsed connection line address=%s", connection_address)); 683 /* Parse and store connection address. Session-level addresses are 684 * packet-scoped since they will be cloned in file-scope when needed. */ 685 if (session_info) { 686 parse_sdp_connection_address(connection_type, connection_address, 687 pinfo->pool, 688 &session_info->conn_addr); 689 } else if (media_desc) { 690 /* Clear possibly inherited address from session level. */ 691 free_address_wmem(wmem_file_scope(), &media_desc->conn_addr); 692 693 parse_sdp_connection_address(connection_type, connection_address, 694 wmem_file_scope(), 695 &media_desc->conn_addr); 696 } 697 698 proto_tree_add_item(sdp_connection_info_tree, 699 hf_connection_info_connection_address, tvb, offset, 700 tokenlen, ENC_UTF_8|ENC_NA); 701 if (next_offset != -1) { 702 offset = next_offset + 1; 703 next_offset = tvb_find_guint8(tvb, offset, -1, '/'); 704 if (next_offset == -1) { 705 tokenlen = -1; /* end of tvbuff */ 706 } else { 707 tokenlen = next_offset - offset; 708 } 709 proto_tree_add_item(sdp_connection_info_tree, 710 hf_connection_info_ttl, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 711 if (next_offset != -1) { 712 offset = next_offset + 1; 713 proto_tree_add_item(sdp_connection_info_tree, 714 hf_connection_info_num_addr, tvb, offset, -1, ENC_UTF_8|ENC_NA); 715 } 716 } 717 } 718 719 static void 720 dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) { 721 proto_tree *sdp_bandwidth_tree; 722 gint offset, next_offset, tokenlen; 723 proto_item *item; 724 gboolean unit_is_kbs = FALSE; 725 gboolean unit_is_bps = FALSE; 726 727 offset = 0; 728 729 sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth); 730 731 /* find the modifier */ 732 next_offset = tvb_find_guint8(tvb, offset, -1, ':'); 733 734 if (next_offset == -1) 735 return; 736 737 tokenlen = next_offset - offset; 738 739 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset, 740 tokenlen, ENC_UTF_8|ENC_NA); 741 if (tvb_strneql(tvb, offset, "CT", 2) == 0) { 742 proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]"); 743 unit_is_kbs = TRUE; 744 } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) { 745 proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]"); 746 unit_is_kbs = TRUE; 747 } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) { 748 proto_item_append_text(item, " [Transport Independent Application Specific maximum]"); 749 unit_is_bps = TRUE; 750 } 751 752 753 offset = next_offset + 1; 754 755 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1, 756 ENC_UTF_8|ENC_NA); 757 if (unit_is_kbs == TRUE) 758 proto_item_append_text(item, " kb/s"); 759 if (unit_is_bps == TRUE) 760 proto_item_append_text(item, " b/s"); 761 } 762 763 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) { 764 proto_tree *sdp_time_tree; 765 gint offset, next_offset, tokenlen; 766 767 offset = 0; 768 769 sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time); 770 771 /* get start time */ 772 tokenlen = find_next_token_in_line(tvb, sdp_time_tree, &offset, &next_offset); 773 if (tokenlen == 0) 774 return; 775 776 proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen, 777 ENC_UTF_8|ENC_NA); 778 779 /* get stop time */ 780 offset = next_offset + 1; 781 proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_UTF_8|ENC_NA); 782 } 783 784 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) { 785 proto_tree *sdp_repeat_time_tree; 786 gint offset, next_offset, tokenlen; 787 gboolean optional = FALSE; 788 789 offset = 0; 790 791 sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time); 792 793 /* get interval */ 794 tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset); 795 if (tokenlen == 0) 796 return; 797 798 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb, 799 offset, tokenlen, ENC_UTF_8|ENC_NA); 800 801 /* get duration */ 802 offset = next_offset + 1; 803 tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset); 804 if (tokenlen == 0) 805 return; 806 807 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb, 808 offset, tokenlen, ENC_UTF_8|ENC_NA); 809 810 /* get offsets */ 811 do { 812 offset = next_offset +1; 813 tokenlen = find_next_optional_token_in_line(tvb, sdp_repeat_time_tree, 814 &offset, &next_offset, optional); 815 if (tokenlen == 0) 816 break; 817 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset, 818 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 819 optional = TRUE; 820 } while (next_offset != -1); 821 822 } 823 824 static void 825 dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) { 826 proto_tree* sdp_timezone_tree; 827 gint offset, next_offset, tokenlen; 828 gboolean optional = FALSE; 829 830 offset = 0; 831 832 sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone); 833 834 do { 835 tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree, 836 &offset, &next_offset, optional); 837 if (tokenlen == 0) 838 break; 839 840 proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset, 841 tokenlen, ENC_UTF_8|ENC_NA); 842 offset = next_offset + 1; 843 tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree, 844 &offset, &next_offset, optional); 845 if (tokenlen == 0) 846 break; 847 proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset, 848 tokenlen, ENC_UTF_8|ENC_NA); 849 offset = next_offset + 1; 850 optional = TRUE; 851 } while (next_offset != -1); 852 853 } 854 855 856 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) { 857 proto_tree *sdp_encryption_key_tree; 858 gint offset, next_offset, tokenlen; 859 860 offset = 0; 861 862 sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key); 863 864 next_offset = tvb_find_guint8(tvb, offset, -1, ':'); 865 866 if (next_offset == -1) 867 return; 868 869 tokenlen = next_offset - offset; 870 871 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type, 872 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 873 874 offset = next_offset + 1; 875 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data, 876 tvb, offset, -1, ENC_UTF_8|ENC_NA); 877 } 878 879 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) { 880 gchar *data_p = NULL; 881 const guint8 *prtcl_id = NULL; 882 gint len; 883 tvbuff_t *keymgmt_tvb; 884 int found_match = 0; 885 proto_tree *key_tree; 886 gint next_offset; 887 gint offset = 0; 888 gint tokenlen; 889 890 key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt); 891 892 tokenlen = find_next_token_in_line(tvb, key_tree, &offset, &next_offset); 893 if (tokenlen == 0) 894 return; 895 896 proto_tree_add_item_ret_string(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &prtcl_id); 897 898 offset = next_offset + 1; 899 900 len = tvb_captured_length_remaining(tvb, offset); 901 if (len < 0) 902 return; 903 904 data_p = (gchar *)tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_UTF_8|ENC_NA); 905 keymgmt_tvb = base64_to_tvb(tvb, data_p); 906 add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data"); 907 908 if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) { 909 found_match = dissector_try_string(key_mgmt_dissector_table, 910 (const gchar *)prtcl_id, 911 keymgmt_tvb, pinfo, 912 key_tree, NULL); 913 } 914 915 if (found_match) { 916 proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data, 917 keymgmt_tvb, 0, -1, ENC_NA); 918 proto_item_set_hidden(ti2); 919 } else { 920 proto_tree_add_item(key_tree, hf_key_mgmt_data, 921 keymgmt_tvb, 0, -1, ENC_NA); 922 } 923 924 } 925 926 927 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) { 928 proto_tree *sdp_session_attribute_tree; 929 gint offset, next_offset, tokenlen; 930 const guint8 *field_name; 931 932 offset = 0; 933 934 sdp_session_attribute_tree = proto_item_add_subtree(ti, 935 ett_sdp_session_attribute); 936 937 next_offset = tvb_find_guint8(tvb, offset, -1, ':'); 938 939 if (next_offset == -1) 940 return; 941 942 tokenlen = next_offset - offset; 943 944 proto_tree_add_item_ret_string(sdp_session_attribute_tree, hf_session_attribute_field, 945 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &field_name); 946 947 offset = next_offset + 1; 948 949 if (strcmp((const char *)field_name, "ipbcp") == 0) { 950 offset = tvb_ws_mempbrk_pattern_guint8(tvb, offset, -1,&pbrk_digits, NULL); 951 952 if (offset == -1) 953 return; 954 955 tokenlen = find_next_token_in_line(tvb, sdp_session_attribute_tree, &offset, &next_offset); 956 if (tokenlen == 0) 957 return; 958 959 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 960 961 offset = tvb_ws_mempbrk_pattern_guint8(tvb, offset, -1,&pbrk_alpha, NULL); 962 963 if (offset == -1) 964 return; 965 966 tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE); 967 968 if (tokenlen == -1) 969 return; 970 971 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 972 } else if (strcmp((const char *)field_name, "key-mgmt") == 0) { 973 tvbuff_t *key_tvb; 974 proto_item *key_ti; 975 976 key_tvb = tvb_new_subset_remaining(tvb, offset); 977 key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_UTF_8|ENC_NA); 978 979 dissect_key_mgmt(key_tvb, pinfo, key_ti); 980 } else { 981 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value, 982 tvb, offset, -1, ENC_UTF_8|ENC_NA); 983 } 984 } 985 986 987 /* Dissect media description - this is passed the line starting after 'm=', so like one of these: 988 * audio 29156 RTP/AVP 18 0 989 * video 49170/2 RTP/AVP 31 99 990 */ 991 static void 992 dissect_sdp_media(tvbuff_t *tvb, packet_info* pinfo, proto_item *ti, 993 media_description_t *media_desc) { 994 proto_tree *sdp_media_tree; 995 gint offset, next_offset, tokenlen, idx; 996 guint8 *media_format; 997 gboolean optional = FALSE; 998 proto_item *it; 999 const guint8 *media_type_str; 1000 const guint8 *media_port_str; 1001 const guint8 *media_proto_str; 1002 transport_proto_t transport_proto; 1003 guint16 media_port; 1004 gboolean media_port_valid; 1005 proto_item *pi; 1006 1007 offset = 0; 1008 1009 /* Create tree for media session */ 1010 sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media); 1011 1012 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset); 1013 if (tokenlen == 0) 1014 return; 1015 1016 /* Type of media session */ 1017 proto_tree_add_item_ret_string(sdp_media_tree, hf_media_media, tvb, offset, tokenlen, 1018 ENC_UTF_8|ENC_NA, pinfo->pool, &media_type_str); 1019 if (media_desc) { 1020 /* for RTP statistics (supposedly?) */ 1021 if (strcmp((const char*)media_type_str, "audio") == 0) 1022 media_desc->media_types |= RTP_MEDIA_AUDIO; 1023 else if (strcmp((const char*)media_type_str, "video") == 0) 1024 media_desc->media_types |= RTP_MEDIA_VIDEO; 1025 else 1026 media_desc->media_types |= RTP_MEDIA_OTHER; 1027 } 1028 DPRINT(("parsed media_type=%s", media_type_str)); 1029 1030 offset = next_offset + 1; 1031 1032 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset); 1033 if (tokenlen == 0) 1034 return; 1035 1036 next_offset = tvb_find_guint8(tvb, offset, tokenlen, '/'); 1037 1038 if (next_offset != -1) { 1039 tokenlen = next_offset - offset; 1040 /* Save port info */ 1041 it = proto_tree_add_item_ret_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen, 1042 ENC_UTF_8|ENC_NA, pinfo->pool, &media_port_str); 1043 DPRINT(("parsed media_port=%s", media_port_str)); 1044 if (g_ascii_isdigit(media_port_str[0])) { 1045 proto_item_set_hidden(it); 1046 media_port_valid = ws_strtou16(media_port_str, NULL, &media_port); 1047 pi = proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen, 1048 media_port); 1049 if (!media_port_valid) 1050 expert_add_info(pinfo, pi, &ei_sdp_invalid_media_port); 1051 if (media_desc) { 1052 media_desc->media_port = media_port; 1053 } 1054 } 1055 1056 offset = next_offset + 1; 1057 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset); 1058 if (tokenlen == 0) 1059 return; 1060 1061 /* TODO: this puts the (optional) number of ports in the tree, but we don't 1062 actually use it for building the extra RTP flows, which we should. */ 1063 proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset, 1064 tokenlen, ENC_UTF_8|ENC_NA); 1065 offset = next_offset + 1; 1066 } else { 1067 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset); 1068 if (tokenlen == 0) 1069 return; 1070 1071 /* Save port info */ 1072 it = proto_tree_add_item_ret_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen, 1073 ENC_UTF_8|ENC_NA, pinfo->pool, &media_port_str); 1074 DPRINT(("parsed media_port=%s", media_port_str)); 1075 if (g_ascii_isdigit(media_port_str[0])) { 1076 proto_item_set_hidden(it); 1077 media_port_valid = ws_strtou16(media_port_str, NULL, &media_port); 1078 pi = proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen, 1079 media_port); 1080 if (!media_port_valid) 1081 expert_add_info(pinfo, pi, &ei_sdp_invalid_media_port); 1082 if (media_desc) { 1083 media_desc->media_port = media_port; 1084 } 1085 } 1086 offset = next_offset + 1; 1087 } 1088 1089 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset); 1090 if (tokenlen == 0) 1091 return; 1092 1093 /* Save port protocol */ 1094 proto_tree_add_item_ret_string(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen, 1095 ENC_UTF_8|ENC_NA, pinfo->pool, &media_proto_str); 1096 DPRINT(("parsed media_proto=%s", media_proto_str)); 1097 /* Detect protocol for registering with other dissectors like RTP. */ 1098 transport_proto = parse_sdp_media_protocol(media_proto_str); 1099 if (media_desc) { 1100 media_desc->proto = transport_proto; 1101 } 1102 1103 do { 1104 offset = next_offset + 1; 1105 tokenlen = find_next_optional_token_in_line(tvb, sdp_media_tree, 1106 &offset, &next_offset, optional); 1107 if (tokenlen == 0) 1108 break; 1109 1110 /* RFC 4566: If the <proto> sub-field is "RTP/AVP" or "RTP/SAVP" the 1111 * <fmt> sub-fields contain RTP payload type numbers. */ 1112 if (transport_proto == SDP_PROTO_RTP || transport_proto == SDP_PROTO_SRTP) { 1113 media_format = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1114 if (g_ascii_isdigit(media_format[0])) { 1115 proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset, 1116 tokenlen, val_to_str_ext((guint32)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u")); 1117 1118 if (media_desc) { 1119 idx = media_desc->media.pt_count; 1120 media_desc->media.pt[idx] = (gint32)strtol((char*)media_format, NULL, 10); 1121 DPRINT(("parsed media codec pt=%d", media_desc->media.pt[idx])); 1122 if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1)) 1123 media_desc->media.pt_count++; 1124 } 1125 } else { 1126 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset, 1127 tokenlen, ENC_UTF_8|ENC_NA); 1128 } 1129 } else { 1130 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset, 1131 tokenlen, ENC_UTF_8|ENC_NA); 1132 } 1133 optional = TRUE; 1134 } while (next_offset != -1); 1135 1136 /* XXX Dissect traffic to "Port" as "Protocol" 1137 * Remember this Port/Protocol pair so we can tear it down again later 1138 * Actually, it's harder than that: 1139 * We need to find out the address of the other side first and it 1140 * looks like that info can be found in SIP headers only. 1141 */ 1142 1143 } 1144 1145 static tvbuff_t * 1146 ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg) 1147 { 1148 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240); 1149 1150 /* arbitrary maximum length */ 1151 if (len < 20480) { 1152 int i; 1153 tvbuff_t *bytes_tvb; 1154 1155 /* first, skip to where the encoded pdu starts, this is 1156 the first hex digit after the '=' char. 1157 */ 1158 while (1) { 1159 if ((*msg == 0) || (*msg == '\n')) { 1160 return NULL; 1161 } 1162 if (*msg == '=') { 1163 msg++; 1164 break; 1165 } 1166 msg++; 1167 } 1168 while (1) { 1169 if ((*msg == 0) || (*msg == '\n')) { 1170 return NULL; 1171 } 1172 if ( ((*msg >= '0') && (*msg <= '9')) 1173 || ((*msg >= 'a') && (*msg <= 'f')) 1174 || ((*msg >= 'A') && (*msg <= 'F'))) { 1175 break; 1176 } 1177 msg++; 1178 } 1179 i = 0; 1180 while (((*msg >= '0') && (*msg <= '9')) 1181 || ((*msg >= 'a') && (*msg <= 'f')) 1182 || ((*msg >= 'A') && (*msg <= 'F'))) { 1183 int val; 1184 if ((*msg >= '0') && (*msg <= '9')) { 1185 val = (*msg)-'0'; 1186 } else if ((*msg >= 'a') && (*msg <= 'f')) { 1187 val = (*msg)-'a'+10; 1188 } else if ((*msg >= 'A') && (*msg <= 'F')) { 1189 val = (*msg)-'A'+10; 1190 } else { 1191 return NULL; 1192 } 1193 val <<= 4; 1194 msg++; 1195 if ((*msg >= '0') && (*msg <= '9')) { 1196 val |= (*msg)-'0'; 1197 } else if ((*msg >= 'a') && (*msg <= 'f')) { 1198 val |= (*msg)-'a'+10; 1199 } else if ((*msg >= 'A') && (*msg <= 'F')) { 1200 val |= (*msg)-'A'+10; 1201 } else { 1202 return NULL; 1203 } 1204 msg++; 1205 1206 buf[i] = (guint8)val; 1207 i++; 1208 } 1209 if (i == 0) { 1210 return NULL; 1211 } 1212 bytes_tvb = tvb_new_child_real_data(tvb, buf, i, i); 1213 add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb"); 1214 return bytes_tvb; 1215 } 1216 return NULL; 1217 } 1218 1219 /* Annex X Profiles and levels definition */ 1220 static const value_string h263_profile_vals[] = 1221 { 1222 { 0, "Baseline Profile" }, 1223 { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" }, 1224 { 2, "Version 1 Backward-Compatibility Profile" }, 1225 { 3, "Version 2 Interactive and Streaming Wireless Profile" }, 1226 { 4, "Version 3 Interactive and Streaming Wireless Profile" }, 1227 { 5, "Conversational High Compression Profile" }, 1228 { 6, "Conversational Internet Profile" }, 1229 { 7, "Conversational Interlace Profile" }, 1230 { 8, "High Latency Profile" }, 1231 { 0, NULL }, 1232 }; 1233 1234 1235 /* RFC 4629 The level are described in table X.2 of H.263 annex X */ 1236 static const value_string h263_level_vals[] = 1237 { 1238 { 10, "QCIF (176 x 144), 1 x 64Kb/s" }, 1239 { 20, "CIF (352 x 288), 2 x 64Kb/s" }, 1240 { 30, "CIF (352 x 288), 6 x 64Kb/s" }, 1241 { 40, "CIF (352 x 288), 32 x 64Kb/s" }, 1242 { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" }, 1243 { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" }, 1244 { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" }, 1245 { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" }, 1246 { 0, NULL }, 1247 }; 1248 1249 1250 static const value_string h264_packetization_mode_vals[] = 1251 { 1252 { 0, "Single NAL mode" }, 1253 { 1, "Non-interleaved mode" }, 1254 { 2, "Interleaved mode" }, 1255 { 0, NULL }, 1256 }; 1257 1258 /* 1259 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types 1260 */ 1261 static void 1262 decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type) { 1263 gint next_offset; 1264 gint end_offset; 1265 guint8 *field_name; 1266 gchar *format_specific_parameter; 1267 proto_item *item; 1268 tvbuff_t * volatile data_tvb; 1269 1270 end_offset = offset + tokenlen; 1271 1272 #if 0 1273 proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'", 1274 tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII)); 1275 #endif 1276 1277 /* Look for an '=' within this value - this may indicate that there is a 1278 profile-level-id parameter to find if the MPEG4 media type is in use */ 1279 next_offset = tvb_find_guint8(tvb, offset, -1, '='); 1280 if (next_offset == -1) 1281 { 1282 /* Give up (and avoid exception) if '=' not found */ 1283 return; 1284 } 1285 1286 /* Find the name of the parameter */ 1287 tokenlen = next_offset - offset; 1288 field_name = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1289 #if 0 1290 proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */ 1291 #endif 1292 offset = next_offset; 1293 1294 /* Dissect the MPEG4 profile-level-id parameter if present */ 1295 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) { 1296 if (strcmp((char*)field_name, "profile-level-id") == 0) { 1297 offset++; 1298 tokenlen = end_offset - offset; 1299 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1300 item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen, 1301 (guint32)strtol((char*)format_specific_parameter, NULL, 10)); 1302 proto_item_set_generated(item); 1303 } else if (strcmp((char*)field_name, "config") == 0) { 1304 /* String including "=" */ 1305 tokenlen = end_offset - offset; 1306 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1307 /* ascii_bytes_to_tvb requires the "=" to be in the buffer */ 1308 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter); 1309 if (mp4ves_config_handle && data_tvb) { 1310 call_dissector(mp4ves_config_handle, data_tvb, pinfo, tree); 1311 } 1312 } 1313 } 1314 1315 /* Dissect the H263-2000 profile parameter if present */ 1316 if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) || 1317 ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) { 1318 if (strcmp((char*)field_name, "profile") == 0) { 1319 offset++; 1320 tokenlen = end_offset - offset; 1321 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1322 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen, 1323 (guint32)strtol((char*)format_specific_parameter, NULL, 10)); 1324 proto_item_set_generated(item); 1325 } else if (strcmp((char*)field_name, "level") == 0) { 1326 offset++; 1327 tokenlen = end_offset - offset; 1328 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1329 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen, 1330 (guint32)strtol((char*)format_specific_parameter, NULL, 10)); 1331 proto_item_set_generated(item); 1332 } 1333 } 1334 1335 1336 /* Dissect the H264 profile-level-id parameter 1337 * RFC 3984: 1338 * A base16 [6] (hexadecimal) representation of 1339 * the following three bytes in the sequence 1340 * parameter set NAL unit specified in [1]: 1) 1341 * profile_idc, 2) a byte herein referred to as 1342 * profile-iop, composed of the values of 1343 * constraint_set0_flag, constraint_set1_flag, 1344 * constraint_set2_flag, and reserved_zero_5bits 1345 * in bit-significance order, starting from the 1346 * most significant bit, and 3) level_idc. 1347 */ 1348 if ((mime_type != NULL) && ((g_ascii_strcasecmp(mime_type, "H264") == 0) || (g_ascii_strcasecmp(mime_type, "H264-SVC") == 0))) { 1349 if (strcmp(field_name, "profile-level-id") == 0) { 1350 int length = 0; 1351 1352 /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/ 1353 tokenlen = end_offset - offset; 1354 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1355 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter); 1356 if (!data_tvb) { 1357 proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter); 1358 return; 1359 } 1360 length = tvb_reported_length(data_tvb); 1361 if (length == 3) { 1362 if (h264_handle && data_tvb) { 1363 dissect_h264_profile(data_tvb, pinfo, tree); 1364 } 1365 } else { 1366 item = proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes"); 1367 proto_item_set_generated(item); 1368 } 1369 } else if (strcmp(field_name, "packetization-mode") == 0) { 1370 offset++; 1371 tokenlen = end_offset - offset; 1372 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1373 item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen, 1374 (guint32)strtol((char*)format_specific_parameter, NULL, 10)); 1375 proto_item_set_generated(item); 1376 } else if (strcmp(field_name, "sprop-parameter-sets") == 0) { 1377 /* The value of the parameter is the 1378 base64 [6] representation of the initial 1379 parameter set NAL units as specified in 1380 sections 7.3.2.1 and 7.3.2.2 of [1]. The 1381 parameter sets are conveyed in decoding order, 1382 and no framing of the parameter set NAL units 1383 takes place. A comma is used to separate any 1384 pair of parameter sets in the list. 1385 */ 1386 const guint8 *data_p = NULL; 1387 gint comma_offset; 1388 1389 1390 /* Move past '=' */ 1391 offset++; 1392 comma_offset = tvb_find_guint8(tvb, offset, -1, ','); 1393 if (comma_offset != -1) { 1394 tokenlen = comma_offset - offset; 1395 } else { 1396 tokenlen = end_offset - offset; 1397 } 1398 1399 proto_tree_add_item_ret_string(tree, hf_sdp_nal_unit_1_string, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &data_p); 1400 1401 data_tvb = base64_to_tvb(tvb, data_p); 1402 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets"); 1403 1404 if (h264_handle && data_tvb) { 1405 TRY { 1406 dissect_h264_nal_unit(data_tvb, pinfo, tree); 1407 } 1408 CATCH_NONFATAL_ERRORS { 1409 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE); 1410 } 1411 ENDTRY; 1412 if (comma_offset != -1) { 1413 /* Second NAL unit */ 1414 offset = comma_offset +1; 1415 tokenlen = end_offset - offset; 1416 proto_tree_add_item_ret_string(tree, hf_sdp_nal_unit_2_string, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &data_p); 1417 data_tvb = base64_to_tvb(tvb, data_p); 1418 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2"); 1419 dissect_h264_nal_unit(data_tvb, pinfo, tree); 1420 } 1421 } 1422 } 1423 } 1424 1425 /* Dissect the H265 1426 * RFC 7798: 1427 */ 1428 else if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H265") == 0)) { 1429 if (strcmp(field_name, "sprop-vps") == 0 || strcmp(field_name, "sprop-sps") == 0 || strcmp(field_name, "sprop-pps") == 0) { 1430 1431 /* Move past '=' */ 1432 offset++; 1433 tokenlen = end_offset - offset; 1434 format_specific_parameter = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8 | ENC_NA); 1435 data_tvb = base64_to_tvb(tvb, format_specific_parameter); 1436 add_new_data_source(pinfo, data_tvb, field_name); 1437 if (h265_handle && data_tvb) { 1438 dissect_h265_format_specific_parameter(tree, data_tvb, pinfo); 1439 } 1440 } 1441 } 1442 1443 } 1444 1445 static const string_string ice_candidate_types[] = { 1446 { "host", "Host candidate" }, 1447 { "srflx", "Server reflexive candidate" }, 1448 { "prflx", "Peer reflexive candidate" }, 1449 { "relay", "Relayed candidate" }, 1450 { 0, NULL } 1451 }; 1452 1453 static void 1454 dissect_sdp_media_attribute_candidate(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset) 1455 { 1456 /* RFC 5245 (ICE): "The candidate attribute is a media-level attribute 1457 * only. It contains a transport address for a candidate that can be 1458 * used for connectivity checks." 1459 * https://tools.ietf.org/html/rfc5245#section-15.1 1460 * 1461 * candidate-attribute = "candidate" ":" foundation SP component-id SP 1462 * transport SP 1463 * priority SP 1464 * connection-address SP ;from RFC 4566 1465 * port ;port from RFC 4566 1466 * SP cand-type 1467 * [SP rel-addr] 1468 * [SP rel-port] 1469 * *(SP extension-att-name SP 1470 * extension-att-value) 1471 * 1472 * Example: "candidate:0 1 UDP 2122252543 10.9.0.2 60299 typ host" 1473 */ 1474 proto_item *pi; 1475 gint next_offset, tokenlen; 1476 const guint8 *candidate_type; 1477 1478 /* foundation: between 1 and 32 "ICE chars" (ALPHA / DIGIT / "+" / "/") */ 1479 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1480 if (tokenlen == 0) 1481 return; 1482 proto_tree_add_item(tree, hf_ice_candidate_foundation, 1483 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1484 offset = next_offset + 1; 1485 1486 /* component-id: integer between 1 and 256. 1487 * For RTP, 1 MUST be RTP and 2 MUST be RTCP (RFC 5245) */ 1488 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1489 if (tokenlen == 0) 1490 return; 1491 proto_tree_add_item(tree, hf_ice_candidate_componentid, 1492 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1493 offset = next_offset + 1; 1494 1495 /* transport: "UDP", etc. */ 1496 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1497 if (tokenlen == 0) 1498 return; 1499 proto_tree_add_item(tree, hf_ice_candidate_transport, 1500 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1501 offset = next_offset + 1; 1502 1503 /* priority: integer between 1 and 2^31-1 */ 1504 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1505 if (tokenlen == 0) 1506 return; 1507 proto_tree_add_item(tree, hf_ice_candidate_priority, 1508 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1509 offset = next_offset + 1; 1510 1511 /* connection-address: IPv4, IPv6 address or FQDN. */ 1512 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1513 if (tokenlen == 0) 1514 return; 1515 proto_tree_add_item(tree, hf_ice_candidate_address, 1516 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1517 offset = next_offset + 1; 1518 1519 /* port */ 1520 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1521 if (tokenlen == 0) 1522 return; 1523 proto_tree_add_item(tree, hf_ice_candidate_port, 1524 tvb, offset, tokenlen, ENC_ASCII|ENC_NA); 1525 offset = next_offset + 1; 1526 1527 /* cand-type: type of candidate (where it learned the candidate) 1528 * Check for "typ " in "typ host" and skip it. */ 1529 if (tvb_strneql(tvb, offset, "typ ", 4)) 1530 return; 1531 offset += 4; 1532 tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset); 1533 if (tokenlen == 0) 1534 return; 1535 pi = proto_tree_add_item_ret_string(tree, hf_ice_candidate_type, 1536 tvb, offset, tokenlen, ENC_ASCII|ENC_NA, 1537 pinfo->pool, &candidate_type); 1538 if ((candidate_type = try_str_to_str(candidate_type, ice_candidate_types))) { 1539 proto_item_append_text(pi, " (%s)", candidate_type); 1540 } 1541 /* offset = next_offset + 1; */ 1542 1543 /* Ignored: [rel-addr] [rel-port] *(extension-att-name extension-att-value) */ 1544 } 1545 1546 typedef struct { 1547 const char *name; 1548 } sdp_names_t; 1549 1550 #define SDP_RTPMAP 1 1551 #define SDP_FMTP 2 1552 #define SDP_PATH 3 1553 #define SDP_H248_ITEM 4 1554 #define SDP_CRYPTO 5 1555 #define SDP_SPRTMAP 6 1556 #define SDP_CANDIDATE 7 1557 #define SDP_ED137_TYPE 8 1558 #define SDP_ED137_TXRXMODE 9 1559 #define SDP_ED137_FID 10 1560 #define SDP_RTCP 11 1561 #define SDP_RTCP_MUX 12 1562 1563 static const sdp_names_t sdp_media_attribute_names[] = { 1564 { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */ 1565 { "rtpmap"}, /* 1 */ 1566 { "fmtp"}, /* 2 */ 1567 { "path"}, /* 3 */ 1568 { "h248item"}, /* 4 */ 1569 { "crypto"}, /* 5 */ 1570 { "sprt"}, /* 6 */ 1571 { "candidate" }, /* 7 */ 1572 { "type" }, /* 8 */ 1573 { "txrxmode" }, /* 9 */ 1574 { "fid" }, /* 10 */ 1575 { "rtcp" }, /* 11 */ 1576 { "rtcp-mux" }, /* 12 */ 1577 }; 1578 1579 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len) 1580 { 1581 guint i; 1582 1583 for (i = 1; i < array_length(sdp_media_attribute_names); i++) { 1584 if ((len == strlen(sdp_media_attribute_names[i].name)) && 1585 (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0)) 1586 return i; 1587 } 1588 1589 return -1; 1590 } 1591 1592 /* A few protocols give the fmtp parameter as a string instead of a 1593 * numeric payload type, list them here (lower case for comparison). 1594 */ 1595 static const string_string media_format_str_types[] = { 1596 /* ETSI TS 102 472, ETSI TS 102 592 */ 1597 { "ipdc-kmm", "IP Datacast Key Management Message"}, 1598 { "ipdc-ksm", "IP Datacast Key Stream Message"}, 1599 /* ETSI TS 124 380 */ 1600 { "mcptt", "Mission Critical Push To Talk"}, 1601 /* ETSI TS 124 581 */ 1602 { "mcvideo", "Mission Critical Video"}, 1603 /* OMA PoC Control Plane */ 1604 { "tbcp", "Talk Burst Control Protocol"}, 1605 { 0, NULL } 1606 }; 1607 1608 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length, 1609 transport_info_t *transport_info, 1610 session_info_t *session_info, 1611 media_description_t *media_desc, 1612 sdp_data_t *sdp_data) 1613 { 1614 proto_tree *sdp_media_attribute_tree, *parameter_item; 1615 proto_item *fmtp_item, *media_format_item, *parameter_tree; 1616 proto_tree *fmtp_tree; 1617 proto_item *pi; 1618 gint offset, next_offset, tokenlen, colon_offset; 1619 /*??guint8 *field_name;*/ 1620 const guint8 *payload_type; 1621 const guint8 *media_format_str; 1622 guint8 *attribute_value; 1623 guint8 pt; 1624 gint sdp_media_attrbute_code; 1625 const char *msrp_res = "msrp://"; 1626 const char *h324ext_h223lcparm = "h324ext/h223lcparm"; 1627 gboolean has_more_pars = TRUE; 1628 tvbuff_t *h245_tvb; 1629 guint8 master_key_length = 0, master_salt_length = 0; 1630 guint32 crypto_tag; 1631 gboolean crypto_tag_valid; 1632 gboolean mki_len_valid; 1633 1634 offset = 0; 1635 1636 /* Create attribute tree */ 1637 sdp_media_attribute_tree = proto_item_add_subtree(ti, 1638 ett_sdp_media_attribute); 1639 /* Find end of field */ 1640 colon_offset = tvb_find_guint8(tvb, offset, -1, ':'); 1641 1642 if (colon_offset == -1) 1643 return; 1644 1645 /* Attribute field name is token before ':' */ 1646 tokenlen = colon_offset - offset; 1647 pi = proto_tree_add_item(sdp_media_attribute_tree, 1648 hf_media_attribute_field, 1649 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1650 /*??field_name = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);*/ 1651 sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen); 1652 1653 /* Skip colon */ 1654 offset = colon_offset + 1; 1655 /* skip leading wsp */ 1656 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); 1657 1658 /* Value is the remainder of the line */ 1659 if (tvb_captured_length_remaining(tvb, offset) > 0) 1660 attribute_value = tvb_get_string_enc(pinfo->pool, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_UTF_8|ENC_NA); 1661 else 1662 { 1663 expert_add_info(pinfo, pi, &ei_sdp_invalid_line_fields); 1664 return; 1665 } 1666 1667 /*********************************************/ 1668 /* Special parsing for some field name types */ 1669 1670 switch (sdp_media_attrbute_code) { 1671 case SDP_RTPMAP: 1672 /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */ 1673 next_offset = tvb_find_guint8(tvb, offset, -1, ' '); 1674 1675 if (next_offset == -1) 1676 return; 1677 1678 tokenlen = next_offset - offset; 1679 1680 proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb, 1681 offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &payload_type); 1682 1683 offset = next_offset + 1; 1684 1685 next_offset = tvb_find_guint8(tvb, offset, -1, '/'); 1686 1687 if (next_offset == -1) { 1688 return; 1689 } 1690 1691 tokenlen = next_offset - offset; 1692 1693 proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb, 1694 offset, tokenlen, ENC_UTF_8|ENC_NA); 1695 1696 if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) { 1697 return; /* Invalid */ 1698 } 1699 1700 /* String is file scope allocated because transport_info is connection related */ 1701 transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1702 1703 next_offset = next_offset + 1; 1704 offset = next_offset; 1705 while (length-1 >= next_offset) { 1706 if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset))) 1707 break; 1708 next_offset++; 1709 } 1710 tokenlen = next_offset - offset; 1711 pi = proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb, 1712 offset, tokenlen, ENC_UTF_8|ENC_NA); 1713 transport_info->sample_rate[pt] = 0; 1714 if (!ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA), 1715 NULL, &transport_info->sample_rate[pt])) { 1716 expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate); 1717 } else if (!strcmp(transport_info->encoding_name[pt], "G722")) { 1718 // The reported sampling rate is 8000, but the actual value is 1719 // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2 1720 proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)"); 1721 } 1722 /* As per RFC2327 it is possible to have multiple Media Descriptions ("m="). 1723 For example: 1724 1725 a=rtpmap:101 G726-32/8000 1726 m=audio 49170 RTP/AVP 0 97 1727 a=rtpmap:97 telephone-event/8000 1728 m=audio 49172 RTP/AVP 97 101 1729 a=rtpmap:97 G726-24/8000 1730 1731 The Media attributes ("a="s) after the "m=" only apply for that "m=". 1732 If there is an "a=" before the first "m=", that attribute applies for 1733 all the session (all the "m="s). 1734 */ 1735 1736 if (session_info) { 1737 /* If this "a=" appear before any "m=", we add it to the session 1738 * info, these will be added later to all media (via 1739 * sdp_new_media_description). 1740 */ 1741 rtp_dyn_payload_insert(session_info->rtp_dyn_payload, 1742 pt, 1743 transport_info->encoding_name[pt], 1744 transport_info->sample_rate[pt]); 1745 } else if (media_desc) { 1746 /* if the "a=" is after an "m=", only apply to this "m=" */ 1747 rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload, 1748 pt, 1749 transport_info->encoding_name[pt], 1750 transport_info->sample_rate[pt]); 1751 } 1752 break; 1753 case SDP_FMTP: 1754 if (sdp_media_attribute_tree) { 1755 guint8 media_format; 1756 /* Reading the Format parameter(fmtp) */ 1757 /* Skip leading space, if any */ 1758 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); 1759 /* Media format extends to the next space */ 1760 next_offset = tvb_find_guint8(tvb, offset, -1, ' '); 1761 1762 if (next_offset == -1) 1763 return; 1764 1765 tokenlen = next_offset - offset; 1766 1767 media_format_item = proto_tree_add_item_ret_string(sdp_media_attribute_tree, hf_media_format, tvb, 1768 offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool, &payload_type); 1769 1770 /* Append encoding name to format if known */ 1771 payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1); 1772 media_format = 0; 1773 if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) { 1774 1775 proto_item_append_text(media_format_item, " [%s]", 1776 media_format_str); 1777 } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) { 1778 if (media_format) { 1779 proto_item_append_text(media_format_item, " [%s]", 1780 transport_info->encoding_name[media_format]); 1781 } 1782 } else { 1783 expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format); 1784 return; 1785 } 1786 1787 1788 #if 0 /* XXX: ?? */ 1789 payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII); 1790 #endif 1791 /* Move offset past the payload type */ 1792 offset = next_offset + 1; 1793 1794 while (has_more_pars == TRUE) { 1795 next_offset = tvb_find_guint8(tvb, offset, -1, ';'); 1796 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset)); 1797 1798 if (next_offset == -1) { 1799 has_more_pars = FALSE; 1800 next_offset= tvb_captured_length(tvb); 1801 } 1802 1803 /* There are at least 2 - add the first parameter */ 1804 tokenlen = next_offset - offset; 1805 fmtp_item = proto_tree_add_item(sdp_media_attribute_tree, 1806 hf_media_format_specific_parameter, tvb, 1807 offset, tokenlen, ENC_UTF_8|ENC_NA); 1808 1809 fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp); 1810 1811 decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen, 1812 transport_info->encoding_name[media_format]); 1813 1814 /* Move offset past "; " and onto firts char */ 1815 offset = next_offset + 1; 1816 } 1817 } 1818 break; 1819 case SDP_PATH: 1820 /* msrp attributes that contain address needed for conversation */ 1821 /* RFC 4975 1822 * path = path-label ":" path-list 1823 * path-label = "path" 1824 * path-list= MSRP-URI *(SP MSRP-URI) 1825 * MSRP-URI = msrp-scheme "://" authority 1826 * ["/" session-id] ";" transport *( ";" URI-parameter) 1827 * ; authority as defined in RFC3986 1828 * 1829 * msrp-scheme = "msrp" / "msrps" 1830 * RFC 3986 1831 * The authority component is preceded by a double slash ("//") and is terminated by 1832 * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by 1833 * the end of the URI. 1834 */ 1835 1836 /* Check for "msrp://" */ 1837 if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle && 1838 media_desc && media_desc->proto == SDP_PROTO_MSRP) { 1839 int address_offset, port_offset, port_end_offset; 1840 1841 /* Address starts here */ 1842 address_offset = offset + (int)strlen(msrp_res); 1843 1844 /* Port is after next ':' */ 1845 port_offset = tvb_find_guint8(tvb, address_offset, -1, ':'); 1846 /* Check if port is present if not skipp */ 1847 if (port_offset!= -1) { 1848 /* Port ends with '/' */ 1849 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/'); 1850 if (port_end_offset == -1) { 1851 /* No "/" look for the ";" */ 1852 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';'); 1853 } 1854 /* Attempt to convert address */ 1855 guint32 msrp_ipaddr; 1856 guint16 msrp_port_number; 1857 if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA), 1858 &msrp_ipaddr)) { 1859 /* Get port number */ 1860 if (ws_strtou16(tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1, 1861 port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) { 1862 /* Port and address are usable, store for later use in 1863 * complete_descriptions (overrides the "c=" address). */ 1864 alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr); 1865 media_desc->media_attr.msrp.port_number = msrp_port_number; 1866 } 1867 } 1868 } 1869 } 1870 break; 1871 case SDP_H248_ITEM: 1872 /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/ 1873 if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) { 1874 /* A.5.1.3 H.223 Logical channel parameters 1875 * This property indicates the H.245 1876 * H223LogicalChannelsParameters structure encoded by applying the PER specified in 1877 * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined 1878 * in ITU-T Rec. H.248.15 is used. 1879 */ 1880 gint len; 1881 asn1_ctx_t actx; 1882 1883 len = (gint)strlen(attribute_value); 1884 h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value); 1885 /* arbitrary maximum length */ 1886 /* should go through a handle, however, the two h245 entry 1887 points are different, one is over tpkt and the other is raw 1888 */ 1889 if (h245_tvb) { 1890 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo); 1891 dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, 1892 sdp_media_attribute_tree, 1893 hf_SDPh223LogicalChannelParameters); 1894 } 1895 } 1896 break; 1897 case SDP_CRYPTO: 1898 /* https://tools.ietf.org/html/rfc4568 1899 * 9.1. Generic "Crypto" Attribute Grammar 1900 * 1901 * The ABNF grammar for the crypto attribute is defined below: 1902 * 1903 * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params 1904 * *(1*WSP session-param) 1905 * 1906 * tag = 1*9DIGIT 1907 * crypto-suite = 1*(ALPHA / DIGIT / "_") 1908 * 1909 * key-params = key-param *(";" key-param) 1910 * key-param = key-method ":" key-info 1911 * key-method = "inline" / key-method-ext 1912 * key-method-ext = 1*(ALPHA / DIGIT / "_") 1913 * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars 1914 * ; except semi-colon 1915 * session-param = 1*(VCHAR) ; visible (printing) characters 1916 * 1917 * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234]. 1918 * 1919 */ 1920 1921 /* We are at the first colon */ 1922 /* tag */ 1923 tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset); 1924 if (tokenlen == 0) 1925 return; 1926 crypto_tag_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, 1927 tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag); 1928 pi = proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen, 1929 crypto_tag); 1930 if (!crypto_tag_valid) 1931 expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag); 1932 offset = next_offset + 1; 1933 1934 /* crypto-suite */ 1935 tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset); 1936 if (tokenlen == 0) 1937 return; 1938 parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite, 1939 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 1940 if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) { 1941 1942 /* XXX This may only work in simple cases */ 1943 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { 1944 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; 1945 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; 1946 /* number of octets used for the Auth Tag in the RTP payload */ 1947 transport_info->auth_tag_len = 10; 1948 } 1949 master_key_length = 16; /* 128 bits = 16 octets */ 1950 master_salt_length = 14; /* 112 bits = 14 octets */ 1951 } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) { 1952 /* XXX This may only work in simple cases */ 1953 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { 1954 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM; 1955 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; 1956 /* number of octets used for the Auth Tag in the RTP payload */ 1957 transport_info->auth_tag_len = 4; 1958 } 1959 master_key_length = 16; /* 128 bits = 16 octets */ 1960 master_salt_length = 14; /* 112 bits = 14 octets */ 1961 } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) { 1962 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) { 1963 /* XXX This may only work in simple cases */ 1964 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8; 1965 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1; 1966 /* number of octets used for the Auth Tag in the RTP payload */ 1967 transport_info->auth_tag_len = 10; 1968 } 1969 master_key_length = 16; /* 128 bits = 16 octets */ 1970 master_salt_length = 14; /* 112 bits = 14 octets */ 1971 } 1972 offset = next_offset + 1; 1973 1974 /* key-params */ 1975 while (has_more_pars == TRUE) { 1976 int param_end_offset; 1977 tvbuff_t *key_salt_tvb; 1978 gchar *data_p = NULL; 1979 1980 param_end_offset = tvb_find_guint8(tvb, offset, -1, ';'); 1981 if (param_end_offset == -1) { 1982 has_more_pars = FALSE; 1983 param_end_offset = tvb_captured_length(tvb); 1984 } 1985 /* key-method or key-method-ext */ 1986 next_offset = tvb_find_guint8(tvb, offset, -1, ':'); 1987 if (next_offset == -1) { 1988 expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param); 1989 break; 1990 } 1991 1992 if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) { 1993 parameter_tree = proto_tree_add_subtree(sdp_media_attribute_tree, tvb, offset, 1994 param_end_offset-offset, ett_sdp_crypto_key_parameters, NULL, "Key parameters"); 1995 /* XXX only for SRTP? */ 1996 /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */ 1997 offset = next_offset +1; 1998 next_offset = tvb_find_guint8(tvb, offset, -1, '|'); 1999 if (next_offset == -1) { 2000 tokenlen = param_end_offset - offset; 2001 } else { 2002 tokenlen = next_offset - offset; 2003 } 2004 data_p = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 2005 key_salt_tvb = base64_to_tvb(tvb, data_p); 2006 add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb"); 2007 if (master_key_length != 0) { 2008 proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA); 2009 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key, 2010 key_salt_tvb, 0, master_key_length, ENC_NA); 2011 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt, 2012 key_salt_tvb, master_key_length, master_salt_length, ENC_NA); 2013 } else { 2014 proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA); 2015 } 2016 2017 /* ["|" lifetime] ["|" mki] are optional */ 2018 if (next_offset != -1) { 2019 offset = next_offset + 1; 2020 next_offset = tvb_find_guint8(tvb, offset, -1, '|'); 2021 if (next_offset == -1) { 2022 if (next_offset < param_end_offset){ 2023 next_offset = param_end_offset; 2024 } 2025 } 2026 if (next_offset != -1) { 2027 /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */ 2028 tokenlen = next_offset - offset; 2029 proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime, 2030 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 2031 offset = next_offset + 1; 2032 } 2033 /* mki = mki-value ":" mki-length 2034 * 2035 * mki-value = 1*DIGIT 2036 */ 2037 if (offset>param_end_offset) { 2038 next_offset = -1; 2039 } else { 2040 next_offset = tvb_find_guint8(tvb, offset, -1, ':'); 2041 } 2042 if (next_offset != -1) { 2043 tokenlen = next_offset - offset; 2044 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 2045 offset = next_offset + 1; 2046 2047 /* mki-length = 1*3DIGIT ; range 1..128. */ 2048 next_offset = param_end_offset; 2049 tokenlen = next_offset - offset; 2050 2051 /* This will not work if more than one parameter */ 2052 /* number of octets used for the MKI in the RTP payload */ 2053 mki_len_valid = ws_strtou32(tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, 2054 ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len); 2055 pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length, 2056 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA); 2057 if (!mki_len_valid) 2058 expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length); 2059 } 2060 } 2061 offset = param_end_offset; 2062 } else { 2063 break; 2064 } 2065 } 2066 break; 2067 case SDP_CANDIDATE: 2068 dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree, pinfo, tvb, offset); 2069 break; 2070 case SDP_ED137_TYPE: 2071 /* Remember the value and add it to tree */ 2072 sdp_data->ed137_type = attribute_value; 2073 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2074 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2075 break; 2076 case SDP_ED137_TXRXMODE: 2077 /* Remember the value and add it to tree */ 2078 sdp_data->ed137_txrxmode = attribute_value; 2079 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2080 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2081 break; 2082 case SDP_ED137_FID: 2083 /* Remember the value and add it to tree */ 2084 sdp_data->ed137_fid = attribute_value; 2085 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2086 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2087 break; 2088 case SDP_RTCP : 2089 if (media_desc) { 2090 if (!ws_strtou16(attribute_value, NULL, &media_desc->control_port)) 2091 media_desc->control_port = 0; /* Just use default, if not legal port */ 2092 } 2093 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2094 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2095 break; 2096 case SDP_RTCP_MUX : 2097 if (media_desc) { 2098 media_desc->control_port = media_desc->media_port; 2099 } 2100 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2101 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2102 break; 2103 default: 2104 /* No special treatment for values of this attribute type, just add as one item. */ 2105 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value, 2106 tvb, offset, -1, ENC_UTF_8|ENC_NA); 2107 break; 2108 } 2109 } 2110 2111 static void 2112 call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length, 2113 transport_info_t *transport_info, 2114 session_info_t *session_info, 2115 media_description_t *media_desc, 2116 sdp_data_t *sdp_data) 2117 { 2118 if (hf == hf_owner) { 2119 dissect_sdp_owner(tvb, ti); 2120 } else if (hf == hf_connection_info) { 2121 dissect_sdp_connection_info(pinfo, tvb, ti, session_info, media_desc); 2122 } else if (hf == hf_bandwidth) { 2123 dissect_sdp_bandwidth(tvb, ti); 2124 } else if (hf == hf_time) { 2125 dissect_sdp_time(tvb, ti); 2126 } else if (hf == hf_repeat_time) { 2127 dissect_sdp_repeat_time(tvb, ti); 2128 } else if (hf == hf_timezone) { 2129 dissect_sdp_timezone(tvb, ti); 2130 } else if (hf == hf_encryption_key) { 2131 dissect_sdp_encryption_key(tvb, ti); 2132 } else if (hf == hf_session_attribute) { 2133 dissect_sdp_session_attribute(tvb, pinfo, ti); 2134 } else if (hf == hf_media) { 2135 dissect_sdp_media(tvb, pinfo, ti, media_desc); 2136 } else if (hf == hf_media_attribute) { 2137 dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, session_info, media_desc, sdp_data); 2138 } 2139 } 2140 2141 /** 2142 * Post-processes the media descriptions after parsing it from the tvb. This 2143 * performs processing that can only be done when the full media description is 2144 * parsed (since otherwise the order of attributes could influence the result). 2145 * Must be called before applying the SDP with apply_sdp_transport. 2146 * It will remove media streams when the port number in the answer is zero. 2147 * 2148 * If the currently processed SDP is an Answer to a known previous Offer, then 2149 * answer_offset is non-zero. 2150 */ 2151 static void 2152 complete_descriptions(transport_info_t *transport_info, guint answer_offset) 2153 { 2154 guint media_count = wmem_array_get_count(transport_info->media_descriptions); 2155 media_description_t *media_descs = (media_description_t *)wmem_array_get_raw(transport_info->media_descriptions); 2156 media_description_t *bundle_media_desc = NULL; 2157 2158 DPRINT(("complete_descriptions called with answer_offset=%d media_count=%d", 2159 answer_offset, media_count)); 2160 2161 for (guint i = answer_offset; i < media_count && !bundle_media_desc; i++) { 2162 for (guint j = i+1; j < media_count && !bundle_media_desc; j++) { 2163 if (media_descs[i].media_port == media_descs[j].media_port) 2164 bundle_media_desc = &media_descs[i]; 2165 } 2166 } 2167 2168 if (bundle_media_desc) { 2169 /* We have "bundling" of media, so now combine all the media bit masks 2170 and merge the rtp_dyn_payload so that the first media description 2171 has all the data for every media desciption. */ 2172 for (guint i = answer_offset; i < media_count; i++) { 2173 media_description_t *media_desc = &media_descs[i]; 2174 2175 if (bundle_media_desc->media_port == media_desc->media_port) { 2176 media_desc->bundled = TRUE; 2177 2178 if (media_desc != bundle_media_desc) { 2179 bundle_media_desc->media_types |= media_desc->media_types; 2180 for (guint pt = 0; pt < 128; ++pt) { 2181 const char * encoding_name; 2182 int sample_rate; 2183 if (rtp_dyn_payload_get_full(media_desc->media.rtp_dyn_payload, 2184 pt, &encoding_name, &sample_rate)) 2185 rtp_dyn_payload_insert(bundle_media_desc->media.rtp_dyn_payload, 2186 pt, encoding_name, sample_rate); 2187 } 2188 } 2189 } 2190 } 2191 } 2192 2193 for (guint i = answer_offset; i < media_count; i++) { 2194 media_description_t *media_desc = &media_descs[i]; 2195 2196 if (media_desc->control_port == 0) 2197 media_desc->control_port = media_desc->media_port + 1; 2198 2199 if (media_desc->control_port == 0) 2200 media_desc->control_port = media_desc->media_port + 1; 2201 2202 /* If this is an answer to a previous offer... */ 2203 if (answer_offset > 0) { 2204 /* A zero port removes the media stream (RFC 3264, Section 8.2) */ 2205 if (media_desc->media_port == 0) { 2206 DPRINT(("disabling media_port=%d, for index=%d", 2207 media_descs[i - answer_offset].media_port, 2208 i - answer_offset)); 2209 media_descs[i - answer_offset].media_port = 0; 2210 } 2211 } 2212 2213 /* MSRP uses addresses discovered in attribute 2214 rather than connection information of media session line */ 2215 if (media_desc->proto == SDP_PROTO_MSRP && msrp_handle && 2216 media_desc->media_attr.msrp.ipaddr.type != AT_NONE) { 2217 /* clear old address and set new address and port. */ 2218 free_address_wmem(wmem_file_scope(), &media_desc->conn_addr); 2219 copy_address_shallow(&media_desc->conn_addr, 2220 &media_desc->media_attr.msrp.ipaddr); 2221 media_desc->media_port = media_desc->media_attr.msrp.port_number; 2222 } 2223 } 2224 } 2225 2226 /** 2227 * Given is a structure containing the parsed result from the SDP (including 2228 * protocol type (RTP, SRTP, T38, etc.), media info (payload type, etc.) and 2229 * connection info (address, port). Register the addresss+port such that the 2230 * protocol will be invoked for this tuple with the media information. 2231 * 2232 * For use with SDP using the Offer/Answer model (such as SIP with INVITE and 2233 * 200 OK). 2234 * XXX what about RTSP where the SDP merely provides media info, without 2235 * actually establishing connections (Bug 5208). 2236 * 2237 * The passed transport information is modified: 'set_rtp' is set when the media 2238 * is assigned to a conversation. Note that the unassigned media (payload types) 2239 * are not freed, this is the responsibility of the caller. 2240 */ 2241 static void 2242 apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int request_frame, sdp_setup_info_t *setup_info) 2243 { 2244 int establish_frame = 0; 2245 2246 struct srtp_info *srtp_info = NULL; 2247 2248 if (!global_sdp_establish_conversation) { 2249 /* Do not register with other dissectors when this pref is disabled. */ 2250 return; 2251 } 2252 2253 /* If no request_frame number has been found use this frame's number */ 2254 if (request_frame == 0) { 2255 establish_frame = pinfo->num; 2256 } else { 2257 establish_frame = request_frame; 2258 } 2259 2260 gboolean bundled_media_set = FALSE; 2261 2262 for (guint i = 0; i < wmem_array_get_count(transport_info->media_descriptions); i++) { 2263 media_description_t *media_desc = 2264 (media_description_t *)wmem_array_index(transport_info->media_descriptions, i); 2265 guint32 current_rtp_port = 0; 2266 2267 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */ 2268 if ((media_desc->media_port != 0) && 2269 !media_desc->media.set_rtp && 2270 (media_desc->proto == SDP_PROTO_RTP || 2271 media_desc->proto == SDP_PROTO_SRTP) && 2272 (media_desc->conn_addr.type == AT_IPv4 || 2273 media_desc->conn_addr.type == AT_IPv6)) { 2274 2275 media_desc->media.set_rtp = TRUE; 2276 2277 if (media_desc->bundled) { 2278 if (bundled_media_set) 2279 continue; 2280 bundled_media_set = TRUE; 2281 } 2282 2283 if (media_desc->proto == SDP_PROTO_SRTP) { 2284 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info); 2285 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) { 2286 srtp_info->encryption_algorithm = transport_info->encryption_algorithm; 2287 srtp_info->auth_algorithm = transport_info->auth_algorithm; 2288 srtp_info->mki_len = transport_info->mki_len; 2289 srtp_info->auth_tag_len = transport_info->auth_tag_len; 2290 2291 } 2292 DPRINT(("calling srtp_add_address, channel=%d, media_port=%d", 2293 i, media_desc->media_port)); 2294 DINDENT(); 2295 /* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number, 2296 because that's where the RTP flow started, and thus conversation needs to check against */ 2297 srtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame, 2298 media_desc->media_types, 2299 media_desc->media.rtp_dyn_payload, srtp_info, 2300 setup_info); 2301 DENDENT(); 2302 } else { 2303 DPRINT(("calling rtp_add_address, channel=%d, media_port=%d", 2304 i, media_desc->media_port)); 2305 DINDENT(); 2306 srtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame, 2307 media_desc->media_types, 2308 media_desc->media.rtp_dyn_payload, NULL, setup_info); 2309 DENDENT(); 2310 } 2311 /* SPRT might use the same port... */ 2312 current_rtp_port = media_desc->media_port; 2313 2314 if (rtcp_handle && media_desc->media_port != media_desc->control_port) { 2315 if (media_desc->proto == SDP_PROTO_SRTP) { 2316 DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d", 2317 i, media_desc->control_port)); 2318 DINDENT(); 2319 srtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame, srtp_info); 2320 DENDENT(); 2321 } else { 2322 DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d", 2323 i, media_desc->control_port)); 2324 DINDENT(); 2325 rtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame); 2326 DENDENT(); 2327 } 2328 } 2329 } 2330 2331 /* add SPRT conversation */ 2332 if (media_desc->proto == SDP_PROTO_SPRT && 2333 (media_desc->conn_addr.type == AT_IPv4 || 2334 media_desc->conn_addr.type == AT_IPv6) && 2335 (sprt_handle)) { 2336 2337 if (media_desc->media_port == 0 && current_rtp_port) { 2338 sprt_add_address(pinfo, &media_desc->conn_addr, current_rtp_port, 2339 0, "SDP", pinfo->num); /* will use same port as RTP */ 2340 } else { 2341 sprt_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", pinfo->num); 2342 } 2343 } 2344 2345 /* Add t38 conversation, if available and only if no rtp */ 2346 if ((media_desc->media_port != 0) && 2347 !media_desc->media.set_rtp && 2348 media_desc->proto == SDP_PROTO_T38 && 2349 media_desc->conn_addr.type == AT_IPv4) { 2350 t38_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", pinfo->num); 2351 } 2352 2353 /* Add MSRP conversation. Uses addresses discovered in attribute 2354 rather than connection information of media session line 2355 (already handled in media conversion) */ 2356 if (media_desc->proto == SDP_PROTO_MSRP && msrp_handle) { 2357 msrp_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, "SDP", pinfo->num); 2358 } 2359 2360 } /* end of loop through all media descriptions. */ 2361 } 2362 2363 void 2364 setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type, 2365 int request_frame, const gboolean delay, sdp_setup_info_t *setup_info) 2366 { 2367 gint offset = 0, next_offset, n; 2368 int linelen; 2369 gboolean in_media_description = FALSE; 2370 guchar type, delim; 2371 const int tokenoffset = 2; 2372 int hf = -1; 2373 gint start_transport_info_count = 0; 2374 transport_info_t* transport_info = NULL; 2375 media_description_t *media_desc = NULL; 2376 session_info_t session_info; 2377 sdp_data_t sdp_data; 2378 2379 DPRINT2(("-------------------- setup_sdp_transport -------------------")); 2380 2381 /* Only do this once during first pass */ 2382 if (pinfo->fd->visited) { 2383 DPRINT(("already visited")); 2384 return; 2385 } 2386 2387 memset(&sdp_data, 0, sizeof(sdp_data)); 2388 2389 if (request_frame != 0) 2390 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame ); 2391 if (transport_info == NULL) { 2392 transport_info = wmem_new0(wmem_file_scope(), transport_info_t); 2393 transport_info->media_descriptions = wmem_array_new(wmem_file_scope(), sizeof(media_description_t)); 2394 2395 for (n = 0; n < SDP_NO_OF_PT; n++) { 2396 /* String is file scope allocated because transport_info is connection related */ 2397 transport_info->encoding_name[n] = wmem_strdup(wmem_file_scope(), UNKNOWN_ENCODING); 2398 } 2399 2400 if (request_frame != 0) 2401 wmem_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info); 2402 } 2403 #ifdef DEBUG_CONVERSATION 2404 else { 2405 DPRINT(("found previous transport_info:")); 2406 sdp_dump_transport_info(pinfo, transport_info); 2407 } 2408 #endif 2409 2410 if (exchange_type != SDP_EXCHANGE_OFFER) 2411 wmem_tree_insert32(sdp_transport_rsps, pinfo->num, (void *)transport_info); 2412 2413 /* Offer has already been answered or rejected and hash tables freed, so 2414 * don't try to add to it 2415 * XXX - Need to support "modified offers" */ 2416 if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) || 2417 (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT)) 2418 return; 2419 2420 /* Initialize the session description before parsing the media descriptions. */ 2421 memset(&session_info, 0, sizeof(session_info_t)); 2422 session_info.rtp_dyn_payload = rtp_dyn_payload_new(); 2423 2424 /* Remember where the answer should start (it will be zero if there was no 2425 * previous offer with media descriptions). */ 2426 start_transport_info_count = wmem_array_get_count(transport_info->media_descriptions); 2427 2428 DPRINT(("start_transport_info_count=%d", start_transport_info_count)); 2429 2430 /* 2431 * Show the SDP message a line at a time. 2432 */ 2433 while (tvb_offset_exists(tvb, offset)) { 2434 /* 2435 * Find the end of the line. 2436 */ 2437 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset); 2438 2439 /* 2440 * Line must contain at least e.g. "v=". 2441 */ 2442 if (linelen < 2) 2443 break; 2444 2445 type = tvb_get_guint8(tvb, offset); 2446 delim = tvb_get_guint8(tvb, offset + 1); 2447 if (delim != '=') { 2448 offset = next_offset; 2449 continue; 2450 } 2451 2452 /* 2453 * Attributes. Only care about ones that affect the transport. Ignore others. 2454 */ 2455 switch (type) { 2456 case 'c': 2457 hf = hf_connection_info; 2458 break; 2459 case 'm': 2460 hf = hf_media; 2461 2462 /* Try to create a new media description (it will return NULL if 2463 * there are too many). */ 2464 media_desc = sdp_new_media_description(transport_info->media_descriptions, &session_info); 2465 2466 in_media_description = TRUE; 2467 DPRINT(("in media description, media descriptions count=%d", 2468 wmem_array_get_count(transport_info->media_descriptions))); 2469 break; 2470 case 'a': 2471 if (in_media_description) { 2472 hf = hf_media_attribute; 2473 } else { 2474 hf = hf_session_attribute; 2475 } 2476 break; 2477 default: 2478 hf = hf_unknown; 2479 break; 2480 } 2481 2482 if (hf != hf_unknown) 2483 { 2484 DINDENT(); 2485 call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset, 2486 linelen - tokenoffset), 2487 pinfo, 2488 hf, NULL, linelen-tokenoffset, 2489 transport_info, 2490 in_media_description ? NULL : &session_info, 2491 media_desc, 2492 &sdp_data); 2493 DENDENT(); 2494 } 2495 2496 offset = next_offset; 2497 } 2498 2499 /* Done parsing media description, no more need for the session-level details. */ 2500 rtp_dyn_payload_free(session_info.rtp_dyn_payload); 2501 session_info.rtp_dyn_payload = NULL; 2502 2503 /* Post-processing, close media streams, apply attributes, etc. */ 2504 complete_descriptions(transport_info, start_transport_info_count); 2505 2506 #ifdef DEBUG_CONVERSATION 2507 sdp_dump_transport_info(pinfo, transport_info); 2508 #endif 2509 2510 /* We have a successful negotiation, apply data to their respective protocols */ 2511 if (!delay || ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) && 2512 (transport_info->sdp_status == SDP_EXCHANGE_OFFER))) { 2513 /* Accepting answer to a previous offer (or delay pref is false). */ 2514 apply_sdp_transport(pinfo, transport_info, request_frame, setup_info); 2515 2516 /* Free all media hash tables that were not assigned to a conversation 2517 * ('set_rtp' is false) */ 2518 clean_unused_media_descriptions(transport_info->media_descriptions); 2519 2520 transport_info->sdp_status = exchange_type; 2521 2522 } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) && 2523 (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)) { 2524 /* Rejecting answer */ 2525 clean_unused_media_descriptions(transport_info->media_descriptions); 2526 2527 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT; 2528 } /* else attempt to accept an unknown offer. */ 2529 } 2530 2531 void setup_sdp_transport_resend(int current_frame, int request_frame) 2532 { 2533 transport_info_t* transport_info = NULL; 2534 2535 if (request_frame != 0) { 2536 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame ); 2537 if (transport_info != NULL) { 2538 wmem_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info); 2539 } 2540 } 2541 } 2542 2543 static int 2544 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) 2545 { 2546 proto_tree *sdp_tree; 2547 proto_item *ti, *sub_ti; 2548 gint offset = 0, next_offset, n; 2549 int linelen; 2550 gboolean in_media_description; 2551 guchar type, delim; 2552 int datalen, tokenoffset, hf = -1; 2553 char *string; 2554 sdp_data_t sdp_data; 2555 2556 transport_info_t local_transport_info; 2557 transport_info_t* transport_info = NULL; 2558 media_description_t *media_desc = NULL; 2559 session_info_t session_info; 2560 sdp_packet_info *sdp_pi; 2561 sdp_setup_info_t *setup_info = NULL; 2562 2563 if (data) { 2564 http_message_info_t *message_info = (http_message_info_t *)data; 2565 if (message_info->type == SIP_DATA) { 2566 setup_info = (sdp_setup_info_t *)message_info->data; 2567 } 2568 } 2569 2570 DPRINT2(("----------------------- dissect_sdp ------------------------")); 2571 2572 /* Initialise packet info for passing to tap */ 2573 sdp_pi = wmem_new(pinfo->pool, sdp_packet_info); 2574 sdp_pi->summary_str[0] = '\0'; 2575 2576 memset(&sdp_data, 0, sizeof(sdp_data)); 2577 2578 if (!pinfo->fd->visited) { 2579 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->num ); 2580 2581 if (transport_info == NULL) { 2582 /* Can't find it in the requests, make sure it's not a response */ 2583 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_rsps, pinfo->num ); 2584 } 2585 } 2586 2587 if (transport_info == NULL) { 2588 transport_info = &local_transport_info; 2589 } 2590 #ifdef DEBUG_CONVERSATION 2591 else { 2592 DPRINT(("found previous transport_info:")); 2593 sdp_dump_transport_info(pinfo, transport_info); 2594 } 2595 #endif 2596 2597 /* Initialize local transport info */ 2598 memset(&local_transport_info, 0, sizeof(local_transport_info)); 2599 /* Note: packet-scoped since it is only needed while parsing this packet. */ 2600 local_transport_info.media_descriptions = wmem_array_new(pinfo->pool, sizeof(media_description_t)); 2601 2602 for (n = 0; n < SDP_NO_OF_PT; n++) { 2603 local_transport_info.encoding_name[n] = wmem_strdup(pinfo->pool, UNKNOWN_ENCODING); 2604 } 2605 2606 /* 2607 * As RFC 2327 says, "SDP is purely a format for session 2608 * description - it does not incorporate a transport protocol, 2609 * and is intended to use different transport protocols as 2610 * appropriate including the Session Announcement Protocol, 2611 * Session Initiation Protocol, Real-Time Streaming Protocol, 2612 * electronic mail using the MIME extensions, and the 2613 * Hypertext Transport Protocol." 2614 * 2615 * We therefore don't set the protocol or info columns; 2616 * instead, we append to them, so that we don't erase 2617 * what the protocol inside which the SDP stuff resides 2618 * put there. 2619 */ 2620 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP"); 2621 2622 ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA); 2623 sdp_tree = proto_item_add_subtree(ti, ett_sdp); 2624 2625 /* 2626 * Show the SDP message a line at a time. 2627 */ 2628 in_media_description = FALSE; 2629 2630 /* Initialize the session description before parsing the media level. */ 2631 memset(&session_info, 0, sizeof(session_info_t)); 2632 session_info.rtp_dyn_payload = rtp_dyn_payload_new(); 2633 2634 while (tvb_offset_exists(tvb, offset)) { 2635 /* 2636 * Find the end of the line. 2637 */ 2638 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset); 2639 2640 /* 2641 * Line must contain at least e.g. "v=". 2642 */ 2643 if (linelen < 2) 2644 break; 2645 2646 type = tvb_get_guint8(tvb, offset); 2647 delim = tvb_get_guint8(tvb, offset + 1); 2648 if (delim != '=') { 2649 proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_UTF_8|ENC_NA); 2650 expert_add_info(pinfo, ti2, &ei_sdp_invalid_line_equal); 2651 offset = next_offset; 2652 continue; 2653 } 2654 2655 /* 2656 * Attributes. 2657 */ 2658 switch (type) { 2659 case 'v': 2660 hf = hf_protocol_version; 2661 break; 2662 case 'o': 2663 hf = hf_owner; 2664 break; 2665 case 's': 2666 hf = hf_session_name; 2667 break; 2668 case 'i': 2669 if (in_media_description) { 2670 hf = hf_media_title; 2671 } else { 2672 hf = hf_session_info; 2673 } 2674 break; 2675 case 'u': 2676 hf = hf_uri; 2677 break; 2678 case 'e': 2679 hf = hf_email; 2680 break; 2681 case 'p': 2682 hf = hf_phone; 2683 break; 2684 case 'c': 2685 hf = hf_connection_info; 2686 break; 2687 case 'b': 2688 hf = hf_bandwidth; 2689 break; 2690 case 't': 2691 hf = hf_time; 2692 break; 2693 case 'r': 2694 hf = hf_repeat_time; 2695 break; 2696 case 'm': 2697 hf = hf_media; 2698 2699 /* Try to create a new media description (it will return NULL if 2700 * there are too many). Pass local_transport_info since we do 2701 * not want to modify the transport_info that was created by 2702 * setup_sdp_transport. */ 2703 media_desc = sdp_new_media_description(local_transport_info.media_descriptions, &session_info); 2704 2705 in_media_description = TRUE; 2706 break; 2707 case 'k': 2708 hf = hf_encryption_key; 2709 break; 2710 case 'a': 2711 if (in_media_description) { 2712 hf = hf_media_attribute; 2713 } else { 2714 hf = hf_session_attribute; 2715 } 2716 break; 2717 case 'z': 2718 hf = hf_timezone; 2719 break; 2720 default: 2721 hf = hf_unknown; 2722 break; 2723 } 2724 tokenoffset = 2; 2725 if (hf == hf_unknown) 2726 tokenoffset = 0; 2727 string = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset + tokenoffset, 2728 linelen - tokenoffset, ENC_ASCII); 2729 sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen, 2730 string); 2731 2732 call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset, 2733 linelen - tokenoffset), 2734 pinfo, 2735 hf, sub_ti, linelen-tokenoffset, 2736 &local_transport_info, 2737 in_media_description ? NULL : &session_info, 2738 in_media_description ? media_desc : NULL, 2739 &sdp_data); 2740 2741 offset = next_offset; 2742 } 2743 2744 if (NULL != sdp_data.ed137_fid) { 2745 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_fid); 2746 (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_fid, 50); 2747 } 2748 if (NULL != sdp_data.ed137_txrxmode) { 2749 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_txrxmode); 2750 if (strlen(sdp_pi->summary_str)) 2751 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2752 (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_txrxmode, 50); 2753 } 2754 if (NULL != sdp_data.ed137_type) { 2755 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_type); 2756 if (strlen(sdp_pi->summary_str)) 2757 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2758 (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_type, 50); 2759 } 2760 2761 /* Done parsing media description, no more need for the session-level details. */ 2762 rtp_dyn_payload_free(session_info.rtp_dyn_payload); 2763 session_info.rtp_dyn_payload = NULL; 2764 2765 /* Post-processing, close media streams, apply attributes, etc. */ 2766 if (transport_info == &local_transport_info) { 2767 DPRINT(("no previous transport_info saved, calling complete_descriptions()")); 2768 DINDENT(); 2769 complete_descriptions(transport_info, 0); 2770 DENDENT(); 2771 #ifdef DEBUG_CONVERSATION 2772 sdp_dump_transport_info(pinfo, transport_info); 2773 #endif 2774 } 2775 #ifdef DEBUG_CONVERSATION 2776 else { 2777 DPRINT(("not overwriting previous transport_info, local_transport_info contents:")); 2778 sdp_dump_transport_info(pinfo, &local_transport_info); 2779 } 2780 #endif 2781 2782 /* For messages not part of the Offer/Answer model, assume that the SDP is 2783 * immediately effective (apply it now). */ 2784 if ((!pinfo->fd->visited) && (transport_info == &local_transport_info)) { 2785 /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper 2786 * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers 2787 * use setup_sdp_transport(), this should be removed 2788 * Note that transport_info contains the SDP info from this frame (and 2789 * not an earlier request (transport_info == &local_transport_info). 2790 * Use 0 as request_frame since there is no (known) request. 2791 */ 2792 apply_sdp_transport(pinfo, transport_info, 0, setup_info); 2793 } 2794 2795 /* Add information to the VoIP Calls dialog. */ 2796 for (guint i = 0; i < wmem_array_get_count(local_transport_info.media_descriptions); i++) 2797 { 2798 media_desc = (media_description_t *)wmem_array_index(local_transport_info.media_descriptions, i); 2799 2800 if (media_desc->media_port != 0) { 2801 /* Create the RTP summary str for the Voip Call analysis. 2802 * XXX - Currently this is based only on the current packet 2803 */ 2804 for (int j = 0; j < media_desc->media.pt_count; j++) 2805 { 2806 DPRINT(("in for-loop for voip call analysis setting for media #%d, pt=%d", 2807 j, media_desc->media. pt[j])); 2808 /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */ 2809 if ((media_desc->media.pt[j] >= 96) && (media_desc->media.pt[j] <= 127)) { 2810 const gchar *payload_type_str = rtp_dyn_payload_get_name( 2811 media_desc->media.rtp_dyn_payload, 2812 media_desc->media.pt[j]); 2813 if (payload_type_str) { 2814 if (strlen(sdp_pi->summary_str)) 2815 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2816 (void) g_strlcat(sdp_pi->summary_str, payload_type_str, 50); 2817 } else { 2818 char num_pt[10]; 2819 g_snprintf(num_pt, 10, "%u", media_desc->media.pt[j]); 2820 if (strlen(sdp_pi->summary_str)) 2821 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2822 (void) g_strlcat(sdp_pi->summary_str, num_pt, 50); 2823 } 2824 } else { 2825 if (strlen(sdp_pi->summary_str)) 2826 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2827 (void) g_strlcat(sdp_pi->summary_str, 2828 val_to_str_ext(media_desc->media.pt[j], &rtp_payload_type_short_vals_ext, "%u"), 2829 50); 2830 } 2831 } 2832 } 2833 2834 /* Create the T38 summary str for the Voip Call analysis 2835 * XXX - Currently this is based only on the current packet 2836 */ 2837 if ((media_desc->media_port != 0) && media_desc->proto == SDP_PROTO_T38) { 2838 if (strlen(sdp_pi->summary_str)) 2839 (void) g_strlcat(sdp_pi->summary_str, " ", 50); 2840 (void) g_strlcat(sdp_pi->summary_str, "t38", 50); 2841 } 2842 } 2843 2844 /* Free all media hash tables that were not assigned to a conversation 2845 * ('set_rtp' is false) */ 2846 if (transport_info == &local_transport_info) { 2847 clean_unused_media_descriptions(transport_info->media_descriptions); 2848 } 2849 2850 datalen = tvb_captured_length_remaining(tvb, offset); 2851 if (datalen > 0) { 2852 proto_tree_add_item(sdp_tree, hf_sdp_data, tvb, offset, datalen, ENC_NA); 2853 } 2854 /* Add Trace info */ 2855 conversation_t *sdp_conv; 2856 wmem_array_t *sdp_conv_info_list; 2857 sdp_conv = find_conversation_pinfo(pinfo, 0); 2858 if (sdp_conv) { 2859 guint i; 2860 sdp_setup_info_t *stored_setup_info; 2861 proto_item *item; 2862 sdp_conv_info_list = (wmem_array_t *)conversation_get_proto_data(sdp_conv, proto_sdp); 2863 if(sdp_conv_info_list){ 2864 for (i = 0; i < wmem_array_get_count(sdp_conv_info_list); i++) { 2865 stored_setup_info = (sdp_setup_info_t *)wmem_array_index(sdp_conv_info_list, i); 2866 if (stored_setup_info->hf_id) { 2867 if (stored_setup_info->hf_type == SDP_TRACE_ID_HF_TYPE_STR) { 2868 item = proto_tree_add_string(sdp_tree, stored_setup_info->hf_id, tvb, 0, 0, stored_setup_info->trace_id.str); 2869 proto_item_set_generated(item); 2870 if (stored_setup_info->add_hidden == TRUE) { 2871 proto_item_set_hidden(item); 2872 } 2873 } else if (stored_setup_info->hf_type == SDP_TRACE_ID_HF_TYPE_GUINT32) { 2874 item = proto_tree_add_uint(sdp_tree, stored_setup_info->hf_id, tvb, 0, 0, stored_setup_info->trace_id.num); 2875 proto_item_set_generated(item); 2876 if (stored_setup_info->add_hidden == TRUE) { 2877 proto_item_set_hidden(item); 2878 } 2879 } 2880 } 2881 } 2882 } 2883 } 2884 /* Report this packet to the tap */ 2885 tap_queue_packet(sdp_tap, pinfo, sdp_pi); 2886 2887 return tvb_captured_length(tvb); 2888 } 2889 2890 void 2891 proto_register_sdp(void) 2892 { 2893 static hf_register_info hf[] = { 2894 { &hf_protocol_version, 2895 { "Session Description Protocol Version (v)", "sdp.version", 2896 FT_STRING, BASE_NONE, NULL, 0x0, 2897 NULL, HFILL } 2898 }, 2899 { &hf_owner, 2900 { "Owner/Creator, Session Id (o)", 2901 "sdp.owner", FT_STRING, BASE_NONE, NULL, 2902 0x0, NULL, HFILL} 2903 }, 2904 { &hf_session_name, 2905 { "Session Name (s)", "sdp.session_name", 2906 FT_STRING, BASE_NONE, NULL, 0x0, 2907 NULL, HFILL } 2908 }, 2909 { &hf_session_info, 2910 { "Session Information (i)", "sdp.session_info", 2911 FT_STRING, BASE_NONE, NULL, 0x0, 2912 NULL, HFILL } 2913 }, 2914 { &hf_uri, 2915 { "URI of Description (u)", "sdp.uri", 2916 FT_STRING, BASE_NONE, NULL, 0x0, 2917 NULL, HFILL } 2918 }, 2919 { &hf_email, 2920 { "E-mail Address (e)", "sdp.email", 2921 FT_STRING, BASE_NONE, NULL, 0x0, 2922 "E-mail Address", HFILL } 2923 }, 2924 { &hf_phone, 2925 { "Phone Number (p)", "sdp.phone", 2926 FT_STRING, BASE_NONE, NULL, 0x0, 2927 NULL, HFILL } 2928 }, 2929 { &hf_connection_info, 2930 { "Connection Information (c)", "sdp.connection_info", 2931 FT_STRING, BASE_NONE, NULL, 0x0, 2932 NULL, HFILL } 2933 }, 2934 { &hf_bandwidth, 2935 { "Bandwidth Information (b)", "sdp.bandwidth", 2936 FT_STRING, BASE_NONE, NULL, 0x0, 2937 NULL, HFILL } 2938 }, 2939 { &hf_timezone, 2940 { "Time Zone Adjustments (z)", "sdp.timezone", 2941 FT_STRING, BASE_NONE, NULL, 0x0, 2942 NULL, HFILL } 2943 }, 2944 { &hf_encryption_key, 2945 { "Encryption Key (k)", "sdp.encryption_key", 2946 FT_STRING, BASE_NONE, NULL, 0x0, 2947 NULL, HFILL } 2948 }, 2949 { &hf_session_attribute, 2950 { "Session Attribute (a)", "sdp.session_attr", 2951 FT_STRING, BASE_NONE, NULL, 0x0, 2952 NULL, HFILL } 2953 }, 2954 { &hf_media_attribute, 2955 { "Media Attribute (a)", "sdp.media_attr", 2956 FT_STRING, BASE_NONE, NULL, 0x0, 2957 NULL, HFILL } 2958 }, 2959 { &hf_time, 2960 { "Time Description, active time (t)", 2961 "sdp.time", FT_STRING, BASE_NONE, NULL, 2962 0x0, NULL, HFILL } 2963 }, 2964 { &hf_repeat_time, 2965 { "Repeat Time (r)", "sdp.repeat_time", 2966 FT_STRING, BASE_NONE, NULL, 0x0, 2967 NULL, HFILL } 2968 }, 2969 { &hf_media, 2970 { "Media Description, name and address (m)", 2971 "sdp.media", FT_STRING, BASE_NONE, NULL, 2972 0x0, NULL, HFILL } 2973 }, 2974 { &hf_media_title, 2975 { "Media Title (i)", "sdp.media_title", 2976 FT_STRING, BASE_NONE, NULL, 0x0, 2977 "Media Title", HFILL } 2978 }, 2979 { &hf_unknown, 2980 { "Unknown", "sdp.unknown", 2981 FT_STRING, BASE_NONE, NULL, 0x0, 2982 NULL, HFILL } 2983 }, 2984 { &hf_invalid, 2985 { "Invalid line", "sdp.invalid", 2986 FT_STRING, BASE_NONE, NULL, 0x0, 2987 NULL, HFILL } 2988 }, 2989 { &hf_owner_username, 2990 { "Owner Username", "sdp.owner.username", 2991 FT_STRING, BASE_NONE, NULL, 0x0, 2992 NULL, HFILL } 2993 }, 2994 { &hf_owner_sessionid, 2995 { "Session ID", "sdp.owner.sessionid", 2996 FT_STRING, BASE_NONE, NULL, 0x0, 2997 NULL, HFILL } 2998 }, 2999 { &hf_owner_version, 3000 { "Session Version", "sdp.owner.version", 3001 FT_STRING, BASE_NONE, NULL, 0x0, 3002 NULL, HFILL } 3003 }, 3004 { &hf_owner_network_type, 3005 { "Owner Network Type", "sdp.owner.network_type", 3006 FT_STRING, BASE_NONE, NULL, 0x0, 3007 NULL, HFILL } 3008 }, 3009 { &hf_owner_address_type, 3010 { "Owner Address Type", "sdp.owner.address_type", 3011 FT_STRING, BASE_NONE, NULL, 0x0, 3012 NULL, HFILL } 3013 }, 3014 { &hf_owner_address, 3015 { "Owner Address", "sdp.owner.address", 3016 FT_STRING, BASE_NONE, NULL, 0x0, 3017 NULL, HFILL } 3018 }, 3019 { &hf_connection_info_network_type, 3020 { "Connection Network Type", "sdp.connection_info.network_type", 3021 FT_STRING, BASE_NONE, NULL, 0x0, 3022 NULL, HFILL } 3023 }, 3024 { &hf_connection_info_address_type, 3025 { "Connection Address Type", "sdp.connection_info.address_type", 3026 FT_STRING, BASE_NONE, NULL, 0x0, 3027 NULL, HFILL } 3028 }, 3029 { &hf_connection_info_connection_address, 3030 { "Connection Address", "sdp.connection_info.address", 3031 FT_STRING, BASE_NONE, NULL, 0x0, 3032 NULL, HFILL } 3033 }, 3034 { &hf_connection_info_ttl, 3035 { "Connection TTL", "sdp.connection_info.ttl", 3036 FT_STRING, BASE_NONE, NULL, 0x0, 3037 NULL, HFILL } 3038 }, 3039 { &hf_connection_info_num_addr, 3040 { "Connection Number of Addresses", "sdp.connection_info.num_addr", 3041 FT_STRING, BASE_NONE, NULL, 0x0, 3042 NULL, HFILL } 3043 }, 3044 { &hf_bandwidth_modifier, 3045 { "Bandwidth Modifier", "sdp.bandwidth.modifier", 3046 FT_STRING, BASE_NONE, NULL, 0x0, 3047 NULL, HFILL } 3048 }, 3049 { &hf_bandwidth_value, 3050 { "Bandwidth Value", "sdp.bandwidth.value", 3051 FT_STRING, BASE_NONE, NULL, 0x0, 3052 "Bandwidth Value (in kbits/s)", HFILL } 3053 }, 3054 { &hf_time_start, 3055 { "Session Start Time", "sdp.time.start", 3056 FT_STRING, BASE_NONE, NULL, 0x0, 3057 NULL, HFILL } 3058 }, 3059 { &hf_time_stop, 3060 { "Session Stop Time", "sdp.time.stop", 3061 FT_STRING, BASE_NONE, NULL, 0x0, 3062 NULL, HFILL } 3063 }, 3064 { &hf_repeat_time_interval, 3065 { "Repeat Interval", "sdp.repeat_time.interval", 3066 FT_STRING, BASE_NONE, NULL, 0x0, 3067 NULL, HFILL } 3068 }, 3069 { &hf_repeat_time_duration, 3070 { "Repeat Duration", "sdp.repeat_time.duration", 3071 FT_STRING, BASE_NONE, NULL, 0x0, 3072 NULL, HFILL } 3073 }, 3074 { &hf_repeat_time_offset, 3075 { "Repeat Offset", "sdp.repeat_time.offset", 3076 FT_STRING, BASE_NONE, NULL, 0x0, 3077 NULL, HFILL } 3078 }, 3079 { &hf_timezone_time, 3080 { "Timezone Time", "sdp.timezone.time", 3081 FT_STRING, BASE_NONE, NULL, 0x0, 3082 NULL, HFILL } 3083 }, 3084 { &hf_timezone_offset, 3085 { "Timezone Offset", "sdp.timezone.offset", 3086 FT_STRING, BASE_NONE, NULL, 0x0, 3087 NULL, HFILL } 3088 }, 3089 { &hf_encryption_key_type, 3090 { "Key Type", "sdp.encryption_key.type", 3091 FT_STRING, BASE_NONE, NULL, 0x0, 3092 NULL, HFILL } 3093 }, 3094 { &hf_encryption_key_data, 3095 { "Key Data", "sdp.encryption_key.data", 3096 FT_STRING, BASE_NONE, NULL, 0x0, 3097 NULL, HFILL } 3098 }, 3099 { &hf_session_attribute_field, 3100 { "Session Attribute Fieldname", "sdp.session_attr.field", 3101 FT_STRING, BASE_NONE, NULL, 0x0, 3102 NULL, HFILL } 3103 }, 3104 { &hf_session_attribute_value, 3105 { "Session Attribute Value", "sdp.session_attr.value", 3106 FT_STRING, BASE_NONE, NULL, 0x0, 3107 NULL, HFILL } 3108 }, 3109 { &hf_media_media, 3110 { "Media Type", "sdp.media.media", 3111 FT_STRING, BASE_NONE, NULL, 0x0, 3112 NULL, HFILL } 3113 }, 3114 { &hf_media_port, 3115 { "Media Port", "sdp.media.port", 3116 FT_UINT16, BASE_DEC, NULL, 0x0, 3117 NULL, HFILL } 3118 }, 3119 { &hf_media_port_string, 3120 { "Media Port", "sdp.media.port_string", 3121 FT_STRING, BASE_NONE, NULL, 0x0, 3122 NULL, HFILL } 3123 }, 3124 { &hf_media_portcount, 3125 { "Media Port Count", "sdp.media.portcount", 3126 FT_STRING, BASE_NONE, NULL, 0x0, 3127 NULL, HFILL } 3128 }, 3129 { &hf_media_proto, 3130 { "Media Protocol", "sdp.media.proto", 3131 FT_STRING, BASE_NONE, NULL, 0x0, 3132 NULL, HFILL } 3133 }, 3134 { &hf_media_format, 3135 { "Media Format", "sdp.media.format", 3136 FT_STRING, BASE_NONE, NULL, 0x0, 3137 NULL, HFILL } 3138 }, 3139 { &hf_media_attribute_field, 3140 { "Media Attribute Fieldname", "sdp.media_attribute.field", 3141 FT_STRING, BASE_NONE, NULL, 0x0, 3142 NULL, HFILL } 3143 }, 3144 { &hf_media_attribute_value, 3145 { "Media Attribute Value", "sdp.media_attribute.value", 3146 FT_STRING, BASE_NONE, NULL, 0x0, 3147 NULL, HFILL } 3148 }, 3149 { &hf_media_encoding_name, 3150 { "MIME Type", "sdp.mime.type", 3151 FT_STRING, BASE_NONE, NULL, 0x0, 3152 "SDP MIME Type", HFILL } 3153 }, 3154 { &hf_media_sample_rate, 3155 { "Sample Rate", "sdp.sample_rate", 3156 FT_STRING, BASE_NONE, NULL, 0x0, 3157 NULL, HFILL } 3158 }, 3159 { &hf_media_format_specific_parameter, 3160 { "Media format specific parameters", "sdp.fmtp.parameter", 3161 FT_STRING, BASE_NONE, NULL, 0x0, 3162 "Format specific parameter(fmtp)", HFILL } 3163 }, 3164 { &hf_ipbcp_version, 3165 { "IPBCP Protocol Version", "sdp.ipbcp.version", 3166 FT_STRING, BASE_NONE, NULL, 0x0, 3167 NULL, HFILL } 3168 }, 3169 { &hf_ipbcp_type, 3170 { "IPBCP Command Type", "sdp.ipbcp.command", 3171 FT_STRING, BASE_NONE, NULL, 0x0, 3172 NULL, HFILL } 3173 }, 3174 {&hf_sdp_fmtp_mpeg4_profile_level_id, 3175 { "Level Code", "sdp.fmtp.profile_level_id", 3176 FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0, 3177 NULL, HFILL } 3178 }, 3179 { &hf_sdp_fmtp_h263_profile, 3180 { "Profile", "sdp.fmtp.h263profile", 3181 FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0, 3182 NULL, HFILL } 3183 }, 3184 { &hf_sdp_fmtp_h263_level, 3185 { "Level", "sdp.fmtp.h263level", 3186 FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0, 3187 NULL, HFILL } 3188 }, 3189 { &hf_sdp_h264_packetization_mode, 3190 { "Packetization mode", "sdp.fmtp.h264_packetization_mode", 3191 FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0, 3192 NULL, HFILL } 3193 }, 3194 { &hf_SDPh223LogicalChannelParameters, 3195 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters", 3196 FT_NONE, BASE_NONE, NULL, 0, 3197 NULL, HFILL } 3198 }, 3199 { &hf_key_mgmt_att_value, 3200 { "Key Management", "sdp.key_mgmt", 3201 FT_STRING, BASE_NONE, NULL, 0x0, 3202 NULL, HFILL } 3203 }, 3204 { &hf_key_mgmt_prtcl_id, 3205 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid", 3206 FT_STRING, BASE_NONE, NULL, 0x0, 3207 NULL, HFILL } 3208 }, 3209 { &hf_key_mgmt_data, 3210 { "Key Management Data", "sdp.key_mgmt.data", 3211 FT_BYTES, BASE_NONE, NULL, 0x0, 3212 NULL, HFILL } 3213 }, 3214 { &hf_sdp_crypto_tag, 3215 { "tag", "sdp.crypto.tag", 3216 FT_UINT32, BASE_DEC, NULL, 0x0, 3217 NULL, HFILL } 3218 }, 3219 { &hf_sdp_crypto_crypto_suite, 3220 { "Crypto suite", "sdp.crypto.crypto_suite", 3221 FT_STRING, BASE_NONE, NULL, 0x0, 3222 NULL, HFILL } 3223 }, 3224 { &hf_sdp_crypto_master_key, 3225 { "Master Key", "sdp.crypto.master_key", 3226 FT_BYTES, BASE_NONE, NULL, 0x0, 3227 NULL, HFILL } 3228 }, 3229 { &hf_sdp_crypto_master_salt, 3230 { "Master salt", "sdp.crypto.master_salt", 3231 FT_BYTES, BASE_NONE, NULL, 0x0, 3232 NULL, HFILL } 3233 }, 3234 { &hf_sdp_crypto_lifetime, 3235 { "Lifetime", "sdp.crypto.lifetime", 3236 FT_STRING, BASE_NONE, NULL, 0x0, 3237 NULL, HFILL } 3238 }, 3239 { &hf_sdp_crypto_mki, 3240 { "mki-value", "sdp.crypto.mki-valu", 3241 FT_STRING, BASE_NONE, NULL, 0x0, 3242 NULL, HFILL } 3243 }, 3244 { &hf_sdp_crypto_mki_length, 3245 { "mki_length", "sdp.crypto.mki_length", 3246 FT_STRING, BASE_NONE, NULL, 0x0, 3247 NULL, HFILL } 3248 }, 3249 { &hf_ice_candidate_foundation, 3250 { "Foundation", "sdp.ice_candidate.foundation", 3251 FT_STRING, BASE_NONE, NULL, 0x0, 3252 "Identifier, same for two candidates with same type, base address, protocol and STUN server", HFILL } 3253 }, 3254 { &hf_ice_candidate_componentid, 3255 { "Component ID", "sdp.ice_candidate.componentid", 3256 FT_STRING, BASE_NONE, NULL, 0x0, 3257 "Media component identifier (For RTP media, 1 is RTP, 2 is RTCP)", HFILL } 3258 }, 3259 { &hf_ice_candidate_transport, 3260 { "Transport", "sdp.ice_candidate.transport", 3261 FT_STRING, BASE_NONE, NULL, 0x0, 3262 "Transport protocol", HFILL } 3263 }, 3264 { &hf_ice_candidate_priority, 3265 { "Priority", "sdp.ice_candidate.priority", 3266 FT_STRING, BASE_NONE, NULL, 0x0, 3267 NULL, HFILL } 3268 }, 3269 { &hf_ice_candidate_address, 3270 { "Connection Address", "sdp.ice_candidate.address", 3271 FT_STRING, BASE_NONE, NULL, 0x0, 3272 "IP address or FQDN of the candidate", HFILL } 3273 }, 3274 { &hf_ice_candidate_port, 3275 { "Candidate Port", "sdp.ice_candidate.port", 3276 FT_STRING, BASE_NONE, NULL, 0x0, 3277 "Port of the candidate", HFILL } 3278 }, 3279 { &hf_ice_candidate_type, 3280 { "Candidate Type", "sdp.ice_candidate.type", 3281 FT_STRING, BASE_NONE, NULL, 0x0, 3282 "The origin of the address and port, i.e. where it was learned", HFILL } 3283 }, 3284 /* Generated from convert_proto_tree_add_text.pl */ 3285 { &hf_sdp_nal_unit_1_string, { "NAL unit 1 string", "sdp.nal_unit_1_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3286 { &hf_sdp_nal_unit_2_string, { "NAL unit 2 string", "sdp.nal_unit_2_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3287 { &hf_sdp_key_and_salt, { "Key and Salt", "sdp.key_and_salt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3288 { &hf_sdp_data, { "Data", "sdp.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, 3289 }; 3290 static gint *ett[] = { 3291 &ett_sdp, 3292 &ett_sdp_owner, 3293 &ett_sdp_connection_info, 3294 &ett_sdp_bandwidth, 3295 &ett_sdp_time, 3296 &ett_sdp_repeat_time, 3297 &ett_sdp_timezone, 3298 &ett_sdp_encryption_key, 3299 &ett_sdp_session_attribute, 3300 &ett_sdp_media, 3301 &ett_sdp_media_attribute, 3302 &ett_sdp_fmtp, 3303 &ett_sdp_key_mgmt, 3304 &ett_sdp_crypto_key_parameters, 3305 }; 3306 3307 static ei_register_info ei[] = { 3308 { &ei_sdp_invalid_key_param, 3309 { "sdp.invalid_key_param", 3310 PI_MALFORMED, PI_NOTE, 3311 "Invalid key-param (no ':' delimiter)", 3312 EXPFILL 3313 } 3314 }, 3315 { &ei_sdp_invalid_line_equal, 3316 { "sdp.invalid_line.no_equal", 3317 PI_MALFORMED, PI_NOTE, 3318 "Invalid SDP line (no '=' delimiter)", 3319 EXPFILL 3320 } 3321 }, 3322 { &ei_sdp_invalid_line_fields, 3323 { "sdp.invalid_line.missing_fields", 3324 PI_MALFORMED, PI_ERROR, 3325 "Invalid SDP line (missing required fields)", 3326 EXPFILL 3327 } 3328 }, 3329 { &ei_sdp_invalid_line_space, 3330 { "sdp.invalid_line.extra_space", 3331 PI_MALFORMED, PI_ERROR, 3332 "Invalid SDP whitespace (extra space character)", 3333 EXPFILL 3334 } 3335 }, 3336 { &ei_sdp_invalid_conversion, 3337 { "sdp.invalid_conversion", 3338 PI_PROTOCOL, PI_WARN, 3339 "Invalid conversion", 3340 EXPFILL 3341 } 3342 }, 3343 { &ei_sdp_invalid_media_port, 3344 { "sdp.invalid_media_port", 3345 PI_MALFORMED, PI_ERROR, 3346 "Invalid media port", 3347 EXPFILL 3348 } 3349 }, 3350 { &ei_sdp_invalid_sample_rate, 3351 { "sdp.invalid_sample_rate", 3352 PI_MALFORMED, PI_ERROR, 3353 "Invalid sample rate", 3354 EXPFILL 3355 } 3356 }, 3357 { &ei_sdp_invalid_media_format, 3358 { "sdp.invalid_media_format", 3359 PI_MALFORMED, PI_ERROR, 3360 "Invalid media format", 3361 EXPFILL 3362 } 3363 }, 3364 { &ei_sdp_invalid_crypto_tag, 3365 { "sdp.invalid_crypto_tag", 3366 PI_MALFORMED, PI_ERROR, 3367 "Invalid crypto tag", 3368 EXPFILL 3369 } 3370 }, 3371 { &ei_sdp_invalid_crypto_mki_length, 3372 { "sdp.invalid_crypto_mki_length", 3373 PI_MALFORMED, PI_ERROR, 3374 "Invalid crypto mki length", 3375 EXPFILL 3376 } 3377 } 3378 }; 3379 3380 module_t *sdp_module; 3381 expert_module_t* expert_sdp; 3382 3383 proto_sdp = proto_register_protocol("Session Description Protocol", 3384 "SDP", "sdp"); 3385 proto_register_field_array(proto_sdp, hf, array_length(hf)); 3386 proto_register_subtree_array(ett, array_length(ett)); 3387 expert_sdp = expert_register_protocol(proto_sdp); 3388 expert_register_field_array(expert_sdp, ei, array_length(ei)); 3389 3390 key_mgmt_dissector_table = register_dissector_table("key_mgmt", 3391 "Key Management", proto_sdp, FT_STRING, BASE_NONE); 3392 /* 3393 * Preferences registration 3394 */ 3395 sdp_module = prefs_register_protocol(proto_sdp, NULL); 3396 prefs_register_bool_preference(sdp_module, "establish_conversation", 3397 "Establish Media Conversation", 3398 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based " 3399 "upon port numbers found in SDP payload", 3400 &global_sdp_establish_conversation); 3401 3402 sdp_transport_reqs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); 3403 sdp_transport_rsps = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); 3404 3405 /* 3406 * Register the dissector by name, so other dissectors can 3407 * grab it by name rather than just referring to it directly. 3408 */ 3409 sdp_handle = register_dissector("sdp", dissect_sdp, proto_sdp); 3410 3411 /* Register for tapping */ 3412 sdp_tap = register_tap("sdp"); 3413 3414 /* compile patterns */ 3415 ws_mempbrk_compile(&pbrk_digits, "0123456789"); 3416 ws_mempbrk_compile(&pbrk_alpha, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); 3417 } 3418 3419 void 3420 proto_reg_handoff_sdp(void) 3421 { 3422 rtcp_handle = find_dissector_add_dependency("rtcp", proto_sdp); 3423 msrp_handle = find_dissector_add_dependency("msrp", proto_sdp); 3424 sprt_handle = find_dissector_add_dependency("sprt", proto_sdp); 3425 h264_handle = find_dissector_add_dependency("h264", proto_sdp); 3426 h265_handle = find_dissector_add_dependency("h265", proto_sdp); 3427 mp4ves_config_handle = find_dissector_add_dependency("mp4ves_config", proto_sdp); 3428 3429 proto_sprt = dissector_handle_get_protocol_index(find_dissector("sprt")); 3430 3431 dissector_add_string("media_type", "application/sdp", sdp_handle); 3432 dissector_add_uint("bctp.tpi", 0x20, sdp_handle); 3433 } 3434 3435 /* 3436 * Editor modelines - https://www.wireshark.org/tools/modelines.html 3437 * 3438 * Local variables: 3439 * c-basic-offset: 4 3440 * tab-width: 8 3441 * indent-tabs-mode: nil 3442 * End: 3443 * 3444 * vi: set shiftwidth=4 tabstop=8 expandtab: 3445 * :indentSize=4:tabSize=8:noTabs=true: 3446 */ 3447