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>
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
31 #ifdef HAVE_SYS_TYPES_H
32 #include <sys/types.h>
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
37 #ifdef HAVE_NETINET_IN_H
38 # include <netinet/in.h>
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
44 #ifdef HAVE_WINSOCK2_H
45 #include <winsock2.h> /* needed to define AF_ values on Windows */
48 #ifdef NEED_INET_V6DEFS_H
49 # include "wsutil/inet_v6defs.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>
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;
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
225 gint32 pt
[SDP_MAX_RTP_PAYLOAD_TYPES
];
227 GHashTable
*rtp_dyn_payload
;
229 } transport_media_pt_t
;
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
];
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 */
251 /* Data that is retrieved from a packet, but does not need to be kept */
253 char *connection_address
;
254 char *connection_type
;
256 char *media_port
[SDP_MAX_RTP_CHANNELS
];
257 char *media_proto
[SDP_MAX_RTP_CHANNELS
];
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
269 * http://www.iana.org/assignments/sdp-parameters
271 static dissector_table_t key_mgmt_dissector_table
;
273 /* Subdissector functions */
275 dissect_sdp_owner(tvbuff_t
*tvb
, proto_item
*ti
) {
276 proto_tree
*sdp_owner_tree
;
277 gint offset
, next_offset
, tokenlen
;
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)
287 tokenlen
= next_offset
- offset
;
289 proto_tree_add_item(sdp_owner_tree
, hf_owner_username
, tvb
, offset
, tokenlen
,
291 offset
= next_offset
+ 1;
293 /* Find the session id */
294 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
295 if (next_offset
== -1)
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)
307 tokenlen
= next_offset
- offset
;
309 proto_tree_add_item(sdp_owner_tree
, hf_owner_version
, tvb
, offset
, tokenlen
,
311 offset
= next_offset
+ 1;
313 /* Find the network type */
314 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
315 if (next_offset
== -1)
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)
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
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
;
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)
356 tokenlen
= next_offset
- offset
;
358 proto_tree_add_item(sdp_connection_info_tree
,
359 hf_connection_info_network_type
, tvb
, offset
, tokenlen
,
361 offset
= next_offset
+ 1;
363 /* Find the address type */
364 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
365 if (next_offset
== -1)
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
,
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
));
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 */
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
);
413 dissect_sdp_bandwidth(tvbuff_t
*tvb
, proto_item
*ti
) {
414 proto_tree
*sdp_bandwidth_tree
;
415 gint offset
, next_offset
, tokenlen
;
417 gboolean unit_is_kbs
= FALSE
;
418 gboolean unit_is_bps
= FALSE
;
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)
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)]");
437 } else if (tvb_strneql(tvb
, offset
, "AS", 2) == 0) {
438 proto_item_append_text(item
, " [Application Specific (RTP session bandwidth)]");
440 } else if (tvb_strneql(tvb
, offset
, "TIAS", 4) == 0) {
441 proto_item_append_text(item
, " [Transport Independent Application Specific maximum]");
446 offset
= next_offset
+ 1;
448 item
= proto_tree_add_item(sdp_bandwidth_tree
, hf_bandwidth_value
, tvb
, offset
, -1,
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
;
462 sdp_time_tree
= proto_item_add_subtree(ti
, ett_sdp_time
);
465 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
466 if (next_offset
== -1)
469 tokenlen
= next_offset
- offset
;
470 proto_tree_add_item(sdp_time_tree
, hf_time_start
, tvb
, offset
, tokenlen
,
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
;
484 sdp_repeat_time_tree
= proto_item_add_subtree(ti
, ett_sdp_time
);
487 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
488 if (next_offset
== -1)
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
);
496 offset
= next_offset
+ 1;
497 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
498 if (next_offset
== -1)
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
);
507 offset
= next_offset
+1;
508 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
509 if (next_offset
!= -1) {
510 tokenlen
= next_offset
- offset
;
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);
520 dissect_sdp_timezone(tvbuff_t
*tvb
, proto_item
* ti
) {
521 proto_tree
* sdp_timezone_tree
;
522 gint offset
, next_offset
, tokenlen
;
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)
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
;
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
;
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)
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
;
578 tvbuff_t
*keymgmt_tvb
;
579 gboolean found_match
= FALSE
;
580 proto_tree
*key_tree
;
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)
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
);
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
,
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
);
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
;
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)
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
);
656 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
658 if (next_offset
== -1)
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
);
670 tokenlen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, FALSE
);
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) {
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
);
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 */
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
;
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)
709 tokenlen
= next_offset
- offset
;
711 /* Type of media session */
712 proto_tree_add_item(sdp_media_tree
, hf_media_media
, tvb
, offset
, tokenlen
,
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)
722 tokenlen
= next_offset
- offset
;
723 next_offset
= tvb_find_guint8(tvb
, offset
, tokenlen
, '/');
725 if (next_offset
!= -1) {
726 tokenlen
= next_offset
- offset
;
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)
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;
741 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
743 if (next_offset
== -1)
745 tokenlen
= next_offset
- offset
;
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)
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
,
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 */
774 break; /* Nothing more left */
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
++;
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.
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 */
812 /* first, skip to where the encoded pdu starts, this is
813 the first hex digit after the '=' char.
816 if ((*msg
== 0) || (*msg
== '\n')) {
826 if ((*msg
== 0) || (*msg
== '\n')) {
829 if ( ((*msg
>= '0') && (*msg
<= '9'))
830 || ((*msg
>= 'a') && (*msg
<= 'f'))
831 || ((*msg
>= 'A') && (*msg
<= 'F'))) {
837 while (((*msg
>= '0') && (*msg
<= '9'))
838 || ((*msg
>= 'a') && (*msg
<= 'f'))
839 || ((*msg
>= 'A') && (*msg
<= 'F'))) {
841 if ((*msg
>= '0') && (*msg
<= '9')) {
843 } else if ((*msg
>= 'a') && (*msg
<= 'f')) {
845 } else if ((*msg
>= 'A') && (*msg
<= 'F')) {
852 if ((*msg
>= '0') && (*msg
<= '9')) {
854 } else if ((*msg
>= 'a') && (*msg
<= 'f')) {
855 val
|= (*msg
)-'a'+10;
856 } else if ((*msg
>= 'A') && (*msg
<= 'F')) {
857 val
|= (*msg
)-'A'+10;
863 buf
[i
] = (guint8
)val
;
869 bytes_tvb
= tvb_new_child_real_data(tvb
, buf
, i
, i
);
870 add_new_data_source(pinfo
, bytes_tvb
, "ASCII bytes to tvb");
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" },
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" },
907 static const value_string h264_packetization_mode_vals
[] =
909 { 0, "Single NAL mode" },
910 { 1, "Non-interleaved mode" },
911 { 2, "Interleaved mode" },
916 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
919 decode_sdp_fmtp(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, gint offset
, gint tokenlen
, char *mime_type
) {
923 gchar
*format_specific_parameter
;
925 tvbuff_t
* volatile data_tvb
;
927 end_offset
= offset
+ tokenlen
;
930 proto_tree_add_text(tree
, tvb
, offset
, tokenlen
, "Debug; Analysed string: '%s'",
931 tvb_get_string(wmem_packet_scope(), tvb
, offset
, tokenlen
));
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 */
943 /* Find the name of the parameter */
944 tokenlen
= next_offset
- offset
;
945 field_name
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, tokenlen
);
947 proto_tree_add_text(tree
, tvb
, offset
, tokenlen
, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type
, field_name
); */
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) {
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) {
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) {
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
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) {
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
);
1014 proto_tree_add_text(tree
, tvb
, offset
, tokenlen
, "Could not convert '%s' to 3 bytes", format_specific_parameter
);
1017 length
= tvb_length(data_tvb
);
1019 if (h264_handle
&& data_tvb
) {
1020 dissect_h264_profile(data_tvb
, pinfo
, tree
);
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) {
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
;
1049 comma_offset
= tvb_find_guint8(tvb
, offset
, -1, ',');
1050 if (comma_offset
!= -1) {
1051 tokenlen
= comma_offset
- offset
;
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
) {
1065 dissect_h264_nal_unit(data_tvb
, pinfo
, tree
);
1067 CATCH_NONFATAL_ERRORS
{
1068 show_exception(tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
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
);
1091 #define SDP_RTPMAP 1
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 */
1103 { "h248item"}, /* 4 */
1104 { "crypto"}, /* 5 */
1108 static gint
find_sdp_media_attribute_names(tvbuff_t
*tvb
, int offset
, guint len
)
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))
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
;
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
;
1137 guint8 master_key_length
= 0, master_salt_length
= 0;
1138 encoding_name_and_rate_t
*encoding_name_and_rate
;
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)
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
);
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
) {
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)
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) {
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
)))
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=").
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
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
];
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 */
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
);
1255 /* if the "a=" is after an "m=", only apply to this "m=" */
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
);
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)
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
]);
1293 payload_type
= tvb_get_string(wmem_packet_scope(), tvb
, offset
, tokenlen
);
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;
1324 /* msrp attributes that contain address needed for conversation */
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"
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
;
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.
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
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
);
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)
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 */
1421 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
1422 if(next_offset
==-1){
1423 /* XXX Add expert item? */
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;
1432 next_offset
= tvb_find_guint8(tvb
, offset
, -1, ' ');
1433 if(next_offset
==-1){
1434 /* XXX Add expert item? */
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;
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
);
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
;
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
);
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
){
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
;
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
);
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
);
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
) {
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
) &&
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
;
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
;
1703 gboolean in_media_description
= FALSE
;
1705 const int tokenoffset
= 2;
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
)
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
))
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=".
1766 type
= tvb_get_guint8(tvb
, offset
);
1767 delim
= tvb_get_guint8(tvb
, offset
+ 1);
1769 offset
= next_offset
;
1774 * Attributes. Only care about ones that affect the transport. Ignore others.
1778 hf
= hf_connection_info
;
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
;
1793 if (in_media_description
) {
1794 hf
= hf_media_attribute
;
1796 hf
= hf_session_attribute
;
1804 if (hf
!= hf_unknown
)
1806 call_sdp_subdissector(tvb_new_subset(tvb
, offset
+ tokenoffset
,
1807 linelen
- tokenoffset
,
1808 linelen
- tokenoffset
),
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
);
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
];
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
);
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
)) &&
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 */
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
) &&
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
;
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
);
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
;
1968 gboolean in_media_description
;
1970 int datalen
, tokenoffset
, hf
= -1;
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
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=".
2055 type
= tvb_get_guint8(tvb
, offset
);
2056 delim
= tvb_get_guint8(tvb
, offset
+ 1);
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
;
2069 hf
= hf_protocol_version
;
2075 hf
= hf_session_name
;
2078 if (in_media_description
) {
2079 hf
= hf_media_title
;
2081 hf
= hf_session_info
;
2094 hf
= hf_connection_info
;
2103 hf
= hf_repeat_time
;
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
;
2118 hf
= hf_encryption_key
;
2121 if (in_media_description
) {
2122 hf
= hf_media_attribute
;
2124 hf
= hf_session_attribute
;
2135 if (hf
== hf_unknown
)
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
,
2142 call_sdp_subdissector(tvb_new_subset(tvb
, offset
+ tokenoffset
,
2143 linelen
- tokenoffset
,
2144 linelen
- tokenoffset
),
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
);
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
];
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
);
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
)) &&
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 */
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
) &&
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);
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);
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"),
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
);
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
);
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,
2327 { "Owner/Creator, Session Id (o)",
2328 "sdp.owner", FT_STRING
, BASE_NONE
, NULL
,
2332 { "Session Name (s)", "sdp.session_name",
2333 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2337 { "Session Information (i)", "sdp.session_info",
2338 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2342 { "URI of Description (u)", "sdp.uri",
2343 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2347 { "E-mail Address (e)", "sdp.email",
2348 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2349 "E-mail Address", HFILL
}
2352 { "Phone Number (p)", "sdp.phone",
2353 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2356 { &hf_connection_info
,
2357 { "Connection Information (c)", "sdp.connection_info",
2358 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2362 { "Bandwidth Information (b)", "sdp.bandwidth",
2363 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2367 { "Time Zone Adjustments (z)", "sdp.timezone",
2368 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2371 { &hf_encryption_key
,
2372 { "Encryption Key (k)", "sdp.encryption_key",
2373 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2376 { &hf_session_attribute
,
2377 { "Session Attribute (a)", "sdp.session_attr",
2378 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2381 { &hf_media_attribute
,
2382 { "Media Attribute (a)", "sdp.media_attr",
2383 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2387 { "Time Description, active time (t)",
2388 "sdp.time", FT_STRING
, BASE_NONE
, NULL
,
2392 { "Repeat Time (r)", "sdp.repeat_time",
2393 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2397 { "Media Description, name and address (m)",
2398 "sdp.media", FT_STRING
, BASE_NONE
, NULL
,
2402 { "Media Title (i)", "sdp.media_title",
2403 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2404 "Media Title", HFILL
}
2407 { "Unknown", "sdp.unknown",
2408 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2412 { "Invalid line", "sdp.invalid",
2413 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2416 { &hf_owner_username
,
2417 { "Owner Username", "sdp.owner.username",
2418 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2421 { &hf_owner_sessionid
,
2422 { "Session ID", "sdp.owner.sessionid",
2423 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2426 { &hf_owner_version
,
2427 { "Session Version", "sdp.owner.version",
2428 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2431 { &hf_owner_network_type
,
2432 { "Owner Network Type", "sdp.owner.network_type",
2433 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2436 { &hf_owner_address_type
,
2437 { "Owner Address Type", "sdp.owner.address_type",
2438 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2441 { &hf_owner_address
,
2442 { "Owner Address", "sdp.owner.address",
2443 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2446 { &hf_connection_info_network_type
,
2447 { "Connection Network Type", "sdp.connection_info.network_type",
2448 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2451 { &hf_connection_info_address_type
,
2452 { "Connection Address Type", "sdp.connection_info.address_type",
2453 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2456 { &hf_connection_info_connection_address
,
2457 { "Connection Address", "sdp.connection_info.address",
2458 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2461 { &hf_connection_info_ttl
,
2462 { "Connection TTL", "sdp.connection_info.ttl",
2463 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2466 { &hf_connection_info_num_addr
,
2467 { "Connection Number of Addresses", "sdp.connection_info.num_addr",
2468 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2471 { &hf_bandwidth_modifier
,
2472 { "Bandwidth Modifier", "sdp.bandwidth.modifier",
2473 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2476 { &hf_bandwidth_value
,
2477 { "Bandwidth Value", "sdp.bandwidth.value",
2478 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2479 "Bandwidth Value (in kbits/s)", HFILL
}
2482 { "Session Start Time", "sdp.time.start",
2483 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2487 { "Session Stop Time", "sdp.time.stop",
2488 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2491 { &hf_repeat_time_interval
,
2492 { "Repeat Interval", "sdp.repeat_time.interval",
2493 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2496 { &hf_repeat_time_duration
,
2497 { "Repeat Duration", "sdp.repeat_time.duration",
2498 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2501 { &hf_repeat_time_offset
,
2502 { "Repeat Offset", "sdp.repeat_time.offset",
2503 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2506 { &hf_timezone_time
,
2507 { "Timezone Time", "sdp.timezone.time",
2508 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2511 { &hf_timezone_offset
,
2512 { "Timezone Offset", "sdp.timezone.offset",
2513 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2516 { &hf_encryption_key_type
,
2517 { "Key Type", "sdp.encryption_key.type",
2518 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2521 { &hf_encryption_key_data
,
2522 { "Key Data", "sdp.encryption_key.data",
2523 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2526 { &hf_session_attribute_field
,
2527 { "Session Attribute Fieldname", "sdp.session_attr.field",
2528 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2531 { &hf_session_attribute_value
,
2532 { "Session Attribute Value", "sdp.session_attr.value",
2533 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2537 { "Media Type", "sdp.media.media",
2538 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2542 { "Media Port", "sdp.media.port",
2543 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
2546 { &hf_media_portcount
,
2547 { "Media Port Count", "sdp.media.portcount",
2548 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2552 { "Media Protocol", "sdp.media.proto",
2553 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2557 { "Media Format", "sdp.media.format",
2558 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2561 { &hf_media_attribute_field
,
2562 { "Media Attribute Fieldname", "sdp.media_attribute.field",
2563 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2566 { &hf_media_attribute_value
,
2567 { "Media Attribute Value", "sdp.media_attribute.value",
2568 FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
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,
2592 { "IPBCP Command Type", "sdp.ipbcp.command",
2593 FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
2601 { &hf_sdp_fmtp_h263_profile
,
2602 { "Profile", "sdp.fmtp.h263profile",
2603 FT_UINT32
, BASE_DEC
, VALS(h263_profile_vals
), 0x0,
2606 { &hf_sdp_fmtp_h263_level
,
2607 { "Level", "sdp.fmtp.h263level",
2608 FT_UINT32
, BASE_DEC
, VALS(h263_level_vals
), 0x0,
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,
2616 { &hf_SDPh223LogicalChannelParameters
,
2617 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
2618 FT_NONE
, BASE_NONE
, NULL
, 0,
2621 { &hf_key_mgmt_att_value
,
2622 { "Key Management", "sdp.key_mgmt",
2623 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2626 { &hf_key_mgmt_prtcl_id
,
2627 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
2628 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2631 { &hf_key_mgmt_data
,
2632 { "Key Management Data", "sdp.key_mgmt.data",
2633 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2636 { &hf_sdp_crypto_tag
,
2637 { "tag", "sdp.crypto.tag",
2638 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2641 { &hf_sdp_crypto_crypto_suite
,
2642 { "Crypto suite", "sdp.crypto.crypto_suite",
2643 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2646 { &hf_sdp_crypto_master_key
,
2647 { "Master Key", "sdp.crypto.master_key",
2648 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2651 { &hf_sdp_crypto_master_salt
,
2652 { "Master salt", "sdp.crypto.master_salt",
2653 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2656 { &hf_sdp_crypto_lifetime
,
2657 { "Lifetime", "sdp.crypto.lifetime",
2658 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2661 { &hf_sdp_crypto_mki
,
2662 { "mki-value", "sdp.crypto.mki-valu",
2663 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2666 { &hf_sdp_crypto_mki_length
,
2667 { "mki_length", "sdp.crypto.mki_length",
2668 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2672 static gint
*ett
[] = {
2675 &ett_sdp_connection_info
,
2678 &ett_sdp_repeat_time
,
2680 &ett_sdp_encryption_key
,
2681 &ett_sdp_session_attribute
,
2683 &ett_sdp_media_attribute
,
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",
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");
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
);