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