2 * Routines for SDP packet disassembly (RFC 2327)
4 * Jason Lango <jal@netapp.com>
5 * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 * Ref https://www.ietf.org/rfc/rfc4566
17 #include <epan/packet.h>
18 #include <epan/exceptions.h>
19 #include <epan/asn1.h>
20 #include <epan/prefs.h>
21 #include <epan/expert.h>
23 #include <epan/rtp_pt.h>
24 #include <epan/show_exception.h>
25 #include <epan/addr_resolv.h>
26 #include <epan/conversation.h>
27 #include <epan/proto_data.h>
28 #include <epan/strutil.h>
30 #include <wsutil/strtoi.h>
31 #include <wsutil/str_util.h>
33 #include "packet-media-type.h"
34 #include "packet-sdp.h"
36 /* un-comment the following as well as this line in conversation.c, to enable debug printing */
37 /* #define DEBUG_CONVERSATION */
38 #include "conversation_debug.h"
40 #include "packet-gsm_osmux.h"
41 #include "packet-rtp.h"
42 #include "packet-rtcp.h"
43 #include "packet-t38.h"
44 #include "packet-msrp.h"
45 #include "packet-sprt.h"
46 #include "packet-bfcp.h"
47 #include "packet-h245.h"
48 #include "packet-h264.h"
49 #include "packet-h265.h"
50 #include "packet-mp4ves.h"
52 void proto_register_sdp(void);
53 void proto_reg_handoff_sdp(void);
55 static dissector_handle_t sdp_handle
;
56 static dissector_handle_t rtcp_handle
;
57 static dissector_handle_t sprt_handle
;
58 static dissector_handle_t msrp_handle
;
59 static dissector_handle_t bfcp_handle
;
60 static dissector_handle_t h264_handle
;
61 static dissector_handle_t h265_handle
;
62 static dissector_handle_t mp4ves_config_handle
;
67 static int proto_sprt
;
69 static const char* UNKNOWN_ENCODING
= "Unknown";
70 static wmem_tree_t
*sdp_transport_reqs
;
71 static wmem_tree_t
*sdp_transport_rsps
;
73 /* preference globals */
74 static bool global_sdp_establish_conversation
= true;
76 /* Top level fields */
77 static int hf_protocol_version
;
79 static int hf_session_name
;
80 static int hf_session_info
;
84 static int hf_connection_info
;
85 static int hf_bandwidth
;
86 static int hf_timezone
;
87 static int hf_encryption_key
;
88 static int hf_session_attribute
;
89 static int hf_media_attribute
;
91 static int hf_repeat_time
;
93 static int hf_media_title
;
94 static int hf_unknown
;
95 static int hf_invalid
;
96 static int hf_ipbcp_version
;
97 static int hf_ipbcp_type
;
99 /* hf_owner subfields*/
100 static int hf_owner_username
;
101 static int hf_owner_sessionid
;
102 static int hf_owner_version
;
103 static int hf_owner_network_type
;
104 static int hf_owner_address_type
;
105 static int hf_owner_address
;
107 /* hf_connection_info subfields */
108 static int hf_connection_info_network_type
;
109 static int hf_connection_info_address_type
;
110 static int hf_connection_info_connection_address
;
111 static int hf_connection_info_ttl
;
112 static int hf_connection_info_num_addr
;
114 /* hf_bandwidth subfields */
115 static int hf_bandwidth_modifier
;
116 static int hf_bandwidth_value
;
118 /* hf_time subfields */
119 static int hf_time_start
;
120 static int hf_time_stop
;
122 /* hf_repeat_time subfield */
123 static int hf_repeat_time_interval
;
124 static int hf_repeat_time_duration
;
125 static int hf_repeat_time_offset
;
127 /* hf_timezone subfields */
128 static int hf_timezone_time
;
129 static int hf_timezone_offset
;
131 /* hf_encryption_key subfields */
132 static int hf_encryption_key_type
;
133 static int hf_encryption_key_data
;
135 /* hf_session_attribute subfields */
136 static int hf_session_attribute_field
;
137 static int hf_session_attribute_value
;
139 /* hf_media subfields */
140 static int hf_media_media
;
141 static int hf_media_port
;
142 static int hf_media_port_string
;
143 static int hf_media_portcount
;
144 static int hf_media_proto
;
145 static int hf_media_format
;
147 /* hf_session_attribute subfields */
148 static int hf_media_attribute_field
;
149 static int hf_media_attribute_value
;
150 static int hf_media_encoding_name
;
151 static int hf_media_sample_rate
;
152 static int hf_media_channels
;
153 static int hf_media_format_specific_parameter
;
154 static int hf_sdp_fmtp_mpeg4_profile_level_id
;
155 static int hf_sdp_fmtp_h263_profile
;
156 static int hf_sdp_fmtp_h263_level
;
157 static int hf_sdp_h264_packetization_mode
;
158 static int hf_SDPh223LogicalChannelParameters
;
160 /* hf_session_attribute hf_media_attribute subfields */
161 static int hf_key_mgmt_att_value
;
162 static int hf_key_mgmt_prtcl_id
;
163 static int hf_key_mgmt_data
;
165 static int hf_sdp_crypto_tag
;
166 static int hf_sdp_crypto_crypto_suite
;
167 static int hf_sdp_crypto_master_key
;
168 static int hf_sdp_crypto_master_salt
;
169 static int hf_sdp_crypto_lifetime
;
170 static int hf_sdp_crypto_mki
;
171 static int hf_sdp_crypto_mki_length
;
173 /* a=candidate subfields */
174 static int hf_ice_candidate_foundation
;
175 static int hf_ice_candidate_componentid
;
176 static int hf_ice_candidate_transport
;
177 static int hf_ice_candidate_priority
;
178 static int hf_ice_candidate_address
;
179 static int hf_ice_candidate_port
;
180 static int hf_ice_candidate_type
;
182 /* Generated from convert_proto_tree_add_text.pl */
183 static int hf_sdp_nal_unit_2_string
;
184 static int hf_sdp_key_and_salt
;
185 static int hf_sdp_nal_unit_1_string
;
186 static int hf_sdp_data
;
190 static int ett_sdp_owner
;
191 static int ett_sdp_connection_info
;
192 static int ett_sdp_bandwidth
;
193 static int ett_sdp_time
;
194 static int ett_sdp_repeat_time
;
195 static int ett_sdp_timezone
;
196 static int ett_sdp_encryption_key
;
197 static int ett_sdp_session_attribute
;
198 static int ett_sdp_media
;
199 static int ett_sdp_media_attribute
;
200 static int ett_sdp_fmtp
;
201 static int ett_sdp_key_mgmt
;
202 static int ett_sdp_crypto_key_parameters
;
204 static expert_field ei_sdp_invalid_key_param
;
205 static expert_field ei_sdp_invalid_line_equal
;
206 static expert_field ei_sdp_invalid_line_fields
;
207 static expert_field ei_sdp_invalid_line_space
;
208 static expert_field ei_sdp_invalid_conversion
;
209 static expert_field ei_sdp_invalid_media_port
;
210 static expert_field ei_sdp_invalid_sample_rate
;
211 static expert_field ei_sdp_invalid_channels
;
212 static expert_field ei_sdp_invalid_media_format
;
213 static expert_field ei_sdp_invalid_crypto_tag
;
214 static expert_field ei_sdp_invalid_crypto_mki_length
;
216 /* patterns used for tvb_ws_mempbrk_pattern_uint8 */
217 static ws_mempbrk_pattern pbrk_digits
;
218 static ws_mempbrk_pattern pbrk_alpha
;
221 SDP_PROTO_UNKNOWN
= 0,
231 #define SDP_MAX_RTP_CHANNELS 4
232 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
233 #define SDP_NO_OF_PT 128
235 * All parameters specific to one media description ("m=").
238 int32_t pt
[SDP_MAX_RTP_PAYLOAD_TYPES
];
240 rtp_dyn_payload_t
*rtp_dyn_payload
;
242 } transport_media_pt_t
;
245 * Store data extracted from one Media Description section of a SDP. Memory is
246 * allocated in wmem_file_scope().
249 transport_proto_t proto
; /**< Protocol, parsed from "m=" line. */
250 uint32_t media_types
; /**< Whether "m=video" or others */
251 bool bundled
; /**< "m=" lines are "bundled", that is, all on same port */
252 uint16_t media_port
; /**< Port number, parsed from "m=" line. */
253 uint16_t control_port
; /**< Port number, parsed from "a=rtcp" or "a=rtcp-mux" line. */
254 address conn_addr
; /**< The address from the "c=" line (default
255 from session level, possibly overridden at
257 transport_media_pt_t media
; /**< Information about payload numbers for this media. */
260 * Media-level only attributes.
265 uint16_t port_number
;
266 } msrp
; /**< MSRP transport info, parsed from "a=label:" */
268 } media_description_t
;
271 * Information parsed from one or two (offer/answer) SDPs that is stored in the
272 * conversation. The contents are allocated within wmem_file_scope().
275 enum sdp_exchange_type sdp_status
;
276 char *encoding_name
[SDP_NO_OF_PT
];
277 int sample_rate
[SDP_NO_OF_PT
];
278 unsigned channels
[SDP_NO_OF_PT
];
280 /* Data parsed from "m=" */
281 wmem_array_t
*media_descriptions
; /* array of media_description_t */
283 wmem_array_t
*sdp_setup_info_list
; /* array of sdp_setup_info_t that refer
284 * to the same RTP conversation */
286 /* SRTP related info XXX note currently we only handle one crypto line in the SDP
287 * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
288 * seting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
289 * and the SDP dissector just provide the relevant data.
290 * YES! packet-sdp.c should be about SDP parsing... SDP *state* needs to be maintained by upper
291 * protocols, because each one has different rules/semantics.
293 unsigned encryption_algorithm
;
294 unsigned auth_algorithm
;
295 unsigned mki_len
; /* number of octets used for the MKI in the RTP payload */
296 unsigned auth_tag_len
; /* number of octets used for the Auth Tag in the RTP payload */
300 * Information about the session description. These are accumulated while
301 * parsing the session description and will be applied to the media description.
302 * Memory scope can be pinfo->pool since the contents are no longer
303 * needed once they are processed into transport_info_t (via
304 * complete_descriptions).
307 address conn_addr
; /**< Parsed from "c=" line. */
308 rtp_dyn_payload_t
*rtp_dyn_payload
; /**< Parsed from "a=rtpmap:" line.
309 Note: wmem_file_scope, needs manual dealloc. */
312 /* Structure for private data to hold ED137 related values */
313 typedef struct sdp_data_t
{
314 char *ed137_type
; /* Radio session type */
315 char *ed137_txrxmode
; /* Tx/Rx mode */
316 char *ed137_fid
; /* Frequency ID */
320 /* here lie the debugging dumper functions */
321 #ifdef DEBUG_CONVERSATION
322 static void sdp_dump_transport_media(const transport_media_pt_t
* media
) {
325 DPRINT2(("transport_media contents:"));
328 DPRINT2(("null transport_media_pt_t*"));
332 count
= (int)media
->pt_count
;
333 DPRINT2(("pt_count=%d",count
));
335 for (i
=0; i
< count
; i
++) {
336 DPRINT2(("pt=%d", media
->pt
[i
]));
339 DPRINT2(("rtp_dyn_payload hashtable=%s", media
->rtp_dyn_payload
? "YES" : "NO"));
340 if (media
->rtp_dyn_payload
) {
341 rtp_dump_dyn_payload(media
->rtp_dyn_payload
);
343 DPRINT2(("set_rtp=%s", media
->set_rtp
? "TRUE" : "FALSE"));
347 static const value_string sdp_exchange_type_vs
[] = {
348 { SDP_EXCHANGE_OFFER
, "SDP_EXCHANGE_OFFER" },
349 { SDP_EXCHANGE_ANSWER_ACCEPT
, "SDP_EXCHANGE_ANSWER_ACCEPT" },
350 { SDP_EXCHANGE_ANSWER_REJECT
, "SDP_EXCHANGE_ANSWER_REJECT" },
354 static void sdp_dump_transport_info(const transport_info_t
* info
) {
357 DPRINT2(("transport_info contents:"));
360 DPRINT2(("null transport_info_t*"));
364 DPRINT2(("sdp_status=%s",
365 val_to_str_const(info
->sdp_status
, sdp_exchange_type_vs
, "SDP_EXCHANGE_UNKNOWN")));
366 DPRINT2(("payload type contents:"));
368 for (i
=0; i
< SDP_NO_OF_PT
; i
++) {
369 /* don't print out unknown encodings */
370 if (info
->encoding_name
[i
] &&
371 strcmp(UNKNOWN_ENCODING
,info
->encoding_name
[i
]) != 0) {
372 DPRINT2(("payload type #%d:",i
));
374 DPRINT2(("encoding_name=%s", info
->encoding_name
[i
]));
375 DPRINT2(("sample_rate=%d", info
->sample_rate
[i
]));
380 count
= wmem_array_get_count(info
->media_descriptions
);
381 DPRINT2(("media_count=%d", count
));
382 DPRINT2(("rtp channels:"));
384 for (i
=0; i
< count
; i
++) {
385 media_description_t
*media_desc
= (media_description_t
*)wmem_array_index(info
->media_descriptions
, i
);
386 DPRINT2(("channel #%d:",i
));
388 DPRINT2(("conn_addr=%s", address_to_str(pinfo
->pool
, &(media_desc
->conn_addr
))));
389 DPRINT2(("media_port=%d", media_desc
->media_port
));
390 DPRINT2(("proto=%d", media_desc
->proto
));
391 sdp_dump_transport_media(&(media_desc
->media
));
395 DPRINT2(("encryption_algorithm=%u", info
->encryption_algorithm
));
396 DPRINT2(("auth_algorithm=%u", info
->auth_algorithm
));
397 if (info
->encryption_algorithm
|| info
->auth_algorithm
) {
398 DPRINT2(("mki_len=%u", info
->mki_len
));
399 if (info
->auth_algorithm
) {
400 DPRINT2(("auth_tag_len=%u", info
->auth_tag_len
));
406 #endif /* DEBUG_CONVERSATION */
409 /* key-mgmt dissector
411 * http://www.iana.org/assignments/sdp-parameters
413 static dissector_table_t key_mgmt_dissector_table
;
415 /* Finds next token (sequence of non-space chars) in tvb from given offset.
416 * The returned value is the token length, or 0 if none found.
417 * The offset is changed to be the starting offset, in case there were one or more
418 * spaces at the beginning. (this will also add expert info in such a case)
419 * The next_offset is set to the next found space after the token, or -1 if the
420 * end of line is hit or no token found.
421 * If this is the last token in the line, tokenlen will not be 0, but next_offset
424 * The optional param, if true, means no expert error will be issued if no token
425 * is found; if false then a expert error will be issued if no token is found.
427 * This function expects to be given a tvb of only one line, and does no error
428 * checking of its given arguments.
431 find_next_optional_token_in_line(tvbuff_t
*tvb
, proto_tree
*tree
,
432 int *offset
, int *next_offset
,
439 if (tvb_offset_exists(tvb
, off
)) {
440 while (tokenlen
== 0) {
441 next_off
= tvb_find_uint8(tvb
, off
, -1, ' ');
442 if (next_off
== -1) {
443 tokenlen
= tvb_captured_length_remaining(tvb
, off
);
444 break; /* Nothing more left */
447 tokenlen
= next_off
- off
;
450 /* two spaces in a row - illegal, but we'll keep dissecting */
451 proto_tree_add_expert(tree
, NULL
, &ei_sdp_invalid_line_space
, tvb
, off
-1, 2);
457 if (!optional
&& tokenlen
== 0) {
458 proto_tree_add_expert(tree
, NULL
, &ei_sdp_invalid_line_fields
, tvb
, 0, -1);
461 *next_offset
= next_off
;
466 /* Same as above, but always issues an expert error if a token is not found. */
468 find_next_token_in_line(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, int *next_offset
)
470 return find_next_optional_token_in_line(tvb
, tree
, offset
, next_offset
, false);
473 /* Convert the protocol from the "m=" line to something we understand. */
474 static transport_proto_t
475 parse_sdp_media_protocol(const char *media_proto
)
477 /* Sorted according to the "proto" registry at
478 * https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml#sdp-parameters-2 */
480 const char *proto_name
;
481 transport_proto_t proto
;
483 { "RTP/AVP", SDP_PROTO_RTP
}, /* RFC 4566 */
484 { "udptl", SDP_PROTO_T38
}, /* ITU-T T.38, example in Annex E */
485 { "UDPTL", SDP_PROTO_T38
}, /* Note: IANA registry contains lower case */
486 { "RTP/AVPF", SDP_PROTO_RTP
}, /* RFC 4585 */
487 { "RTP/SAVP", SDP_PROTO_SRTP
}, /* RFC 3711 */
488 { "RTP/SAVPF", SDP_PROTO_SRTP
}, /* RFC 5124 */
489 { "UDP/TLS/RTP/SAVP", SDP_PROTO_SRTP
}, /* RFC 5764 */
490 { "UDP/TLS/RTP/SAVPF", SDP_PROTO_SRTP
}, /* RFC 5764 */
491 { "msrp/tcp", SDP_PROTO_MSRP
}, /* Not in IANA, where is this from? */
492 { "UDPSPRT", SDP_PROTO_SPRT
}, /* Not in IANA, but draft-rajeshkumar-avt-v150-registration-00 */
493 { "udpsprt", SDP_PROTO_SPRT
}, /* lowercase per section E.1.1 of ITU-T V.150.1 */
494 { "udpsprt", SDP_PROTO_SPRT
}, /* lowercase per section E.1.1 of ITU-T V.150.1 */
495 { "UDP/BFCP", SDP_PROTO_BFCP
}, /* RFC 8856 */
498 for (unsigned i
= 0; i
< G_N_ELEMENTS(protocols
); i
++) {
499 if (!strcmp(protocols
[i
].proto_name
, media_proto
)) {
500 return protocols
[i
].proto
;
504 return SDP_PROTO_UNKNOWN
;
507 /* Parses the parts from "c=" into address structures. */
509 parse_sdp_connection_address(const uint8_t *connection_type
, const char *connection_address
,
510 wmem_allocator_t
*allocator
, address
*conn_addr
)
512 if (strcmp(connection_type
, "IP4") == 0) {
515 if (str_to_ip(connection_address
, &ip4_addr
)) {
516 /* connection_address could be converted to a valid ipv4 address*/
517 alloc_address_wmem(allocator
, conn_addr
, AT_IPv4
, 4, &ip4_addr
);
519 } else if (strcmp(connection_type
, "IP6") == 0) {
520 ws_in6_addr ip6_addr
;
522 if (str_to_ip6(connection_address
, &ip6_addr
)) {
523 /* connection_address could be converted to a valid ipv6 address*/
524 alloc_address_wmem(allocator
, conn_addr
, AT_IPv6
, 16, &ip6_addr
);
530 * Starts a new media description. If there are too many media descriptions,
531 * no new media description is started and NULL is returned.
533 static media_description_t
*
534 sdp_new_media_description(wmem_array_t
*media_descriptions
, session_info_t
*session_info
)
536 media_description_t empty_desc
;
537 media_description_t
*media_desc
;
539 /* Limit number to avoid consuming excess memory. */
540 if (wmem_array_get_count(media_descriptions
) >= SDP_MAX_RTP_CHANNELS
) {
541 DPRINT(("Too many media descriptions (more than %d), returning NULL!",
542 wmem_array_get_count(media_descriptions
)));
546 memset(&empty_desc
, 0, sizeof(media_description_t
));
547 wmem_array_append_one(media_descriptions
, empty_desc
);
548 media_desc
= (media_description_t
*) wmem_array_index(media_descriptions
,
549 wmem_array_get_count(media_descriptions
) - 1);
551 /* XXX does it make sense making media_desc->media.pt a wmem array? */
553 /* If "c=" is given at the session level, copy it to the media description.
554 * It will be overridden as needed. */
555 if (session_info
->conn_addr
.type
!= AT_NONE
) {
556 copy_address_wmem(wmem_file_scope(), &media_desc
->conn_addr
, &session_info
->conn_addr
);
559 /* If "a=rtpmap:" was set on the session level, copy them to media level. */
560 media_desc
->media
.rtp_dyn_payload
=
561 rtp_dyn_payload_dup(session_info
->rtp_dyn_payload
);
566 /* Remove information about media descriptions which are unused. These appeared
567 * in the "a=rtpmap:" (and maybe even in the payload types part of "m="?), but
568 * are not used (port is zero or it was not assigned to RTP dissector). */
570 clean_unused_media_descriptions(wmem_array_t
*descs
)
572 for (unsigned i
= 0; i
< wmem_array_get_count(descs
); i
++) {
573 media_description_t
*media_desc
= (media_description_t
*)wmem_array_index(descs
, i
);
575 /* If not assigned to subdissector, clear the unused information. */
576 if (!media_desc
->media
.set_rtp
) {
577 rtp_dyn_payload_free(media_desc
->media
.rtp_dyn_payload
);
578 media_desc
->media
.rtp_dyn_payload
= NULL
;
584 /* Subdissector functions */
586 dissect_sdp_owner(tvbuff_t
*tvb
, proto_item
*ti
) {
587 proto_tree
*sdp_owner_tree
;
588 int offset
, next_offset
, tokenlen
;
592 sdp_owner_tree
= proto_item_add_subtree(ti
, ett_sdp_owner
);
594 /* Find the username */
595 tokenlen
= find_next_token_in_line(tvb
, sdp_owner_tree
, &offset
, &next_offset
);
599 proto_tree_add_item(sdp_owner_tree
, hf_owner_username
, tvb
, offset
, tokenlen
,
601 offset
= next_offset
+ 1;
603 /* Find the session id */
604 tokenlen
= find_next_token_in_line(tvb
, sdp_owner_tree
, &offset
, &next_offset
);
608 proto_tree_add_item(sdp_owner_tree
, hf_owner_sessionid
, tvb
, offset
,
609 tokenlen
, ENC_UTF_8
);
610 offset
= next_offset
+ 1;
612 /* Find the version */
613 tokenlen
= find_next_token_in_line(tvb
, sdp_owner_tree
, &offset
, &next_offset
);
617 proto_tree_add_item(sdp_owner_tree
, hf_owner_version
, tvb
, offset
, tokenlen
,
619 offset
= next_offset
+ 1;
621 /* Find the network type */
622 tokenlen
= find_next_token_in_line(tvb
, sdp_owner_tree
, &offset
, &next_offset
);
626 proto_tree_add_item(sdp_owner_tree
, hf_owner_network_type
, tvb
, offset
,
627 tokenlen
, ENC_UTF_8
);
628 offset
= next_offset
+ 1;
630 /* Find the address type */
631 tokenlen
= find_next_token_in_line(tvb
, sdp_owner_tree
, &offset
, &next_offset
);
635 proto_tree_add_item(sdp_owner_tree
, hf_owner_address_type
, tvb
, offset
,
636 tokenlen
, ENC_UTF_8
);
637 offset
= next_offset
+ 1;
639 /* Find the address */
640 proto_tree_add_item(sdp_owner_tree
, hf_owner_address
, tvb
, offset
, -1, ENC_UTF_8
);
644 * XXX - this can leak memory if an exception is thrown after we've fetched
648 dissect_sdp_connection_info(packet_info
*pinfo
, tvbuff_t
*tvb
, proto_item
* ti
, session_info_t
*session_info
, media_description_t
*media_desc
)
650 proto_tree
*sdp_connection_info_tree
;
651 int offset
, next_offset
, tokenlen
;
652 const uint8_t *connection_type
, *connection_address
;
656 sdp_connection_info_tree
= proto_item_add_subtree(ti
,
657 ett_sdp_connection_info
);
659 /* Find the network type */
660 tokenlen
= find_next_token_in_line(tvb
, sdp_connection_info_tree
, &offset
, &next_offset
);
664 proto_tree_add_item(sdp_connection_info_tree
,
665 hf_connection_info_network_type
, tvb
, offset
, tokenlen
,
667 offset
= next_offset
+ 1;
669 /* Find the address type */
670 tokenlen
= find_next_token_in_line(tvb
, sdp_connection_info_tree
, &offset
, &next_offset
);
674 /* Save connection address type */
675 proto_tree_add_item_ret_string(sdp_connection_info_tree
,
676 hf_connection_info_address_type
, tvb
, offset
, tokenlen
,
677 ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &connection_type
);
678 DPRINT(("parsed connection line type=%s", connection_type
));
679 offset
= next_offset
+ 1;
681 /* Find the connection address */
682 /* XXX - what if there's a <number of addresses> value? */
683 next_offset
= tvb_find_uint8(tvb
, offset
, -1, '/');
684 if (next_offset
== -1) {
685 tokenlen
= -1; /* end of tvbuff */
686 /* Save connection address */
687 connection_address
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), ENC_UTF_8
|ENC_NA
);
689 tokenlen
= next_offset
- offset
;
690 /* Save connection address */
691 connection_address
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
);
694 DPRINT(("parsed connection line address=%s", connection_address
));
695 /* Parse and store connection address. Session-level addresses are
696 * packet-scoped since they will be cloned in file-scope when needed. */
698 parse_sdp_connection_address(connection_type
, connection_address
,
700 &session_info
->conn_addr
);
701 } else if (media_desc
) {
702 /* Clear possibly inherited address from session level. */
703 free_address_wmem(wmem_file_scope(), &media_desc
->conn_addr
);
705 parse_sdp_connection_address(connection_type
, connection_address
,
707 &media_desc
->conn_addr
);
710 proto_tree_add_item(sdp_connection_info_tree
,
711 hf_connection_info_connection_address
, tvb
, offset
,
712 tokenlen
, ENC_UTF_8
);
713 if (next_offset
!= -1) {
714 offset
= next_offset
+ 1;
715 next_offset
= tvb_find_uint8(tvb
, offset
, -1, '/');
716 if (next_offset
== -1) {
717 tokenlen
= -1; /* end of tvbuff */
719 tokenlen
= next_offset
- offset
;
721 proto_tree_add_item(sdp_connection_info_tree
,
722 hf_connection_info_ttl
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
723 if (next_offset
!= -1) {
724 offset
= next_offset
+ 1;
725 proto_tree_add_item(sdp_connection_info_tree
,
726 hf_connection_info_num_addr
, tvb
, offset
, -1, ENC_UTF_8
);
732 dissect_sdp_bandwidth(tvbuff_t
*tvb
, proto_item
*ti
) {
733 proto_tree
*sdp_bandwidth_tree
;
734 int offset
, next_offset
, tokenlen
;
736 bool unit_is_kbs
= false;
737 bool unit_is_bps
= false;
741 sdp_bandwidth_tree
= proto_item_add_subtree(ti
, ett_sdp_bandwidth
);
743 /* find the modifier */
744 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
746 if (next_offset
== -1)
749 tokenlen
= next_offset
- offset
;
751 item
= proto_tree_add_item(sdp_bandwidth_tree
, hf_bandwidth_modifier
, tvb
, offset
,
752 tokenlen
, ENC_UTF_8
);
753 if (tvb_strneql(tvb
, offset
, "CT", 2) == 0) {
754 proto_item_append_text(item
, " [Conference Total(total bandwidth of all RTP sessions)]");
756 } else if (tvb_strneql(tvb
, offset
, "AS", 2) == 0) {
757 proto_item_append_text(item
, " [Application Specific (RTP session bandwidth)]");
759 } else if (tvb_strneql(tvb
, offset
, "TIAS", 4) == 0) {
760 proto_item_append_text(item
, " [Transport Independent Application Specific maximum]");
765 offset
= next_offset
+ 1;
767 item
= proto_tree_add_item(sdp_bandwidth_tree
, hf_bandwidth_value
, tvb
, offset
, -1,
769 if (unit_is_kbs
== true)
770 proto_item_append_text(item
, " kb/s");
771 if (unit_is_bps
== true)
772 proto_item_append_text(item
, " b/s");
775 static void dissect_sdp_time(tvbuff_t
*tvb
, proto_item
* ti
) {
776 proto_tree
*sdp_time_tree
;
777 int offset
, next_offset
, tokenlen
;
781 sdp_time_tree
= proto_item_add_subtree(ti
, ett_sdp_time
);
784 tokenlen
= find_next_token_in_line(tvb
, sdp_time_tree
, &offset
, &next_offset
);
788 proto_tree_add_item(sdp_time_tree
, hf_time_start
, tvb
, offset
, tokenlen
,
792 offset
= next_offset
+ 1;
793 proto_tree_add_item(sdp_time_tree
, hf_time_stop
, tvb
, offset
, -1, ENC_UTF_8
);
796 static void dissect_sdp_repeat_time(tvbuff_t
*tvb
, proto_item
* ti
) {
797 proto_tree
*sdp_repeat_time_tree
;
798 int offset
, next_offset
, tokenlen
;
799 bool optional
= false;
803 sdp_repeat_time_tree
= proto_item_add_subtree(ti
, ett_sdp_time
);
806 tokenlen
= find_next_token_in_line(tvb
, sdp_repeat_time_tree
, &offset
, &next_offset
);
810 proto_tree_add_item(sdp_repeat_time_tree
, hf_repeat_time_interval
, tvb
,
811 offset
, tokenlen
, ENC_UTF_8
);
814 offset
= next_offset
+ 1;
815 tokenlen
= find_next_token_in_line(tvb
, sdp_repeat_time_tree
, &offset
, &next_offset
);
819 proto_tree_add_item(sdp_repeat_time_tree
, hf_repeat_time_duration
, tvb
,
820 offset
, tokenlen
, ENC_UTF_8
);
824 offset
= next_offset
+1;
825 tokenlen
= find_next_optional_token_in_line(tvb
, sdp_repeat_time_tree
,
826 &offset
, &next_offset
, optional
);
829 proto_tree_add_item(sdp_repeat_time_tree
, hf_repeat_time_offset
,
830 tvb
, offset
, tokenlen
, ENC_UTF_8
);
832 } while (next_offset
!= -1);
837 dissect_sdp_timezone(tvbuff_t
*tvb
, proto_item
* ti
) {
838 proto_tree
* sdp_timezone_tree
;
839 int offset
, next_offset
, tokenlen
;
840 bool optional
= false;
844 sdp_timezone_tree
= proto_item_add_subtree(ti
, ett_sdp_timezone
);
847 tokenlen
= find_next_optional_token_in_line(tvb
, sdp_timezone_tree
,
848 &offset
, &next_offset
, optional
);
852 proto_tree_add_item(sdp_timezone_tree
, hf_timezone_time
, tvb
, offset
,
853 tokenlen
, ENC_UTF_8
);
854 offset
= next_offset
+ 1;
855 tokenlen
= find_next_optional_token_in_line(tvb
, sdp_timezone_tree
,
856 &offset
, &next_offset
, optional
);
859 proto_tree_add_item(sdp_timezone_tree
, hf_timezone_offset
, tvb
, offset
,
860 tokenlen
, ENC_UTF_8
);
861 offset
= next_offset
+ 1;
863 } while (next_offset
!= -1);
868 static void dissect_sdp_encryption_key(tvbuff_t
*tvb
, proto_item
* ti
) {
869 proto_tree
*sdp_encryption_key_tree
;
870 int offset
, next_offset
, tokenlen
;
874 sdp_encryption_key_tree
= proto_item_add_subtree(ti
, ett_sdp_encryption_key
);
876 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
878 if (next_offset
== -1)
881 tokenlen
= next_offset
- offset
;
883 proto_tree_add_item(sdp_encryption_key_tree
, hf_encryption_key_type
,
884 tvb
, offset
, tokenlen
, ENC_UTF_8
);
886 offset
= next_offset
+ 1;
887 proto_tree_add_item(sdp_encryption_key_tree
, hf_encryption_key_data
,
888 tvb
, offset
, -1, ENC_UTF_8
);
891 static void dissect_key_mgmt(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_item
* ti
) {
893 const uint8_t *prtcl_id
= NULL
;
895 tvbuff_t
*keymgmt_tvb
;
897 proto_tree
*key_tree
;
902 key_tree
= proto_item_add_subtree(ti
, ett_sdp_key_mgmt
);
904 tokenlen
= find_next_token_in_line(tvb
, key_tree
, &offset
, &next_offset
);
908 proto_tree_add_item_ret_string(key_tree
, hf_key_mgmt_prtcl_id
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &prtcl_id
);
910 offset
= next_offset
+ 1;
912 len
= tvb_captured_length_remaining(tvb
, offset
);
916 data_p
= (char *)tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, len
, ENC_UTF_8
|ENC_NA
);
917 keymgmt_tvb
= base64_to_tvb(tvb
, data_p
);
918 add_new_data_source(pinfo
, keymgmt_tvb
, "Key Management Data");
920 if ((prtcl_id
!= NULL
) && (key_mgmt_dissector_table
!= NULL
)) {
921 found_match
= dissector_try_string(key_mgmt_dissector_table
,
922 (const char *)prtcl_id
,
928 proto_item
*ti2
= proto_tree_add_item(key_tree
, hf_key_mgmt_data
,
929 keymgmt_tvb
, 0, -1, ENC_NA
);
930 proto_item_set_hidden(ti2
);
932 proto_tree_add_item(key_tree
, hf_key_mgmt_data
,
933 keymgmt_tvb
, 0, -1, ENC_NA
);
939 static void dissect_sdp_session_attribute(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_item
* ti
) {
940 proto_tree
*sdp_session_attribute_tree
;
941 int offset
, next_offset
, tokenlen
;
942 const uint8_t *field_name
;
946 sdp_session_attribute_tree
= proto_item_add_subtree(ti
,
947 ett_sdp_session_attribute
);
949 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
951 if (next_offset
== -1)
954 tokenlen
= next_offset
- offset
;
956 proto_tree_add_item_ret_string(sdp_session_attribute_tree
, hf_session_attribute_field
,
957 tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &field_name
);
959 offset
= next_offset
+ 1;
961 if (tvb_captured_length_remaining(tvb
, offset
) == 0) {
962 expert_add_info(pinfo
, ti
, &ei_sdp_invalid_line_fields
);
966 if (strcmp((const char *)field_name
, "ipbcp") == 0) {
967 offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, offset
, -1,&pbrk_digits
, NULL
);
972 tokenlen
= find_next_token_in_line(tvb
, sdp_session_attribute_tree
, &offset
, &next_offset
);
976 proto_tree_add_item(sdp_session_attribute_tree
, hf_ipbcp_version
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
978 offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, offset
, -1,&pbrk_alpha
, NULL
);
983 tokenlen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
988 proto_tree_add_item(sdp_session_attribute_tree
, hf_ipbcp_type
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
989 } else if (strcmp((const char *)field_name
, "key-mgmt") == 0) {
993 key_tvb
= tvb_new_subset_remaining(tvb
, offset
);
994 key_ti
= proto_tree_add_item(sdp_session_attribute_tree
, hf_key_mgmt_att_value
, key_tvb
, 0, -1, ENC_UTF_8
);
996 dissect_key_mgmt(key_tvb
, pinfo
, key_ti
);
998 proto_tree_add_item(sdp_session_attribute_tree
, hf_session_attribute_value
,
999 tvb
, offset
, -1, ENC_UTF_8
);
1004 /* Dissect media description - this is passed the line starting after 'm=', so like one of these:
1005 * audio 29156 RTP/AVP 18 0
1006 * video 49170/2 RTP/AVP 31 99
1009 dissect_sdp_media(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_item
*ti
,
1010 media_description_t
*media_desc
) {
1011 proto_tree
*sdp_media_tree
;
1012 int offset
, next_offset
, tokenlen
, idx
;
1013 uint8_t *media_format
;
1014 bool optional
= false;
1016 const uint8_t *media_type_str
;
1017 const uint8_t *media_port_str
;
1018 const uint8_t *media_proto_str
;
1019 transport_proto_t transport_proto
;
1020 uint16_t media_port
;
1021 bool media_port_valid
;
1026 /* Create tree for media session */
1027 sdp_media_tree
= proto_item_add_subtree(ti
, ett_sdp_media
);
1029 tokenlen
= find_next_token_in_line(tvb
, sdp_media_tree
, &offset
, &next_offset
);
1033 /* Type of media session */
1034 proto_tree_add_item_ret_string(sdp_media_tree
, hf_media_media
, tvb
, offset
, tokenlen
,
1035 ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &media_type_str
);
1037 /* for RTP statistics (supposedly?) */
1038 if (strcmp((const char*)media_type_str
, "audio") == 0)
1039 media_desc
->media_types
|= RTP_MEDIA_AUDIO
;
1040 else if (strcmp((const char*)media_type_str
, "video") == 0)
1041 media_desc
->media_types
|= RTP_MEDIA_VIDEO
;
1043 media_desc
->media_types
|= RTP_MEDIA_OTHER
;
1045 DPRINT(("parsed media_type=%s", media_type_str
));
1047 offset
= next_offset
+ 1;
1049 tokenlen
= find_next_token_in_line(tvb
, sdp_media_tree
, &offset
, &next_offset
);
1053 next_offset
= tvb_find_uint8(tvb
, offset
, tokenlen
, '/');
1055 if (next_offset
!= -1) {
1056 tokenlen
= next_offset
- offset
;
1057 /* Save port info */
1058 it
= proto_tree_add_item_ret_string(sdp_media_tree
, hf_media_port_string
, tvb
, offset
, tokenlen
,
1059 ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &media_port_str
);
1060 DPRINT(("parsed media_port=%s", media_port_str
));
1061 if (g_ascii_isdigit(media_port_str
[0])) {
1062 proto_item_set_hidden(it
);
1063 media_port_valid
= ws_strtou16(media_port_str
, NULL
, &media_port
);
1064 pi
= proto_tree_add_uint(sdp_media_tree
, hf_media_port
, tvb
, offset
, tokenlen
,
1066 if (!media_port_valid
)
1067 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_media_port
);
1069 media_desc
->media_port
= media_port
;
1073 offset
= next_offset
+ 1;
1074 tokenlen
= find_next_token_in_line(tvb
, sdp_media_tree
, &offset
, &next_offset
);
1078 /* TODO: this puts the (optional) number of ports in the tree, but we don't
1079 actually use it for building the extra RTP flows, which we should. */
1080 proto_tree_add_item(sdp_media_tree
, hf_media_portcount
, tvb
, offset
,
1081 tokenlen
, ENC_UTF_8
);
1082 offset
= next_offset
+ 1;
1084 tokenlen
= find_next_token_in_line(tvb
, sdp_media_tree
, &offset
, &next_offset
);
1088 /* Save port info */
1089 it
= proto_tree_add_item_ret_string(sdp_media_tree
, hf_media_port_string
, tvb
, offset
, tokenlen
,
1090 ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &media_port_str
);
1091 DPRINT(("parsed media_port=%s", media_port_str
));
1092 if (g_ascii_isdigit(media_port_str
[0])) {
1093 proto_item_set_hidden(it
);
1094 media_port_valid
= ws_strtou16(media_port_str
, NULL
, &media_port
);
1095 pi
= proto_tree_add_uint(sdp_media_tree
, hf_media_port
, tvb
, offset
, tokenlen
,
1097 if (!media_port_valid
)
1098 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_media_port
);
1100 media_desc
->media_port
= media_port
;
1103 offset
= next_offset
+ 1;
1106 tokenlen
= find_next_token_in_line(tvb
, sdp_media_tree
, &offset
, &next_offset
);
1110 /* Save port protocol */
1111 proto_tree_add_item_ret_string(sdp_media_tree
, hf_media_proto
, tvb
, offset
, tokenlen
,
1112 ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &media_proto_str
);
1113 DPRINT(("parsed media_proto=%s", media_proto_str
));
1114 /* Detect protocol for registering with other dissectors like RTP. */
1115 transport_proto
= parse_sdp_media_protocol(media_proto_str
);
1117 media_desc
->proto
= transport_proto
;
1121 offset
= next_offset
+ 1;
1122 tokenlen
= find_next_optional_token_in_line(tvb
, sdp_media_tree
,
1123 &offset
, &next_offset
, optional
);
1127 /* RFC 4566: If the <proto> sub-field is "RTP/AVP" or "RTP/SAVP" the
1128 * <fmt> sub-fields contain RTP payload type numbers. */
1129 if (transport_proto
== SDP_PROTO_RTP
|| transport_proto
== SDP_PROTO_SRTP
) {
1130 media_format
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
);
1131 if (g_ascii_isdigit(media_format
[0])) {
1132 proto_tree_add_string(sdp_media_tree
, hf_media_format
, tvb
, offset
,
1133 tokenlen
, val_to_str_ext((uint32_t)strtoul((char*)media_format
, NULL
, 10), &rtp_payload_type_vals_ext
, "%u"));
1136 idx
= media_desc
->media
.pt_count
;
1137 media_desc
->media
.pt
[idx
] = (int32_t)strtol((char*)media_format
, NULL
, 10);
1138 DPRINT(("parsed media codec pt=%d", media_desc
->media
.pt
[idx
]));
1139 if (idx
< (SDP_MAX_RTP_PAYLOAD_TYPES
-1))
1140 media_desc
->media
.pt_count
++;
1143 proto_tree_add_item(sdp_media_tree
, hf_media_format
, tvb
, offset
,
1144 tokenlen
, ENC_UTF_8
);
1147 proto_tree_add_item(sdp_media_tree
, hf_media_format
, tvb
, offset
,
1148 tokenlen
, ENC_UTF_8
);
1151 } while (next_offset
!= -1);
1153 /* XXX Dissect traffic to "Port" as "Protocol"
1154 * Remember this Port/Protocol pair so we can tear it down again later
1155 * Actually, it's harder than that:
1156 * We need to find out the address of the other side first and it
1157 * looks like that info can be found in SIP headers only.
1163 ascii_bytes_to_tvb(tvbuff_t
*tvb
, packet_info
*pinfo
, char *msg
)
1166 uint8_t *buf
= convert_string_to_hex(msg
, &nbytes
);
1168 tvbuff_t
*bytes_tvb
;
1170 bytes_tvb
= tvb_new_child_real_data(tvb
, buf
, (unsigned)nbytes
, (unsigned)nbytes
);
1171 tvb_set_free_cb(bytes_tvb
, g_free
);
1172 add_new_data_source(pinfo
, bytes_tvb
, "ASCII bytes to tvb");
1178 /* Annex X Profiles and levels definition */
1179 static const value_string h263_profile_vals
[] =
1181 { 0, "Baseline Profile" },
1182 { 1, "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
1183 { 2, "Version 1 Backward-Compatibility Profile" },
1184 { 3, "Version 2 Interactive and Streaming Wireless Profile" },
1185 { 4, "Version 3 Interactive and Streaming Wireless Profile" },
1186 { 5, "Conversational High Compression Profile" },
1187 { 6, "Conversational Internet Profile" },
1188 { 7, "Conversational Interlace Profile" },
1189 { 8, "High Latency Profile" },
1194 /* RFC 4629 The level are described in table X.2 of H.263 annex X */
1195 static const value_string h263_level_vals
[] =
1197 { 10, "QCIF (176 x 144), 1 x 64Kb/s" },
1198 { 20, "CIF (352 x 288), 2 x 64Kb/s" },
1199 { 30, "CIF (352 x 288), 6 x 64Kb/s" },
1200 { 40, "CIF (352 x 288), 32 x 64Kb/s" },
1201 { 45, "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
1202 { 50, "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
1203 { 60, "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
1204 { 70, "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
1209 static const value_string h264_packetization_mode_vals
[] =
1211 { 0, "Single NAL mode" },
1212 { 1, "Non-interleaved mode" },
1213 { 2, "Interleaved mode" },
1218 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
1221 decode_sdp_fmtp(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, int offset
, int tokenlen
, uint8_t pt
, transport_info_t
*transport_info
, rtp_dyn_payload_t
*rtp_dyn_payload
) {
1224 uint8_t *field_name
;
1225 char *format_specific_parameter
;
1227 tvbuff_t
* volatile data_tvb
;
1229 const char *mime_type
= transport_info
->encoding_name
[pt
];
1230 end_offset
= offset
+ tokenlen
;
1233 proto_tree_add_debug(tree
, tvb
, offset
, tokenlen
, "Debug; Analysed string: '%s'",
1234 tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_ASCII
));
1237 /* Look for an '=' within this string - RFC 4855 suggets that parameters
1238 be "parameter=value" pairs. We'll store them in a hash map from the
1239 parameter name to the value, as well as dissect some of them here,
1240 depending on the media type.
1242 next_offset
= tvb_find_uint8(tvb
, offset
, tokenlen
, '=');
1243 if (next_offset
== -1)
1245 /* Some media types, like telephone-event and RED, don't have the
1246 * "parameter=value" syntax:
1247 * https://datatracker.ietf.org/doc/html/rfc4733
1248 * 2.4.1. "Relationship to SDP"
1249 * "The "events" media type parameter deviates from the convention
1250 * suggested in RFC 3555 because it omits the string "events=" before
1251 * the list of supported events."
1252 * https://www.iana.org/assignments/media-types/audio/RED
1253 * We'll handle them with the empty string as the parameter name.
1254 * The media types should know how to deal with that, if necessary.
1256 field_name
= wmem_strdup(pinfo
->pool
, "");
1258 /* Find the name of the parameter */
1259 tokenlen
= next_offset
- offset
;
1260 field_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
1263 proto_tree_add_debug(tree
, tvb
, offset
, tokenlen
, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type
, field_name
); */
1266 /* Move past the '=' */
1267 offset
= next_offset
+ 1;
1271 tokenlen
= end_offset
- offset
;
1272 format_specific_parameter
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
1274 if (rtp_dyn_payload
) {
1275 rtp_dyn_payload_add_fmtp(rtp_dyn_payload
, pt
,
1277 format_specific_parameter
);
1280 /* Dissect the MPEG4 profile-level-id parameter if present */
1281 if ((mime_type
!= NULL
) && (g_ascii_strcasecmp(mime_type
, "MP4V-ES") == 0)) {
1282 if (strcmp((char*)field_name
, "profile-level-id") == 0) {
1283 item
= proto_tree_add_uint(tree
, hf_sdp_fmtp_mpeg4_profile_level_id
, tvb
, offset
, tokenlen
,
1284 (uint32_t)strtol((char*)format_specific_parameter
, NULL
, 10));
1285 proto_item_set_generated(item
);
1286 } else if (strcmp((char*)field_name
, "config") == 0) {
1287 data_tvb
= ascii_bytes_to_tvb(tvb
, pinfo
, format_specific_parameter
);
1288 if (mp4ves_config_handle
&& data_tvb
) {
1289 call_dissector(mp4ves_config_handle
, data_tvb
, pinfo
, tree
);
1294 /* Dissect the H263-2000 profile parameter if present */
1295 if (((mime_type
!= NULL
) && (g_ascii_strcasecmp(mime_type
, "H263-2000") == 0)) ||
1296 ((mime_type
!= NULL
) && (g_ascii_strcasecmp(mime_type
, "H263-1998") == 0))) {
1297 if (strcmp((char*)field_name
, "profile") == 0) {
1298 item
= proto_tree_add_uint(tree
, hf_sdp_fmtp_h263_profile
, tvb
, offset
, tokenlen
,
1299 (uint32_t)strtol((char*)format_specific_parameter
, NULL
, 10));
1300 proto_item_set_generated(item
);
1301 } else if (strcmp((char*)field_name
, "level") == 0) {
1302 item
= proto_tree_add_uint(tree
, hf_sdp_fmtp_h263_level
, tvb
, offset
, tokenlen
,
1303 (uint32_t)strtol((char*)format_specific_parameter
, NULL
, 10));
1304 proto_item_set_generated(item
);
1309 /* Dissect the H264 profile-level-id parameter
1311 * A base16 [6] (hexadecimal) representation of
1312 * the following three bytes in the sequence
1313 * parameter set NAL unit specified in [1]: 1)
1314 * profile_idc, 2) a byte herein referred to as
1315 * profile-iop, composed of the values of
1316 * constraint_set0_flag, constraint_set1_flag,
1317 * constraint_set2_flag, and reserved_zero_5bits
1318 * in bit-significance order, starting from the
1319 * most significant bit, and 3) level_idc.
1321 if ((mime_type
!= NULL
) && ((g_ascii_strcasecmp(mime_type
, "H264") == 0) || (g_ascii_strcasecmp(mime_type
, "H264-SVC") == 0))) {
1322 if (strcmp(field_name
, "profile-level-id") == 0) {
1325 data_tvb
= ascii_bytes_to_tvb(tvb
, pinfo
, format_specific_parameter
);
1327 proto_tree_add_expert_format(tree
, pinfo
, &ei_sdp_invalid_conversion
, tvb
, offset
, tokenlen
, "Could not convert '%s' to 3 bytes", format_specific_parameter
);
1330 length
= tvb_reported_length(data_tvb
);
1332 if (h264_handle
&& data_tvb
) {
1333 dissect_h264_profile(data_tvb
, pinfo
, tree
);
1336 item
= proto_tree_add_expert_format(tree
, pinfo
, &ei_sdp_invalid_conversion
, tvb
, offset
, tokenlen
, "Incorrectly coded, must be three bytes");
1337 proto_item_set_generated(item
);
1339 } else if (strcmp(field_name
, "packetization-mode") == 0) {
1340 item
= proto_tree_add_uint(tree
, hf_sdp_h264_packetization_mode
, tvb
, offset
, tokenlen
,
1341 (uint32_t)strtol((char*)format_specific_parameter
, NULL
, 10));
1342 proto_item_set_generated(item
);
1343 } else if (strcmp(field_name
, "sprop-parameter-sets") == 0) {
1344 /* The value of the parameter is the
1345 base64 [6] representation of the initial
1346 parameter set NAL units as specified in
1347 sections 7.3.2.1 and 7.3.2.2 of [1]. The
1348 parameter sets are conveyed in decoding order,
1349 and no framing of the parameter set NAL units
1350 takes place. A comma is used to separate any
1351 pair of parameter sets in the list.
1353 const uint8_t *data_p
= NULL
;
1356 comma_offset
= tvb_find_uint8(tvb
, offset
, -1, ',');
1357 if (comma_offset
!= -1) {
1358 tokenlen
= comma_offset
- offset
;
1360 tokenlen
= end_offset
- offset
;
1363 proto_tree_add_item_ret_string(tree
, hf_sdp_nal_unit_1_string
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &data_p
);
1365 data_tvb
= base64_to_tvb(tvb
, data_p
);
1366 add_new_data_source(pinfo
, data_tvb
, "h264 prop-parameter-sets");
1368 if (h264_handle
&& data_tvb
) {
1370 dissect_h264_nal_unit(data_tvb
, pinfo
, tree
);
1372 CATCH_NONFATAL_ERRORS
{
1373 show_exception(tvb
, pinfo
, tree
, EXCEPT_CODE
, GET_MESSAGE
);
1376 if (comma_offset
!= -1) {
1377 /* Second NAL unit */
1378 offset
= comma_offset
+1;
1379 tokenlen
= end_offset
- offset
;
1380 proto_tree_add_item_ret_string(tree
, hf_sdp_nal_unit_2_string
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &data_p
);
1381 data_tvb
= base64_to_tvb(tvb
, data_p
);
1382 add_new_data_source(pinfo
, data_tvb
, "h264 prop-parameter-sets 2");
1383 dissect_h264_nal_unit(data_tvb
, pinfo
, tree
);
1392 else if ((mime_type
!= NULL
) && (g_ascii_strcasecmp(mime_type
, "H265") == 0)) {
1393 if (strcmp(field_name
, "sprop-vps") == 0 || strcmp(field_name
, "sprop-sps") == 0 || strcmp(field_name
, "sprop-pps") == 0) {
1395 data_tvb
= base64_to_tvb(tvb
, format_specific_parameter
);
1396 add_new_data_source(pinfo
, data_tvb
, field_name
);
1397 if (h265_handle
&& data_tvb
) {
1398 dissect_h265_format_specific_parameter(tree
, data_tvb
, pinfo
);
1405 static const string_string ice_candidate_types
[] = {
1406 { "host", "Host candidate" },
1407 { "srflx", "Server reflexive candidate" },
1408 { "prflx", "Peer reflexive candidate" },
1409 { "relay", "Relayed candidate" },
1414 dissect_sdp_media_attribute_candidate(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
)
1416 /* RFC 5245 (ICE): "The candidate attribute is a media-level attribute
1417 * only. It contains a transport address for a candidate that can be
1418 * used for connectivity checks."
1419 * https://tools.ietf.org/html/rfc5245#section-15.1
1421 * candidate-attribute = "candidate" ":" foundation SP component-id SP
1424 * connection-address SP ;from RFC 4566
1425 * port ;port from RFC 4566
1429 * *(SP extension-att-name SP
1430 * extension-att-value)
1432 * Example: "candidate:0 1 UDP 2122252543 10.9.0.2 60299 typ host"
1435 int next_offset
, tokenlen
;
1436 const uint8_t *candidate_type
;
1438 /* foundation: between 1 and 32 "ICE chars" (ALPHA / DIGIT / "+" / "/") */
1439 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1442 proto_tree_add_item(tree
, hf_ice_candidate_foundation
,
1443 tvb
, offset
, tokenlen
, ENC_ASCII
);
1444 offset
= next_offset
+ 1;
1446 /* component-id: integer between 1 and 256.
1447 * For RTP, 1 MUST be RTP and 2 MUST be RTCP (RFC 5245) */
1448 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1451 proto_tree_add_item(tree
, hf_ice_candidate_componentid
,
1452 tvb
, offset
, tokenlen
, ENC_ASCII
);
1453 offset
= next_offset
+ 1;
1455 /* transport: "UDP", etc. */
1456 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1459 proto_tree_add_item(tree
, hf_ice_candidate_transport
,
1460 tvb
, offset
, tokenlen
, ENC_ASCII
);
1461 offset
= next_offset
+ 1;
1463 /* priority: integer between 1 and 2^31-1 */
1464 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1467 proto_tree_add_item(tree
, hf_ice_candidate_priority
,
1468 tvb
, offset
, tokenlen
, ENC_ASCII
);
1469 offset
= next_offset
+ 1;
1471 /* connection-address: IPv4, IPv6 address or FQDN. */
1472 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1475 proto_tree_add_item(tree
, hf_ice_candidate_address
,
1476 tvb
, offset
, tokenlen
, ENC_ASCII
);
1477 offset
= next_offset
+ 1;
1480 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1483 proto_tree_add_item(tree
, hf_ice_candidate_port
,
1484 tvb
, offset
, tokenlen
, ENC_ASCII
);
1485 offset
= next_offset
+ 1;
1487 /* cand-type: type of candidate (where it learned the candidate)
1488 * Check for "typ " in "typ host" and skip it. */
1489 if (tvb_strneql(tvb
, offset
, "typ ", 4))
1492 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1495 pi
= proto_tree_add_item_ret_string(tree
, hf_ice_candidate_type
,
1496 tvb
, offset
, tokenlen
, ENC_ASCII
|ENC_NA
,
1497 pinfo
->pool
, &candidate_type
);
1498 if ((candidate_type
= try_str_to_str(candidate_type
, ice_candidate_types
))) {
1499 proto_item_append_text(pi
, " (%s)", candidate_type
);
1501 /* offset = next_offset + 1; */
1503 /* Ignored: [rel-addr] [rel-port] *(extension-att-name extension-att-value) */
1510 #define SDP_RTPMAP 1
1513 #define SDP_H248_ITEM 4
1514 #define SDP_CRYPTO 5
1515 #define SDP_SPRTMAP 6
1516 #define SDP_CANDIDATE 7
1517 #define SDP_ED137_TYPE 8
1518 #define SDP_ED137_TXRXMODE 9
1519 #define SDP_ED137_FID 10
1521 #define SDP_RTCP_MUX 12
1523 static const sdp_names_t sdp_media_attribute_names
[] = {
1524 { "Unknown-name"}, /* 0 Pad so that the real headers start at index 1 */
1525 { "rtpmap"}, /* 1 */
1528 { "h248item"}, /* 4 */
1529 { "crypto"}, /* 5 */
1531 { "candidate" }, /* 7 */
1533 { "txrxmode" }, /* 9 */
1535 { "rtcp" }, /* 11 */
1536 { "rtcp-mux" }, /* 12 */
1539 static int find_sdp_media_attribute_names(tvbuff_t
*tvb
, int offset
, unsigned len
)
1543 for (i
= 1; i
< array_length(sdp_media_attribute_names
); i
++) {
1544 if ((len
== strlen(sdp_media_attribute_names
[i
].name
)) &&
1545 (tvb_strncaseeql(tvb
, offset
, sdp_media_attribute_names
[i
].name
, len
) == 0))
1552 /* A few protocols give the fmtp parameter as a string instead of a
1553 * numeric payload type, list them here (lower case for comparison).
1555 static const string_string media_format_str_types
[] = {
1556 /* ETSI TS 102 472, ETSI TS 102 592 */
1557 { "ipdc-kmm", "IP Datacast Key Management Message"},
1558 { "ipdc-ksm", "IP Datacast Key Stream Message"},
1559 /* ETSI TS 124 380 */
1560 { "mcptt", "Mission Critical Push To Talk"},
1561 /* ETSI TS 124 581 */
1562 { "mcvideo", "Mission Critical Video"},
1563 /* OMA PoC Control Plane */
1564 { "tbcp", "Talk Burst Control Protocol"},
1569 dissect_sdp_media_attribute_rtpmap(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
, int length
,
1570 transport_info_t
*transport_info
, session_info_t
*session_info
,
1571 media_description_t
*media_desc
, int offset
)
1573 int next_offset
, tokenlen
;
1574 const uint8_t *payload_type
;
1578 /* RFC 8866 6.6 rtpmap
1580 rtpmap-value = payload-type SP encoding-name
1581 "/" clock-rate [ "/" encoding-params ]
1582 payload-type = zero-based-integer
1583 encoding-name = token
1584 clock-rate = integer
1585 encoding-params = channels
1588 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ' ');
1590 if (next_offset
== -1)
1593 tokenlen
= next_offset
- offset
;
1595 proto_tree_add_item_ret_string(tree
, hf_media_format
, tvb
,
1596 offset
, tokenlen
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, &payload_type
);
1598 offset
= next_offset
+ 1;
1600 next_offset
= tvb_find_uint8(tvb
, offset
, -1, '/');
1602 if (next_offset
== -1) {
1606 tokenlen
= next_offset
- offset
;
1608 proto_tree_add_item(tree
, hf_media_encoding_name
, tvb
,
1609 offset
, tokenlen
, ENC_UTF_8
);
1611 if (!ws_strtou8(payload_type
, NULL
, &pt
) || pt
>= SDP_NO_OF_PT
) {
1612 return; /* Invalid */
1615 /* String is file scope allocated because transport_info is connection related */
1616 transport_info
->encoding_name
[pt
] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
);
1618 offset
= next_offset
+ 1;
1620 next_offset
= tvb_find_uint8(tvb
, offset
, length
- offset
, '/');
1621 if (next_offset
== -1) {
1622 next_offset
= length
;
1625 tokenlen
= next_offset
- offset
;
1626 pi
= proto_tree_add_item(tree
, hf_media_sample_rate
, tvb
,
1627 offset
, tokenlen
, ENC_UTF_8
);
1628 transport_info
->sample_rate
[pt
] = 0;
1629 if (!ws_strtou32(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
),
1630 NULL
, &transport_info
->sample_rate
[pt
])) {
1631 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_sample_rate
);
1632 } else if (!strcmp(transport_info
->encoding_name
[pt
], "G722")) {
1633 // The reported sampling rate is 8000, but the actual value is
1634 // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2
1635 proto_item_append_text(pi
, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)");
1638 transport_info
->channels
[pt
] = 1;
1639 if (media_desc
&& media_desc
->media_types
& RTP_MEDIA_AUDIO
) {
1640 if (next_offset
< length
) {
1641 offset
= next_offset
+ 1;
1642 tokenlen
= length
- offset
;
1643 pi
= proto_tree_add_item(tree
, hf_media_channels
, tvb
,
1644 offset
, tokenlen
, ENC_UTF_8
);
1645 if (!ws_strtou32(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
),
1646 NULL
, &transport_info
->channels
[pt
])) {
1647 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_channels
);
1651 /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1654 a=rtpmap:101 G726-32/8000
1655 m=audio 49170 RTP/AVP 0 97
1656 a=rtpmap:97 telephone-event/8000
1657 m=audio 49172 RTP/AVP 97 101
1658 a=rtpmap:97 G726-24/8000
1660 The Media attributes ("a="s) after the "m=" only apply for that "m=".
1661 If there is an "a=" before the first "m=", that attribute applies for
1662 all the session (all the "m="s).
1666 /* If this "a=" appear before any "m=", we add it to the session
1667 * info, these will be added later to all media (via
1668 * sdp_new_media_description).
1670 * NOTE: This should not happen, because rtpmap is Usage Level: media
1671 * (RFC 8866 6.6, also RFC 4566 6, and heavily implied by RFC 2327)
1673 rtp_dyn_payload_insert(session_info
->rtp_dyn_payload
,
1675 transport_info
->encoding_name
[pt
],
1676 transport_info
->sample_rate
[pt
],
1677 transport_info
->channels
[pt
]);
1678 } else if (media_desc
) {
1679 /* if the "a=" is after an "m=", only apply to this "m=" */
1680 rtp_dyn_payload_insert(media_desc
->media
.rtp_dyn_payload
,
1682 transport_info
->encoding_name
[pt
],
1683 transport_info
->sample_rate
[pt
],
1684 transport_info
->channels
[pt
]);
1689 dissect_sdp_media_attribute_fmtp(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
,
1690 transport_info_t
*transport_info
, session_info_t
*session_info
,
1691 media_description_t
*media_desc
, int offset
)
1693 int next_offset
, tokenlen
;
1694 proto_item
*fmtp_item
, *media_format_item
;
1695 const uint8_t *payload_type
;
1696 const uint8_t *media_format_str
;
1697 proto_tree
*fmtp_tree
;
1698 bool has_more_pars
= true;
1699 /* Reading the Format parameter(fmtp) */
1700 uint8_t media_format
;
1702 /* Skip leading space, if any */
1703 offset
= tvb_skip_wsp(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
));
1704 /* Media format extends to the next space */
1705 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ' ');
1707 if (next_offset
== -1)
1710 tokenlen
= next_offset
- offset
;
1712 media_format_item
= proto_tree_add_item_ret_string(tree
, hf_media_format
, tvb
,
1713 offset
, tokenlen
, ENC_UTF_8
| ENC_NA
, pinfo
->pool
, &payload_type
);
1715 /* Append encoding name to format if known */
1716 payload_type
= wmem_ascii_strdown(pinfo
->pool
, payload_type
, -1);
1718 if ((media_format_str
= try_str_to_str(payload_type
, media_format_str_types
))) {
1720 proto_item_append_text(media_format_item
, " [%s]",
1722 } else if (ws_strtou8(payload_type
, NULL
, &media_format
) && media_format
< SDP_NO_OF_PT
) {
1724 proto_item_append_text(media_format_item
, " [%s]",
1725 transport_info
->encoding_name
[media_format
]);
1728 expert_add_info(pinfo
, media_format_item
, &ei_sdp_invalid_media_format
);
1734 payload_type
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_ASCII
);
1736 /* Move offset past the payload type */
1737 offset
= next_offset
+ 1;
1739 while (has_more_pars
== true) {
1740 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ';');
1741 offset
= tvb_skip_wsp(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
));
1743 if (next_offset
== -1) {
1744 has_more_pars
= false;
1745 next_offset
= tvb_captured_length(tvb
);
1748 /* There are at least 2 - add the first parameter */
1749 tokenlen
= next_offset
- offset
;
1750 fmtp_item
= proto_tree_add_item(tree
, hf_media_format_specific_parameter
, tvb
,
1751 offset
, tokenlen
, ENC_UTF_8
);
1753 fmtp_tree
= proto_item_add_subtree(fmtp_item
, ett_sdp_fmtp
);
1755 rtp_dyn_payload_t
*rtp_dyn_payload
= NULL
;
1757 rtp_dyn_payload
= session_info
->rtp_dyn_payload
;
1758 } else if (media_desc
) {
1759 rtp_dyn_payload
= media_desc
->media
.rtp_dyn_payload
;
1761 decode_sdp_fmtp(fmtp_tree
, tvb
, pinfo
, offset
, tokenlen
,
1762 media_format
, transport_info
, rtp_dyn_payload
);
1764 /* Move offset past "; " and onto first char */
1765 offset
= next_offset
+ 1;
1770 dissect_sdp_media_attribute_path(packet_info
*pinfo
, tvbuff_t
*tvb
, uint8_t *attribute_value
,
1771 media_description_t
*media_desc
, const char *msrp_res
, int offset
)
1773 /* msrp attributes that contain address needed for conversation */
1775 * path = path-label ":" path-list
1776 * path-label = "path"
1777 * path-list= MSRP-URI *(SP MSRP-URI)
1778 * MSRP-URI = msrp-scheme "://" authority
1779 * ["/" session-id] ";" transport *( ";" URI-parameter)
1780 * ; authority as defined in RFC3986
1782 * msrp-scheme = "msrp" / "msrps"
1784 * The authority component is preceded by a double slash ("//") and is terminated by
1785 * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1786 * the end of the URI.
1789 /* Check for "msrp://" */
1790 if (strncmp((char*)attribute_value
, msrp_res
, strlen(msrp_res
)) == 0 && msrp_handle
&&
1791 media_desc
&& media_desc
->proto
== SDP_PROTO_MSRP
) {
1792 int address_offset
, port_offset
, port_end_offset
;
1794 /* Address starts here */
1795 address_offset
= offset
+ (int)strlen(msrp_res
);
1797 /* Port is after next ':' */
1798 port_offset
= tvb_find_uint8(tvb
, address_offset
, -1, ':');
1799 /* Check if port is present if not skipp */
1800 if (port_offset
!= -1) {
1801 /* Port ends with '/' */
1802 port_end_offset
= tvb_find_uint8(tvb
, port_offset
, -1, '/');
1803 if (port_end_offset
== -1) {
1804 /* No "/" look for the ";" */
1805 port_end_offset
= tvb_find_uint8(tvb
, port_offset
, -1, ';');
1807 /* Attempt to convert address */
1808 uint32_t msrp_ipaddr
;
1809 uint16_t msrp_port_number
;
1810 if (str_to_ip((char*)tvb_get_string_enc(pinfo
->pool
, tvb
, address_offset
, port_offset
-address_offset
, ENC_UTF_8
|ENC_NA
),
1812 /* Get port number */
1813 if (ws_strtou16(tvb_get_string_enc(pinfo
->pool
, tvb
, port_offset
+ 1,
1814 port_end_offset
- port_offset
- 1, ENC_UTF_8
|ENC_NA
), NULL
, &msrp_port_number
)) {
1815 /* Port and address are usable, store for later use in
1816 * complete_descriptions (overrides the "c=" address). */
1817 alloc_address_wmem(wmem_file_scope(), &media_desc
->media_attr
.msrp
.ipaddr
, AT_IPv4
, 4, &msrp_ipaddr
);
1818 media_desc
->media_attr
.msrp
.port_number
= msrp_port_number
;
1826 dissect_sdp_media_attribute_h248_item(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
,
1827 uint8_t *attribute_value
, const char *msrp_res
)
1829 const char *h324ext_h223lcparm
= "h324ext/h223lcparm";
1832 if (strncmp((char*)attribute_value
, h324ext_h223lcparm
, strlen(msrp_res
)) == 0) {
1833 /* A.5.1.3 H.223 Logical channel parameters
1834 * This property indicates the H.245
1835 * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1836 * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1837 * in ITU-T Rec. H.248.15 is used.
1839 * H.248.15 6 IANA considerations
1840 * The format of the Package attribute is as below:
1841 * a=h248item:<package name>/<property name> = <value>
1845 attribute_value
= strchr(attribute_value
, '=');
1846 if (!attribute_value
) {
1850 h245_tvb
= ascii_bytes_to_tvb(tvb
, pinfo
, ++attribute_value
);
1851 /* should go through a handle, however, the two h245 entry
1852 points are different, one is over tpkt and the other is raw
1855 asn1_ctx_init(&actx
, ASN1_ENC_PER
, true, pinfo
);
1856 dissect_h245_H223LogicalChannelParameters(h245_tvb
, 0, &actx
,
1857 tree
,hf_SDPh223LogicalChannelParameters
);
1863 dissect_sdp_media_attribute_crypto(proto_tree
*tree
, packet_info
*pinfo
, tvbuff_t
*tvb
,
1864 transport_info_t
*transport_info
, int offset
)
1866 /* https://tools.ietf.org/html/rfc4568
1867 * 9.1. Generic "Crypto" Attribute Grammar
1869 * The ABNF grammar for the crypto attribute is defined below:
1871 * "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
1872 * *(1*WSP session-param)
1875 * crypto-suite = 1*(ALPHA / DIGIT / "_")
1877 * key-params = key-param *(";" key-param)
1878 * key-param = key-method ":" key-info
1879 * key-method = "inline" / key-method-ext
1880 * key-method-ext = 1*(ALPHA / DIGIT / "_")
1881 * key-info = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
1882 * ; except semi-colon
1883 * session-param = 1*(VCHAR) ; visible (printing) characters
1885 * where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
1888 int next_offset
, tokenlen
;
1889 proto_tree
*parameter_item
;
1890 proto_item
*parameter_tree
;
1891 uint32_t crypto_tag
;
1892 bool crypto_tag_valid
;
1893 bool has_more_pars
= true;
1894 uint8_t master_key_length
= 0, master_salt_length
= 0;
1898 /* We are at the first colon */
1900 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1903 crypto_tag_valid
= ws_strtou32(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
,
1904 tokenlen
, ENC_UTF_8
|ENC_NA
), NULL
, &crypto_tag
);
1905 pi
= proto_tree_add_uint(tree
, hf_sdp_crypto_tag
, tvb
, offset
, tokenlen
, crypto_tag
);
1906 if (!crypto_tag_valid
)
1907 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_crypto_tag
);
1908 offset
= next_offset
+ 1;
1911 tokenlen
= find_next_token_in_line(tvb
, tree
, &offset
, &next_offset
);
1914 parameter_item
= proto_tree_add_item(tree
, hf_sdp_crypto_crypto_suite
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
1915 if (tvb_strncaseeql(tvb
, offset
, "AES_CM_128_HMAC_SHA1_80", tokenlen
) == 0) {
1917 /* XXX This may only work in simple cases */
1918 if (transport_info
->encryption_algorithm
== SRTP_ENC_ALG_NOT_SET
) {
1919 transport_info
->encryption_algorithm
= SRTP_ENC_ALG_AES_CM
;
1920 transport_info
->auth_algorithm
= SRTP_AUTH_ALG_HMAC_SHA1
;
1921 /* number of octets used for the Auth Tag in the RTP payload */
1922 transport_info
->auth_tag_len
= 10;
1924 master_key_length
= 16; /* 128 bits = 16 octets */
1925 master_salt_length
= 14; /* 112 bits = 14 octets */
1926 } else if (tvb_strncaseeql(tvb
, offset
, "AES_CM_128_HMAC_SHA1_32", tokenlen
) == 0) {
1927 /* XXX This may only work in simple cases */
1928 if (transport_info
->encryption_algorithm
== SRTP_ENC_ALG_NOT_SET
) {
1929 transport_info
->encryption_algorithm
= SRTP_ENC_ALG_AES_CM
;
1930 transport_info
->auth_algorithm
= SRTP_AUTH_ALG_HMAC_SHA1
;
1931 /* number of octets used for the Auth Tag in the RTP payload */
1932 transport_info
->auth_tag_len
= 4;
1934 master_key_length
= 16; /* 128 bits = 16 octets */
1935 master_salt_length
= 14; /* 112 bits = 14 octets */
1936 } else if (tvb_strncaseeql(tvb
, offset
, "F8_128_HMAC_SHA1_80", tokenlen
) == 0) {
1937 if (transport_info
->encryption_algorithm
== SRTP_ENC_ALG_NOT_SET
) {
1938 /* XXX This may only work in simple cases */
1939 transport_info
->encryption_algorithm
= SRTP_ENC_ALG_AES_F8
;
1940 transport_info
->auth_algorithm
= SRTP_AUTH_ALG_HMAC_SHA1
;
1941 /* number of octets used for the Auth Tag in the RTP payload */
1942 transport_info
->auth_tag_len
= 10;
1944 master_key_length
= 16; /* 128 bits = 16 octets */
1945 master_salt_length
= 14; /* 112 bits = 14 octets */
1947 offset
= next_offset
+ 1;
1950 while (has_more_pars
== true) {
1951 int param_end_offset
;
1952 tvbuff_t
*key_salt_tvb
;
1953 char *data_p
= NULL
;
1955 param_end_offset
= tvb_find_uint8(tvb
, offset
, -1, ';');
1956 if (param_end_offset
== -1) {
1957 has_more_pars
= false;
1958 param_end_offset
= tvb_captured_length(tvb
);
1960 /* key-method or key-method-ext */
1961 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
1962 if (next_offset
== -1) {
1963 expert_add_info(pinfo
, parameter_item
, &ei_sdp_invalid_key_param
);
1967 if (tvb_strncaseeql(tvb
, offset
, "inline", next_offset
-offset
) == 0) {
1968 parameter_tree
= proto_tree_add_subtree(tree
, tvb
, offset
,param_end_offset
-offset
,
1969 ett_sdp_crypto_key_parameters
, NULL
, "Key parameters");
1970 /* XXX only for SRTP? */
1971 /* srtp-key-info = key-salt ["|" lifetime] ["|" mki] */
1972 offset
= next_offset
+1;
1973 next_offset
= tvb_find_uint8(tvb
, offset
, -1, '|');
1974 if (next_offset
== -1) {
1975 tokenlen
= param_end_offset
- offset
;
1977 tokenlen
= next_offset
- offset
;
1979 data_p
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
, ENC_UTF_8
|ENC_NA
);
1980 key_salt_tvb
= base64_to_tvb(tvb
, data_p
);
1981 add_new_data_source(pinfo
, key_salt_tvb
, "Key_Salt_tvb");
1982 if (master_key_length
!= 0) {
1983 proto_tree_add_item(parameter_tree
, hf_sdp_key_and_salt
, tvb
, offset
, tokenlen
, ENC_NA
);
1984 proto_tree_add_item(parameter_tree
, hf_sdp_crypto_master_key
,
1985 key_salt_tvb
, 0, master_key_length
, ENC_NA
);
1986 proto_tree_add_item(parameter_tree
, hf_sdp_crypto_master_salt
,
1987 key_salt_tvb
, master_key_length
, master_salt_length
, ENC_NA
);
1989 proto_tree_add_item(parameter_tree
, hf_sdp_key_and_salt
, key_salt_tvb
, 0, -1, ENC_NA
);
1992 /* ["|" lifetime] ["|" mki] are optional */
1993 if (next_offset
!= -1) {
1994 offset
= next_offset
+ 1;
1995 next_offset
= tvb_find_uint8(tvb
, offset
, -1, '|');
1996 if (next_offset
== -1) {
1997 if (next_offset
< param_end_offset
){
1998 next_offset
= param_end_offset
;
2001 if (next_offset
!= -1) {
2002 /*lifetime = ["2^"] 1*(DIGIT) ; see section 6.1 for "2^" */
2003 tokenlen
= next_offset
- offset
;
2004 proto_tree_add_item(parameter_tree
, hf_sdp_crypto_lifetime
,
2005 tvb
, offset
, tokenlen
, ENC_UTF_8
);
2006 offset
= next_offset
+ 1;
2008 /* mki = mki-value ":" mki-length
2010 * mki-value = 1*DIGIT
2012 if (offset
>param_end_offset
) {
2015 next_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
2017 if (next_offset
!= -1) {
2018 tokenlen
= next_offset
- offset
;
2019 proto_tree_add_item(parameter_tree
, hf_sdp_crypto_mki
, tvb
, offset
, tokenlen
, ENC_UTF_8
);
2020 offset
= next_offset
+ 1;
2022 /* mki-length = 1*3DIGIT ; range 1..128. */
2023 next_offset
= param_end_offset
;
2024 tokenlen
= next_offset
- offset
;
2026 /* This will not work if more than one parameter */
2027 /* number of octets used for the MKI in the RTP payload */
2028 mki_len_valid
= ws_strtou32(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tokenlen
,
2029 ENC_UTF_8
|ENC_NA
), NULL
, &transport_info
->mki_len
);
2030 pi
= proto_tree_add_item(parameter_tree
, hf_sdp_crypto_mki_length
,
2031 tvb
, offset
, tokenlen
, ENC_UTF_8
);
2033 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_crypto_mki_length
);
2036 offset
= param_end_offset
;
2043 static void dissect_sdp_media_attribute(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_item
* ti
, int length
,
2044 transport_info_t
*transport_info
,
2045 session_info_t
*session_info
,
2046 media_description_t
*media_desc
,
2047 sdp_data_t
*sdp_data
)
2049 proto_tree
*sdp_media_attribute_tree
;
2051 int offset
, tokenlen
, colon_offset
;
2052 uint8_t *attribute_value
;
2053 int sdp_media_attrbute_code
;
2054 const char *msrp_res
= "msrp://";
2058 /* Create attribute tree */
2059 sdp_media_attribute_tree
= proto_item_add_subtree(ti
,
2060 ett_sdp_media_attribute
);
2061 /* Find end of field */
2062 colon_offset
= tvb_find_uint8(tvb
, offset
, -1, ':');
2064 if (colon_offset
== -1)
2067 /* Attribute field name is token before ':' */
2068 tokenlen
= colon_offset
- offset
;
2069 pi
= proto_tree_add_item(sdp_media_attribute_tree
,
2070 hf_media_attribute_field
,
2071 tvb
, offset
, tokenlen
, ENC_UTF_8
);
2072 /*??field_name = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);*/
2073 sdp_media_attrbute_code
= find_sdp_media_attribute_names(tvb
, offset
, tokenlen
);
2076 offset
= colon_offset
+ 1;
2077 /* skip leading wsp */
2078 offset
= tvb_skip_wsp(tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
));
2080 /* Value is the remainder of the line */
2081 if (tvb_captured_length_remaining(tvb
, offset
) > 0)
2082 attribute_value
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, tvb_captured_length_remaining(tvb
, offset
), ENC_UTF_8
|ENC_NA
);
2085 expert_add_info(pinfo
, pi
, &ei_sdp_invalid_line_fields
);
2089 /*********************************************/
2090 /* Special parsing for some field name types */
2092 switch (sdp_media_attrbute_code
) {
2094 /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
2095 dissect_sdp_media_attribute_rtpmap(sdp_media_attribute_tree
, pinfo
, tvb
, length
, transport_info
,
2096 session_info
, media_desc
, offset
);
2099 dissect_sdp_media_attribute_fmtp(sdp_media_attribute_tree
, pinfo
, tvb
, transport_info
,
2100 session_info
, media_desc
, offset
);
2103 dissect_sdp_media_attribute_path(pinfo
, tvb
, attribute_value
, media_desc
, msrp_res
, offset
);
2106 /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
2107 dissect_sdp_media_attribute_h248_item(sdp_media_attribute_tree
, pinfo
, tvb
, attribute_value
, msrp_res
);
2110 dissect_sdp_media_attribute_crypto(sdp_media_attribute_tree
, pinfo
, tvb
, transport_info
, offset
);
2113 dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree
, pinfo
, tvb
, offset
);
2115 case SDP_ED137_TYPE
:
2116 /* Remember the value and add it to tree */
2117 sdp_data
->ed137_type
= attribute_value
;
2118 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2119 tvb
, offset
, -1, ENC_UTF_8
);
2121 case SDP_ED137_TXRXMODE
:
2122 /* Remember the value and add it to tree */
2123 sdp_data
->ed137_txrxmode
= attribute_value
;
2124 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2125 tvb
, offset
, -1, ENC_UTF_8
);
2128 /* Remember the value and add it to tree */
2129 sdp_data
->ed137_fid
= attribute_value
;
2130 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2131 tvb
, offset
, -1, ENC_UTF_8
);
2135 if (!ws_strtou16(attribute_value
, NULL
, &media_desc
->control_port
))
2136 media_desc
->control_port
= 0; /* Just use default, if not legal port */
2138 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2139 tvb
, offset
, -1, ENC_UTF_8
);
2143 media_desc
->control_port
= media_desc
->media_port
;
2145 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2146 tvb
, offset
, -1, ENC_UTF_8
);
2149 /* No special treatment for values of this attribute type, just add as one item. */
2150 proto_tree_add_item(sdp_media_attribute_tree
, hf_media_attribute_value
,
2151 tvb
, offset
, -1, ENC_UTF_8
);
2157 call_sdp_subdissector(tvbuff_t
*tvb
, packet_info
*pinfo
, int hf
, proto_tree
* ti
, int length
,
2158 transport_info_t
*transport_info
,
2159 session_info_t
*session_info
,
2160 media_description_t
*media_desc
,
2161 sdp_data_t
*sdp_data
)
2163 if (hf
== hf_owner
) {
2164 dissect_sdp_owner(tvb
, ti
);
2165 } else if (hf
== hf_connection_info
) {
2166 dissect_sdp_connection_info(pinfo
, tvb
, ti
, session_info
, media_desc
);
2167 } else if (hf
== hf_bandwidth
) {
2168 dissect_sdp_bandwidth(tvb
, ti
);
2169 } else if (hf
== hf_time
) {
2170 dissect_sdp_time(tvb
, ti
);
2171 } else if (hf
== hf_repeat_time
) {
2172 dissect_sdp_repeat_time(tvb
, ti
);
2173 } else if (hf
== hf_timezone
) {
2174 dissect_sdp_timezone(tvb
, ti
);
2175 } else if (hf
== hf_encryption_key
) {
2176 dissect_sdp_encryption_key(tvb
, ti
);
2177 } else if (hf
== hf_session_attribute
) {
2178 dissect_sdp_session_attribute(tvb
, pinfo
, ti
);
2179 } else if (hf
== hf_media
) {
2180 dissect_sdp_media(tvb
, pinfo
, ti
, media_desc
);
2181 } else if (hf
== hf_media_attribute
) {
2182 dissect_sdp_media_attribute(tvb
, pinfo
, ti
, length
, transport_info
, session_info
, media_desc
, sdp_data
);
2187 * Post-processes the media descriptions after parsing it from the tvb. This
2188 * performs processing that can only be done when the full media description is
2189 * parsed (since otherwise the order of attributes could influence the result).
2190 * Must be called before applying the SDP with apply_sdp_transport.
2191 * It will remove media streams when the port number in the answer is zero.
2193 * If the currently processed SDP is an Answer to a known previous Offer, then
2194 * answer_offset is non-zero.
2197 complete_descriptions(transport_info_t
*transport_info
, unsigned answer_offset
)
2199 unsigned media_count
= wmem_array_get_count(transport_info
->media_descriptions
);
2200 media_description_t
*media_descs
= (media_description_t
*)wmem_array_get_raw(transport_info
->media_descriptions
);
2201 media_description_t
*bundle_media_desc
= NULL
;
2203 DPRINT(("complete_descriptions called with answer_offset=%d media_count=%d",
2204 answer_offset
, media_count
));
2206 for (unsigned i
= answer_offset
; i
< media_count
&& !bundle_media_desc
; i
++) {
2207 for (unsigned j
= i
+1; j
< media_count
&& !bundle_media_desc
; j
++) {
2208 if (media_descs
[i
].media_port
== media_descs
[j
].media_port
)
2209 bundle_media_desc
= &media_descs
[i
];
2213 if (bundle_media_desc
) {
2214 /* We have "bundling" of media, so now combine all the media bit masks
2215 and merge the rtp_dyn_payload so that the first media description
2216 has all the data for every media desciption. */
2217 for (unsigned i
= answer_offset
; i
< media_count
; i
++) {
2218 media_description_t
*media_desc
= &media_descs
[i
];
2220 if (bundle_media_desc
->media_port
== media_desc
->media_port
) {
2221 media_desc
->bundled
= true;
2223 if (media_desc
!= bundle_media_desc
) {
2224 bundle_media_desc
->media_types
|= media_desc
->media_types
;
2225 for (unsigned pt
= 0; pt
< 128; ++pt
) {
2226 const char * encoding_name
;
2229 wmem_map_t
*fmtp_map
;
2230 if (rtp_dyn_payload_get_full(media_desc
->media
.rtp_dyn_payload
,
2231 pt
, &encoding_name
, &sample_rate
, &channels
, &fmtp_map
))
2232 rtp_dyn_payload_insert_full(bundle_media_desc
->media
.rtp_dyn_payload
,
2233 pt
, encoding_name
, sample_rate
, channels
, fmtp_map
);
2240 for (unsigned i
= answer_offset
; i
< media_count
; i
++) {
2241 media_description_t
*media_desc
= &media_descs
[i
];
2243 if (media_desc
->control_port
== 0)
2244 media_desc
->control_port
= media_desc
->media_port
+ 1;
2246 if (media_desc
->control_port
== 0)
2247 media_desc
->control_port
= media_desc
->media_port
+ 1;
2249 /* If this is an answer to a previous offer... */
2250 if (answer_offset
> 0) {
2251 /* A zero port removes the media stream (RFC 3264, Section 8.2) */
2252 if (media_desc
->media_port
== 0) {
2253 DPRINT(("disabling media_port=%d, for index=%d",
2254 media_descs
[i
- answer_offset
].media_port
,
2255 i
- answer_offset
));
2256 media_descs
[i
- answer_offset
].media_port
= 0;
2260 /* MSRP uses addresses discovered in attribute
2261 rather than connection information of media session line */
2262 if (media_desc
->proto
== SDP_PROTO_MSRP
&& msrp_handle
&&
2263 media_desc
->media_attr
.msrp
.ipaddr
.type
!= AT_NONE
) {
2264 /* clear old address and set new address and port. */
2265 free_address_wmem(wmem_file_scope(), &media_desc
->conn_addr
);
2266 copy_address_shallow(&media_desc
->conn_addr
,
2267 &media_desc
->media_attr
.msrp
.ipaddr
);
2268 media_desc
->media_port
= media_desc
->media_attr
.msrp
.port_number
;
2274 * Given is a structure containing the parsed result from the SDP (including
2275 * protocol type (RTP, SRTP, T38, etc.), media info (payload type, etc.) and
2276 * connection info (address, port). Register the addresss+port such that the
2277 * protocol will be invoked for this tuple with the media information.
2279 * For use with SDP using the Offer/Answer model (such as SIP with INVITE and
2281 * XXX what about RTSP where the SDP merely provides media info, without
2282 * actually establishing connections (Bug 5208).
2284 * The passed transport information is modified: 'set_rtp' is set when the media
2285 * is assigned to a conversation. Note that the unassigned media (payload types)
2286 * are not freed, this is the responsibility of the caller.
2289 apply_sdp_transport(packet_info
*pinfo
, transport_info_t
*transport_info
, int request_frame
, sdp_setup_info_t
*setup_info
)
2291 int establish_frame
= 0;
2292 wmem_array_t
*setup_info_list
;
2294 struct srtp_info
*srtp_info
= NULL
;
2296 if (!global_sdp_establish_conversation
) {
2297 /* Do not register with other dissectors when this pref is disabled. */
2301 /* If no request_frame number has been found use this frame's number */
2302 if (request_frame
== 0) {
2303 establish_frame
= pinfo
->num
;
2305 establish_frame
= request_frame
;
2308 bool bundled_media_set
= false;
2310 for (unsigned i
= 0; i
< wmem_array_get_count(transport_info
->media_descriptions
); i
++) {
2311 media_description_t
*media_desc
=
2312 (media_description_t
*)wmem_array_index(transport_info
->media_descriptions
, i
);
2313 uint32_t current_rtp_port
= 0;
2315 /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2316 if ((media_desc
->media_port
!= 0) &&
2317 !media_desc
->media
.set_rtp
&&
2318 (media_desc
->proto
== SDP_PROTO_RTP
||
2319 media_desc
->proto
== SDP_PROTO_SRTP
) &&
2320 (media_desc
->conn_addr
.type
== AT_IPv4
||
2321 media_desc
->conn_addr
.type
== AT_IPv6
)) {
2323 media_desc
->media
.set_rtp
= true;
2325 if (media_desc
->bundled
) {
2326 if (bundled_media_set
)
2328 bundled_media_set
= true;
2331 if (media_desc
->proto
== SDP_PROTO_SRTP
) {
2332 srtp_info
= wmem_new0(wmem_file_scope(), struct srtp_info
);
2333 if (transport_info
->encryption_algorithm
!= SRTP_ENC_ALG_NOT_SET
) {
2334 srtp_info
->encryption_algorithm
= transport_info
->encryption_algorithm
;
2335 srtp_info
->auth_algorithm
= transport_info
->auth_algorithm
;
2336 srtp_info
->mki_len
= transport_info
->mki_len
;
2337 srtp_info
->auth_tag_len
= transport_info
->auth_tag_len
;
2340 DPRINT(("calling srtp_add_address, channel=%d, media_port=%d",
2341 i
, media_desc
->media_port
));
2343 /* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number,
2344 because that's where the RTP flow started, and thus conversation needs to check against */
2345 srtp_add_address(pinfo
, PT_UDP
, &media_desc
->conn_addr
, media_desc
->media_port
, 0, "SDP", establish_frame
,
2346 media_desc
->media_types
,
2347 media_desc
->media
.rtp_dyn_payload
, srtp_info
,
2350 } else if (setup_info
&& setup_info
->is_osmux
) {
2351 DPRINT(("calling osmux_add_address, channel=%d, media_port=%d",
2352 i
, media_desc
->media_port
));
2354 osmux_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->media_port
, 0, establish_frame
);
2357 DPRINT(("calling rtp_add_address, channel=%d, media_port=%d",
2358 i
, media_desc
->media_port
));
2360 srtp_add_address(pinfo
, PT_UDP
, &media_desc
->conn_addr
, media_desc
->media_port
, 0, "SDP", establish_frame
,
2361 media_desc
->media_types
,
2362 media_desc
->media
.rtp_dyn_payload
, NULL
, setup_info
);
2365 /* SPRT might use the same port... */
2366 current_rtp_port
= media_desc
->media_port
;
2368 if (rtcp_handle
&& media_desc
->media_port
!= media_desc
->control_port
) {
2369 if (media_desc
->proto
== SDP_PROTO_SRTP
) {
2370 DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
2371 i
, media_desc
->control_port
));
2373 srtcp_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->control_port
, 0, "SDP", establish_frame
, srtp_info
);
2375 } else if (!setup_info
|| !setup_info
->is_osmux
) {
2376 DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
2377 i
, media_desc
->control_port
));
2379 rtcp_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->control_port
, 0, "SDP", establish_frame
);
2385 /* add SPRT conversation */
2386 if (media_desc
->proto
== SDP_PROTO_SPRT
&&
2387 (media_desc
->conn_addr
.type
== AT_IPv4
||
2388 media_desc
->conn_addr
.type
== AT_IPv6
) &&
2391 if (media_desc
->media_port
== 0 && current_rtp_port
) {
2392 sprt_add_address(pinfo
, &media_desc
->conn_addr
, current_rtp_port
,
2393 0, "SDP", pinfo
->num
); /* will use same port as RTP */
2395 sprt_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->media_port
, 0, "SDP", pinfo
->num
);
2399 /* Add t38 conversation, if available and only if no rtp */
2400 if ((media_desc
->media_port
!= 0) &&
2401 !media_desc
->media
.set_rtp
&&
2402 media_desc
->proto
== SDP_PROTO_T38
&&
2403 media_desc
->conn_addr
.type
== AT_IPv4
) {
2404 t38_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->media_port
, 0, "SDP", pinfo
->num
);
2407 /* Add MSRP conversation. Uses addresses discovered in attribute
2408 rather than connection information of media session line
2409 (already handled in media conversion) */
2410 if (media_desc
->proto
== SDP_PROTO_MSRP
&& msrp_handle
) {
2411 msrp_add_address(pinfo
, &media_desc
->conn_addr
, media_desc
->media_port
, "SDP", pinfo
->num
);
2414 /* Add BFCP conversation. Uses addresses discovered in attribute
2415 rather than connection information of media session line
2416 (already handled in media conversion) */
2417 if (media_desc
->proto
== SDP_PROTO_BFCP
&& bfcp_handle
) {
2418 bfcp_add_address(pinfo
, PT_UDP
, &media_desc
->conn_addr
, media_desc
->media_port
, "SDP", establish_frame
);
2420 } /* end of loop through all media descriptions. */
2422 /* Copy the list of setup info of calls with the same RTP information
2423 * to the transport info, so that we have it when dissecting the
2425 * XXX - There can be multiple media descriptions, and while this SDP's
2426 * setup info is on all of them, some other SDP might have some but not
2427 * all media descriptions, so the arrays of setup infos might be different.
2428 * They should be consolidated as with rtp_add_setup_info_if_no_duplicate()
2429 * in packet-rtp.c, or stored with each media descriptor.
2431 setup_info_list
= p_get_proto_data(pinfo
->pool
, pinfo
, proto_sdp
, 0);
2432 if (setup_info_list
) {
2433 transport_info
->sdp_setup_info_list
= setup_info_list
;
2438 setup_sdp_transport(tvbuff_t
*tvb
, packet_info
*pinfo
, enum sdp_exchange_type exchange_type
,
2439 int request_frame
, const bool delay
, sdp_setup_info_t
*setup_info
)
2441 int offset
= 0, next_offset
, n
;
2443 bool in_media_description
= false;
2444 unsigned char type
, delim
;
2445 const int tokenoffset
= 2;
2447 int start_transport_info_count
= 0;
2448 transport_info_t
* transport_info
= NULL
;
2449 media_description_t
*media_desc
= NULL
;
2450 session_info_t session_info
;
2451 sdp_data_t sdp_data
;
2453 DPRINT2(("-------------------- setup_sdp_transport -------------------"));
2455 /* Only do this once during first pass */
2456 if (pinfo
->fd
->visited
) {
2457 DPRINT(("already visited"));
2461 memset(&sdp_data
, 0, sizeof(sdp_data
));
2463 if (request_frame
!= 0)
2464 transport_info
= (transport_info_t
*)wmem_tree_lookup32( sdp_transport_reqs
, request_frame
);
2465 if (transport_info
== NULL
) {
2466 transport_info
= wmem_new0(wmem_file_scope(), transport_info_t
);
2467 transport_info
->media_descriptions
= wmem_array_new(wmem_file_scope(), sizeof(media_description_t
));
2469 for (n
= 0; n
< SDP_NO_OF_PT
; n
++) {
2470 /* String is file scope allocated because transport_info is connection related */
2471 transport_info
->encoding_name
[n
] = wmem_strdup(wmem_file_scope(), UNKNOWN_ENCODING
);
2474 if (request_frame
!= 0)
2475 wmem_tree_insert32(sdp_transport_reqs
, request_frame
, (void *)transport_info
);
2477 #ifdef DEBUG_CONVERSATION
2479 DPRINT(("found previous transport_info:"));
2480 sdp_dump_transport_info(pinfo
, transport_info
);
2484 if (exchange_type
!= SDP_EXCHANGE_OFFER
)
2485 wmem_tree_insert32(sdp_transport_rsps
, pinfo
->num
, (void *)transport_info
);
2487 /* Offer has already been answered or rejected and hash tables freed, so
2488 * don't try to add to it
2489 * XXX - Need to support "modified offers" */
2490 if ((transport_info
->sdp_status
== SDP_EXCHANGE_ANSWER_REJECT
) ||
2491 (transport_info
->sdp_status
== SDP_EXCHANGE_ANSWER_ACCEPT
))
2494 /* Initialize the session description before parsing the media descriptions. */
2495 memset(&session_info
, 0, sizeof(session_info_t
));
2496 session_info
.rtp_dyn_payload
= rtp_dyn_payload_new();
2498 /* Remember where the answer should start (it will be zero if there was no
2499 * previous offer with media descriptions). */
2500 start_transport_info_count
= wmem_array_get_count(transport_info
->media_descriptions
);
2502 DPRINT(("start_transport_info_count=%d", start_transport_info_count
));
2505 * Show the SDP message a line at a time.
2507 while (tvb_offset_exists(tvb
, offset
)) {
2509 * Find the end of the line.
2511 linelen
= tvb_find_line_end_unquoted(tvb
, offset
, -1, &next_offset
);
2514 * Line must contain at least e.g. "v=".
2519 type
= tvb_get_uint8(tvb
, offset
);
2520 delim
= tvb_get_uint8(tvb
, offset
+ 1);
2522 offset
= next_offset
;
2527 * Attributes. Only care about ones that affect the transport. Ignore others.
2531 hf
= hf_connection_info
;
2536 /* Try to create a new media description (it will return NULL if
2537 * there are too many). */
2538 media_desc
= sdp_new_media_description(transport_info
->media_descriptions
, &session_info
);
2540 in_media_description
= true;
2541 DPRINT(("in media description, media descriptions count=%d",
2542 wmem_array_get_count(transport_info
->media_descriptions
)));
2545 if (in_media_description
) {
2546 hf
= hf_media_attribute
;
2548 hf
= hf_session_attribute
;
2556 if (hf
!= hf_unknown
)
2559 call_sdp_subdissector(tvb_new_subset_length(tvb
, offset
+ tokenoffset
,
2560 linelen
- tokenoffset
),
2562 hf
, NULL
, linelen
-tokenoffset
,
2564 in_media_description
? NULL
: &session_info
,
2570 offset
= next_offset
;
2573 /* Done parsing media description, no more need for the session-level details. */
2574 rtp_dyn_payload_free(session_info
.rtp_dyn_payload
);
2575 session_info
.rtp_dyn_payload
= NULL
;
2577 /* Post-processing, close media streams, apply attributes, etc. */
2578 complete_descriptions(transport_info
, start_transport_info_count
);
2580 #ifdef DEBUG_CONVERSATION
2581 sdp_dump_transport_info(pinfo
, transport_info
);
2584 /* We have a successful negotiation, apply data to their respective protocols */
2585 if (!delay
|| ((exchange_type
== SDP_EXCHANGE_ANSWER_ACCEPT
) &&
2586 (transport_info
->sdp_status
== SDP_EXCHANGE_OFFER
))) {
2587 /* Accepting answer to a previous offer (or delay pref is false). */
2588 apply_sdp_transport(pinfo
, transport_info
, request_frame
, setup_info
);
2590 /* Free all media hash tables that were not assigned to a conversation
2591 * ('set_rtp' is false) */
2592 clean_unused_media_descriptions(transport_info
->media_descriptions
);
2594 transport_info
->sdp_status
= exchange_type
;
2596 } else if ((exchange_type
== SDP_EXCHANGE_ANSWER_REJECT
) &&
2597 (transport_info
->sdp_status
!= SDP_EXCHANGE_ANSWER_REJECT
)) {
2598 /* Rejecting answer */
2599 clean_unused_media_descriptions(transport_info
->media_descriptions
);
2601 transport_info
->sdp_status
= SDP_EXCHANGE_ANSWER_REJECT
;
2602 } /* else attempt to accept an unknown offer. */
2605 void setup_sdp_transport_resend(int current_frame
, int request_frame
)
2607 transport_info_t
* transport_info
= NULL
;
2609 if (request_frame
!= 0) {
2610 transport_info
= (transport_info_t
*)wmem_tree_lookup32( sdp_transport_reqs
, request_frame
);
2611 if (transport_info
!= NULL
) {
2612 wmem_tree_insert32(sdp_transport_reqs
, current_frame
, (void *)transport_info
);
2618 dissect_sdp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
2620 proto_tree
*sdp_tree
;
2621 proto_item
*ti
, *sub_ti
;
2622 int offset
= 0, next_offset
, n
;
2624 bool in_media_description
;
2625 unsigned char type
, delim
;
2626 int datalen
, tokenoffset
, hf
= -1;
2628 sdp_data_t sdp_data
;
2630 transport_info_t local_transport_info
;
2631 transport_info_t
* transport_info
= NULL
;
2632 media_description_t
*media_desc
= NULL
;
2633 session_info_t session_info
;
2634 sdp_packet_info
*sdp_pi
;
2635 sdp_setup_info_t
*setup_info
= NULL
;
2638 media_content_info_t
*content_info
= (media_content_info_t
*)data
;
2639 if (content_info
->type
== MEDIA_CONTAINER_SIP_DATA
) {
2640 setup_info
= (sdp_setup_info_t
*)content_info
->data
;
2644 DPRINT2(("----------------------- dissect_sdp ------------------------"));
2646 /* Initialise packet info for passing to tap */
2647 sdp_pi
= wmem_new(pinfo
->pool
, sdp_packet_info
);
2648 sdp_pi
->summary_str
[0] = '\0';
2650 memset(&sdp_data
, 0, sizeof(sdp_data
));
2652 transport_info
= (transport_info_t
*)wmem_tree_lookup32( sdp_transport_reqs
, pinfo
->num
);
2654 if (transport_info
== NULL
) {
2655 /* Can't find it in the requests, make sure it's not a response */
2656 transport_info
= (transport_info_t
*)wmem_tree_lookup32( sdp_transport_rsps
, pinfo
->num
);
2659 if (transport_info
== NULL
) {
2660 transport_info
= &local_transport_info
;
2662 #ifdef DEBUG_CONVERSATION
2664 DPRINT(("found previous transport_info:"));
2665 sdp_dump_transport_info(pinfo
, transport_info
);
2669 /* Initialize local transport info */
2670 memset(&local_transport_info
, 0, sizeof(local_transport_info
));
2671 /* Note: packet-scoped since it is only needed while parsing this packet. */
2672 local_transport_info
.media_descriptions
= wmem_array_new(pinfo
->pool
, sizeof(media_description_t
));
2674 for (n
= 0; n
< SDP_NO_OF_PT
; n
++) {
2675 local_transport_info
.encoding_name
[n
] = wmem_strdup(pinfo
->pool
, UNKNOWN_ENCODING
);
2679 * As RFC 2327 says, "SDP is purely a format for session
2680 * description - it does not incorporate a transport protocol,
2681 * and is intended to use different transport protocols as
2682 * appropriate including the Session Announcement Protocol,
2683 * Session Initiation Protocol, Real-Time Streaming Protocol,
2684 * electronic mail using the MIME extensions, and the
2685 * Hypertext Transport Protocol."
2687 * We therefore don't set the protocol or info columns;
2688 * instead, we append to them, so that we don't erase
2689 * what the protocol inside which the SDP stuff resides
2692 col_append_str(pinfo
->cinfo
, COL_PROTOCOL
, "/SDP");
2694 ti
= proto_tree_add_item(tree
, proto_sdp
, tvb
, offset
, -1, ENC_NA
);
2695 sdp_tree
= proto_item_add_subtree(ti
, ett_sdp
);
2698 * Show the SDP message a line at a time.
2700 in_media_description
= false;
2702 /* Initialize the session description before parsing the media level. */
2703 memset(&session_info
, 0, sizeof(session_info_t
));
2704 session_info
.rtp_dyn_payload
= rtp_dyn_payload_new();
2706 while (tvb_offset_exists(tvb
, offset
)) {
2708 * Find the end of the line.
2710 linelen
= tvb_find_line_end_unquoted(tvb
, offset
, -1, &next_offset
);
2713 * Line must contain at least e.g. "v=".
2718 type
= tvb_get_uint8(tvb
, offset
);
2719 delim
= tvb_get_uint8(tvb
, offset
+ 1);
2721 proto_item
*ti2
= proto_tree_add_item(sdp_tree
, hf_invalid
, tvb
, offset
, linelen
, ENC_UTF_8
);
2722 expert_add_info(pinfo
, ti2
, &ei_sdp_invalid_line_equal
);
2723 offset
= next_offset
;
2732 hf
= hf_protocol_version
;
2738 hf
= hf_session_name
;
2741 if (in_media_description
) {
2742 hf
= hf_media_title
;
2744 hf
= hf_session_info
;
2757 hf
= hf_connection_info
;
2766 hf
= hf_repeat_time
;
2771 /* Try to create a new media description (it will return NULL if
2772 * there are too many). Pass local_transport_info since we do
2773 * not want to modify the transport_info that was created by
2774 * setup_sdp_transport. */
2775 media_desc
= sdp_new_media_description(local_transport_info
.media_descriptions
, &session_info
);
2777 in_media_description
= true;
2780 hf
= hf_encryption_key
;
2783 if (in_media_description
) {
2784 hf
= hf_media_attribute
;
2786 hf
= hf_session_attribute
;
2797 if (hf
== hf_unknown
)
2799 string
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ tokenoffset
,
2800 linelen
- tokenoffset
, ENC_ASCII
);
2801 sub_ti
= proto_tree_add_string(sdp_tree
, hf
, tvb
, offset
, linelen
,
2804 call_sdp_subdissector(tvb_new_subset_length(tvb
, offset
+ tokenoffset
,
2805 linelen
- tokenoffset
),
2807 hf
, sub_ti
, linelen
-tokenoffset
,
2808 &local_transport_info
,
2809 in_media_description
? NULL
: &session_info
,
2810 in_media_description
? media_desc
: NULL
,
2813 offset
= next_offset
;
2816 if (NULL
!= sdp_data
.ed137_fid
) {
2817 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", sdp_data
.ed137_fid
);
2818 (void) g_strlcat(sdp_pi
->summary_str
, sdp_data
.ed137_fid
, 50);
2820 if (NULL
!= sdp_data
.ed137_txrxmode
) {
2821 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", sdp_data
.ed137_txrxmode
);
2822 if (strlen(sdp_pi
->summary_str
))
2823 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2824 (void) g_strlcat(sdp_pi
->summary_str
, sdp_data
.ed137_txrxmode
, 50);
2826 if (NULL
!= sdp_data
.ed137_type
) {
2827 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ", sdp_data
.ed137_type
);
2828 if (strlen(sdp_pi
->summary_str
))
2829 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2830 (void) g_strlcat(sdp_pi
->summary_str
, sdp_data
.ed137_type
, 50);
2833 /* Done parsing media description, no more need for the session-level details. */
2834 rtp_dyn_payload_free(session_info
.rtp_dyn_payload
);
2835 session_info
.rtp_dyn_payload
= NULL
;
2837 /* Post-processing, close media streams, apply attributes, etc. */
2838 if (transport_info
== &local_transport_info
) {
2839 DPRINT(("no previous transport_info saved, calling complete_descriptions()"));
2841 complete_descriptions(transport_info
, 0);
2843 #ifdef DEBUG_CONVERSATION
2844 sdp_dump_transport_info(pinfo
, transport_info
);
2847 #ifdef DEBUG_CONVERSATION
2849 DPRINT(("not overwriting previous transport_info, local_transport_info contents:"));
2850 sdp_dump_transport_info(pinfo
, &local_transport_info
);
2854 /* For messages not part of the Offer/Answer model, assume that the SDP is
2855 * immediately effective (apply it now). */
2856 if ((!pinfo
->fd
->visited
) && (transport_info
== &local_transport_info
)) {
2857 /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
2858 * OFFER/ANSWER functionality using setup_sdp_transport(). Once all of the higher layers
2859 * use setup_sdp_transport(), this should be removed
2860 * Note that transport_info contains the SDP info from this frame (and
2861 * not an earlier request (transport_info == &local_transport_info).
2862 * Use 0 as request_frame since there is no (known) request.
2864 apply_sdp_transport(pinfo
, transport_info
, 0, setup_info
);
2865 /* Save the list of setup info of calls with the same RTP information
2866 * to the packet in file scope, since transport_info is local and
2867 * we won't do this on future passes.
2869 p_add_proto_data(wmem_file_scope(), pinfo
, proto_sdp
, 0, transport_info
->sdp_setup_info_list
);
2872 /* Add information to the VoIP Calls dialog. */
2873 for (unsigned i
= 0; i
< wmem_array_get_count(local_transport_info
.media_descriptions
); i
++)
2875 media_desc
= (media_description_t
*)wmem_array_index(local_transport_info
.media_descriptions
, i
);
2877 if (media_desc
->media_port
!= 0) {
2878 /* Create the RTP summary str for the Voip Call analysis.
2879 * XXX - Currently this is based only on the current packet
2881 for (int j
= 0; j
< media_desc
->media
.pt_count
; j
++)
2883 DPRINT(("in for-loop for voip call analysis setting for media #%d, pt=%d",
2884 j
, media_desc
->media
. pt
[j
]));
2885 /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
2886 if ((media_desc
->media
.pt
[j
] >= 96) && (media_desc
->media
.pt
[j
] <= 127)) {
2887 const char *payload_type_str
= rtp_dyn_payload_get_name(
2888 media_desc
->media
.rtp_dyn_payload
,
2889 media_desc
->media
.pt
[j
]);
2890 if (payload_type_str
) {
2891 if (strlen(sdp_pi
->summary_str
))
2892 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2893 (void) g_strlcat(sdp_pi
->summary_str
, payload_type_str
, 50);
2896 snprintf(num_pt
, 10, "%u", media_desc
->media
.pt
[j
]);
2897 if (strlen(sdp_pi
->summary_str
))
2898 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2899 (void) g_strlcat(sdp_pi
->summary_str
, num_pt
, 50);
2902 if (strlen(sdp_pi
->summary_str
))
2903 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2904 (void) g_strlcat(sdp_pi
->summary_str
,
2905 val_to_str_ext(media_desc
->media
.pt
[j
], &rtp_payload_type_short_vals_ext
, "%u"),
2911 /* Create the T38 summary str for the Voip Call analysis
2912 * XXX - Currently this is based only on the current packet
2914 if ((media_desc
->media_port
!= 0) && media_desc
->proto
== SDP_PROTO_T38
) {
2915 if (strlen(sdp_pi
->summary_str
))
2916 (void) g_strlcat(sdp_pi
->summary_str
, " ", 50);
2917 (void) g_strlcat(sdp_pi
->summary_str
, "t38", 50);
2921 /* Free all media hash tables that were not assigned to a conversation
2922 * ('set_rtp' is false) */
2923 if (transport_info
== &local_transport_info
) {
2924 clean_unused_media_descriptions(transport_info
->media_descriptions
);
2927 datalen
= tvb_captured_length_remaining(tvb
, offset
);
2929 proto_tree_add_item(sdp_tree
, hf_sdp_data
, tvb
, offset
, datalen
, ENC_NA
);
2931 /* Add Trace info */
2932 wmem_array_t
*setup_info_list
= transport_info
->sdp_setup_info_list
;
2933 if (!setup_info_list
) {
2934 setup_info_list
= (wmem_array_t
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sdp
, 0);
2936 if (setup_info_list
) {
2938 sdp_setup_info_t
*stored_setup_info
;
2940 for (i
= 0; i
< wmem_array_get_count(setup_info_list
); i
++) {
2941 stored_setup_info
= (sdp_setup_info_t
*)wmem_array_index(setup_info_list
, i
);
2942 if (stored_setup_info
->hf_id
) {
2943 if (stored_setup_info
->hf_type
== SDP_TRACE_ID_HF_TYPE_STR
) {
2944 item
= proto_tree_add_string(sdp_tree
, stored_setup_info
->hf_id
, tvb
, 0, 0, stored_setup_info
->trace_id
.str
);
2945 proto_item_set_generated(item
);
2946 if (stored_setup_info
->add_hidden
== true) {
2947 proto_item_set_hidden(item
);
2949 } else if (stored_setup_info
->hf_type
== SDP_TRACE_ID_HF_TYPE_UINT32
) {
2950 item
= proto_tree_add_uint(sdp_tree
, stored_setup_info
->hf_id
, tvb
, 0, 0, stored_setup_info
->trace_id
.num
);
2951 proto_item_set_generated(item
);
2952 if (stored_setup_info
->add_hidden
== true) {
2953 proto_item_set_hidden(item
);
2959 /* Report this packet to the tap */
2960 tap_queue_packet(sdp_tap
, pinfo
, sdp_pi
);
2962 return tvb_captured_length(tvb
);
2966 proto_register_sdp(void)
2968 static hf_register_info hf
[] = {
2969 { &hf_protocol_version
,
2970 { "Session Description Protocol Version (v)", "sdp.version",
2971 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2975 { "Owner/Creator, Session Id (o)",
2976 "sdp.owner", FT_STRING
, BASE_NONE
, NULL
,
2980 { "Session Name (s)", "sdp.session_name",
2981 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2985 { "Session Information (i)", "sdp.session_info",
2986 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2990 { "URI of Description (u)", "sdp.uri",
2991 FT_STRING
, BASE_NONE
, NULL
, 0x0,
2995 { "E-mail Address (e)", "sdp.email",
2996 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3000 { "Phone Number (p)", "sdp.phone",
3001 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3004 { &hf_connection_info
,
3005 { "Connection Information (c)", "sdp.connection_info",
3006 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3010 { "Bandwidth Information (b)", "sdp.bandwidth",
3011 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3015 { "Time Zone Adjustments (z)", "sdp.timezone",
3016 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3019 { &hf_encryption_key
,
3020 { "Encryption Key (k)", "sdp.encryption_key",
3021 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3024 { &hf_session_attribute
,
3025 { "Session Attribute (a)", "sdp.session_attr",
3026 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3029 { &hf_media_attribute
,
3030 { "Media Attribute (a)", "sdp.media_attr",
3031 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3035 { "Time Description, active time (t)",
3036 "sdp.time", FT_STRING
, BASE_NONE
, NULL
,
3040 { "Repeat Time (r)", "sdp.repeat_time",
3041 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3045 { "Media Description, name and address (m)",
3046 "sdp.media", FT_STRING
, BASE_NONE
, NULL
, 0x0,
3050 { "Media Title (i)", "sdp.media_title",
3051 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3055 { "Unknown", "sdp.unknown",
3056 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3060 { "Invalid line", "sdp.invalid",
3061 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3064 { &hf_owner_username
,
3065 { "Owner Username", "sdp.owner.username",
3066 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3069 { &hf_owner_sessionid
,
3070 { "Session ID", "sdp.owner.sessionid",
3071 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3074 { &hf_owner_version
,
3075 { "Session Version", "sdp.owner.version",
3076 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3079 { &hf_owner_network_type
,
3080 { "Owner Network Type", "sdp.owner.network_type",
3081 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3084 { &hf_owner_address_type
,
3085 { "Owner Address Type", "sdp.owner.address_type",
3086 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3089 { &hf_owner_address
,
3090 { "Owner Address", "sdp.owner.address",
3091 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3094 { &hf_connection_info_network_type
,
3095 { "Connection Network Type", "sdp.connection_info.network_type",
3096 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3099 { &hf_connection_info_address_type
,
3100 { "Connection Address Type", "sdp.connection_info.address_type",
3101 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3104 { &hf_connection_info_connection_address
,
3105 { "Connection Address", "sdp.connection_info.address",
3106 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3109 { &hf_connection_info_ttl
,
3110 { "Connection TTL", "sdp.connection_info.ttl",
3111 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3114 { &hf_connection_info_num_addr
,
3115 { "Connection Number of Addresses", "sdp.connection_info.num_addr",
3116 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3119 { &hf_bandwidth_modifier
,
3120 { "Bandwidth Modifier", "sdp.bandwidth.modifier",
3121 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3124 { &hf_bandwidth_value
,
3125 { "Bandwidth Value", "sdp.bandwidth.value",
3126 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3127 "Bandwidth Value (in kbits/s)", HFILL
}
3130 { "Session Start Time", "sdp.time.start",
3131 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3135 { "Session Stop Time", "sdp.time.stop",
3136 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3139 { &hf_repeat_time_interval
,
3140 { "Repeat Interval", "sdp.repeat_time.interval",
3141 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3144 { &hf_repeat_time_duration
,
3145 { "Repeat Duration", "sdp.repeat_time.duration",
3146 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3149 { &hf_repeat_time_offset
,
3150 { "Repeat Offset", "sdp.repeat_time.offset",
3151 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3154 { &hf_timezone_time
,
3155 { "Timezone Time", "sdp.timezone.time",
3156 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3159 { &hf_timezone_offset
,
3160 { "Timezone Offset", "sdp.timezone.offset",
3161 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3164 { &hf_encryption_key_type
,
3165 { "Key Type", "sdp.encryption_key.type",
3166 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3169 { &hf_encryption_key_data
,
3170 { "Key Data", "sdp.encryption_key.data",
3171 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3174 { &hf_session_attribute_field
,
3175 { "Session Attribute Fieldname", "sdp.session_attr.field",
3176 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3179 { &hf_session_attribute_value
,
3180 { "Session Attribute Value", "sdp.session_attr.value",
3181 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3185 { "Media Type", "sdp.media.media",
3186 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3190 { "Media Port", "sdp.media.port",
3191 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
3194 { &hf_media_port_string
,
3195 { "Media Port", "sdp.media.port_string",
3196 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3199 { &hf_media_portcount
,
3200 { "Media Port Count", "sdp.media.portcount",
3201 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3205 { "Media Protocol", "sdp.media.proto",
3206 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3210 { "Media Format", "sdp.media.format",
3211 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3214 { &hf_media_attribute_field
,
3215 { "Media Attribute Fieldname", "sdp.media_attribute.field",
3216 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3219 { &hf_media_attribute_value
,
3220 { "Media Attribute Value", "sdp.media_attribute.value",
3221 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3224 { &hf_media_encoding_name
,
3225 { "MIME Type", "sdp.mime.type",
3226 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3227 "SDP MIME Type", HFILL
}
3229 { &hf_media_sample_rate
,
3230 { "Sample Rate", "sdp.sample_rate",
3231 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3234 { &hf_media_channels
,
3235 { "Audio Channels", "sdp.channels",
3236 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3239 { &hf_media_format_specific_parameter
,
3240 { "Media format specific parameters", "sdp.fmtp.parameter",
3241 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3242 "Format specific parameter(fmtp)", HFILL
}
3244 { &hf_ipbcp_version
,
3245 { "IPBCP Protocol Version", "sdp.ipbcp.version",
3246 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3250 { "IPBCP Command Type", "sdp.ipbcp.command",
3251 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3254 {&hf_sdp_fmtp_mpeg4_profile_level_id
,
3255 { "Level Code", "sdp.fmtp.profile_level_id",
3256 FT_UINT32
, BASE_DEC
, VALS(mp4ves_level_indication_vals
), 0x0,
3259 { &hf_sdp_fmtp_h263_profile
,
3260 { "Profile", "sdp.fmtp.h263profile",
3261 FT_UINT32
, BASE_DEC
, VALS(h263_profile_vals
), 0x0,
3264 { &hf_sdp_fmtp_h263_level
,
3265 { "Level", "sdp.fmtp.h263level",
3266 FT_UINT32
, BASE_DEC
, VALS(h263_level_vals
), 0x0,
3269 { &hf_sdp_h264_packetization_mode
,
3270 { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
3271 FT_UINT32
, BASE_DEC
, VALS(h264_packetization_mode_vals
), 0x0,
3274 { &hf_SDPh223LogicalChannelParameters
,
3275 { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
3276 FT_NONE
, BASE_NONE
, NULL
, 0,
3279 { &hf_key_mgmt_att_value
,
3280 { "Key Management", "sdp.key_mgmt",
3281 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3284 { &hf_key_mgmt_prtcl_id
,
3285 { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
3286 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3289 { &hf_key_mgmt_data
,
3290 { "Key Management Data", "sdp.key_mgmt.data",
3291 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3294 { &hf_sdp_crypto_tag
,
3295 { "tag", "sdp.crypto.tag",
3296 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
3299 { &hf_sdp_crypto_crypto_suite
,
3300 { "Crypto suite", "sdp.crypto.crypto_suite",
3301 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3304 { &hf_sdp_crypto_master_key
,
3305 { "Master Key", "sdp.crypto.master_key",
3306 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3309 { &hf_sdp_crypto_master_salt
,
3310 { "Master salt", "sdp.crypto.master_salt",
3311 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
3314 { &hf_sdp_crypto_lifetime
,
3315 { "Lifetime", "sdp.crypto.lifetime",
3316 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3319 { &hf_sdp_crypto_mki
,
3320 { "mki-value", "sdp.crypto.mki-valu",
3321 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3324 { &hf_sdp_crypto_mki_length
,
3325 { "mki_length", "sdp.crypto.mki_length",
3326 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3329 { &hf_ice_candidate_foundation
,
3330 { "Foundation", "sdp.ice_candidate.foundation",
3331 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3332 "Identifier, same for two candidates with same type, base address, protocol and STUN server", HFILL
}
3334 { &hf_ice_candidate_componentid
,
3335 { "Component ID", "sdp.ice_candidate.componentid",
3336 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3337 "Media component identifier (For RTP media, 1 is RTP, 2 is RTCP)", HFILL
}
3339 { &hf_ice_candidate_transport
,
3340 { "Transport", "sdp.ice_candidate.transport",
3341 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3342 "Transport protocol", HFILL
}
3344 { &hf_ice_candidate_priority
,
3345 { "Priority", "sdp.ice_candidate.priority",
3346 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3349 { &hf_ice_candidate_address
,
3350 { "Connection Address", "sdp.ice_candidate.address",
3351 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3352 "IP address or FQDN of the candidate", HFILL
}
3354 { &hf_ice_candidate_port
,
3355 { "Candidate Port", "sdp.ice_candidate.port",
3356 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3357 "Port of the candidate", HFILL
}
3359 { &hf_ice_candidate_type
,
3360 { "Candidate Type", "sdp.ice_candidate.type",
3361 FT_STRING
, BASE_NONE
, NULL
, 0x0,
3362 "The origin of the address and port, i.e. where it was learned", HFILL
}
3364 /* Generated from convert_proto_tree_add_text.pl */
3365 { &hf_sdp_nal_unit_1_string
, { "NAL unit 1 string", "sdp.nal_unit_1_string", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3366 { &hf_sdp_nal_unit_2_string
, { "NAL unit 2 string", "sdp.nal_unit_2_string", FT_STRING
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3367 { &hf_sdp_key_and_salt
, { "Key and Salt", "sdp.key_and_salt", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3368 { &hf_sdp_data
, { "Data", "sdp.data", FT_BYTES
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
3370 static int *ett
[] = {
3373 &ett_sdp_connection_info
,
3376 &ett_sdp_repeat_time
,
3378 &ett_sdp_encryption_key
,
3379 &ett_sdp_session_attribute
,
3381 &ett_sdp_media_attribute
,
3384 &ett_sdp_crypto_key_parameters
,
3387 static ei_register_info ei
[] = {
3388 { &ei_sdp_invalid_key_param
,
3389 { "sdp.invalid_key_param",
3390 PI_MALFORMED
, PI_NOTE
,
3391 "Invalid key-param (no ':' delimiter)",
3395 { &ei_sdp_invalid_line_equal
,
3396 { "sdp.invalid_line.no_equal",
3397 PI_MALFORMED
, PI_NOTE
,
3398 "Invalid SDP line (no '=' delimiter)",
3402 { &ei_sdp_invalid_line_fields
,
3403 { "sdp.invalid_line.missing_fields",
3404 PI_MALFORMED
, PI_ERROR
,
3405 "Invalid SDP line (missing required fields)",
3409 { &ei_sdp_invalid_line_space
,
3410 { "sdp.invalid_line.extra_space",
3411 PI_MALFORMED
, PI_ERROR
,
3412 "Invalid SDP whitespace (extra space character)",
3416 { &ei_sdp_invalid_conversion
,
3417 { "sdp.invalid_conversion",
3418 PI_PROTOCOL
, PI_WARN
,
3419 "Invalid conversion",
3423 { &ei_sdp_invalid_media_port
,
3424 { "sdp.invalid_media_port",
3425 PI_MALFORMED
, PI_ERROR
,
3426 "Invalid media port",
3430 { &ei_sdp_invalid_sample_rate
,
3431 { "sdp.invalid_sample_rate",
3432 PI_MALFORMED
, PI_ERROR
,
3433 "Invalid sample rate",
3437 { &ei_sdp_invalid_channels
,
3438 { "sdp.invalid_channels",
3439 PI_MALFORMED
, PI_WARN
,
3440 "Invalid number of audio channels",
3444 { &ei_sdp_invalid_media_format
,
3445 { "sdp.invalid_media_format",
3446 PI_MALFORMED
, PI_ERROR
,
3447 "Invalid media format",
3451 { &ei_sdp_invalid_crypto_tag
,
3452 { "sdp.invalid_crypto_tag",
3453 PI_MALFORMED
, PI_ERROR
,
3454 "Invalid crypto tag",
3458 { &ei_sdp_invalid_crypto_mki_length
,
3459 { "sdp.invalid_crypto_mki_length",
3460 PI_MALFORMED
, PI_ERROR
,
3461 "Invalid crypto mki length",
3467 module_t
*sdp_module
;
3468 expert_module_t
* expert_sdp
;
3470 proto_sdp
= proto_register_protocol("Session Description Protocol",
3472 proto_register_field_array(proto_sdp
, hf
, array_length(hf
));
3473 proto_register_subtree_array(ett
, array_length(ett
));
3474 expert_sdp
= expert_register_protocol(proto_sdp
);
3475 expert_register_field_array(expert_sdp
, ei
, array_length(ei
));
3477 key_mgmt_dissector_table
= register_dissector_table("key_mgmt",
3478 "Key Management", proto_sdp
, FT_STRING
, STRING_CASE_SENSITIVE
);
3480 * Preferences registration
3482 sdp_module
= prefs_register_protocol(proto_sdp
, NULL
);
3483 prefs_register_bool_preference(sdp_module
, "establish_conversation",
3484 "Establish Media Conversation",
3485 "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
3486 "upon port numbers found in SDP payload",
3487 &global_sdp_establish_conversation
);
3489 sdp_transport_reqs
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3490 sdp_transport_rsps
= wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3493 * Register the dissector by name, so other dissectors can
3494 * grab it by name rather than just referring to it directly.
3496 sdp_handle
= register_dissector("sdp", dissect_sdp
, proto_sdp
);
3498 /* Register for tapping */
3499 sdp_tap
= register_tap("sdp");
3501 /* compile patterns */
3502 ws_mempbrk_compile(&pbrk_digits
, "0123456789");
3503 ws_mempbrk_compile(&pbrk_alpha
, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
3507 proto_reg_handoff_sdp(void)
3509 rtcp_handle
= find_dissector_add_dependency("rtcp", proto_sdp
);
3510 msrp_handle
= find_dissector_add_dependency("msrp", proto_sdp
);
3511 sprt_handle
= find_dissector_add_dependency("sprt", proto_sdp
);
3512 bfcp_handle
= find_dissector_add_dependency("bfcp", proto_sdp
);
3513 h264_handle
= find_dissector_add_dependency("h264", proto_sdp
);
3514 h265_handle
= find_dissector_add_dependency("h265", proto_sdp
);
3515 mp4ves_config_handle
= find_dissector_add_dependency("mp4ves_config", proto_sdp
);
3517 proto_sprt
= dissector_handle_get_protocol_index(find_dissector("sprt"));
3519 dissector_add_string("media_type", "application/sdp", sdp_handle
);
3520 dissector_add_uint("bctp.tpi", 0x20, sdp_handle
);
3524 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3529 * indent-tabs-mode: nil
3532 * vi: set shiftwidth=4 tabstop=8 expandtab:
3533 * :indentSize=4:tabSize=8:noTabs=true: