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