2 * Routines for SDP packet disassembly (RFC 2327)
4 * Jason Lango <jal@netapp.com>
5 * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * Ref http://www.ietf.org/rfc/rfc4566.txt?number=4566
31 #include <epan/packet.h>
32 #include <epan/exceptions.h>
33 #include <epan/strutil.h>
34 #include <epan/wmem/wmem.h>
35 #include <epan/asn1.h>
36 #include <epan/prefs.h>
37 #include <epan/expert.h>
39 #include <epan/rtp_pt.h>
40 #include <epan/show_exception.h>
41 #include <epan/addr_resolv.h>
43 #include "packet-sdp.h"
44 #include "packet-rtp.h"
46 #include "packet-rtcp.h"
47 #include "packet-t38.h"
48 #include "packet-msrp.h"
49 #include "packet-sprt.h"
50 #include "packet-per.h"
51 #include "packet-h245.h"
52 #include "packet-h264.h"
53 #include "packet-mp4ves.h"
55 void proto_register_sdp(void);
56 void proto_reg_handoff_sdp(void);
58 static dissector_handle_t rtcp_handle;
59 static dissector_handle_t sprt_handle;
60 static dissector_handle_t msrp_handle;
61 static dissector_handle_t h264_handle;
62 static dissector_handle_t mp4ves_handle;
64 static int sdp_tap = -1;
66 static int proto_sdp = -1;
67 static int proto_sprt = -1;
69 static const char* UNKNOWN_ENCODING = "Unknown";
70 static wmem_tree_t *sdp_transport_reqs = NULL;
71 static wmem_tree_t *sdp_transport_rsps = NULL;
73 /* preference globals */
74 static gboolean global_sdp_establish_conversation = TRUE;
76 /* Top level fields */
77 static int hf_protocol_version = -1;
78 static int hf_owner = -1;
79 static int hf_session_name = -1;
80 static int hf_session_info = -1;
81 static int hf_uri = -1;
82 static int hf_email = -1;
83 static int hf_phone = -1;
84 static int hf_connection_info = -1;
85 static int hf_bandwidth = -1;
86 static int hf_timezone = -1;
87 static int hf_encryption_key = -1;
88 static int hf_session_attribute = -1;
89 static int hf_media_attribute = -1;
90 static int hf_time = -1;
91 static int hf_repeat_time = -1;
92 static int hf_media = -1;
93 static int hf_media_title = -1;
94 static int hf_unknown = -1;
95 static int hf_invalid = -1;
96 static int hf_ipbcp_version = -1;
97 static int hf_ipbcp_type = -1;
99 /* hf_owner subfields*/
100 static int hf_owner_username = -1;
101 static int hf_owner_sessionid = -1;
102 static int hf_owner_version = -1;
103 static int hf_owner_network_type = -1;
104 static int hf_owner_address_type = -1;
105 static int hf_owner_address = -1;
107 /* hf_connection_info subfields */
108 static int hf_connection_info_network_type = -1;
109 static int hf_connection_info_address_type = -1;
110 static int hf_connection_info_connection_address = -1;
111 static int hf_connection_info_ttl = -1;
112 static int hf_connection_info_num_addr = -1;
114 /* hf_bandwidth subfields */
115 static int hf_bandwidth_modifier = -1;
116 static int hf_bandwidth_value = -1;
118 /* hf_time subfields */
119 static int hf_time_start = -1;
120 static int hf_time_stop = -1;
122 /* hf_repeat_time subfield */
123 static int hf_repeat_time_interval = -1;
124 static int hf_repeat_time_duration = -1;
125 static int hf_repeat_time_offset = -1;
127 /* hf_timezone subfields */
128 static int hf_timezone_time = -1;
129 static int hf_timezone_offset = -1;
131 /* hf_encryption_key subfields */
132 static int hf_encryption_key_type = -1;
133 static int hf_encryption_key_data = -1;
135 /* hf_session_attribute subfields */
136 static int hf_session_attribute_field = -1;
137 static int hf_session_attribute_value = -1;
139 /* hf_media subfields */
140 static int hf_media_media = -1;
141 static int hf_media_port = -1;
142 static int hf_media_portcount = -1;
143 static int hf_media_proto = -1;
144 static int hf_media_format = -1;
146 /* hf_session_attribute subfields */
147 static int hf_media_attribute_field = -1;
148 static int hf_media_attribute_value = -1;
149 static int hf_media_encoding_name = -1;
150 static int hf_media_sample_rate = -1;
151 static int hf_media_format_specific_parameter = -1;
152 static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
153 static int hf_sdp_fmtp_h263_profile = -1;
154 static int hf_sdp_fmtp_h263_level = -1;
155 static int hf_sdp_h264_packetization_mode = -1;
156 static int hf_SDPh223LogicalChannelParameters = -1;
158 /* hf_session_attribute hf_media_attribute subfields */
159 static int hf_key_mgmt_att_value = -1;
160 static int hf_key_mgmt_prtcl_id = -1;
161 static int hf_key_mgmt_data = -1;
163 static int hf_sdp_crypto_tag = -1;
164 static int hf_sdp_crypto_crypto_suite = -1;
165 static int hf_sdp_crypto_master_key = -1;
166 static int hf_sdp_crypto_master_salt = -1;
167 static int hf_sdp_crypto_lifetime = -1;
168 static int hf_sdp_crypto_mki = -1;
169 static int hf_sdp_crypto_mki_length = -1;
172 static int ett_sdp = -1;
173 static int ett_sdp_owner = -1;
174 static int ett_sdp_connection_info = -1;
175 static int ett_sdp_bandwidth = -1;
176 static int ett_sdp_time = -1;
177 static int ett_sdp_repeat_time = -1;
178 static int ett_sdp_timezone = -1;
179 static int ett_sdp_encryption_key = -1;
180 static int ett_sdp_session_attribute = -1;
181 static int ett_sdp_media = -1;
182 static int ett_sdp_media_attribute = -1;
183 static int ett_sdp_fmtp = -1;
184 static int ett_sdp_key_mgmt = -1;
185 static int ett_sdp_crypto_key_parameters = -1;
187 static expert_field ei_sdp_invalid_key_param = EI_INIT;
188 static expert_field ei_sdp_invalid_line = EI_INIT;
190 #define SDP_RTP_PROTO 0x00000001
191 #define SDP_SRTP_PROTO 0x00000002
192 #define SDP_T38_PROTO 0x00000004
193 #define SDP_MSRP_PROTO 0x00000008
194 #define SDP_SPRT_PROTO 0x00000010
195 #define SDP_IPv4 0x80000000
196 #define SDP_IPv6 0x40000000
197 #define SDP_MSRP_IPv4 0x20000000
198 #define SDP_VIDEO 0x10000000
201 #define SDP_MAX_RTP_CHANNELS 4
202 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
203 #define SDP_NO_OF_PT 128
205 gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
207 GHashTable *rtp_dyn_payload;
209 } transport_media_pt_t;
212 enum sdp_exchange_type sdp_status;
213 char *encoding_name[SDP_NO_OF_PT];
214 int sample_rate[SDP_NO_OF_PT];
215 int media_port[SDP_MAX_RTP_CHANNELS];
216 address src_addr[SDP_MAX_RTP_CHANNELS];
217 guint proto_bitmask[SDP_MAX_RTP_CHANNELS];
218 transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
220 /* SRTP related info XXX note currently we only handle one crypto line in the SDP
221 * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
222 * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
223 * and the SDP dissector just provide the relevant data.
224 * YES! packet-sdp.c should be about SDP parsing... SDP *state* needs to be maintained by upper
225 * protocols, because each one has different rules/semantics.
227 guint encryption_algorithm;
228 guint auth_algorithm;
229 guint mki_len; /* number of octets used for the MKI in the RTP payload */
230 guint auth_tag_len; /* number of octets used for the Auth Tag in the RTP payload */
233 /* Data that is retrieved from a packet, but does not need to be kept */
235 char *connection_address; /* there should actually be SDP_MAX_RTP_CHANNELS of these too */
236 char *connection_type;
237 /* media_type is for 'audio', 'video', etc, so per-stream */
238 char *media_type[SDP_MAX_RTP_CHANNELS];
239 char *media_port[SDP_MAX_RTP_CHANNELS];
240 char *media_proto[SDP_MAX_RTP_CHANNELS];
243 /* MSRP transport info (as set while parsing path attribute) */
244 gboolean msrp_transport_address_set;
245 guint32 msrp_ipaddr[4];
246 guint16 msrp_port_number;
248 } disposable_media_info_t;
250 /* key-mgmt dissector
252 * http://www.iana.org/assignments/sdp-parameters
254 static dissector_table_t key_mgmt_dissector_table;
256 /* Subdissector functions */
258 dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) {
259 proto_tree *sdp_owner_tree;
260 gint offset, next_offset, tokenlen;
264 sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner);
266 /* Find the username */
267 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
268 if (next_offset == -1)
270 tokenlen = next_offset - offset;
272 proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
274 offset = next_offset + 1;
276 /* Find the session id */
277 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
278 if (next_offset == -1)
280 tokenlen = next_offset - offset;
282 proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
283 tokenlen, ENC_ASCII|ENC_NA);
284 offset = next_offset + 1;
286 /* Find the version */
287 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
288 if (next_offset == -1)
290 tokenlen = next_offset - offset;
292 proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
294 offset = next_offset + 1;
296 /* Find the network type */
297 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
298 if (next_offset == -1)
300 tokenlen = next_offset - offset;
302 proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
303 tokenlen, ENC_ASCII|ENC_NA);
304 offset = next_offset + 1;
306 /* Find the address type */
307 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
308 if (next_offset == -1)
310 tokenlen = next_offset - offset;
312 proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
313 tokenlen, ENC_ASCII|ENC_NA);
314 offset = next_offset + 1;
316 /* Find the address */
317 proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_ASCII|ENC_NA);
321 * XXX - this can leak memory if an exception is thrown after we've fetched
325 dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
326 disposable_media_info_t *media_info) {
327 proto_tree *sdp_connection_info_tree;
328 gint offset, next_offset, tokenlen;
332 sdp_connection_info_tree = proto_item_add_subtree(ti,
333 ett_sdp_connection_info);
335 /* Find the network type */
336 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
337 if (next_offset == -1)
339 tokenlen = next_offset - offset;
341 proto_tree_add_item(sdp_connection_info_tree,
342 hf_connection_info_network_type, tvb, offset, tokenlen,
344 offset = next_offset + 1;
346 /* Find the address type */
347 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
348 if (next_offset == -1)
350 tokenlen = next_offset - offset;
351 /* Save connection address type */
352 media_info->connection_type = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
355 proto_tree_add_item(sdp_connection_info_tree,
356 hf_connection_info_address_type, tvb, offset, tokenlen,
358 offset = next_offset + 1;
360 /* Find the connection address */
361 /* XXX - what if there's a <number of addresses> value? */
362 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
363 if (next_offset == -1) {
364 tokenlen = -1; /* end of tvbuff */
365 /* Save connection address */
366 media_info->connection_address =
367 (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tvb_length_remaining(tvb, offset));
369 tokenlen = next_offset - offset;
370 /* Save connection address */
371 media_info->connection_address = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
374 proto_tree_add_item(sdp_connection_info_tree,
375 hf_connection_info_connection_address, tvb, offset,
376 tokenlen, ENC_ASCII|ENC_NA);
377 if (next_offset != -1) {
378 offset = next_offset + 1;
379 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
380 if (next_offset == -1) {
381 tokenlen = -1; /* end of tvbuff */
383 tokenlen = next_offset - offset;
385 proto_tree_add_item(sdp_connection_info_tree,
386 hf_connection_info_ttl, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
387 if (next_offset != -1) {
388 offset = next_offset + 1;
389 proto_tree_add_item(sdp_connection_info_tree,
390 hf_connection_info_num_addr, tvb, offset, -1, ENC_ASCII|ENC_NA);
396 dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) {
397 proto_tree *sdp_bandwidth_tree;
398 gint offset, next_offset, tokenlen;
400 gboolean unit_is_kbs = FALSE;
401 gboolean unit_is_bps = FALSE;
405 sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth);
407 /* find the modifier */
408 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
410 if (next_offset == -1)
413 tokenlen = next_offset - offset;
415 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
416 tokenlen, ENC_ASCII|ENC_NA);
417 if (tvb_strneql(tvb, offset, "CT", 2) == 0) {
418 proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
420 } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) {
421 proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
423 } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) {
424 proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
429 offset = next_offset + 1;
431 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
433 if (unit_is_kbs == TRUE)
434 proto_item_append_text(item, " kb/s");
435 if (unit_is_bps == TRUE)
436 proto_item_append_text(item, " b/s");
439 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) {
440 proto_tree *sdp_time_tree;
441 gint offset, next_offset, tokenlen;
445 sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
448 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
449 if (next_offset == -1)
452 tokenlen = next_offset - offset;
453 proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
457 offset = next_offset + 1;
458 proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_ASCII|ENC_NA);
461 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) {
462 proto_tree *sdp_repeat_time_tree;
463 gint offset, next_offset, tokenlen;
467 sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
470 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
471 if (next_offset == -1)
474 tokenlen = next_offset - offset;
475 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
476 offset, tokenlen, ENC_ASCII|ENC_NA);
479 offset = next_offset + 1;
480 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
481 if (next_offset == -1)
484 tokenlen = next_offset - offset;
485 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb,
486 offset, tokenlen, ENC_ASCII|ENC_NA);
490 offset = next_offset +1;
491 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
492 if (next_offset != -1) {
493 tokenlen = next_offset - offset;
495 tokenlen = -1; /* end of tvbuff */
497 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
498 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
499 } while (next_offset != -1);
503 dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) {
504 proto_tree* sdp_timezone_tree;
505 gint offset, next_offset, tokenlen;
509 sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone);
512 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
513 if (next_offset == -1)
515 tokenlen = next_offset - offset;
517 proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
518 tokenlen, ENC_ASCII|ENC_NA);
519 offset = next_offset + 1;
520 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
521 if (next_offset != -1) {
522 tokenlen = next_offset - offset;
524 tokenlen = -1; /* end of tvbuff */
526 proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
527 tokenlen, ENC_ASCII|ENC_NA);
528 offset = next_offset + 1;
529 } while (next_offset != -1);
534 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) {
535 proto_tree *sdp_encryption_key_tree;
536 gint offset, next_offset, tokenlen;
540 sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key);
542 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
544 if (next_offset == -1)
547 tokenlen = next_offset - offset;
549 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type,
550 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
552 offset = next_offset + 1;
553 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data,
554 tvb, offset, -1, ENC_ASCII|ENC_NA);
557 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
558 gchar *data_p = NULL;
559 gchar *prtcl_id = NULL;
561 tvbuff_t *keymgmt_tvb;
562 gboolean found_match = FALSE;
563 proto_tree *key_tree;
568 key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
570 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
572 if (next_offset == -1)
575 tokenlen = next_offset - offset;
576 prtcl_id = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
578 proto_tree_add_item(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
580 offset = next_offset + 1;
582 len = tvb_length_remaining(tvb, offset);
586 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, len);
587 keymgmt_tvb = base64_to_tvb(tvb, data_p);
588 add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
590 if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) {
591 found_match = dissector_try_string(key_mgmt_dissector_table,
598 proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
599 keymgmt_tvb, 0, -1, ENC_NA);
600 PROTO_ITEM_SET_HIDDEN(ti2);
602 proto_tree_add_item(key_tree, hf_key_mgmt_data,
603 keymgmt_tvb, 0, -1, ENC_NA);
609 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
610 proto_tree *sdp_session_attribute_tree;
611 gint offset, next_offset, tokenlen;
616 sdp_session_attribute_tree = proto_item_add_subtree(ti,
617 ett_sdp_session_attribute);
619 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
621 if (next_offset == -1)
624 tokenlen = next_offset - offset;
626 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_field,
627 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
629 field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
631 offset = next_offset + 1;
633 if (strcmp((char*)field_name, "ipbcp") == 0) {
634 offset = tvb_pbrk_guint8(tvb, offset, -1,"0123456789", NULL);
639 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
641 if (next_offset == -1)
644 tokenlen = next_offset - offset;
646 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
648 offset = tvb_pbrk_guint8(tvb, offset, -1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
653 tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
658 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
659 } else if (strcmp((char*)field_name, "key-mgmt") == 0) {
663 key_tvb = tvb_new_subset_remaining(tvb, offset);
664 key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_ASCII|ENC_NA);
666 dissect_key_mgmt(key_tvb, pinfo, key_ti);
668 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
669 tvb, offset, -1, ENC_ASCII|ENC_NA);
674 /* Dissect media description */
676 dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
677 transport_info_t *transport_info, disposable_media_info_t *media_info) {
678 proto_tree *sdp_media_tree;
679 gint offset, next_offset, tokenlen, idx;
680 guint8 *media_format;
684 /* Create tree for media session */
685 sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media);
687 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
689 if (next_offset == -1)
692 tokenlen = next_offset - offset;
694 /* Type of media session */
695 proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
698 media_info->media_type[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
700 offset = next_offset + 1;
702 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
703 if (next_offset == -1)
705 tokenlen = next_offset - offset;
706 next_offset = tvb_find_guint8(tvb, offset, tokenlen, '/');
708 if (next_offset != -1) {
709 tokenlen = next_offset - offset;
711 media_info->media_port[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
713 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
714 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
715 offset = next_offset + 1;
716 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
717 if (next_offset == -1)
719 tokenlen = next_offset - offset;
720 proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
721 tokenlen, ENC_ASCII|ENC_NA);
722 offset = next_offset + 1;
724 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
726 if (next_offset == -1)
728 tokenlen = next_offset - offset;
730 media_info->media_port[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
731 /* XXX Remember Port */
732 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
733 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
734 offset = next_offset + 1;
737 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
739 if ( next_offset == -1)
742 tokenlen = next_offset - offset;
743 /* Save port protocol */
744 media_info->media_proto[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
746 /* XXX Remember Protocol */
747 proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
751 offset = next_offset + 1;
752 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
754 if (next_offset == -1) {
755 tokenlen = tvb_length_remaining(tvb, offset); /* End of tvbuff */
757 break; /* Nothing more left */
759 tokenlen = next_offset - offset;
762 if (!strcmp(media_info->media_proto[media_info->media_count], "RTP/AVP")) {
763 media_format = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
764 proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
765 tokenlen, val_to_str_ext((guint32)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u"));
766 idx = transport_info->media[transport_info->media_count].pt_count;
767 transport_info->media[transport_info->media_count].pt[idx] = (gint32)strtol((char*)media_format, NULL, 10);
768 if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
769 transport_info->media[transport_info->media_count].pt_count++;
771 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
772 tokenlen, ENC_ASCII|ENC_NA);
774 } while (next_offset != -1);
776 /* XXX Dissect traffic to "Port" as "Protocol"
777 * Remember this Port/Protocol pair so we can tear it down again later
778 * Actually, it's harder than that:
779 * We need to find out the address of the other side first and it
780 * looks like that info can be found in SIP headers only.
786 ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
788 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
790 /* arbitrary maximum length */
795 /* first, skip to where the encoded pdu starts, this is
796 the first hex digit after the '=' char.
799 if ((*msg == 0) || (*msg == '\n')) {
809 if ((*msg == 0) || (*msg == '\n')) {
812 if ( ((*msg >= '0') && (*msg <= '9'))
813 || ((*msg >= 'a') && (*msg <= 'f'))
814 || ((*msg >= 'A') && (*msg <= 'F'))) {
820 while (((*msg >= '0') && (*msg <= '9'))
821 || ((*msg >= 'a') && (*msg <= 'f'))
822 || ((*msg >= 'A') && (*msg <= 'F'))) {
824 if ((*msg >= '0') && (*msg <= '9')) {
826 } else if ((*msg >= 'a') && (*msg <= 'f')) {
828 } else if ((*msg >= 'A') && (*msg <= 'F')) {
835 if ((*msg >= '0') && (*msg <= '9')) {
837 } else if ((*msg >= 'a') && (*msg <= 'f')) {
838 val |= (*msg)-'a'+10;
839 } else if ((*msg >= 'A') && (*msg <= 'F')) {
840 val |= (*msg)-'A'+10;
846 buf[i] = (guint8)val;
852 bytes_tvb = tvb_new_child_real_data(tvb, buf, i, i);
853 add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
859 /* Annex X Profiles and levels definition */
860 static const value_string h263_profile_vals[] =
862 { 0, "Baseline Profile" },
863 { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
864 { 2, "Version 1 Backward-Compatibility Profile" },
865 { 3, "Version 2 Interactive and Streaming Wireless Profile" },
866 { 4, "Version 3 Interactive and Streaming Wireless Profile" },
867 { 5, "Conversational High Compression Profile" },
868 { 6, "Conversational Internet Profile" },
869 { 7, "Conversational Interlace Profile" },
870 { 8, "High Latency Profile" },
875 /* RFC 4629 The level are described in table X.2 of H.263 annex X */
876 static const value_string h263_level_vals[] =
878 { 10, "QCIF (176 x 144), 1 x 64Kb/s" },
879 { 20, "CIF (352 x 288), 2 x 64Kb/s" },
880 { 30, "CIF (352 x 288), 6 x 64Kb/s" },
881 { 40, "CIF (352 x 288), 32 x 64Kb/s" },
882 { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
883 { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
884 { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
885 { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
890 static const value_string h264_packetization_mode_vals[] =
892 { 0, "Single NAL mode" },
893 { 1, "Non-interleaved mode" },
894 { 2, "Interleaved mode" },
899 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
902 decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type) {
906 gchar *format_specific_parameter;
908 tvbuff_t * volatile data_tvb;
910 end_offset = offset + tokenlen;
913 proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
914 tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
917 /* Look for an '=' within this value - this may indicate that there is a
918 profile-level-id parameter to find if the MPEG4 media type is in use */
919 next_offset = tvb_find_guint8(tvb, offset, -1, '=');
920 if (next_offset == -1)
922 /* Give up (and avoid exception) if '=' not found */
926 /* Find the name of the parameter */
927 tokenlen = next_offset - offset;
928 field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
930 proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
932 offset = next_offset;
934 /* Dissect the MPEG4 profile-level-id parameter if present */
935 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) {
936 if (strcmp((char*)field_name, "profile-level-id") == 0) {
938 tokenlen = end_offset - offset;
939 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
940 item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
941 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
942 PROTO_ITEM_SET_GENERATED(item);
943 } else if (strcmp((char*)field_name, "config") == 0) {
944 /* String including "=" */
945 tokenlen = end_offset - offset;
946 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
947 /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
948 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
949 if (mp4ves_handle && data_tvb) {
950 dissect_mp4ves_config(data_tvb, pinfo, tree);
955 /* Dissect the H263-2000 profile parameter if present */
956 if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) ||
957 ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) {
958 if (strcmp((char*)field_name, "profile") == 0) {
960 tokenlen = end_offset - offset;
961 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
962 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
963 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
964 PROTO_ITEM_SET_GENERATED(item);
965 } else if (strcmp((char*)field_name, "level") == 0) {
967 tokenlen = end_offset - offset;
968 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
969 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
970 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
971 PROTO_ITEM_SET_GENERATED(item);
976 /* Dissect the H264 profile-level-id parameter
978 * A base16 [6] (hexadecimal) representation of
979 * the following three bytes in the sequence
980 * parameter set NAL unit specified in [1]: 1)
981 * profile_idc, 2) a byte herein referred to as
982 * profile-iop, composed of the values of
983 * constraint_set0_flag, constraint_set1_flag,
984 * constraint_set2_flag, and reserved_zero_5bits
985 * in bit-significance order, starting from the
986 * most significant bit, and 3) level_idc.
988 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H264") == 0)) {
989 if (strcmp(field_name, "profile-level-id") == 0) {
992 /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
993 tokenlen = end_offset - offset;
994 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
995 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
997 proto_tree_add_text(tree, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter);
1000 length = tvb_length(data_tvb);
1002 if (h264_handle && data_tvb) {
1003 dissect_h264_profile(data_tvb, pinfo, tree);
1006 item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
1007 PROTO_ITEM_SET_GENERATED(item);
1009 } else if (strcmp(field_name, "packetization-mode") == 0) {
1011 tokenlen = end_offset - offset;
1012 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1013 item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
1014 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1015 PROTO_ITEM_SET_GENERATED(item);
1016 } else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
1017 /* The value of the parameter is the
1018 base64 [6] representation of the initial
1019 parameter set NAL units as specified in
1020 sections 7.3.2.1 and 7.3.2.2 of [1]. The
1021 parameter sets are conveyed in decoding order,
1022 and no framing of the parameter set NAL units
1023 takes place. A comma is used to separate any
1024 pair of parameter sets in the list.
1026 gchar *data_p = NULL;
1032 comma_offset = tvb_find_guint8(tvb, offset, -1, ',');
1033 if (comma_offset != -1) {
1034 tokenlen = comma_offset - offset;
1036 tokenlen = end_offset - offset;
1039 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1040 proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 1 string: %s", data_p);
1042 /* proto_tree_add_text(tree, tvb, offset, tokenlen, "String %s", data_p); */
1043 data_tvb = base64_to_tvb(tvb, data_p);
1044 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
1046 if (h264_handle && data_tvb) {
1048 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1050 CATCH_NONFATAL_ERRORS {
1051 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1054 if (comma_offset != -1) {
1055 /* Second NAL unit */
1056 offset = comma_offset +1;
1057 tokenlen = end_offset - offset;
1058 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1059 proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 2 string: %s", data_p);
1060 data_tvb = base64_to_tvb(tvb, data_p);
1061 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
1062 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1074 #define SDP_RTPMAP 1
1077 #define SDP_H248_ITEM 4
1078 #define SDP_CRYPTO 5
1079 #define SDP_SPRTMAP 6
1081 static const sdp_names_t sdp_media_attribute_names[] = {
1082 { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */
1083 { "rtpmap"}, /* 1 */
1086 { "h248item"}, /* 4 */
1087 { "crypto"}, /* 5 */
1091 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
1095 for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
1096 if ((len == strlen(sdp_media_attribute_names[i].name)) &&
1097 (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0))
1104 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length,
1105 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1106 proto_tree *sdp_media_attribute_tree, *parameter_item;
1107 proto_item *fmtp_item, *media_format_item, *parameter_tree;
1108 proto_tree *fmtp_tree;
1109 gint offset, next_offset, tokenlen, n, colon_offset;
1110 /*??guint8 *field_name;*/
1111 guint8 *payload_type;
1112 guint8 *attribute_value;
1115 gint sdp_media_attrbute_code;
1116 const char *msrp_res = "msrp://";
1117 const char *h324ext_h223lcparm = "h324ext/h223lcparm";
1118 gboolean has_more_pars = TRUE;
1120 guint8 master_key_length = 0, master_salt_length = 0;
1121 encoding_name_and_rate_t *encoding_name_and_rate;
1125 /* Create attribute tree */
1126 sdp_media_attribute_tree = proto_item_add_subtree(ti,
1127 ett_sdp_media_attribute);
1128 /* Find end of field */
1129 colon_offset = tvb_find_guint8(tvb, offset, -1, ':');
1131 if (colon_offset == -1)
1134 /* Attribute field name is token before ':' */
1135 tokenlen = colon_offset - offset;
1136 proto_tree_add_item(sdp_media_attribute_tree,
1137 hf_media_attribute_field,
1138 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1139 /*??field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);*/
1140 sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
1143 offset = colon_offset + 1;
1144 /* skip leading wsp */
1145 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1147 /* Value is the remainder of the line */
1148 attribute_value = tvb_get_string(wmem_packet_scope(), tvb, offset, tvb_length_remaining(tvb, offset));
1152 /*********************************************/
1153 /* Special parsing for some field name types */
1155 switch (sdp_media_attrbute_code) {
1157 /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
1158 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1160 if (next_offset == -1)
1163 tokenlen = next_offset - offset;
1165 proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
1166 offset, tokenlen, ENC_ASCII|ENC_NA);
1168 payload_type = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1170 offset = next_offset + 1;
1172 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
1174 if (next_offset == -1) {
1178 tokenlen = next_offset - offset;
1180 proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
1181 offset, tokenlen, ENC_ASCII|ENC_NA);
1183 pt = atoi((char*)payload_type);
1184 if (pt >= SDP_NO_OF_PT) {
1185 return; /* Invalid */
1188 key = wmem_new(wmem_file_scope(), gint);
1189 *key = (gint)strtol((char*)payload_type, NULL, 10);
1191 transport_info->encoding_name[pt] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1193 next_offset = next_offset + 1;
1194 offset = next_offset;
1195 while (length-1 >= next_offset) {
1196 if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
1200 tokenlen = next_offset - offset;
1201 proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
1202 offset, tokenlen, ENC_ASCII|ENC_NA);
1203 transport_info->sample_rate[pt] = atoi(tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1204 /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1207 a=rtpmap:101 G726-32/8000
1208 m=audio 49170 RTP/AVP 0 97
1209 a=rtpmap:97 telephone-event/8000
1210 m=audio 49172 RTP/AVP 97 101
1211 a=rtpmap:97 G726-24/8000
1213 The Media attributes ("a="s) after the "m=" only apply for that "m=".
1214 If there is an "a=" before the first "m=", that attribute applies for
1215 all the session (all the "m="s).
1218 /* so, if this "a=" appear before any "m=", we add it to all the dynamic
1221 if (transport_info->media_count < 0) {
1222 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1223 encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
1224 encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
1225 encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1227 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1228 key, encoding_name_and_rate);
1229 } else { /* we create a new key and encoding_name to assign to the other hash tables */
1231 key2 = wmem_new(wmem_file_scope(), gint);
1232 *key2 = (gint)strtol((char*)payload_type, NULL, 10);
1233 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1234 key2, encoding_name_and_rate);
1238 /* if the "a=" is after an "m=", only apply to this "m=" */
1240 /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
1241 encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
1243 encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
1244 encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1245 g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
1246 key, encoding_name_and_rate);
1249 if (sdp_media_attribute_tree) {
1250 guint8 media_format;
1251 /* Reading the Format parameter(fmtp) */
1252 /* Skip leading space, if any */
1253 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1254 /* Media format extends to the next space */
1255 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1257 if (next_offset == -1)
1260 tokenlen = next_offset - offset;
1263 media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
1264 hf_media_format, tvb, offset,
1265 tokenlen, ENC_ASCII|ENC_NA);
1266 media_format = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1267 if (media_format >= SDP_NO_OF_PT) {
1268 return; /* Invalid */
1271 /* Append encoding name to format if known */
1272 proto_item_append_text(media_format_item, " [%s]",
1273 transport_info->encoding_name[media_format]);
1276 payload_type = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1278 /* Move offset past the payload type */
1279 offset = next_offset + 1;
1281 while (has_more_pars == TRUE) {
1282 next_offset = tvb_find_guint8(tvb, offset, -1, ';');
1283 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1285 if (next_offset == -1) {
1286 has_more_pars = FALSE;
1287 next_offset= tvb_length(tvb);
1290 /* There are at least 2 - add the first parameter */
1291 tokenlen = next_offset - offset;
1292 fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
1293 hf_media_format_specific_parameter, tvb,
1294 offset, tokenlen, ENC_ASCII|ENC_NA);
1296 fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
1298 decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
1299 transport_info->encoding_name[media_format]);
1301 /* Move offset past "; " and onto firts char */
1302 offset = next_offset + 1;
1307 /* msrp attributes that contain address needed for conversation */
1309 * path = path-label ":" path-list
1310 * path-label = "path"
1311 * path-list= MSRP-URI *(SP MSRP-URI)
1312 * MSRP-URI = msrp-scheme "://" authority
1313 * ["/" session-id] ";" transport *( ";" URI-parameter)
1314 * ; authority as defined in RFC3986
1316 * msrp-scheme = "msrp" / "msrps"
1318 * The authority component is preceded by a double slash ("//") and is terminated by
1319 * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1320 * the end of the URI.
1323 /* Check for "msrp://" */
1324 if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0) {
1325 int address_offset, port_offset, port_end_offset;
1327 /* Address starts here */
1328 address_offset = offset + (int)strlen(msrp_res);
1330 /* Port is after next ':' */
1331 port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
1332 /* Check if port is present if not skipp */
1333 if (port_offset!= -1) {
1334 /* Port ends with '/' */
1335 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
1336 if (port_end_offset == -1) {
1337 /* No "/" look for the ";" */
1338 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');
1340 /* Attempt to convert address */
1341 if (str_to_ip((char*)tvb_get_string(wmem_packet_scope(), tvb, address_offset, port_offset-address_offset),
1342 &media_info->msrp_ipaddr)) {
1343 /* Get port number */
1344 media_info->msrp_port_number = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, port_offset + 1, port_end_offset - port_offset - 1));
1345 /* Set flag so this info can be used */
1346 media_info->msrp_transport_address_set = TRUE;
1352 /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
1353 if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
1354 /* A.5.1.3 H.223 Logical channel parameters
1355 * This property indicates the H.245
1356 * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1357 * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1358 * in ITU-T Rec. H.248.15 is used.
1363 len = (gint)strlen(attribute_value);
1364 h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
1365 /* arbitrary maximum length */
1366 /* should go through a handle, however, the two h245 entry
1367 points are different, one is over tpkt and the other is raw
1370 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1371 dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
1372 sdp_media_attribute_tree,
1373 hf_SDPh223LogicalChannelParameters);
1378 /* http://tools.ietf.org/html/rfc4568
1379 * 9.1. Generic "Crypto" Attribute Grammar
1381 * The ABNF grammar for the crypto attribute is defined below:
1383 * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
1384 * *(1*WSP session-param)
1387 * crypto-suite = 1*(ALPHA / DIGIT / "_")
1389 * key-params = key-param *(";" key-param)
1390 * key-param = key-method ":" key-info
1391 * key-method = "inline" / key-method-ext
1392 * key-method-ext = 1*(ALPHA / DIGIT / "_")
1393 * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
1394 * ; except semi-colon
1395 * session-param = 1*(VCHAR) ; visible (printing) characters
1397 * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
1401 /* We are at the first colon */
1403 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1404 if(next_offset==-1){
1405 /* XXX Add expert item? */
1408 tokenlen = next_offset - offset;
1409 proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen,
1410 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
1411 offset = next_offset + 1;
1414 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1415 if(next_offset==-1){
1416 /* XXX Add expert item? */
1419 tokenlen = next_offset - offset;
1420 parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite,
1421 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1422 if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
1424 /* XXX This may only work in simple cases */
1425 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1426 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1427 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1428 /* number of octets used for the Auth Tag in the RTP payload */
1429 transport_info->auth_tag_len = 10;
1431 master_key_length = 16; /* 128 bits = 16 octets */
1432 master_salt_length = 14; /* 112 bits = 14 octets */
1433 } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
1434 /* XXX This may only work in simple cases */
1435 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1436 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1437 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1438 /* number of octets used for the Auth Tag in the RTP payload */
1439 transport_info->auth_tag_len = 4;
1441 master_key_length = 16; /* 128 bits = 16 octets */
1442 master_salt_length = 14; /* 112 bits = 14 octets */
1443 } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
1444 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1445 /* XXX This may only work in simple cases */
1446 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
1447 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1448 /* number of octets used for the Auth Tag in the RTP payload */
1449 transport_info->auth_tag_len = 10;
1451 master_key_length = 16; /* 128 bits = 16 octets */
1452 master_salt_length = 14; /* 112 bits = 14 octets */
1454 offset = next_offset + 1;
1457 while (has_more_pars == TRUE) {
1458 int param_end_offset;
1459 tvbuff_t *key_salt_tvb;
1460 gchar *data_p = NULL;
1462 param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
1463 if (param_end_offset == -1) {
1464 has_more_pars = FALSE;
1465 param_end_offset = tvb_length(tvb);
1467 /* key-method or key-method-ext */
1468 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1469 if (next_offset == -1) {
1470 expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
1474 if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
1475 parameter_item = proto_tree_add_text(sdp_media_attribute_tree,
1476 tvb, offset, param_end_offset-offset, "Key parameters");
1477 parameter_tree = proto_item_add_subtree(parameter_item, ett_sdp_crypto_key_parameters);
1478 /* XXX only for SRTP? */
1479 /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
1480 offset = next_offset +1;
1481 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1482 if (next_offset == -1) {
1483 tokenlen = param_end_offset - offset;
1485 tokenlen = next_offset - offset;
1487 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1488 key_salt_tvb = base64_to_tvb(tvb, data_p);
1489 add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
1490 if (master_key_length != 0) {
1491 proto_tree_add_text(parameter_tree, tvb, offset, tokenlen, "Key and Salt");
1492 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
1493 key_salt_tvb, 0, master_key_length, ENC_ASCII|ENC_NA);
1494 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
1495 key_salt_tvb, master_key_length, master_salt_length, ENC_ASCII|ENC_NA);
1497 proto_tree_add_text(parameter_tree, key_salt_tvb, 0, -1, "Key and Salt");
1500 /* ["|" lifetime] ["|" mki] are optional */
1501 if (next_offset != -1) {
1502 offset = next_offset + 1;
1503 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1504 if(next_offset == -1){
1505 if(next_offset < param_end_offset){
1506 next_offset = param_end_offset;
1509 if (next_offset != -1) {
1510 /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
1511 tokenlen = next_offset - offset;
1512 proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
1513 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1514 offset = next_offset + 1;
1516 /* mki = mki-value ":" mki-length
1518 * mki-value = 1*DIGIT
1520 if(offset>param_end_offset){
1523 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1525 if (next_offset != -1) {
1526 tokenlen = next_offset - offset;
1527 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1528 offset = next_offset + 1;
1530 /* mki-length = 1*3DIGIT ; range 1..128. */
1531 next_offset = param_end_offset;
1532 tokenlen = next_offset - offset;
1534 /* This will not work if more than one parameter */
1535 /* number of octets used for the MKI in the RTP payload */
1536 transport_info->mki_len = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1537 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
1538 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1541 offset = param_end_offset;
1549 /* No special treatment for values of this attribute type, just add as one item. */
1550 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
1551 tvb, offset, -1, ENC_ASCII|ENC_NA);
1557 call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
1558 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1559 if (hf == hf_owner) {
1560 dissect_sdp_owner(tvb, ti);
1561 } else if (hf == hf_connection_info) {
1562 dissect_sdp_connection_info(tvb, ti, media_info);
1563 } else if (hf == hf_bandwidth) {
1564 dissect_sdp_bandwidth(tvb, ti);
1565 } else if (hf == hf_time) {
1566 dissect_sdp_time(tvb, ti);
1567 } else if (hf == hf_repeat_time) {
1568 dissect_sdp_repeat_time(tvb, ti);
1569 } else if (hf == hf_timezone) {
1570 dissect_sdp_timezone(tvb, ti);
1571 } else if (hf == hf_encryption_key) {
1572 dissect_sdp_encryption_key(tvb, ti);
1573 } else if (hf == hf_session_attribute) {
1574 dissect_sdp_session_attribute(tvb, pinfo, ti);
1575 } else if (hf == hf_media) {
1576 dissect_sdp_media(tvb, ti, transport_info, media_info);
1577 } else if (hf == hf_media_attribute) {
1578 dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, media_info);
1583 convert_disposable_media(transport_info_t* transport_info, disposable_media_info_t* media_info,
1584 gint start_transport_info_count)
1586 gint8 n, transport_index;
1587 guint proto_bitmask;
1589 for (n = 0; (n < media_info->media_count) && (n+start_transport_info_count < SDP_MAX_RTP_CHANNELS); n++)
1591 transport_index = n+start_transport_info_count;
1592 if (media_info->media_port[n] != NULL) {
1593 transport_info->media_port[transport_index] = (int)strtol(media_info->media_port[n], NULL, 10);
1596 if (media_info->media_proto[n] != NULL) {
1597 /* Check if media protocol is RTP
1598 * and stream decoding is enabled in preferences
1600 if (global_sdp_establish_conversation) {
1603 /* Check if media protocol is RTP */
1604 /* XXX: what about 'RTP/AVPF' or RTP/SAVPF'? */
1605 if (!strcmp(media_info->media_proto[n],"RTP/AVP")) {
1606 transport_info->proto_bitmask[transport_index] |= SDP_RTP_PROTO;
1607 proto_bitmask |= SDP_RTP_PROTO;
1609 /* Check if media protocol is SRTP */
1610 else if (!strcmp(media_info->media_proto[n],"RTP/SAVP")) {
1611 transport_info->proto_bitmask[transport_index] |= SDP_SRTP_PROTO;
1612 proto_bitmask |= SDP_SRTP_PROTO;
1614 /* Check if media protocol is T38 */
1615 else if ((!strcmp(media_info->media_proto[n],"UDPTL")) ||
1616 (!strcmp(media_info->media_proto[n],"udptl"))) {
1617 transport_info->proto_bitmask[transport_index] |= SDP_T38_PROTO;
1618 proto_bitmask |= SDP_T38_PROTO;
1620 /* Check if media protocol is MSRP/TCP */
1621 else if (!strcmp(media_info->media_proto[n],"msrp/tcp")) {
1622 transport_info->proto_bitmask[transport_index] |= SDP_MSRP_PROTO;
1623 proto_bitmask |= SDP_MSRP_PROTO;
1625 /* Check if media protocol is SPRT */
1626 else if ((!strcmp(media_info->media_proto[n],"UDPSPRT")) ||
1627 (!strcmp(media_info->media_proto[n],"udpsprt"))) {
1628 transport_info->proto_bitmask[transport_index] |= SDP_SPRT_PROTO;
1629 proto_bitmask |= SDP_SPRT_PROTO;
1632 /* now check if this stream's port==0, in which case we need to disable its paired stream */
1633 if (transport_info->media_port[transport_index] == 0) {
1634 /* This should disable the matching media session in the offer - it's a bit of a hack though,
1635 basically start_transport_info_count is 0 for the offer, and >0 for the answer, so we
1636 check that and if this is the answer, then we go set the offer's paired stream to 0.
1637 If it turns out we got a port=0 in the offer, we don't care and it's ok to let the
1638 answer have a non-port=0 (though that would be illegal per the RFCs). */
1639 if (start_transport_info_count > 0 && (proto_bitmask & transport_info->proto_bitmask[n])) {
1640 transport_info->media_port[n] = 0;
1646 if ((media_info->connection_address != NULL) &&
1647 (media_info->connection_type != NULL)) {
1648 if (strcmp(media_info->connection_type, "IP4") == 0) {
1649 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 4);
1650 if (str_to_ip(media_info->connection_address, (void*)transport_info->src_addr[transport_index].data)) {
1651 /* connection_address could be converted to a valid ipv4 address*/
1652 transport_info->proto_bitmask[transport_index] |= SDP_IPv4;
1653 transport_info->src_addr[transport_index].type = AT_IPv4;
1654 transport_info->src_addr[transport_index].len = 4;
1656 } else if (strcmp(media_info->connection_type, "IP6") == 0) {
1657 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 16);
1658 if (str_to_ip6(media_info->connection_address, (void*)transport_info->src_addr[transport_index].data)) {
1659 /* connection_address could be converted to a valid ipv6 address*/
1660 transport_info->proto_bitmask[transport_index] |= SDP_IPv6;
1661 transport_info->src_addr[transport_index].type = AT_IPv6;
1662 transport_info->src_addr[transport_index].len = 16;
1667 /* MSRP uses addresses discovered in attribute
1668 rather than connection information of media session line */
1669 if ((transport_info->proto_bitmask[transport_index] & SDP_MSRP_PROTO) &&
1670 (transport_info->proto_bitmask[transport_index] & SDP_MSRP_IPv4) &&
1672 transport_info->src_addr[transport_index].type = AT_IPv4;
1673 transport_info->src_addr[transport_index].len = 4;
1674 transport_info->src_addr[transport_index].data = wmem_memdup(wmem_file_scope(), media_info->msrp_ipaddr, 4);
1675 transport_info->media_port[transport_index] = media_info->msrp_port_number;
1678 if ((media_info->media_type[transport_index] != NULL) &&
1679 (strcmp(media_info->media_type[transport_index], "video") == 0)) {
1680 transport_info->proto_bitmask[transport_index] |= SDP_VIDEO;
1686 setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type, int request_frame)
1688 gint offset = 0, next_offset, n;
1690 gboolean in_media_description = FALSE;
1692 const int tokenoffset = 2;
1694 gint start_transport_info_count = 0;
1695 transport_info_t* transport_info = NULL;
1696 disposable_media_info_t media_info;
1698 struct srtp_info *srtp_info = NULL;
1700 /* Only do this once during first pass */
1701 if (pinfo->fd->flags.visited)
1704 memset(&media_info, 0, sizeof(media_info));
1706 if (request_frame != 0)
1707 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
1708 if (transport_info == NULL) {
1709 transport_info = wmem_new0(wmem_file_scope(), transport_info_t);
1710 transport_info->media_count = -1;
1712 for (n = 0; n < SDP_NO_OF_PT; n++) {
1713 transport_info->encoding_name[n] = (char*)UNKNOWN_ENCODING;
1715 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1716 transport_info->media[n].rtp_dyn_payload =
1717 g_hash_table_new(g_int_hash, g_int_equal);
1718 transport_info->media[n].set_rtp = FALSE;
1721 if (request_frame != 0)
1722 wmem_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info);
1725 if (exchange_type != SDP_EXCHANGE_OFFER)
1726 wmem_tree_insert32(sdp_transport_rsps, pinfo->fd->num, (void *)transport_info);
1728 /* Offer has already been answered or rejected and hash tables freed, so
1729 * don't try to add to it
1730 * XXX - Need to support "modified offers" */
1731 if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) ||
1732 (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT))
1735 if (transport_info->media_count > 0)
1736 start_transport_info_count = transport_info->media_count;
1739 * Show the SDP message a line at a time.
1741 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1743 * Find the end of the line.
1745 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1748 * Line must contain at least e.g. "v=".
1753 type = tvb_get_guint8(tvb, offset);
1754 delim = tvb_get_guint8(tvb, offset + 1);
1756 offset = next_offset;
1761 * Attributes. Only care about ones that affect the transport. Ignore others.
1765 hf = hf_connection_info;
1770 /* Increase the count of media channels, but don't walk off the end of the arrays. */
1771 if (((transport_info->media_count < 0) && (in_media_description == FALSE)) || (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)))
1772 transport_info->media_count++;
1774 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
1775 media_info.media_count++;
1777 in_media_description = TRUE;
1780 if (in_media_description) {
1781 hf = hf_media_attribute;
1783 hf = hf_session_attribute;
1791 if (hf != hf_unknown)
1793 call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
1794 linelen - tokenoffset,
1795 linelen - tokenoffset),
1797 hf, NULL, linelen-tokenoffset, transport_info, &media_info);
1800 offset = next_offset;
1803 if (in_media_description) {
1804 /* Increase the count of media channels, but don't walk off the end of the arrays. */
1805 if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1))
1806 transport_info->media_count++;
1807 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
1808 media_info.media_count++;
1811 /* Take all of the collected strings and convert them into something permanent
1812 * for the life of the capture
1814 convert_disposable_media(transport_info, &media_info, start_transport_info_count);
1816 /* We have a successful negotiation, apply data to their respective protocols */
1817 if ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
1818 (transport_info->sdp_status == SDP_EXCHANGE_OFFER)) {
1819 for (n = 0; n <= transport_info->media_count; n++) {
1820 guint32 current_rtp_port = 0;
1822 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
1823 if ((transport_info->media_port[n] != 0) &&
1824 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
1825 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
1826 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
1827 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
1828 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
1829 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
1830 srtp_info->auth_algorithm = transport_info->auth_algorithm;
1831 srtp_info->mki_len = transport_info->mki_len;
1832 srtp_info->auth_tag_len = transport_info->auth_tag_len;
1835 /* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number,
1836 because that's where the RTP flow started, and thus conversation needs to check against */
1837 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", request_frame,
1838 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
1839 transport_info->media[n].rtp_dyn_payload, srtp_info);
1841 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", request_frame,
1842 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
1843 transport_info->media[n].rtp_dyn_payload);
1845 transport_info->media[n].set_rtp = TRUE;
1846 /* SPRT might use the same port... */
1847 current_rtp_port = transport_info->media_port[n];
1850 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
1851 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", request_frame, srtp_info);
1853 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", request_frame);
1858 /* add SPRT conversation */
1859 if ((transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
1860 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
1863 if (transport_info->media_port[n] == 0 && current_rtp_port) {
1864 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
1865 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
1867 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
1871 /* Add t38 conversation, if available and only if no rtp */
1872 if ((transport_info->media_port[n] != 0) &&
1873 !transport_info->media[n].set_rtp &&
1874 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
1875 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
1876 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
1879 /* Add MSRP conversation. Uses addresses discovered in attribute
1880 rather than connection information of media session line
1881 (already handled in media conversion) */
1882 if ((transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
1883 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
1885 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
1888 /* Free the hash table if we did't assigned it to a conv use it */
1889 if (!transport_info->media[n].set_rtp)
1891 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1892 transport_info->media[n].rtp_dyn_payload = NULL;
1896 /* Free the remaining hash tables not used */
1897 if (transport_info->media_count == -1)
1899 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
1901 if (!transport_info->media[n].set_rtp)
1903 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1904 transport_info->media[n].rtp_dyn_payload = NULL;
1910 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
1912 if (!transport_info->media[n].set_rtp)
1914 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1915 transport_info->media[n].rtp_dyn_payload = NULL;
1919 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_ACCEPT;
1921 } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) &&
1922 (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)){
1924 /* Free the hash tables, since they won't be put to use */
1925 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
1927 if (!transport_info->media[n].set_rtp)
1929 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1930 transport_info->media[n].rtp_dyn_payload = NULL;
1934 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT;
1938 void setup_sdp_transport_resend(int current_frame, int request_frame)
1940 transport_info_t* transport_info = NULL;
1942 if (request_frame != 0) {
1943 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
1944 if (transport_info != NULL) {
1945 wmem_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info);
1951 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1953 proto_tree *sdp_tree;
1954 proto_item *ti, *sub_ti;
1955 gint offset = 0, next_offset, n, i;
1957 gboolean in_media_description;
1959 int datalen, tokenoffset, hf = -1;
1962 transport_info_t local_transport_info;
1963 transport_info_t* transport_info = NULL;
1964 disposable_media_info_t media_info;
1966 sdp_packet_info *sdp_pi;
1967 struct srtp_info *srtp_info = NULL;
1969 /* Initialise packet info for passing to tap */
1970 sdp_pi = wmem_new(wmem_packet_scope(), sdp_packet_info);
1971 sdp_pi->summary_str[0] = '\0';
1973 if (!pinfo->fd->flags.visited) {
1974 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->fd->num );
1976 if (transport_info == NULL) {
1977 /* Can't find it in the requests, make sure it's not a response */
1978 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_rsps, pinfo->fd->num );
1982 if (transport_info == NULL) {
1983 transport_info = &local_transport_info;
1986 /* Initialize local transport info */
1987 memset(&local_transport_info, 0, sizeof(local_transport_info));
1988 local_transport_info.media_count = -1;
1990 for (n = 0; n < SDP_NO_OF_PT; n++) {
1991 local_transport_info.encoding_name[n] = (char*)UNKNOWN_ENCODING;
1993 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1994 local_transport_info.media[n].rtp_dyn_payload =
1995 g_hash_table_new(g_int_hash, g_int_equal);
1996 local_transport_info.media[n].set_rtp = FALSE;
1999 memset(&media_info, 0, sizeof(media_info));
2002 * As RFC 2327 says, "SDP is purely a format for session
2003 * description - it does not incorporate a transport protocol,
2004 * and is intended to use different transport protocols as
2005 * appropriate including the Session Announcement Protocol,
2006 * Session Initiation Protocol, Real-Time Streaming Protocol,
2007 * electronic mail using the MIME extensions, and the
2008 * Hypertext Transport Protocol."
2010 * We therefore don't set the protocol or info columns;
2011 * instead, we append to them, so that we don't erase
2012 * what the protocol inside which the SDP stuff resides
2015 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
2017 /* XXX: Needs description.
2018 * Putting with session description in info col is redundant when it's in the
2019 * protocol col in my opinion, commenting it out for now 2012-10-09. Remove if no one complains.
2020 * If some one want it consider " ,with SDP"
2022 /*col_append_str(pinfo->cinfo, COL_INFO, ", with session description");*/
2024 ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA);
2025 sdp_tree = proto_item_add_subtree(ti, ett_sdp);
2028 * Show the SDP message a line at a time.
2030 in_media_description = FALSE;
2032 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2034 * Find the end of the line.
2036 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
2039 * Line must contain at least e.g. "v=".
2044 type = tvb_get_guint8(tvb, offset);
2045 delim = tvb_get_guint8(tvb, offset + 1);
2047 proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_ASCII|ENC_NA);
2048 expert_add_info(pinfo, ti2, &ei_sdp_invalid_line);
2049 offset = next_offset;
2058 hf = hf_protocol_version;
2064 hf = hf_session_name;
2067 if (in_media_description) {
2068 hf = hf_media_title;
2070 hf = hf_session_info;
2083 hf = hf_connection_info;
2092 hf = hf_repeat_time;
2097 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2098 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2099 local_transport_info.media_count++;
2101 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
2102 media_info.media_count++;
2104 in_media_description = TRUE;
2107 hf = hf_encryption_key;
2110 if (in_media_description) {
2111 hf = hf_media_attribute;
2113 hf = hf_session_attribute;
2124 if (hf == hf_unknown)
2126 string = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset + tokenoffset,
2127 linelen - tokenoffset);
2128 sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
2131 call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
2132 linelen - tokenoffset,
2133 linelen - tokenoffset),
2135 hf, sub_ti, linelen-tokenoffset,
2136 &local_transport_info, &media_info);
2138 offset = next_offset;
2141 if (in_media_description) {
2142 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2143 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2144 local_transport_info.media_count++;
2145 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2146 media_info.media_count++;
2149 /* Take all of the collected strings and convert them into something permanent
2150 * for the life of the capture
2152 if (transport_info == &local_transport_info)
2153 convert_disposable_media(transport_info, &media_info, 0);
2155 for (n = 0; n < local_transport_info.media_count; n++)
2157 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2158 /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
2159 * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers
2160 * use setup_sdp_transport(), this should be removed
2162 guint32 current_rtp_port = 0;
2164 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2165 (transport_info->media_port[n] != 0) &&
2166 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
2167 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
2168 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2169 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
2170 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
2171 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
2172 srtp_info->auth_algorithm = transport_info->auth_algorithm;
2173 srtp_info->mki_len = transport_info->mki_len;
2174 srtp_info->auth_tag_len = transport_info->auth_tag_len;
2176 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2177 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2178 transport_info->media[n].rtp_dyn_payload, srtp_info);
2180 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2181 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2182 transport_info->media[n].rtp_dyn_payload);
2184 transport_info->media[n].set_rtp = TRUE;
2185 /* SPRT might use the same port... */
2186 current_rtp_port = transport_info->media_port[n];
2189 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2190 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
2192 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
2197 /* add SPRT conversation */
2198 /* XXX - more placeholder functionality */
2199 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2200 (transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
2201 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
2204 if (transport_info->media_port[n] == 0 && current_rtp_port) {
2205 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
2206 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
2208 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2212 /* Add t38 conversation, if available and only if no rtp */
2213 /* XXX - more placeholder functionality */
2214 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2215 (transport_info->media_port[n] != 0) &&
2216 !transport_info->media[n].set_rtp &&
2217 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
2218 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
2219 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2222 /* Add MSRP conversation. Uses addresses discovered in attribute
2223 rather than connection information of media session line */
2224 /* XXX - more placeholder functionality */
2225 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2226 (transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
2227 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
2229 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
2232 if (local_transport_info.media_port[n] != 0) {
2233 /* Create the RTP summary str for the Voip Call analysis.
2234 * XXX - Currently this is based only on the current packet
2236 for (i = 0; i < local_transport_info.media[n].pt_count; i++)
2238 /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
2239 if ((local_transport_info.media[n].pt[i] >= 96) && (local_transport_info.media[n].pt[i] <= 127)) {
2240 encoding_name_and_rate_t *encoding_name_and_rate_pt =
2241 (encoding_name_and_rate_t *)g_hash_table_lookup(
2242 local_transport_info.media[n].rtp_dyn_payload,
2243 &local_transport_info.media[n].pt[i]);
2244 if (encoding_name_and_rate_pt) {
2245 if (strlen(sdp_pi->summary_str))
2246 g_strlcat(sdp_pi->summary_str, " ", 50);
2247 g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
2250 g_snprintf(num_pt, 10, "%u", local_transport_info.media[n].pt[i]);
2251 if (strlen(sdp_pi->summary_str))
2252 g_strlcat(sdp_pi->summary_str, " ", 50);
2253 g_strlcat(sdp_pi->summary_str, num_pt, 50);
2256 if (strlen(sdp_pi->summary_str))
2257 g_strlcat(sdp_pi->summary_str, " ", 50);
2258 g_strlcat(sdp_pi->summary_str,
2259 val_to_str_ext(local_transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"),
2265 /* Free the hash table if we did't assigned it to a conv use it */
2266 /* XXX - more placeholder functionality */
2267 if ((transport_info == &local_transport_info) &&
2268 !transport_info->media[n].set_rtp)
2270 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
2271 transport_info->media[n].rtp_dyn_payload = NULL;
2274 /* Create the T38 summary str for the Voip Call analysis
2275 * XXX - Currently this is based only on the current packet
2277 if ((local_transport_info.media_port[n] != 0) &&
2278 (local_transport_info.proto_bitmask[n] & SDP_T38_PROTO)) {
2279 if (strlen(sdp_pi->summary_str))
2280 g_strlcat(sdp_pi->summary_str, " ", 50);
2281 g_strlcat(sdp_pi->summary_str, "t38", 50);
2285 /* Free the remainded hash tables not used */
2286 /* XXX - more placeholder functionality */
2287 if (transport_info == &local_transport_info) {
2288 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
2290 if (!transport_info->media[n].set_rtp)
2292 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
2293 transport_info->media[n].rtp_dyn_payload = NULL;
2298 datalen = tvb_length_remaining(tvb, offset);
2300 proto_tree_add_text(sdp_tree, tvb, offset, datalen, "Data (%d bytes)", datalen);
2302 /* Report this packet to the tap */
2303 tap_queue_packet(sdp_tap, pinfo, sdp_pi);
2307 proto_register_sdp(void)
2309 static hf_register_info hf[] = {
2310 { &hf_protocol_version,
2311 { "Session Description Protocol Version (v)", "sdp.version",
2312 FT_STRING, BASE_NONE, NULL, 0x0,
2316 { "Owner/Creator, Session Id (o)",
2317 "sdp.owner", FT_STRING, BASE_NONE, NULL,
2321 { "Session Name (s)", "sdp.session_name",
2322 FT_STRING, BASE_NONE, NULL, 0x0,
2326 { "Session Information (i)", "sdp.session_info",
2327 FT_STRING, BASE_NONE, NULL, 0x0,
2331 { "URI of Description (u)", "sdp.uri",
2332 FT_STRING, BASE_NONE, NULL, 0x0,
2336 { "E-mail Address (e)", "sdp.email",
2337 FT_STRING, BASE_NONE, NULL, 0x0,
2338 "E-mail Address", HFILL }
2341 { "Phone Number (p)", "sdp.phone",
2342 FT_STRING, BASE_NONE, NULL, 0x0,
2345 { &hf_connection_info,
2346 { "Connection Information (c)", "sdp.connection_info",
2347 FT_STRING, BASE_NONE, NULL, 0x0,
2351 { "Bandwidth Information (b)", "sdp.bandwidth",
2352 FT_STRING, BASE_NONE, NULL, 0x0,
2356 { "Time Zone Adjustments (z)", "sdp.timezone",
2357 FT_STRING, BASE_NONE, NULL, 0x0,
2360 { &hf_encryption_key,
2361 { "Encryption Key (k)", "sdp.encryption_key",
2362 FT_STRING, BASE_NONE, NULL, 0x0,
2365 { &hf_session_attribute,
2366 { "Session Attribute (a)", "sdp.session_attr",
2367 FT_STRING, BASE_NONE, NULL, 0x0,
2370 { &hf_media_attribute,
2371 { "Media Attribute (a)", "sdp.media_attr",
2372 FT_STRING, BASE_NONE, NULL, 0x0,
2376 { "Time Description, active time (t)",
2377 "sdp.time", FT_STRING, BASE_NONE, NULL,
2381 { "Repeat Time (r)", "sdp.repeat_time",
2382 FT_STRING, BASE_NONE, NULL, 0x0,
2386 { "Media Description, name and address (m)",
2387 "sdp.media", FT_STRING, BASE_NONE, NULL,
2391 { "Media Title (i)", "sdp.media_title",
2392 FT_STRING, BASE_NONE, NULL, 0x0,
2393 "Media Title", HFILL }
2396 { "Unknown", "sdp.unknown",
2397 FT_STRING, BASE_NONE, NULL, 0x0,
2401 { "Invalid line", "sdp.invalid",
2402 FT_STRING, BASE_NONE, NULL, 0x0,
2405 { &hf_owner_username,
2406 { "Owner Username", "sdp.owner.username",
2407 FT_STRING, BASE_NONE, NULL, 0x0,
2410 { &hf_owner_sessionid,
2411 { "Session ID", "sdp.owner.sessionid",
2412 FT_STRING, BASE_NONE, NULL, 0x0,
2415 { &hf_owner_version,
2416 { "Session Version", "sdp.owner.version",
2417 FT_STRING, BASE_NONE, NULL, 0x0,
2420 { &hf_owner_network_type,
2421 { "Owner Network Type", "sdp.owner.network_type",
2422 FT_STRING, BASE_NONE, NULL, 0x0,
2425 { &hf_owner_address_type,
2426 { "Owner Address Type", "sdp.owner.address_type",
2427 FT_STRING, BASE_NONE, NULL, 0x0,
2430 { &hf_owner_address,
2431 { "Owner Address", "sdp.owner.address",
2432 FT_STRING, BASE_NONE, NULL, 0x0,
2435 { &hf_connection_info_network_type,
2436 { "Connection Network Type", "sdp.connection_info.network_type",
2437 FT_STRING, BASE_NONE, NULL, 0x0,
2440 { &hf_connection_info_address_type,
2441 { "Connection Address Type", "sdp.connection_info.address_type",
2442 FT_STRING, BASE_NONE, NULL, 0x0,
2445 { &hf_connection_info_connection_address,
2446 { "Connection Address", "sdp.connection_info.address",
2447 FT_STRING, BASE_NONE, NULL, 0x0,
2450 { &hf_connection_info_ttl,
2451 { "Connection TTL", "sdp.connection_info.ttl",
2452 FT_STRING, BASE_NONE, NULL, 0x0,
2455 { &hf_connection_info_num_addr,
2456 { "Connection Number of Addresses", "sdp.connection_info.num_addr",
2457 FT_STRING, BASE_NONE, NULL, 0x0,
2460 { &hf_bandwidth_modifier,
2461 { "Bandwidth Modifier", "sdp.bandwidth.modifier",
2462 FT_STRING, BASE_NONE, NULL, 0x0,
2465 { &hf_bandwidth_value,
2466 { "Bandwidth Value", "sdp.bandwidth.value",
2467 FT_STRING, BASE_NONE, NULL, 0x0,
2468 "Bandwidth Value (in kbits/s)", HFILL }
2471 { "Session Start Time", "sdp.time.start",
2472 FT_STRING, BASE_NONE, NULL, 0x0,
2476 { "Session Stop Time", "sdp.time.stop",
2477 FT_STRING, BASE_NONE, NULL, 0x0,
2480 { &hf_repeat_time_interval,
2481 { "Repeat Interval", "sdp.repeat_time.interval",
2482 FT_STRING, BASE_NONE, NULL, 0x0,
2485 { &hf_repeat_time_duration,
2486 { "Repeat Duration", "sdp.repeat_time.duration",
2487 FT_STRING, BASE_NONE, NULL, 0x0,
2490 { &hf_repeat_time_offset,
2491 { "Repeat Offset", "sdp.repeat_time.offset",
2492 FT_STRING, BASE_NONE, NULL, 0x0,
2495 { &hf_timezone_time,
2496 { "Timezone Time", "sdp.timezone.time",
2497 FT_STRING, BASE_NONE, NULL, 0x0,
2500 { &hf_timezone_offset,
2501 { "Timezone Offset", "sdp.timezone.offset",
2502 FT_STRING, BASE_NONE, NULL, 0x0,
2505 { &hf_encryption_key_type,
2506 { "Key Type", "sdp.encryption_key.type",
2507 FT_STRING, BASE_NONE, NULL, 0x0,
2510 { &hf_encryption_key_data,
2511 { "Key Data", "sdp.encryption_key.data",
2512 FT_STRING, BASE_NONE, NULL, 0x0,
2515 { &hf_session_attribute_field,
2516 { "Session Attribute Fieldname", "sdp.session_attr.field",
2517 FT_STRING, BASE_NONE, NULL, 0x0,
2520 { &hf_session_attribute_value,
2521 { "Session Attribute Value", "sdp.session_attr.value",
2522 FT_STRING, BASE_NONE, NULL, 0x0,
2526 { "Media Type", "sdp.media.media",
2527 FT_STRING, BASE_NONE, NULL, 0x0,
2531 { "Media Port", "sdp.media.port",
2532 FT_UINT16, BASE_DEC, NULL, 0x0,
2535 { &hf_media_portcount,
2536 { "Media Port Count", "sdp.media.portcount",
2537 FT_STRING, BASE_NONE, NULL, 0x0,
2541 { "Media Protocol", "sdp.media.proto",
2542 FT_STRING, BASE_NONE, NULL, 0x0,
2546 { "Media Format", "sdp.media.format",
2547 FT_STRING, BASE_NONE, NULL, 0x0,
2550 { &hf_media_attribute_field,
2551 { "Media Attribute Fieldname", "sdp.media_attribute.field",
2552 FT_STRING, BASE_NONE, NULL, 0x0,
2555 { &hf_media_attribute_value,
2556 { "Media Attribute Value", "sdp.media_attribute.value",
2557 FT_STRING, BASE_NONE, NULL, 0x0,
2560 { &hf_media_encoding_name,
2561 { "MIME Type", "sdp.mime.type",
2562 FT_STRING, BASE_NONE, NULL, 0x0,
2563 "SDP MIME Type", HFILL }
2565 { &hf_media_sample_rate,
2566 { "Sample Rate", "sdp.sample_rate",
2567 FT_STRING, BASE_NONE, NULL, 0x0,
2570 { &hf_media_format_specific_parameter,
2571 { "Media format specific parameters", "sdp.fmtp.parameter",
2572 FT_STRING, BASE_NONE, NULL, 0x0,
2573 "Format specific parameter(fmtp)", HFILL }
2575 { &hf_ipbcp_version,
2576 { "IPBCP Protocol Version", "sdp.ipbcp.version",
2577 FT_STRING, BASE_NONE, NULL, 0x0,
2581 { "IPBCP Command Type", "sdp.ipbcp.command",
2582 FT_STRING, BASE_NONE, NULL, 0x0,
2585 {&hf_sdp_fmtp_mpeg4_profile_level_id,
2586 { "Level Code", "sdp.fmtp.profile_level_id",
2587 FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0,
2590 { &hf_sdp_fmtp_h263_profile,
2591 { "Profile", "sdp.fmtp.h263profile",
2592 FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0,
2595 { &hf_sdp_fmtp_h263_level,
2596 { "Level", "sdp.fmtp.h263level",
2597 FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0,
2600 { &hf_sdp_h264_packetization_mode,
2601 { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
2602 FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0,
2605 { &hf_SDPh223LogicalChannelParameters,
2606 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
2607 FT_NONE, BASE_NONE, NULL, 0,
2610 { &hf_key_mgmt_att_value,
2611 { "Key Management", "sdp.key_mgmt",
2612 FT_STRING, BASE_NONE, NULL, 0x0,
2615 { &hf_key_mgmt_prtcl_id,
2616 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
2617 FT_STRING, BASE_NONE, NULL, 0x0,
2620 { &hf_key_mgmt_data,
2621 { "Key Management Data", "sdp.key_mgmt.data",
2622 FT_BYTES, BASE_NONE, NULL, 0x0,
2625 { &hf_sdp_crypto_tag,
2626 { "tag", "sdp.crypto.tag",
2627 FT_UINT32, BASE_DEC, NULL, 0x0,
2630 { &hf_sdp_crypto_crypto_suite,
2631 { "Crypto suite", "sdp.crypto.crypto_suite",
2632 FT_STRING, BASE_NONE, NULL, 0x0,
2635 { &hf_sdp_crypto_master_key,
2636 { "Master Key", "sdp.crypto.master_key",
2637 FT_BYTES, BASE_NONE, NULL, 0x0,
2640 { &hf_sdp_crypto_master_salt,
2641 { "Master salt", "sdp.crypto.master_salt",
2642 FT_BYTES, BASE_NONE, NULL, 0x0,
2645 { &hf_sdp_crypto_lifetime,
2646 { "Lifetime", "sdp.crypto.lifetime",
2647 FT_STRING, BASE_NONE, NULL, 0x0,
2650 { &hf_sdp_crypto_mki,
2651 { "mki-value", "sdp.crypto.mki-valu",
2652 FT_STRING, BASE_NONE, NULL, 0x0,
2655 { &hf_sdp_crypto_mki_length,
2656 { "mki_length", "sdp.crypto.mki_length",
2657 FT_STRING, BASE_NONE, NULL, 0x0,
2661 static gint *ett[] = {
2664 &ett_sdp_connection_info,
2667 &ett_sdp_repeat_time,
2669 &ett_sdp_encryption_key,
2670 &ett_sdp_session_attribute,
2672 &ett_sdp_media_attribute,
2675 &ett_sdp_crypto_key_parameters,
2678 static ei_register_info ei[] = {
2679 { &ei_sdp_invalid_key_param, { "sdp.invalid_key_param", PI_MALFORMED, PI_NOTE, "Invalid key-param (no ':' delimiter)", EXPFILL }},
2680 { &ei_sdp_invalid_line, { "sdp.invalid_line", PI_MALFORMED, PI_NOTE, "Invalid SDP line (no '=' delimiter)", EXPFILL }},
2683 module_t *sdp_module;
2684 expert_module_t* expert_sdp;
2686 proto_sdp = proto_register_protocol("Session Description Protocol",
2688 proto_register_field_array(proto_sdp, hf, array_length(hf));
2689 proto_register_subtree_array(ett, array_length(ett));
2690 expert_sdp = expert_register_protocol(proto_sdp);
2691 expert_register_field_array(expert_sdp, ei, array_length(ei));
2693 key_mgmt_dissector_table = register_dissector_table("key_mgmt",
2694 "Key Management", FT_STRING, BASE_NONE);
2696 * Preferences registration
2698 sdp_module = prefs_register_protocol(proto_sdp, NULL);
2699 prefs_register_bool_preference(sdp_module, "establish_conversation",
2700 "Establish Media Conversation",
2701 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
2702 "upon port numbers found in SDP payload",
2703 &global_sdp_establish_conversation);
2705 sdp_transport_reqs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
2706 sdp_transport_rsps = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
2709 * Register the dissector by name, so other dissectors can
2710 * grab it by name rather than just referring to it directly.
2712 register_dissector("sdp", dissect_sdp, proto_sdp);
2714 /* Register for tapping */
2715 sdp_tap = register_tap("sdp");
2719 proto_reg_handoff_sdp(void)
2721 dissector_handle_t sdp_handle;
2723 rtcp_handle = find_dissector("rtcp");
2724 msrp_handle = find_dissector("msrp");
2725 sprt_handle = find_dissector("sprt");
2726 h264_handle = find_dissector("h264");
2727 mp4ves_handle = find_dissector("mp4ves");
2729 proto_sprt = dissector_handle_get_protocol_index(find_dissector("sprt"));
2731 sdp_handle = find_dissector("sdp");
2732 dissector_add_string("media_type", "application/sdp", sdp_handle);
2733 dissector_add_uint("bctp.tpi", 0x20, sdp_handle);