HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-sdp.c
blob25666a4ae4e73fc50cf68f6c890cfa2556021f2e
1 /* packet-sdp.c
2 * Routines for SDP packet disassembly (RFC 2327)
4 * Jason Lango <jal@netapp.com>
5 * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
7 * $Id$
9 * Wireshark - Network traffic analyzer
10 * By Gerald Combs <gerald@wireshark.org>
11 * Copyright 1998 Gerald Combs
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * Ref http://www.ietf.org/rfc/rfc4566.txt?number=4566
29 #include "config.h"
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
33 #endif
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
36 #endif
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
39 #endif
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
44 #ifdef HAVE_WINSOCK2_H
45 #include <winsock2.h> /* needed to define AF_ values on Windows */
46 #endif
48 #ifdef NEED_INET_V6DEFS_H
49 # include "wsutil/inet_v6defs.h"
50 #endif
52 #include <glib.h>
54 #include <epan/packet.h>
55 #include <epan/exceptions.h>
56 #include <epan/strutil.h>
57 #include <epan/wmem/wmem.h>
58 #include <epan/base64.h>
59 #include <epan/asn1.h>
60 #include <epan/prefs.h>
61 #include <epan/expert.h>
62 #include <epan/tap.h>
63 #include <epan/rtp_pt.h>
64 #include <epan/show_exception.h>
66 #include "packet-sdp.h"
67 #include "packet-rtp.h"
69 #include "packet-rtcp.h"
70 #include "packet-t38.h"
71 #include "packet-msrp.h"
72 #include "packet-sprt.h"
73 #include "packet-per.h"
74 #include "packet-h245.h"
75 #include "packet-h264.h"
76 #include "packet-mp4ves.h"
78 static dissector_handle_t rtcp_handle;
79 static dissector_handle_t sprt_handle;
80 static dissector_handle_t msrp_handle;
81 static dissector_handle_t h264_handle;
82 static dissector_handle_t mp4ves_handle;
84 static int sdp_tap = -1;
86 static int proto_sdp = -1;
87 static int proto_sprt = -1;
89 static const char* UNKNOWN_ENCODING = "Unknown";
90 static wmem_tree_t *sdp_transport_reqs = NULL;
91 static wmem_tree_t *sdp_transport_rsps = NULL;
93 /* preference globals */
94 static gboolean global_sdp_establish_conversation = TRUE;
96 /* Top level fields */
97 static int hf_protocol_version = -1;
98 static int hf_owner = -1;
99 static int hf_session_name = -1;
100 static int hf_session_info = -1;
101 static int hf_uri = -1;
102 static int hf_email = -1;
103 static int hf_phone = -1;
104 static int hf_connection_info = -1;
105 static int hf_bandwidth = -1;
106 static int hf_timezone = -1;
107 static int hf_encryption_key = -1;
108 static int hf_session_attribute = -1;
109 static int hf_media_attribute = -1;
110 static int hf_time = -1;
111 static int hf_repeat_time = -1;
112 static int hf_media = -1;
113 static int hf_media_title = -1;
114 static int hf_unknown = -1;
115 static int hf_invalid = -1;
116 static int hf_ipbcp_version = -1;
117 static int hf_ipbcp_type = -1;
119 /* hf_owner subfields*/
120 static int hf_owner_username = -1;
121 static int hf_owner_sessionid = -1;
122 static int hf_owner_version = -1;
123 static int hf_owner_network_type = -1;
124 static int hf_owner_address_type = -1;
125 static int hf_owner_address = -1;
127 /* hf_connection_info subfields */
128 static int hf_connection_info_network_type = -1;
129 static int hf_connection_info_address_type = -1;
130 static int hf_connection_info_connection_address = -1;
131 static int hf_connection_info_ttl = -1;
132 static int hf_connection_info_num_addr = -1;
134 /* hf_bandwidth subfields */
135 static int hf_bandwidth_modifier = -1;
136 static int hf_bandwidth_value = -1;
138 /* hf_time subfields */
139 static int hf_time_start = -1;
140 static int hf_time_stop = -1;
142 /* hf_repeat_time subfield */
143 static int hf_repeat_time_interval = -1;
144 static int hf_repeat_time_duration = -1;
145 static int hf_repeat_time_offset = -1;
147 /* hf_timezone subfields */
148 static int hf_timezone_time = -1;
149 static int hf_timezone_offset = -1;
151 /* hf_encryption_key subfields */
152 static int hf_encryption_key_type = -1;
153 static int hf_encryption_key_data = -1;
155 /* hf_session_attribute subfields */
156 static int hf_session_attribute_field = -1;
157 static int hf_session_attribute_value = -1;
159 /* hf_media subfields */
160 static int hf_media_media = -1;
161 static int hf_media_port = -1;
162 static int hf_media_portcount = -1;
163 static int hf_media_proto = -1;
164 static int hf_media_format = -1;
166 /* hf_session_attribute subfields */
167 static int hf_media_attribute_field = -1;
168 static int hf_media_attribute_value = -1;
169 static int hf_media_encoding_name = -1;
170 static int hf_media_sample_rate = -1;
171 static int hf_media_format_specific_parameter = -1;
172 static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
173 static int hf_sdp_fmtp_h263_profile = -1;
174 static int hf_sdp_fmtp_h263_level = -1;
175 static int hf_sdp_h264_packetization_mode = -1;
176 static int hf_SDPh223LogicalChannelParameters = -1;
178 /* hf_session_attribute hf_media_attribute subfields */
179 static int hf_key_mgmt_att_value = -1;
180 static int hf_key_mgmt_prtcl_id = -1;
181 static int hf_key_mgmt_data = -1;
183 static int hf_sdp_crypto_tag = -1;
184 static int hf_sdp_crypto_crypto_suite = -1;
185 static int hf_sdp_crypto_master_key = -1;
186 static int hf_sdp_crypto_master_salt = -1;
187 static int hf_sdp_crypto_lifetime = -1;
188 static int hf_sdp_crypto_mki = -1;
189 static int hf_sdp_crypto_mki_length = -1;
191 /* trees */
192 static int ett_sdp = -1;
193 static int ett_sdp_owner = -1;
194 static int ett_sdp_connection_info = -1;
195 static int ett_sdp_bandwidth = -1;
196 static int ett_sdp_time = -1;
197 static int ett_sdp_repeat_time = -1;
198 static int ett_sdp_timezone = -1;
199 static int ett_sdp_encryption_key = -1;
200 static int ett_sdp_session_attribute = -1;
201 static int ett_sdp_media = -1;
202 static int ett_sdp_media_attribute = -1;
203 static int ett_sdp_fmtp = -1;
204 static int ett_sdp_key_mgmt = -1;
205 static int ett_sdp_crypto_key_parameters = -1;
207 static expert_field ei_sdp_invalid_key_param = EI_INIT;
208 static expert_field ei_sdp_invalid_line = EI_INIT;
210 #define SDP_RTP_PROTO 0x00000001
211 #define SDP_SRTP_PROTO 0x00000002
212 #define SDP_T38_PROTO 0x00000004
213 #define SDP_MSRP_PROTO 0x00000008
214 #define SDP_SPRT_PROTO 0x00000010
215 #define SDP_IPv4 0x80000000
216 #define SDP_IPv6 0x40000000
217 #define SDP_MSRP_IPv4 0x20000000
218 #define SDP_VIDEO 0x10000000
221 #define SDP_MAX_RTP_CHANNELS 4
222 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
223 #define SDP_NO_OF_PT 128
224 typedef struct {
225 gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
226 gint8 pt_count;
227 GHashTable *rtp_dyn_payload;
228 gboolean set_rtp;
229 } transport_media_pt_t;
231 typedef struct {
232 enum sdp_exchange_type sdp_status;
233 char *encoding_name[SDP_NO_OF_PT];
234 int sample_rate[SDP_NO_OF_PT];
235 int media_port[SDP_MAX_RTP_CHANNELS];
236 address src_addr[SDP_MAX_RTP_CHANNELS];
237 guint proto_bitmask[SDP_MAX_RTP_CHANNELS];
238 transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
239 gint8 media_count;
240 /* SRTP related info XXX note currently we only handle one crypto line in the SDP
241 * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
242 * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
243 * and the SDP dissector just provide the relevant data.
245 guint encryption_algorithm;
246 guint auth_algorithm;
247 guint mki_len; /* number of octets used for the MKI in the RTP payload */
248 guint auth_tag_len; /* number of octets used for the Auth Tag in the RTP payload */
249 } transport_info_t;
251 /* Data that is retrieved from a packet, but does not need to be kept */
252 typedef struct {
253 char *connection_address;
254 char *connection_type;
255 char *media_type;
256 char *media_port[SDP_MAX_RTP_CHANNELS];
257 char *media_proto[SDP_MAX_RTP_CHANNELS];
258 guint8 media_count;
260 /* MSRP transport info (as set while parsing path attribute) */
261 gboolean msrp_transport_address_set;
262 guint32 msrp_ipaddr[4];
263 guint16 msrp_port_number;
265 } disposable_media_info_t;
267 /* key-mgmt dissector
268 * IANA registry:
269 * http://www.iana.org/assignments/sdp-parameters
271 static dissector_table_t key_mgmt_dissector_table;
273 /* Subdissector functions */
274 static void
275 dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) {
276 proto_tree *sdp_owner_tree;
277 gint offset, next_offset, tokenlen;
279 offset = 0;
281 sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner);
283 /* Find the username */
284 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
285 if (next_offset == -1)
286 return;
287 tokenlen = next_offset - offset;
289 proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
290 ENC_ASCII|ENC_NA);
291 offset = next_offset + 1;
293 /* Find the session id */
294 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
295 if (next_offset == -1)
296 return;
297 tokenlen = next_offset - offset;
299 proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
300 tokenlen, ENC_ASCII|ENC_NA);
301 offset = next_offset + 1;
303 /* Find the version */
304 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
305 if (next_offset == -1)
306 return;
307 tokenlen = next_offset - offset;
309 proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
310 ENC_ASCII|ENC_NA);
311 offset = next_offset + 1;
313 /* Find the network type */
314 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
315 if (next_offset == -1)
316 return;
317 tokenlen = next_offset - offset;
319 proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
320 tokenlen, ENC_ASCII|ENC_NA);
321 offset = next_offset + 1;
323 /* Find the address type */
324 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
325 if (next_offset == -1)
326 return;
327 tokenlen = next_offset - offset;
329 proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
330 tokenlen, ENC_ASCII|ENC_NA);
331 offset = next_offset + 1;
333 /* Find the address */
334 proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_ASCII|ENC_NA);
338 * XXX - this can leak memory if an exception is thrown after we've fetched
339 * a string.
341 static void
342 dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
343 disposable_media_info_t *media_info) {
344 proto_tree *sdp_connection_info_tree;
345 gint offset, next_offset, tokenlen;
347 offset = 0;
349 sdp_connection_info_tree = proto_item_add_subtree(ti,
350 ett_sdp_connection_info);
352 /* Find the network type */
353 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
354 if (next_offset == -1)
355 return;
356 tokenlen = next_offset - offset;
358 proto_tree_add_item(sdp_connection_info_tree,
359 hf_connection_info_network_type, tvb, offset, tokenlen,
360 ENC_ASCII|ENC_NA);
361 offset = next_offset + 1;
363 /* Find the address type */
364 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
365 if (next_offset == -1)
366 return;
367 tokenlen = next_offset - offset;
368 /* Save connection address type */
369 media_info->connection_type = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
372 proto_tree_add_item(sdp_connection_info_tree,
373 hf_connection_info_address_type, tvb, offset, tokenlen,
374 ENC_ASCII|ENC_NA);
375 offset = next_offset + 1;
377 /* Find the connection address */
378 /* XXX - what if there's a <number of addresses> value? */
379 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
380 if (next_offset == -1) {
381 tokenlen = -1; /* end of tvbuff */
382 /* Save connection address */
383 media_info->connection_address =
384 (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tvb_length_remaining(tvb, offset));
385 } else {
386 tokenlen = next_offset - offset;
387 /* Save connection address */
388 media_info->connection_address = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
391 proto_tree_add_item(sdp_connection_info_tree,
392 hf_connection_info_connection_address, tvb, offset,
393 tokenlen, ENC_ASCII|ENC_NA);
394 if (next_offset != -1) {
395 offset = next_offset + 1;
396 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
397 if (next_offset == -1) {
398 tokenlen = -1; /* end of tvbuff */
399 } else {
400 tokenlen = next_offset - offset;
402 proto_tree_add_item(sdp_connection_info_tree,
403 hf_connection_info_ttl, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
404 if (next_offset != -1) {
405 offset = next_offset + 1;
406 proto_tree_add_item(sdp_connection_info_tree,
407 hf_connection_info_num_addr, tvb, offset, -1, ENC_ASCII|ENC_NA);
412 static void
413 dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) {
414 proto_tree *sdp_bandwidth_tree;
415 gint offset, next_offset, tokenlen;
416 proto_item *item;
417 gboolean unit_is_kbs = FALSE;
418 gboolean unit_is_bps = FALSE;
420 offset = 0;
422 sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth);
424 /* find the modifier */
425 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
427 if (next_offset == -1)
428 return;
430 tokenlen = next_offset - offset;
432 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
433 tokenlen, ENC_ASCII|ENC_NA);
434 if (tvb_strneql(tvb, offset, "CT", 2) == 0) {
435 proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
436 unit_is_kbs = TRUE;
437 } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) {
438 proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
439 unit_is_kbs = TRUE;
440 } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) {
441 proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
442 unit_is_bps = TRUE;
446 offset = next_offset + 1;
448 item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
449 ENC_ASCII|ENC_NA);
450 if (unit_is_kbs == TRUE)
451 proto_item_append_text(item, " kb/s");
452 if (unit_is_bps == TRUE)
453 proto_item_append_text(item, " b/s");
456 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) {
457 proto_tree *sdp_time_tree;
458 gint offset, next_offset, tokenlen;
460 offset = 0;
462 sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
464 /* get start time */
465 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
466 if (next_offset == -1)
467 return;
469 tokenlen = next_offset - offset;
470 proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
471 ENC_ASCII|ENC_NA);
473 /* get stop time */
474 offset = next_offset + 1;
475 proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_ASCII|ENC_NA);
478 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) {
479 proto_tree *sdp_repeat_time_tree;
480 gint offset, next_offset, tokenlen;
482 offset = 0;
484 sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
486 /* get interval */
487 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
488 if (next_offset == -1)
489 return;
491 tokenlen = next_offset - offset;
492 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
493 offset, tokenlen, ENC_ASCII|ENC_NA);
495 /* get duration */
496 offset = next_offset + 1;
497 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
498 if (next_offset == -1)
499 return;
501 tokenlen = next_offset - offset;
502 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb,
503 offset, tokenlen, ENC_ASCII|ENC_NA);
505 /* get offsets */
507 offset = next_offset +1;
508 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
509 if (next_offset != -1) {
510 tokenlen = next_offset - offset;
511 } else {
512 tokenlen = -1; /* end of tvbuff */
514 proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
515 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
516 } while (next_offset != -1);
519 static void
520 dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) {
521 proto_tree* sdp_timezone_tree;
522 gint offset, next_offset, tokenlen;
524 offset = 0;
526 sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone);
529 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
530 if (next_offset == -1)
531 break;
532 tokenlen = next_offset - offset;
534 proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
535 tokenlen, ENC_ASCII|ENC_NA);
536 offset = next_offset + 1;
537 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
538 if (next_offset != -1) {
539 tokenlen = next_offset - offset;
540 } else {
541 tokenlen = -1; /* end of tvbuff */
543 proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
544 tokenlen, ENC_ASCII|ENC_NA);
545 offset = next_offset + 1;
546 } while (next_offset != -1);
551 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) {
552 proto_tree *sdp_encryption_key_tree;
553 gint offset, next_offset, tokenlen;
555 offset = 0;
557 sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key);
559 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
561 if (next_offset == -1)
562 return;
564 tokenlen = next_offset - offset;
566 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type,
567 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
569 offset = next_offset + 1;
570 proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data,
571 tvb, offset, -1, ENC_ASCII|ENC_NA);
574 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
575 gchar *data_p = NULL;
576 gchar *prtcl_id = NULL;
577 gint len;
578 tvbuff_t *keymgmt_tvb;
579 gboolean found_match = FALSE;
580 proto_tree *key_tree;
581 gint next_offset;
582 gint offset = 0;
583 gint tokenlen;
585 key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
587 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
589 if (next_offset == -1)
590 return;
592 tokenlen = next_offset - offset;
593 prtcl_id = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
595 proto_tree_add_item(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
597 offset = next_offset + 1;
599 len = tvb_length_remaining(tvb, offset);
600 if (len < 0)
601 return;
603 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, len);
604 keymgmt_tvb = base64_to_tvb(tvb, data_p);
605 add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
607 if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) {
608 found_match = dissector_try_string(key_mgmt_dissector_table,
609 prtcl_id,
610 keymgmt_tvb, pinfo,
611 key_tree, NULL);
614 if (found_match) {
615 proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
616 keymgmt_tvb, 0, -1, ENC_NA);
617 PROTO_ITEM_SET_HIDDEN(ti2);
618 } else {
619 proto_tree_add_item(key_tree, hf_key_mgmt_data,
620 keymgmt_tvb, 0, -1, ENC_NA);
626 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
627 proto_tree *sdp_session_attribute_tree;
628 gint offset, next_offset, tokenlen;
629 guint8 *field_name;
631 offset = 0;
633 sdp_session_attribute_tree = proto_item_add_subtree(ti,
634 ett_sdp_session_attribute);
636 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
638 if (next_offset == -1)
639 return;
641 tokenlen = next_offset - offset;
643 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_field,
644 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
646 field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
648 offset = next_offset + 1;
650 if (strcmp((char*)field_name, "ipbcp") == 0) {
651 offset = tvb_pbrk_guint8(tvb, offset, -1,"0123456789", NULL);
653 if (offset == -1)
654 return;
656 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
658 if (next_offset == -1)
659 return;
661 tokenlen = next_offset - offset;
663 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
665 offset = tvb_pbrk_guint8(tvb, offset, -1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
667 if (offset == -1)
668 return;
670 tokenlen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
672 if (tokenlen == -1)
673 return;
675 proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
676 } else if (strcmp((char*)field_name, "key-mgmt") == 0) {
677 tvbuff_t *key_tvb;
678 proto_item *key_ti;
680 key_tvb = tvb_new_subset_remaining(tvb, offset);
681 key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_ASCII|ENC_NA);
683 dissect_key_mgmt(key_tvb, pinfo, key_ti);
684 } else {
685 proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
686 tvb, offset, -1, ENC_ASCII|ENC_NA);
691 /* Dissect media description */
692 static void
693 dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
694 transport_info_t *transport_info, disposable_media_info_t *media_info) {
695 proto_tree *sdp_media_tree;
696 gint offset, next_offset, tokenlen, idx;
697 guint8 *media_format;
699 offset = 0;
701 /* Create tree for media session */
702 sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media);
704 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
706 if (next_offset == -1)
707 return;
709 tokenlen = next_offset - offset;
711 /* Type of media session */
712 proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
713 ENC_ASCII|ENC_NA);
715 media_info->media_type = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
717 offset = next_offset + 1;
719 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
720 if (next_offset == -1)
721 return;
722 tokenlen = next_offset - offset;
723 next_offset = tvb_find_guint8(tvb, offset, tokenlen, '/');
725 if (next_offset != -1) {
726 tokenlen = next_offset - offset;
727 /* Save port info */
728 media_info->media_port[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
730 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
731 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
732 offset = next_offset + 1;
733 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
734 if (next_offset == -1)
735 return;
736 tokenlen = next_offset - offset;
737 proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
738 tokenlen, ENC_ASCII|ENC_NA);
739 offset = next_offset + 1;
740 } else {
741 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
743 if (next_offset == -1)
744 return;
745 tokenlen = next_offset - offset;
746 /* Save port info */
747 media_info->media_port[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
748 /* XXX Remember Port */
749 proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
750 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
751 offset = next_offset + 1;
754 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
756 if ( next_offset == -1)
757 return;
759 tokenlen = next_offset - offset;
760 /* Save port protocol */
761 media_info->media_proto[media_info->media_count] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
763 /* XXX Remember Protocol */
764 proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
765 ENC_ASCII|ENC_NA);
767 do {
768 offset = next_offset + 1;
769 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
771 if (next_offset == -1) {
772 tokenlen = tvb_length_remaining(tvb, offset); /* End of tvbuff */
773 if (tokenlen == 0)
774 break; /* Nothing more left */
775 } else {
776 tokenlen = next_offset - offset;
779 if (!strcmp(media_info->media_proto[media_info->media_count], "RTP/AVP")) {
780 media_format = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
781 proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
782 tokenlen, val_to_str_ext((guint32)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u"));
783 idx = transport_info->media[transport_info->media_count].pt_count;
784 transport_info->media[transport_info->media_count].pt[idx] = (gint32)strtol((char*)media_format, NULL, 10);
785 if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
786 transport_info->media[transport_info->media_count].pt_count++;
787 } else {
788 proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
789 tokenlen, ENC_ASCII|ENC_NA);
791 } while (next_offset != -1);
793 /* XXX Dissect traffic to "Port" as "Protocol"
794 * Remember this Port/Protocol pair so we can tear it down again later
795 * Actually, it's harder than that:
796 * We need to find out the address of the other side first and it
797 * looks like that info can be found in SIP headers only.
802 static tvbuff_t *
803 ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
805 guint8 *buf = (guint8 *)wmem_alloc(pinfo->pool, 10240);
807 /* arbitrary maximum length */
808 if (len < 20480) {
809 int i;
810 tvbuff_t *bytes_tvb;
812 /* first, skip to where the encoded pdu starts, this is
813 the first hex digit after the '=' char.
815 while (1) {
816 if ((*msg == 0) || (*msg == '\n')) {
817 return NULL;
819 if (*msg == '=') {
820 msg++;
821 break;
823 msg++;
825 while (1) {
826 if ((*msg == 0) || (*msg == '\n')) {
827 return NULL;
829 if ( ((*msg >= '0') && (*msg <= '9'))
830 || ((*msg >= 'a') && (*msg <= 'f'))
831 || ((*msg >= 'A') && (*msg <= 'F'))) {
832 break;
834 msg++;
836 i = 0;
837 while (((*msg >= '0') && (*msg <= '9'))
838 || ((*msg >= 'a') && (*msg <= 'f'))
839 || ((*msg >= 'A') && (*msg <= 'F'))) {
840 int val;
841 if ((*msg >= '0') && (*msg <= '9')) {
842 val = (*msg)-'0';
843 } else if ((*msg >= 'a') && (*msg <= 'f')) {
844 val = (*msg)-'a'+10;
845 } else if ((*msg >= 'A') && (*msg <= 'F')) {
846 val = (*msg)-'A'+10;
847 } else {
848 return NULL;
850 val <<= 4;
851 msg++;
852 if ((*msg >= '0') && (*msg <= '9')) {
853 val |= (*msg)-'0';
854 } else if ((*msg >= 'a') && (*msg <= 'f')) {
855 val |= (*msg)-'a'+10;
856 } else if ((*msg >= 'A') && (*msg <= 'F')) {
857 val |= (*msg)-'A'+10;
858 } else {
859 return NULL;
861 msg++;
863 buf[i] = (guint8)val;
864 i++;
866 if (i == 0) {
867 return NULL;
869 bytes_tvb = tvb_new_child_real_data(tvb, buf, i, i);
870 add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
871 return bytes_tvb;
873 return NULL;
876 /* Annex X Profiles and levels definition */
877 static const value_string h263_profile_vals[] =
879 { 0, "Baseline Profile" },
880 { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
881 { 2, "Version 1 Backward-Compatibility Profile" },
882 { 3, "Version 2 Interactive and Streaming Wireless Profile" },
883 { 4, "Version 3 Interactive and Streaming Wireless Profile" },
884 { 5, "Conversational High Compression Profile" },
885 { 6, "Conversational Internet Profile" },
886 { 7, "Conversational Interlace Profile" },
887 { 8, "High Latency Profile" },
888 { 0, NULL },
892 /* RFC 4629 The level are described in table X.2 of H.263 annex X */
893 static const value_string h263_level_vals[] =
895 { 10, "QCIF (176 x 144), 1 x 64Kb/s" },
896 { 20, "CIF (352 x 288), 2 x 64Kb/s" },
897 { 30, "CIF (352 x 288), 6 x 64Kb/s" },
898 { 40, "CIF (352 x 288), 32 x 64Kb/s" },
899 { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
900 { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
901 { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
902 { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
903 { 0, NULL },
907 static const value_string h264_packetization_mode_vals[] =
909 { 0, "Single NAL mode" },
910 { 1, "Non-interleaved mode" },
911 { 2, "Interleaved mode" },
912 { 0, NULL },
916 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
918 static void
919 decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type) {
920 gint next_offset;
921 gint end_offset;
922 guint8 *field_name;
923 gchar *format_specific_parameter;
924 proto_item *item;
925 tvbuff_t * volatile data_tvb;
927 end_offset = offset + tokenlen;
929 #if 0
930 proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
931 tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
932 #endif
934 /* Look for an '=' within this value - this may indicate that there is a
935 profile-level-id parameter to find if the MPEG4 media type is in use */
936 next_offset = tvb_find_guint8(tvb, offset, -1, '=');
937 if (next_offset == -1)
939 /* Give up (and avoid exception) if '=' not found */
940 return;
943 /* Find the name of the parameter */
944 tokenlen = next_offset - offset;
945 field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
946 #if 0
947 proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
948 #endif
949 offset = next_offset;
951 /* Dissect the MPEG4 profile-level-id parameter if present */
952 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) {
953 if (strcmp((char*)field_name, "profile-level-id") == 0) {
954 offset++;
955 tokenlen = end_offset - offset;
956 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
957 item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
958 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
959 PROTO_ITEM_SET_GENERATED(item);
960 } else if (strcmp((char*)field_name, "config") == 0) {
961 /* String including "=" */
962 tokenlen = end_offset - offset;
963 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
964 /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
965 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
966 if (mp4ves_handle && data_tvb) {
967 dissect_mp4ves_config(data_tvb, pinfo, tree);
972 /* Dissect the H263-2000 profile parameter if present */
973 if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) ||
974 ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) {
975 if (strcmp((char*)field_name, "profile") == 0) {
976 offset++;
977 tokenlen = end_offset - offset;
978 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
979 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
980 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
981 PROTO_ITEM_SET_GENERATED(item);
982 } else if (strcmp((char*)field_name, "level") == 0) {
983 offset++;
984 tokenlen = end_offset - offset;
985 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
986 item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
987 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
988 PROTO_ITEM_SET_GENERATED(item);
993 /* Dissect the H264 profile-level-id parameter
994 * RFC 3984:
995 * A base16 [6] (hexadecimal) representation of
996 * the following three bytes in the sequence
997 * parameter set NAL unit specified in [1]: 1)
998 * profile_idc, 2) a byte herein referred to as
999 * profile-iop, composed of the values of
1000 * constraint_set0_flag, constraint_set1_flag,
1001 * constraint_set2_flag, and reserved_zero_5bits
1002 * in bit-significance order, starting from the
1003 * most significant bit, and 3) level_idc.
1005 if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H264") == 0)) {
1006 if (strcmp(field_name, "profile-level-id") == 0) {
1007 int length = 0;
1009 /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
1010 tokenlen = end_offset - offset;
1011 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1012 data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
1013 if (!data_tvb) {
1014 proto_tree_add_text(tree, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter);
1015 return;
1017 length = tvb_length(data_tvb);
1018 if (length == 3) {
1019 if (h264_handle && data_tvb) {
1020 dissect_h264_profile(data_tvb, pinfo, tree);
1022 } else {
1023 item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
1024 PROTO_ITEM_SET_GENERATED(item);
1026 } else if (strcmp(field_name, "packetization-mode") == 0) {
1027 offset++;
1028 tokenlen = end_offset - offset;
1029 format_specific_parameter = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1030 item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
1031 (guint32)strtol((char*)format_specific_parameter, NULL, 10));
1032 PROTO_ITEM_SET_GENERATED(item);
1033 } else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
1034 /* The value of the parameter is the
1035 base64 [6] representation of the initial
1036 parameter set NAL units as specified in
1037 sections 7.3.2.1 and 7.3.2.2 of [1]. The
1038 parameter sets are conveyed in decoding order,
1039 and no framing of the parameter set NAL units
1040 takes place. A comma is used to separate any
1041 pair of parameter sets in the list.
1043 gchar *data_p = NULL;
1044 gint comma_offset;
1047 /* Move past '=' */
1048 offset++;
1049 comma_offset = tvb_find_guint8(tvb, offset, -1, ',');
1050 if (comma_offset != -1) {
1051 tokenlen = comma_offset - offset;
1052 } else {
1053 tokenlen = end_offset - offset;
1056 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1057 proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 1 string: %s", data_p);
1059 /* proto_tree_add_text(tree, tvb, offset, tokenlen, "String %s", data_p); */
1060 data_tvb = base64_to_tvb(tvb, data_p);
1061 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
1063 if (h264_handle && data_tvb) {
1064 TRY {
1065 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1067 CATCH_NONFATAL_ERRORS {
1068 show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1070 ENDTRY;
1071 if (comma_offset != -1) {
1072 /* Second NAL unit */
1073 offset = comma_offset +1;
1074 tokenlen = end_offset - offset;
1075 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1076 proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 2 string: %s", data_p);
1077 data_tvb = base64_to_tvb(tvb, data_p);
1078 add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
1079 dissect_h264_nal_unit(data_tvb, pinfo, tree);
1087 typedef struct {
1088 const char *name;
1089 } sdp_names_t;
1091 #define SDP_RTPMAP 1
1092 #define SDP_FMTP 2
1093 #define SDP_PATH 3
1094 #define SDP_H248_ITEM 4
1095 #define SDP_CRYPTO 5
1096 #define SDP_SPRTMAP 6
1098 static const sdp_names_t sdp_media_attribute_names[] = {
1099 { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */
1100 { "rtpmap"}, /* 1 */
1101 { "fmtp"}, /* 2 */
1102 { "path"}, /* 3 */
1103 { "h248item"}, /* 4 */
1104 { "crypto"}, /* 5 */
1105 { "sprt"}, /* 6 */
1108 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
1110 guint i;
1112 for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
1113 if ((len == strlen(sdp_media_attribute_names[i].name)) &&
1114 (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0))
1115 return i;
1118 return -1;
1121 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length,
1122 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1123 proto_tree *sdp_media_attribute_tree, *parameter_item;
1124 proto_item *fmtp_item, *media_format_item, *parameter_tree;
1125 proto_tree *fmtp_tree;
1126 gint offset, next_offset, tokenlen, n, colon_offset;
1127 /*??guint8 *field_name;*/
1128 guint8 *payload_type;
1129 guint8 *attribute_value;
1130 gint *key;
1131 guint8 pt;
1132 gint sdp_media_attrbute_code;
1133 const char *msrp_res = "msrp://";
1134 const char *h324ext_h223lcparm = "h324ext/h223lcparm";
1135 gboolean has_more_pars = TRUE;
1136 tvbuff_t *h245_tvb;
1137 guint8 master_key_length = 0, master_salt_length = 0;
1138 encoding_name_and_rate_t *encoding_name_and_rate;
1140 offset = 0;
1142 /* Create attribute tree */
1143 sdp_media_attribute_tree = proto_item_add_subtree(ti,
1144 ett_sdp_media_attribute);
1145 /* Find end of field */
1146 colon_offset = tvb_find_guint8(tvb, offset, -1, ':');
1148 if (colon_offset == -1)
1149 return;
1151 /* Attribute field name is token before ':' */
1152 tokenlen = colon_offset - offset;
1153 proto_tree_add_item(sdp_media_attribute_tree,
1154 hf_media_attribute_field,
1155 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1156 /*??field_name = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);*/
1157 sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
1159 /* Skip colon */
1160 offset = colon_offset + 1;
1161 /* skip leading wsp */
1162 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1164 /* Value is the remainder of the line */
1165 attribute_value = tvb_get_string(wmem_packet_scope(), tvb, offset, tvb_length_remaining(tvb, offset));
1169 /*********************************************/
1170 /* Special parsing for some field name types */
1172 switch (sdp_media_attrbute_code) {
1173 case SDP_RTPMAP:
1174 /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
1175 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1177 if (next_offset == -1)
1178 return;
1180 tokenlen = next_offset - offset;
1182 proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
1183 offset, tokenlen, ENC_ASCII|ENC_NA);
1185 payload_type = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1187 offset = next_offset + 1;
1189 next_offset = tvb_find_guint8(tvb, offset, -1, '/');
1191 if (next_offset == -1) {
1192 return;
1195 tokenlen = next_offset - offset;
1197 proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
1198 offset, tokenlen, ENC_ASCII|ENC_NA);
1200 pt = atoi((char*)payload_type);
1201 if (pt >= SDP_NO_OF_PT) {
1202 return; /* Invalid */
1205 key = wmem_new(wmem_file_scope(), gint);
1206 *key = (gint)strtol((char*)payload_type, NULL, 10);
1208 transport_info->encoding_name[pt] = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1210 next_offset = next_offset + 1;
1211 offset = next_offset;
1212 while (length-1 >= next_offset) {
1213 if (!g_ascii_isdigit(tvb_get_guint8(tvb, next_offset)))
1214 break;
1215 next_offset++;
1217 tokenlen = next_offset - offset;
1218 proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
1219 offset, tokenlen, ENC_ASCII|ENC_NA);
1220 transport_info->sample_rate[pt] = atoi(tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1221 /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1222 For example:
1224 a=rtpmap:101 G726-32/8000
1225 m=audio 49170 RTP/AVP 0 97
1226 a=rtpmap:97 telephone-event/8000
1227 m=audio 49172 RTP/AVP 97 101
1228 a=rtpmap:97 G726-24/8000
1230 The Media attributes ("a="s) after the "m=" only apply for that "m=".
1231 If there is an "a=" before the first "m=", that attribute applies for
1232 all the session (all the "m="s).
1235 /* so, if this "a=" appear before any "m=", we add it to all the dynamic
1236 * hash tables
1238 if (transport_info->media_count < 0) {
1239 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1240 encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
1241 encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
1242 encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1243 if (n == 0) {
1244 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1245 key, encoding_name_and_rate);
1246 } else { /* we create a new key and encoding_name to assign to the other hash tables */
1247 gint *key2;
1248 key2 = wmem_new(wmem_file_scope(), gint);
1249 *key2 = (gint)strtol((char*)payload_type, NULL, 10);
1250 g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1251 key2, encoding_name_and_rate);
1254 return;
1255 /* if the "a=" is after an "m=", only apply to this "m=" */
1256 } else
1257 /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
1258 encoding_name_and_rate = wmem_new(wmem_file_scope(), encoding_name_and_rate_t);
1260 encoding_name_and_rate->encoding_name = wmem_strdup(wmem_file_scope(), transport_info->encoding_name[pt]);
1261 encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1262 g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
1263 key, encoding_name_and_rate);
1264 break;
1265 case SDP_FMTP:
1266 if (sdp_media_attribute_tree) {
1267 guint8 media_format;
1268 /* Reading the Format parameter(fmtp) */
1269 /* Skip leading space, if any */
1270 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1271 /* Media format extends to the next space */
1272 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1274 if (next_offset == -1)
1275 return;
1277 tokenlen = next_offset - offset;
1280 media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
1281 hf_media_format, tvb, offset,
1282 tokenlen, ENC_ASCII|ENC_NA);
1283 media_format = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1284 if (media_format >= SDP_NO_OF_PT) {
1285 return; /* Invalid */
1288 /* Append encoding name to format if known */
1289 proto_item_append_text(media_format_item, " [%s]",
1290 transport_info->encoding_name[media_format]);
1292 #if 0 /* XXX: ?? */
1293 payload_type = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1294 #endif
1295 /* Move offset past the payload type */
1296 offset = next_offset + 1;
1298 while (has_more_pars == TRUE) {
1299 next_offset = tvb_find_guint8(tvb, offset, -1, ';');
1300 offset = tvb_skip_wsp(tvb, offset, tvb_length_remaining(tvb, offset));
1302 if (next_offset == -1) {
1303 has_more_pars = FALSE;
1304 next_offset= tvb_length(tvb);
1307 /* There are at least 2 - add the first parameter */
1308 tokenlen = next_offset - offset;
1309 fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
1310 hf_media_format_specific_parameter, tvb,
1311 offset, tokenlen, ENC_ASCII|ENC_NA);
1313 fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
1315 decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
1316 transport_info->encoding_name[media_format]);
1318 /* Move offset past "; " and onto firts char */
1319 offset = next_offset + 1;
1322 break;
1323 case SDP_PATH:
1324 /* msrp attributes that contain address needed for conversation */
1325 /* RFC 4975
1326 * path = path-label ":" path-list
1327 * path-label = "path"
1328 * path-list= MSRP-URI *(SP MSRP-URI)
1329 * MSRP-URI = msrp-scheme "://" authority
1330 * ["/" session-id] ";" transport *( ";" URI-parameter)
1331 * ; authority as defined in RFC3986
1333 * msrp-scheme = "msrp" / "msrps"
1334 * RFC 3986
1335 * The authority component is preceded by a double slash ("//") and is terminated by
1336 * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1337 * the end of the URI.
1340 /* Check for "msrp://" */
1341 if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0) {
1342 int address_offset, port_offset, port_end_offset;
1344 /* Address starts here */
1345 address_offset = offset + (int)strlen(msrp_res);
1347 /* Port is after next ':' */
1348 port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
1349 /* Check if port is present if not skipp */
1350 if (port_offset!= -1) {
1351 /* Port ends with '/' */
1352 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
1353 if (port_end_offset == -1) {
1354 /* No "/" look for the ";" */
1355 port_end_offset = tvb_find_guint8(tvb, port_offset, -1, ';');;
1357 /* Attempt to convert address */
1358 if (inet_pton(AF_INET,
1359 (char*)tvb_get_string(wmem_packet_scope(), tvb, address_offset, port_offset-address_offset),
1360 &media_info->msrp_ipaddr) > 0) {
1361 /* Get port number */
1362 media_info->msrp_port_number = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, port_offset + 1, port_end_offset - port_offset - 1));
1363 /* Set flag so this info can be used */
1364 media_info->msrp_transport_address_set = TRUE;
1368 break;
1369 case SDP_H248_ITEM:
1370 /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
1371 if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
1372 /* A.5.1.3 H.223 Logical channel parameters
1373 * This property indicates the H.245
1374 * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1375 * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1376 * in ITU-T Rec. H.248.15 is used.
1378 gint len;
1379 asn1_ctx_t actx;
1381 len = (gint)strlen(attribute_value);
1382 h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
1383 /* arbitrary maximum length */
1384 /* should go through a handle, however, the two h245 entry
1385 points are different, one is over tpkt and the other is raw
1387 if (h245_tvb) {
1388 asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1389 dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
1390 sdp_media_attribute_tree,
1391 hf_SDPh223LogicalChannelParameters);
1394 break;
1395 case SDP_CRYPTO:
1396 /* http://tools.ietf.org/html/rfc4568
1397 * 9.1. Generic "Crypto" Attribute Grammar
1399 * The ABNF grammar for the crypto attribute is defined below:
1401 * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
1402 * *(1*WSP session-param)
1404 * tag = 1*9DIGIT
1405 * crypto-suite = 1*(ALPHA / DIGIT / "_")
1407 * key-params = key-param *(";" key-param)
1408 * key-param = key-method ":" key-info
1409 * key-method = "inline" / key-method-ext
1410 * key-method-ext = 1*(ALPHA / DIGIT / "_")
1411 * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
1412 * ; except semi-colon
1413 * session-param = 1*(VCHAR) ; visible (printing) characters
1415 * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
1419 /* We are at the first colon */
1420 /* tag */
1421 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1422 if(next_offset==-1){
1423 /* XXX Add expert item? */
1424 return;
1426 tokenlen = next_offset - offset;
1427 proto_tree_add_uint(sdp_media_attribute_tree, hf_sdp_crypto_tag, tvb, offset, tokenlen,
1428 atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen)));
1429 offset = next_offset + 1;
1431 /* crypto-suite */
1432 next_offset = tvb_find_guint8(tvb, offset, -1, ' ');
1433 if(next_offset==-1){
1434 /* XXX Add expert item? */
1435 return;
1437 tokenlen = next_offset - offset;
1438 parameter_item = proto_tree_add_item(sdp_media_attribute_tree, hf_sdp_crypto_crypto_suite,
1439 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1440 if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
1442 /* XXX This may only work in simple cases */
1443 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1444 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1445 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1446 /* number of octets used for the Auth Tag in the RTP payload */
1447 transport_info->auth_tag_len = 10;
1449 master_key_length = 16; /* 128 bits = 16 octets */
1450 master_salt_length = 14; /* 112 bits = 14 octets */
1451 } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
1452 /* XXX This may only work in simple cases */
1453 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1454 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1455 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1456 /* number of octets used for the Auth Tag in the RTP payload */
1457 transport_info->auth_tag_len = 4;
1459 master_key_length = 16; /* 128 bits = 16 octets */
1460 master_salt_length = 14; /* 112 bits = 14 octets */
1461 } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
1462 if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1463 /* XXX This may only work in simple cases */
1464 transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
1465 transport_info->auth_algorithm = SRTP_AUTH_ALG_HMAC_SHA1;
1466 /* number of octets used for the Auth Tag in the RTP payload */
1467 transport_info->auth_tag_len = 10;
1469 master_key_length = 16; /* 128 bits = 16 octets */
1470 master_salt_length = 14; /* 112 bits = 14 octets */
1472 offset = next_offset + 1;
1474 /* key-params */
1475 while (has_more_pars == TRUE) {
1476 int param_end_offset;
1477 tvbuff_t *key_salt_tvb;
1478 gchar *data_p = NULL;
1480 param_end_offset = tvb_find_guint8(tvb, offset, -1, ';');
1481 if (param_end_offset == -1) {
1482 has_more_pars = FALSE;
1483 param_end_offset = tvb_length(tvb);
1485 /* key-method or key-method-ext */
1486 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1487 if (next_offset == -1) {
1488 expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
1489 break;
1492 if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
1493 parameter_item = proto_tree_add_text(sdp_media_attribute_tree,
1494 tvb, offset, param_end_offset-offset, "Key parameters");
1495 parameter_tree = proto_item_add_subtree(parameter_item, ett_sdp_crypto_key_parameters);
1496 /* XXX only for SRTP? */
1497 /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
1498 offset = next_offset +1;
1499 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1500 if (next_offset == -1) {
1501 tokenlen = param_end_offset - offset;
1502 } else {
1503 tokenlen = next_offset - offset;
1505 data_p = tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen);
1506 key_salt_tvb = base64_to_tvb(tvb, data_p);
1507 add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
1508 if (master_key_length != 0) {
1509 proto_tree_add_text(parameter_tree, tvb, offset, tokenlen, "Key and Salt");
1510 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
1511 key_salt_tvb, 0, master_key_length, ENC_ASCII|ENC_NA);
1512 proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
1513 key_salt_tvb, master_key_length, master_salt_length, ENC_ASCII|ENC_NA);
1514 } else {
1515 proto_tree_add_text(parameter_tree, key_salt_tvb, 0, -1, "Key and Salt");
1518 /* ["|" lifetime] ["|" mki] are optional */
1519 if (next_offset != -1) {
1520 offset = next_offset + 1;
1521 next_offset = tvb_find_guint8(tvb, offset, -1, '|');
1522 if(next_offset == -1){
1523 if(next_offset < param_end_offset){
1524 next_offset = param_end_offset;
1527 if (next_offset != -1) {
1528 /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
1529 tokenlen = next_offset - offset;
1530 proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
1531 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1532 offset = next_offset + 1;
1534 /* mki = mki-value ":" mki-length
1536 * mki-value = 1*DIGIT
1538 if(offset>param_end_offset){
1539 next_offset = -1;
1540 }else{
1541 next_offset = tvb_find_guint8(tvb, offset, -1, ':');
1543 if (next_offset != -1) {
1544 tokenlen = next_offset - offset;
1545 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1546 offset = next_offset + 1;
1548 /* mki-length = 1*3DIGIT ; range 1..128. */
1549 next_offset = param_end_offset;
1550 tokenlen = next_offset - offset;
1552 /* This will not work if more than one parameter */
1553 /* number of octets used for the MKI in the RTP payload */
1554 transport_info->mki_len = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset, tokenlen));
1555 proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
1556 tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
1559 offset = param_end_offset;
1560 } else {
1561 break;
1565 break;
1566 default:
1567 /* No special treatment for values of this attribute type, just add as one item. */
1568 proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
1569 tvb, offset, -1, ENC_ASCII|ENC_NA);
1570 break;
1574 static void
1575 call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
1576 transport_info_t *transport_info, disposable_media_info_t *media_info) {
1577 if (hf == hf_owner) {
1578 dissect_sdp_owner(tvb, ti);
1579 } else if (hf == hf_connection_info) {
1580 dissect_sdp_connection_info(tvb, ti, media_info);
1581 } else if (hf == hf_bandwidth) {
1582 dissect_sdp_bandwidth(tvb, ti);
1583 } else if (hf == hf_time) {
1584 dissect_sdp_time(tvb, ti);
1585 } else if (hf == hf_repeat_time) {
1586 dissect_sdp_repeat_time(tvb, ti);
1587 } else if (hf == hf_timezone) {
1588 dissect_sdp_timezone(tvb, ti);
1589 } else if (hf == hf_encryption_key) {
1590 dissect_sdp_encryption_key(tvb, ti);
1591 } else if (hf == hf_session_attribute) {
1592 dissect_sdp_session_attribute(tvb, pinfo, ti);
1593 } else if (hf == hf_media) {
1594 dissect_sdp_media(tvb, ti, transport_info, media_info);
1595 } else if (hf == hf_media_attribute) {
1596 dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, media_info);
1600 static void
1601 convert_disposable_media(transport_info_t* transport_info, disposable_media_info_t* media_info,
1602 gint start_transport_info_count)
1604 gint8 n, i, transport_index;
1605 guint proto_bitmask;
1607 for (n = 0; (n < media_info->media_count) && (n+start_transport_info_count < SDP_MAX_RTP_CHANNELS); n++)
1609 transport_index = n+start_transport_info_count;
1610 if (media_info->media_port[n] != NULL) {
1611 transport_info->media_port[transport_index] = (int)strtol(media_info->media_port[n], NULL, 10);
1614 if (media_info->media_proto[n] != NULL) {
1615 /* Check if media protocol is RTP
1616 * and stream decoding is enabled in preferences
1618 if (global_sdp_establish_conversation) {
1619 proto_bitmask = 0;
1621 /* Check if media protocol is RTP */
1622 if (!strcmp(media_info->media_proto[n],"RTP/AVP")) {
1623 transport_info->proto_bitmask[transport_index] |= SDP_RTP_PROTO;
1624 proto_bitmask |= SDP_RTP_PROTO;
1626 /* Check if media protocol is SRTP */
1627 else if (!strcmp(media_info->media_proto[n],"RTP/SAVP")) {
1628 transport_info->proto_bitmask[transport_index] |= SDP_SRTP_PROTO;
1629 proto_bitmask |= SDP_SRTP_PROTO;
1631 /* Check if media protocol is T38 */
1632 else if ((!strcmp(media_info->media_proto[n],"UDPTL")) ||
1633 (!strcmp(media_info->media_proto[n],"udptl"))) {
1634 transport_info->proto_bitmask[transport_index] |= SDP_T38_PROTO;
1635 proto_bitmask |= SDP_T38_PROTO;
1637 /* Check if media protocol is MSRP/TCP */
1638 else if (!strcmp(media_info->media_proto[n],"msrp/tcp")) {
1639 transport_info->proto_bitmask[transport_index] |= SDP_MSRP_PROTO;
1640 proto_bitmask |= SDP_MSRP_PROTO;
1642 /* Check if media protocol is SPRT */
1643 else if ((!strcmp(media_info->media_proto[n],"UDPSPRT")) ||
1644 (!strcmp(media_info->media_proto[n],"udpsprt"))) {
1645 transport_info->proto_bitmask[transport_index] |= SDP_SPRT_PROTO;
1646 proto_bitmask |= SDP_SPRT_PROTO;
1649 if (transport_info->media_port[transport_index] == 0) {
1650 /* This will disable any ports that share the media */
1651 for (i = 0; i < transport_index; i++) {
1652 if (proto_bitmask & transport_info->proto_bitmask[i]) {
1653 transport_info->media_port[i] = 0;
1660 if ((media_info->connection_address != NULL) &&
1661 (media_info->connection_type != NULL)) {
1662 if (strcmp(media_info->connection_type, "IP4") == 0) {
1663 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 4);
1664 if (inet_pton(AF_INET, media_info->connection_address, (void*)transport_info->src_addr[transport_index].data) > 0) {
1665 /* connection_address could be converted to a valid ipv4 address*/
1666 transport_info->proto_bitmask[transport_index] |= SDP_IPv4;
1667 transport_info->src_addr[transport_index].type = AT_IPv4;
1668 transport_info->src_addr[transport_index].len = 4;
1670 } else if (strcmp(media_info->connection_type, "IP6") == 0) {
1671 transport_info->src_addr[transport_index].data = wmem_alloc(wmem_file_scope(), 16);
1672 if (inet_pton(AF_INET6, media_info->connection_address, (void*)transport_info->src_addr[transport_index].data) > 0) {
1673 /* connection_address could be converted to a valid ipv6 address*/
1674 transport_info->proto_bitmask[transport_index] |= SDP_IPv6;
1675 transport_info->src_addr[transport_index].type = AT_IPv6;
1676 transport_info->src_addr[transport_index].len = 16;
1681 /* MSRP uses addresses discovered in attribute
1682 rather than connection information of media session line */
1683 if ((transport_info->proto_bitmask[transport_index] & SDP_MSRP_PROTO) &&
1684 (transport_info->proto_bitmask[transport_index] & SDP_MSRP_IPv4) &&
1685 msrp_handle) {
1686 transport_info->src_addr[transport_index].type = AT_IPv4;
1687 transport_info->src_addr[transport_index].len = 4;
1688 transport_info->src_addr[transport_index].data = wmem_memdup(wmem_file_scope(), media_info->msrp_ipaddr, 4);
1689 transport_info->media_port[transport_index] = media_info->msrp_port_number;
1692 if ((media_info->media_type != NULL) && (strcmp(media_info->media_type, "video") == 0)) {
1693 transport_info->proto_bitmask[transport_index] |= SDP_VIDEO;
1698 void
1699 setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type, int request_frame)
1701 gint offset = 0, next_offset, n;
1702 int linelen;
1703 gboolean in_media_description = FALSE;
1704 guchar type, delim;
1705 const int tokenoffset = 2;
1706 int hf = -1;
1707 gint start_transport_info_count = 0;
1708 transport_info_t* transport_info = NULL;
1709 disposable_media_info_t media_info;
1711 struct srtp_info *srtp_info = NULL;
1713 /* Only do this once during first pass */
1714 if (pinfo->fd->flags.visited)
1715 return;
1717 memset(&media_info, 0, sizeof(media_info));
1719 if (request_frame != 0)
1720 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
1721 if (transport_info == NULL) {
1722 transport_info = wmem_new0(wmem_file_scope(), transport_info_t);
1723 transport_info->media_count = -1;
1725 for (n = 0; n < SDP_NO_OF_PT; n++) {
1726 transport_info->encoding_name[n] = (char*)UNKNOWN_ENCODING;
1728 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
1729 transport_info->media[n].rtp_dyn_payload =
1730 g_hash_table_new(g_int_hash, g_int_equal);
1731 transport_info->media[n].set_rtp = FALSE;
1734 if (request_frame != 0)
1735 wmem_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info);
1738 if (exchange_type != SDP_EXCHANGE_OFFER)
1739 wmem_tree_insert32(sdp_transport_rsps, pinfo->fd->num, (void *)transport_info);
1741 /* Offer has already been answered or rejected and hash tables freed, so
1742 * don't try to add to it
1743 * XXX - Need to support "modified offers" */
1744 if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) ||
1745 (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT))
1746 return;
1748 if (transport_info->media_count > 0)
1749 start_transport_info_count = transport_info->media_count;
1752 * Show the SDP message a line at a time.
1754 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1756 * Find the end of the line.
1758 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
1761 * Line must contain at least e.g. "v=".
1763 if (linelen < 2)
1764 break;
1766 type = tvb_get_guint8(tvb, offset);
1767 delim = tvb_get_guint8(tvb, offset + 1);
1768 if (delim != '=') {
1769 offset = next_offset;
1770 continue;
1774 * Attributes. Only care about ones that affect the transport. Ignore others.
1776 switch (type) {
1777 case 'c':
1778 hf = hf_connection_info;
1779 break;
1780 case 'm':
1781 hf = hf_media;
1783 /* Increase the count of media channels, but don't walk off the end of the arrays. */
1784 if (((transport_info->media_count < 0) && (in_media_description == FALSE)) || (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)))
1785 transport_info->media_count++;
1787 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
1788 media_info.media_count++;
1790 in_media_description = TRUE;
1791 break;
1792 case 'a':
1793 if (in_media_description) {
1794 hf = hf_media_attribute;
1795 } else {
1796 hf = hf_session_attribute;
1798 break;
1799 default:
1800 hf = hf_unknown;
1801 break;
1804 if (hf != hf_unknown)
1806 call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
1807 linelen - tokenoffset,
1808 linelen - tokenoffset),
1809 pinfo,
1810 hf, NULL, linelen-tokenoffset, transport_info, &media_info);
1813 offset = next_offset;
1816 if (in_media_description) {
1817 /* Increase the count of media channels, but don't walk off the end of the arrays. */
1818 if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1))
1819 transport_info->media_count++;
1820 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
1821 media_info.media_count++;
1824 /* Take all of the collected strings and convert them into something permanent
1825 * for the life of the capture
1827 convert_disposable_media(transport_info, &media_info, start_transport_info_count);
1829 /* We have a successful negotiation, apply data to their respective protocols */
1830 if ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
1831 (transport_info->sdp_status == SDP_EXCHANGE_OFFER)) {
1832 for (n = 0; n <= transport_info->media_count; n++) {
1833 guint32 current_rtp_port = 0;
1835 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
1836 if ((transport_info->media_port[n] != 0) &&
1837 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
1838 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
1839 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
1840 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
1841 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
1842 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
1843 srtp_info->auth_algorithm = transport_info->auth_algorithm;
1844 srtp_info->mki_len = transport_info->mki_len;
1845 srtp_info->auth_tag_len = transport_info->auth_tag_len;
1848 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
1849 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
1850 transport_info->media[n].rtp_dyn_payload, srtp_info);
1851 } else {
1852 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
1853 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
1854 transport_info->media[n].rtp_dyn_payload);
1856 transport_info->media[n].set_rtp = TRUE;
1857 /* SPRT might use the same port... */
1858 current_rtp_port = transport_info->media_port[n];
1860 if (rtcp_handle) {
1861 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
1862 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
1863 } else {
1864 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
1869 /* add SPRT conversation */
1870 if ((transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
1871 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
1872 (sprt_handle)) {
1874 if (transport_info->media_port[n] == 0 && current_rtp_port) {
1875 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
1876 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
1877 } else {
1878 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
1882 /* Add t38 conversation, if available and only if no rtp */
1883 if ((transport_info->media_port[n] != 0) &&
1884 !transport_info->media[n].set_rtp &&
1885 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
1886 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
1887 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
1890 /* Add MSRP conversation. Uses addresses discovered in attribute
1891 rather than connection information of media session line
1892 (already handled in media conversion) */
1893 if ((transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
1894 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
1895 msrp_handle) {
1896 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
1899 /* Free the hash table if we did't assigned it to a conv use it */
1900 if (!transport_info->media[n].set_rtp)
1902 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1903 transport_info->media[n].rtp_dyn_payload = NULL;
1907 /* Free the remaining hash tables not used */
1908 if (transport_info->media_count == -1)
1910 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
1912 if (!transport_info->media[n].set_rtp)
1914 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1915 transport_info->media[n].rtp_dyn_payload = NULL;
1919 else
1921 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
1923 if (!transport_info->media[n].set_rtp)
1925 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1926 transport_info->media[n].rtp_dyn_payload = NULL;
1930 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_ACCEPT;
1932 } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) &&
1933 (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)){
1935 /* Free the hash tables, since they won't be put to use */
1936 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++)
1938 if (!transport_info->media[n].set_rtp)
1940 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
1941 transport_info->media[n].rtp_dyn_payload = NULL;
1945 transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT;
1949 void setup_sdp_transport_resend(int current_frame, int request_frame)
1951 transport_info_t* transport_info = NULL;
1953 if (request_frame != 0) {
1954 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
1955 if (transport_info != NULL) {
1956 wmem_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info);
1961 static void
1962 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1964 proto_tree *sdp_tree;
1965 proto_item *ti, *sub_ti;
1966 gint offset = 0, next_offset, n, i;
1967 int linelen;
1968 gboolean in_media_description;
1969 guchar type, delim;
1970 int datalen, tokenoffset, hf = -1;
1971 char *string;
1973 transport_info_t local_transport_info;
1974 transport_info_t* transport_info = NULL;
1975 disposable_media_info_t media_info;
1977 sdp_packet_info *sdp_pi;
1978 struct srtp_info *srtp_info = NULL;
1980 /* Initialise packet info for passing to tap */
1981 sdp_pi = wmem_new(wmem_packet_scope(), sdp_packet_info);
1982 sdp_pi->summary_str[0] = '\0';
1984 if (!pinfo->fd->flags.visited) {
1985 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->fd->num );
1987 if (transport_info == NULL) {
1988 /* Can't find it in the requests, make sure it's not a response */
1989 transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_rsps, pinfo->fd->num );
1993 if (transport_info == NULL) {
1994 transport_info = &local_transport_info;
1997 /* Initialize local transport info */
1998 memset(&local_transport_info, 0, sizeof(local_transport_info));
1999 local_transport_info.media_count = -1;
2001 for (n = 0; n < SDP_NO_OF_PT; n++) {
2002 local_transport_info.encoding_name[n] = (char*)UNKNOWN_ENCODING;
2004 for (n = 0; n < SDP_MAX_RTP_CHANNELS; n++) {
2005 local_transport_info.media[n].rtp_dyn_payload =
2006 g_hash_table_new(g_int_hash, g_int_equal);
2007 local_transport_info.media[n].set_rtp = FALSE;
2010 memset(&media_info, 0, sizeof(media_info));
2013 * As RFC 2327 says, "SDP is purely a format for session
2014 * description - it does not incorporate a transport protocol,
2015 * and is intended to use different transport protocols as
2016 * appropriate including the Session Announcement Protocol,
2017 * Session Initiation Protocol, Real-Time Streaming Protocol,
2018 * electronic mail using the MIME extensions, and the
2019 * Hypertext Transport Protocol."
2021 * We therefore don't set the protocol or info columns;
2022 * instead, we append to them, so that we don't erase
2023 * what the protocol inside which the SDP stuff resides
2024 * put there.
2026 col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
2028 /* XXX: Needs description.
2029 * Putting with session description in info col is redundant when it's in the
2030 * protocol col in my opinion, commenting it out for now 2012-10-09. Remove if no one complains.
2031 * If some one want it consider " ,with SDP"
2033 /*col_append_str(pinfo->cinfo, COL_INFO, ", with session description");*/
2035 ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA);
2036 sdp_tree = proto_item_add_subtree(ti, ett_sdp);
2039 * Show the SDP message a line at a time.
2041 in_media_description = FALSE;
2043 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2045 * Find the end of the line.
2047 linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
2050 * Line must contain at least e.g. "v=".
2052 if (linelen < 2)
2053 break;
2055 type = tvb_get_guint8(tvb, offset);
2056 delim = tvb_get_guint8(tvb, offset + 1);
2057 if (delim != '=') {
2058 proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_ASCII|ENC_NA);
2059 expert_add_info(pinfo, ti2, &ei_sdp_invalid_line);
2060 offset = next_offset;
2061 continue;
2065 * Attributes.
2067 switch (type) {
2068 case 'v':
2069 hf = hf_protocol_version;
2070 break;
2071 case 'o':
2072 hf = hf_owner;
2073 break;
2074 case 's':
2075 hf = hf_session_name;
2076 break;
2077 case 'i':
2078 if (in_media_description) {
2079 hf = hf_media_title;
2080 } else {
2081 hf = hf_session_info;
2083 break;
2084 case 'u':
2085 hf = hf_uri;
2086 break;
2087 case 'e':
2088 hf = hf_email;
2089 break;
2090 case 'p':
2091 hf = hf_phone;
2092 break;
2093 case 'c':
2094 hf = hf_connection_info;
2095 break;
2096 case 'b':
2097 hf = hf_bandwidth;
2098 break;
2099 case 't':
2100 hf = hf_time;
2101 break;
2102 case 'r':
2103 hf = hf_repeat_time;
2104 break;
2105 case 'm':
2106 hf = hf_media;
2108 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2109 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2110 local_transport_info.media_count++;
2112 if (in_media_description && (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1)))
2113 media_info.media_count++;
2115 in_media_description = TRUE;
2116 break;
2117 case 'k':
2118 hf = hf_encryption_key;
2119 break;
2120 case 'a':
2121 if (in_media_description) {
2122 hf = hf_media_attribute;
2123 } else {
2124 hf = hf_session_attribute;
2126 break;
2127 case 'z':
2128 hf = hf_timezone;
2129 break;
2130 default:
2131 hf = hf_unknown;
2132 break;
2134 tokenoffset = 2;
2135 if (hf == hf_unknown)
2136 tokenoffset = 0;
2137 string = (char*)tvb_get_string(wmem_packet_scope(), tvb, offset + tokenoffset,
2138 linelen - tokenoffset);
2139 sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
2140 string);
2142 call_sdp_subdissector(tvb_new_subset(tvb, offset + tokenoffset,
2143 linelen - tokenoffset,
2144 linelen - tokenoffset),
2145 pinfo,
2146 hf, sub_ti, linelen-tokenoffset,
2147 &local_transport_info, &media_info);
2149 offset = next_offset;
2152 if (in_media_description) {
2153 /* Increase the count of media channels, but don't walk off the end of the arrays. */
2154 if (local_transport_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2155 local_transport_info.media_count++;
2156 if (media_info.media_count < (SDP_MAX_RTP_CHANNELS-1))
2157 media_info.media_count++;
2160 /* Take all of the collected strings and convert them into something permanent
2161 * for the life of the capture
2163 if (transport_info == &local_transport_info)
2164 convert_disposable_media(transport_info, &media_info, 0);
2166 for (n = 0; n < local_transport_info.media_count; n++)
2168 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2169 /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
2170 * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers
2171 * use setup_sdp_transport(), this should be removed
2173 guint32 current_rtp_port = 0;
2175 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2176 (transport_info->media_port[n] != 0) &&
2177 (transport_info->proto_bitmask[n] & (SDP_RTP_PROTO|SDP_SRTP_PROTO)) &&
2178 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6))) {
2179 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2180 srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
2181 if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
2182 srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
2183 srtp_info->auth_algorithm = transport_info->auth_algorithm;
2184 srtp_info->mki_len = transport_info->mki_len;
2185 srtp_info->auth_tag_len = transport_info->auth_tag_len;
2187 srtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2188 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2189 transport_info->media[n].rtp_dyn_payload, srtp_info);
2190 } else {
2191 rtp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num,
2192 (transport_info->proto_bitmask[n] & SDP_VIDEO) ? TRUE : FALSE,
2193 transport_info->media[n].rtp_dyn_payload);
2195 transport_info->media[n].set_rtp = TRUE;
2196 /* SPRT might use the same port... */
2197 current_rtp_port = transport_info->media_port[n];
2199 if (rtcp_handle) {
2200 if (transport_info->proto_bitmask[n] & SDP_SRTP_PROTO) {
2201 srtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num, srtp_info);
2202 } else {
2203 rtcp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n]+1, 0, "SDP", pinfo->fd->num);
2208 /* add SPRT conversation */
2209 /* XXX - more placeholder functionality */
2210 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2211 (transport_info->proto_bitmask[n] & SDP_SPRT_PROTO) &&
2212 (transport_info->proto_bitmask[n] & (SDP_IPv4|SDP_IPv6)) &&
2213 (sprt_handle)) {
2215 if (transport_info->media_port[n] == 0 && current_rtp_port) {
2216 sprt_add_address(pinfo, &transport_info->src_addr[n], current_rtp_port,
2217 0, "SDP", pinfo->fd->num); /* will use same port as RTP */
2218 } else {
2219 sprt_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2223 /* Add t38 conversation, if available and only if no rtp */
2224 /* XXX - more placeholder functionality */
2225 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2226 (transport_info->media_port[n] != 0) &&
2227 !transport_info->media[n].set_rtp &&
2228 (transport_info->proto_bitmask[n] & SDP_T38_PROTO) &&
2229 (transport_info->proto_bitmask[n] & SDP_IPv4)) {
2230 t38_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], 0, "SDP", pinfo->fd->num);
2233 /* Add MSRP conversation. Uses addresses discovered in attribute
2234 rather than connection information of media session line */
2235 /* XXX - more placeholder functionality */
2236 if ((!pinfo->fd->flags.visited) && (transport_info == &local_transport_info) &&
2237 (transport_info->proto_bitmask[n] & SDP_MSRP_PROTO) &&
2238 (transport_info->proto_bitmask[n] & SDP_MSRP_IPv4) &&
2239 msrp_handle) {
2240 msrp_add_address(pinfo, &transport_info->src_addr[n], transport_info->media_port[n], "SDP", pinfo->fd->num);
2243 if (local_transport_info.media_port[n] != 0) {
2244 /* Create the RTP summary str for the Voip Call analysis.
2245 * XXX - Currently this is based only on the current packet
2247 for (i = 0; i < local_transport_info.media[n].pt_count; i++)
2249 /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
2250 if ((local_transport_info.media[n].pt[i] >= 96) && (local_transport_info.media[n].pt[i] <= 127)) {
2251 encoding_name_and_rate_t *encoding_name_and_rate_pt =
2252 (encoding_name_and_rate_t *)g_hash_table_lookup(
2253 local_transport_info.media[n].rtp_dyn_payload,
2254 &local_transport_info.media[n].pt[i]);
2255 if (encoding_name_and_rate_pt) {
2256 if (strlen(sdp_pi->summary_str))
2257 g_strlcat(sdp_pi->summary_str, " ", 50);
2258 g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
2259 } else {
2260 char num_pt[10];
2261 g_snprintf(num_pt, 10, "%u", local_transport_info.media[n].pt[i]);
2262 if (strlen(sdp_pi->summary_str))
2263 g_strlcat(sdp_pi->summary_str, " ", 50);
2264 g_strlcat(sdp_pi->summary_str, num_pt, 50);
2266 } else {
2267 if (strlen(sdp_pi->summary_str))
2268 g_strlcat(sdp_pi->summary_str, " ", 50);
2269 g_strlcat(sdp_pi->summary_str,
2270 val_to_str_ext(local_transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"),
2271 50);
2276 /* Free the hash table if we did't assigned it to a conv use it */
2277 /* XXX - more placeholder functionality */
2278 if ((transport_info == &local_transport_info) &&
2279 !transport_info->media[n].set_rtp)
2281 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
2282 transport_info->media[n].rtp_dyn_payload = NULL;
2285 /* Create the T38 summary str for the Voip Call analysis
2286 * XXX - Currently this is based only on the current packet
2288 if ((local_transport_info.media_port[n] != 0) &&
2289 (local_transport_info.proto_bitmask[n] & SDP_T38_PROTO)) {
2290 if (strlen(sdp_pi->summary_str))
2291 g_strlcat(sdp_pi->summary_str, " ", 50);
2292 g_strlcat(sdp_pi->summary_str, "t38", 50);
2296 /* Free the remainded hash tables not used */
2297 /* XXX - more placeholder functionality */
2298 if (transport_info == &local_transport_info) {
2299 for (n = transport_info->media_count; n < SDP_MAX_RTP_CHANNELS; n++)
2301 if (!transport_info->media[n].set_rtp)
2303 rtp_free_hash_dyn_payload(transport_info->media[n].rtp_dyn_payload);
2304 transport_info->media[n].rtp_dyn_payload = NULL;
2309 datalen = tvb_length_remaining(tvb, offset);
2310 if (datalen > 0) {
2311 proto_tree_add_text(sdp_tree, tvb, offset, datalen, "Data (%d bytes)", datalen);
2313 /* Report this packet to the tap */
2314 tap_queue_packet(sdp_tap, pinfo, sdp_pi);
2317 void
2318 proto_register_sdp(void)
2320 static hf_register_info hf[] = {
2321 { &hf_protocol_version,
2322 { "Session Description Protocol Version (v)", "sdp.version",
2323 FT_STRING, BASE_NONE, NULL, 0x0,
2324 NULL, HFILL }
2326 { &hf_owner,
2327 { "Owner/Creator, Session Id (o)",
2328 "sdp.owner", FT_STRING, BASE_NONE, NULL,
2329 0x0, NULL, HFILL}
2331 { &hf_session_name,
2332 { "Session Name (s)", "sdp.session_name",
2333 FT_STRING, BASE_NONE, NULL, 0x0,
2334 NULL, HFILL }
2336 { &hf_session_info,
2337 { "Session Information (i)", "sdp.session_info",
2338 FT_STRING, BASE_NONE, NULL, 0x0,
2339 NULL, HFILL }
2341 { &hf_uri,
2342 { "URI of Description (u)", "sdp.uri",
2343 FT_STRING, BASE_NONE, NULL, 0x0,
2344 NULL, HFILL }
2346 { &hf_email,
2347 { "E-mail Address (e)", "sdp.email",
2348 FT_STRING, BASE_NONE, NULL, 0x0,
2349 "E-mail Address", HFILL }
2351 { &hf_phone,
2352 { "Phone Number (p)", "sdp.phone",
2353 FT_STRING, BASE_NONE, NULL, 0x0,
2354 NULL, HFILL }
2356 { &hf_connection_info,
2357 { "Connection Information (c)", "sdp.connection_info",
2358 FT_STRING, BASE_NONE, NULL, 0x0,
2359 NULL, HFILL }
2361 { &hf_bandwidth,
2362 { "Bandwidth Information (b)", "sdp.bandwidth",
2363 FT_STRING, BASE_NONE, NULL, 0x0,
2364 NULL, HFILL }
2366 { &hf_timezone,
2367 { "Time Zone Adjustments (z)", "sdp.timezone",
2368 FT_STRING, BASE_NONE, NULL, 0x0,
2369 NULL, HFILL }
2371 { &hf_encryption_key,
2372 { "Encryption Key (k)", "sdp.encryption_key",
2373 FT_STRING, BASE_NONE, NULL, 0x0,
2374 NULL, HFILL }
2376 { &hf_session_attribute,
2377 { "Session Attribute (a)", "sdp.session_attr",
2378 FT_STRING, BASE_NONE, NULL, 0x0,
2379 NULL, HFILL }
2381 { &hf_media_attribute,
2382 { "Media Attribute (a)", "sdp.media_attr",
2383 FT_STRING, BASE_NONE, NULL, 0x0,
2384 NULL, HFILL }
2386 { &hf_time,
2387 { "Time Description, active time (t)",
2388 "sdp.time", FT_STRING, BASE_NONE, NULL,
2389 0x0, NULL, HFILL }
2391 { &hf_repeat_time,
2392 { "Repeat Time (r)", "sdp.repeat_time",
2393 FT_STRING, BASE_NONE, NULL, 0x0,
2394 NULL, HFILL }
2396 { &hf_media,
2397 { "Media Description, name and address (m)",
2398 "sdp.media", FT_STRING, BASE_NONE, NULL,
2399 0x0, NULL, HFILL }
2401 { &hf_media_title,
2402 { "Media Title (i)", "sdp.media_title",
2403 FT_STRING, BASE_NONE, NULL, 0x0,
2404 "Media Title", HFILL }
2406 { &hf_unknown,
2407 { "Unknown", "sdp.unknown",
2408 FT_STRING, BASE_NONE, NULL, 0x0,
2409 NULL, HFILL }
2411 { &hf_invalid,
2412 { "Invalid line", "sdp.invalid",
2413 FT_STRING, BASE_NONE, NULL, 0x0,
2414 NULL, HFILL }
2416 { &hf_owner_username,
2417 { "Owner Username", "sdp.owner.username",
2418 FT_STRING, BASE_NONE, NULL, 0x0,
2419 NULL, HFILL }
2421 { &hf_owner_sessionid,
2422 { "Session ID", "sdp.owner.sessionid",
2423 FT_STRING, BASE_NONE, NULL, 0x0,
2424 NULL, HFILL }
2426 { &hf_owner_version,
2427 { "Session Version", "sdp.owner.version",
2428 FT_STRING, BASE_NONE, NULL, 0x0,
2429 NULL, HFILL }
2431 { &hf_owner_network_type,
2432 { "Owner Network Type", "sdp.owner.network_type",
2433 FT_STRING, BASE_NONE, NULL, 0x0,
2434 NULL, HFILL }
2436 { &hf_owner_address_type,
2437 { "Owner Address Type", "sdp.owner.address_type",
2438 FT_STRING, BASE_NONE, NULL, 0x0,
2439 NULL, HFILL }
2441 { &hf_owner_address,
2442 { "Owner Address", "sdp.owner.address",
2443 FT_STRING, BASE_NONE, NULL, 0x0,
2444 NULL, HFILL }
2446 { &hf_connection_info_network_type,
2447 { "Connection Network Type", "sdp.connection_info.network_type",
2448 FT_STRING, BASE_NONE, NULL, 0x0,
2449 NULL, HFILL }
2451 { &hf_connection_info_address_type,
2452 { "Connection Address Type", "sdp.connection_info.address_type",
2453 FT_STRING, BASE_NONE, NULL, 0x0,
2454 NULL, HFILL }
2456 { &hf_connection_info_connection_address,
2457 { "Connection Address", "sdp.connection_info.address",
2458 FT_STRING, BASE_NONE, NULL, 0x0,
2459 NULL, HFILL }
2461 { &hf_connection_info_ttl,
2462 { "Connection TTL", "sdp.connection_info.ttl",
2463 FT_STRING, BASE_NONE, NULL, 0x0,
2464 NULL, HFILL }
2466 { &hf_connection_info_num_addr,
2467 { "Connection Number of Addresses", "sdp.connection_info.num_addr",
2468 FT_STRING, BASE_NONE, NULL, 0x0,
2469 NULL, HFILL }
2471 { &hf_bandwidth_modifier,
2472 { "Bandwidth Modifier", "sdp.bandwidth.modifier",
2473 FT_STRING, BASE_NONE, NULL, 0x0,
2474 NULL, HFILL }
2476 { &hf_bandwidth_value,
2477 { "Bandwidth Value", "sdp.bandwidth.value",
2478 FT_STRING, BASE_NONE, NULL, 0x0,
2479 "Bandwidth Value (in kbits/s)", HFILL }
2481 { &hf_time_start,
2482 { "Session Start Time", "sdp.time.start",
2483 FT_STRING, BASE_NONE, NULL, 0x0,
2484 NULL, HFILL }
2486 { &hf_time_stop,
2487 { "Session Stop Time", "sdp.time.stop",
2488 FT_STRING, BASE_NONE, NULL, 0x0,
2489 NULL, HFILL }
2491 { &hf_repeat_time_interval,
2492 { "Repeat Interval", "sdp.repeat_time.interval",
2493 FT_STRING, BASE_NONE, NULL, 0x0,
2494 NULL, HFILL }
2496 { &hf_repeat_time_duration,
2497 { "Repeat Duration", "sdp.repeat_time.duration",
2498 FT_STRING, BASE_NONE, NULL, 0x0,
2499 NULL, HFILL }
2501 { &hf_repeat_time_offset,
2502 { "Repeat Offset", "sdp.repeat_time.offset",
2503 FT_STRING, BASE_NONE, NULL, 0x0,
2504 NULL, HFILL }
2506 { &hf_timezone_time,
2507 { "Timezone Time", "sdp.timezone.time",
2508 FT_STRING, BASE_NONE, NULL, 0x0,
2509 NULL, HFILL }
2511 { &hf_timezone_offset,
2512 { "Timezone Offset", "sdp.timezone.offset",
2513 FT_STRING, BASE_NONE, NULL, 0x0,
2514 NULL, HFILL }
2516 { &hf_encryption_key_type,
2517 { "Key Type", "sdp.encryption_key.type",
2518 FT_STRING, BASE_NONE, NULL, 0x0,
2519 NULL, HFILL }
2521 { &hf_encryption_key_data,
2522 { "Key Data", "sdp.encryption_key.data",
2523 FT_STRING, BASE_NONE, NULL, 0x0,
2524 NULL, HFILL }
2526 { &hf_session_attribute_field,
2527 { "Session Attribute Fieldname", "sdp.session_attr.field",
2528 FT_STRING, BASE_NONE, NULL, 0x0,
2529 NULL, HFILL }
2531 { &hf_session_attribute_value,
2532 { "Session Attribute Value", "sdp.session_attr.value",
2533 FT_STRING, BASE_NONE, NULL, 0x0,
2534 NULL, HFILL }
2536 { &hf_media_media,
2537 { "Media Type", "sdp.media.media",
2538 FT_STRING, BASE_NONE, NULL, 0x0,
2539 NULL, HFILL }
2541 { &hf_media_port,
2542 { "Media Port", "sdp.media.port",
2543 FT_UINT16, BASE_DEC, NULL, 0x0,
2544 NULL, HFILL }
2546 { &hf_media_portcount,
2547 { "Media Port Count", "sdp.media.portcount",
2548 FT_STRING, BASE_NONE, NULL, 0x0,
2549 NULL, HFILL }
2551 { &hf_media_proto,
2552 { "Media Protocol", "sdp.media.proto",
2553 FT_STRING, BASE_NONE, NULL, 0x0,
2554 NULL, HFILL }
2556 { &hf_media_format,
2557 { "Media Format", "sdp.media.format",
2558 FT_STRING, BASE_NONE, NULL, 0x0,
2559 NULL, HFILL }
2561 { &hf_media_attribute_field,
2562 { "Media Attribute Fieldname", "sdp.media_attribute.field",
2563 FT_STRING, BASE_NONE, NULL, 0x0,
2564 NULL, HFILL }
2566 { &hf_media_attribute_value,
2567 { "Media Attribute Value", "sdp.media_attribute.value",
2568 FT_STRING, BASE_NONE, NULL, 0x0,
2569 NULL, HFILL }
2571 { &hf_media_encoding_name,
2572 { "MIME Type", "sdp.mime.type",
2573 FT_STRING, BASE_NONE, NULL, 0x0,
2574 "SDP MIME Type", HFILL }
2576 { &hf_media_sample_rate,
2577 { "Sample Rate", "sdp.sample_rate",
2578 FT_STRING, BASE_NONE, NULL, 0x0,
2579 NULL, HFILL }
2581 { &hf_media_format_specific_parameter,
2582 { "Media format specific parameters", "sdp.fmtp.parameter",
2583 FT_STRING, BASE_NONE, NULL, 0x0,
2584 "Format specific parameter(fmtp)", HFILL }
2586 { &hf_ipbcp_version,
2587 { "IPBCP Protocol Version", "sdp.ipbcp.version",
2588 FT_STRING, BASE_NONE, NULL, 0x0,
2589 NULL, HFILL }
2591 { &hf_ipbcp_type,
2592 { "IPBCP Command Type", "sdp.ipbcp.command",
2593 FT_STRING, BASE_NONE, NULL, 0x0,
2594 NULL, HFILL }
2596 {&hf_sdp_fmtp_mpeg4_profile_level_id,
2597 { "Level Code", "sdp.fmtp.profile_level_id",
2598 FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0,
2599 NULL, HFILL }
2601 { &hf_sdp_fmtp_h263_profile,
2602 { "Profile", "sdp.fmtp.h263profile",
2603 FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0,
2604 NULL, HFILL }
2606 { &hf_sdp_fmtp_h263_level,
2607 { "Level", "sdp.fmtp.h263level",
2608 FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0,
2609 NULL, HFILL }
2611 { &hf_sdp_h264_packetization_mode,
2612 { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
2613 FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0,
2614 NULL, HFILL }
2616 { &hf_SDPh223LogicalChannelParameters,
2617 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
2618 FT_NONE, BASE_NONE, NULL, 0,
2619 NULL, HFILL }
2621 { &hf_key_mgmt_att_value,
2622 { "Key Management", "sdp.key_mgmt",
2623 FT_STRING, BASE_NONE, NULL, 0x0,
2624 NULL, HFILL }
2626 { &hf_key_mgmt_prtcl_id,
2627 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
2628 FT_STRING, BASE_NONE, NULL, 0x0,
2629 NULL, HFILL }
2631 { &hf_key_mgmt_data,
2632 { "Key Management Data", "sdp.key_mgmt.data",
2633 FT_BYTES, BASE_NONE, NULL, 0x0,
2634 NULL, HFILL }
2636 { &hf_sdp_crypto_tag,
2637 { "tag", "sdp.crypto.tag",
2638 FT_UINT32, BASE_DEC, NULL, 0x0,
2639 NULL, HFILL }
2641 { &hf_sdp_crypto_crypto_suite,
2642 { "Crypto suite", "sdp.crypto.crypto_suite",
2643 FT_STRING, BASE_NONE, NULL, 0x0,
2644 NULL, HFILL }
2646 { &hf_sdp_crypto_master_key,
2647 { "Master Key", "sdp.crypto.master_key",
2648 FT_BYTES, BASE_NONE, NULL, 0x0,
2649 NULL, HFILL }
2651 { &hf_sdp_crypto_master_salt,
2652 { "Master salt", "sdp.crypto.master_salt",
2653 FT_BYTES, BASE_NONE, NULL, 0x0,
2654 NULL, HFILL }
2656 { &hf_sdp_crypto_lifetime,
2657 { "Lifetime", "sdp.crypto.lifetime",
2658 FT_STRING, BASE_NONE, NULL, 0x0,
2659 NULL, HFILL }
2661 { &hf_sdp_crypto_mki,
2662 { "mki-value", "sdp.crypto.mki-valu",
2663 FT_STRING, BASE_NONE, NULL, 0x0,
2664 NULL, HFILL }
2666 { &hf_sdp_crypto_mki_length,
2667 { "mki_length", "sdp.crypto.mki_length",
2668 FT_STRING, BASE_NONE, NULL, 0x0,
2669 NULL, HFILL }
2672 static gint *ett[] = {
2673 &ett_sdp,
2674 &ett_sdp_owner,
2675 &ett_sdp_connection_info,
2676 &ett_sdp_bandwidth,
2677 &ett_sdp_time,
2678 &ett_sdp_repeat_time,
2679 &ett_sdp_timezone,
2680 &ett_sdp_encryption_key,
2681 &ett_sdp_session_attribute,
2682 &ett_sdp_media,
2683 &ett_sdp_media_attribute,
2684 &ett_sdp_fmtp,
2685 &ett_sdp_key_mgmt,
2686 &ett_sdp_crypto_key_parameters,
2689 static ei_register_info ei[] = {
2690 { &ei_sdp_invalid_key_param, { "sdp.invalid_key_param", PI_MALFORMED, PI_NOTE, "Invalid key-param (no ':' delimiter)", EXPFILL }},
2691 { &ei_sdp_invalid_line, { "sdp.invalid_line", PI_MALFORMED, PI_NOTE, "Invalid SDP line (no '=' delimiter)", EXPFILL }},
2694 module_t *sdp_module;
2695 expert_module_t* expert_sdp;
2697 proto_sdp = proto_register_protocol("Session Description Protocol",
2698 "SDP", "sdp");
2699 proto_register_field_array(proto_sdp, hf, array_length(hf));
2700 proto_register_subtree_array(ett, array_length(ett));
2701 expert_sdp = expert_register_protocol(proto_sdp);
2702 expert_register_field_array(expert_sdp, ei, array_length(ei));
2704 key_mgmt_dissector_table = register_dissector_table("key_mgmt",
2705 "Key Management", FT_STRING, BASE_NONE);
2707 * Preferences registration
2709 sdp_module = prefs_register_protocol(proto_sdp, NULL);
2710 prefs_register_bool_preference(sdp_module, "establish_conversation",
2711 "Establish Media Conversation",
2712 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
2713 "upon port numbers found in SDP payload",
2714 &global_sdp_establish_conversation);
2716 sdp_transport_reqs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
2717 sdp_transport_rsps = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
2720 * Register the dissector by name, so other dissectors can
2721 * grab it by name rather than just referring to it directly.
2723 register_dissector("sdp", dissect_sdp, proto_sdp);
2725 /* Register for tapping */
2726 sdp_tap = register_tap("sdp");
2729 void
2730 proto_reg_handoff_sdp(void)
2732 dissector_handle_t sdp_handle;
2734 rtcp_handle = find_dissector("rtcp");
2735 msrp_handle = find_dissector("msrp");
2736 sprt_handle = find_dissector("sprt");
2737 h264_handle = find_dissector("h264");
2738 mp4ves_handle = find_dissector("mp4ves");
2740 proto_sprt = dissector_handle_get_protocol_index(find_dissector("sprt"));
2742 sdp_handle = find_dissector("sdp");
2743 dissector_add_string("media_type", "application/sdp", sdp_handle);
2744 dissector_add_uint("bctp.tpi", 0x20, sdp_handle);