Coverage Report

Created: 2026-03-30 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-sdp.c
Line
Count
Source
1
/* packet-sdp.c
2
 * Routines for SDP packet disassembly (RFC 2327)
3
 *
4
 * Jason Lango <jal@netapp.com>
5
 * Liberally copied from packet-http.c, by Guy Harris <guy@alum.mit.edu>
6
 *
7
 * Wireshark - Network traffic analyzer
8
 * By Gerald Combs <gerald@wireshark.org>
9
 * Copyright 1998 Gerald Combs
10
 *
11
 * SPDX-License-Identifier: GPL-2.0-or-later
12
 * Ref https://www.ietf.org/rfc/rfc4566
13
 */
14
15
#include "config.h"
16
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>
22
#include <epan/tap.h>
23
#include <epan/show_exception.h>
24
#include <epan/addr_resolv.h>
25
#include <epan/conversation.h>
26
#include <epan/proto_data.h>
27
#include <epan/strutil.h>
28
29
#include <wsutil/strtoi.h>
30
#include <wsutil/str_util.h>
31
#include <wsutil/array.h>
32
33
#include "packet-media-type.h"
34
#include "packet-sdp.h"
35
#include "packet-http.h"
36
37
/* un-comment the following as well as this line in conversation.c, to enable debug printing */
38
/* #define DEBUG_CONVERSATION */
39
#include "conversation_debug.h"
40
41
#include "packet-gsm_osmux.h"
42
#include "packet-rtp.h"
43
#include "packet-rtp_pt.h"
44
#include "packet-rtcp.h"
45
#include "packet-t38.h"
46
#include "packet-msrp.h"
47
#include "packet-sprt.h"
48
#include "packet-bfcp.h"
49
#include "packet-h245.h"
50
#include "packet-h264.h"
51
#include "packet-h265.h"
52
#include "packet-mp4ves.h"
53
54
void proto_register_sdp(void);
55
void proto_reg_handoff_sdp(void);
56
57
static dissector_handle_t sdp_handle;
58
static dissector_handle_t rtcp_handle;
59
static dissector_handle_t sprt_handle;
60
static dissector_handle_t msrp_handle;
61
static dissector_handle_t bfcp_handle;
62
static dissector_handle_t h264_handle;
63
static dissector_handle_t h265_handle;
64
static dissector_handle_t mp4ves_config_handle;
65
66
static int sdp_tap;
67
68
static int proto_sdp;
69
static int proto_sprt;
70
71
static const char* UNKNOWN_ENCODING = "Unknown";
72
static wmem_tree_t *sdp_transport_reqs;
73
static wmem_tree_t *sdp_transport_rsps;
74
static wmem_map_t *sdp_rtsp_control_map;
75
76
/* preference globals */
77
static bool global_sdp_establish_conversation = true;
78
79
/* Top level fields */
80
static int hf_protocol_version;
81
static int hf_owner;
82
static int hf_session_name;
83
static int hf_session_info;
84
static int hf_uri;
85
static int hf_email;
86
static int hf_phone;
87
static int hf_connection_info;
88
static int hf_bandwidth;
89
static int hf_timezone;
90
static int hf_encryption_key;
91
static int hf_session_attribute;
92
static int hf_media_attribute;
93
static int hf_time;
94
static int hf_repeat_time;
95
static int hf_media;
96
static int hf_media_title;
97
static int hf_unknown;
98
static int hf_invalid;
99
static int hf_ipbcp_version;
100
static int hf_ipbcp_type;
101
102
/* hf_owner subfields*/
103
static int hf_owner_username;
104
static int hf_owner_sessionid;
105
static int hf_owner_version;
106
static int hf_owner_network_type;
107
static int hf_owner_address_type;
108
static int hf_owner_address;
109
110
/* hf_connection_info subfields */
111
static int hf_connection_info_network_type;
112
static int hf_connection_info_address_type;
113
static int hf_connection_info_connection_address;
114
static int hf_connection_info_ttl;
115
static int hf_connection_info_num_addr;
116
117
/* hf_bandwidth subfields */
118
static int hf_bandwidth_modifier;
119
static int hf_bandwidth_value;
120
121
/* hf_time subfields */
122
static int hf_time_start;
123
static int hf_time_stop;
124
125
/* hf_repeat_time subfield */
126
static int hf_repeat_time_interval;
127
static int hf_repeat_time_duration;
128
static int hf_repeat_time_offset;
129
130
/* hf_timezone subfields */
131
static int hf_timezone_time;
132
static int hf_timezone_offset;
133
134
/* hf_encryption_key subfields */
135
static int hf_encryption_key_type;
136
static int hf_encryption_key_data;
137
138
/* hf_session_attribute subfields */
139
static int hf_session_attribute_field;
140
static int hf_session_attribute_value;
141
142
/* hf_media subfields */
143
static int hf_media_media;
144
static int hf_media_port;
145
static int hf_media_port_string;
146
static int hf_media_portcount;
147
static int hf_media_proto;
148
static int hf_media_format;
149
150
/* hf_session_attribute subfields */
151
static int hf_media_attribute_field;
152
static int hf_media_attribute_value;
153
static int hf_media_encoding_name;
154
static int hf_media_sample_rate;
155
static int hf_media_channels;
156
static int hf_media_format_specific_parameter;
157
static int hf_sdp_fmtp_mpeg4_profile_level_id;
158
static int hf_sdp_fmtp_h263_profile;
159
static int hf_sdp_fmtp_h263_level;
160
static int hf_sdp_h264_packetization_mode;
161
static int hf_SDPh223LogicalChannelParameters;
162
163
/* hf_session_attribute hf_media_attribute subfields */
164
static int hf_key_mgmt_att_value;
165
static int hf_key_mgmt_prtcl_id;
166
static int hf_key_mgmt_data;
167
168
static int hf_sdp_crypto_tag;
169
static int hf_sdp_crypto_crypto_suite;
170
static int hf_sdp_crypto_master_key;
171
static int hf_sdp_crypto_master_salt;
172
static int hf_sdp_crypto_lifetime;
173
static int hf_sdp_crypto_mki;
174
static int hf_sdp_crypto_mki_length;
175
176
/* a=candidate subfields */
177
static int hf_ice_candidate_foundation;
178
static int hf_ice_candidate_componentid;
179
static int hf_ice_candidate_transport;
180
static int hf_ice_candidate_priority;
181
static int hf_ice_candidate_address;
182
static int hf_ice_candidate_port;
183
static int hf_ice_candidate_type;
184
185
/* Generated from convert_proto_tree_add_text.pl */
186
static int hf_sdp_nal_unit_2_string;
187
static int hf_sdp_key_and_salt;
188
static int hf_sdp_nal_unit_1_string;
189
static int hf_sdp_data;
190
191
/* trees */
192
static int ett_sdp;
193
static int ett_sdp_owner;
194
static int ett_sdp_connection_info;
195
static int ett_sdp_bandwidth;
196
static int ett_sdp_time;
197
static int ett_sdp_repeat_time;
198
static int ett_sdp_timezone;
199
static int ett_sdp_encryption_key;
200
static int ett_sdp_session_attribute;
201
static int ett_sdp_media;
202
static int ett_sdp_media_attribute;
203
static int ett_sdp_fmtp;
204
static int ett_sdp_key_mgmt;
205
static int ett_sdp_crypto_key_parameters;
206
207
static expert_field ei_sdp_invalid_key_param;
208
static expert_field ei_sdp_invalid_line_equal;
209
static expert_field ei_sdp_invalid_line_fields;
210
static expert_field ei_sdp_invalid_line_space;
211
static expert_field ei_sdp_invalid_conversion;
212
static expert_field ei_sdp_invalid_media_port;
213
static expert_field ei_sdp_invalid_sample_rate;
214
static expert_field ei_sdp_invalid_channels;
215
static expert_field ei_sdp_invalid_media_format;
216
static expert_field ei_sdp_invalid_crypto_tag;
217
static expert_field ei_sdp_invalid_crypto_mki_length;
218
219
/* patterns used for tvb_ws_mempbrk_pattern_uint8 */
220
static ws_mempbrk_pattern pbrk_digits;
221
static ws_mempbrk_pattern pbrk_alpha;
222
223
typedef enum {
224
    SDP_PROTO_UNKNOWN = 0,
225
    SDP_PROTO_RTP,
226
    SDP_PROTO_SRTP,
227
    SDP_PROTO_T38,
228
    SDP_PROTO_MSRP,
229
    SDP_PROTO_SPRT,
230
    SDP_PROTO_BFCP,
231
} transport_proto_t;
232
233
234
542
#define SDP_MAX_RTP_CHANNELS 4
235
4
#define SDP_MAX_RTP_PAYLOAD_TYPES 20
236
16.1k
#define SDP_NO_OF_PT 128
237
/*
238
 * All parameters specific to one media description ("m=").
239
 */
240
typedef struct {
241
    int32_t pt[SDP_MAX_RTP_PAYLOAD_TYPES];
242
    int8_t pt_count;
243
    rtp_dyn_payload_t *rtp_dyn_payload;
244
    bool set_rtp;
245
} transport_media_pt_t;
246
247
/*
248
 * Store data extracted from one Media Description section of a SDP. Memory is
249
 * allocated in wmem_file_scope().
250
 */
251
typedef struct {
252
    transport_proto_t proto;    /**< Protocol, parsed from "m=" line. */
253
    uint32_t media_types;        /**< Whether "m=video" or others */
254
    bool bundled;           /**< "m=" lines are "bundled", that is, all on same port */
255
    uint16_t media_port;         /**< Port number, parsed from "m=" line. */
256
    uint16_t control_port;       /**< Port number, parsed from "a=rtcp" or "a=rtcp-mux" line. */
257
    address conn_addr;          /**< The address from the "c=" line (default
258
                                     from session level, possibly overridden at
259
                                     the media level). */
260
    char* control_uri;          /**< RTSP media control URI, parsed from "a=control:"
261
                                     XXX - allowed to default to session level if not
262
                                     overridden if only one media desc, but this is
263
                                     not implemented yet. */
264
    transport_media_pt_t media; /**< Information about payload numbers for this media. */
265
266
    /*
267
     * Media-level only attributes.
268
     */
269
    union {
270
        struct {
271
            address ipaddr;
272
            uint16_t port_number;
273
        } msrp;                 /**< MSRP transport info, parsed from "a=label:" */
274
    } media_attr;
275
} media_description_t;
276
277
/*
278
 * Information parsed from one or two (offer/answer) SDPs that is stored in the
279
 * conversation. The contents are allocated within wmem_file_scope().
280
 */
281
typedef struct {
282
    enum sdp_exchange_type sdp_status;
283
    char  *encoding_name[SDP_NO_OF_PT];
284
    unsigned sample_rate[SDP_NO_OF_PT];
285
    unsigned channels[SDP_NO_OF_PT];
286
287
    /* Data parsed from "m=" */
288
    wmem_array_t *media_descriptions;   /* array of media_description_t */
289
290
    wmem_array_t *sdp_setup_info_list;  /* array of sdp_setup_info_t that refer
291
                                         * to the same RTP conversation */
292
293
    /* SRTP related info XXX note currently we only handle one crypto line in the SDP
294
    * We should probably handle offer/answer and session updates etc(SIP) quite possibly the whole handling of
295
    * setting up the RTP conversations should be done by the signaling protocol(s) calling the SDP dissector
296
    * and the SDP dissector just provide the relevant data.
297
    * YES! packet-sdp.c should be about SDP parsing... SDP *state* needs to be maintained by upper
298
    * protocols, because each one has different rules/semantics.
299
    */
300
    unsigned  encryption_algorithm;
301
    unsigned  auth_algorithm;
302
    unsigned  mki_len;                /* number of octets used for the MKI in the RTP payload */
303
    unsigned  auth_tag_len;           /* number of octets used for the Auth Tag in the RTP payload */
304
} transport_info_t;
305
306
/*
307
 * Information about the session description. These are accumulated while
308
 * parsing the session description and will be applied to the media description.
309
 * Memory scope can be pinfo->pool since the contents are no longer
310
 * needed once they are processed into transport_info_t (via
311
 * complete_descriptions).
312
 */
313
typedef struct {
314
    address conn_addr;         /**< Parsed from "c=" line. */
315
    rtp_dyn_payload_t *rtp_dyn_payload; /**< Parsed from "a=rtpmap:" line.
316
                                             Note: wmem_file_scope, needs manual dealloc. */
317
} session_info_t;
318
319
/* Structure for private data to hold ED137 related values */
320
typedef struct sdp_data_t {
321
  char *ed137_type;           /* Radio session type */
322
  char *ed137_txrxmode;       /* Tx/Rx mode */
323
  char *ed137_fid;            /* Frequency ID */
324
} sdp_data_t;
325
326
327
/* here lie the debugging dumper functions */
328
#ifdef DEBUG_CONVERSATION
329
static void sdp_dump_transport_media(const transport_media_pt_t* media) {
330
    int i;
331
    int count;
332
    DPRINT2(("transport_media contents:"));
333
    DINDENT();
334
        if (!media) {
335
            DPRINT2(("null transport_media_pt_t*"));
336
            DENDENT();
337
            return;
338
        }
339
        count = (int)media->pt_count;
340
        DPRINT2(("pt_count=%d",count));
341
        DINDENT();
342
            for (i=0; i < count; i++) {
343
                DPRINT2(("pt=%d", media->pt[i]));
344
            }
345
        DENDENT();
346
        DPRINT2(("rtp_dyn_payload hashtable=%s", media->rtp_dyn_payload ? "YES" : "NO"));
347
        if (media->rtp_dyn_payload) {
348
            rtp_dump_dyn_payload(media->rtp_dyn_payload);
349
        }
350
        DPRINT2(("set_rtp=%s", media->set_rtp ? "TRUE" : "FALSE"));
351
    DENDENT();
352
}
353
354
static const value_string sdp_exchange_type_vs[] = {
355
    { SDP_EXCHANGE_OFFER,         "SDP_EXCHANGE_OFFER" },
356
    { SDP_EXCHANGE_ANSWER_ACCEPT, "SDP_EXCHANGE_ANSWER_ACCEPT" },
357
    { SDP_EXCHANGE_ANSWER_REJECT, "SDP_EXCHANGE_ANSWER_REJECT" },
358
    { 0, NULL }
359
};
360
361
static void sdp_dump_transport_info(packet_info *pinfo, const transport_info_t* info) {
362
    int i;
363
    int count;
364
    DPRINT2(("transport_info contents:"));
365
    DINDENT();
366
        if (!info) {
367
            DPRINT2(("null transport_info_t*"));
368
            DENDENT();
369
            return;
370
        }
371
        DPRINT2(("sdp_status=%s",
372
                 val_to_str_const(info->sdp_status, sdp_exchange_type_vs, "SDP_EXCHANGE_UNKNOWN")));
373
        DPRINT2(("payload type contents:"));
374
        DINDENT();
375
            for (i=0; i < SDP_NO_OF_PT; i++) {
376
                /* don't print out unknown encodings */
377
                if (info->encoding_name[i] &&
378
                    strcmp(UNKNOWN_ENCODING,info->encoding_name[i]) != 0) {
379
                    DPRINT2(("payload type #%d:",i));
380
                    DINDENT();
381
                        DPRINT2(("encoding_name=%s", info->encoding_name[i]));
382
                        DPRINT2(("sample_rate=%d", info->sample_rate[i]));
383
                    DENDENT();
384
                }
385
            }
386
        DENDENT();
387
        count = wmem_array_get_count(info->media_descriptions);
388
        DPRINT2(("media_count=%d", count));
389
        DPRINT2(("rtp channels:"));
390
        DINDENT();
391
            for (i=0; i < count; i++) {
392
                media_description_t *media_desc = (media_description_t *)wmem_array_index(info->media_descriptions, i);
393
                DPRINT2(("channel #%d:",i));
394
                DINDENT();
395
                    DPRINT2(("conn_addr=%s", address_to_str(pinfo->pool, &(media_desc->conn_addr))));
396
                    DPRINT2(("media_port=%d", media_desc->media_port));
397
                    DPRINT2(("proto=%d", media_desc->proto));
398
                    sdp_dump_transport_media(&(media_desc->media));
399
                DENDENT();
400
            }
401
        DENDENT();
402
        DPRINT2(("encryption_algorithm=%u", info->encryption_algorithm));
403
        DPRINT2(("auth_algorithm=%u", info->auth_algorithm));
404
        if (info->encryption_algorithm || info->auth_algorithm) {
405
            DPRINT2(("mki_len=%u", info->mki_len));
406
            if (info->auth_algorithm) {
407
                DPRINT2(("auth_tag_len=%u", info->auth_tag_len));
408
            }
409
        }
410
    DENDENT();
411
}
412
413
#endif /* DEBUG_CONVERSATION */
414
415
416
/* key-mgmt dissector
417
 * IANA registry:
418
 * http://www.iana.org/assignments/sdp-parameters
419
 */
420
static dissector_table_t key_mgmt_dissector_table;
421
422
/* Finds next token (sequence of non-space chars) in tvb from given offset.
423
 * The returned value is the token length, or 0 if none found.
424
 * The offset is changed to be the starting offset, in case there were one or more
425
 * spaces at the beginning. (this will also add expert info in such a case)
426
 * The next_offset is set to the next found space after the token, or the end
427
 * of the buffer (line) if none found.
428
 *
429
 * The optional param, if true, means no expert error will be issued if no token
430
 * is found; if false then a expert error will be issued if no token is found.
431
 *
432
 * This function expects to be given a tvb of only one line, and does no error
433
 * checking of its given arguments.
434
 */
435
static inline int
436
find_next_optional_token_in_line(tvbuff_t *tvb, proto_tree *tree,
437
                                 unsigned *offset, unsigned *next_offset,
438
                                 const bool optional)
439
3.38k
{
440
3.38k
    unsigned tokenlen = 0;
441
3.38k
    unsigned next_off = tvb_reported_length(tvb);
442
3.38k
    unsigned off      = *offset;
443
444
3.38k
    if (tvb_offset_exists(tvb, off)) {
445
6.98k
        while (tokenlen == 0) {
446
4.99k
            if (!tvb_find_uint8_remaining(tvb, off, ' ', &next_off)) {
447
862
                tokenlen = tvb_captured_length_remaining(tvb, off);
448
862
                break; /* Nothing more left */
449
862
            }
450
451
4.13k
            tokenlen = next_off - off;
452
453
4.13k
            if (tokenlen == 0) {
454
                /* two spaces in a row - illegal, but we'll keep dissecting */
455
2.14k
                proto_tree_add_expert(tree, NULL, &ei_sdp_invalid_line_space, tvb, off-1, 2);
456
2.14k
                off = next_off + 1;
457
2.14k
            }
458
4.13k
        }
459
2.85k
    }
460
461
3.38k
    if (!optional && tokenlen == 0) {
462
629
        proto_tree_add_expert_remaining(tree, NULL, &ei_sdp_invalid_line_fields, tvb, 0);
463
629
    }
464
465
3.38k
    *next_offset = next_off;
466
3.38k
    *offset      = off;
467
3.38k
    return tokenlen;
468
3.38k
}
469
470
/* Same as above, but always issues an expert error if a token is not found. */
471
static inline int
472
find_next_token_in_line(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, unsigned *next_offset)
473
2.48k
{
474
2.48k
    return find_next_optional_token_in_line(tvb, tree, offset, next_offset, false);
475
2.48k
}
476
477
/* Convert the protocol from the "m=" line to something we understand. */
478
static transport_proto_t
479
parse_sdp_media_protocol(const char *media_proto)
480
229
{
481
    /* Sorted according to the "proto" registry at
482
     * https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml#sdp-parameters-2 */
483
229
    const struct {
484
229
        const char *proto_name;
485
229
        transport_proto_t proto;
486
229
    } protocols[] = {
487
229
        { "RTP/AVP",            SDP_PROTO_RTP }, /* RFC 4566 */
488
229
        { "udptl",              SDP_PROTO_T38 }, /* ITU-T T.38, example in Annex E */
489
229
        { "UDPTL",              SDP_PROTO_T38 }, /* Note: IANA registry contains lower case */
490
229
        { "RTP/AVPF",           SDP_PROTO_RTP }, /* RFC 4585 */
491
229
        { "RTP/SAVP",           SDP_PROTO_SRTP }, /* RFC 3711 */
492
229
        { "RTP/SAVPF",          SDP_PROTO_SRTP }, /* RFC 5124 */
493
229
        { "UDP/TLS/RTP/SAVP",   SDP_PROTO_SRTP }, /* RFC 5764 */
494
229
        { "UDP/TLS/RTP/SAVPF",  SDP_PROTO_SRTP }, /* RFC 5764 */
495
229
        { "msrp/tcp",           SDP_PROTO_MSRP }, /* Not in IANA, where is this from? */
496
229
        { "UDPSPRT",            SDP_PROTO_SPRT }, /* Not in IANA, but draft-rajeshkumar-avt-v150-registration-00 */
497
229
        { "udpsprt",            SDP_PROTO_SPRT }, /* lowercase per section E.1.1 of ITU-T V.150.1 */
498
229
        { "udpsprt",            SDP_PROTO_SPRT }, /* lowercase per section E.1.1 of ITU-T V.150.1 */
499
229
        { "UDP/BFCP",           SDP_PROTO_BFCP }, /* RFC 8856 */
500
229
    };
501
502
3.08k
    for (unsigned i = 0; i < G_N_ELEMENTS(protocols); i++) {
503
2.86k
        if (!strcmp(protocols[i].proto_name, media_proto)) {
504
10
            return protocols[i].proto;
505
10
        }
506
2.86k
    }
507
508
219
    return SDP_PROTO_UNKNOWN;
509
229
}
510
511
/* Parses the parts from "c=" into address structures. */
512
static void
513
parse_sdp_connection_address(const char *connection_type, const char *connection_address,
514
        wmem_allocator_t *allocator, address *conn_addr)
515
3
{
516
3
    if (strcmp(connection_type, "IP4") == 0) {
517
0
        uint32_t ip4_addr;
518
519
0
        if (str_to_ip(connection_address, &ip4_addr)) {
520
            /* connection_address could be converted to a valid ipv4 address*/
521
0
            alloc_address_wmem(allocator, conn_addr, AT_IPv4, 4, &ip4_addr);
522
0
        }
523
3
    } else if (strcmp(connection_type, "IP6") == 0) {
524
0
        ws_in6_addr ip6_addr;
525
526
0
        if (str_to_ip6(connection_address, &ip6_addr)) {
527
            /* connection_address could be converted to a valid ipv6 address*/
528
0
            alloc_address_wmem(allocator, conn_addr, AT_IPv6, 16, &ip6_addr);
529
0
        }
530
0
    }
531
3
}
532
533
/**
534
 * Starts a new media description. If there are too many media descriptions,
535
 * no new media description is started and NULL is returned.
536
 */
537
static media_description_t *
538
sdp_new_media_description(wmem_array_t *media_descriptions, session_info_t *session_info)
539
542
{
540
542
    media_description_t empty_desc;
541
542
    media_description_t *media_desc;
542
543
    /* Limit number to avoid consuming excess memory. */
544
542
    if (wmem_array_get_count(media_descriptions) >= SDP_MAX_RTP_CHANNELS) {
545
320
        DPRINT(("Too many media descriptions (more than %d), returning NULL!",
546
320
                wmem_array_get_count(media_descriptions)));
547
320
        return NULL;
548
320
    }
549
550
222
    memset(&empty_desc, 0, sizeof(media_description_t));
551
222
    wmem_array_append_one(media_descriptions, empty_desc);
552
222
    media_desc = (media_description_t *) wmem_array_index(media_descriptions,
553
222
            wmem_array_get_count(media_descriptions) - 1);
554
555
    /* XXX does it make sense making media_desc->media.pt a wmem array? */
556
557
    /* If "c=" is given at the session level, copy it to the media description.
558
     * It will be overridden as needed. */
559
222
    if (session_info->conn_addr.type != AT_NONE) {
560
0
        copy_address_wmem(wmem_file_scope(), &media_desc->conn_addr, &session_info->conn_addr);
561
0
    }
562
563
    /* If "a=rtpmap:" was set on the session level, copy them to media level. */
564
222
    media_desc->media.rtp_dyn_payload =
565
222
        rtp_dyn_payload_dup(session_info->rtp_dyn_payload);
566
567
222
    return media_desc;
568
542
}
569
570
rtp_dyn_payload_t *
571
sdp_get_rtsp_media_desc(const char* control_uri)
572
0
{
573
0
    return wmem_map_lookup(sdp_rtsp_control_map, control_uri);
574
0
}
575
576
/* Remove information about media descriptions which are unused. These appeared
577
 * in the "a=rtpmap:" (and maybe even in the payload types part of "m="?), but
578
 * are not used (port is zero or it was not assigned to RTP dissector). */
579
static void
580
clean_unused_media_descriptions(wmem_array_t *descs)
581
120
{
582
341
    for (unsigned i = 0; i < wmem_array_get_count(descs); i++) {
583
221
        media_description_t *media_desc = (media_description_t *)wmem_array_index(descs, i);
584
585
        /* If not assigned to subdissector, clear the unused information. */
586
221
        if (!media_desc->media.set_rtp) {
587
221
            rtp_dyn_payload_free(media_desc->media.rtp_dyn_payload);
588
221
            media_desc->media.rtp_dyn_payload = NULL;
589
221
        }
590
221
    }
591
120
}
592
593
594
/* Subdissector functions */
595
static void
596
62
dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti) {
597
62
    proto_tree *sdp_owner_tree;
598
62
    unsigned    offset, next_offset, tokenlen;
599
600
62
    offset = 0;
601
602
62
    sdp_owner_tree = proto_item_add_subtree(ti, ett_sdp_owner);
603
604
    /* Find the username */
605
62
    tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
606
62
    if (tokenlen == 0)
607
0
        return;
608
609
62
    proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
610
62
                        ENC_UTF_8);
611
62
    offset = next_offset  + 1;
612
613
    /* Find the session id */
614
62
    tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
615
62
    if (tokenlen == 0)
616
17
        return;
617
618
45
    proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
619
45
                        tokenlen, ENC_UTF_8);
620
45
    offset = next_offset + 1;
621
622
    /* Find the version */
623
45
    tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
624
45
    if (tokenlen == 0)
625
21
        return;
626
627
24
    proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
628
24
                        ENC_UTF_8);
629
24
    offset = next_offset + 1;
630
631
    /* Find the network type */
632
24
    tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
633
24
    if (tokenlen == 0)
634
7
        return;
635
636
17
    proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
637
17
                        tokenlen, ENC_UTF_8);
638
17
    offset = next_offset + 1;
639
640
    /* Find the address type */
641
17
    tokenlen = find_next_token_in_line(tvb, sdp_owner_tree, &offset, &next_offset);
642
17
    if (tokenlen == 0)
643
10
        return;
644
645
7
    proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
646
7
                        tokenlen, ENC_UTF_8);
647
7
    offset = next_offset + 1;
648
649
    /* Find the address */
650
7
    proto_tree_add_item(sdp_owner_tree, hf_owner_address, tvb, offset, -1, ENC_UTF_8);
651
7
}
652
653
/*
654
 * XXX - this can leak memory if an exception is thrown after we've fetched
655
 * a string.
656
 */
657
static void
658
dissect_sdp_connection_info(packet_info *pinfo, tvbuff_t *tvb, proto_item* ti, session_info_t *session_info, media_description_t *media_desc)
659
34
{
660
34
    proto_tree *sdp_connection_info_tree;
661
34
    unsigned    offset, next_offset, tokenlen;
662
34
    const char *connection_type, *connection_address;
663
664
34
    offset = 0;
665
666
34
    sdp_connection_info_tree = proto_item_add_subtree(ti,
667
34
                                                      ett_sdp_connection_info);
668
669
    /* Find the network type */
670
34
    tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset);
671
34
    if (tokenlen == 0)
672
11
        return;
673
674
23
    proto_tree_add_item(sdp_connection_info_tree,
675
23
                        hf_connection_info_network_type, tvb, offset, tokenlen,
676
23
                        ENC_UTF_8);
677
23
    offset = next_offset + 1;
678
679
    /* Find the address type */
680
23
    tokenlen = find_next_token_in_line(tvb, sdp_connection_info_tree, &offset, &next_offset);
681
23
    if (tokenlen == 0)
682
19
        return;
683
684
    /* Save connection address type */
685
4
    proto_tree_add_item_ret_string(sdp_connection_info_tree,
686
4
                        hf_connection_info_address_type, tvb, offset, tokenlen,
687
4
                        ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&connection_type);
688
4
    DPRINT(("parsed connection line type=%s", connection_type));
689
4
    offset = next_offset + 1;
690
691
    /* Find the connection address */
692
    /* XXX - what if there's a <number of addresses> value? */
693
4
    tvb_find_uint8_remaining(tvb, offset, '/', &next_offset);
694
4
    tokenlen = next_offset - offset;
695
    /* Save connection address */
696
4
    connection_address = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
697
698
4
    DPRINT(("parsed connection line address=%s", connection_address));
699
    /* Parse and store connection address. Session-level addresses are
700
     * packet-scoped since they will be cloned in file-scope when needed. */
701
4
    if (session_info) {
702
3
        parse_sdp_connection_address(connection_type, connection_address,
703
3
                pinfo->pool,
704
3
                &session_info->conn_addr);
705
3
    } else if (media_desc) {
706
        /* Clear possibly inherited address from session level. */
707
0
        free_address_wmem(wmem_file_scope(), &media_desc->conn_addr);
708
709
0
        parse_sdp_connection_address(connection_type, connection_address,
710
0
                wmem_file_scope(),
711
0
                &media_desc->conn_addr);
712
0
    }
713
714
4
    proto_tree_add_item(sdp_connection_info_tree,
715
4
                        hf_connection_info_connection_address, tvb, offset,
716
4
                        tokenlen, ENC_UTF_8);
717
4
    if (tvb_captured_length_remaining(tvb, next_offset)) {
718
1
        offset = next_offset + 1;
719
1
        tvb_find_uint8_remaining(tvb, offset, '/', &next_offset);
720
1
        tokenlen = next_offset - offset;
721
1
        proto_tree_add_item(sdp_connection_info_tree,
722
1
                            hf_connection_info_ttl, tvb, offset, tokenlen, ENC_UTF_8);
723
1
        if (tvb_captured_length_remaining(tvb, next_offset)) {
724
0
            offset = next_offset + 1;
725
0
            proto_tree_add_item(sdp_connection_info_tree,
726
0
                                hf_connection_info_num_addr, tvb, offset, -1, ENC_UTF_8);
727
0
        }
728
1
    }
729
4
}
730
731
static void
732
1
dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti) {
733
1
    proto_tree *sdp_bandwidth_tree;
734
1
    unsigned    offset, next_offset, tokenlen;
735
1
    proto_item *item;
736
1
    bool        unit_is_kbs = false;
737
1
    bool        unit_is_bps = false;
738
739
1
    offset = 0;
740
741
1
    sdp_bandwidth_tree = proto_item_add_subtree(ti, ett_sdp_bandwidth);
742
743
    /* find the modifier */
744
1
    if (!tvb_find_uint8_remaining(tvb, offset, ':', &next_offset))
745
1
        return;
746
747
0
    tokenlen = next_offset - offset;
748
749
0
    item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
750
0
                               tokenlen, ENC_UTF_8);
751
0
    if (tvb_strneql(tvb, offset, "CT", 2) == 0) {
752
0
        proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
753
0
        unit_is_kbs = true;
754
0
    } else if (tvb_strneql(tvb, offset, "AS", 2) == 0) {
755
0
        proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
756
0
        unit_is_kbs = true;
757
0
    } else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0) {
758
0
        proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
759
0
        unit_is_bps = true;
760
0
    }
761
762
763
0
    offset = next_offset + 1;
764
765
0
    item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
766
0
                               ENC_UTF_8);
767
0
    if (unit_is_kbs == true)
768
0
        proto_item_append_text(item, " kb/s");
769
0
    if (unit_is_bps == true)
770
0
        proto_item_append_text(item, " b/s");
771
0
}
772
773
0
static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti) {
774
0
    proto_tree *sdp_time_tree;
775
0
    unsigned    offset, next_offset, tokenlen;
776
777
0
    offset = 0;
778
779
0
    sdp_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
780
781
    /* get start time */
782
0
    tokenlen = find_next_token_in_line(tvb, sdp_time_tree, &offset, &next_offset);
783
0
    if (tokenlen == 0)
784
0
        return;
785
786
0
    proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
787
0
                        ENC_UTF_8);
788
789
    /* get stop time */
790
0
    offset = next_offset + 1;
791
0
    proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, ENC_UTF_8);
792
0
}
793
794
147
static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti) {
795
147
    proto_tree *sdp_repeat_time_tree;
796
147
    unsigned    offset, next_offset, tokenlen;
797
147
    bool        optional = false;
798
799
147
    offset = 0;
800
801
147
    sdp_repeat_time_tree = proto_item_add_subtree(ti, ett_sdp_time);
802
803
    /* get interval */
804
147
    tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset);
805
147
    if (tokenlen == 0)
806
0
        return;
807
808
147
    proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
809
147
                        offset, tokenlen, ENC_UTF_8);
810
811
    /* get duration */
812
147
    offset = next_offset + 1;
813
147
    tokenlen = find_next_token_in_line(tvb, sdp_repeat_time_tree, &offset, &next_offset);
814
147
    if (tokenlen == 0)
815
94
        return;
816
817
53
    proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_duration, tvb,
818
53
                        offset, tokenlen, ENC_UTF_8);
819
820
    /* get offsets */
821
108
    do {
822
108
        offset = next_offset +1;
823
108
        tokenlen = find_next_optional_token_in_line(tvb, sdp_repeat_time_tree,
824
108
                                                    &offset, &next_offset, optional);
825
108
        if (tokenlen == 0)
826
31
            break;
827
77
        proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
828
77
                            tvb, offset, tokenlen, ENC_UTF_8);
829
77
        optional = true;
830
77
    } while (tvb_captured_length_remaining(tvb, next_offset));
831
832
53
}
833
834
static void
835
98
dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti) {
836
98
    proto_tree* sdp_timezone_tree;
837
98
    unsigned    offset, next_offset, tokenlen;
838
98
    bool        optional = false;
839
840
98
    offset = 0;
841
842
98
    sdp_timezone_tree = proto_item_add_subtree(ti, ett_sdp_timezone);
843
844
168
    do {
845
168
        tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree,
846
168
                                                    &offset, &next_offset, optional);
847
168
        if (tokenlen == 0)
848
18
            break;
849
850
150
        proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
851
150
                            tokenlen, ENC_UTF_8);
852
150
        offset = next_offset + 1;
853
150
        tokenlen = find_next_optional_token_in_line(tvb, sdp_timezone_tree,
854
150
                                                    &offset, &next_offset, optional);
855
150
        if (tokenlen == 0)
856
44
            break;
857
106
        proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
858
106
                            tokenlen, ENC_UTF_8);
859
106
        offset = next_offset + 1;
860
106
        optional = true;
861
106
    } while (tvb_captured_length_remaining(tvb, next_offset));
862
863
98
}
864
865
866
18
static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti) {
867
18
    proto_tree *sdp_encryption_key_tree;
868
18
    unsigned    offset, next_offset, tokenlen;
869
870
18
    offset = 0;
871
872
18
    sdp_encryption_key_tree = proto_item_add_subtree(ti, ett_sdp_encryption_key);
873
874
18
    if (!tvb_find_uint8_remaining(tvb, offset, ':', &next_offset))
875
12
        return;
876
877
6
    tokenlen = next_offset - offset;
878
879
6
    proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_type,
880
6
                        tvb, offset, tokenlen, ENC_UTF_8);
881
882
6
    offset = next_offset + 1;
883
6
    proto_tree_add_item(sdp_encryption_key_tree, hf_encryption_key_data,
884
6
                        tvb, offset, -1, ENC_UTF_8);
885
6
}
886
887
0
static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
888
0
    char         *data_p      = NULL;
889
0
    const uint8_t *prtcl_id    = NULL;
890
0
    int           len;
891
0
    tvbuff_t     *keymgmt_tvb;
892
0
    int           found_match = 0;
893
0
    proto_tree   *key_tree;
894
0
    unsigned      next_offset;
895
0
    unsigned      offset      = 0;
896
0
    unsigned      tokenlen;
897
898
0
    key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
899
900
0
    tokenlen = find_next_token_in_line(tvb, key_tree, &offset, &next_offset);
901
0
    if (tokenlen == 0)
902
0
        return;
903
904
0
    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);
905
906
0
    offset = next_offset + 1;
907
908
0
    len = tvb_captured_length_remaining(tvb, offset);
909
0
    if (len < 0)
910
0
        return;
911
912
0
    data_p = (char *)tvb_get_string_enc(pinfo->pool, tvb, offset, len, ENC_UTF_8|ENC_NA);
913
0
    keymgmt_tvb = base64_to_tvb(tvb, data_p);
914
0
    add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
915
916
0
    if ((prtcl_id != NULL) && (key_mgmt_dissector_table != NULL)) {
917
0
        found_match = dissector_try_string_with_data(key_mgmt_dissector_table,
918
0
                                           (const char *)prtcl_id,
919
0
                                           keymgmt_tvb, pinfo,
920
0
                                           key_tree, true, NULL);
921
0
    }
922
923
0
    if (found_match) {
924
0
        proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
925
0
                                              keymgmt_tvb, 0, -1, ENC_NA);
926
0
        proto_item_set_hidden(ti2);
927
0
    } else {
928
0
        proto_tree_add_item(key_tree, hf_key_mgmt_data,
929
0
                            keymgmt_tvb, 0, -1, ENC_NA);
930
0
    }
931
932
0
}
933
934
935
0
static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti) {
936
0
    proto_tree   *sdp_session_attribute_tree;
937
0
    unsigned      offset, next_offset, tokenlen;
938
0
    const uint8_t *field_name;
939
940
0
    offset = 0;
941
942
0
    sdp_session_attribute_tree = proto_item_add_subtree(ti,
943
0
                                                        ett_sdp_session_attribute);
944
945
0
    if (!tvb_find_uint8_remaining(tvb, offset, ':', &next_offset))
946
0
        return;
947
948
0
    tokenlen = next_offset - offset;
949
950
0
    proto_tree_add_item_ret_string(sdp_session_attribute_tree, hf_session_attribute_field,
951
0
                        tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, &field_name);
952
953
0
    offset = next_offset + 1;
954
955
0
    if (tvb_captured_length_remaining(tvb, offset) == 0) {
956
0
        expert_add_info(pinfo, ti, &ei_sdp_invalid_line_fields);
957
0
        return;
958
0
    }
959
960
0
    if (strcmp((const char *)field_name, "ipbcp") == 0) {
961
0
        if (!tvb_ws_mempbrk_uint8_remaining(tvb, offset, &pbrk_digits, &offset, NULL))
962
0
            return;
963
964
0
        tokenlen = find_next_token_in_line(tvb, sdp_session_attribute_tree, &offset, &next_offset);
965
0
        if (tokenlen == 0)
966
0
            return;
967
968
0
        proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_version, tvb, offset, tokenlen, ENC_UTF_8);
969
970
0
        if (!tvb_ws_mempbrk_uint8_remaining(tvb, offset, &pbrk_alpha, &offset, NULL))
971
0
            return;
972
973
0
        tvb_find_line_end_remaining(tvb, offset, &tokenlen, &next_offset);
974
975
0
        proto_tree_add_item(sdp_session_attribute_tree, hf_ipbcp_type, tvb, offset, tokenlen, ENC_UTF_8);
976
0
    } else if (strcmp((const char *)field_name, "key-mgmt") == 0) {
977
0
        tvbuff_t   *key_tvb;
978
0
        proto_item *key_ti;
979
980
0
        key_tvb = tvb_new_subset_remaining(tvb, offset);
981
0
        key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, ENC_UTF_8);
982
983
0
        dissect_key_mgmt(key_tvb, pinfo, key_ti);
984
0
    } else {
985
0
        proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
986
0
                            tvb, offset, -1, ENC_UTF_8);
987
0
    }
988
0
}
989
990
991
/* Dissect media description - this is passed the line starting after 'm=', so like one of these:
992
 *    audio 29156 RTP/AVP 18 0
993
 *    video 49170/2 RTP/AVP 31 99
994
 */
995
static void
996
dissect_sdp_media(tvbuff_t *tvb, packet_info* pinfo, proto_item *ti,
997
542
                  media_description_t *media_desc) {
998
542
    proto_tree *sdp_media_tree;
999
542
    unsigned    offset, next_offset, tokenlen, idx;
1000
542
    uint8_t    *media_format;
1001
542
    bool        optional = false;
1002
542
    proto_item *it;
1003
542
    const char *media_type_str;
1004
542
    const char *media_port_str;
1005
542
    const char *media_proto_str;
1006
542
    transport_proto_t transport_proto;
1007
542
    uint16_t    media_port;
1008
542
    bool        media_port_valid;
1009
542
    proto_item *pi;
1010
1011
542
    offset = 0;
1012
1013
    /* Create tree for media session */
1014
542
    sdp_media_tree = proto_item_add_subtree(ti, ett_sdp_media);
1015
1016
542
    tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
1017
542
    if (tokenlen == 0)
1018
10
        return;
1019
1020
    /* Type of media session */
1021
532
    proto_tree_add_item_ret_string(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
1022
532
                        ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&media_type_str);
1023
532
    if (media_desc) {
1024
        /* for RTP statistics (supposedly?) */
1025
215
        if (strcmp(media_type_str, "audio") == 0)
1026
0
            media_desc->media_types |= RTP_MEDIA_AUDIO;
1027
215
        else if (strcmp(media_type_str, "video") == 0)
1028
0
            media_desc->media_types |= RTP_MEDIA_VIDEO;
1029
215
        else
1030
215
            media_desc->media_types |= RTP_MEDIA_OTHER;
1031
215
    }
1032
532
    DPRINT(("parsed media_type=%s", media_type_str));
1033
1034
532
    offset = next_offset + 1;
1035
1036
532
    tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
1037
532
    if (tokenlen == 0)
1038
105
        return;
1039
1040
427
    if (tvb_find_uint8_length(tvb, offset, tokenlen, '/', &next_offset)) {
1041
28
        tokenlen = next_offset - offset;
1042
        /* Save port info */
1043
28
        it = proto_tree_add_item_ret_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen,
1044
28
                                   ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&media_port_str);
1045
28
        DPRINT(("parsed media_port=%s", media_port_str));
1046
28
        if (g_ascii_isdigit(media_port_str[0])) {
1047
26
            proto_item_set_hidden(it);
1048
26
            media_port_valid = ws_strtou16(media_port_str, NULL, &media_port);
1049
26
            pi = proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
1050
26
                                media_port);
1051
26
            if (!media_port_valid)
1052
20
                expert_add_info(pinfo, pi, &ei_sdp_invalid_media_port);
1053
26
            if (media_desc) {
1054
11
                media_desc->media_port = media_port;
1055
11
            }
1056
26
        }
1057
1058
28
        offset = next_offset + 1;
1059
28
        tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
1060
28
        if (tokenlen == 0)
1061
0
            return;
1062
1063
        /* TODO: this puts the (optional) number of ports in the tree, but we don't
1064
           actually use it for building the extra RTP flows, which we should. */
1065
28
        proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
1066
28
                            tokenlen, ENC_UTF_8);
1067
28
        offset = next_offset + 1;
1068
399
    } else {
1069
399
        tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
1070
399
        if (tokenlen == 0)
1071
0
            return;
1072
1073
        /* Save port info */
1074
399
        it = proto_tree_add_item_ret_string(sdp_media_tree, hf_media_port_string, tvb, offset, tokenlen,
1075
399
                                   ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&media_port_str);
1076
399
        DPRINT(("parsed media_port=%s", media_port_str));
1077
399
        if (g_ascii_isdigit(media_port_str[0])) {
1078
201
            proto_item_set_hidden(it);
1079
201
            media_port_valid = ws_strtou16(media_port_str, NULL, &media_port);
1080
201
            pi = proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
1081
201
                                media_port);
1082
201
            if (!media_port_valid)
1083
64
                expert_add_info(pinfo, pi, &ei_sdp_invalid_media_port);
1084
201
            if (media_desc) {
1085
100
                media_desc->media_port = media_port;
1086
100
            }
1087
201
        }
1088
399
        offset = next_offset + 1;
1089
399
    }
1090
1091
427
    tokenlen = find_next_token_in_line(tvb, sdp_media_tree, &offset, &next_offset);
1092
427
    if (tokenlen == 0)
1093
197
        return;
1094
1095
    /* Save port protocol */
1096
230
    proto_tree_add_item_ret_string(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
1097
230
                        ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&media_proto_str);
1098
230
    DPRINT(("parsed media_proto=%s", media_proto_str));
1099
    /* Detect protocol for registering with other dissectors like RTP. */
1100
230
    transport_proto = parse_sdp_media_protocol(media_proto_str);
1101
230
    if (media_desc) {
1102
111
        media_desc->proto = transport_proto;
1103
111
    }
1104
1105
470
    do {
1106
470
        offset = next_offset + 1;
1107
470
        tokenlen = find_next_optional_token_in_line(tvb, sdp_media_tree,
1108
470
                                                    &offset, &next_offset, optional);
1109
470
        if (tokenlen == 0)
1110
108
            break;
1111
1112
        /* RFC 4566: If the <proto> sub-field is "RTP/AVP" or "RTP/SAVP" the
1113
         * <fmt> sub-fields contain RTP payload type numbers. */
1114
362
        if (transport_proto == SDP_PROTO_RTP || transport_proto == SDP_PROTO_SRTP) {
1115
43
            media_format = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1116
43
            if (g_ascii_isdigit(media_format[0])) {
1117
21
                proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
1118
21
                                      tokenlen, val_to_str_ext(pinfo->pool, (uint32_t)strtoul((char*)media_format, NULL, 10), &rtp_payload_type_vals_ext, "%u"));
1119
1120
21
                if (media_desc) {
1121
4
                    idx = media_desc->media.pt_count;
1122
4
                    media_desc->media.pt[idx] = (int32_t)strtol((char*)media_format, NULL, 10);
1123
4
                    DPRINT(("parsed media codec pt=%d", media_desc->media.pt[idx]));
1124
4
                    if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
1125
4
                        media_desc->media.pt_count++;
1126
4
                }
1127
22
            } else {
1128
22
                proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
1129
22
                                    tokenlen, ENC_UTF_8);
1130
22
            }
1131
319
        } else {
1132
319
            proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
1133
319
                                tokenlen, ENC_UTF_8);
1134
319
        }
1135
362
        optional = true;
1136
362
    } while (tvb_captured_length_remaining(tvb, next_offset));
1137
1138
    /* XXX Dissect traffic to "Port" as "Protocol"
1139
     *     Remember this Port/Protocol pair so we can tear it down again later
1140
     *     Actually, it's harder than that:
1141
     *         We need to find out the address of the other side first and it
1142
     *         looks like that info can be found in SIP headers only.
1143
     */
1144
1145
230
}
1146
1147
static tvbuff_t *
1148
ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, char *msg)
1149
0
{
1150
0
    size_t nbytes;
1151
0
    uint8_t *buf = convert_string_to_hex(msg, &nbytes);
1152
0
    if (buf) {
1153
0
        tvbuff_t *bytes_tvb;
1154
1155
0
        bytes_tvb = tvb_new_child_real_data(tvb, buf, (unsigned)nbytes, (unsigned)nbytes);
1156
0
        tvb_set_free_cb(bytes_tvb, g_free);
1157
0
        add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
1158
0
        return bytes_tvb;
1159
0
    }
1160
0
    return NULL;
1161
0
}
1162
1163
/* Annex X Profiles and levels definition */
1164
static const value_string h263_profile_vals[] =
1165
{
1166
    { 0,    "Baseline Profile" },
1167
    { 1,    "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
1168
    { 2,    "Version 1 Backward-Compatibility Profile" },
1169
    { 3,    "Version 2 Interactive and Streaming Wireless Profile" },
1170
    { 4,    "Version 3 Interactive and Streaming Wireless Profile" },
1171
    { 5,    "Conversational High Compression Profile" },
1172
    { 6,    "Conversational Internet Profile" },
1173
    { 7,    "Conversational Interlace Profile" },
1174
    { 8,    "High Latency Profile" },
1175
    { 0, NULL },
1176
};
1177
1178
1179
/* RFC 4629 The level are described in table X.2 of H.263 annex X */
1180
static const value_string h263_level_vals[] =
1181
{
1182
    { 10,    "QCIF (176 x 144), 1 x 64Kb/s" },
1183
    { 20,    "CIF (352 x 288), 2 x 64Kb/s" },
1184
    { 30,    "CIF (352 x 288), 6 x 64Kb/s" },
1185
    { 40,    "CIF (352 x 288), 32 x 64Kb/s" },
1186
    { 45,    "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
1187
    { 50,    "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
1188
    { 60,    "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
1189
    { 70,    "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
1190
    { 0, NULL },
1191
};
1192
1193
1194
static const value_string h264_packetization_mode_vals[] =
1195
{
1196
    { 0,    "Single NAL mode" },
1197
    { 1,    "Non-interleaved mode" },
1198
    { 2,    "Interleaved mode" },
1199
    { 0, NULL },
1200
};
1201
1202
/*
1203
 * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
1204
 */
1205
static void
1206
0
decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, unsigned offset, unsigned tokenlen, uint8_t pt, transport_info_t *transport_info, rtp_dyn_payload_t *rtp_dyn_payload) {
1207
0
  unsigned             next_offset;
1208
0
  unsigned             end_offset;
1209
0
  char                *field_name;
1210
0
  char                *format_specific_parameter;
1211
0
  proto_item          *item;
1212
0
  tvbuff_t * volatile  data_tvb;
1213
1214
0
  const char *mime_type = transport_info->encoding_name[pt];
1215
0
  end_offset = offset + tokenlen;
1216
1217
#if 0
1218
    proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
1219
    tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII));
1220
#endif
1221
1222
    /* Look for an '=' within this string - RFC 4855 suggests that parameters
1223
       be "parameter=value" pairs. We'll store them in a hash map from the
1224
       parameter name to the value, as well as dissect some of them here,
1225
       depending on the media type.
1226
     */
1227
0
    if (!tvb_find_uint8_length(tvb, offset, tokenlen, '=', &next_offset))
1228
0
    {
1229
        /* Some media types, like telephone-event and RED, don't have the
1230
         * "parameter=value" syntax:
1231
         * https://datatracker.ietf.org/doc/html/rfc4733
1232
         * 2.4.1. "Relationship to SDP"
1233
         * "The "events" media type parameter deviates from the convention
1234
         * suggested in RFC 3555 because it omits the string "events=" before
1235
         * the list of supported events."
1236
         * https://www.iana.org/assignments/media-types/audio/RED
1237
         * We'll handle them with the empty string as the parameter name.
1238
         * The media types should know how to deal with that, if necessary.
1239
         */
1240
0
        field_name = wmem_strdup(pinfo->pool, "");
1241
0
    } else {
1242
        /* Find the name of the parameter */
1243
0
        tokenlen = next_offset - offset;
1244
0
        field_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8);
1245
1246
#if 0
1247
        proto_tree_add_debug(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
1248
#endif
1249
1250
        /* Move past the '=' */
1251
0
        offset = next_offset + 1;
1252
0
    }
1253
1254
    /* Get the value */
1255
0
    tokenlen = end_offset - offset;
1256
0
    format_specific_parameter = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8);
1257
1258
0
    if (rtp_dyn_payload) {
1259
0
        rtp_dyn_payload_add_fmtp(rtp_dyn_payload, pt,
1260
0
                                 field_name,
1261
0
                                 format_specific_parameter);
1262
0
    }
1263
1264
    /* Dissect the MPEG4 profile-level-id parameter if present */
1265
0
    if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0)) {
1266
0
        if (strcmp((char*)field_name, "profile-level-id") == 0) {
1267
0
            item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
1268
0
                                       (uint32_t)strtol((char*)format_specific_parameter, NULL, 10));
1269
0
            proto_item_set_generated(item);
1270
0
        } else if (strcmp((char*)field_name, "config") == 0) {
1271
0
            data_tvb = ascii_bytes_to_tvb(tvb, pinfo, format_specific_parameter);
1272
0
            if (mp4ves_config_handle && data_tvb) {
1273
0
                call_dissector(mp4ves_config_handle, data_tvb, pinfo, tree);
1274
0
            }
1275
0
        }
1276
0
    }
1277
1278
    /* Dissect the H263-2000 profile parameter if present */
1279
0
    if (((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-2000") == 0)) ||
1280
0
        ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H263-1998") == 0))) {
1281
0
        if (strcmp((char*)field_name, "profile") == 0) {
1282
0
            item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
1283
0
                                       (uint32_t)strtol((char*)format_specific_parameter, NULL, 10));
1284
0
            proto_item_set_generated(item);
1285
0
        } else if (strcmp((char*)field_name, "level") == 0) {
1286
0
            item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
1287
0
                                       (uint32_t)strtol((char*)format_specific_parameter, NULL, 10));
1288
0
            proto_item_set_generated(item);
1289
0
        }
1290
0
    }
1291
1292
1293
    /* Dissect the H264 profile-level-id parameter
1294
     * RFC 3984:
1295
     * A base16 [6] (hexadecimal) representation of
1296
     * the following three bytes in the sequence
1297
     * parameter set NAL unit specified in [1]: 1)
1298
     * profile_idc, 2) a byte herein referred to as
1299
     * profile-iop, composed of the values of
1300
     * constraint_set0_flag, constraint_set1_flag,
1301
     * constraint_set2_flag, and reserved_zero_5bits
1302
     * in bit-significance order, starting from the
1303
     * most significant bit, and 3) level_idc.
1304
     */
1305
0
    if ((mime_type != NULL) && ((g_ascii_strcasecmp(mime_type, "H264") == 0) || (g_ascii_strcasecmp(mime_type, "H264-SVC") == 0))) {
1306
0
        if (strcmp(field_name, "profile-level-id") == 0) {
1307
0
            int length = 0;
1308
1309
0
            data_tvb = ascii_bytes_to_tvb(tvb, pinfo, format_specific_parameter);
1310
0
            if (!data_tvb) {
1311
0
                proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes", format_specific_parameter);
1312
0
                return;
1313
0
            }
1314
0
            length = tvb_reported_length(data_tvb);
1315
0
            if (length == 3) {
1316
0
                if (h264_handle && data_tvb) {
1317
0
                    dissect_h264_profile(data_tvb, pinfo, tree);
1318
0
                }
1319
0
            } else {
1320
0
                item = proto_tree_add_expert_format(tree, pinfo, &ei_sdp_invalid_conversion, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
1321
0
                proto_item_set_generated(item);
1322
0
            }
1323
0
        } else if (strcmp(field_name, "packetization-mode") == 0) {
1324
0
            item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
1325
0
                                       (uint32_t)strtol((char*)format_specific_parameter, NULL, 10));
1326
0
            proto_item_set_generated(item);
1327
0
        } else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
1328
            /* The value of the parameter is the
1329
               base64 [6] representation of the initial
1330
               parameter set NAL units as specified in
1331
               sections 7.3.2.1 and 7.3.2.2 of [1].  The
1332
               parameter sets are conveyed in decoding order,
1333
               and no framing of the parameter set NAL units
1334
               takes place.  A comma is used to separate any
1335
               pair of parameter sets in the list.
1336
            */
1337
0
            const char *data_p = NULL;
1338
0
            unsigned comma_offset;
1339
1340
0
            tvb_find_uint8_length(tvb, offset, end_offset - offset, ',', &comma_offset);
1341
0
            tokenlen = comma_offset - offset;
1342
1343
0
            proto_tree_add_item_ret_string(tree, hf_sdp_nal_unit_1_string, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&data_p);
1344
1345
0
            data_tvb = base64_to_tvb(tvb, data_p);
1346
0
            add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
1347
1348
0
            if (h264_handle && data_tvb) {
1349
0
                TRY {
1350
0
                    dissect_h264_nal_unit(data_tvb, pinfo, tree);
1351
0
                }
1352
0
                CATCH_NONFATAL_ERRORS {
1353
0
                    show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
1354
0
                }
1355
0
                ENDTRY;
1356
0
                if (comma_offset < end_offset) {
1357
                    /* Second NAL unit */
1358
0
                    offset   = comma_offset +1;
1359
0
                    tokenlen = end_offset - offset;
1360
0
                    proto_tree_add_item_ret_string(tree, hf_sdp_nal_unit_2_string, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&data_p);
1361
0
                    data_tvb = base64_to_tvb(tvb, data_p);
1362
0
                    add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
1363
0
                    dissect_h264_nal_unit(data_tvb, pinfo, tree);
1364
0
                }
1365
0
            }
1366
0
        }
1367
0
    }
1368
1369
    /* Dissect the H265
1370
    * RFC 7798:
1371
    */
1372
0
    else if ((mime_type != NULL) && (g_ascii_strcasecmp(mime_type, "H265") == 0)) {
1373
0
        if (strcmp(field_name, "sprop-vps") == 0 || strcmp(field_name, "sprop-sps") == 0 || strcmp(field_name, "sprop-pps") == 0) {
1374
1375
0
            data_tvb = base64_to_tvb(tvb, format_specific_parameter);
1376
0
            add_new_data_source(pinfo, data_tvb, field_name);
1377
0
            if (h265_handle && data_tvb) {
1378
0
                dissect_h265_format_specific_parameter(tree, data_tvb, pinfo);
1379
0
            }
1380
0
        }
1381
0
    }
1382
1383
0
}
1384
1385
static const string_string ice_candidate_types[] = {
1386
    { "host",       "Host candidate" },
1387
    { "srflx",      "Server reflexive candidate" },
1388
    { "prflx",      "Peer reflexive candidate" },
1389
    { "relay",      "Relayed candidate" },
1390
    { NULL, NULL }
1391
};
1392
1393
static void
1394
dissect_sdp_media_attribute_candidate(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset)
1395
0
{
1396
    /* RFC 5245 (ICE): "The candidate attribute is a media-level attribute
1397
     * only. It contains a transport address for a candidate that can be
1398
     * used for connectivity checks."
1399
     * https://tools.ietf.org/html/rfc5245#section-15.1
1400
     *
1401
     *   candidate-attribute   = "candidate" ":" foundation SP component-id SP
1402
     *                           transport SP
1403
     *                           priority SP
1404
     *                           connection-address SP     ;from RFC 4566
1405
     *                           port         ;port from RFC 4566
1406
     *                           SP cand-type
1407
     *                           [SP rel-addr]
1408
     *                           [SP rel-port]
1409
     *                           *(SP extension-att-name SP
1410
     *                                extension-att-value)
1411
     *
1412
     * Example: "candidate:0 1 UDP 2122252543 10.9.0.2 60299 typ host"
1413
     */
1414
0
    proto_item   *pi;
1415
0
    unsigned      next_offset, tokenlen;
1416
0
    const char   *candidate_type;
1417
1418
    /* foundation: between 1 and 32 "ICE chars" (ALPHA / DIGIT / "+" / "/") */
1419
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1420
0
    if (tokenlen == 0)
1421
0
        return;
1422
0
    proto_tree_add_item(tree, hf_ice_candidate_foundation,
1423
0
            tvb, offset, tokenlen, ENC_ASCII);
1424
0
    offset = next_offset + 1;
1425
1426
    /* component-id: integer between 1 and 256.
1427
     * For RTP, 1 MUST be RTP and 2 MUST be RTCP (RFC 5245) */
1428
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1429
0
    if (tokenlen == 0)
1430
0
        return;
1431
0
    proto_tree_add_item(tree, hf_ice_candidate_componentid,
1432
0
            tvb, offset, tokenlen, ENC_ASCII);
1433
0
    offset = next_offset + 1;
1434
1435
    /* transport: "UDP", etc. */
1436
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1437
0
    if (tokenlen == 0)
1438
0
        return;
1439
0
    proto_tree_add_item(tree, hf_ice_candidate_transport,
1440
0
            tvb, offset, tokenlen, ENC_ASCII);
1441
0
    offset = next_offset + 1;
1442
1443
    /* priority: integer between 1 and 2^31-1 */
1444
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1445
0
    if (tokenlen == 0)
1446
0
        return;
1447
0
    proto_tree_add_item(tree, hf_ice_candidate_priority,
1448
0
            tvb, offset, tokenlen, ENC_ASCII);
1449
0
    offset = next_offset + 1;
1450
1451
    /* connection-address: IPv4, IPv6 address or FQDN. */
1452
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1453
0
    if (tokenlen == 0)
1454
0
        return;
1455
0
    proto_tree_add_item(tree, hf_ice_candidate_address,
1456
0
            tvb, offset, tokenlen, ENC_ASCII);
1457
0
    offset = next_offset + 1;
1458
1459
    /* port */
1460
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1461
0
    if (tokenlen == 0)
1462
0
        return;
1463
0
    proto_tree_add_item(tree, hf_ice_candidate_port,
1464
0
            tvb, offset, tokenlen, ENC_ASCII);
1465
0
    offset = next_offset + 1;
1466
1467
    /* cand-type: type of candidate (where it learned the candidate)
1468
     * Check for "typ " in "typ host" and skip it. */
1469
0
    if (tvb_strneql(tvb, offset, "typ ", 4))
1470
0
        return;
1471
0
    offset += 4;
1472
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1473
0
    if (tokenlen == 0)
1474
0
        return;
1475
0
    pi = proto_tree_add_item_ret_string(tree, hf_ice_candidate_type,
1476
0
            tvb, offset, tokenlen, ENC_ASCII|ENC_NA,
1477
0
            pinfo->pool, (const uint8_t**)&candidate_type);
1478
0
    if ((candidate_type = try_str_to_str(candidate_type, ice_candidate_types))) {
1479
0
        proto_item_append_text(pi, " (%s)", candidate_type);
1480
0
    }
1481
    /* offset = next_offset + 1; */
1482
1483
    /* Ignored: [rel-addr] [rel-port] *(extension-att-name extension-att-value) */
1484
0
}
1485
1486
typedef struct {
1487
  const char *name;
1488
} sdp_names_t;
1489
1490
0
#define SDP_RTPMAP              1
1491
0
#define SDP_FMTP                2
1492
0
#define SDP_PATH                3
1493
0
#define SDP_H248_ITEM           4
1494
0
#define SDP_CRYPTO              5
1495
#define SDP_SPRTMAP             6
1496
0
#define SDP_CANDIDATE           7
1497
0
#define SDP_ED137_TYPE          8
1498
0
#define SDP_ED137_TXRXMODE      9
1499
0
#define SDP_ED137_FID           10
1500
0
#define SDP_RTCP                11
1501
0
#define SDP_RTCP_MUX            12
1502
0
#define SDP_CONTROL             13
1503
1504
static const sdp_names_t sdp_media_attribute_names[] = {
1505
    { "Unknown-name"},    /* 0 Pad so that the real headers start at index 1 */
1506
    { "rtpmap"},          /* 1 */
1507
    { "fmtp"},            /* 2 */
1508
    { "path"},            /* 3 */
1509
    { "h248item"},        /* 4 */
1510
    { "crypto"},          /* 5 */
1511
    { "sprt"},            /* 6 */
1512
    { "candidate" },      /* 7 */
1513
    { "type" },           /* 8 */
1514
    { "txrxmode" },       /* 9 */
1515
    { "fid" },            /* 10 */
1516
    { "rtcp" },           /* 11 */
1517
    { "rtcp-mux" },       /* 12 */
1518
    { "control" },        /* 13 */
1519
};
1520
1521
static int find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, unsigned len)
1522
0
{
1523
0
    unsigned i;
1524
1525
0
    for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
1526
0
        if ((len == strlen(sdp_media_attribute_names[i].name)) &&
1527
0
            (tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0))
1528
0
            return i;
1529
0
    }
1530
1531
0
    return -1;
1532
0
}
1533
1534
/* A few protocols give the fmtp parameter as a string instead of a
1535
 * numeric payload type, list them here (lower case for comparison).
1536
 */
1537
static const string_string media_format_str_types[] = {
1538
    /* ETSI TS 102 472, ETSI TS 102 592 */
1539
    { "ipdc-kmm", "IP Datacast Key Management Message"},
1540
    { "ipdc-ksm", "IP Datacast Key Stream Message"},
1541
    /* ETSI TS 124 380 */
1542
    { "mcptt",    "Mission Critical Push To Talk"},
1543
    /* ETSI TS 124 581 */
1544
    { "mcvideo",  "Mission Critical Video"},
1545
    /* ETSI TS 124 582 */
1546
    { "mcdata",  "Mission Critical Data"},
1547
    /* OMA PoC Control Plane */
1548
    { "tbcp",     "Talk Burst Control Protocol"},
1549
    { NULL, NULL }
1550
};
1551
1552
static void
1553
dissect_sdp_media_attribute_rtpmap(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned length,
1554
                                   transport_info_t *transport_info, session_info_t *session_info,
1555
                                   media_description_t *media_desc, unsigned offset)
1556
0
{
1557
0
    unsigned      next_offset, tokenlen;
1558
0
    const char   *payload_type;
1559
0
    proto_item   *pi;
1560
0
    uint8_t       pt;
1561
1562
    /* RFC 8866 6.6 rtpmap
1563
       Syntax:
1564
          rtpmap-value = payload-type SP encoding-name
1565
          "/" clock-rate [ "/" encoding-params ]
1566
          payload-type = zero-based-integer
1567
          encoding-name = token
1568
          clock-rate = integer
1569
          encoding-params = channels
1570
          channels = integer
1571
     */
1572
0
    if (!tvb_find_uint8_remaining(tvb, offset, ' ', &next_offset))
1573
0
        return;
1574
1575
0
    tokenlen = next_offset - offset;
1576
1577
0
    proto_tree_add_item_ret_string(tree, hf_media_format, tvb,
1578
0
                                   offset, tokenlen, ENC_UTF_8|ENC_NA, pinfo->pool,
1579
0
                                   (const uint8_t**)&payload_type);
1580
1581
0
    offset = next_offset + 1;
1582
1583
0
    if (!tvb_find_uint8_remaining(tvb, offset, '/', &next_offset)) {
1584
0
        return;
1585
0
    }
1586
1587
0
    tokenlen = next_offset - offset;
1588
1589
0
    proto_tree_add_item(tree, hf_media_encoding_name, tvb,
1590
0
                        offset, tokenlen, ENC_UTF_8);
1591
1592
0
    if (!ws_strtou8(payload_type, NULL, &pt) || pt >= SDP_NO_OF_PT) {
1593
0
        return;   /* Invalid */
1594
0
    }
1595
1596
    /* String is file scope allocated because transport_info is connection related */
1597
0
    transport_info->encoding_name[pt] = (char*)tvb_get_string_enc(wmem_file_scope(), tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1598
1599
0
    offset = next_offset + 1;
1600
1601
0
    tvb_find_uint8_length(tvb, offset, length - offset, '/', &next_offset);
1602
1603
0
    tokenlen = next_offset - offset;
1604
0
    pi = proto_tree_add_item(tree, hf_media_sample_rate, tvb,
1605
0
                             offset, tokenlen, ENC_UTF_8);
1606
0
    transport_info->sample_rate[pt] = 0;
1607
0
    if (!ws_strtou32((char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA),
1608
0
                     NULL, &transport_info->sample_rate[pt])) {
1609
0
        expert_add_info(pinfo, pi, &ei_sdp_invalid_sample_rate);
1610
0
    } else if (!strcmp(transport_info->encoding_name[pt], "G722")) {
1611
        // The reported sampling rate is 8000, but the actual value is
1612
        // 16kHz. https://tools.ietf.org/html/rfc3551#section-4.5.2
1613
0
        proto_item_append_text(pi, " (RTP clock rate is 8kHz, actual sampling rate is 16kHz)");
1614
0
    }
1615
1616
0
    transport_info->channels[pt] = 1;
1617
0
    if (media_desc && media_desc->media_types & RTP_MEDIA_AUDIO) {
1618
0
        if (next_offset < length) {
1619
0
            offset = next_offset + 1;
1620
0
            tokenlen = length - offset;
1621
0
            pi = proto_tree_add_item(tree, hf_media_channels, tvb,
1622
0
                                     offset, tokenlen, ENC_UTF_8);
1623
0
            if (!ws_strtou32((char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA),
1624
0
                             NULL, &transport_info->channels[pt])) {
1625
0
                expert_add_info(pinfo, pi, &ei_sdp_invalid_channels);
1626
0
            }
1627
0
        }
1628
0
    }
1629
    /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1630
       For example:
1631
1632
       a=rtpmap:101 G726-32/8000
1633
       m=audio 49170 RTP/AVP 0 97
1634
       a=rtpmap:97 telephone-event/8000
1635
       m=audio 49172 RTP/AVP 97 101
1636
       a=rtpmap:97 G726-24/8000
1637
1638
       The Media attributes ("a="s) after the "m=" only apply for that "m=".
1639
       If there is an "a=" before the first "m=", that attribute applies for
1640
       all the session (all the "m="s).
1641
    */
1642
1643
0
    if (session_info) {
1644
        /* If this "a=" appear before any "m=", we add it to the session
1645
         * info, these will be added later to all media (via
1646
         * sdp_new_media_description).
1647
         *
1648
         * NOTE: This should not happen, because rtpmap is Usage Level: media
1649
         * (RFC 8866 6.6, also RFC 4566 6, and heavily implied by RFC 2327)
1650
         */
1651
0
        rtp_dyn_payload_insert(session_info->rtp_dyn_payload,
1652
0
                               pt,
1653
0
                               transport_info->encoding_name[pt],
1654
0
                               transport_info->sample_rate[pt],
1655
0
                               transport_info->channels[pt]);
1656
0
    } else if (media_desc) {
1657
        /* if the "a=" is after an "m=", only apply to this "m=" */
1658
0
        rtp_dyn_payload_insert(media_desc->media.rtp_dyn_payload,
1659
0
                               pt,
1660
0
                               transport_info->encoding_name[pt],
1661
0
                               transport_info->sample_rate[pt],
1662
0
                               transport_info->channels[pt]);
1663
0
    }
1664
0
}
1665
1666
static void
1667
dissect_sdp_media_attribute_fmtp(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
1668
                                 transport_info_t *transport_info, session_info_t *session_info,
1669
                                 media_description_t *media_desc, unsigned offset)
1670
0
{
1671
0
    unsigned      next_offset, tokenlen;
1672
0
    proto_item   *fmtp_item, *media_format_item;
1673
0
    const char   *payload_type;
1674
0
    const char   *media_format_str;
1675
0
    proto_tree   *fmtp_tree;
1676
0
    bool          has_more_pars      = true;
1677
    /* Reading the Format parameter(fmtp) */
1678
0
    uint8_t       media_format;
1679
1680
    /* Skip leading space, if any */
1681
0
    offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
1682
    /* Media format extends to the next space */
1683
0
    if (!tvb_find_uint8_remaining(tvb, offset, ' ', &next_offset))
1684
0
        return;
1685
1686
0
    tokenlen = next_offset - offset;
1687
1688
0
    media_format_item = proto_tree_add_item_ret_string(tree, hf_media_format, tvb,
1689
0
                                                       offset, tokenlen, ENC_UTF_8 | ENC_NA, pinfo->pool,
1690
0
                                                       (const uint8_t**)&payload_type);
1691
1692
    /* Append encoding name to format if known */
1693
0
    payload_type = wmem_ascii_strdown(pinfo->pool, payload_type, -1);
1694
0
    media_format = 0;
1695
0
    if ((media_format_str = try_str_to_str(payload_type, media_format_str_types))) {
1696
1697
0
        proto_item_append_text(media_format_item, " [%s]",
1698
0
                               media_format_str);
1699
0
    } else if (ws_strtou8(payload_type, NULL, &media_format) && media_format < SDP_NO_OF_PT) {
1700
0
        if (media_format) {
1701
0
            proto_item_append_text(media_format_item, " [%s]",
1702
0
                                   transport_info->encoding_name[media_format]);
1703
0
        }
1704
0
    } else {
1705
0
        expert_add_info(pinfo, media_format_item, &ei_sdp_invalid_media_format);
1706
0
        return;
1707
0
    }
1708
1709
1710
#if 0 /* XXX:  ?? */
1711
    payload_type = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);
1712
#endif
1713
    /* Move offset past the payload type */
1714
0
    offset = next_offset + 1;
1715
1716
0
    while (has_more_pars == true) {
1717
0
        offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
1718
1719
0
        if (!tvb_find_uint8_remaining(tvb, offset, ';', &next_offset)) {
1720
0
            has_more_pars = false;
1721
0
            next_offset = tvb_captured_length(tvb);
1722
0
        }
1723
1724
        /* There are at least 2 - add the first parameter */
1725
0
        tokenlen = next_offset - offset;
1726
0
        fmtp_item = proto_tree_add_item(tree, hf_media_format_specific_parameter, tvb,
1727
0
                                        offset, tokenlen, ENC_UTF_8);
1728
1729
0
        fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
1730
1731
0
        rtp_dyn_payload_t *rtp_dyn_payload = NULL;
1732
0
        if (session_info) {
1733
0
            rtp_dyn_payload = session_info->rtp_dyn_payload;
1734
0
        } else if (media_desc) {
1735
0
            rtp_dyn_payload = media_desc->media.rtp_dyn_payload;
1736
0
        }
1737
0
        decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
1738
0
                        media_format, transport_info, rtp_dyn_payload);
1739
1740
        /* Move offset past "; " and onto first char */
1741
0
        offset = next_offset + 1;
1742
0
    }
1743
0
}
1744
1745
static void
1746
dissect_sdp_media_attribute_path(packet_info *pinfo, tvbuff_t *tvb, char *attribute_value,
1747
                                 media_description_t *media_desc, const char *msrp_res, unsigned offset)
1748
0
{
1749
    /* msrp attributes that contain address needed for conversation */
1750
    /*    RFC 4975
1751
     *    path = path-label ":" path-list
1752
     *    path-label = "path"
1753
     *    path-list= MSRP-URI *(SP MSRP-URI)
1754
     *    MSRP-URI = msrp-scheme "://" authority
1755
     *       ["/" session-id] ";" transport *( ";" URI-parameter)
1756
     *                        ; authority as defined in RFC3986
1757
     *
1758
     *    msrp-scheme = "msrp" / "msrps"
1759
     * RFC 3986
1760
     * The authority component is preceded by a double slash ("//") and is terminated by
1761
     * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1762
     * the end of the URI.
1763
     */
1764
1765
    /* Check for "msrp://" */
1766
0
    if (strncmp(attribute_value, msrp_res, strlen(msrp_res)) == 0 && msrp_handle &&
1767
0
        media_desc && media_desc->proto == SDP_PROTO_MSRP) {
1768
0
        unsigned address_offset, port_offset, port_end_offset;
1769
1770
        /* Address starts here */
1771
0
        address_offset = offset + (unsigned)strlen(msrp_res);
1772
1773
        /* Port is after next ':' */
1774
        /* Check if port is present, if not skip */
1775
0
        if (tvb_find_uint8_remaining(tvb, address_offset, ':', &port_offset)) {
1776
            /* Port ends with '/' */
1777
0
            if (!tvb_find_uint8_remaining(tvb, port_offset, '/', &port_end_offset)) {
1778
                /* No "/" look for the ";" */
1779
0
                tvb_find_uint8_remaining(tvb, port_offset, ';', &port_end_offset);
1780
0
            }
1781
            /* Attempt to convert address */
1782
0
            uint32_t msrp_ipaddr;
1783
0
            uint16_t msrp_port_number;
1784
0
            if (str_to_ip((char*)tvb_get_string_enc(pinfo->pool, tvb, address_offset, port_offset-address_offset, ENC_UTF_8|ENC_NA),
1785
0
                          &msrp_ipaddr)) {
1786
                /* Get port number */
1787
0
                if (ws_strtou16((char*)tvb_get_string_enc(pinfo->pool, tvb, port_offset + 1,
1788
0
                                                   port_end_offset - port_offset - 1, ENC_UTF_8|ENC_NA), NULL, &msrp_port_number)) {
1789
                    /* Port and address are usable, store for later use in
1790
                     * complete_descriptions (overrides the "c=" address). */
1791
0
                    alloc_address_wmem(wmem_file_scope(), &media_desc->media_attr.msrp.ipaddr, AT_IPv4, 4, &msrp_ipaddr);
1792
0
                    media_desc->media_attr.msrp.port_number = msrp_port_number;
1793
0
                }
1794
0
            }
1795
0
        }
1796
0
    }
1797
0
}
1798
1799
static void
1800
dissect_sdp_media_attribute_h248_item(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
1801
                                      char *attribute_value, const char *msrp_res)
1802
0
{
1803
0
    const char   *h324ext_h223lcparm = "h324ext/h223lcparm";
1804
0
    tvbuff_t     *h245_tvb;
1805
1806
0
    if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0) {
1807
        /* A.5.1.3 H.223 Logical channel parameters
1808
         * This property indicates the H.245
1809
         * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1810
         * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1811
         * in ITU-T Rec. H.248.15 is used.
1812
         *
1813
         * H.248.15 6 IANA considerations
1814
         * The format of the Package attribute is as below:
1815
         *     a=h248item:<package name>/<property name> = <value>
1816
         */
1817
0
        asn1_ctx_t actx;
1818
1819
0
        attribute_value = strchr(attribute_value, '=');
1820
0
        if (!attribute_value) {
1821
0
            return;
1822
0
        }
1823
1824
0
        h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, ++attribute_value);
1825
        /* should go through a handle, however,  the two h245 entry
1826
           points are different, one is over tpkt and the other is raw
1827
        */
1828
0
        if (h245_tvb) {
1829
0
            asn1_ctx_init(&actx, ASN1_ENC_PER, true, pinfo);
1830
0
            dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx,
1831
0
                                                      tree,hf_SDPh223LogicalChannelParameters);
1832
0
        }
1833
0
    }
1834
0
}
1835
1836
static void
1837
dissect_sdp_media_attribute_crypto(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
1838
                                   transport_info_t *transport_info, unsigned offset)
1839
0
{
1840
    /* https://tools.ietf.org/html/rfc4568
1841
    * 9.1.  Generic "Crypto" Attribute Grammar
1842
    *
1843
    *   The ABNF grammar for the crypto attribute is defined below:
1844
    *
1845
    *   "a=crypto:" tag 1*WSP crypto-suite 1*WSP key-params
1846
    *                                           *(1*WSP session-param)
1847
    *
1848
    *   tag              = 1*9DIGIT
1849
    *   crypto-suite     = 1*(ALPHA / DIGIT / "_")
1850
    *
1851
    *   key-params       = key-param *(";" key-param)
1852
    *   key-param        = key-method ":" key-info
1853
    *   key-method       = "inline" / key-method-ext
1854
    *   key-method-ext   = 1*(ALPHA / DIGIT / "_")
1855
    *   key-info         = 1*(%x21-3A / %x3C-7E) ; visible (printing) chars
1856
    *                                        ; except semi-colon
1857
    *  session-param    = 1*(VCHAR)         ; visible (printing) characters
1858
    *
1859
    *   where WSP, ALPHA, DIGIT, and VCHAR are defined in [RFC4234].
1860
    *
1861
    */
1862
0
    unsigned      next_offset, tokenlen;
1863
0
    proto_tree   *parameter_item;
1864
0
    proto_item   *parameter_tree;
1865
0
    uint32_t      crypto_tag;
1866
0
    bool          crypto_tag_valid;
1867
0
    bool          has_more_pars      = true;
1868
0
    uint8_t       master_key_length  = 0, master_salt_length = 0;
1869
0
    bool          mki_len_valid;
1870
0
    proto_item   *pi;
1871
1872
    /* We are at the first colon */
1873
    /* tag */
1874
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1875
0
    if (tokenlen == 0)
1876
0
        return;
1877
0
    crypto_tag_valid = ws_strtou32((char*)tvb_get_string_enc(pinfo->pool, tvb, offset,
1878
0
                                                      tokenlen, ENC_UTF_8|ENC_NA), NULL, &crypto_tag);
1879
0
    pi = proto_tree_add_uint(tree, hf_sdp_crypto_tag, tvb, offset, tokenlen, crypto_tag);
1880
0
    if (!crypto_tag_valid)
1881
0
        expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_tag);
1882
0
    offset = next_offset + 1;
1883
1884
    /* crypto-suite */
1885
0
    tokenlen = find_next_token_in_line(tvb, tree, &offset, &next_offset);
1886
0
    if (tokenlen == 0)
1887
0
        return;
1888
0
    parameter_item = proto_tree_add_item(tree, hf_sdp_crypto_crypto_suite, tvb, offset, tokenlen, ENC_UTF_8);
1889
0
    if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_80", tokenlen) == 0) {
1890
1891
        /* XXX This may only work in simple cases */
1892
0
        if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1893
0
            transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1894
0
            transport_info->auth_algorithm       = SRTP_AUTH_ALG_HMAC_SHA1;
1895
            /* number of octets used for the Auth Tag in the RTP payload */
1896
0
            transport_info->auth_tag_len         = 10;
1897
0
        }
1898
0
        master_key_length  = 16; /* 128 bits = 16 octets */
1899
0
        master_salt_length = 14; /* 112 bits = 14 octets */
1900
0
    } else if (tvb_strncaseeql(tvb, offset, "AES_CM_128_HMAC_SHA1_32", tokenlen) == 0) {
1901
        /* XXX This may only work in simple cases */
1902
0
        if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1903
0
            transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_CM;
1904
0
            transport_info->auth_algorithm       = SRTP_AUTH_ALG_HMAC_SHA1;
1905
            /* number of octets used for the Auth Tag in the RTP payload */
1906
0
            transport_info->auth_tag_len         = 4;
1907
0
        }
1908
0
        master_key_length  = 16; /* 128 bits = 16 octets */
1909
0
        master_salt_length = 14; /* 112 bits = 14 octets */
1910
0
    } else if (tvb_strncaseeql(tvb, offset, "F8_128_HMAC_SHA1_80", tokenlen) == 0) {
1911
0
        if (transport_info->encryption_algorithm == SRTP_ENC_ALG_NOT_SET) {
1912
            /* XXX This may only work in simple cases */
1913
0
            transport_info->encryption_algorithm = SRTP_ENC_ALG_AES_F8;
1914
0
            transport_info->auth_algorithm       = SRTP_AUTH_ALG_HMAC_SHA1;
1915
            /* number of octets used for the Auth Tag in the RTP payload */
1916
0
            transport_info->auth_tag_len         = 10;
1917
0
        }
1918
0
        master_key_length  = 16; /* 128 bits = 16 octets */
1919
0
        master_salt_length = 14; /* 112 bits = 14 octets */
1920
0
    }
1921
0
    offset = next_offset + 1;
1922
1923
    /* key-params */
1924
0
    while (has_more_pars == true) {
1925
0
        unsigned  param_end_offset;
1926
0
        tvbuff_t *key_salt_tvb;
1927
0
        char     *data_p = NULL;
1928
1929
0
        if (!tvb_find_uint8_remaining(tvb, offset, ';', &param_end_offset)) {
1930
0
            has_more_pars = false;
1931
0
        }
1932
        /* key-method or key-method-ext */
1933
0
        if (!tvb_find_uint8_remaining(tvb, offset, ':', &next_offset)) {
1934
0
            expert_add_info(pinfo, parameter_item, &ei_sdp_invalid_key_param);
1935
0
            break;
1936
0
        }
1937
1938
0
        if (tvb_strncaseeql(tvb, offset, "inline", next_offset-offset) == 0) {
1939
0
            parameter_tree = proto_tree_add_subtree(tree, tvb, offset,param_end_offset-offset,
1940
0
                                                    ett_sdp_crypto_key_parameters, NULL, "Key parameters");
1941
            /* XXX only for SRTP? */
1942
            /* srtp-key-info       = key-salt ["|" lifetime] ["|" mki] */
1943
0
            offset      = next_offset +1;
1944
0
            tokenlen = param_end_offset - offset;
1945
0
            if (tvb_find_uint8_length(tvb, offset, tokenlen, '|', &next_offset)) {
1946
0
                tokenlen = next_offset - offset;
1947
0
            }
1948
0
            data_p = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_UTF_8|ENC_NA);
1949
0
            key_salt_tvb = base64_to_tvb(tvb, data_p);
1950
0
            add_new_data_source(pinfo, key_salt_tvb, "Key_Salt_tvb");
1951
0
            if (master_key_length != 0) {
1952
0
                proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, tvb, offset, tokenlen, ENC_NA);
1953
0
                proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_key,
1954
0
                                    key_salt_tvb, 0, master_key_length, ENC_NA);
1955
0
                proto_tree_add_item(parameter_tree, hf_sdp_crypto_master_salt,
1956
0
                                    key_salt_tvb, master_key_length, master_salt_length, ENC_NA);
1957
0
            } else {
1958
0
                proto_tree_add_item(parameter_tree, hf_sdp_key_and_salt, key_salt_tvb, 0, -1, ENC_NA);
1959
0
            }
1960
1961
            /*  ["|" lifetime] ["|" mki] are optional */
1962
0
            if (next_offset < param_end_offset) {
1963
                /* We found one "|" in the parameter. If there is a second
1964
                 * one, then there's both a lifetime and mki. */
1965
0
                offset = next_offset + 1;
1966
0
                if (tvb_find_uint8_length(tvb, offset, param_end_offset - offset, '|', &next_offset)) {
1967
                    /*lifetime           = ["2^"] 1*(DIGIT)   ; see section 6.1 for "2^" */
1968
0
                    tokenlen = next_offset - offset;
1969
0
                    proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
1970
0
                                        tvb, offset, tokenlen, ENC_UTF_8);
1971
0
                    offset   = next_offset + 1;
1972
0
                    tvb_find_uint8_length(tvb, offset, param_end_offset - offset, ':', &next_offset);
1973
                    /* XXX - If there's no ':', either the packet is short or
1974
                     * the mki is malformed, expert info? */
1975
0
                } else {
1976
                    /* There's only one. Per RFC 4568 6.1, "note that the
1977
                     * lifetime field never includes a colon, whereas the
1978
                     * third field always does."
1979
                     * https://datatracker.ietf.org/doc/html/rfc4568#section-6.1
1980
                     */
1981
0
                    tokenlen = param_end_offset - offset;
1982
0
                    if (!tvb_find_uint8_length(tvb, offset, tokenlen, ':', &next_offset)) {
1983
0
                        proto_tree_add_item(parameter_tree, hf_sdp_crypto_lifetime,
1984
0
                                            tvb, offset, tokenlen, ENC_UTF_8);
1985
0
                        offset = param_end_offset;
1986
0
                    }
1987
0
                }
1988
                /* mki                 = mki-value ":" mki-length
1989
                *
1990
                * mki-value           = 1*DIGIT
1991
                */
1992
0
                if (next_offset < param_end_offset) {
1993
0
                    tokenlen    = next_offset - offset;
1994
0
                    proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki, tvb, offset, tokenlen, ENC_UTF_8);
1995
0
                    offset      = next_offset + 1;
1996
1997
                    /* mki-length          = 1*3DIGIT   ; range 1..128. */
1998
0
                    next_offset = param_end_offset;
1999
0
                    tokenlen    = next_offset - offset;
2000
2001
                    /* This will not work if more than one parameter */
2002
                    /* number of octets used for the MKI in the RTP payload */
2003
0
                    mki_len_valid = ws_strtou32((char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen,
2004
0
                                                                   ENC_UTF_8|ENC_NA), NULL, &transport_info->mki_len);
2005
0
                    pi = proto_tree_add_item(parameter_tree, hf_sdp_crypto_mki_length,
2006
0
                                             tvb, offset, tokenlen, ENC_UTF_8);
2007
0
                    if (!mki_len_valid)
2008
0
                        expert_add_info(pinfo, pi, &ei_sdp_invalid_crypto_mki_length);
2009
0
                }
2010
0
            }
2011
0
            offset = param_end_offset;
2012
0
        } else {
2013
0
            break;
2014
0
        }
2015
0
    }
2016
0
}
2017
2018
static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, unsigned length,
2019
                                        transport_info_t *transport_info,
2020
                                        session_info_t *session_info,
2021
                                        media_description_t *media_desc,
2022
                                        sdp_data_t *sdp_data)
2023
0
{
2024
0
    proto_tree   *sdp_media_attribute_tree;
2025
0
    proto_item   *pi;
2026
0
    unsigned      offset, tokenlen, colon_offset;
2027
0
    char         *attribute_value;
2028
0
    int           sdp_media_attrbute_code;
2029
0
    const char   *msrp_res           = "msrp://";
2030
2031
0
    offset = 0;
2032
2033
    /* Create attribute tree */
2034
0
    sdp_media_attribute_tree = proto_item_add_subtree(ti,
2035
0
                                                      ett_sdp_media_attribute);
2036
    /* Find end of field */
2037
0
    if (!tvb_find_uint8_remaining(tvb, offset, ':', &colon_offset))
2038
0
      return;
2039
2040
    /* Attribute field name is token before ':' */
2041
0
    tokenlen = colon_offset - offset;
2042
0
    pi = proto_tree_add_item(sdp_media_attribute_tree,
2043
0
                             hf_media_attribute_field,
2044
0
                             tvb, offset, tokenlen, ENC_UTF_8);
2045
    /*??field_name = tvb_get_string_enc(pinfo->pool, tvb, offset, tokenlen, ENC_ASCII);*/
2046
0
    sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
2047
2048
    /* Skip colon */
2049
0
    offset = colon_offset + 1;
2050
    /* skip leading wsp */
2051
0
    offset = tvb_skip_wsp(tvb, offset, tvb_captured_length_remaining(tvb, offset));
2052
2053
    /* Value is the remainder of the line */
2054
0
    if (tvb_captured_length_remaining(tvb, offset) > 0)
2055
0
        attribute_value = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, tvb_captured_length_remaining(tvb, offset), ENC_UTF_8|ENC_NA);
2056
0
    else
2057
0
    {
2058
0
        expert_add_info(pinfo, pi, &ei_sdp_invalid_line_fields);
2059
0
        return;
2060
0
    }
2061
2062
    /*********************************************/
2063
    /* Special parsing for some field name types */
2064
2065
0
    switch (sdp_media_attrbute_code) {
2066
0
        case SDP_RTPMAP:
2067
            /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
2068
0
            dissect_sdp_media_attribute_rtpmap(sdp_media_attribute_tree, pinfo, tvb, length, transport_info,
2069
0
                                               session_info, media_desc, offset);
2070
0
            break;
2071
0
        case SDP_FMTP:
2072
0
            dissect_sdp_media_attribute_fmtp(sdp_media_attribute_tree, pinfo, tvb, transport_info,
2073
0
                                               session_info, media_desc, offset);
2074
0
            break;
2075
0
        case SDP_PATH:
2076
0
            dissect_sdp_media_attribute_path(pinfo, tvb, attribute_value, media_desc, msrp_res, offset);
2077
0
            break;
2078
0
        case SDP_H248_ITEM:
2079
            /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
2080
0
            dissect_sdp_media_attribute_h248_item(sdp_media_attribute_tree, pinfo, tvb, attribute_value, msrp_res);
2081
0
            break;
2082
0
        case SDP_CRYPTO:
2083
0
            dissect_sdp_media_attribute_crypto(sdp_media_attribute_tree, pinfo, tvb, transport_info, offset);
2084
0
            break;
2085
0
        case SDP_CANDIDATE:
2086
0
            dissect_sdp_media_attribute_candidate(sdp_media_attribute_tree, pinfo, tvb, offset);
2087
0
            break;
2088
0
        case SDP_ED137_TYPE:
2089
            /* Remember the value and add it to tree */
2090
0
            sdp_data->ed137_type = attribute_value;
2091
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2092
0
                                tvb, offset, -1, ENC_UTF_8);
2093
0
            break;
2094
0
        case SDP_ED137_TXRXMODE:
2095
            /* Remember the value and add it to tree */
2096
0
            sdp_data->ed137_txrxmode = attribute_value;
2097
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2098
0
                                tvb, offset, -1, ENC_UTF_8);
2099
0
            break;
2100
0
        case SDP_ED137_FID:
2101
            /* Remember the value and add it to tree */
2102
0
            sdp_data->ed137_fid = attribute_value;
2103
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2104
0
                                tvb, offset, -1, ENC_UTF_8);
2105
0
            break;
2106
0
        case SDP_RTCP :
2107
0
            if (media_desc) {
2108
0
                if (!ws_strtou16(attribute_value, NULL, &media_desc->control_port))
2109
0
                    media_desc->control_port = 0; /* Just use default, if not legal port */
2110
0
            }
2111
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2112
0
                                tvb, offset, -1, ENC_UTF_8);
2113
0
            break;
2114
0
        case SDP_RTCP_MUX :
2115
0
            if (media_desc) {
2116
0
                media_desc->control_port = media_desc->media_port;
2117
0
            }
2118
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2119
0
                                tvb, offset, -1, ENC_UTF_8);
2120
0
            break;
2121
0
        case SDP_CONTROL:
2122
0
            if (media_desc) {
2123
0
                media_desc->control_uri = wmem_ascii_strdown(wmem_file_scope(), attribute_value, -1);
2124
0
            }
2125
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2126
0
                                tvb, offset, -1, ENC_UTF_8);
2127
0
            break;
2128
0
        default:
2129
            /* No special treatment for values of this attribute type, just add as one item. */
2130
0
            proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
2131
0
                                tvb, offset, -1, ENC_UTF_8);
2132
0
            break;
2133
0
    }
2134
0
}
2135
2136
static void
2137
call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
2138
                      transport_info_t *transport_info,
2139
                      session_info_t *session_info,
2140
                      media_description_t *media_desc,
2141
                      sdp_data_t *sdp_data)
2142
964
{
2143
964
    if (hf == hf_owner) {
2144
62
        dissect_sdp_owner(tvb, ti);
2145
902
    } else if (hf == hf_connection_info) {
2146
34
        dissect_sdp_connection_info(pinfo, tvb, ti, session_info, media_desc);
2147
868
    } else if (hf == hf_bandwidth) {
2148
1
        dissect_sdp_bandwidth(tvb, ti);
2149
867
    } else if (hf == hf_time) {
2150
0
        dissect_sdp_time(tvb, ti);
2151
867
    } else if (hf == hf_repeat_time) {
2152
147
        dissect_sdp_repeat_time(tvb, ti);
2153
720
    } else if (hf == hf_timezone) {
2154
98
        dissect_sdp_timezone(tvb, ti);
2155
622
    } else if (hf == hf_encryption_key) {
2156
18
        dissect_sdp_encryption_key(tvb, ti);
2157
604
    } else if (hf == hf_session_attribute) {
2158
0
        dissect_sdp_session_attribute(tvb, pinfo, ti);
2159
604
    } else if (hf == hf_media) {
2160
542
        dissect_sdp_media(tvb, pinfo, ti, media_desc);
2161
542
    } else if (hf == hf_media_attribute) {
2162
0
        dissect_sdp_media_attribute(tvb, pinfo, ti, length, transport_info, session_info, media_desc, sdp_data);
2163
0
    }
2164
964
}
2165
2166
/**
2167
 * Post-processes the media descriptions after parsing it from the tvb. This
2168
 * performs processing that can only be done when the full media description is
2169
 * parsed (since otherwise the order of attributes could influence the result).
2170
 * Must be called before applying the SDP with apply_sdp_transport.
2171
 * It will remove media streams when the port number in the answer is zero.
2172
 *
2173
 * If the currently processed SDP is an Answer to a known previous Offer, then
2174
 * answer_offset is non-zero.
2175
 */
2176
static void
2177
complete_descriptions(transport_info_t *transport_info, unsigned answer_offset)
2178
120
{
2179
120
    unsigned media_count = wmem_array_get_count(transport_info->media_descriptions);
2180
120
    media_description_t *media_descs = (media_description_t *)wmem_array_get_raw(transport_info->media_descriptions);
2181
120
    media_description_t *bundle_media_desc = NULL;
2182
2183
120
    DPRINT(("complete_descriptions called with answer_offset=%d media_count=%d",
2184
120
            answer_offset, media_count));
2185
2186
206
    for (unsigned i = answer_offset; i < media_count && !bundle_media_desc; i++) {
2187
188
        for (unsigned j = i+1; j < media_count && !bundle_media_desc; j++) {
2188
102
            if (media_descs[i].media_port == media_descs[j].media_port)
2189
55
                bundle_media_desc = &media_descs[i];
2190
102
        }
2191
86
    }
2192
2193
120
    if (bundle_media_desc) {
2194
        /* We have "bundling" of media, so now combine all the media bit masks
2195
           and merge the rtp_dyn_payload so that the first media description
2196
           has all the data for every media description. */
2197
253
        for (unsigned i = answer_offset; i < media_count; i++) {
2198
198
            media_description_t *media_desc = &media_descs[i];
2199
2200
198
            if (bundle_media_desc->media_port == media_desc->media_port) {
2201
162
                media_desc->bundled = true;
2202
2203
162
                if (media_desc != bundle_media_desc) {
2204
107
                    bundle_media_desc->media_types |= media_desc->media_types;
2205
13.8k
                    for (unsigned pt = 0; pt < 128; ++pt) {
2206
13.6k
                        const char * encoding_name;
2207
13.6k
                        int sample_rate;
2208
13.6k
                        unsigned channels;
2209
13.6k
                        wmem_map_t *fmtp_map;
2210
13.6k
                        if (rtp_dyn_payload_get_full(media_desc->media.rtp_dyn_payload,
2211
13.6k
                                                     pt, &encoding_name, &sample_rate, &channels, &fmtp_map))
2212
0
                            rtp_dyn_payload_insert_full(bundle_media_desc->media.rtp_dyn_payload,
2213
0
                                                        pt, encoding_name, sample_rate, channels, fmtp_map);
2214
13.6k
                    }
2215
107
                }
2216
162
            }
2217
198
        }
2218
55
    }
2219
2220
341
    for (unsigned i = answer_offset; i < media_count; i++) {
2221
221
        media_description_t *media_desc = &media_descs[i];
2222
2223
221
        if (media_desc->control_port == 0)
2224
221
            media_desc->control_port = media_desc->media_port + 1;
2225
2226
221
        if (media_desc->control_port == 0)
2227
3
            media_desc->control_port = media_desc->media_port + 1;
2228
2229
        /* If this is an answer to a previous offer... */
2230
221
        if (answer_offset > 0) {
2231
            /* A zero port removes the media stream (RFC 3264, Section 8.2) */
2232
0
            if (media_desc->media_port == 0) {
2233
0
                DPRINT(("disabling media_port=%d, for index=%d",
2234
0
                        media_descs[i - answer_offset].media_port,
2235
0
                        i - answer_offset));
2236
0
                media_descs[i - answer_offset].media_port = 0;
2237
0
            }
2238
0
        }
2239
2240
        /* MSRP uses addresses discovered in attribute
2241
           rather than connection information of media session line */
2242
221
        if (media_desc->proto == SDP_PROTO_MSRP && msrp_handle &&
2243
0
            media_desc->media_attr.msrp.ipaddr.type != AT_NONE) {
2244
            /* clear old address and set new address and port. */
2245
0
            free_address_wmem(wmem_file_scope(), &media_desc->conn_addr);
2246
0
            copy_address_shallow(&media_desc->conn_addr,
2247
0
                                 &media_desc->media_attr.msrp.ipaddr);
2248
0
            media_desc->media_port = media_desc->media_attr.msrp.port_number;
2249
0
        }
2250
221
    }
2251
120
}
2252
2253
/**
2254
 * Given is a structure containing the parsed result from the SDP (including
2255
 * protocol type (RTP, SRTP, T38, etc.), media info (payload type, etc.) and
2256
 * connection info (address, port). Register the address+port such that the
2257
 * protocol will be invoked for this tuple with the media information.
2258
 *
2259
 * For use with SDP using the Offer/Answer model (such as SIP with INVITE and
2260
 * 200 OK).
2261
 * XXX what about RTSP where the SDP merely provides media info, without
2262
 * actually establishing connections (Bug 5208).
2263
 *
2264
 * The passed transport information is modified: 'set_rtp' is set when the media
2265
 * is assigned to a conversation. Note that the unassigned media (payload types)
2266
 * are not freed, this is the responsibility of the caller.
2267
 */
2268
static void
2269
apply_sdp_transport(packet_info *pinfo, transport_info_t *transport_info, int request_frame, sdp_setup_info_t *setup_info)
2270
120
{
2271
120
    int establish_frame = 0;
2272
120
    wmem_array_t *setup_info_list;
2273
2274
120
    struct srtp_info *srtp_info = NULL;
2275
2276
120
    if (!global_sdp_establish_conversation) {
2277
        /* Do not register with other dissectors when this pref is disabled. */
2278
0
        return;
2279
0
    }
2280
2281
    /* If no request_frame number has been found use this frame's number */
2282
120
    if (request_frame == 0) {
2283
120
        establish_frame = pinfo->num;
2284
120
    } else {
2285
0
        establish_frame = request_frame;
2286
0
    }
2287
2288
120
    bool bundled_media_set = false;
2289
2290
341
    for (unsigned i = 0; i < wmem_array_get_count(transport_info->media_descriptions); i++) {
2291
221
        media_description_t *media_desc =
2292
221
            (media_description_t *)wmem_array_index(transport_info->media_descriptions, i);
2293
221
        uint32_t current_rtp_port = 0;
2294
2295
        /* "a=control:" is an attribute unique to RTSP. RTSP uses the same
2296
         * transport types as RTP but the port is either zero or merely a
2297
         * suggestion, actual information is obtained by later RTSP methods.
2298
         * We do not apply the descriptor here but save it, keyed by the
2299
         * URI. (RTSP clients can also receive media description via other
2300
         * protocols like HTTP, so there is no guarantee that the RTSP protocol
2301
         * is the caller here.)
2302
         */
2303
221
        if (media_desc->control_uri) {
2304
            /* Ensure that we do not attempt to set it below. */
2305
0
            media_desc->media.set_rtp = true;
2306
0
            if (setup_info && setup_info->base_uri) {
2307
0
                char *absolute_uri = determine_http_location_target(wmem_file_scope(), setup_info->base_uri, media_desc->control_uri);
2308
0
                if (absolute_uri) {
2309
0
                    media_desc->control_uri = absolute_uri;
2310
0
                }
2311
0
            }
2312
0
            ascii_strdown_inplace(media_desc->control_uri);
2313
            /* If there are multiple entries with the same URI they SHOULD be
2314
             * the same, so we could free the existing entry.  */
2315
0
            rtp_dyn_payload_t *old_rtp_pt;
2316
0
            old_rtp_pt = wmem_map_insert(sdp_rtsp_control_map, media_desc->control_uri, media_desc->media.rtp_dyn_payload);
2317
0
            if (old_rtp_pt && old_rtp_pt != media_desc->media.rtp_dyn_payload) {
2318
0
                rtp_dyn_payload_free(old_rtp_pt);
2319
0
            }
2320
0
        }
2321
2322
        /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
2323
221
        if ((media_desc->media_port != 0) &&
2324
59
            !media_desc->media.set_rtp &&
2325
59
            (media_desc->proto == SDP_PROTO_RTP ||
2326
58
             media_desc->proto == SDP_PROTO_SRTP) &&
2327
1
            (media_desc->conn_addr.type == AT_IPv4 ||
2328
1
             media_desc->conn_addr.type == AT_IPv6)) {
2329
2330
0
            media_desc->media.set_rtp = true;
2331
2332
0
            if (media_desc->bundled) {
2333
0
                if (bundled_media_set)
2334
0
                    continue;
2335
0
                bundled_media_set = true;
2336
0
            }
2337
2338
0
            if (media_desc->proto == SDP_PROTO_SRTP) {
2339
0
                srtp_info = wmem_new0(wmem_file_scope(), struct srtp_info);
2340
0
                if (transport_info->encryption_algorithm != SRTP_ENC_ALG_NOT_SET) {
2341
0
                    srtp_info->encryption_algorithm = transport_info->encryption_algorithm;
2342
0
                    srtp_info->auth_algorithm       = transport_info->auth_algorithm;
2343
0
                    srtp_info->mki_len              = transport_info->mki_len;
2344
0
                    srtp_info->auth_tag_len         = transport_info->auth_tag_len;
2345
2346
0
                }
2347
0
                DPRINT(("calling srtp_add_address, channel=%d, media_port=%d",
2348
0
                        i, media_desc->media_port));
2349
0
                DINDENT();
2350
                /* srtp_add_address and rtp_add_address are given the request_frame's not this frame's number,
2351
                   because that's where the RTP flow started, and thus conversation needs to check against */
2352
0
                srtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame,
2353
0
                                 media_desc->media_types,
2354
0
                                 media_desc->media.rtp_dyn_payload, srtp_info,
2355
0
                                 setup_info);
2356
0
                DENDENT();
2357
0
            } else if (setup_info && setup_info->is_osmux) {
2358
0
                DPRINT(("calling osmux_add_address, channel=%d, media_port=%d",
2359
0
                        i, media_desc->media_port));
2360
0
                DINDENT();
2361
0
                osmux_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, 0, establish_frame);
2362
0
                DENDENT();
2363
0
            } else {
2364
0
                DPRINT(("calling rtp_add_address, channel=%d, media_port=%d",
2365
0
                        i, media_desc->media_port));
2366
0
                DINDENT();
2367
0
                srtp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", establish_frame,
2368
0
                                 media_desc->media_types,
2369
0
                                 media_desc->media.rtp_dyn_payload, NULL, setup_info);
2370
0
                DENDENT();
2371
0
            }
2372
            /* SPRT might use the same port... */
2373
0
            current_rtp_port = media_desc->media_port;
2374
2375
0
            if (rtcp_handle && media_desc->media_port != media_desc->control_port) {
2376
0
                if (media_desc->proto == SDP_PROTO_SRTP) {
2377
0
                    DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
2378
0
                            i, media_desc->control_port));
2379
0
                    DINDENT();
2380
0
                    srtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame, srtp_info);
2381
0
                    DENDENT();
2382
0
                 } else if (!setup_info || !setup_info->is_osmux) {
2383
0
                    DPRINT(("calling rtcp_add_address, channel=%d, control_port=%d",
2384
0
                            i, media_desc->control_port));
2385
0
                    DINDENT();
2386
0
                    rtcp_add_address(pinfo, &media_desc->conn_addr, media_desc->control_port, 0, "SDP", establish_frame);
2387
0
                    DENDENT();
2388
0
                 }
2389
0
            }
2390
0
        }
2391
2392
        /* add SPRT conversation */
2393
221
        if (media_desc->proto == SDP_PROTO_SPRT &&
2394
0
            (media_desc->conn_addr.type == AT_IPv4 ||
2395
0
             media_desc->conn_addr.type == AT_IPv6) &&
2396
0
            (sprt_handle)) {
2397
2398
0
            if (media_desc->media_port == 0 && current_rtp_port) {
2399
0
                sprt_add_address(pinfo, &media_desc->conn_addr, current_rtp_port,
2400
0
                                 0, "SDP", pinfo->num); /* will use same port as RTP */
2401
0
            } else {
2402
0
                sprt_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", pinfo->num);
2403
0
            }
2404
0
        }
2405
2406
        /* Add t38 conversation, if available and only if no rtp */
2407
221
        if ((media_desc->media_port != 0) &&
2408
59
            !media_desc->media.set_rtp &&
2409
59
            media_desc->proto == SDP_PROTO_T38 &&
2410
0
            media_desc->conn_addr.type == AT_IPv4) {
2411
0
            t38_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, 0, "SDP", pinfo->num);
2412
0
        }
2413
2414
        /* Add MSRP conversation.  Uses addresses discovered in attribute
2415
           rather than connection information of media session line
2416
           (already handled in media conversion) */
2417
221
        if (media_desc->proto == SDP_PROTO_MSRP && msrp_handle) {
2418
0
            msrp_add_address(pinfo, &media_desc->conn_addr, media_desc->media_port, "SDP", pinfo->num);
2419
0
        }
2420
2421
        /* Add BFCP conversation.  Uses addresses discovered in attribute
2422
           rather than connection information of media session line
2423
           (already handled in media conversion) */
2424
221
        if (media_desc->proto == SDP_PROTO_BFCP && bfcp_handle) {
2425
0
            bfcp_add_address(pinfo, PT_UDP, &media_desc->conn_addr, media_desc->media_port, "SDP", establish_frame);
2426
0
        }
2427
221
    } /* end of loop through all media descriptions. */
2428
2429
    /* Copy the list of setup info of calls with the same RTP information
2430
     * to the transport info, so that we have it when dissecting the
2431
     * request as well.
2432
     * XXX - There can be multiple media descriptions, and while this SDP's
2433
     * setup info is on all of them, some other SDP might have some but not
2434
     * all media descriptions, so the arrays of setup infos might be different.
2435
     * They should be consolidated as with rtp_add_setup_info_if_no_duplicate()
2436
     * in packet-rtp.c, or stored with each media descriptor.
2437
     */
2438
120
    setup_info_list = p_get_proto_data(pinfo->pool, pinfo, proto_sdp, 0);
2439
120
    if (setup_info_list) {
2440
0
        transport_info->sdp_setup_info_list = setup_info_list;
2441
0
    }
2442
120
}
2443
2444
void
2445
setup_sdp_transport(tvbuff_t *tvb, packet_info *pinfo, enum sdp_exchange_type exchange_type,
2446
    int request_frame, const bool delay, sdp_setup_info_t *setup_info)
2447
0
{
2448
0
    unsigned    offset = 0, next_offset, n;
2449
0
    unsigned    linelen;
2450
0
    bool        in_media_description = false;
2451
0
    unsigned char      type, delim;
2452
0
    const int   tokenoffset = 2;
2453
0
    int         hf     = -1;
2454
0
    int         start_transport_info_count = 0;
2455
0
    transport_info_t* transport_info = NULL;
2456
0
    media_description_t *media_desc = NULL;
2457
0
    session_info_t session_info;
2458
0
    sdp_data_t  sdp_data;
2459
2460
0
    DPRINT2(("-------------------- setup_sdp_transport -------------------"));
2461
2462
    /* Only do this once during first pass */
2463
0
    if (pinfo->fd->visited) {
2464
0
        DPRINT(("already visited"));
2465
0
        return;
2466
0
    }
2467
2468
0
    memset(&sdp_data, 0, sizeof(sdp_data));
2469
2470
0
    if (request_frame != 0)
2471
0
        transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
2472
0
    if (transport_info == NULL) {
2473
0
        transport_info = wmem_new0(wmem_file_scope(), transport_info_t);
2474
0
        transport_info->media_descriptions = wmem_array_new(wmem_file_scope(), sizeof(media_description_t));
2475
2476
0
        for (n = 0; n < SDP_NO_OF_PT; n++) {
2477
            /* String is file scope allocated because transport_info is connection related */
2478
0
            transport_info->encoding_name[n] = wmem_strdup(wmem_file_scope(), UNKNOWN_ENCODING);
2479
0
        }
2480
2481
0
        if (request_frame != 0)
2482
0
            wmem_tree_insert32(sdp_transport_reqs, request_frame, (void *)transport_info);
2483
0
    }
2484
#ifdef DEBUG_CONVERSATION
2485
    else {
2486
        DPRINT(("found previous transport_info:"));
2487
        sdp_dump_transport_info(pinfo, transport_info);
2488
    }
2489
#endif
2490
2491
0
    if (exchange_type != SDP_EXCHANGE_OFFER)
2492
0
        wmem_tree_insert32(sdp_transport_rsps, pinfo->num, (void *)transport_info);
2493
2494
    /* Offer has already been answered or rejected and hash tables freed, so
2495
     * don't try to add to it
2496
     * XXX - Need to support "modified offers" */
2497
0
    if ((transport_info->sdp_status == SDP_EXCHANGE_ANSWER_REJECT) ||
2498
0
        (transport_info->sdp_status == SDP_EXCHANGE_ANSWER_ACCEPT))
2499
0
        return;
2500
2501
    /* Initialize the session description before parsing the media descriptions. */
2502
0
    memset(&session_info, 0, sizeof(session_info_t));
2503
0
    session_info.rtp_dyn_payload = rtp_dyn_payload_new();
2504
2505
    /* Remember where the answer should start (it will be zero if there was no
2506
     * previous offer with media descriptions). */
2507
0
    start_transport_info_count = wmem_array_get_count(transport_info->media_descriptions);
2508
2509
0
    DPRINT(("start_transport_info_count=%d", start_transport_info_count));
2510
2511
    /*
2512
     * Show the SDP message a line at a time.
2513
     */
2514
0
    while (tvb_offset_exists(tvb, offset)) {
2515
        /*
2516
         * Find the end of the line.
2517
         */
2518
0
        tvb_find_line_end_unquoted_remaining(tvb, offset, &linelen, &next_offset);
2519
2520
        /*
2521
         * Line must contain at least e.g. "v=".
2522
         */
2523
0
        if (linelen < 2)
2524
0
            break;
2525
2526
0
        type  = tvb_get_uint8(tvb, offset);
2527
0
        delim = tvb_get_uint8(tvb, offset + 1);
2528
0
        if (delim != '=') {
2529
0
            offset = next_offset;
2530
0
            continue;
2531
0
        }
2532
2533
        /*
2534
         * Attributes.  Only care about ones that affect the transport.  Ignore others.
2535
         */
2536
0
        switch (type) {
2537
0
            case 'c':
2538
0
                hf = hf_connection_info;
2539
0
                break;
2540
0
            case 'm':
2541
0
                hf = hf_media;
2542
2543
                /* Try to create a new media description (it will return NULL if
2544
                 * there are too many). */
2545
0
                media_desc = sdp_new_media_description(transport_info->media_descriptions, &session_info);
2546
2547
0
                in_media_description = true;
2548
0
                DPRINT(("in media description, media descriptions count=%d",
2549
0
                        wmem_array_get_count(transport_info->media_descriptions)));
2550
0
                break;
2551
0
            case 'a':
2552
0
                if (in_media_description) {
2553
0
                    hf = hf_media_attribute;
2554
0
                } else {
2555
0
                    hf = hf_session_attribute;
2556
0
                }
2557
0
                break;
2558
0
            default:
2559
0
                hf = hf_unknown;
2560
0
                break;
2561
0
        }
2562
2563
0
        if (hf != hf_unknown)
2564
0
        {
2565
0
            DINDENT();
2566
0
            call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset,
2567
0
                                                   linelen - tokenoffset),
2568
0
                                    pinfo,
2569
0
                                    hf, NULL, linelen-tokenoffset,
2570
0
                                    transport_info,
2571
0
                                    in_media_description ? NULL : &session_info,
2572
0
                                    media_desc,
2573
0
                                    &sdp_data);
2574
0
            DENDENT();
2575
0
        }
2576
2577
0
        offset = next_offset;
2578
0
    }
2579
2580
    /* Done parsing media description, no more need for the session-level details. */
2581
0
    rtp_dyn_payload_free(session_info.rtp_dyn_payload);
2582
0
    session_info.rtp_dyn_payload = NULL;
2583
2584
    /* Post-processing, close media streams, apply attributes, etc. */
2585
0
    complete_descriptions(transport_info, start_transport_info_count);
2586
2587
#ifdef DEBUG_CONVERSATION
2588
    sdp_dump_transport_info(pinfo, transport_info);
2589
#endif
2590
2591
    /* We have a successful negotiation, apply data to their respective protocols */
2592
0
    if (!delay || ((exchange_type == SDP_EXCHANGE_ANSWER_ACCEPT) &&
2593
0
        (transport_info->sdp_status == SDP_EXCHANGE_OFFER))) {
2594
        /* Accepting answer to a previous offer (or delay pref is false). */
2595
0
        apply_sdp_transport(pinfo, transport_info, request_frame, setup_info);
2596
2597
        /* Free all media hash tables that were not assigned to a conversation
2598
         * ('set_rtp' is false) */
2599
0
        clean_unused_media_descriptions(transport_info->media_descriptions);
2600
2601
0
        transport_info->sdp_status = exchange_type;
2602
2603
0
    } else if ((exchange_type == SDP_EXCHANGE_ANSWER_REJECT) &&
2604
0
               (transport_info->sdp_status != SDP_EXCHANGE_ANSWER_REJECT)) {
2605
        /* Rejecting answer */
2606
0
        clean_unused_media_descriptions(transport_info->media_descriptions);
2607
2608
0
        transport_info->sdp_status = SDP_EXCHANGE_ANSWER_REJECT;
2609
0
    } /* else attempt to accept an unknown offer. */
2610
0
}
2611
2612
void setup_sdp_transport_resend(int current_frame, int request_frame)
2613
0
{
2614
0
    transport_info_t* transport_info = NULL;
2615
2616
0
    if (request_frame != 0) {
2617
0
        transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, request_frame );
2618
0
        if (transport_info != NULL) {
2619
0
            wmem_tree_insert32(sdp_transport_reqs, current_frame, (void *)transport_info);
2620
0
        }
2621
0
    }
2622
0
}
2623
2624
static int
2625
dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2626
125
{
2627
125
    proto_tree *sdp_tree;
2628
125
    proto_item *ti, *sub_ti;
2629
125
    unsigned    offset = 0, next_offset, n;
2630
125
    unsigned    linelen;
2631
125
    bool        in_media_description;
2632
125
    unsigned char      type, delim;
2633
125
    unsigned    datalen, tokenoffset;
2634
125
    int         hf = -1;
2635
125
    char       *string;
2636
125
    sdp_data_t  sdp_data;
2637
2638
125
    transport_info_t  local_transport_info;
2639
125
    transport_info_t* transport_info = NULL;
2640
125
    media_description_t *media_desc = NULL;
2641
125
    session_info_t session_info;
2642
125
    sdp_packet_info  *sdp_pi;
2643
125
    sdp_setup_info_t *setup_info = NULL;
2644
2645
125
    if (data) {
2646
19
        media_content_info_t *content_info = (media_content_info_t *)data;
2647
19
        if (content_info->type == MEDIA_CONTAINER_SIP_DATA) {
2648
19
            setup_info = (sdp_setup_info_t *)content_info->data;
2649
19
        }
2650
19
    }
2651
2652
125
    DPRINT2(("----------------------- dissect_sdp ------------------------"));
2653
2654
    /* Initialise packet info for passing to tap */
2655
125
    sdp_pi = wmem_new(pinfo->pool, sdp_packet_info);
2656
125
    sdp_pi->summary_str[0] = '\0';
2657
2658
125
    memset(&sdp_data, 0, sizeof(sdp_data));
2659
2660
125
    transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_reqs, pinfo->num );
2661
2662
125
    if (transport_info == NULL) {
2663
      /* Can't find it in the requests, make sure it's not a response */
2664
125
      transport_info = (transport_info_t*)wmem_tree_lookup32( sdp_transport_rsps, pinfo->num );
2665
125
    }
2666
2667
125
    if (transport_info == NULL) {
2668
125
      transport_info = &local_transport_info;
2669
125
    }
2670
#ifdef DEBUG_CONVERSATION
2671
    else {
2672
        DPRINT(("found previous transport_info:"));
2673
        sdp_dump_transport_info(pinfo, transport_info);
2674
    }
2675
#endif
2676
2677
    /* Initialize local transport info */
2678
125
    memset(&local_transport_info, 0, sizeof(local_transport_info));
2679
    /* Note: packet-scoped since it is only needed while parsing this packet. */
2680
125
    local_transport_info.media_descriptions = wmem_array_new(pinfo->pool, sizeof(media_description_t));
2681
2682
16.1k
    for (n = 0; n < SDP_NO_OF_PT; n++) {
2683
16.0k
        local_transport_info.encoding_name[n] = wmem_strdup(pinfo->pool, UNKNOWN_ENCODING);
2684
16.0k
    }
2685
2686
    /*
2687
     * As RFC 2327 says, "SDP is purely a format for session
2688
     * description - it does not incorporate a transport protocol,
2689
     * and is intended to use different transport protocols as
2690
     * appropriate including the Session Announcement Protocol,
2691
     * Session Initiation Protocol, Real-Time Streaming Protocol,
2692
     * electronic mail using the MIME extensions, and the
2693
     * Hypertext Transport Protocol."
2694
     *
2695
     * We therefore don't set the protocol or info columns;
2696
     * instead, we append to them, so that we don't erase
2697
     * what the protocol inside which the SDP stuff resides
2698
     * put there.
2699
     */
2700
125
    col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
2701
2702
125
    ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, ENC_NA);
2703
125
    sdp_tree = proto_item_add_subtree(ti, ett_sdp);
2704
2705
    /*
2706
     * Show the SDP message a line at a time.
2707
     */
2708
125
    in_media_description = false;
2709
2710
    /* Initialize the session description before parsing the media level. */
2711
125
    memset(&session_info, 0, sizeof(session_info_t));
2712
125
    session_info.rtp_dyn_payload = rtp_dyn_payload_new();
2713
2714
1.37k
    while (tvb_offset_exists(tvb, offset)) {
2715
        /*
2716
         * Find the end of the line.
2717
         */
2718
1.25k
        tvb_find_line_end_unquoted_remaining(tvb, offset, &linelen, &next_offset);
2719
2720
        /*
2721
         * Line must contain at least e.g. "v=".
2722
         */
2723
1.25k
        if (linelen < 2)
2724
12
            break;
2725
2726
1.24k
        type  = tvb_get_uint8(tvb, offset);
2727
1.24k
        delim = tvb_get_uint8(tvb, offset + 1);
2728
1.24k
        if (delim != '=') {
2729
281
            proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, ENC_UTF_8);
2730
281
            expert_add_info(pinfo, ti2, &ei_sdp_invalid_line_equal);
2731
281
            offset = next_offset;
2732
281
            continue;
2733
281
        }
2734
2735
        /*
2736
         * Attributes.
2737
         */
2738
964
        switch (type) {
2739
0
            case 'v':
2740
0
                hf = hf_protocol_version;
2741
0
                break;
2742
62
            case 'o':
2743
62
                hf = hf_owner;
2744
62
                break;
2745
0
            case 's':
2746
0
                hf = hf_session_name;
2747
0
                break;
2748
7
            case 'i':
2749
7
                if (in_media_description) {
2750
0
                  hf = hf_media_title;
2751
7
                } else {
2752
7
                  hf = hf_session_info;
2753
7
                }
2754
7
                break;
2755
0
            case 'u':
2756
0
                hf = hf_uri;
2757
0
                break;
2758
2
            case 'e':
2759
2
                hf = hf_email;
2760
2
                break;
2761
0
            case 'p':
2762
0
                hf = hf_phone;
2763
0
                break;
2764
34
            case 'c':
2765
34
                hf = hf_connection_info;
2766
34
                break;
2767
1
            case 'b':
2768
1
                hf = hf_bandwidth;
2769
1
                break;
2770
0
            case 't':
2771
0
                hf = hf_time;
2772
0
                break;
2773
147
            case 'r':
2774
147
                hf = hf_repeat_time;
2775
147
                break;
2776
542
            case 'm':
2777
542
                hf = hf_media;
2778
2779
                /* Try to create a new media description (it will return NULL if
2780
                 * there are too many). Pass local_transport_info since we do
2781
                 * not want to modify the transport_info that was created by
2782
                 * setup_sdp_transport. */
2783
542
                media_desc = sdp_new_media_description(local_transport_info.media_descriptions, &session_info);
2784
2785
542
                in_media_description = true;
2786
542
                break;
2787
18
            case 'k':
2788
18
                hf = hf_encryption_key;
2789
18
                break;
2790
0
            case 'a':
2791
0
                if (in_media_description) {
2792
0
                    hf = hf_media_attribute;
2793
0
                } else {
2794
0
                    hf = hf_session_attribute;
2795
0
                }
2796
0
                break;
2797
98
            case 'z':
2798
98
                hf = hf_timezone;
2799
98
                break;
2800
53
            default:
2801
53
                hf = hf_unknown;
2802
53
                break;
2803
964
        }
2804
964
        tokenoffset = 2;
2805
964
        if (hf == hf_unknown)
2806
53
            tokenoffset = 0;
2807
964
        string = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset + tokenoffset,
2808
964
                                                 linelen - tokenoffset, ENC_ASCII);
2809
964
        sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
2810
964
                                       string);
2811
2812
964
        call_sdp_subdissector(tvb_new_subset_length(tvb, offset + tokenoffset,
2813
964
                                             linelen - tokenoffset),
2814
964
                              pinfo,
2815
964
                              hf, sub_ti, linelen-tokenoffset,
2816
964
                              &local_transport_info,
2817
964
                              in_media_description ? NULL : &session_info,
2818
964
                              in_media_description ? media_desc : NULL,
2819
964
                              &sdp_data);
2820
2821
964
        offset = next_offset;
2822
964
    }
2823
2824
125
    if (NULL != sdp_data.ed137_fid) {
2825
0
      col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_fid);
2826
0
      (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_fid, 50);
2827
0
    }
2828
125
    if (NULL != sdp_data.ed137_txrxmode) {
2829
0
      col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_txrxmode);
2830
0
      if (strlen(sdp_pi->summary_str))
2831
0
          (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2832
0
      (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_txrxmode, 50);
2833
0
    }
2834
125
    if (NULL != sdp_data.ed137_type) {
2835
0
      col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", sdp_data.ed137_type);
2836
0
      if (strlen(sdp_pi->summary_str))
2837
0
          (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2838
0
      (void) g_strlcat(sdp_pi->summary_str, sdp_data.ed137_type, 50);
2839
0
    }
2840
2841
    /* Done parsing media description, no more need for the session-level details. */
2842
125
    rtp_dyn_payload_free(session_info.rtp_dyn_payload);
2843
125
    session_info.rtp_dyn_payload = NULL;
2844
2845
    /* Post-processing, close media streams, apply attributes, etc. */
2846
125
    if (transport_info == &local_transport_info) {
2847
120
        DPRINT(("no previous transport_info saved, calling complete_descriptions()"));
2848
120
        DINDENT();
2849
120
        complete_descriptions(transport_info, 0);
2850
120
        DENDENT();
2851
#ifdef DEBUG_CONVERSATION
2852
        sdp_dump_transport_info(pinfo, transport_info);
2853
#endif
2854
120
    }
2855
#ifdef DEBUG_CONVERSATION
2856
    else {
2857
        DPRINT(("not overwriting previous transport_info, local_transport_info contents:"));
2858
        sdp_dump_transport_info(pinfo, &local_transport_info);
2859
    }
2860
#endif
2861
2862
    /* For messages not part of the Offer/Answer model, assume that the SDP is
2863
     * immediately effective (apply it now). */
2864
125
    if ((!pinfo->fd->visited) && (transport_info == &local_transport_info)) {
2865
        /* XXX - This is a placeholder for higher layer protocols that haven't implemented the proper
2866
         * OFFER/ANSWER functionality using setup_sdp_transport().  Once all of the higher layers
2867
         * use setup_sdp_transport(), this should be removed
2868
         * Note that transport_info contains the SDP info from this frame (and
2869
         * not an earlier request (transport_info == &local_transport_info).
2870
         * Use 0 as request_frame since there is no (known) request.
2871
         */
2872
120
        apply_sdp_transport(pinfo, transport_info, 0, setup_info);
2873
        /* Save the list of setup info of calls with the same RTP information
2874
         * to the packet in file scope, since transport_info is local and
2875
         * we won't do this on future passes.
2876
         */
2877
120
        p_add_proto_data(wmem_file_scope(), pinfo, proto_sdp, 0, transport_info->sdp_setup_info_list);
2878
120
    }
2879
2880
    /* Add information to the VoIP Calls dialog. */
2881
346
    for (unsigned i = 0; i < wmem_array_get_count(local_transport_info.media_descriptions); i++)
2882
221
    {
2883
221
        media_desc = (media_description_t *)wmem_array_index(local_transport_info.media_descriptions, i);
2884
2885
221
        if (media_desc->media_port != 0) {
2886
            /* Create the RTP summary str for the Voip Call analysis.
2887
             * XXX - Currently this is based only on the current packet
2888
             */
2889
60
            for (int j = 0; j < media_desc->media.pt_count; j++)
2890
1
            {
2891
1
                DPRINT(("in for-loop for voip call analysis setting for media #%d, pt=%d",
2892
1
                        j, media_desc->media. pt[j]));
2893
                /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
2894
1
                if ((media_desc->media.pt[j] >= 96) && (media_desc->media.pt[j] <= 127)) {
2895
0
                    const char *payload_type_str = rtp_dyn_payload_get_name(
2896
0
                        media_desc->media.rtp_dyn_payload,
2897
0
                        media_desc->media.pt[j]);
2898
0
                    if (payload_type_str) {
2899
0
                        if (strlen(sdp_pi->summary_str))
2900
0
                            (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2901
0
                        (void) g_strlcat(sdp_pi->summary_str, payload_type_str, 50);
2902
0
                    } else {
2903
0
                        char num_pt[10];
2904
0
                        snprintf(num_pt, 10, "%u", media_desc->media.pt[j]);
2905
0
                        if (strlen(sdp_pi->summary_str))
2906
0
                            (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2907
0
                        (void) g_strlcat(sdp_pi->summary_str, num_pt, 50);
2908
0
                      }
2909
1
                } else {
2910
1
                    if (strlen(sdp_pi->summary_str))
2911
0
                        (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2912
1
                    (void) g_strlcat(sdp_pi->summary_str,
2913
1
                              val_to_str_ext(pinfo->pool, media_desc->media.pt[j], &rtp_payload_type_short_vals_ext, "%u"),
2914
1
                              50);
2915
1
                }
2916
1
            }
2917
59
        }
2918
2919
        /* Create the T38 summary str for the Voip Call analysis
2920
         * XXX - Currently this is based only on the current packet
2921
         */
2922
221
        if ((media_desc->media_port != 0) && media_desc->proto == SDP_PROTO_T38) {
2923
0
            if (strlen(sdp_pi->summary_str))
2924
0
                (void) g_strlcat(sdp_pi->summary_str, " ", 50);
2925
0
            (void) g_strlcat(sdp_pi->summary_str, "t38", 50);
2926
0
        }
2927
221
    }
2928
2929
    /* Free all media hash tables that were not assigned to a conversation
2930
     * ('set_rtp' is false) */
2931
125
    if (transport_info == &local_transport_info) {
2932
120
        clean_unused_media_descriptions(transport_info->media_descriptions);
2933
120
    }
2934
2935
125
    datalen = tvb_captured_length_remaining(tvb, offset);
2936
125
    if (datalen > 0) {
2937
12
        proto_tree_add_item(sdp_tree, hf_sdp_data, tvb, offset, datalen, ENC_NA);
2938
12
    }
2939
    /* Add Trace info */
2940
125
    wmem_array_t *setup_info_list = transport_info->sdp_setup_info_list;
2941
125
    if (!setup_info_list) {
2942
120
        setup_info_list = (wmem_array_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sdp, 0);
2943
120
    }
2944
125
    if (setup_info_list) {
2945
0
        unsigned i;
2946
0
        sdp_setup_info_t *stored_setup_info;
2947
0
        proto_item *item;
2948
0
        for (i = 0; i < wmem_array_get_count(setup_info_list); i++) {
2949
0
            stored_setup_info = (sdp_setup_info_t *)wmem_array_index(setup_info_list, i);
2950
0
            if (stored_setup_info->hf_id) {
2951
0
                if (stored_setup_info->hf_type == SDP_TRACE_ID_HF_TYPE_STR) {
2952
0
                    item = proto_tree_add_string(sdp_tree, stored_setup_info->hf_id, tvb, 0, 0, stored_setup_info->trace_id.str);
2953
0
                    proto_item_set_generated(item);
2954
0
                    if (stored_setup_info->add_hidden == true) {
2955
0
                        proto_item_set_hidden(item);
2956
0
                    }
2957
0
                } else if (stored_setup_info->hf_type == SDP_TRACE_ID_HF_TYPE_UINT32) {
2958
0
                    item = proto_tree_add_uint(sdp_tree, stored_setup_info->hf_id, tvb, 0, 0, stored_setup_info->trace_id.num);
2959
0
                    proto_item_set_generated(item);
2960
0
                    if (stored_setup_info->add_hidden == true) {
2961
0
                        proto_item_set_hidden(item);
2962
0
                    }
2963
0
                }
2964
0
            }
2965
0
        }
2966
0
    }
2967
    /* Report this packet to the tap */
2968
125
    tap_queue_packet(sdp_tap, pinfo, sdp_pi);
2969
2970
125
    return tvb_captured_length(tvb);
2971
125
}
2972
2973
void
2974
proto_register_sdp(void)
2975
14
{
2976
14
    static hf_register_info hf[] = {
2977
14
        { &hf_protocol_version,
2978
14
            { "Session Description Protocol Version (v)", "sdp.version",
2979
14
              FT_STRING, BASE_NONE, NULL, 0x0,
2980
14
              NULL, HFILL }
2981
14
        },
2982
14
        { &hf_owner,
2983
14
            { "Owner/Creator, Session Id (o)",
2984
14
              "sdp.owner", FT_STRING, BASE_NONE, NULL,
2985
14
              0x0, NULL, HFILL}
2986
14
        },
2987
14
        { &hf_session_name,
2988
14
            { "Session Name (s)", "sdp.session_name",
2989
14
              FT_STRING, BASE_NONE, NULL, 0x0,
2990
14
              NULL, HFILL }
2991
14
        },
2992
14
        { &hf_session_info,
2993
14
            { "Session Information (i)", "sdp.session_info",
2994
14
              FT_STRING, BASE_NONE, NULL, 0x0,
2995
14
              NULL, HFILL }
2996
14
        },
2997
14
        { &hf_uri,
2998
14
            { "URI of Description (u)", "sdp.uri",
2999
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3000
14
              NULL, HFILL }
3001
14
        },
3002
14
        { &hf_email,
3003
14
            { "E-mail Address (e)", "sdp.email",
3004
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3005
14
              NULL, HFILL }
3006
14
        },
3007
14
        { &hf_phone,
3008
14
            { "Phone Number (p)", "sdp.phone",
3009
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3010
14
              NULL, HFILL }
3011
14
        },
3012
14
        { &hf_connection_info,
3013
14
            { "Connection Information (c)", "sdp.connection_info",
3014
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3015
14
              NULL, HFILL }
3016
14
        },
3017
14
        { &hf_bandwidth,
3018
14
            { "Bandwidth Information (b)", "sdp.bandwidth",
3019
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3020
14
              NULL, HFILL }
3021
14
        },
3022
14
        { &hf_timezone,
3023
14
            { "Time Zone Adjustments (z)", "sdp.timezone",
3024
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3025
14
              NULL, HFILL }
3026
14
        },
3027
14
        { &hf_encryption_key,
3028
14
            { "Encryption Key (k)", "sdp.encryption_key",
3029
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3030
14
              NULL, HFILL }
3031
14
        },
3032
14
        { &hf_session_attribute,
3033
14
            { "Session Attribute (a)", "sdp.session_attr",
3034
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3035
14
              NULL, HFILL }
3036
14
        },
3037
14
        { &hf_media_attribute,
3038
14
            { "Media Attribute (a)", "sdp.media_attr",
3039
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3040
14
              NULL, HFILL }
3041
14
        },
3042
14
        { &hf_time,
3043
14
            { "Time Description, active time (t)",
3044
14
              "sdp.time", FT_STRING, BASE_NONE, NULL,
3045
14
              0x0, NULL, HFILL }
3046
14
        },
3047
14
        { &hf_repeat_time,
3048
14
            { "Repeat Time (r)", "sdp.repeat_time",
3049
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3050
14
              NULL, HFILL }
3051
14
        },
3052
14
        { &hf_media,
3053
14
            { "Media Description, name and address (m)",
3054
14
              "sdp.media", FT_STRING, BASE_NONE, NULL, 0x0,
3055
14
              NULL, HFILL }
3056
14
        },
3057
14
        { &hf_media_title,
3058
14
            { "Media Title (i)", "sdp.media_title",
3059
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3060
14
              NULL, HFILL }
3061
14
        },
3062
14
        { &hf_unknown,
3063
14
            { "Unknown", "sdp.unknown",
3064
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3065
14
              NULL, HFILL }
3066
14
        },
3067
14
        { &hf_invalid,
3068
14
            { "Invalid line", "sdp.invalid",
3069
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3070
14
              NULL, HFILL }
3071
14
        },
3072
14
        { &hf_owner_username,
3073
14
            { "Owner Username", "sdp.owner.username",
3074
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3075
14
              NULL, HFILL }
3076
14
        },
3077
14
        { &hf_owner_sessionid,
3078
14
            { "Session ID", "sdp.owner.sessionid",
3079
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3080
14
              NULL, HFILL }
3081
14
        },
3082
14
        { &hf_owner_version,
3083
14
            { "Session Version", "sdp.owner.version",
3084
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3085
14
              NULL, HFILL }
3086
14
        },
3087
14
        { &hf_owner_network_type,
3088
14
            { "Owner Network Type", "sdp.owner.network_type",
3089
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3090
14
              NULL, HFILL }
3091
14
        },
3092
14
        { &hf_owner_address_type,
3093
14
            { "Owner Address Type", "sdp.owner.address_type",
3094
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3095
14
              NULL, HFILL }
3096
14
        },
3097
14
        { &hf_owner_address,
3098
14
            { "Owner Address", "sdp.owner.address",
3099
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3100
14
              NULL, HFILL }
3101
14
        },
3102
14
        { &hf_connection_info_network_type,
3103
14
            { "Connection Network Type", "sdp.connection_info.network_type",
3104
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3105
14
              NULL, HFILL }
3106
14
        },
3107
14
        { &hf_connection_info_address_type,
3108
14
            { "Connection Address Type", "sdp.connection_info.address_type",
3109
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3110
14
              NULL, HFILL }
3111
14
        },
3112
14
        { &hf_connection_info_connection_address,
3113
14
            { "Connection Address", "sdp.connection_info.address",
3114
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3115
14
              NULL, HFILL }
3116
14
        },
3117
14
        { &hf_connection_info_ttl,
3118
14
            { "Connection TTL", "sdp.connection_info.ttl",
3119
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3120
14
              NULL, HFILL }
3121
14
        },
3122
14
        { &hf_connection_info_num_addr,
3123
14
            { "Connection Number of Addresses", "sdp.connection_info.num_addr",
3124
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3125
14
              NULL, HFILL }
3126
14
        },
3127
14
        { &hf_bandwidth_modifier,
3128
14
            { "Bandwidth Modifier", "sdp.bandwidth.modifier",
3129
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3130
14
              NULL, HFILL }
3131
14
        },
3132
14
        { &hf_bandwidth_value,
3133
14
            { "Bandwidth Value", "sdp.bandwidth.value",
3134
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3135
14
              "Bandwidth Value (in kbits/s)", HFILL }
3136
14
        },
3137
14
        { &hf_time_start,
3138
14
            { "Session Start Time", "sdp.time.start",
3139
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3140
14
              NULL, HFILL }
3141
14
        },
3142
14
        { &hf_time_stop,
3143
14
            { "Session Stop Time", "sdp.time.stop",
3144
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3145
14
              NULL, HFILL }
3146
14
        },
3147
14
        { &hf_repeat_time_interval,
3148
14
            { "Repeat Interval", "sdp.repeat_time.interval",
3149
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3150
14
              NULL, HFILL }
3151
14
        },
3152
14
        { &hf_repeat_time_duration,
3153
14
            { "Repeat Duration", "sdp.repeat_time.duration",
3154
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3155
14
              NULL, HFILL }
3156
14
        },
3157
14
        { &hf_repeat_time_offset,
3158
14
            { "Repeat Offset", "sdp.repeat_time.offset",
3159
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3160
14
              NULL, HFILL }
3161
14
        },
3162
14
        { &hf_timezone_time,
3163
14
            { "Timezone Time", "sdp.timezone.time",
3164
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3165
14
              NULL, HFILL }
3166
14
        },
3167
14
        { &hf_timezone_offset,
3168
14
            { "Timezone Offset", "sdp.timezone.offset",
3169
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3170
14
              NULL, HFILL }
3171
14
        },
3172
14
        { &hf_encryption_key_type,
3173
14
            { "Key Type", "sdp.encryption_key.type",
3174
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3175
14
              NULL, HFILL }
3176
14
        },
3177
14
        { &hf_encryption_key_data,
3178
14
            { "Key Data", "sdp.encryption_key.data",
3179
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3180
14
              NULL, HFILL }
3181
14
        },
3182
14
        { &hf_session_attribute_field,
3183
14
            { "Session Attribute Fieldname", "sdp.session_attr.field",
3184
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3185
14
              NULL, HFILL }
3186
14
        },
3187
14
        { &hf_session_attribute_value,
3188
14
            { "Session Attribute Value", "sdp.session_attr.value",
3189
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3190
14
              NULL, HFILL }
3191
14
        },
3192
14
        { &hf_media_media,
3193
14
            { "Media Type", "sdp.media.media",
3194
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3195
14
              NULL, HFILL }
3196
14
        },
3197
14
        { &hf_media_port,
3198
14
            { "Media Port", "sdp.media.port",
3199
14
              FT_UINT16, BASE_PT_UDP, NULL, 0x0,
3200
14
              NULL, HFILL }
3201
14
        },
3202
14
        { &hf_media_port_string,
3203
14
            { "Media Port", "sdp.media.port_string",
3204
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3205
14
              NULL, HFILL }
3206
14
        },
3207
14
        { &hf_media_portcount,
3208
14
            { "Media Port Count", "sdp.media.portcount",
3209
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3210
14
              NULL, HFILL }
3211
14
        },
3212
14
        { &hf_media_proto,
3213
14
            { "Media Protocol", "sdp.media.proto",
3214
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3215
14
              NULL, HFILL }
3216
14
        },
3217
14
        { &hf_media_format,
3218
14
            { "Media Format", "sdp.media.format",
3219
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3220
14
              NULL, HFILL }
3221
14
        },
3222
14
        { &hf_media_attribute_field,
3223
14
            { "Media Attribute Fieldname", "sdp.media_attribute.field",
3224
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3225
14
              NULL, HFILL }
3226
14
        },
3227
14
        { &hf_media_attribute_value,
3228
14
            { "Media Attribute Value", "sdp.media_attribute.value",
3229
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3230
14
              NULL, HFILL }
3231
14
        },
3232
14
        { &hf_media_encoding_name,
3233
14
            { "MIME Type", "sdp.mime.type",
3234
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3235
14
              "SDP MIME Type", HFILL }
3236
14
        },
3237
14
        { &hf_media_sample_rate,
3238
14
            { "Sample Rate", "sdp.sample_rate",
3239
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3240
14
              NULL, HFILL }
3241
14
        },
3242
14
        { &hf_media_channels,
3243
14
            { "Audio Channels", "sdp.channels",
3244
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3245
14
              NULL, HFILL }
3246
14
        },
3247
14
        { &hf_media_format_specific_parameter,
3248
14
            { "Media format specific parameters", "sdp.fmtp.parameter",
3249
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3250
14
              "Format specific parameter(fmtp)", HFILL }
3251
14
        },
3252
14
        { &hf_ipbcp_version,
3253
14
            { "IPBCP Protocol Version", "sdp.ipbcp.version",
3254
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3255
14
              NULL, HFILL }
3256
14
        },
3257
14
        { &hf_ipbcp_type,
3258
14
            { "IPBCP Command Type", "sdp.ipbcp.command",
3259
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3260
14
              NULL, HFILL }
3261
14
        },
3262
14
        {&hf_sdp_fmtp_mpeg4_profile_level_id,
3263
14
           { "Level Code", "sdp.fmtp.profile_level_id",
3264
14
             FT_UINT32, BASE_DEC, VALS(mp4ves_level_indication_vals), 0x0,
3265
14
             NULL, HFILL }
3266
14
        },
3267
14
        { &hf_sdp_fmtp_h263_profile,
3268
14
            { "Profile", "sdp.fmtp.h263profile",
3269
14
              FT_UINT32, BASE_DEC, VALS(h263_profile_vals), 0x0,
3270
14
              NULL, HFILL }
3271
14
        },
3272
14
        { &hf_sdp_fmtp_h263_level,
3273
14
            { "Level", "sdp.fmtp.h263level",
3274
14
              FT_UINT32, BASE_DEC, VALS(h263_level_vals), 0x0,
3275
14
              NULL, HFILL }
3276
14
        },
3277
14
        { &hf_sdp_h264_packetization_mode,
3278
14
            { "Packetization mode", "sdp.fmtp.h264_packetization_mode",
3279
14
              FT_UINT32, BASE_DEC, VALS(h264_packetization_mode_vals), 0x0,
3280
14
              NULL, HFILL }
3281
14
        },
3282
14
        { &hf_SDPh223LogicalChannelParameters,
3283
14
            { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
3284
14
              FT_NONE, BASE_NONE, NULL, 0,
3285
14
              NULL, HFILL }
3286
14
        },
3287
14
        { &hf_key_mgmt_att_value,
3288
14
            { "Key Management", "sdp.key_mgmt",
3289
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3290
14
              NULL, HFILL }
3291
14
        },
3292
14
        { &hf_key_mgmt_prtcl_id,
3293
14
            { "Key Management Protocol (kmpid)", "sdp.key_mgmt.kmpid",
3294
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3295
14
              NULL, HFILL }
3296
14
        },
3297
14
        { &hf_key_mgmt_data,
3298
14
            { "Key Management Data", "sdp.key_mgmt.data",
3299
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
3300
14
              NULL, HFILL }
3301
14
        },
3302
14
        { &hf_sdp_crypto_tag,
3303
14
            { "tag", "sdp.crypto.tag",
3304
14
              FT_UINT32, BASE_DEC, NULL, 0x0,
3305
14
              NULL, HFILL }
3306
14
        },
3307
14
        { &hf_sdp_crypto_crypto_suite,
3308
14
            { "Crypto suite", "sdp.crypto.crypto_suite",
3309
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3310
14
              NULL, HFILL }
3311
14
        },
3312
14
        { &hf_sdp_crypto_master_key,
3313
14
            { "Master Key", "sdp.crypto.master_key",
3314
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
3315
14
              NULL, HFILL }
3316
14
        },
3317
14
        { &hf_sdp_crypto_master_salt,
3318
14
            { "Master salt", "sdp.crypto.master_salt",
3319
14
              FT_BYTES, BASE_NONE, NULL, 0x0,
3320
14
              NULL, HFILL }
3321
14
        },
3322
14
        { &hf_sdp_crypto_lifetime,
3323
14
            { "Lifetime", "sdp.crypto.lifetime",
3324
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3325
14
              NULL, HFILL }
3326
14
        },
3327
14
        { &hf_sdp_crypto_mki,
3328
14
            { "mki-value", "sdp.crypto.mki-valu",
3329
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3330
14
              NULL, HFILL }
3331
14
        },
3332
14
        { &hf_sdp_crypto_mki_length,
3333
14
            { "mki_length", "sdp.crypto.mki_length",
3334
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3335
14
              NULL, HFILL }
3336
14
        },
3337
14
        { &hf_ice_candidate_foundation,
3338
14
            { "Foundation", "sdp.ice_candidate.foundation",
3339
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3340
14
              "Identifier, same for two candidates with same type, base address, protocol and STUN server", HFILL }
3341
14
        },
3342
14
        { &hf_ice_candidate_componentid,
3343
14
            { "Component ID", "sdp.ice_candidate.componentid",
3344
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3345
14
              "Media component identifier (For RTP media, 1 is RTP, 2 is RTCP)", HFILL }
3346
14
        },
3347
14
        { &hf_ice_candidate_transport,
3348
14
            { "Transport", "sdp.ice_candidate.transport",
3349
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3350
14
              "Transport protocol", HFILL }
3351
14
        },
3352
14
        { &hf_ice_candidate_priority,
3353
14
            { "Priority", "sdp.ice_candidate.priority",
3354
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3355
14
              NULL, HFILL }
3356
14
        },
3357
14
        { &hf_ice_candidate_address,
3358
14
            { "Connection Address", "sdp.ice_candidate.address",
3359
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3360
14
              "IP address or FQDN of the candidate", HFILL }
3361
14
        },
3362
14
        { &hf_ice_candidate_port,
3363
14
            { "Candidate Port", "sdp.ice_candidate.port",
3364
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3365
14
              "Port of the candidate", HFILL }
3366
14
        },
3367
14
        { &hf_ice_candidate_type,
3368
14
            { "Candidate Type", "sdp.ice_candidate.type",
3369
14
              FT_STRING, BASE_NONE, NULL, 0x0,
3370
14
              "The origin of the address and port, i.e. where it was learned", HFILL }
3371
14
        },
3372
      /* Generated from convert_proto_tree_add_text.pl */
3373
14
      { &hf_sdp_nal_unit_1_string, { "NAL unit 1 string", "sdp.nal_unit_1_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3374
14
      { &hf_sdp_nal_unit_2_string, { "NAL unit 2 string", "sdp.nal_unit_2_string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3375
14
      { &hf_sdp_key_and_salt, { "Key and Salt", "sdp.key_and_salt", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3376
14
      { &hf_sdp_data, { "Data", "sdp.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3377
14
    };
3378
14
    static int *ett[] = {
3379
14
        &ett_sdp,
3380
14
        &ett_sdp_owner,
3381
14
        &ett_sdp_connection_info,
3382
14
        &ett_sdp_bandwidth,
3383
14
        &ett_sdp_time,
3384
14
        &ett_sdp_repeat_time,
3385
14
        &ett_sdp_timezone,
3386
14
        &ett_sdp_encryption_key,
3387
14
        &ett_sdp_session_attribute,
3388
14
        &ett_sdp_media,
3389
14
        &ett_sdp_media_attribute,
3390
14
        &ett_sdp_fmtp,
3391
14
        &ett_sdp_key_mgmt,
3392
14
        &ett_sdp_crypto_key_parameters,
3393
14
    };
3394
3395
14
    static ei_register_info ei[] = {
3396
14
        { &ei_sdp_invalid_key_param,
3397
14
            { "sdp.invalid_key_param",
3398
14
              PI_MALFORMED, PI_NOTE,
3399
14
              "Invalid key-param (no ':' delimiter)",
3400
14
              EXPFILL
3401
14
            }
3402
14
        },
3403
14
        { &ei_sdp_invalid_line_equal,
3404
14
            { "sdp.invalid_line.no_equal",
3405
14
              PI_MALFORMED, PI_NOTE,
3406
14
              "Invalid SDP line (no '=' delimiter)",
3407
14
              EXPFILL
3408
14
            }
3409
14
        },
3410
14
        { &ei_sdp_invalid_line_fields,
3411
14
            { "sdp.invalid_line.missing_fields",
3412
14
              PI_MALFORMED, PI_ERROR,
3413
14
              "Invalid SDP line (missing required fields)",
3414
14
              EXPFILL
3415
14
            }
3416
14
        },
3417
14
        { &ei_sdp_invalid_line_space,
3418
14
            { "sdp.invalid_line.extra_space",
3419
14
              PI_MALFORMED, PI_ERROR,
3420
14
              "Invalid SDP whitespace (extra space character)",
3421
14
              EXPFILL
3422
14
            }
3423
14
        },
3424
14
        { &ei_sdp_invalid_conversion,
3425
14
            { "sdp.invalid_conversion",
3426
14
              PI_PROTOCOL, PI_WARN,
3427
14
              "Invalid conversion",
3428
14
              EXPFILL
3429
14
            }
3430
14
        },
3431
14
        { &ei_sdp_invalid_media_port,
3432
14
            { "sdp.invalid_media_port",
3433
14
              PI_MALFORMED, PI_ERROR,
3434
14
              "Invalid media port",
3435
14
              EXPFILL
3436
14
            }
3437
14
        },
3438
14
        { &ei_sdp_invalid_sample_rate,
3439
14
            { "sdp.invalid_sample_rate",
3440
14
              PI_MALFORMED, PI_ERROR,
3441
14
              "Invalid sample rate",
3442
14
              EXPFILL
3443
14
            }
3444
14
        },
3445
14
        { &ei_sdp_invalid_channels,
3446
14
            { "sdp.invalid_channels",
3447
14
              PI_MALFORMED, PI_WARN,
3448
14
              "Invalid number of audio channels",
3449
14
              EXPFILL
3450
14
            }
3451
14
        },
3452
14
        { &ei_sdp_invalid_media_format,
3453
14
            { "sdp.invalid_media_format",
3454
14
              PI_MALFORMED, PI_ERROR,
3455
14
              "Invalid media format",
3456
14
              EXPFILL
3457
14
            }
3458
14
        },
3459
14
        { &ei_sdp_invalid_crypto_tag,
3460
14
            { "sdp.invalid_crypto_tag",
3461
14
              PI_MALFORMED, PI_ERROR,
3462
14
              "Invalid crypto tag",
3463
14
              EXPFILL
3464
14
            }
3465
14
        },
3466
14
        { &ei_sdp_invalid_crypto_mki_length,
3467
14
            { "sdp.invalid_crypto_mki_length",
3468
14
              PI_MALFORMED, PI_ERROR,
3469
14
              "Invalid crypto mki length",
3470
14
              EXPFILL
3471
14
            }
3472
14
        }
3473
14
    };
3474
3475
14
    module_t *sdp_module;
3476
14
    expert_module_t* expert_sdp;
3477
3478
14
    proto_sdp = proto_register_protocol("Session Description Protocol",
3479
14
                                        "SDP", "sdp");
3480
14
    proto_register_field_array(proto_sdp, hf, array_length(hf));
3481
14
    proto_register_subtree_array(ett, array_length(ett));
3482
14
    expert_sdp = expert_register_protocol(proto_sdp);
3483
14
    expert_register_field_array(expert_sdp, ei, array_length(ei));
3484
3485
14
    key_mgmt_dissector_table = register_dissector_table("key_mgmt",
3486
14
                                                        "Key Management", proto_sdp, FT_STRING, STRING_CASE_SENSITIVE);
3487
    /*
3488
     * Preferences registration
3489
     */
3490
14
    sdp_module = prefs_register_protocol(proto_sdp, NULL);
3491
14
    prefs_register_bool_preference(sdp_module, "establish_conversation",
3492
14
                                   "Establish Media Conversation",
3493
14
                                   "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
3494
14
                                   "upon port numbers found in SDP payload",
3495
14
                                   &global_sdp_establish_conversation);
3496
3497
14
    sdp_transport_reqs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3498
14
    sdp_transport_rsps = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3499
14
    sdp_rtsp_control_map = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), wmem_str_hash, g_str_equal);
3500
3501
    /*
3502
     * Register the dissector by name, so other dissectors can
3503
     * grab it by name rather than just referring to it directly.
3504
     */
3505
14
    sdp_handle = register_dissector("sdp", dissect_sdp, proto_sdp);
3506
3507
    /* Register for tapping */
3508
14
    sdp_tap = register_tap("sdp");
3509
3510
    /* compile patterns */
3511
14
    ws_mempbrk_compile(&pbrk_digits, "0123456789");
3512
14
    ws_mempbrk_compile(&pbrk_alpha, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
3513
14
}
3514
3515
void
3516
proto_reg_handoff_sdp(void)
3517
14
{
3518
14
    rtcp_handle   = find_dissector_add_dependency("rtcp", proto_sdp);
3519
14
    msrp_handle   = find_dissector_add_dependency("msrp", proto_sdp);
3520
14
    sprt_handle   = find_dissector_add_dependency("sprt", proto_sdp);
3521
14
    bfcp_handle   = find_dissector_add_dependency("bfcp", proto_sdp);
3522
14
    h264_handle   = find_dissector_add_dependency("h264", proto_sdp);
3523
14
    h265_handle   = find_dissector_add_dependency("h265", proto_sdp);
3524
14
    mp4ves_config_handle = find_dissector_add_dependency("mp4ves_config", proto_sdp);
3525
3526
14
    proto_sprt    = dissector_handle_get_protocol_index(find_dissector("sprt"));
3527
3528
14
    dissector_add_string("media_type", "application/sdp", sdp_handle);
3529
14
    dissector_add_uint("bctp.tpi", 0x20, sdp_handle);
3530
14
}
3531
3532
/*
3533
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3534
 *
3535
 * Local variables:
3536
 * c-basic-offset: 4
3537
 * tab-width: 8
3538
 * indent-tabs-mode: nil
3539
 * End:
3540
 *
3541
 * vi: set shiftwidth=4 tabstop=8 expandtab:
3542
 * :indentSize=4:tabSize=8:noTabs=true:
3543
 */