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
29 #include <epan/packet.h>
30 #include <epan/exceptions.h>
31 #include <epan/asn1.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
35 #include <epan/rtp_pt.h>
36 #include <epan/show_exception.h>
37 #include <epan/addr_resolv.h>
39 #include "packet-sdp.h"
41 /* un-comment the following as well as this line in conversation.c, to enable debug printing */
42 /* #define DEBUG_CONVERSATION */
43 #include "conversation_debug.h"
45 #include "packet-rtp.h"
47 #include "packet-rtcp.h"
48 #include "packet-t38.h"
49 #include "packet-msrp.h"
50 #include "packet-sprt.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_port_string = -1;
143 static int hf_media_portcount = -1;
144 static int hf_media_proto = -1;
145 static int hf_media_format = -1;
147 /* hf_session_attribute subfields */
148 static int hf_media_attribute_field = -1;
149 static int hf_media_attribute_value = -1;
150 static int hf_media_encoding_name = -1;
151 static int hf_media_sample_rate = -1;
152 static int hf_media_format_specific_parameter = -1;
153 static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
154 static int hf_sdp_fmtp_h263_profile = -1;
155 static int hf_sdp_fmtp_h263_level = -1;
156 static int hf_sdp_h264_packetization_mode = -1;
157 static int hf_SDPh223LogicalChannelParameters = -1;
159 /* hf_session_attribute hf_media_attribute subfields */
160 static int hf_key_mgmt_att_value = -1;
161 static int hf_key_mgmt_prtcl_id = -1;
162 static int hf_key_mgmt_data = -1;
164 static int hf_sdp_crypto_tag = -1;
165 static int hf_sdp_crypto_crypto_suite = -1;
166 static int hf_sdp_crypto_master_key = -1;
167 static int hf_sdp_crypto_master_salt = -1;
168 static int hf_sdp_crypto_lifetime = -1;
169 static int hf_sdp_crypto_mki = -1;
170 static int hf_sdp_crypto_mki_length = -1;
172 /* Generated from convert_proto_tree_add_text.pl */
173 static int hf_sdp_nal_unit_2_string = -1;
174 static int hf_sdp_key_and_salt = -1;
175 static int hf_sdp_nal_unit_1_string = -1;
176 static int hf_sdp_data = -1;
179 static int ett_sdp = -1;
180 static int ett_sdp_owner = -1;
181 static int ett_sdp_connection_info = -1;
182 static int ett_sdp_bandwidth = -1;
183 static int ett_sdp_time = -1;
184 static int ett_sdp_repeat_time = -1;
185 static int ett_sdp_timezone = -1;
186 static int ett_sdp_encryption_key = -1;
187 static int ett_sdp_session_attribute = -1;
188 static int ett_sdp_media = -1;
189 static int ett_sdp_media_attribute = -1;
190 static int ett_sdp_fmtp = -1;
191 static int ett_sdp_key_mgmt = -1;
192 static int ett_sdp_crypto_key_parameters = -1;
194 static expert_field ei_sdp_invalid_key_param = EI_INIT;
195 static expert_field ei_sdp_invalid_line_equal = EI_INIT;
196 static expert_field ei_sdp_invalid_line_fields = EI_INIT;
197 static expert_field ei_sdp_invalid_line_space = EI_INIT;
198 static expert_field ei_sdp_invalid_conversion = EI_INIT;
200 /* patterns used for tvb_ws_mempbrk_pattern_guint8 */
201 static ws_mempbrk_pattern pbrk_digits;
202 static ws_mempbrk_pattern pbrk_alpha;
204 #define SDP_RTP_PROTO 0x00000001
205 #define SDP_SRTP_PROTO 0x00000002
206 #define SDP_T38_PROTO 0x00000004
207 #define SDP_MSRP_PROTO 0x00000008
208 #define SDP_SPRT_PROTO 0x00000010
209 #define SDP_IPv4 0x80000000
210 #define SDP_IPv6 0x40000000
211 #define SDP_MSRP_IPv4 0x20000000
212 #define SDP_VIDEO 0x10000000
215 #define SDP_MAX_RTP_CHANNELS 4
216 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
217 #define SDP_NO_OF_PT 128
219 gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
221 rtp_dyn_payload_t *rtp_dyn_payload;
223 } transport_media_pt_t;
226 enum sdp_exchange_type sdp_status;
227 char *encoding_name[SDP_NO_OF_PT];
228 int sample_rate[SDP_NO_OF_PT];
229 int media_port[SDP_MAX_RTP_CHANNELS];
230 address src_addr[SDP_MAX_RTP_CHANNELS];
231 guint proto_bitmask[SDP_MAX_RTP_CHANNELS];
232 transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
234 /* SRTP related info XXX note currently we only handle one crypto line in the SDP
235 * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
236 * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
237 * and the SDP dissector just provide the relevant data.
238 * YES! packet-sdp.c should be about SDP parsing... SDP *state* needs to be maintained by upper
239 * protocols, because each one has different rules/semantics.
241 guint encryption_algorithm;
242 guint auth_algorithm;
243 guint mki_len; /* number of octets used for the MKI in the RTP payload */
244 guint auth_tag_len; /* number of octets used for the Auth Tag in the RTP payload */
247 /* Data that is retrieved from a packet, but does not need to be kept */
249 char *connection_address; /* there should actually be SDP_MAX_RTP_CHANNELS of these too */
250 char *connection_type;
251 /* media_type is for 'audio', 'video', etc, so per-stream */
252 char *media_type[SDP_MAX_RTP_CHANNELS];
253 char *media_port[SDP_MAX_RTP_CHANNELS];
254 char *media_proto[SDP_MAX_RTP_CHANNELS];
257 /* MSRP transport info (as set while parsing path attribute) */
258 gboolean msrp_transport_address_set;
259 guint32 msrp_ipaddr[4];
260 guint16 msrp_port_number;
262 } disposable_media_info_t;
265 /* here lie the debugging dumper functions */
266 #ifdef DEBUG_CONVERSATION
267 static void sdp_dump_transport_media(const transport_media_pt_t* media) {
270 DPRINT2(("transport_media contents:"));
273 DPRINT2(("null transport_media_pt_t*"));
277 count = (int)media->pt_count;
278 DPRINT2(("pt_count=%d",count));
280 for (i=0; i < count; i++) {
281 DPRINT2(("pt=%d", media->pt[i]));
284 DPRINT2(("rtp_dyn_payload hashtable=%s", media->rtp_dyn_payload ? "YES" : "NO"));
285 if (media->rtp_dyn_payload) {
286 rtp_dump_dyn_payload(media->rtp_dyn_payload);
288 DPRINT2(("set_rtp=%s", media->set_rtp ? "TRUE" : "FALSE"));
292 static const value_string sdp_exchange_type_vs[] = {
293 { SDP_EXCHANGE_OFFER, "SDP_EXCHANGE_OFFER" },
294 { SDP_EXCHANGE_ANSWER_ACCEPT, "SDP_EXCHANGE_ANSWER_ACCEPT" },
295 { SDP_EXCHANGE_ANSWER_REJECT, "SDP_EXCHANGE_ANSWER_REJECT" },
299 static void sdp_dump_transport_info(const transport_info_t* info) {
302 DPRINT2(("transport_info contents:"));
305 DPRINT2(("null transport_info_t*"));
309 DPRINT2(("sdp_status=%s",
310 val_to_str(info->sdp_status, sdp_exchange_type_vs, "SDP_EXCHANGE_UNKNOWN")));
311 DPRINT2(("payload type contents:"));
313 for (i=0; i < SDP_NO_OF_PT; i++) {
314 /* don't print out unknown encodings */
315 if (info->encoding_name[i] &&
316 strcmp(UNKNOWN_ENCODING,info->encoding_name[i]) != 0) {
317 DPRINT2(("payload type #%d:",i));
319 DPRINT2(("encoding_name=%s", info->encoding_name[i]));
320 DPRINT2(("sample_rate=%d", info->sample_rate[i]));
325 count = (int)info->media_count;
326 DPRINT2(("media_count=%d", count));
327 DPRINT2(("rtp channels:"));
329 for (i=0; i <= count; i++) {
330 DPRINT2(("channel #%d:",i));
332 DPRINT2(("src_addr=%s",
333 address_to_str(wmem_packet_scope(), &(info->src_addr[i]))));
334 DPRINT2(("media_port=%d", info->media_port[i]));
335 DPRINT2(("proto_bitmask=%x", info->proto_bitmask[i]));
336 sdp_dump_transport_media(&(info->media[i]));
340 DPRINT2(("encryption_algorithm=%u", info->encryption_algorithm));
341 DPRINT2(("auth_algorithm=%u", info->auth_algorithm));
342 if (info->encryption_algorithm || info->auth_algorithm) {
343 DPRINT2(("mki_len=%u", info->mki_len));
344 if (info->auth_algorithm) {
345 DPRINT2(("auth_tag_len=%u", info->auth_tag_len));
351 static void sdp_dump_disposable_media_info(const disposable_media_info_t* info) {
354 DPRINT2(("disposable_media_info contents:"));
357 DPRINT2(("null disposable_media_info_t*"));
361 DPRINT2(("connection_address=%s",
362 info->connection_address ? info->connection_address : "NULL"));
363 DPRINT2(("connection_type=%s",
364 info->connection_type ? info->connection_type : "NULL"));
365 count = (int)info->media_count;
366 DPRINT2(("media_count=%d",count));
368 for (i=0; i < count; i++) {
369 DPRINT2(("media #%d:",i));
371 DPRINT2(("media_type=%s", info->media_type[i] ? info->media_type[i] : "NULL"));
372 DPRINT2(("media_port=%s", info->media_port[i] ? info->media_port[i] : "NULL"));
373 DPRINT2(("media_proto=%s", info->media_proto[i] ? info->media_proto[i] : "NULL"));
377 DPRINT2(("msrp_transport_address_set=%s",
378 info->msrp_transport_address_set ? "TRUE" : "FALSE"));
379 if (info->msrp_transport_address_set) {
381 DPRINT2(("msrp_ipaddr=%u.%u.%u.%u",
382 info->msrp_ipaddr[0],info->msrp_ipaddr[1],
383 info->msrp_ipaddr[2],info->msrp_ipaddr[3]));
384 DPRINT2(("msrp_port_number=%hu",info->msrp_port_number));
389 #endif /* DEBUG_CONVERSATION */
392 /* key-mgmt dissector
394 * http://www.iana.org/assignments/sdp-parameters
396 static dissector_table_t key_mgmt_dissector_table;
398 /* Finds next token (sequence of non-space chars) in tvb from given offset.
399 * The returned value is the token length, or 0 if none found.
400 * The offset is changed to be the starting offset, in case there were one or more
401 * spaces at the beginning. (this will also add expert info in such a case)
402 * The next_offset is set to the next found space after the token, or -1 if the
403 * end of line is hit or no token found.
404 * If this is the last token in the line, tokenlen will not be 0, but next_offset
407 * The optional param, if TRUE, means no expert error will be issued if no token
408 * is found; if FALSE then a expert error will be issued if no token is found.
410 * This function expects to be given a tvb of only one line, and does no error
411 * checking of its given arguments.
414 find_next_optional_token_in_line(tvbuff_t *tvb, proto_tree *tree,
415 gint *offset, gint *next_offset,
416 const gboolean optional)
422 if (tvb_offset_exists(tvb, off)) {
423 while (tokenlen == 0) {
424 next_off = tvb_find_guint8(tvb, off, -1, ' ');
425 if (next_off == -1) {
426 tokenlen = tvb_captured_length_remaining(tvb, off);
427 break; /* Nothing more left */
430 tokenlen = next_off - off;
433 /* two spaces in a row - illegal, but we'll keep dissecting */
434 proto_tree_add_expert(tree, NULL, &ei_sdp_invalid_line_space, tvb, off-1, 2);
440 if (!optional && tokenlen == 0) {
441 proto_tree_add_expert(tree, NULL, &ei_sdp_invalid_line_fields, tvb, 0, -1);
444 *next_offset = next_off;
449 /* Same as above, but always issues an expert error if a token is not found. */
451 find_next_token_in_line(tvbuff_t *tvb, proto_tree *tree, gint *offset, gint *next_offset)
453 return find_next_optional_token_in_line(tvb, tree, offset, next_offset, FALSE);
457 /* Subdissector functions */
459 dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) {
460 proto_tree *sdp_owner_tree;
461 gint offset, next_offset, tokenlen;
465 sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner);
467 /* Find the username */
468 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
472 proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
474 offset = next_offset + 1;
476 /* Find the session id */
477 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
481 proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
482 tokenlen, ENC_UTF_8|ENC_NA);
483 offset = next_offset + 1;
485 /* Find the version */
486 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
490 proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
492 offset = next_offset + 1;
494 /* Find the network type */
495 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
499 proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
500 tokenlen, ENC_UTF_8|ENC_NA);
501 offset = next_offset + 1;
503 /* Find the address type */
504 tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
508 proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
509 tokenlen, ENC_UTF_8|ENC_NA);
510 offset = next_offset + 1;
512 /* Find the address */
513 proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_UTF_8|ENC_NA);
517 * XXX - this can leak memory if an exception is thrown after we've fetched
521 dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
522 disposable_media_info_t *media_info) {
523 proto_tree *sdp_connection_info_tree;
524 gint offset, next_offset, tokenlen;
528 sdp_connection_info_tree = proto_item_add_subtree(ti,
529 ett_sdp_connection_info);
531 /* Find the network type */
532 tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset);
536 proto_tree_add_item(sdp_connection_info_tree,
537 hf_connection_info_network_type, tvb, offset, tokenlen,
539 offset = next_offset + 1;
541 /* Find the address type */
542 tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset);
546 /* Save connection address type */
547 media_info->connection_type = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
549 DPRINT(("parsed connection line type=%s", media_info->connection_type));
551 proto_tree_add_item(sdp_connection_info_tree,
552 hf_connection_info_address_type, tvb, offset, tokenlen,
554 offset = next_offset + 1;
556 /* Find the connection address */
557 /* XXX - what if there's a <number of addresses> value? */
558 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
559 if (next_offset == -1) {
560 tokenlen = -1; /* end of tvbuff */
561 /* Save connection address */
562 media_info->connection_address =
563 (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_UTF_8|ENC_NA);
565 tokenlen = next_offset - offset;
566 /* Save connection address */
567 media_info->connection_address = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
570 DPRINT(("parsed connection line address=%s", media_info->connection_address));
572 proto_tree_add_item(sdp_connection_info_tree,
573 hf_connection_info_connection_address, tvb, offset,
574 tokenlen, ENC_UTF_8|ENC_NA);
575 if (next_offset != -1) {
576 offset = next_offset + 1;
577 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
578 if (next_offset == -1) {
579 tokenlen = -1; /* end of tvbuff */
581 tokenlen = next_offset - offset;
583 proto_tree_add_item(sdp_connection_info_tree,
584 hf_connection_info_ttl, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
585 if (next_offset != -1) {
586 offset = next_offset + 1;
587 proto_tree_add_item(sdp_connection_info_tree,
588 hf_connection_info_num_addr, tvb, offset, -1, ENC_UTF_8|ENC_NA);
594 dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) {
595 proto_tree *sdp_bandwidth_tree;
596 gint offset, next_offset, tokenlen;
598 gboolean unit_is_kbs = FALSE;
599 gboolean unit_is_bps = FALSE;
603 sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth);
605 /* find the modifier */
606 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
608 if (next_offset == -1)
611 tokenlen = next_offset - offset;
613 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
614 tokenlen, ENC_UTF_8|ENC_NA);
615 if (tvb_strneql(tvb, offset, "CT", 2) == 0) {
616 proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
618 } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) {
619 proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
621 } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) {
622 proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
627 offset = next_offset + 1;
629 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
631 if (unit_is_kbs == TRUE)
632 proto_item_append_text(item, " kb/s");
633 if (unit_is_bps == TRUE)
634 proto_item_append_text(item, " b/s");
637 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) {
638 proto_tree *sdp_time_tree;
639 gint offset, next_offset, tokenlen;
643 sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
646 tokenlen = find_next_token_in_line(tvb, sdp_time_tree, &offset, &next_offset);
650 proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
654 offset = next_offset + 1;
655 proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_UTF_8|ENC_NA);
658 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) {
659 proto_tree *sdp_repeat_time_tree;
660 gint offset, next_offset, tokenlen;
661 gboolean optional = FALSE;
665 sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
668 tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset);
672 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
673 offset, tokenlen, ENC_UTF_8|ENC_NA);
676 offset = next_offset + 1;
677 tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset);
681 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb,
682 offset, tokenlen, ENC_UTF_8|ENC_NA);
686 offset = next_offset +1;
687 tokenlen = find_next_optional_token_in_line(tvb, sdp_repeat_time_tree,
688 &offset, &next_offset, optional);
691 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
692 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
694 } while (next_offset != -1);
699 dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) {
700 proto_tree* sdp_timezone_tree;
701 gint offset, next_offset, tokenlen;
702 gboolean optional = FALSE;
706 sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone);
709 tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree,
710 &offset, &next_offset, optional);
714 proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
715 tokenlen, ENC_UTF_8|ENC_NA);
716 offset = next_offset + 1;
717 tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree,
718 &offset, &next_offset, optional);
721 proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
722 tokenlen, ENC_UTF_8|ENC_NA);
723 offset = next_offset + 1;
725 } while (next_offset != -1);
730 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) {
731 proto_tree *sdp_encryption_key_tree;
732 gint offset, next_offset, tokenlen;
736 sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key);
738 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
740 if (next_offset == -1)
743 tokenlen = next_offset - offset;
745 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type,
746 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
748 offset = next_offset + 1;
749 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data,
750 tvb, offset, -1, ENC_UTF_8|ENC_NA);
753 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
754 gchar *data_p = NULL;
755 gchar *prtcl_id = NULL;
757 tvbuff_t *keymgmt_tvb;
759 proto_tree *key_tree;
764 key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
766 tokenlen = find_next_token_in_line(tvb, key_tree, &offset, &next_offset);
770 prtcl_id = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
772 proto_tree_add_item(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
774 offset = next_offset + 1;
776 len = tvb_captured_length_remaining(tvb, offset);
780 data_p = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, len, ENC_UTF_8|ENC_NA);
781 keymgmt_tvb = base64_to_tvb(tvb, data_p);
782 add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
784 if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) {
785 found_match = dissector_try_string(key_mgmt_dissector_table,
792 proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
793 keymgmt_tvb, 0, -1, ENC_NA);
794 PROTO_ITEM_SET_HIDDEN(ti2);
796 proto_tree_add_item(key_tree, hf_key_mgmt_data,
797 keymgmt_tvb, 0, -1, ENC_NA);
803 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
804 proto_tree *sdp_session_attribute_tree;
805 gint offset, next_offset, tokenlen;
810 sdp_session_attribute_tree = proto_item_add_subtree(ti,
811 ett_sdp_session_attribute);
813 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
815 if (next_offset == -1)
818 tokenlen = next_offset - offset;
820 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_field,
821 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
823 field_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
825 offset = next_offset + 1;
827 if (strcmp((char*)field_name, "ipbcp") == 0) {
828 offset = tvb_ws_mempbrk_pattern_guint8(tvb, offset, -1,&pbrk_digits, NULL);
833 tokenlen = find_next_token_in_line(tvb, sdp_session_attribute_tree, &offset, &next_offset);
837 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
839 offset = tvb_ws_mempbrk_pattern_guint8(tvb, offset, -1,&pbrk_alpha, NULL);
844 tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
849 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
850 } else if (strcmp((char*)field_name, "key-mgmt") == 0) {
854 key_tvb = tvb_new_subset_remaining(tvb, offset);
855 key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_UTF_8|ENC_NA);
857 dissect_key_mgmt(key_tvb, pinfo, key_ti);
859 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
860 tvb, offset, -1, ENC_UTF_8|ENC_NA);
865 /* Dissect media description - this is passed the line starting after 'm=', so like one of these:
866 * audio 29156 RTP/AVP 18 0
867 * video 49170/2 RTP/AVP 31 99
870 dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
871 transport_info_t *transport_info, disposable_media_info_t *media_info) {
872 proto_tree *sdp_media_tree;
873 gint offset, next_offset, tokenlen, idx;
874 guint8 *media_format;
875 gboolean optional = FALSE;
880 /* Create tree for media session */
881 sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media);
883 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
887 /* Type of media session */
888 proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
891 media_info->media_type[media_info->media_count] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
893 DPRINT(("parsed media_type=%s, for media_count=%d",
894 media_info->media_type[media_info->media_count],
895 media_info->media_count));
897 offset = next_offset + 1;
899 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
903 next_offset = tvb_find_guint8(tvb, offset, tokenlen, '/');
905 if (next_offset != -1) {
906 tokenlen = next_offset - offset;
908 media_info->media_port[media_info->media_count] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
910 DPRINT(("parsed media_port=%s, for media_count=%d",
911 media_info->media_port[media_info->media_count],
912 media_info->media_count));
914 it = proto_tree_add_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen,
915 media_info->media_port[media_info->media_count]);
916 if (g_ascii_isdigit(media_info->media_port[media_info->media_count][0])) {
917 PROTO_ITEM_SET_HIDDEN(it);
918 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
919 atoi(media_info->media_port[media_info->media_count]));
922 offset = next_offset + 1;
923 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
927 /* TODO: this puts the (optional) number of ports in the tree, but we don't
928 actually use it for building the extra RTP flows, which we should. */
929 proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
930 tokenlen, ENC_UTF_8|ENC_NA);
931 offset = next_offset + 1;
933 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
938 media_info->media_port[media_info->media_count] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
939 DPRINT(("parsed media_port=%s, for media_count=%d",
940 media_info->media_port[media_info->media_count],
941 media_info->media_count));
942 /* XXX Remember Port */
943 it = proto_tree_add_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen,
944 media_info->media_port[media_info->media_count]);
945 if (g_ascii_isdigit(media_info->media_port[media_info->media_count][0])) {
946 PROTO_ITEM_SET_HIDDEN(it);
947 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
948 atoi(media_info->media_port[media_info->media_count]));
950 offset = next_offset + 1;
953 tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
957 /* Save port protocol */
958 media_info->media_proto[media_info->media_count] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
960 DPRINT(("parsed media_proto=%s, for media_count=%d",
961 media_info->media_proto[media_info->media_count],
962 media_info->media_count));
964 /* XXX Remember Protocol */
965 proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
969 offset = next_offset + 1;
970 tokenlen = find_next_optional_token_in_line(tvb, sdp_media_tree,
971 &offset, &next_offset, optional);
975 if (!strcmp(media_info->media_proto[media_info->media_count], "RTP/AVP")) {
976 media_format = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
977 if (g_ascii_isdigit(media_format[0])) {
978 proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
979 tokenlen, val_to_str_ext((guint32)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u"));
980 idx = transport_info->media[transport_info->media_count].pt_count;
981 transport_info->media[transport_info->media_count].pt[idx] = (gint32)strtol((char*)media_format, NULL, 10);
982 DPRINT(("parsed media codec pt=%d, for media_count=%d",
983 transport_info->media[transport_info->media_count].pt[idx],
984 transport_info->media_count));
985 if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
986 transport_info->media[transport_info->media_count].pt_count++;
988 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
989 tokenlen, ENC_UTF_8|ENC_NA);
992 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
993 tokenlen, ENC_UTF_8|ENC_NA);
996 } while (next_offset != -1);
998 /* XXX Dissect traffic to "Port" as "Protocol"
999 * Remember this Port/Protocol pair so we can tear it down again later
1000 * Actually, it's harder than that:
1001 * We need to find out the address of the other side first and it
1002 * looks like that info can be found in SIP headers only.
1008 ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
1010 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
1012 /* arbitrary maximum length */
1015 tvbuff_t *bytes_tvb;
1017 /* first, skip to where the encoded pdu starts, this is
1018 the first hex digit after the '=' char.
1021 if ((*msg == 0) || (*msg == '\n')) {
1031 if ((*msg == 0) || (*msg == '\n')) {
1034 if ( ((*msg >= '0') && (*msg <= '9'))
1035 || ((*msg >= 'a') && (*msg <= 'f'))
1036 || ((*msg >= 'A') && (*msg <= 'F'))) {
1042 while (((*msg >= '0') && (*msg <= '9'))
1043 || ((*msg >= 'a') && (*msg <= 'f'))
1044 || ((*msg >= 'A') && (*msg <= 'F'))) {
1046 if ((*msg >= '0') && (*msg <= '9')) {
1048 } else if ((*msg >= 'a') && (*msg <= 'f')) {
1049 val = (*msg)-'a'+10;
1050 } else if ((*msg >= 'A') && (*msg <= 'F')) {
1051 val = (*msg)-'A'+10;
1057 if ((*msg >= '0') && (*msg <= '9')) {
1059 } else if ((*msg >= 'a') && (*msg <= 'f')) {
1060 val |= (*msg)-'a'+10;
1061 } else if ((*msg >= 'A') && (*msg <= 'F')) {
1062 val |= (*msg)-'A'+10;
1068 buf[i] = (guint8)val;
1074 bytes_tvb = tvb_new_child_real_data(tvb, buf, i, i);
1075 add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
1081 /* Annex X Profiles and levels definition */
1082 static const value_string h263_profile_vals[] =
1084 { 0, "Baseline Profile" },
1085 { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
1086 { 2, "Version 1 Backward-Compatibility Profile" },
1087 { 3, "Version 2 Interactive and Streaming Wireless Profile" },
1088 { 4, "Version 3 Interactive and Streaming Wireless Profile" },
1089 { 5, "Conversational High Compression Profile" },
1090 { 6, "Conversational Internet Profile" },
1091 { 7, "Conversational Interlace Profile" },
1092 { 8, "High Latency Profile" },
1097 /* RFC 4629 The level are described in table X.2 of H.263 annex X */
1098 static const value_string h263_level_vals[] =
1100 { 10, "QCIF (176 x 144), 1 x 64Kb/s" },
1101 { 20, "CIF (352 x 288), 2 x 64Kb/s" },
1102 { 30, "CIF (352 x 288), 6 x 64Kb/s" },
1103 { 40, "CIF (352 x 288), 32 x 64Kb/s" },
1104 { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
1105 { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
1106 { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
1107 { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
1112 static const value_string h264_packetization_mode_vals[] =
1114 { 0, "Single NAL mode" },
1115 { 1, "Non-interleaved mode" },
1116 { 2, "Interleaved mode" },
1121 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
1124 decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type) {
1128 gchar *format_specific_parameter;
1130 tvbuff_t * volatile data_tvb;
1132 end_offset = offset + tokenlen;
1135 proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
1136 tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_ASCII));
1139 /* Look for an '=' within this value - this may indicate that there is a
1140 profile-level-id parameter to find if the MPEG4 media type is in use */
1141 next_offset = tvb_find_guint8(tvb, offset, -1, '=');
1142 if (next_offset == -1)
1144 /* Give up (and avoid exception) if '=' not found */
1148 /* Find the name of the parameter */
1149 tokenlen = next_offset - offset;
1150 field_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1152 proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
1154 offset = next_offset;
1156 /* Dissect the MPEG4 profile-level-id parameter if present */
1157 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) {
1158 if (strcmp((char*)field_name, "profile-level-id") == 0) {
1160 tokenlen = end_offset - offset;
1161 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1162 item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
1163 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1164 PROTO_ITEM_SET_GENERATED(item);
1165 } else if (strcmp((char*)field_name, "config") == 0) {
1166 /* String including "=" */
1167 tokenlen = end_offset - offset;
1168 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1169 /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
1170 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
1171 if (mp4ves_handle && data_tvb) {
1172 dissect_mp4ves_config(data_tvb, pinfo, tree);
1177 /* Dissect the H263-2000 profile parameter if present */
1178 if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) ||
1179 ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) {
1180 if (strcmp((char*)field_name, "profile") == 0) {
1182 tokenlen = end_offset - offset;
1183 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1184 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
1185 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1186 PROTO_ITEM_SET_GENERATED(item);
1187 } else if (strcmp((char*)field_name, "level") == 0) {
1189 tokenlen = end_offset - offset;
1190 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1191 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
1192 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1193 PROTO_ITEM_SET_GENERATED(item);
1198 /* Dissect the H264 profile-level-id parameter
1200 * A base16 [6] (hexadecimal) representation of
1201 * the following three bytes in the sequence
1202 * parameter set NAL unit specified in [1]: 1)
1203 * profile_idc, 2) a byte herein referred to as
1204 * profile-iop, composed of the values of
1205 * constraint_set0_flag, constraint_set1_flag,
1206 * constraint_set2_flag, and reserved_zero_5bits
1207 * in bit-significance order, starting from the
1208 * most significant bit, and 3) level_idc.
1210 if ((mime_type != NULL) && ((g_ascii_strcasecmp(mime_type, "H264") == 0) || (g_ascii_strcasecmp(mime_type, "H264-SVC") == 0))) {
1211 if (strcmp(field_name, "profile-level-id") == 0) {
1214 /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
1215 tokenlen = end_offset - offset;
1216 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1217 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
1219 proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter);
1222 length = tvb_reported_length(data_tvb);
1224 if (h264_handle && data_tvb) {
1225 dissect_h264_profile(data_tvb, pinfo, tree);
1228 item = proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
1229 PROTO_ITEM_SET_GENERATED(item);
1231 } else if (strcmp(field_name, "packetization-mode") == 0) {
1233 tokenlen = end_offset - offset;
1234 format_specific_parameter = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1235 item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
1236 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1237 PROTO_ITEM_SET_GENERATED(item);
1238 } else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
1239 /* The value of the parameter is the
1240 base64 [6] representation of the initial
1241 parameter set NAL units as specified in
1242 sections 7.3.2.1 and 7.3.2.2 of [1]. The
1243 parameter sets are conveyed in decoding order,
1244 and no framing of the parameter set NAL units
1245 takes place. A comma is used to separate any
1246 pair of parameter sets in the list.
1248 gchar *data_p = NULL;
1254 comma_offset = tvb_find_guint8(tvb, offset, -1, ',');
1255 if (comma_offset != -1) {
1256 tokenlen = comma_offset - offset;
1258 tokenlen = end_offset - offset;
1261 data_p = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1262 proto_tree_add_string(tree, hf_sdp_nal_unit_1_string, tvb, offset, tokenlen, data_p);
1264 data_tvb = base64_to_tvb(tvb, data_p);
1265 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
1267 if (h264_handle && data_tvb) {
1269 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1271 CATCH_NONFATAL_ERRORS {
1272 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1275 if (comma_offset != -1) {
1276 /* Second NAL unit */
1277 offset = comma_offset +1;
1278 tokenlen = end_offset - offset;
1279 data_p = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1280 proto_tree_add_string(tree, hf_sdp_nal_unit_2_string, tvb, offset, tokenlen, data_p);
1281 data_tvb = base64_to_tvb(tvb, data_p);
1282 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
1283 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1295 #define SDP_RTPMAP 1
1298 #define SDP_H248_ITEM 4
1299 #define SDP_CRYPTO 5
1300 #define SDP_SPRTMAP 6
1302 static const sdp_names_t sdp_media_attribute_names[] = {
1303 { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */
1304 { "rtpmap"}, /* 1 */
1307 { "h248item"}, /* 4 */
1308 { "crypto"}, /* 5 */
1312 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
1316 for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
1317 if ((len == strlen(sdp_media_attribute_names[i].name)) &&
1318 (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0))
1325 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length,
1326 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1327 proto_tree *sdp_media_attribute_tree, *parameter_item;
1328 proto_item *fmtp_item, *media_format_item, *parameter_tree;
1329 proto_tree *fmtp_tree;
1330 gint offset, next_offset, tokenlen, n, colon_offset;
1331 /*??guint8 *field_name;*/
1332 guint8 *payload_type;
1333 guint8 *attribute_value;
1335 gint sdp_media_attrbute_code;
1336 const char *msrp_res = "msrp://";
1337 const char *h324ext_h223lcparm = "h324ext/h223lcparm";
1338 gboolean has_more_pars = TRUE;
1340 guint8 master_key_length = 0, master_salt_length = 0;
1344 /* Create attribute tree */
1345 sdp_media_attribute_tree = proto_item_add_subtree(ti,
1346 ett_sdp_media_attribute);
1347 /* Find end of field */
1348 colon_offset = tvb_find_guint8(tvb, offset, -1, ':');
1350 if (colon_offset == -1)
1353 /* Attribute field name is token before ':' */
1354 tokenlen = colon_offset - offset;
1355 proto_tree_add_item(sdp_media_attribute_tree,
1356 hf_media_attribute_field,
1357 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1358 /*??field_name = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_ASCII);*/
1359 sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
1362 offset = colon_offset + 1;
1363 /* skip leading wsp */
1364 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
1366 /* Value is the remainder of the line */
1367 attribute_value = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_UTF_8|ENC_NA);
1371 /*********************************************/
1372 /* Special parsing for some field name types */
1374 switch (sdp_media_attrbute_code) {
1376 /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
1377 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1379 if (next_offset == -1)
1382 tokenlen = next_offset - offset;
1384 proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
1385 offset, tokenlen, ENC_UTF_8|ENC_NA);
1387 payload_type = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1389 offset = next_offset + 1;
1391 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
1393 if (next_offset == -1) {
1397 tokenlen = next_offset - offset;
1399 proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
1400 offset, tokenlen, ENC_UTF_8|ENC_NA);
1402 pt = atoi((char*)payload_type);
1403 if (pt >= SDP_NO_OF_PT) {
1404 return; /* Invalid */
1407 transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1409 next_offset = next_offset + 1;
1410 offset = next_offset;
1411 while (length-1 >= next_offset) {
1412 if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
1416 tokenlen = next_offset - offset;
1417 proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
1418 offset, tokenlen, ENC_UTF_8|ENC_NA);
1419 transport_info->sample_rate[pt] = atoi(tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA));
1420 /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1423 a=rtpmap:101 G726-32/8000
1424 m=audio 49170 RTP/AVP 0 97
1425 a=rtpmap:97 telephone-event/8000
1426 m=audio 49172 RTP/AVP 97 101
1427 a=rtpmap:97 G726-24/8000
1429 The Media attributes ("a="s) after the "m=" only apply for that "m=".
1430 If there is an "a=" before the first "m=", that attribute applies for
1431 all the session (all the "m="s).
1434 /* so, if this "a=" appear before any "m=", we add it to all the dynamic
1437 if (transport_info->media_count < 0) {
1438 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1439 rtp_dyn_payload_insert(transport_info->media[n].rtp_dyn_payload,
1441 transport_info->encoding_name[pt],
1442 transport_info->sample_rate[pt]);
1445 /* if the "a=" is after an "m=", only apply to this "m=" */
1448 rtp_dyn_payload_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
1449 pt, transport_info->encoding_name[pt], transport_info->sample_rate[pt]);
1452 if (sdp_media_attribute_tree) {
1453 guint8 media_format;
1454 /* Reading the Format parameter(fmtp) */
1455 /* Skip leading space, if any */
1456 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
1457 /* Media format extends to the next space */
1458 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1460 if (next_offset == -1)
1463 tokenlen = next_offset - offset;
1466 media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
1467 hf_media_format, tvb, offset,
1468 tokenlen, ENC_UTF_8|ENC_NA);
1469 media_format = atoi((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA));
1470 if (media_format >= SDP_NO_OF_PT) {
1471 return; /* Invalid */
1474 /* Append encoding name to format if known */
1475 proto_item_append_text(media_format_item, " [%s]",
1476 transport_info->encoding_name[media_format]);
1479 payload_type = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_ASCII);
1481 /* Move offset past the payload type */
1482 offset = next_offset + 1;
1484 while (has_more_pars == TRUE) {
1485 next_offset = tvb_find_guint8(tvb, offset, -1, ';');
1486 offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
1488 if (next_offset == -1) {
1489 has_more_pars = FALSE;
1490 next_offset= tvb_captured_length(tvb);
1493 /* There are at least 2 - add the first parameter */
1494 tokenlen = next_offset - offset;
1495 fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
1496 hf_media_format_specific_parameter, tvb,
1497 offset, tokenlen, ENC_UTF_8|ENC_NA);
1499 fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
1501 decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
1502 transport_info->encoding_name[media_format]);
1504 /* Move offset past "; " and onto firts char */
1505 offset = next_offset + 1;
1510 /* msrp attributes that contain address needed for conversation */
1512 * path = path-label ":" path-list
1513 * path-label = "path"
1514 * path-list= MSRP-URI *(SP MSRP-URI)
1515 * MSRP-URI = msrp-scheme "://" authority
1516 * ["/" session-id] ";" transport *( ";" URI-parameter)
1517 * ; authority as defined in RFC3986
1519 * msrp-scheme = "msrp" / "msrps"
1521 * The authority component is preceded by a double slash ("//") and is terminated by
1522 * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1523 * the end of the URI.
1526 /* Check for "msrp://" */
1527 if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0) {
1528 int address_offset, port_offset, port_end_offset;
1530 /* Address starts here */
1531 address_offset = offset + (int)strlen(msrp_res);
1533 /* Port is after next ':' */
1534 port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
1535 /* Check if port is present if not skipp */
1536 if (port_offset!= -1) {
1537 /* Port ends with '/' */
1538 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
1539 if (port_end_offset == -1) {
1540 /* No "/" look for the ";" */
1541 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');
1543 /* Attempt to convert address */
1544 if (str_to_ip((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA),
1545 &media_info->msrp_ipaddr)) {
1546 /* Get port number */
1547 media_info->msrp_port_number = atoi((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, port_offset + 1, port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA));
1548 /* Set flag so this info can be used */
1549 media_info->msrp_transport_address_set = TRUE;
1555 /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
1556 if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
1557 /* A.5.1.3 H.223 Logical channel parameters
1558 * This property indicates the H.245
1559 * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1560 * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1561 * in ITU-T Rec. H.248.15 is used.
1566 len = (gint)strlen(attribute_value);
1567 h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
1568 /* arbitrary maximum length */
1569 /* should go through a handle, however, the two h245 entry
1570 points are different, one is over tpkt and the other is raw
1573 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1574 dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
1575 sdp_media_attribute_tree,
1576 hf_SDPh223LogicalChannelParameters);
1581 /* http://tools.ietf.org/html/rfc4568
1582 * 9.1. Generic "Crypto" Attribute Grammar
1584 * The ABNF grammar for the crypto attribute is defined below:
1586 * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
1587 * *(1*WSP session-param)
1590 * crypto-suite = 1*(ALPHA / DIGIT / "_")
1592 * key-params = key-param *(";" key-param)
1593 * key-param = key-method ":" key-info
1594 * key-method = "inline" / key-method-ext
1595 * key-method-ext = 1*(ALPHA / DIGIT / "_")
1596 * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
1597 * ; except semi-colon
1598 * session-param = 1*(VCHAR) ; visible (printing) characters
1600 * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
1604 /* We are at the first colon */
1606 tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset);
1609 proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen,
1610 atoi((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA)));
1611 offset = next_offset + 1;
1614 tokenlen = find_next_token_in_line(tvb, sdp_media_attribute_tree, &offset, &next_offset);
1617 parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite,
1618 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1619 if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
1621 /* XXX This may only work in simple cases */
1622 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1623 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1624 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1625 /* number of octets used for the Auth Tag in the RTP payload */
1626 transport_info->auth_tag_len = 10;
1628 master_key_length = 16; /* 128 bits = 16 octets */
1629 master_salt_length = 14; /* 112 bits = 14 octets */
1630 } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
1631 /* XXX This may only work in simple cases */
1632 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1633 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1634 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1635 /* number of octets used for the Auth Tag in the RTP payload */
1636 transport_info->auth_tag_len = 4;
1638 master_key_length = 16; /* 128 bits = 16 octets */
1639 master_salt_length = 14; /* 112 bits = 14 octets */
1640 } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
1641 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1642 /* XXX This may only work in simple cases */
1643 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
1644 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1645 /* number of octets used for the Auth Tag in the RTP payload */
1646 transport_info->auth_tag_len = 10;
1648 master_key_length = 16; /* 128 bits = 16 octets */
1649 master_salt_length = 14; /* 112 bits = 14 octets */
1651 offset = next_offset + 1;
1654 while (has_more_pars == TRUE) {
1655 int param_end_offset;
1656 tvbuff_t *key_salt_tvb;
1657 gchar *data_p = NULL;
1659 param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
1660 if (param_end_offset == -1) {
1661 has_more_pars = FALSE;
1662 param_end_offset = tvb_captured_length(tvb);
1664 /* key-method or key-method-ext */
1665 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1666 if (next_offset == -1) {
1667 expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
1671 if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
1672 parameter_tree = proto_tree_add_subtree(sdp_media_attribute_tree, tvb, offset,
1673 param_end_offset-offset, ett_sdp_crypto_key_parameters, NULL, "Key parameters");
1674 /* XXX only for SRTP? */
1675 /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
1676 offset = next_offset +1;
1677 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1678 if (next_offset == -1) {
1679 tokenlen = param_end_offset - offset;
1681 tokenlen = next_offset - offset;
1683 data_p = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1684 key_salt_tvb = base64_to_tvb(tvb, data_p);
1685 add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
1686 if (master_key_length != 0) {
1687 proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA);
1688 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
1689 key_salt_tvb, 0, master_key_length, ENC_NA);
1690 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
1691 key_salt_tvb, master_key_length, master_salt_length, ENC_NA);
1693 proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA);
1696 /* ["|" lifetime] ["|" mki] are optional */
1697 if (next_offset != -1) {
1698 offset = next_offset + 1;
1699 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1700 if (next_offset == -1) {
1701 if (next_offset < param_end_offset){
1702 next_offset = param_end_offset;
1705 if (next_offset != -1) {
1706 /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
1707 tokenlen = next_offset - offset;
1708 proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
1709 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1710 offset = next_offset + 1;
1712 /* mki = mki-value ":" mki-length
1714 * mki-value = 1*DIGIT
1716 if (offset>param_end_offset) {
1719 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1721 if (next_offset != -1) {
1722 tokenlen = next_offset - offset;
1723 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1724 offset = next_offset + 1;
1726 /* mki-length = 1*3DIGIT ; range 1..128. */
1727 next_offset = param_end_offset;
1728 tokenlen = next_offset - offset;
1730 /* This will not work if more than one parameter */
1731 /* number of octets used for the MKI in the RTP payload */
1732 transport_info->mki_len = atoi((char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA));
1733 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
1734 tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1737 offset = param_end_offset;
1745 /* No special treatment for values of this attribute type, just add as one item. */
1746 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
1747 tvb, offset, -1, ENC_UTF_8|ENC_NA);
1753 call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
1754 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1755 if (hf == hf_owner) {
1756 dissect_sdp_owner(tvb, ti);
1757 } else if (hf == hf_connection_info) {
1758 dissect_sdp_connection_info(tvb, ti, media_info);
1759 } else if (hf == hf_bandwidth) {
1760 dissect_sdp_bandwidth(tvb, ti);
1761 } else if (hf == hf_time) {
1762 dissect_sdp_time(tvb, ti);
1763 } else if (hf == hf_repeat_time) {
1764 dissect_sdp_repeat_time(tvb, ti);
1765 } else if (hf == hf_timezone) {
1766 dissect_sdp_timezone(tvb, ti);
1767 } else if (hf == hf_encryption_key) {
1768 dissect_sdp_encryption_key(tvb, ti);
1769 } else if (hf == hf_session_attribute) {
1770 dissect_sdp_session_attribute(tvb, pinfo, ti);
1771 } else if (hf == hf_media) {
1772 dissect_sdp_media(tvb, ti, transport_info, media_info);
1773 } else if (hf == hf_media_attribute) {
1774 dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, media_info);
1779 convert_disposable_media(transport_info_t* transport_info, disposable_media_info_t* media_info,
1780 gint start_transport_info_count)
1782 gint8 n, transport_index;
1783 guint proto_bitmask;
1785 for (n = 0; (n < media_info->media_count) && (n+start_transport_info_count < SDP_MAX_RTP_CHANNELS); n++)
1787 transport_index = n+start_transport_info_count;
1788 if (media_info->media_port[n] != NULL) {
1789 transport_info->media_port[transport_index] = (int)strtol(media_info->media_port[n], NULL, 10);
1790 DPRINT(("set transport_info media port number=%d, for transport_index=%d",
1791 transport_info->media_port[transport_index], transport_index));
1794 if (media_info->media_proto[n] != NULL) {
1795 /* Check if media protocol is RTP
1796 * and stream decoding is enabled in preferences
1798 if (global_sdp_establish_conversation) {
1801 /* Check if media protocol is RTP */
1802 /* XXX: what about 'RTP/AVPF' or RTP/SAVPF'? */
1803 if (!strcmp(media_info->media_proto[n],"RTP/AVP")) {
1804 transport_info->proto_bitmask[transport_index] |= SDP_RTP_PROTO;
1805 proto_bitmask |= SDP_RTP_PROTO;
1806 DPRINT(("set SDP_RTP_PROTO bitmask=%x, for transport_index=%d",
1807 transport_info->proto_bitmask[transport_index], transport_index));
1809 /* Check if media protocol is SRTP */
1810 else if (!strcmp(media_info->media_proto[n],"RTP/SAVP")) {
1811 transport_info->proto_bitmask[transport_index] |= SDP_SRTP_PROTO;
1812 proto_bitmask |= SDP_SRTP_PROTO;
1813 DPRINT(("set SDP_SRTP_PROTO bitmask=%x, for transport_index=%d",
1814 transport_info->proto_bitmask[transport_index], transport_index));
1816 /* Check if media protocol is T38 */
1817 else if ((!strcmp(media_info->media_proto[n],"UDPTL")) ||
1818 (!strcmp(media_info->media_proto[n],"udptl"))) {
1819 transport_info->proto_bitmask[transport_index] |= SDP_T38_PROTO;
1820 proto_bitmask |= SDP_T38_PROTO;
1821 DPRINT(("set SDP_T38_PROTO bitmask=%x, for transport_index=%d",
1822 transport_info->proto_bitmask[transport_index], transport_index));
1824 /* Check if media protocol is MSRP/TCP */
1825 else if (!strcmp(media_info->media_proto[n],"msrp/tcp")) {
1826 transport_info->proto_bitmask[transport_index] |= SDP_MSRP_PROTO;
1827 proto_bitmask |= SDP_MSRP_PROTO;
1828 DPRINT(("set SDP_MSRP_PROTO bitmask=%x, for transport_index=%d",
1829 transport_info->proto_bitmask[transport_index], transport_index));
1831 /* Check if media protocol is SPRT */
1832 else if ((!strcmp(media_info->media_proto[n],"UDPSPRT")) ||
1833 (!strcmp(media_info->media_proto[n],"udpsprt"))) {
1834 transport_info->proto_bitmask[transport_index] |= SDP_SPRT_PROTO;
1835 proto_bitmask |= SDP_SPRT_PROTO;
1836 DPRINT(("set SDP_SPRT_PROTO bitmask=%x, for transport_index=%d",
1837 transport_info->proto_bitmask[transport_index], transport_index));
1840 /* now check if this stream's port==0, in which case we need to disable its paired stream */
1841 if (transport_info->media_port[transport_index] == 0) {
1842 /* This should disable the matching media session in the offer - it's a bit of a hack though,
1843 basically start_transport_info_count is 0 for the offer, and >0 for the answer, so we
1844 check that and if this is the answer, then we go set the offer's paired stream to 0.
1845 If it turns out we got a port=0 in the offer, we don't care and it's ok to let the
1846 answer have a non-port=0 (though that would be illegal per the RFCs). */
1847 if (start_transport_info_count > 0 && (proto_bitmask & transport_info->proto_bitmask[n])) {
1848 transport_info->media_port[n] = 0;
1849 DPRINT(("disabled media_port=%d, for transport_index=%d",
1850 n, transport_index));
1856 if ((media_info->connection_address != NULL) &&
1857 (media_info->connection_type != NULL)) {
1858 if (strcmp(media_info->connection_type, "IP4") == 0) {
1859 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 4);
1860 if (str_to_ip(media_info->connection_address, (void*)transport_info->src_addr[transport_index].data)) {
1861 /* connection_address could be converted to a valid ipv4 address*/
1862 transport_info->proto_bitmask[transport_index] |= SDP_IPv4;
1863 transport_info->src_addr[transport_index].type = AT_IPv4;
1864 transport_info->src_addr[transport_index].len = 4;
1865 DPRINT(("set SDP_IPv4 bitmask=%x, for transport_index=%d",
1866 transport_info->proto_bitmask[transport_index], transport_index));
1868 } else if (strcmp(media_info->connection_type, "IP6") == 0) {
1869 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 16);
1870 if (str_to_ip6(media_info->connection_address, (void*)transport_info->src_addr[transport_index].data)) {
1871 /* connection_address could be converted to a valid ipv6 address*/
1872 transport_info->proto_bitmask[transport_index] |= SDP_IPv6;
1873 transport_info->src_addr[transport_index].type = AT_IPv6;
1874 transport_info->src_addr[transport_index].len = 16;
1875 DPRINT(("set SDP_IPv6 bitmask=%x, for transport_index=%d",
1876 transport_info->proto_bitmask[transport_index], transport_index));
1881 /* MSRP uses addresses discovered in attribute
1882 rather than connection information of media session line */
1883 if ((transport_info->proto_bitmask[transport_index] & SDP_MSRP_PROTO) &&
1884 (transport_info->proto_bitmask[transport_index] & SDP_MSRP_IPv4) &&
1886 transport_info->src_addr[transport_index].type = AT_IPv4;
1887 transport_info->src_addr[transport_index].len = 4;
1888 transport_info->src_addr[transport_index].data = wmem_memdup(wmem_file_scope(), media_info->msrp_ipaddr, 4);
1889 transport_info->media_port[transport_index] = media_info->msrp_port_number;
1892 if ((media_info->media_type[transport_index] != NULL) &&
1893 (strcmp(media_info->media_type[transport_index], "video") == 0)) {
1894 transport_info->proto_bitmask[transport_index] |= SDP_VIDEO;
1895 DPRINT(("set SDP_VIDEO bitmask=%x, for transport_index=%d",
1896 transport_info->proto_bitmask[transport_index], transport_index));
1902 setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type,
1903 int request_frame, const gboolean delay)
1905 gint offset = 0, next_offset, n;
1907 gboolean in_media_description = FALSE;
1909 const int tokenoffset = 2;
1911 gint start_transport_info_count = 0;
1912 transport_info_t* transport_info = NULL;
1913 disposable_media_info_t media_info;
1915 struct srtp_info *srtp_info = NULL;
1917 DPRINT2(("-------------------- setup_sdp_transport -------------------"));
1919 /* Only do this once during first pass */
1920 if (pinfo->fd->flags.visited) {
1921 DPRINT(("already visited"));
1925 memset(&media_info, 0, sizeof(media_info));
1927 if (request_frame != 0)
1928 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
1929 if (transport_info == NULL) {
1930 transport_info = wmem_new0(wmem_file_scope(), transport_info_t);
1931 transport_info->media_count = -1;
1933 for (n = 0; n < SDP_NO_OF_PT; n++) {
1934 transport_info->encoding_name[n] = (char*)UNKNOWN_ENCODING;
1936 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1937 transport_info->media[n].rtp_dyn_payload = rtp_dyn_payload_new();
1938 transport_info->media[n].set_rtp = FALSE;
1941 if (request_frame != 0)
1942 wmem_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info);
1944 #ifdef DEBUG_CONVERSATION
1946 DPRINT(("found previous transport_info:"));
1947 sdp_dump_transport_info(transport_info);
1951 if (exchange_type != SDP_EXCHANGE_OFFER)
1952 wmem_tree_insert32(sdp_transport_rsps, pinfo->fd->num, (void *)transport_info);
1954 /* Offer has already been answered or rejected and hash tables freed, so
1955 * don't try to add to it
1956 * XXX - Need to support "modified offers" */
1957 if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) ||
1958 (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT))
1961 if (transport_info->media_count > 0)
1962 start_transport_info_count = transport_info->media_count;
1964 DPRINT(("start_transport_info_count=%d", start_transport_info_count));
1966 /* if we don't delay, and this is an answer after a previous offer, then
1967 we free'd the unused media rtp_dyn_payload last time while processing
1968 the offer, so we need to re-create them this time in case we need them.
1969 If they don't get used they'll get free'd again later */
1970 if (!delay && (exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
1971 (transport_info->sdp_status == SDP_EXCHANGE_OFFER)) {
1972 for (n = start_transport_info_count; n < SDP_MAX_RTP_CHANNELS; n++) {
1973 if (!transport_info->media[n].rtp_dyn_payload)
1974 transport_info->media[n].rtp_dyn_payload = rtp_dyn_payload_new();
1979 * Show the SDP message a line at a time.
1981 while (tvb_offset_exists(tvb, offset)) {
1983 * Find the end of the line.
1985 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1988 * Line must contain at least e.g. "v=".
1993 type = tvb_get_guint8(tvb, offset);
1994 delim = tvb_get_guint8(tvb, offset + 1);
1996 offset = next_offset;
2001 * Attributes. Only care about ones that affect the transport. Ignore others.
2005 hf = hf_connection_info;
2010 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2011 if (((transport_info->media_count < 0) && (in_media_description == FALSE)) || (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)))
2012 transport_info->media_count++;
2014 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
2015 media_info.media_count++;
2017 in_media_description = TRUE;
2018 DPRINT(("in media description, transport_info->media_count=%d, "
2019 "media_info.media_count=%d",
2020 transport_info->media_count, media_info.media_count));
2023 if (in_media_description) {
2024 hf = hf_media_attribute;
2026 hf = hf_session_attribute;
2034 if (hf != hf_unknown)
2037 call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset,
2038 linelen - tokenoffset),
2040 hf, NULL, linelen-tokenoffset, transport_info, &media_info);
2044 offset = next_offset;
2047 if (in_media_description) {
2048 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2049 /* XXX: I don't know why this was done here - I'm keeping it here in case
2050 * removing it causes problems, but it's wrong. transport_info->media_count
2051 * is already incremented in the while() loop above. Incrementing it
2052 * again here will cause bugs. The name of this is misleading, because
2053 * 'transport_info->media_count' is actually an index, not count.
2054 * In other words, it's a 0-based number, of the current rtp channel.
2055 * So debug printing shows bogus rtp channels get created and then later
2056 * removed because luckily it knows they were bogus. But it will cause bugs
2057 * because if we're not delaying, then for the SDP_EXCHANGE_ANSWER_ACCEPT
2058 * run through this function, it will add new RTP channels at a +1 index,
2059 * which will likely cause problems.
2061 if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1))
2062 transport_info->media_count++;
2063 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2064 media_info.media_count++;
2067 #ifdef DEBUG_CONVERSATION
2068 sdp_dump_disposable_media_info(&media_info);
2071 DPRINT(("calling convert_disposable_media(), transport_info->media_count=%d, "
2072 "media_info.media_count=%d, start_transport_info_count=%d",
2073 transport_info->media_count, media_info.media_count, start_transport_info_count));
2075 /* Take all of the collected strings and convert them into something permanent
2076 * for the life of the capture
2078 convert_disposable_media(transport_info, &media_info, start_transport_info_count);
2081 #ifdef DEBUG_CONVERSATION
2082 sdp_dump_transport_info(transport_info);
2085 /* We have a successful negotiation, apply data to their respective protocols */
2086 if (!delay || ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
2087 (transport_info->sdp_status == SDP_EXCHANGE_OFFER))) {
2089 for (n = 0; n <= transport_info->media_count; n++) {
2090 guint32 current_rtp_port = 0;
2092 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2093 if ((transport_info->media_port[n] != 0) &&
2094 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
2095 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
2097 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2098 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
2099 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
2100 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
2101 srtp_info->auth_algorithm = transport_info->auth_algorithm;
2102 srtp_info->mki_len = transport_info->mki_len;
2103 srtp_info->auth_tag_len = transport_info->auth_tag_len;
2106 DPRINT(("calling srtp_add_address, channel=%d, media_port=%d",
2107 n, transport_info->media_port[n]));
2109 /* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number,
2110 because that's where the RTP flow started, and thus conversation needs to check against */
2111 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", request_frame,
2112 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2113 transport_info->media[n].rtp_dyn_payload, srtp_info);
2116 DPRINT(("calling rtp_add_address, channel=%d, media_port=%d",
2117 n, transport_info->media_port[n]));
2119 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", request_frame,
2120 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2121 transport_info->media[n].rtp_dyn_payload);
2124 transport_info->media[n].set_rtp = TRUE;
2125 /* SPRT might use the same port... */
2126 current_rtp_port = transport_info->media_port[n];
2129 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2130 DPRINT(("calling rtcp_add_address, channel=%d, media_port=%d",
2131 n, transport_info->media_port[n]+1));
2133 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", request_frame, srtp_info);
2136 DPRINT(("calling rtcp_add_address, channel=%d, media_port=%d",
2137 n, transport_info->media_port[n]+1));
2139 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", request_frame);
2145 /* add SPRT conversation */
2146 if ((transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
2147 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
2150 if (transport_info->media_port[n] == 0 && current_rtp_port) {
2151 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
2152 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
2154 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2158 /* Add t38 conversation, if available and only if no rtp */
2159 if ((transport_info->media_port[n] != 0) &&
2160 !transport_info->media[n].set_rtp &&
2161 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
2162 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
2163 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2166 /* Add MSRP conversation. Uses addresses discovered in attribute
2167 rather than connection information of media session line
2168 (already handled in media conversion) */
2169 if ((transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
2170 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
2172 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
2175 /* Free the hash table if we did't assigned it to a conv use it */
2176 if (!transport_info->media[n].set_rtp)
2178 DPRINT(("set_rtp is not set, calling rtp_dyn_payload_free, "
2179 "channel=%d, media_port=%d",
2180 n, transport_info->media_port[n]));
2181 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2182 transport_info->media[n].rtp_dyn_payload = NULL;
2185 } /* end for (n = 0; n <= transport_info->media_count; n++) */
2187 /* Free the remaining hash tables not used */
2188 if (transport_info->media_count == -1)
2190 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
2192 if (!transport_info->media[n].set_rtp)
2194 DPRINT(("media_count == -1, calling rtp_dyn_payload_free, "
2195 "channel=%d, media_port=%d",
2196 n, transport_info->media_port[n]));
2197 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2198 transport_info->media[n].rtp_dyn_payload = NULL;
2204 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
2206 if (!transport_info->media[n].set_rtp)
2208 DPRINT(("media_count != -1, calling rtp_dyn_payload_free, "
2209 "channel=%d, media_port=%d",
2210 n, transport_info->media_port[n]));
2211 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2212 transport_info->media[n].rtp_dyn_payload = NULL;
2216 transport_info->sdp_status = exchange_type;
2218 } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) &&
2219 (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)) {
2221 /* Free the hash tables, since they won't be put to use */
2222 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
2224 if (!transport_info->media[n].set_rtp)
2226 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2227 transport_info->media[n].rtp_dyn_payload = NULL;
2231 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT;
2235 void setup_sdp_transport_resend(int current_frame, int request_frame)
2237 transport_info_t* transport_info = NULL;
2239 if (request_frame != 0) {
2240 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
2241 if (transport_info != NULL) {
2242 wmem_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info);
2248 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2250 proto_tree *sdp_tree;
2251 proto_item *ti, *sub_ti;
2252 gint offset = 0, next_offset, n, i;
2254 gboolean in_media_description;
2256 int datalen, tokenoffset, hf = -1;
2259 transport_info_t local_transport_info;
2260 transport_info_t* transport_info = NULL;
2261 disposable_media_info_t media_info;
2263 sdp_packet_info *sdp_pi;
2264 struct srtp_info *srtp_info = NULL;
2266 DPRINT2(("----------------------- dissect_sdp ------------------------"));
2268 /* Initialise packet info for passing to tap */
2269 sdp_pi = wmem_new(wmem_packet_scope(), sdp_packet_info);
2270 sdp_pi->summary_str[0] = '\0';
2272 if (!pinfo->fd->flags.visited) {
2273 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->fd->num );
2275 if (transport_info == NULL) {
2276 /* Can't find it in the requests, make sure it's not a response */
2277 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_rsps, pinfo->fd->num );
2281 if (transport_info == NULL) {
2282 transport_info = &local_transport_info;
2284 #ifdef DEBUG_CONVERSATION
2286 DPRINT(("found previous transport_info:"));
2287 sdp_dump_transport_info(transport_info);
2291 /* Initialize local transport info */
2292 memset(&local_transport_info, 0, sizeof(local_transport_info));
2293 local_transport_info.media_count = -1;
2295 for (n = 0; n < SDP_NO_OF_PT; n++) {
2296 local_transport_info.encoding_name[n] = (char*)UNKNOWN_ENCODING;
2298 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
2299 local_transport_info.media[n].rtp_dyn_payload = rtp_dyn_payload_new();
2300 local_transport_info.media[n].set_rtp = FALSE;
2303 memset(&media_info, 0, sizeof(media_info));
2306 * As RFC 2327 says, "SDP is purely a format for session
2307 * description - it does not incorporate a transport protocol,
2308 * and is intended to use different transport protocols as
2309 * appropriate including the Session Announcement Protocol,
2310 * Session Initiation Protocol, Real-Time Streaming Protocol,
2311 * electronic mail using the MIME extensions, and the
2312 * Hypertext Transport Protocol."
2314 * We therefore don't set the protocol or info columns;
2315 * instead, we append to them, so that we don't erase
2316 * what the protocol inside which the SDP stuff resides
2319 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
2321 /* XXX: Needs description.
2322 * Putting with session description in info col is redundant when it's in the
2323 * protocol col in my opinion, commenting it out for now 2012-10-09. Remove if no one complains.
2324 * If some one want it consider " ,with SDP"
2326 /*col_append_str(pinfo->cinfo, COL_INFO, ", with session description");*/
2328 ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA);
2329 sdp_tree = proto_item_add_subtree(ti, ett_sdp);
2332 * Show the SDP message a line at a time.
2334 in_media_description = FALSE;
2336 while (tvb_offset_exists(tvb, offset)) {
2338 * Find the end of the line.
2340 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
2343 * Line must contain at least e.g. "v=".
2348 type = tvb_get_guint8(tvb, offset);
2349 delim = tvb_get_guint8(tvb, offset + 1);
2351 proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_UTF_8|ENC_NA);
2352 expert_add_info(pinfo, ti2, &ei_sdp_invalid_line_equal);
2353 offset = next_offset;
2362 hf = hf_protocol_version;
2368 hf = hf_session_name;
2371 if (in_media_description) {
2372 hf = hf_media_title;
2374 hf = hf_session_info;
2387 hf = hf_connection_info;
2396 hf = hf_repeat_time;
2401 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2402 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2403 local_transport_info.media_count++;
2405 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
2406 media_info.media_count++;
2408 in_media_description = TRUE;
2411 hf = hf_encryption_key;
2414 if (in_media_description) {
2415 hf = hf_media_attribute;
2417 hf = hf_session_attribute;
2428 if (hf == hf_unknown)
2430 string = (char*)tvb_get_string_enc(wmem_packet_scope(), tvb, offset + tokenoffset,
2431 linelen - tokenoffset, ENC_ASCII);
2432 sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
2435 call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset,
2436 linelen - tokenoffset),
2438 hf, sub_ti, linelen-tokenoffset,
2439 &local_transport_info, &media_info);
2441 offset = next_offset;
2444 if (in_media_description) {
2445 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2446 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2447 local_transport_info.media_count++;
2448 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2449 media_info.media_count++;
2452 /* Take all of the collected strings and convert them into something permanent
2453 * for the life of the capture
2455 if (transport_info == &local_transport_info) {
2456 DPRINT(("no previous transport_info saved, calling convert_disposable_media()"));
2458 convert_disposable_media(transport_info, &media_info, 0);
2460 #ifdef DEBUG_CONVERSATION
2461 sdp_dump_transport_info(transport_info);
2464 #ifdef DEBUG_CONVERSATION
2466 DPRINT(("not overwriting previous transport_info, local_transport_info contents:"));
2467 sdp_dump_transport_info(&local_transport_info);
2471 for (n = 0; n < local_transport_info.media_count; n++)
2473 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2474 /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
2475 * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers
2476 * use setup_sdp_transport(), this should be removed
2478 guint32 current_rtp_port = 0;
2480 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2481 (transport_info->media_port[n] != 0) &&
2482 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
2483 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
2485 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2486 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
2487 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
2488 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
2489 srtp_info->auth_algorithm = transport_info->auth_algorithm;
2490 srtp_info->mki_len = transport_info->mki_len;
2491 srtp_info->auth_tag_len = transport_info->auth_tag_len;
2493 DPRINT(("calling srtp_add_address for media_port=%d, for channel=%d",
2494 transport_info->media_port[n],n));
2496 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2497 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2498 transport_info->media[n].rtp_dyn_payload, srtp_info);
2501 DPRINT(("calling rtp_add_address for media_port=%d, for channel=%d",
2502 transport_info->media_port[n],n));
2504 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2505 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2506 transport_info->media[n].rtp_dyn_payload);
2509 transport_info->media[n].set_rtp = TRUE;
2510 /* SPRT might use the same port... */
2511 current_rtp_port = transport_info->media_port[n];
2514 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2515 DPRINT(("calling srtcp_add_address for media_port=%d, for channel=%d",
2516 transport_info->media_port[n],n));
2518 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
2521 DPRINT(("calling rtcp_add_address for media_port=%d, for channel=%d",
2522 transport_info->media_port[n],n));
2524 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
2530 /* add SPRT conversation */
2531 /* XXX - more placeholder functionality */
2532 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2533 (transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
2534 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
2537 if (transport_info->media_port[n] == 0 && current_rtp_port) {
2538 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
2539 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
2541 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2545 /* Add t38 conversation, if available and only if no rtp */
2546 /* XXX - more placeholder functionality */
2547 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2548 (transport_info->media_port[n] != 0) &&
2549 !transport_info->media[n].set_rtp &&
2550 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
2551 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
2552 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2555 /* Add MSRP conversation. Uses addresses discovered in attribute
2556 rather than connection information of media session line */
2557 /* XXX - more placeholder functionality */
2558 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2559 (transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
2560 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
2562 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
2565 if (local_transport_info.media_port[n] != 0) {
2566 /* Create the RTP summary str for the Voip Call analysis.
2567 * XXX - Currently this is based only on the current packet
2569 for (i = 0; i < local_transport_info.media[n].pt_count; i++)
2571 DPRINT(("in for-loop for voip call analysis setting for media #%d, pt=%d",
2572 i, local_transport_info.media[n].pt[i]));
2573 /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
2574 if ((local_transport_info.media[n].pt[i] >= 96) && (local_transport_info.media[n].pt[i] <= 127)) {
2575 const gchar *payload_type_str = rtp_dyn_payload_get_name(
2576 local_transport_info.media[n].rtp_dyn_payload,
2577 local_transport_info.media[n].pt[i]);
2578 if (payload_type_str) {
2579 if (strlen(sdp_pi->summary_str))
2580 g_strlcat(sdp_pi->summary_str, " ", 50);
2581 g_strlcat(sdp_pi->summary_str, payload_type_str, 50);
2584 g_snprintf(num_pt, 10, "%u", local_transport_info.media[n].pt[i]);
2585 if (strlen(sdp_pi->summary_str))
2586 g_strlcat(sdp_pi->summary_str, " ", 50);
2587 g_strlcat(sdp_pi->summary_str, num_pt, 50);
2590 if (strlen(sdp_pi->summary_str))
2591 g_strlcat(sdp_pi->summary_str, " ", 50);
2592 g_strlcat(sdp_pi->summary_str,
2593 val_to_str_ext(local_transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"),
2599 /* Free the hash table if we did't assigned it to a conv use it */
2600 /* XXX - more placeholder functionality */
2601 if ((transport_info == &local_transport_info) &&
2602 !transport_info->media[n].set_rtp)
2604 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2605 transport_info->media[n].rtp_dyn_payload = NULL;
2608 /* Create the T38 summary str for the Voip Call analysis
2609 * XXX - Currently this is based only on the current packet
2611 if ((local_transport_info.media_port[n] != 0) &&
2612 (local_transport_info.proto_bitmask[n] & SDP_T38_PROTO)) {
2613 if (strlen(sdp_pi->summary_str))
2614 g_strlcat(sdp_pi->summary_str, " ", 50);
2615 g_strlcat(sdp_pi->summary_str, "t38", 50);
2619 /* Free the remainded hash tables not used */
2620 /* XXX - more placeholder functionality */
2621 if (transport_info == &local_transport_info) {
2622 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
2624 if (!transport_info->media[n].set_rtp)
2626 rtp_dyn_payload_free(transport_info->media[n].rtp_dyn_payload);
2627 transport_info->media[n].rtp_dyn_payload = NULL;
2632 datalen = tvb_captured_length_remaining(tvb, offset);
2634 proto_tree_add_item(sdp_tree, hf_sdp_data, tvb, offset, datalen, ENC_NA);
2636 /* Report this packet to the tap */
2637 tap_queue_packet(sdp_tap, pinfo, sdp_pi);
2641 proto_register_sdp(void)
2643 static hf_register_info hf[] = {
2644 { &hf_protocol_version,
2645 { "Session Description Protocol Version (v)", "sdp.version",
2646 FT_STRING, BASE_NONE, NULL, 0x0,
2650 { "Owner/Creator, Session Id (o)",
2651 "sdp.owner", FT_STRING, BASE_NONE, NULL,
2655 { "Session Name (s)", "sdp.session_name",
2656 FT_STRING, BASE_NONE, NULL, 0x0,
2660 { "Session Information (i)", "sdp.session_info",
2661 FT_STRING, BASE_NONE, NULL, 0x0,
2665 { "URI of Description (u)", "sdp.uri",
2666 FT_STRING, BASE_NONE, NULL, 0x0,
2670 { "E-mail Address (e)", "sdp.email",
2671 FT_STRING, BASE_NONE, NULL, 0x0,
2672 "E-mail Address", HFILL }
2675 { "Phone Number (p)", "sdp.phone",
2676 FT_STRING, BASE_NONE, NULL, 0x0,
2679 { &hf_connection_info,
2680 { "Connection Information (c)", "sdp.connection_info",
2681 FT_STRING, BASE_NONE, NULL, 0x0,
2685 { "Bandwidth Information (b)", "sdp.bandwidth",
2686 FT_STRING, BASE_NONE, NULL, 0x0,
2690 { "Time Zone Adjustments (z)", "sdp.timezone",
2691 FT_STRING, BASE_NONE, NULL, 0x0,
2694 { &hf_encryption_key,
2695 { "Encryption Key (k)", "sdp.encryption_key",
2696 FT_STRING, BASE_NONE, NULL, 0x0,
2699 { &hf_session_attribute,
2700 { "Session Attribute (a)", "sdp.session_attr",
2701 FT_STRING, BASE_NONE, NULL, 0x0,
2704 { &hf_media_attribute,
2705 { "Media Attribute (a)", "sdp.media_attr",
2706 FT_STRING, BASE_NONE, NULL, 0x0,
2710 { "Time Description, active time (t)",
2711 "sdp.time", FT_STRING, BASE_NONE, NULL,
2715 { "Repeat Time (r)", "sdp.repeat_time",
2716 FT_STRING, BASE_NONE, NULL, 0x0,
2720 { "Media Description, name and address (m)",
2721 "sdp.media", FT_STRING, BASE_NONE, NULL,
2725 { "Media Title (i)", "sdp.media_title",
2726 FT_STRING, BASE_NONE, NULL, 0x0,
2727 "Media Title", HFILL }
2730 { "Unknown", "sdp.unknown",
2731 FT_STRING, BASE_NONE, NULL, 0x0,
2735 { "Invalid line", "sdp.invalid",
2736 FT_STRING, BASE_NONE, NULL, 0x0,
2739 { &hf_owner_username,
2740 { "Owner Username", "sdp.owner.username",
2741 FT_STRING, BASE_NONE, NULL, 0x0,
2744 { &hf_owner_sessionid,
2745 { "Session ID", "sdp.owner.sessionid",
2746 FT_STRING, BASE_NONE, NULL, 0x0,
2749 { &hf_owner_version,
2750 { "Session Version", "sdp.owner.version",
2751 FT_STRING, BASE_NONE, NULL, 0x0,
2754 { &hf_owner_network_type,
2755 { "Owner Network Type", "sdp.owner.network_type",
2756 FT_STRING, BASE_NONE, NULL, 0x0,
2759 { &hf_owner_address_type,
2760 { "Owner Address Type", "sdp.owner.address_type",
2761 FT_STRING, BASE_NONE, NULL, 0x0,
2764 { &hf_owner_address,
2765 { "Owner Address", "sdp.owner.address",
2766 FT_STRING, BASE_NONE, NULL, 0x0,
2769 { &hf_connection_info_network_type,
2770 { "Connection Network Type", "sdp.connection_info.network_type",
2771 FT_STRING, BASE_NONE, NULL, 0x0,
2774 { &hf_connection_info_address_type,
2775 { "Connection Address Type", "sdp.connection_info.address_type",
2776 FT_STRING, BASE_NONE, NULL, 0x0,
2779 { &hf_connection_info_connection_address,
2780 { "Connection Address", "sdp.connection_info.address",
2781 FT_STRING, BASE_NONE, NULL, 0x0,
2784 { &hf_connection_info_ttl,
2785 { "Connection TTL", "sdp.connection_info.ttl",
2786 FT_STRING, BASE_NONE, NULL, 0x0,
2789 { &hf_connection_info_num_addr,
2790 { "Connection Number of Addresses", "sdp.connection_info.num_addr",
2791 FT_STRING, BASE_NONE, NULL, 0x0,
2794 { &hf_bandwidth_modifier,
2795 { "Bandwidth Modifier", "sdp.bandwidth.modifier",
2796 FT_STRING, BASE_NONE, NULL, 0x0,
2799 { &hf_bandwidth_value,
2800 { "Bandwidth Value", "sdp.bandwidth.value",
2801 FT_STRING, BASE_NONE, NULL, 0x0,
2802 "Bandwidth Value (in kbits/s)", HFILL }
2805 { "Session Start Time", "sdp.time.start",
2806 FT_STRING, BASE_NONE, NULL, 0x0,
2810 { "Session Stop Time", "sdp.time.stop",
2811 FT_STRING, BASE_NONE, NULL, 0x0,
2814 { &hf_repeat_time_interval,
2815 { "Repeat Interval", "sdp.repeat_time.interval",
2816 FT_STRING, BASE_NONE, NULL, 0x0,
2819 { &hf_repeat_time_duration,
2820 { "Repeat Duration", "sdp.repeat_time.duration",
2821 FT_STRING, BASE_NONE, NULL, 0x0,
2824 { &hf_repeat_time_offset,
2825 { "Repeat Offset", "sdp.repeat_time.offset",
2826 FT_STRING, BASE_NONE, NULL, 0x0,
2829 { &hf_timezone_time,
2830 { "Timezone Time", "sdp.timezone.time",
2831 FT_STRING, BASE_NONE, NULL, 0x0,
2834 { &hf_timezone_offset,
2835 { "Timezone Offset", "sdp.timezone.offset",
2836 FT_STRING, BASE_NONE, NULL, 0x0,
2839 { &hf_encryption_key_type,
2840 { "Key Type", "sdp.encryption_key.type",
2841 FT_STRING, BASE_NONE, NULL, 0x0,
2844 { &hf_encryption_key_data,
2845 { "Key Data", "sdp.encryption_key.data",
2846 FT_STRING, BASE_NONE, NULL, 0x0,
2849 { &hf_session_attribute_field,
2850 { "Session Attribute Fieldname", "sdp.session_attr.field",
2851 FT_STRING, BASE_NONE, NULL, 0x0,
2854 { &hf_session_attribute_value,
2855 { "Session Attribute Value", "sdp.session_attr.value",
2856 FT_STRING, BASE_NONE, NULL, 0x0,
2860 { "Media Type", "sdp.media.media",
2861 FT_STRING, BASE_NONE, NULL, 0x0,
2865 { "Media Port", "sdp.media.port",
2866 FT_UINT16, BASE_DEC, NULL, 0x0,
2869 { &hf_media_port_string,
2870 { "Media Port", "sdp.media.port_string",
2871 FT_STRING, BASE_NONE, NULL, 0x0,
2874 { &hf_media_portcount,
2875 { "Media Port Count", "sdp.media.portcount",
2876 FT_STRING, BASE_NONE, NULL, 0x0,
2880 { "Media Protocol", "sdp.media.proto",
2881 FT_STRING, BASE_NONE, NULL, 0x0,
2885 { "Media Format", "sdp.media.format",
2886 FT_STRING, BASE_NONE, NULL, 0x0,
2889 { &hf_media_attribute_field,
2890 { "Media Attribute Fieldname", "sdp.media_attribute.field",
2891 FT_STRING, BASE_NONE, NULL, 0x0,
2894 { &hf_media_attribute_value,
2895 { "Media Attribute Value", "sdp.media_attribute.value",
2896 FT_STRING, BASE_NONE, NULL, 0x0,
2899 { &hf_media_encoding_name,
2900 { "MIME Type", "sdp.mime.type",
2901 FT_STRING, BASE_NONE, NULL, 0x0,
2902 "SDP MIME Type", HFILL }
2904 { &hf_media_sample_rate,
2905 { "Sample Rate", "sdp.sample_rate",
2906 FT_STRING, BASE_NONE, NULL, 0x0,
2909 { &hf_media_format_specific_parameter,
2910 { "Media format specific parameters", "sdp.fmtp.parameter",
2911 FT_STRING, BASE_NONE, NULL, 0x0,
2912 "Format specific parameter(fmtp)", HFILL }
2914 { &hf_ipbcp_version,
2915 { "IPBCP Protocol Version", "sdp.ipbcp.version",
2916 FT_STRING, BASE_NONE, NULL, 0x0,
2920 { "IPBCP Command Type", "sdp.ipbcp.command",
2921 FT_STRING, BASE_NONE, NULL, 0x0,
2924 {&hf_sdp_fmtp_mpeg4_profile_level_id,
2925 { "Level Code", "sdp.fmtp.profile_level_id",
2926 FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0,
2929 { &hf_sdp_fmtp_h263_profile,
2930 { "Profile", "sdp.fmtp.h263profile",
2931 FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0,
2934 { &hf_sdp_fmtp_h263_level,
2935 { "Level", "sdp.fmtp.h263level",
2936 FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0,
2939 { &hf_sdp_h264_packetization_mode,
2940 { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
2941 FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0,
2944 { &hf_SDPh223LogicalChannelParameters,
2945 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
2946 FT_NONE, BASE_NONE, NULL, 0,
2949 { &hf_key_mgmt_att_value,
2950 { "Key Management", "sdp.key_mgmt",
2951 FT_STRING, BASE_NONE, NULL, 0x0,
2954 { &hf_key_mgmt_prtcl_id,
2955 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
2956 FT_STRING, BASE_NONE, NULL, 0x0,
2959 { &hf_key_mgmt_data,
2960 { "Key Management Data", "sdp.key_mgmt.data",
2961 FT_BYTES, BASE_NONE, NULL, 0x0,
2964 { &hf_sdp_crypto_tag,
2965 { "tag", "sdp.crypto.tag",
2966 FT_UINT32, BASE_DEC, NULL, 0x0,
2969 { &hf_sdp_crypto_crypto_suite,
2970 { "Crypto suite", "sdp.crypto.crypto_suite",
2971 FT_STRING, BASE_NONE, NULL, 0x0,
2974 { &hf_sdp_crypto_master_key,
2975 { "Master Key", "sdp.crypto.master_key",
2976 FT_BYTES, BASE_NONE, NULL, 0x0,
2979 { &hf_sdp_crypto_master_salt,
2980 { "Master salt", "sdp.crypto.master_salt",
2981 FT_BYTES, BASE_NONE, NULL, 0x0,
2984 { &hf_sdp_crypto_lifetime,
2985 { "Lifetime", "sdp.crypto.lifetime",
2986 FT_STRING, BASE_NONE, NULL, 0x0,
2989 { &hf_sdp_crypto_mki,
2990 { "mki-value", "sdp.crypto.mki-valu",
2991 FT_STRING, BASE_NONE, NULL, 0x0,
2994 { &hf_sdp_crypto_mki_length,
2995 { "mki_length", "sdp.crypto.mki_length",
2996 FT_STRING, BASE_NONE, NULL, 0x0,
2999 /* Generated from convert_proto_tree_add_text.pl */
3000 { &hf_sdp_nal_unit_1_string, { "NAL unit 1 string", "sdp.nal_unit_1_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3001 { &hf_sdp_nal_unit_2_string, { "NAL unit 2 string", "sdp.nal_unit_2_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3002 { &hf_sdp_key_and_salt, { "Key and Salt", "sdp.key_and_salt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3003 { &hf_sdp_data, { "Data", "sdp.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3005 static gint *ett[] = {
3008 &ett_sdp_connection_info,
3011 &ett_sdp_repeat_time,
3013 &ett_sdp_encryption_key,
3014 &ett_sdp_session_attribute,
3016 &ett_sdp_media_attribute,
3019 &ett_sdp_crypto_key_parameters,
3022 static ei_register_info ei[] = {
3023 { &ei_sdp_invalid_key_param,
3024 { "sdp.invalid_key_param",
3025 PI_MALFORMED, PI_NOTE,
3026 "Invalid key-param (no ':' delimiter)",
3030 { &ei_sdp_invalid_line_equal,
3031 { "sdp.invalid_line.no_equal",
3032 PI_MALFORMED, PI_NOTE,
3033 "Invalid SDP line (no '=' delimiter)",
3037 { &ei_sdp_invalid_line_fields,
3038 { "sdp.invalid_line.missing_fields",
3039 PI_MALFORMED, PI_ERROR,
3040 "Invalid SDP line (missing required fields)",
3044 { &ei_sdp_invalid_line_space,
3045 { "sdp.invalid_line.extra_space",
3046 PI_MALFORMED, PI_ERROR,
3047 "Invalid SDP whitespace (extra space character)",
3051 { &ei_sdp_invalid_conversion,
3052 { "sdp.invalid_conversion",
3053 PI_PROTOCOL, PI_WARN,
3054 "Invalid conversion",
3060 module_t *sdp_module;
3061 expert_module_t* expert_sdp;
3063 proto_sdp = proto_register_protocol("Session Description Protocol",
3065 proto_register_field_array(proto_sdp, hf, array_length(hf));
3066 proto_register_subtree_array(ett, array_length(ett));
3067 expert_sdp = expert_register_protocol(proto_sdp);
3068 expert_register_field_array(expert_sdp, ei, array_length(ei));
3070 key_mgmt_dissector_table = register_dissector_table("key_mgmt",
3071 "Key Management", FT_STRING, BASE_NONE);
3073 * Preferences registration
3075 sdp_module = prefs_register_protocol(proto_sdp, NULL);
3076 prefs_register_bool_preference(sdp_module, "establish_conversation",
3077 "Establish Media Conversation",
3078 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
3079 "upon port numbers found in SDP payload",
3080 &global_sdp_establish_conversation);
3082 sdp_transport_reqs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3083 sdp_transport_rsps = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3086 * Register the dissector by name, so other dissectors can
3087 * grab it by name rather than just referring to it directly.
3089 register_dissector("sdp", dissect_sdp, proto_sdp);
3091 /* Register for tapping */
3092 sdp_tap = register_tap("sdp");
3094 /* compile patterns */
3095 ws_mempbrk_compile(&pbrk_digits, "0123456789");
3096 ws_mempbrk_compile(&pbrk_alpha, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
3100 proto_reg_handoff_sdp(void)
3102 dissector_handle_t sdp_handle;
3104 rtcp_handle = find_dissector("rtcp");
3105 msrp_handle = find_dissector("msrp");
3106 sprt_handle = find_dissector("sprt");
3107 h264_handle = find_dissector("h264");
3108 mp4ves_handle = find_dissector("mp4ves");
3110 proto_sprt = dissector_handle_get_protocol_index(find_dissector("sprt"));
3112 sdp_handle = find_dissector("sdp");
3113 dissector_add_string("media_type", "application/sdp", sdp_handle);
3114 dissector_add_uint("bctp.tpi", 0x20, sdp_handle);
3118 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3123 * indent-tabs-mode: nil
3126 * vi: set shiftwidth=4 tabstop=8 expandtab:
3127 * :indentSize=4:tabSize=8:noTabs=true: