14a579a40052cd59b6bf3a33e862b4eed5aaf580
[obnox/wireshark/wip.git] / epan / dissectors / packet-sdp.c
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  * $Id$
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26  * Ref http://www.ietf.org/rfc/rfc4566.txt?number=4566
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdlib.h>
34 #include <ctype.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
38 #endif
39 #ifdef HAVE_SYS_SOCKET_H
40 #include <sys/socket.h>
41 #endif
42 #ifdef HAVE_NETINET_IN_H
43 # include <netinet/in.h>
44 #endif
45 #ifdef HAVE_ARPA_INET_H
46 #include <arpa/inet.h>
47 #endif
48
49 #ifdef HAVE_WINSOCK2_H
50 #include <winsock2.h>           /* needed to define AF_ values on Windows */
51 #endif
52
53 #ifdef NEED_INET_V6DEFS_H
54 # include "wsutil/inet_v6defs.h"
55 #endif
56
57 #include <glib.h>
58
59 #include <epan/packet.h>
60 #include <epan/strutil.h>
61 #include <epan/emem.h>
62 #include <epan/base64.h>
63 #include <epan/asn1.h>
64 #include <epan/prefs.h>
65 #include <epan/expert.h>
66 #include <epan/tap.h>
67
68 #include "packet-sdp.h"
69
70 #include "packet-rtp.h"
71 #include <epan/rtp_pt.h>
72
73 #include "packet-rtcp.h"
74 #include "packet-t38.h"
75 #include "packet-msrp.h"
76 #include "packet-per.h"
77 #include "packet-h245.h"
78 #include "packet-h264.h"
79 #include "packet-mp4ves.h"
80
81 static dissector_handle_t rtp_handle    = NULL;
82 static dissector_handle_t rtcp_handle   = NULL;
83 static dissector_handle_t t38_handle    = NULL;
84 static dissector_handle_t msrp_handle   = NULL;
85 static dissector_handle_t h264_handle   = NULL;
86 static dissector_handle_t mp4ves_handle = NULL;
87
88 static int sdp_tap = -1;
89
90 static int proto_sdp = -1;
91
92 /* preference globals */
93 static gboolean global_sdp_establish_conversation = TRUE;
94
95 /* Top level fields */
96 static int hf_protocol_version = -1;
97 static int hf_owner = -1;
98 static int hf_session_name = -1;
99 static int hf_session_info = -1;
100 static int hf_uri = -1;
101 static int hf_email = -1;
102 static int hf_phone = -1;
103 static int hf_connection_info = -1;
104 static int hf_bandwidth = -1;
105 static int hf_timezone = -1;
106 static int hf_encryption_key = -1;
107 static int hf_session_attribute = -1;
108 static int hf_media_attribute = -1;
109 static int hf_time = -1;
110 static int hf_repeat_time = -1;
111 static int hf_media = -1;
112 static int hf_media_title = -1;
113 static int hf_unknown = -1;
114 static int hf_invalid = -1;
115 static int hf_ipbcp_version = -1;
116 static int hf_ipbcp_type = -1;
117
118 /* hf_owner subfields*/
119 static int hf_owner_username = -1;
120 static int hf_owner_sessionid = -1;
121 static int hf_owner_version = -1;
122 static int hf_owner_network_type = -1;
123 static int hf_owner_address_type = -1;
124 static int hf_owner_address = -1;
125
126 /* hf_connection_info subfields */
127 static int hf_connection_info_network_type = -1;
128 static int hf_connection_info_address_type = -1;
129 static int hf_connection_info_connection_address = -1;
130 static int hf_connection_info_ttl = -1;
131 static int hf_connection_info_num_addr = -1;
132
133 /* hf_bandwidth subfields */
134 static int hf_bandwidth_modifier = -1;
135 static int hf_bandwidth_value = -1;
136
137 /* hf_time subfields */
138 static int hf_time_start = -1;
139 static int hf_time_stop = -1;
140
141 /* hf_repeat_time subfield */
142 static int hf_repeat_time_interval = -1;
143 static int hf_repeat_time_duration = -1;
144 static int hf_repeat_time_offset = -1;
145
146 /* hf_timezone subfields */
147 static int hf_timezone_time = -1;
148 static int hf_timezone_offset = -1;
149
150 /* hf_encryption_key subfields */
151 static int hf_encryption_key_type = -1;
152 static int hf_encryption_key_data = -1;
153
154 /* hf_session_attribute subfields */
155 static int hf_session_attribute_field = -1;
156 static int hf_session_attribute_value = -1;
157
158 /* hf_media subfields */
159 static int hf_media_media = -1;
160 static int hf_media_port = -1;
161 static int hf_media_portcount = -1;
162 static int hf_media_proto = -1;
163 static int hf_media_format = -1;
164
165 /* hf_session_attribute subfields */
166 static int hf_media_attribute_field = -1;
167 static int hf_media_attribute_value = -1;
168 static int hf_media_encoding_name = -1;
169 static int hf_media_sample_rate = -1;
170 static int hf_media_format_specific_parameter = -1;
171 static int hf_sdp_fmtp_mpeg4_profile_level_id = -1;
172 static int hf_sdp_fmtp_h263_profile = -1;
173 static int hf_sdp_fmtp_h263_level = -1;
174 static int hf_sdp_h264_packetization_mode = -1;
175 static int hf_sdp_h264_sprop_parameter_sets = -1;
176 static int hf_SDPh223LogicalChannelParameters = -1;
177
178 /* hf_session_attribute hf_media_attribute subfields */
179 static int hf_key_mgmt_att_value = -1;
180 static int hf_key_mgmt_prtcl_id = -1;
181 static int hf_key_mgmt_data = -1;
182
183 /* trees */
184 static int ett_sdp = -1;
185 static int ett_sdp_owner = -1;
186 static int ett_sdp_connection_info = -1;
187 static int ett_sdp_bandwidth = -1;
188 static int ett_sdp_time = -1;
189 static int ett_sdp_repeat_time = -1;
190 static int ett_sdp_timezone = -1;
191 static int ett_sdp_encryption_key = -1;
192 static int ett_sdp_session_attribute = -1;
193 static int ett_sdp_media = -1;
194 static int ett_sdp_media_attribute = -1;
195 static int ett_sdp_fmtp = -1;
196 static int ett_sdp_key_mgmt = -1;
197
198
199 #define SDP_MAX_RTP_CHANNELS 4
200 #define SDP_MAX_RTP_PAYLOAD_TYPES 20
201 #define SDP_NO_OF_PT 128
202 typedef struct {
203   gint32 pt[SDP_MAX_RTP_PAYLOAD_TYPES];
204   gint8 pt_count;
205   GHashTable *rtp_dyn_payload;
206 } transport_media_pt_t;
207
208 typedef struct {
209   char *connection_address;
210   char *connection_type;
211   char *media_type;
212   char *encoding_name[SDP_NO_OF_PT];
213   int   sample_rate[SDP_NO_OF_PT];
214   char *media_port[SDP_MAX_RTP_CHANNELS];
215   char *media_proto[SDP_MAX_RTP_CHANNELS];
216   transport_media_pt_t media[SDP_MAX_RTP_CHANNELS];
217   gint8 media_count;
218 } transport_info_t;
219
220
221 /* MSRP transport info (as set while parsing path attribute) */
222 static gboolean msrp_transport_address_set = FALSE;
223 static guint32  msrp_ipaddr[4];
224 static guint16  msrp_port_number;
225
226 /* key-mgmt dissector
227  * IANA registry:
228  * http://www.iana.org/assignments/sdp-parameters
229  */
230 static dissector_table_t key_mgmt_dissector_table;
231
232
233 /* Protocol registration */
234 void proto_register_sdp(void);
235 void proto_reg_handoff_sdp(void);
236
237
238 /* static functions */
239
240 static void call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,
241                                   transport_info_t *transport_info);
242
243 /* Subdissector functions */
244 static void dissect_sdp_owner(tvbuff_t *tvb, proto_item* ti);
245 static void dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
246                                         transport_info_t *transport_info);
247 static void dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti);
248 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti);
249 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti);
250 static void dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti);
251 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti);
252 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti);
253 static void dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
254                               transport_info_t *transport_info);
255 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item *ti, int length,transport_info_t *transport_info);
256
257 static void free_encoding_name_str (void *ptr)
258 {
259   encoding_name_and_rate_t *encoding_name_and_rate = (encoding_name_and_rate_t *)ptr;
260
261   if (encoding_name_and_rate->encoding_name) {
262     g_free(encoding_name_and_rate->encoding_name);
263   }
264 }
265
266 static void
267 dissect_sdp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
268 {
269   proto_tree  *sdp_tree;
270   proto_item  *ti, *sub_ti;
271   gint        offset = 0;
272   gint        next_offset;
273   int         linelen;
274   gboolean    in_media_description;
275   guchar      type;
276   guchar      delim;
277   int         datalen;
278   int         tokenoffset;
279   int         hf = -1;
280   char        *string;
281
282   address     src_addr;
283
284   transport_info_t transport_info;
285
286   guint32     port=0;
287   gboolean    is_rtp=FALSE;
288   gboolean    is_srtp=FALSE;
289   gboolean    is_t38=FALSE;
290   gboolean    is_msrp=FALSE;
291   gboolean    set_rtp=FALSE;
292   gboolean    is_ipv4_addr=FALSE;
293   gboolean    is_ipv6_addr=FALSE;
294   gboolean    is_video=FALSE;
295   guint32     ipaddr[4];
296   gint        n,i;
297   sdp_packet_info *sdp_pi;
298   gchar       *unknown_encoding = ep_strdup("Unknown");
299
300   /* Initialise packet info for passing to tap */
301   sdp_pi = ep_alloc(sizeof(sdp_packet_info));
302   sdp_pi->summary_str[0] = '\0';
303
304   /* Initialise RTP channel info */
305   transport_info.connection_address=NULL;
306   transport_info.connection_type=NULL;
307   transport_info.media_type=NULL;
308   for (n=0; n < SDP_NO_OF_PT; n++){
309     transport_info.encoding_name[n]=unknown_encoding;
310     transport_info.sample_rate[n] = 0;
311   }
312   for (n=0; n < SDP_MAX_RTP_CHANNELS; n++)
313   {
314     transport_info.media_port[n]=NULL;
315     transport_info.media_proto[n]=NULL;
316     transport_info.media[n].pt_count = 0;
317     transport_info.media[n].rtp_dyn_payload =
318         g_hash_table_new_full( g_int_hash, g_int_equal, g_free, free_encoding_name_str);
319   }
320   transport_info.media_count = 0;
321
322   /*
323    * As RFC 2327 says, "SDP is purely a format for session
324    * description - it does not incorporate a transport protocol,
325    * and is intended to use different transport protocols as
326    * appropriate including the Session Announcement Protocol,
327    * Session Initiation Protocol, Real-Time Streaming Protocol,
328    * electronic mail using the MIME extensions, and the
329    * Hypertext Transport Protocol."
330    *
331    * We therefore don't set the protocol or info columns;
332    * instead, we append to them, so that we don't erase
333    * what the protocol inside which the SDP stuff resides
334    * put there.
335    */
336   col_append_str(pinfo->cinfo, COL_PROTOCOL, "/SDP");
337
338   /* XXX: Needs description. */
339   col_append_str(pinfo->cinfo, COL_INFO, ", with session description");
340
341   ti = proto_tree_add_item(tree, proto_sdp, tvb, offset, -1, FALSE);
342   sdp_tree = proto_item_add_subtree(ti, ett_sdp);
343
344   /*
345    * Show the SDP message a line at a time.
346    */
347   in_media_description = FALSE;
348
349   while (tvb_reported_length_remaining(tvb, offset) > 0) {
350     /*
351      * Find the end of the line.
352      */
353     linelen = tvb_find_line_end_unquoted(tvb, offset, -1, &next_offset);
354
355
356
357     /*
358      * Line must contain at least e.g. "v=".
359      */
360     if (linelen < 2)
361       break;
362
363     type = tvb_get_guint8(tvb,offset);
364     delim = tvb_get_guint8(tvb,offset + 1);
365     if (delim != '=') {
366       proto_item *ti2 = proto_tree_add_item(sdp_tree, hf_invalid, tvb, offset, linelen, FALSE);
367       expert_add_info_format(pinfo, ti2, PI_MALFORMED, PI_NOTE,
368                              "Invalid SDP line (no '=' delimiter)");
369       offset = next_offset;
370       continue;
371     }
372
373     /*
374      * Attributes.
375      */
376     switch (type) {
377     case 'v':
378       hf = hf_protocol_version;
379       break;
380     case 'o':
381       hf = hf_owner;
382       break;
383     case 's':
384       hf = hf_session_name;
385       break;
386     case 'i':
387       if (in_media_description) {
388         hf = hf_media_title;
389       }
390       else{
391         hf = hf_session_info;
392       }
393       break;
394     case 'u':
395       hf = hf_uri;
396       break;
397     case 'e':
398       hf = hf_email;
399       break;
400     case 'p':
401       hf = hf_phone;
402       break;
403     case 'c':
404       hf = hf_connection_info;
405       break;
406     case 'b':
407       hf = hf_bandwidth;
408       break;
409     case 't':
410       hf = hf_time;
411       break;
412     case 'r':
413       hf = hf_repeat_time;
414       break;
415     case 'm':
416       hf = hf_media;
417       in_media_description = TRUE;
418       break;
419     case 'k':
420       hf = hf_encryption_key;
421       break;
422     case 'a':
423       if (in_media_description) {
424         hf = hf_media_attribute;
425       }
426       else{
427         hf = hf_session_attribute;
428       }
429       break;
430     case 'z':
431       hf = hf_timezone;
432       break;
433     default:
434       hf = hf_unknown;
435       break;
436     }
437     tokenoffset = 2;
438     if (hf == hf_unknown)
439       tokenoffset = 0;
440     string = (char*)tvb_get_ephemeral_string(tvb, offset + tokenoffset,
441                                              linelen - tokenoffset);
442     sub_ti = proto_tree_add_string(sdp_tree, hf, tvb, offset, linelen,
443                                    string);
444     call_sdp_subdissector(tvb_new_subset(tvb,offset+tokenoffset,
445                                          linelen-tokenoffset,
446                                          linelen-tokenoffset),
447                                          pinfo,
448                                          hf,sub_ti,linelen-tokenoffset,&transport_info),
449     offset = next_offset;
450   }
451
452
453   /* Now look, if we have strings collected.
454    * Try to convert ipv4 addresses and ports into binary format,
455    * so we can use them to detect rtp and rtcp streams.
456    * Don't forget to free the strings!
457    */
458
459   for (n = 0; n < transport_info.media_count; n++)
460   {
461     if(transport_info.media_port[n]!=NULL) {
462       port = atol(transport_info.media_port[n]);
463     }
464     if(transport_info.media_proto[n]!=NULL) {
465       /* Check if media protocol is RTP
466        * and stream decoding is enabled in preferences
467        */
468        if(global_sdp_establish_conversation){
469          /* Check if media protocol is RTP */
470          is_rtp = (strcmp(transport_info.media_proto[n],"RTP/AVP")==0);
471          /* Check if media protocol is SRTP */
472          is_srtp = (strcmp(transport_info.media_proto[n],"RTP/SAVP")==0);
473          /* Check if media protocol is T38 */
474          is_t38 = ( (strcmp(transport_info.media_proto[n],"UDPTL")==0) ||
475                     (strcmp(transport_info.media_proto[n],"udptl")==0) );
476          /* Check if media protocol is MSRP/TCP */
477          is_msrp = (strcmp(transport_info.media_proto[n],"msrp/tcp")==0);
478        }
479     }
480
481
482     if(transport_info.connection_address!=NULL) {
483       if(transport_info.connection_type!=NULL) {
484         if (strcmp(transport_info.connection_type,"IP4")==0) {
485           if(inet_pton(AF_INET,transport_info.connection_address, &ipaddr)==1 ) {
486             /* connection_address could be converted to a valid ipv4 address*/
487             is_ipv4_addr=TRUE;
488             src_addr.type=AT_IPv4;
489             src_addr.len=4;
490           }
491         }
492         else if (strcmp(transport_info.connection_type,"IP6")==0){
493           if (inet_pton(AF_INET6, transport_info.connection_address, &ipaddr)==1){
494             /* connection_address could be converted to a valid ipv6 address*/
495             is_ipv6_addr=TRUE;
496             src_addr.type=AT_IPv6;
497             src_addr.len=16;
498           }
499         }
500       }
501     }
502     if (strcmp(transport_info.media_type,"video")==0){
503       is_video = TRUE;
504     }
505     set_rtp = FALSE;
506     /* Add (s)rtp and (s)rtcp conversation, if available (overrides t38 if conversation already set) */
507     if((!pinfo->fd->flags.visited) && port!=0 && (is_rtp||is_srtp) && (is_ipv4_addr || is_ipv6_addr)){
508       src_addr.data=(guint8*)&ipaddr;
509       if(rtp_handle){
510         if (is_srtp) {
511           struct srtp_info *dummy_srtp_info = se_alloc0(sizeof(struct srtp_info));
512           srtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num, is_video,
513                            transport_info.media[n].rtp_dyn_payload, dummy_srtp_info);
514         } else {
515           rtp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num, is_video,
516                           transport_info.media[n].rtp_dyn_payload);
517         }
518         set_rtp = TRUE;
519       }
520       if(rtcp_handle){
521         port++;
522         rtcp_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num);
523       }
524     }
525
526     /* Add t38 conversation, if available and only if no rtp */
527     if((!pinfo->fd->flags.visited) && port!=0 && !set_rtp && is_t38 && is_ipv4_addr){
528       src_addr.data=(guint8*)&ipaddr;
529       if(t38_handle){
530         t38_add_address(pinfo, &src_addr, port, 0, "SDP", pinfo->fd->num);
531       }
532     }
533
534     /* Add MSRP conversation.  Uses addresses discovered in attribute
535        rather than connection information of media session line */
536     if (is_msrp ){
537       if ((!pinfo->fd->flags.visited) && msrp_transport_address_set){
538         if(msrp_handle){
539           src_addr.type=AT_IPv4;
540           src_addr.len=4;
541           src_addr.data=(guint8*)&msrp_ipaddr;
542           msrp_add_address(pinfo, &src_addr, msrp_port_number, "SDP", pinfo->fd->num);
543         }
544       }
545     }
546
547     if (port!=0) {
548       /* Create the RTP summary str for the Voip Call analysis */
549       for (i = 0; i < transport_info.media[n].pt_count; i++)
550       {
551         /* if the payload type is dynamic (96 to 127), check the hash table to add the desc in the SDP summary */
552         if ( (transport_info.media[n].pt[i] >=96) && (transport_info.media[n].pt[i] <=127) ) {
553           encoding_name_and_rate_t *encoding_name_and_rate_pt = g_hash_table_lookup(transport_info.media[n].rtp_dyn_payload, &transport_info.media[n].pt[i]);
554           if (encoding_name_and_rate_pt) {
555             if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
556             g_strlcat(sdp_pi->summary_str, encoding_name_and_rate_pt->encoding_name, 50);
557           } else {
558             char num_pt[10];
559             g_snprintf(num_pt, 10, "%u", transport_info.media[n].pt[i]);
560             if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
561             g_strlcat(sdp_pi->summary_str, num_pt, 50);
562           }
563         } else
564           if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
565           g_strlcat(sdp_pi->summary_str, val_to_str_ext(transport_info.media[n].pt[i], &rtp_payload_type_short_vals_ext, "%u"), 50);
566       }
567     }
568
569     /* Free the hash table if we did't assigned it to a conv use it */
570     if (set_rtp == FALSE)
571       rtp_free_hash_dyn_payload(transport_info.media[n].rtp_dyn_payload);
572
573     /* Create the T38 summary str for the Voip Call analysis */
574     if (port!=0 && is_t38) {
575       if (strlen(sdp_pi->summary_str)) g_strlcat(sdp_pi->summary_str, " ", 50);
576       g_strlcat(sdp_pi->summary_str, "t38", 50);
577     }
578   }
579
580   /* Free the remainded hash tables not used */
581   for (n = transport_info.media_count; n < SDP_MAX_RTP_CHANNELS; n++)
582   {
583     rtp_free_hash_dyn_payload(transport_info.media[n].rtp_dyn_payload);
584   }
585
586
587   datalen = tvb_length_remaining(tvb, offset);
588   if (datalen > 0) {
589     proto_tree_add_text(sdp_tree, tvb, offset, datalen, "Data (%d bytes)",
590                         datalen);
591   }
592
593   /* Report this packet to the tap */
594   tap_queue_packet(sdp_tap, pinfo, sdp_pi);
595 }
596
597 static void
598 call_sdp_subdissector(tvbuff_t *tvb, packet_info *pinfo, int hf, proto_tree* ti, int length,transport_info_t *transport_info){
599   if(hf == hf_owner){
600     dissect_sdp_owner(tvb,ti);
601   } else if ( hf == hf_connection_info) {
602     dissect_sdp_connection_info(tvb,ti,transport_info);
603   } else if ( hf == hf_bandwidth) {
604     dissect_sdp_bandwidth(tvb,ti);
605   } else if ( hf == hf_time) {
606     dissect_sdp_time(tvb,ti);
607   } else if ( hf == hf_repeat_time ){
608     dissect_sdp_repeat_time(tvb,ti);
609   } else if ( hf == hf_timezone ) {
610     dissect_sdp_timezone(tvb,ti);
611   } else if ( hf == hf_encryption_key ) {
612     dissect_sdp_encryption_key(tvb,ti);
613   } else if ( hf == hf_session_attribute ){
614     dissect_sdp_session_attribute(tvb,pinfo,ti);
615   } else if ( hf == hf_media ) {
616     dissect_sdp_media(tvb,ti,transport_info);
617   } else if ( hf == hf_media_attribute ){
618     dissect_sdp_media_attribute(tvb,pinfo,ti, length, transport_info);
619   }
620 }
621
622 static void
623 dissect_sdp_owner(tvbuff_t *tvb, proto_item *ti){
624   proto_tree *sdp_owner_tree;
625   gint offset,next_offset,tokenlen;
626
627   offset = 0;
628   next_offset = 0;
629   tokenlen = 0;
630
631   sdp_owner_tree = proto_item_add_subtree(ti,ett_sdp_owner);
632
633   /* Find the username */
634   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
635   if( next_offset == -1 )
636     return;
637   tokenlen = next_offset - offset;
638
639   proto_tree_add_item(sdp_owner_tree, hf_owner_username, tvb, offset, tokenlen,
640                       FALSE);
641   offset = next_offset  + 1;
642
643   /* Find the session id */
644   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
645   if( next_offset == -1 )
646     return;
647   tokenlen = next_offset - offset;
648
649   proto_tree_add_item(sdp_owner_tree, hf_owner_sessionid, tvb, offset,
650                       tokenlen, FALSE);
651   offset = next_offset + 1;
652
653   /* Find the version */
654   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
655   if( next_offset == -1 )
656     return;
657   tokenlen = next_offset - offset;
658
659   proto_tree_add_item(sdp_owner_tree, hf_owner_version, tvb, offset, tokenlen,
660                       FALSE);
661   offset = next_offset + 1;
662
663   /* Find the network type */
664   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
665   if( next_offset == -1 )
666     return;
667   tokenlen = next_offset - offset;
668
669   proto_tree_add_item(sdp_owner_tree, hf_owner_network_type, tvb, offset,
670                       tokenlen, FALSE);
671   offset = next_offset + 1;
672
673   /* Find the address type */
674   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
675   if( next_offset == -1 )
676     return;
677   tokenlen = next_offset - offset;
678
679   proto_tree_add_item(sdp_owner_tree, hf_owner_address_type, tvb, offset,
680                       tokenlen, FALSE);
681   offset = next_offset + 1;
682
683   /* Find the address */
684   proto_tree_add_item(sdp_owner_tree,hf_owner_address, tvb, offset, -1, FALSE);
685 }
686
687 /*
688  * XXX - this can leak memory if an exception is thrown after we've fetched
689  * a string.
690  */
691 static void
692 dissect_sdp_connection_info(tvbuff_t *tvb, proto_item* ti,
693                             transport_info_t *transport_info){
694   proto_tree *sdp_connection_info_tree;
695   gint offset,next_offset,tokenlen;
696
697   offset = 0;
698   next_offset = 0;
699   tokenlen = 0;
700
701   sdp_connection_info_tree = proto_item_add_subtree(ti,
702                                                     ett_sdp_connection_info);
703
704   /* Find the network type */
705   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
706   if( next_offset == -1 )
707     return;
708   tokenlen = next_offset - offset;
709
710   proto_tree_add_item(sdp_connection_info_tree,
711                       hf_connection_info_network_type, tvb, offset, tokenlen,
712                       FALSE);
713   offset = next_offset + 1;
714
715   /* Find the address type */
716   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
717   if( next_offset == -1 )
718     return;
719   tokenlen = next_offset - offset;
720   /* Save connection address type */
721   transport_info->connection_type = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
722
723
724   proto_tree_add_item(sdp_connection_info_tree,
725                       hf_connection_info_address_type, tvb, offset, tokenlen,
726                       FALSE);
727   offset = next_offset + 1;
728
729   /* Find the connection address */
730   /* XXX - what if there's a <number of addresses> value? */
731   next_offset = tvb_find_guint8(tvb,offset,-1,'/');
732   if( next_offset == -1){
733     tokenlen = -1; /* end of tvbuff */
734     /* Save connection address */
735     transport_info->connection_address =
736         (char*)tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
737   } else {
738     tokenlen = next_offset - offset;
739     /* Save connection address */
740     transport_info->connection_address = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
741   }
742
743   proto_tree_add_item(sdp_connection_info_tree,
744                       hf_connection_info_connection_address, tvb, offset,
745                       tokenlen, FALSE);
746   if(next_offset != -1){
747     offset = next_offset + 1;
748     next_offset = tvb_find_guint8(tvb,offset,-1,'/');
749     if( next_offset == -1){
750       tokenlen = -1; /* end of tvbuff */
751     } else {
752       tokenlen = next_offset - offset;
753     }
754     proto_tree_add_item(sdp_connection_info_tree,
755                         hf_connection_info_ttl, tvb, offset, tokenlen, FALSE);
756     if(next_offset != -1){
757       offset = next_offset + 1;
758       proto_tree_add_item(sdp_connection_info_tree,
759                           hf_connection_info_num_addr, tvb, offset, -1, FALSE);
760     }
761   }
762 }
763
764 static void
765 dissect_sdp_bandwidth(tvbuff_t *tvb, proto_item *ti){
766   proto_tree * sdp_bandwidth_tree;
767   gint offset, next_offset, tokenlen;
768   proto_item *item;
769   gboolean unit_is_kbs = FALSE;
770   gboolean unit_is_bps = FALSE;
771
772   offset = 0;
773   next_offset = 0;
774   tokenlen = 0;
775
776   sdp_bandwidth_tree = proto_item_add_subtree(ti,ett_sdp_bandwidth);
777
778   /* find the modifier */
779   next_offset = tvb_find_guint8(tvb,offset,-1,':');
780
781   if( next_offset == -1)
782     return;
783
784   tokenlen = next_offset - offset;
785
786   item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_modifier, tvb, offset,
787                       tokenlen, FALSE);
788   if (tvb_strneql(tvb, offset, "CT", 2) == 0){
789     proto_item_append_text(item, " [Conference Total(total bandwidth of all RTP sessions)]");
790     unit_is_kbs = TRUE;
791   }else if (tvb_strneql(tvb, offset, "AS", 2) == 0){
792     proto_item_append_text(item, " [Application Specific (RTP session bandwidth)]");
793     unit_is_kbs = TRUE;
794   }else if (tvb_strneql(tvb, offset, "TIAS", 4) == 0){
795     proto_item_append_text(item, " [Transport Independent Application Specific maximum]");
796     unit_is_bps = TRUE;
797   }
798
799
800   offset = next_offset + 1;
801
802   item = proto_tree_add_item(sdp_bandwidth_tree, hf_bandwidth_value, tvb, offset, -1,
803                       FALSE);
804   if (unit_is_kbs == TRUE)
805     proto_item_append_text(item, " kb/s");
806   if (unit_is_bps == TRUE)
807     proto_item_append_text(item, " b/s");
808 }
809
810 static void dissect_sdp_time(tvbuff_t *tvb, proto_item* ti){
811   proto_tree *sdp_time_tree;
812   gint offset,next_offset, tokenlen;
813
814   offset = 0;
815   next_offset = 0;
816   tokenlen = 0;
817
818   sdp_time_tree = proto_item_add_subtree(ti,ett_sdp_time);
819
820   /* get start time */
821   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
822   if( next_offset == -1 )
823     return;
824
825   tokenlen = next_offset - offset;
826   proto_tree_add_item(sdp_time_tree, hf_time_start, tvb, offset, tokenlen,
827                       FALSE);
828
829   /* get stop time */
830   offset = next_offset + 1;
831   proto_tree_add_item(sdp_time_tree, hf_time_stop, tvb, offset, -1, FALSE);
832 }
833
834 static void dissect_sdp_repeat_time(tvbuff_t *tvb, proto_item* ti){
835   proto_tree *sdp_repeat_time_tree;
836   gint offset,next_offset, tokenlen;
837
838   offset = 0;
839   next_offset = 0;
840   tokenlen = 0;
841
842   sdp_repeat_time_tree = proto_item_add_subtree(ti,ett_sdp_time);
843
844   /* get interval */
845   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
846   if( next_offset == -1 )
847     return;
848
849   tokenlen = next_offset - offset;
850   proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_interval, tvb,
851                       offset, tokenlen, FALSE);
852
853   /* get duration */
854   offset = next_offset + 1;
855   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
856   if( next_offset == -1 )
857     return;
858
859   tokenlen = next_offset - offset;
860   proto_tree_add_item(sdp_repeat_time_tree,hf_repeat_time_duration, tvb,
861                       offset, tokenlen, FALSE);
862
863   /* get offsets */
864   do{
865     offset = next_offset +1;
866     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
867     if(next_offset != -1){
868       tokenlen = next_offset - offset;
869     } else {
870       tokenlen = -1; /* end of tvbuff */
871     }
872     proto_tree_add_item(sdp_repeat_time_tree, hf_repeat_time_offset,
873                         tvb, offset, tokenlen, FALSE);
874   } while( next_offset != -1 );
875
876 }
877 static void
878 dissect_sdp_timezone(tvbuff_t *tvb, proto_item* ti){
879   proto_tree* sdp_timezone_tree;
880   gint offset, next_offset, tokenlen;
881   offset = 0;
882   next_offset = 0;
883   tokenlen = 0;
884
885   sdp_timezone_tree = proto_item_add_subtree(ti,ett_sdp_timezone);
886
887   do{
888     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
889     if(next_offset == -1)
890       break;
891     tokenlen = next_offset - offset;
892
893     proto_tree_add_item(sdp_timezone_tree, hf_timezone_time, tvb, offset,
894                         tokenlen, FALSE);
895     offset = next_offset + 1;
896     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
897     if(next_offset != -1){
898       tokenlen = next_offset - offset;
899     } else {
900       tokenlen = -1; /* end of tvbuff */
901     }
902     proto_tree_add_item(sdp_timezone_tree, hf_timezone_offset, tvb, offset,
903                         tokenlen, FALSE);
904     offset = next_offset + 1;
905   } while (next_offset != -1);
906
907 }
908
909
910 static void dissect_sdp_encryption_key(tvbuff_t *tvb, proto_item * ti){
911   proto_tree *sdp_encryption_key_tree;
912   gint offset, next_offset, tokenlen;
913
914   offset = 0;
915   next_offset = 0;
916   tokenlen = 0;
917
918   sdp_encryption_key_tree = proto_item_add_subtree(ti,ett_sdp_encryption_key);
919
920   next_offset = tvb_find_guint8(tvb,offset,-1,':');
921
922   if(next_offset == -1)
923     return;
924
925   tokenlen = next_offset - offset;
926
927   proto_tree_add_item(sdp_encryption_key_tree,hf_encryption_key_type,
928                       tvb, offset, tokenlen, FALSE);
929
930   offset = next_offset + 1;
931   proto_tree_add_item(sdp_encryption_key_tree,hf_encryption_key_data,
932                       tvb, offset, -1, FALSE);
933 }
934
935 static void dissect_key_mgmt(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti){
936   gchar *data_p = NULL;
937   gchar *prtcl_id = NULL;
938   gint len;
939   tvbuff_t *keymgmt_tvb;
940   gboolean found_match = FALSE;
941   proto_tree *key_tree;
942   gint next_offset;
943   gint offset = 0;
944   gint tokenlen;
945
946   key_tree = proto_item_add_subtree(ti, ett_sdp_key_mgmt);
947
948   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
949
950   if (next_offset == -1)
951     return;
952
953   tokenlen = next_offset - offset;
954   prtcl_id = tvb_get_ephemeral_string(tvb, offset, tokenlen);
955
956   proto_tree_add_item(key_tree, hf_key_mgmt_prtcl_id, tvb, offset, tokenlen, FALSE);
957
958   offset = next_offset + 1;
959
960   len = tvb_length_remaining(tvb, offset);
961   if (len < 0)
962     return;
963
964   data_p = tvb_get_ephemeral_string(tvb, offset, len);
965   keymgmt_tvb = base64_to_tvb(tvb, data_p);
966   add_new_data_source(pinfo, keymgmt_tvb, "Key Management Data");
967
968   if ( prtcl_id != NULL && key_mgmt_dissector_table != NULL ) {
969     found_match = dissector_try_string(key_mgmt_dissector_table,
970                                        prtcl_id,
971                                        keymgmt_tvb, pinfo,
972                                        key_tree);
973   }
974
975   if (found_match) {
976     proto_item *ti2 = proto_tree_add_item(key_tree, hf_key_mgmt_data,
977                                          keymgmt_tvb, 0, -1, FALSE);
978     PROTO_ITEM_SET_HIDDEN(ti2);
979   }
980   else {
981     proto_tree_add_item(key_tree, hf_key_mgmt_data,
982                         keymgmt_tvb, 0, -1, FALSE);
983   }
984
985 }
986
987
988 static void dissect_sdp_session_attribute(tvbuff_t *tvb, packet_info * pinfo, proto_item * ti){
989   proto_tree *sdp_session_attribute_tree;
990   gint offset, next_offset, tokenlen;
991   guint8 *field_name;
992
993   offset = 0;
994   next_offset = 0;
995   tokenlen = 0;
996
997   sdp_session_attribute_tree = proto_item_add_subtree(ti,
998                                                       ett_sdp_session_attribute);
999
1000   next_offset = tvb_find_guint8(tvb,offset,-1,':');
1001
1002   if(next_offset == -1)
1003     return;
1004
1005   tokenlen = next_offset - offset;
1006
1007   proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_field,
1008                       tvb, offset, tokenlen, FALSE);
1009
1010   field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1011
1012   offset = next_offset + 1;
1013
1014   if (strcmp((char*)field_name, "ipbcp") == 0) {
1015     offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"0123456789", NULL);
1016
1017     if (offset == -1)
1018       return;
1019
1020     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
1021
1022     if (next_offset == -1)
1023       return;
1024
1025     tokenlen = next_offset - offset;
1026
1027     proto_tree_add_item(sdp_session_attribute_tree,hf_ipbcp_version,tvb,offset,tokenlen,FALSE);
1028
1029     offset = tvb_pbrk_guint8(tvb,offset,-1,(guint8 *)"ABCDEFGHIJKLMNOPQRSTUVWXYZ", NULL);
1030
1031     if (offset == -1)
1032       return;
1033
1034     tokenlen = tvb_find_line_end(tvb,offset,-1, &next_offset, FALSE);
1035
1036     if (tokenlen == -1)
1037       return;
1038
1039     proto_tree_add_item(sdp_session_attribute_tree,hf_ipbcp_type,tvb,offset,tokenlen,FALSE);
1040   } else if (strcmp((char*)field_name, "key-mgmt") == 0) {
1041     tvbuff_t *key_tvb;
1042     proto_item *key_ti;
1043
1044     key_tvb = tvb_new_subset_remaining(tvb, offset);
1045     key_ti = proto_tree_add_item(sdp_session_attribute_tree, hf_key_mgmt_att_value, key_tvb, 0, -1, FALSE);
1046
1047     dissect_key_mgmt(key_tvb, pinfo, key_ti);
1048   } else {
1049     proto_tree_add_item(sdp_session_attribute_tree, hf_session_attribute_value,
1050                         tvb, offset, -1, FALSE);
1051   }
1052 }
1053
1054
1055 /* Dissect media description */
1056 static void
1057 dissect_sdp_media(tvbuff_t *tvb, proto_item *ti,
1058                   transport_info_t *transport_info){
1059   proto_tree *sdp_media_tree;
1060   gint offset, next_offset, tokenlen, idx;
1061   guint8 *media_format;
1062
1063   offset = 0;
1064   next_offset = 0;
1065   tokenlen = 0;
1066
1067   /* Re-initialise for a new media description */
1068   msrp_transport_address_set = FALSE;
1069
1070   /* Create tree for media session */
1071   sdp_media_tree = proto_item_add_subtree(ti,ett_sdp_media);
1072
1073   next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
1074
1075   if(next_offset == -1)
1076     return;
1077
1078   tokenlen = next_offset - offset;
1079
1080   /* Type of media session */
1081   proto_tree_add_item(sdp_media_tree, hf_media_media, tvb, offset, tokenlen,
1082                       FALSE);
1083
1084   transport_info->media_type = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
1085
1086   offset = next_offset + 1;
1087
1088   next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
1089   if(next_offset == -1)
1090     return;
1091   tokenlen = next_offset - offset;
1092   next_offset = tvb_find_guint8(tvb,offset, tokenlen, '/');
1093
1094   if(next_offset != -1){
1095     tokenlen = next_offset - offset;
1096     /* Save port info */
1097     transport_info->media_port[transport_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
1098
1099     proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
1100                         atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen)));
1101     offset = next_offset + 1;
1102     next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
1103     if(next_offset == -1)
1104       return;
1105     tokenlen = next_offset - offset;
1106     proto_tree_add_item(sdp_media_tree, hf_media_portcount, tvb, offset,
1107                         tokenlen, FALSE);
1108     offset = next_offset + 1;
1109   } else {
1110     next_offset = tvb_find_guint8(tvb,offset, -1, ' ');
1111
1112     if(next_offset == -1)
1113       return;
1114     tokenlen = next_offset - offset;
1115     /* Save port info */
1116     transport_info->media_port[transport_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
1117
1118     /* XXX Remember Port */
1119     proto_tree_add_uint(sdp_media_tree, hf_media_port, tvb, offset, tokenlen,
1120                         atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen)));
1121     offset = next_offset + 1;
1122   }
1123
1124   next_offset = tvb_find_guint8(tvb,offset,-1,' ');
1125
1126   if( next_offset == -1)
1127     return;
1128
1129   tokenlen = next_offset - offset;
1130   /* Save port protocol */
1131   transport_info->media_proto[transport_info->media_count] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
1132
1133   /* XXX Remember Protocol */
1134   proto_tree_add_item(sdp_media_tree, hf_media_proto, tvb, offset, tokenlen,
1135                       FALSE);
1136
1137   do {
1138     offset = next_offset + 1;
1139     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
1140
1141     if(next_offset == -1){
1142       tokenlen = tvb_length_remaining(tvb, offset); /* End of tvbuff */
1143       if (tokenlen == 0)
1144         break; /* Nothing more left */
1145     } else {
1146       tokenlen = next_offset - offset;
1147     }
1148
1149     if (strcmp(transport_info->media_proto[transport_info->media_count],
1150                "RTP/AVP") == 0) {
1151       media_format = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1152       proto_tree_add_string(sdp_media_tree, hf_media_format, tvb, offset,
1153                             tokenlen, val_to_str_ext(atol((char*)media_format), &rtp_payload_type_vals_ext, "%u"));
1154       idx = transport_info->media[transport_info->media_count].pt_count;
1155       transport_info->media[transport_info->media_count].pt[idx] = atol((char*)media_format);
1156       if (idx < (SDP_MAX_RTP_PAYLOAD_TYPES-1))
1157         transport_info->media[transport_info->media_count].pt_count++;
1158     } else {
1159       proto_tree_add_item(sdp_media_tree, hf_media_format, tvb, offset,
1160                           tokenlen, FALSE);
1161     }
1162   } while (next_offset != -1);
1163
1164   /* Increase the count of media channels, but don't walk off the end
1165      of the arrays. */
1166   if (transport_info->media_count < (SDP_MAX_RTP_CHANNELS-1)){
1167     transport_info->media_count++;
1168   }
1169
1170   /* XXX Dissect traffic to "Port" as "Protocol"
1171    *     Remember this Port/Protocol pair so we can tear it down again later
1172    *     Actually, it's harder than that:
1173    *         We need to find out the address of the other side first and it
1174    *         looks like that info can be found in SIP headers only.
1175    */
1176
1177 }
1178
1179 static tvbuff_t *
1180 ascii_bytes_to_tvb(tvbuff_t *tvb, packet_info *pinfo, gint len, gchar *msg)
1181 {
1182   guint8 *buf = g_malloc(10240);
1183
1184   /* arbitrary maximum length */
1185   if(len<20480){
1186     int i;
1187     tvbuff_t *bytes_tvb;
1188
1189     /* first, skip to where the encoded pdu starts, this is
1190        the first hex digit after the '=' char.
1191     */
1192     while(1){
1193       if((*msg==0)||(*msg=='\n')){
1194         return NULL;
1195       }
1196       if(*msg=='='){
1197         msg++;
1198         break;
1199       }
1200       msg++;
1201     }
1202     while(1){
1203       if((*msg==0)||(*msg=='\n')){
1204         return NULL;
1205       }
1206       if( ((*msg>='0')&&(*msg<='9'))
1207           ||  ((*msg>='a')&&(*msg<='f'))
1208           ||  ((*msg>='A')&&(*msg<='F'))){
1209         break;
1210       }
1211       msg++;
1212     }
1213     i=0;
1214     while( ((*msg>='0')&&(*msg<='9'))
1215            ||((*msg>='a')&&(*msg<='f'))
1216            ||((*msg>='A')&&(*msg<='F'))  ){
1217       int val;
1218       if((*msg>='0')&&(*msg<='9')){
1219         val=(*msg)-'0';
1220       } else if((*msg>='a')&&(*msg<='f')){
1221         val=(*msg)-'a'+10;
1222       } else if((*msg>='A')&&(*msg<='F')){
1223         val=(*msg)-'A'+10;
1224       } else {
1225         return NULL;
1226       }
1227       val<<=4;
1228       msg++;
1229       if((*msg>='0')&&(*msg<='9')){
1230         val|=(*msg)-'0';
1231       } else if((*msg>='a')&&(*msg<='f')){
1232         val|=(*msg)-'a'+10;
1233       } else if((*msg>='A')&&(*msg<='F')){
1234         val|=(*msg)-'A'+10;
1235       } else {
1236         return NULL;
1237       }
1238       msg++;
1239
1240       buf[i]=(guint8)val;
1241       i++;
1242     }
1243     if(i==0){
1244       return NULL;
1245     }
1246     bytes_tvb = tvb_new_child_real_data(tvb, buf,i,i);
1247     tvb_set_free_cb(bytes_tvb, g_free);
1248     add_new_data_source(pinfo, bytes_tvb, "ASCII bytes to tvb");
1249     return bytes_tvb;
1250   }
1251   return NULL;
1252 }
1253
1254 /* Annex X Profiles and levels definition */
1255 static const value_string h263_profile_vals[] =
1256 {
1257   { 0,    "Baseline Profile" },
1258   { 1,    "H.320 Coding Efficiency Version 2 Backward-Compatibility Profile" },
1259   { 2,    "Version 1 Backward-Compatibility Profile" },
1260   { 3,    "Version 2 Interactive and Streaming Wireless Profile" },
1261   { 4,    "Version 3 Interactive and Streaming Wireless Profile" },
1262   { 5,    "Conversational High Compression Profile" },
1263   { 6,    "Conversational Internet Profile" },
1264   { 7,    "Conversational Interlace Profile" },
1265   { 8,    "High Latency Profile" },
1266   { 0, NULL },
1267 };
1268
1269
1270 /* RFC 4629 The level are described in table X.2 of H.263 annex X */
1271 static const value_string h263_level_vals[] =
1272 {
1273   { 10,    "QCIF (176 x 144), 1 x 64Kb/s" },
1274   { 20,    "CIF (352 x 288), 2 x 64Kb/s" },
1275   { 30,    "CIF (352 x 288), 6 x 64Kb/s" },
1276   { 40,    "CIF (352 x 288), 32 x 64Kb/s" },
1277   { 45,    "QCIF (176 x144) support of CPFMT, 2 x 64Kb/s" },
1278   { 50,    "CIF (352 x 288) support of CPFMT, 64 x 64Kb/s" },
1279   { 60,    "CPFMT: 720 x 288 support of CPFMT, 128 x 64Kb/s" },
1280   { 70,    "CPFMT: 720 x 576 support of CPFMT, 256 x 64Kb/s" },
1281   { 0, NULL },
1282 };
1283
1284
1285 static const value_string h264_packetization_mode_vals[] =
1286 {
1287   { 0,    "Single NAL mode" },
1288   { 1,    "Non-interleaved mode" },
1289   { 2,    "Interleaved mode" },
1290   { 0, NULL },
1291 };
1292
1293 /*
1294  * TODO: Make this a more generic routine to dissect fmtp parameters depending on media types
1295  */
1296 static void
1297 decode_sdp_fmtp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset, gint tokenlen, char *mime_type){
1298   gint next_offset;
1299   gint end_offset;
1300   guint8 *field_name;
1301   gchar *format_specific_parameter;
1302   proto_item *item;
1303   tvbuff_t *data_tvb;
1304
1305   end_offset = offset + tokenlen;
1306
1307   /*
1308   proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; Analysed string: '%s'",
1309   tvb_get_ephemeral_string(tvb, offset, tokenlen));
1310   */
1311
1312   /* Look for an '=' within this value - this may indicate that there is a
1313      profile-level-id parameter to find if the MPEG4 media type is in use */
1314   next_offset = tvb_find_guint8(tvb,offset,-1,'=');
1315   if (next_offset == -1)
1316   {
1317     /* Give up (and avoid exception) if '=' not found */
1318     return;
1319   }
1320
1321   /* Find the name of the parameter */
1322   tokenlen = next_offset - offset;
1323   field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1324   /*proto_tree_add_text(tree, tvb, offset, tokenlen, "Debug; MIMEtype '%s'Parameter name: '%s'", mime_type, field_name); */
1325
1326   offset = next_offset;
1327
1328   /* Dissect the MPEG4 profile-level-id parameter if present */
1329   if (mime_type != NULL && g_ascii_strcasecmp(mime_type, "MP4V-ES") == 0) {
1330     if (strcmp((char*)field_name, "profile-level-id") == 0) {
1331       offset++;
1332       tokenlen = end_offset - offset;
1333       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1334       item = proto_tree_add_uint(tree, hf_sdp_fmtp_mpeg4_profile_level_id, tvb, offset, tokenlen,
1335                                  atol((char*)format_specific_parameter));
1336       PROTO_ITEM_SET_GENERATED(item);
1337     } else if (strcmp((char*)field_name, "config") == 0) {
1338       /* String including "=" */
1339       tokenlen = end_offset - offset;
1340       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1341       /* ascii_bytes_to_tvb requires the "=" to be in the buffer */
1342       data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
1343       if(mp4ves_handle && data_tvb){
1344         dissect_mp4ves_config(data_tvb, pinfo, tree);
1345       }
1346     }
1347   }
1348
1349   /* Dissect the H263-2000 profile parameter if present */
1350   if ((mime_type != NULL && g_ascii_strcasecmp(mime_type, "H263-2000") == 0)||(mime_type != NULL && g_ascii_strcasecmp(mime_type, "H263-1998") == 0)) {
1351     if (strcmp((char*)field_name, "profile") == 0) {
1352       offset++;
1353       tokenlen = end_offset - offset;
1354       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1355       item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_profile, tvb, offset, tokenlen,
1356                                  atol((char*)format_specific_parameter));
1357       PROTO_ITEM_SET_GENERATED(item);
1358     } else if(strcmp((char*)field_name, "level") == 0) {
1359       offset++;
1360       tokenlen = end_offset - offset;
1361       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1362       item = proto_tree_add_uint(tree, hf_sdp_fmtp_h263_level, tvb, offset, tokenlen,
1363                                  atol((char*)format_specific_parameter));
1364       PROTO_ITEM_SET_GENERATED(item);
1365     }
1366   }
1367
1368
1369   /* Dissect the H264 profile-level-id parameter
1370    * RFC 3984:
1371    * A base16 [6] (hexadecimal) representation of
1372    * the following three bytes in the sequence
1373    * parameter set NAL unit specified in [1]: 1)
1374    * profile_idc, 2) a byte herein referred to as
1375    * profile-iop, composed of the values of
1376    * constraint_set0_flag, constraint_set1_flag,
1377    * constraint_set2_flag, and reserved_zero_5bits
1378    * in bit-significance order, starting from the
1379    * most significant bit, and 3) level_idc.
1380    */
1381   if (mime_type != NULL && g_ascii_strcasecmp(mime_type, "H264") == 0) {
1382     if (strcmp(field_name, "profile-level-id") == 0) {
1383       int length = 0;
1384
1385       /* Length includes "=" as it's required by ascii_bytes_to_tvb()*/
1386       tokenlen = end_offset - offset;
1387       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1388       data_tvb = ascii_bytes_to_tvb(tvb, pinfo, tokenlen, format_specific_parameter);
1389       if(!data_tvb){
1390         proto_tree_add_text(tree, tvb, offset, tokenlen, "Could not convert '%s' to 3 bytes",format_specific_parameter);
1391         return;
1392       }
1393       length = tvb_length(data_tvb);
1394       if (length == 3){
1395         if(h264_handle && data_tvb){
1396           dissect_h264_profile(data_tvb, pinfo, tree);
1397         }
1398       }else{
1399         item = proto_tree_add_text(tree, tvb, offset, tokenlen, "Incorrectly coded, must be three bytes");
1400         PROTO_ITEM_SET_GENERATED(item);
1401       }
1402     }else if (strcmp(field_name, "packetization-mode") == 0) {
1403       offset++;
1404       tokenlen = end_offset - offset;
1405       format_specific_parameter = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1406       item = proto_tree_add_uint(tree, hf_sdp_h264_packetization_mode, tvb, offset, tokenlen,
1407                                  atol((char*)format_specific_parameter));
1408       PROTO_ITEM_SET_GENERATED(item);
1409
1410     }else if (strcmp(field_name, "sprop-parameter-sets") == 0) {
1411       /* The value of the parameter is the
1412          base64 [6] representation of the initial
1413          parameter set NAL units as specified in
1414          sections 7.3.2.1 and 7.3.2.2 of [1].  The
1415          parameter sets are conveyed in decoding order,
1416          and no framing of the parameter set NAL units
1417          takes place.  A comma is used to separate any
1418          pair of parameter sets in the list.
1419       */
1420       gchar *data_p = NULL;
1421       gint comma_offset;
1422
1423
1424       /* Move past '=' */
1425       offset++;
1426       comma_offset = tvb_find_guint8(tvb,offset,-1,',');
1427       if (comma_offset != -1){
1428         tokenlen = comma_offset - offset;
1429       }else{
1430         tokenlen = end_offset - offset;
1431       }
1432
1433       data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1434       proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 1 string: %s", data_p);
1435
1436       /* proto_tree_add_text(tree, tvb, offset, tokenlen, "String %s",data_p); */
1437       data_tvb = base64_to_tvb(tvb, data_p);
1438       add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets");
1439
1440       if(h264_handle && data_tvb){
1441         dissect_h264_nal_unit(data_tvb, pinfo, tree);
1442         if (comma_offset != -1){
1443           /* Second NAL unit */
1444           offset = comma_offset +1;
1445           tokenlen = end_offset - offset;
1446           data_p = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1447           proto_tree_add_text(tree, tvb, offset, tokenlen, "NAL unit 2 string: %s", data_p);
1448           data_tvb = base64_to_tvb(tvb, data_p);
1449           add_new_data_source(pinfo, data_tvb, "h264 prop-parameter-sets 2");
1450           dissect_h264_nal_unit(data_tvb, pinfo, tree);
1451         }
1452       }
1453     }
1454   }
1455
1456 }
1457
1458 typedef struct {
1459         const char *name;
1460 } sdp_names_t;
1461
1462 #define SDP_RTPMAP              1
1463 #define SDP_FMTP                2
1464 #define SDP_PATH                3
1465 #define SDP_H248_ITEM   4
1466
1467 static const sdp_names_t sdp_media_attribute_names[] = {
1468   { "Unknown-name"},    /* 0 Pad so that the real headers start at index 1 */
1469   { "rtpmap"},          /* 1 */
1470   { "fmtp"},            /* 2 */
1471   { "path"},            /* 3 */
1472   { "h248item"},        /* 4 */
1473 };
1474
1475 static gint find_sdp_media_attribute_names(tvbuff_t *tvb, int offset, guint len)
1476 {
1477   guint i;
1478
1479   for (i = 1; i < array_length(sdp_media_attribute_names); i++) {
1480     if (len == strlen(sdp_media_attribute_names[i].name) &&
1481         tvb_strncaseeql(tvb, offset, sdp_media_attribute_names[i].name, len) == 0)
1482       return i;
1483   }
1484
1485   return -1;
1486 }
1487
1488 static void dissect_sdp_media_attribute(tvbuff_t *tvb, packet_info *pinfo, proto_item * ti, int length, transport_info_t *transport_info){
1489   proto_tree *sdp_media_attribute_tree;
1490   proto_item *fmtp_item, *media_format_item;
1491   proto_tree *fmtp_tree;
1492   gint offset, next_offset, tokenlen, n, colon_offset;
1493   gint start_offset;
1494   /*??guint8 *field_name;*/
1495   guint8 *payload_type;
1496   guint8 *attribute_value;
1497   gint   *key;
1498   guint8 pt;
1499   gint  sdp_media_attrbute_code;
1500   const char *msrp_res = "msrp://";
1501   const char *h324ext_h223lcparm = "h324ext/h223lcparm";
1502   gboolean has_more_pars = TRUE;
1503   tvbuff_t *h245_tvb;
1504   encoding_name_and_rate_t *encoding_name_and_rate;
1505
1506   offset = 0;
1507   next_offset = 0;
1508   tokenlen = 0;
1509
1510   /* Create attribute tree */
1511   sdp_media_attribute_tree = proto_item_add_subtree(ti,
1512                                                     ett_sdp_media_attribute);
1513   /* Find end of field */
1514   colon_offset = tvb_find_guint8(tvb,offset,-1,':');
1515
1516   if(colon_offset == -1)
1517     return;
1518
1519   /* Attribute field name is token before ':' */
1520   tokenlen = colon_offset - offset;
1521   proto_tree_add_item(sdp_media_attribute_tree,
1522                       hf_media_attribute_field,
1523                       tvb, offset, tokenlen, FALSE);
1524   /*??field_name = tvb_get_ephemeral_string(tvb, offset, tokenlen);*/
1525   sdp_media_attrbute_code = find_sdp_media_attribute_names(tvb, offset, tokenlen);
1526
1527   /* Skip colon */
1528   offset = colon_offset + 1;
1529   /* skip leading wsp */
1530   offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
1531
1532   /* Value is the remainder of the line */
1533   attribute_value = tvb_get_ephemeral_string(tvb, offset, tvb_length_remaining(tvb, offset));
1534
1535
1536
1537   /*********************************************/
1538   /* Special parsing for some field name types */
1539
1540   switch (sdp_media_attrbute_code){
1541   case SDP_RTPMAP:
1542     /* decode the rtpmap to see if it is DynamicPayload to dissect them automatic */
1543     next_offset = tvb_find_guint8(tvb,offset,-1,' ');
1544
1545     if(next_offset == -1)
1546       return;
1547
1548     tokenlen = next_offset - offset;
1549
1550     proto_tree_add_item(sdp_media_attribute_tree, hf_media_format, tvb,
1551                         offset, tokenlen, FALSE);
1552
1553     payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);
1554
1555     offset = next_offset + 1;
1556
1557     next_offset = tvb_find_guint8(tvb,offset,-1,'/');
1558
1559     if(next_offset == -1){
1560       return;
1561     }
1562
1563     tokenlen = next_offset - offset;
1564
1565     start_offset = offset;
1566     proto_tree_add_item(sdp_media_attribute_tree, hf_media_encoding_name, tvb,
1567                         offset, tokenlen, FALSE);
1568
1569     key=g_malloc( sizeof(gint) );
1570     *key=atol((char*)payload_type);
1571     pt = atoi((char*)payload_type);
1572     if (pt >= SDP_NO_OF_PT) {
1573       return;   /* Invalid */
1574     }
1575     transport_info->encoding_name[pt] = (char*)tvb_get_ephemeral_string(tvb, offset, tokenlen);
1576
1577     next_offset =  next_offset + 1;
1578     offset = next_offset;
1579     while (length-1 >= next_offset){
1580       if(!isdigit(tvb_get_guint8(tvb, next_offset)))
1581         break;
1582       next_offset++;
1583     }
1584     tokenlen = next_offset - offset;
1585     proto_tree_add_item(sdp_media_attribute_tree, hf_media_sample_rate, tvb,
1586                         offset, tokenlen, FALSE);
1587     transport_info->sample_rate[pt] = atoi(tvb_get_ephemeral_string(tvb, offset, tokenlen));
1588     /* As per RFC2327 it is possible to have multiple Media Descriptions ("m=").
1589        For example:
1590
1591        a=rtpmap:101 G726-32/8000
1592        m=audio 49170 RTP/AVP 0 97
1593        a=rtpmap:97 telephone-event/8000
1594        m=audio 49172 RTP/AVP 97 101
1595        a=rtpmap:97 G726-24/8000
1596
1597        The Media attributes ("a="s) after the "m=" only apply for that "m=".
1598        If there is an "a=" before the first "m=", that attribute applies for
1599        all the session (all the "m="s).
1600     */
1601
1602     /* so, if this "a=" appear before any "m=", we add it to all the dynamic
1603      * hash tables
1604      */
1605     if (transport_info->media_count == 0) {
1606       for (n=0; n < SDP_MAX_RTP_CHANNELS; n++) {
1607         encoding_name_and_rate = g_malloc( sizeof(encoding_name_and_rate_t));
1608         encoding_name_and_rate->encoding_name = g_strdup(transport_info->encoding_name[pt]);
1609         encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1610         if (n==0){
1611           g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1612                               key, encoding_name_and_rate);
1613         }
1614         else {    /* we create a new key and encoding_name to assign to the other hash tables */
1615           gint *key2;
1616           key2=g_malloc( sizeof(gint) );
1617           *key2=atol((char*)payload_type);
1618           g_hash_table_insert(transport_info->media[n].rtp_dyn_payload,
1619                               key2, encoding_name_and_rate);
1620         }
1621       }
1622       return;
1623       /* if the "a=" is after an "m=", only apply to this "m=" */
1624     }else
1625       /* in case there is an overflow in SDP_MAX_RTP_CHANNELS, we keep always the last "m=" */
1626       encoding_name_and_rate = g_malloc( sizeof(encoding_name_and_rate_t));
1627
1628     encoding_name_and_rate->encoding_name = g_strdup(transport_info->encoding_name[pt]);
1629     encoding_name_and_rate->sample_rate = transport_info->sample_rate[pt];
1630     if (transport_info->media_count == SDP_MAX_RTP_CHANNELS-1)
1631       g_hash_table_insert(transport_info->media[ transport_info->media_count ].rtp_dyn_payload,
1632                           key, encoding_name_and_rate);
1633     else
1634       g_hash_table_insert(transport_info->media[ transport_info->media_count-1 ].rtp_dyn_payload,
1635                             key, encoding_name_and_rate);
1636     break;
1637   case SDP_FMTP:
1638     if(sdp_media_attribute_tree){
1639       guint8 media_format;
1640       /* Reading the Format parameter(fmtp) */
1641       /* Skip leading space, if any */
1642       offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
1643       /* Media format extends to the next space */
1644       next_offset = tvb_find_guint8(tvb,offset,-1,' ');
1645
1646       if(next_offset == -1)
1647         return;
1648
1649       tokenlen = next_offset - offset;
1650
1651
1652       media_format_item = proto_tree_add_item(sdp_media_attribute_tree,
1653                                               hf_media_format, tvb, offset,
1654                                               tokenlen, FALSE);
1655       media_format = atoi((char*)tvb_get_ephemeral_string(tvb, offset, tokenlen));
1656       if (media_format >= SDP_NO_OF_PT) {
1657         return;   /* Invalid */
1658       }
1659
1660       /* Append encoding name to format if known */
1661       proto_item_append_text(media_format_item, " [%s]",
1662                              transport_info->encoding_name[media_format]);
1663
1664       /*??payload_type = tvb_get_ephemeral_string(tvb, offset, tokenlen);*/
1665       /* Move offset past the payload type */
1666       offset = next_offset + 1;
1667
1668       while(has_more_pars==TRUE){
1669         next_offset = tvb_find_guint8(tvb,offset,-1,';');
1670         offset = tvb_skip_wsp(tvb,offset,tvb_length_remaining(tvb,offset));
1671
1672         if(next_offset == -1){
1673           has_more_pars = FALSE;
1674           next_offset= tvb_length(tvb);
1675         }else{
1676
1677         }
1678
1679         /* There are at least 2 - add the first parameter */
1680         tokenlen = next_offset - offset;
1681         fmtp_item = proto_tree_add_item(sdp_media_attribute_tree,
1682                                         hf_media_format_specific_parameter, tvb,
1683                                         offset, tokenlen, FALSE);
1684
1685         fmtp_tree = proto_item_add_subtree(fmtp_item, ett_sdp_fmtp);
1686
1687         decode_sdp_fmtp(fmtp_tree, tvb, pinfo, offset, tokenlen,
1688                         transport_info->encoding_name[media_format]);
1689
1690         /* Move offset past "; " and onto firts char */
1691         offset = next_offset + 1;
1692       }
1693     }
1694     break;
1695   case SDP_PATH:
1696     /* msrp attributes that contain address needed for conversation */
1697     /*    RFC 4975
1698      *    path = path-label ":" path-list
1699      *    path-label = "path"
1700      *    path-list= MSRP-URI *(SP MSRP-URI)
1701      *    MSRP-URI = msrp-scheme "://" authority
1702      *       ["/" session-id] ";" transport *( ";" URI-parameter)
1703      *                        ; authority as defined in RFC3986
1704      *
1705      *    msrp-scheme = "msrp" / "msrps"
1706      * RFC 3986
1707      * The authority component is preceded by a double slash ("//") and is terminated by
1708      * the next slash ("/"), question mark ("?"), or number sign ("#") character, or by
1709      * the end of the URI.
1710      */
1711
1712     /* Check for "msrp://" */
1713     if (strncmp((char*)attribute_value, msrp_res, strlen(msrp_res)) == 0){
1714       int address_offset, port_offset, port_end_offset;
1715
1716       /* Address starts here */
1717       address_offset = offset + (int)strlen(msrp_res);
1718
1719       /* Port is after next ':' */
1720       port_offset = tvb_find_guint8(tvb, address_offset, -1, ':');
1721       /* Check if port is present if not skipp */
1722       if(port_offset!= -1){
1723         /* Port ends with '/' */
1724         port_end_offset = tvb_find_guint8(tvb, port_offset, -1, '/');
1725
1726         /* Attempt to convert address */
1727         if (inet_pton(AF_INET, (char*)tvb_get_ephemeral_string(tvb, address_offset, port_offset-address_offset), &msrp_ipaddr) > 0) {
1728           /* Get port number */
1729           msrp_port_number = atoi((char*)tvb_get_ephemeral_string(tvb, port_offset+1, port_end_offset-port_offset-1));
1730           /* Set flag so this info can be used */
1731           msrp_transport_address_set = TRUE;
1732         }
1733       }
1734     }
1735     break;
1736   case SDP_H248_ITEM:
1737     /* Decode h248 item ITU-T Rec. H.248.12 (2001)/Amd.1 (11/2002)*/
1738     if (strncmp((char*)attribute_value, h324ext_h223lcparm, strlen(msrp_res)) == 0){
1739       /* A.5.1.3 H.223 Logical channel parameters
1740        * This property indicates the H.245
1741        * H223LogicalChannelsParameters structure encoded by applying the PER specified in
1742        * ITU-T Rec. X.691. Value encoded as per A.5.1.2. For text encoding the mechanism defined
1743        * in ITU-T Rec. H.248.15 is used.
1744        */
1745       gint len;
1746       asn1_ctx_t actx;
1747
1748       len = (gint)strlen(attribute_value);
1749       h245_tvb = ascii_bytes_to_tvb(tvb, pinfo, len, attribute_value);
1750       /* arbitrary maximum length */
1751       /* should go through a handle, however,  the two h245 entry
1752          points are different, one is over tpkt and the other is raw
1753       */
1754       if (h245_tvb){
1755         asn1_ctx_init(&actx, ASN1_ENC_PER, TRUE, pinfo);
1756         dissect_h245_H223LogicalChannelParameters(h245_tvb, 0, &actx, sdp_media_attribute_tree, hf_SDPh223LogicalChannelParameters);
1757       }
1758     }
1759     break;
1760   default:
1761     /* No special treatment for values of this attribute type, just add as one item. */
1762     proto_tree_add_item(sdp_media_attribute_tree, hf_media_attribute_value,
1763                         tvb, offset, -1, FALSE);
1764     break;
1765   }
1766 }
1767
1768 void
1769 proto_register_sdp(void)
1770 {
1771   static hf_register_info hf[] = {
1772     { &hf_protocol_version,
1773       { "Session Description Protocol Version (v)",
1774         "sdp.version", FT_STRING, BASE_NONE,NULL,0x0,
1775         NULL, HFILL }},
1776     { &hf_owner,
1777       { "Owner/Creator, Session Id (o)",
1778         "sdp.owner", FT_STRING, BASE_NONE, NULL, 0x0,
1779         NULL, HFILL}},
1780     { &hf_session_name,
1781       { "Session Name (s)",
1782         "sdp.session_name", FT_STRING, BASE_NONE,NULL, 0x0,
1783         NULL, HFILL }},
1784     { &hf_session_info,
1785       { "Session Information (i)",
1786         "sdp.session_info", FT_STRING, BASE_NONE, NULL, 0x0,
1787         NULL, HFILL }},
1788     { &hf_uri,
1789       { "URI of Description (u)",
1790         "sdp.uri", FT_STRING, BASE_NONE,NULL, 0x0,
1791         NULL, HFILL }},
1792     { &hf_email,
1793       { "E-mail Address (e)",
1794         "sdp.email", FT_STRING, BASE_NONE, NULL, 0x0,
1795         "E-mail Address", HFILL }},
1796     { &hf_phone,
1797       { "Phone Number (p)",
1798         "sdp.phone", FT_STRING, BASE_NONE, NULL, 0x0,
1799         NULL, HFILL }},
1800     { &hf_connection_info,
1801       { "Connection Information (c)",
1802         "sdp.connection_info", FT_STRING, BASE_NONE, NULL, 0x0,
1803         NULL, HFILL }},
1804     { &hf_bandwidth,
1805       { "Bandwidth Information (b)",
1806         "sdp.bandwidth", FT_STRING, BASE_NONE, NULL, 0x0,
1807         NULL, HFILL }},
1808     { &hf_timezone,
1809       { "Time Zone Adjustments (z)",
1810         "sdp.timezone", FT_STRING, BASE_NONE, NULL, 0x0,
1811         NULL, HFILL }},
1812     { &hf_encryption_key,
1813       { "Encryption Key (k)",
1814         "sdp.encryption_key", FT_STRING, BASE_NONE, NULL, 0x0,
1815         NULL, HFILL }},
1816     { &hf_session_attribute,
1817       { "Session Attribute (a)",
1818         "sdp.session_attr", FT_STRING, BASE_NONE, NULL, 0x0,
1819         NULL, HFILL }},
1820     { &hf_media_attribute,
1821       { "Media Attribute (a)",
1822         "sdp.media_attr", FT_STRING, BASE_NONE, NULL, 0x0,
1823         NULL, HFILL }},
1824     { &hf_time,
1825       { "Time Description, active time (t)",
1826         "sdp.time", FT_STRING, BASE_NONE, NULL, 0x0,
1827         NULL, HFILL }},
1828     { &hf_repeat_time,
1829       { "Repeat Time (r)",
1830         "sdp.repeat_time", FT_STRING, BASE_NONE, NULL, 0x0,
1831         NULL, HFILL }},
1832     { &hf_media,
1833       { "Media Description, name and address (m)",
1834         "sdp.media", FT_STRING, BASE_NONE, NULL, 0x0,
1835         NULL, HFILL }},
1836     { &hf_media_title,
1837       { "Media Title (i)",
1838         "sdp.media_title",FT_STRING, BASE_NONE, NULL, 0x0,
1839         "Media Title", HFILL }},
1840     { &hf_unknown,
1841       { "Unknown",
1842         "sdp.unknown",FT_STRING, BASE_NONE, NULL, 0x0,
1843         NULL, HFILL }},
1844     { &hf_invalid,
1845       { "Invalid line",
1846         "sdp.invalid",FT_STRING, BASE_NONE, NULL, 0x0,
1847         NULL, HFILL }},
1848     { &hf_owner_username,
1849       { "Owner Username",
1850         "sdp.owner.username",FT_STRING, BASE_NONE, NULL, 0x0,
1851         NULL, HFILL }},
1852     { &hf_owner_sessionid,
1853       { "Session ID",
1854         "sdp.owner.sessionid",FT_STRING, BASE_NONE, NULL, 0x0,
1855         NULL, HFILL }},
1856     { &hf_owner_version,
1857       { "Session Version",
1858         "sdp.owner.version",FT_STRING, BASE_NONE, NULL, 0x0,
1859         NULL, HFILL }},
1860     { &hf_owner_network_type,
1861       { "Owner Network Type",
1862         "sdp.owner.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
1863         NULL, HFILL }},
1864     { &hf_owner_address_type,
1865       { "Owner Address Type",
1866         "sdp.owner.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
1867         NULL, HFILL }},
1868     { &hf_owner_address,
1869       { "Owner Address",
1870         "sdp.owner.address",FT_STRING, BASE_NONE, NULL, 0x0,
1871         NULL, HFILL }},
1872     { &hf_connection_info_network_type,
1873       { "Connection Network Type",
1874         "sdp.connection_info.network_type",FT_STRING, BASE_NONE, NULL, 0x0,
1875         NULL, HFILL }},
1876     { &hf_connection_info_address_type,
1877       { "Connection Address Type",
1878         "sdp.connection_info.address_type",FT_STRING, BASE_NONE, NULL, 0x0,
1879         NULL, HFILL }},
1880     { &hf_connection_info_connection_address,
1881       { "Connection Address",
1882         "sdp.connection_info.address",FT_STRING, BASE_NONE, NULL, 0x0,
1883         NULL, HFILL }},
1884     { &hf_connection_info_ttl,
1885       { "Connection TTL",
1886         "sdp.connection_info.ttl",FT_STRING, BASE_NONE, NULL, 0x0,
1887         NULL, HFILL }},
1888     { &hf_connection_info_num_addr,
1889       { "Connection Number of Addresses",
1890         "sdp.connection_info.num_addr",FT_STRING, BASE_NONE, NULL, 0x0,
1891         NULL, HFILL }},
1892     { &hf_bandwidth_modifier,
1893       { "Bandwidth Modifier",
1894         "sdp.bandwidth.modifier",FT_STRING, BASE_NONE, NULL, 0x0,
1895         NULL, HFILL }},
1896     { &hf_bandwidth_value,
1897       { "Bandwidth Value",
1898         "sdp.bandwidth.value",FT_STRING, BASE_NONE, NULL, 0x0,
1899         "Bandwidth Value (in kbits/s)", HFILL }},
1900     { &hf_time_start,
1901       { "Session Start Time",
1902         "sdp.time.start",FT_STRING, BASE_NONE, NULL, 0x0,
1903         NULL, HFILL }},
1904     { &hf_time_stop,
1905       { "Session Stop Time",
1906         "sdp.time.stop",FT_STRING, BASE_NONE, NULL, 0x0,
1907         NULL, HFILL }},
1908     { &hf_repeat_time_interval,
1909       { "Repeat Interval",
1910         "sdp.repeat_time.interval",FT_STRING, BASE_NONE, NULL, 0x0,
1911         NULL, HFILL }},
1912     { &hf_repeat_time_duration,
1913       { "Repeat Duration",
1914         "sdp.repeat_time.duration",FT_STRING, BASE_NONE, NULL, 0x0,
1915         NULL, HFILL }},
1916     { &hf_repeat_time_offset,
1917       { "Repeat Offset",
1918         "sdp.repeat_time.offset",FT_STRING, BASE_NONE, NULL, 0x0,
1919         NULL, HFILL }},
1920     { &hf_timezone_time,
1921       { "Timezone Time",
1922         "sdp.timezone.time",FT_STRING, BASE_NONE, NULL, 0x0,
1923         NULL, HFILL }},
1924     { &hf_timezone_offset,
1925       { "Timezone Offset",
1926         "sdp.timezone.offset",FT_STRING, BASE_NONE, NULL, 0x0,
1927         NULL, HFILL }},
1928     { &hf_encryption_key_type,
1929       { "Key Type",
1930         "sdp.encryption_key.type",FT_STRING, BASE_NONE, NULL, 0x0,
1931         NULL, HFILL }},
1932     { &hf_encryption_key_data,
1933       { "Key Data",
1934         "sdp.encryption_key.data",FT_STRING, BASE_NONE, NULL, 0x0,
1935         NULL, HFILL }},
1936     { &hf_session_attribute_field,
1937       { "Session Attribute Fieldname",
1938         "sdp.session_attr.field",FT_STRING, BASE_NONE, NULL, 0x0,
1939         NULL, HFILL }},
1940     { &hf_session_attribute_value,
1941       { "Session Attribute Value",
1942         "sdp.session_attr.value",FT_STRING, BASE_NONE, NULL, 0x0,
1943         NULL, HFILL }},
1944     { &hf_media_media,
1945       { "Media Type",
1946         "sdp.media.media",FT_STRING, BASE_NONE, NULL, 0x0,
1947         NULL, HFILL }},
1948     { &hf_media_port,
1949       { "Media Port",
1950         "sdp.media.port",FT_UINT16, BASE_DEC, NULL, 0x0,
1951         NULL, HFILL }},
1952     { &hf_media_portcount,
1953       { "Media Port Count",
1954         "sdp.media.portcount",FT_STRING, BASE_NONE, NULL, 0x0,
1955         NULL, HFILL }},
1956     { &hf_media_proto,
1957       { "Media Protocol",
1958         "sdp.media.proto",FT_STRING, BASE_NONE, NULL, 0x0,
1959         NULL, HFILL }},
1960     { &hf_media_format,
1961       { "Media Format",
1962         "sdp.media.format",FT_STRING, BASE_NONE, NULL, 0x0,
1963         NULL, HFILL }},
1964     { &hf_media_attribute_field,
1965       { "Media Attribute Fieldname",
1966         "sdp.media_attribute.field",FT_STRING, BASE_NONE, NULL, 0x0,
1967         NULL, HFILL }},
1968     { &hf_media_attribute_value,
1969       { "Media Attribute Value",
1970         "sdp.media_attribute.value",FT_STRING, BASE_NONE, NULL, 0x0,
1971         NULL, HFILL }},
1972     { &hf_media_encoding_name,
1973       { "MIME Type",
1974         "sdp.mime.type",FT_STRING, BASE_NONE, NULL, 0x0,
1975         "SDP MIME Type", HFILL }},
1976     { &hf_media_sample_rate,
1977       { "Sample Rate",
1978         "sdp.sample_rate",FT_STRING, BASE_NONE, NULL, 0x0,
1979         NULL, HFILL }},
1980     { &hf_media_format_specific_parameter,
1981       { "Media format specific parameters",
1982         "sdp.fmtp.parameter",FT_STRING, BASE_NONE, NULL, 0x0,
1983         "Format specific parameter(fmtp)", HFILL }},
1984     { &hf_ipbcp_version,
1985       { "IPBCP Protocol Version",
1986         "ipbcp.version",FT_STRING, BASE_NONE, NULL, 0x0,
1987         NULL, HFILL }},
1988     { &hf_ipbcp_type,
1989       { "IPBCP Command Type",
1990         "ipbcp.command",FT_STRING, BASE_NONE, NULL, 0x0,
1991         NULL, HFILL }},
1992     {&hf_sdp_fmtp_mpeg4_profile_level_id,
1993       { "Level Code",
1994         "sdp.fmtp.profile_level_id",FT_UINT32, BASE_DEC,VALS(mp4ves_level_indication_vals), 0x0,
1995         NULL, HFILL }},
1996     { &hf_sdp_fmtp_h263_profile,
1997       { "Profile",
1998         "sdp.fmtp.h263profile",FT_UINT32, BASE_DEC,VALS(h263_profile_vals), 0x0,
1999         NULL, HFILL }},
2000     { &hf_sdp_fmtp_h263_level,
2001       { "Level",
2002         "sdp.fmtp.h263level",FT_UINT32, BASE_DEC,VALS(h263_level_vals), 0x0,
2003         NULL, HFILL }},
2004     { &hf_sdp_h264_packetization_mode,
2005       { "Packetization mode",
2006         "sdp.fmtp.h264_packetization_mode",FT_UINT32, BASE_DEC,VALS(h264_packetization_mode_vals), 0x0,
2007         NULL, HFILL }},
2008     { &hf_sdp_h264_sprop_parameter_sets,
2009       { "Sprop_parameter_sets",
2010         "sdp.h264.sprop_parameter_sets", FT_BYTES, BASE_NONE, NULL, 0x0,
2011         NULL, HFILL }},
2012     { &hf_SDPh223LogicalChannelParameters,
2013       { "h223LogicalChannelParameters", "sdp.h223LogicalChannelParameters",
2014         FT_NONE, BASE_NONE, NULL, 0,
2015         NULL, HFILL }},
2016     { &hf_key_mgmt_att_value,
2017       { "Key Management",
2018         "sdp.key_mgmt", FT_STRING, BASE_NONE, NULL, 0x0,
2019         NULL, HFILL }},
2020     { &hf_key_mgmt_prtcl_id,
2021       { "Key Management Protocol (kmpid)",
2022         "sdp.key_mgmt.kmpid", FT_STRING, BASE_NONE, NULL, 0x0,
2023         NULL, HFILL }},
2024     { &hf_key_mgmt_data,
2025       { "Key Management Data",
2026         "sdp.key_mgmt.data", FT_BYTES, BASE_NONE, NULL, 0x0,
2027         NULL, HFILL }},
2028   };
2029   static gint *ett[] = {
2030     &ett_sdp,
2031     &ett_sdp_owner,
2032     &ett_sdp_connection_info,
2033     &ett_sdp_bandwidth,
2034     &ett_sdp_time,
2035     &ett_sdp_repeat_time,
2036     &ett_sdp_timezone,
2037     &ett_sdp_encryption_key,
2038     &ett_sdp_session_attribute,
2039     &ett_sdp_media,
2040     &ett_sdp_media_attribute,
2041     &ett_sdp_fmtp,
2042     &ett_sdp_key_mgmt,
2043   };
2044
2045   module_t *sdp_module;
2046
2047   proto_sdp = proto_register_protocol("Session Description Protocol",
2048                                       "SDP", "sdp");
2049   proto_register_field_array(proto_sdp, hf, array_length(hf));
2050   proto_register_subtree_array(ett, array_length(ett));
2051
2052   key_mgmt_dissector_table = register_dissector_table("key_mgmt",
2053                                                       "Key Management", FT_STRING, BASE_NONE);
2054
2055   /*
2056    * Preferences registration
2057    */
2058    sdp_module = prefs_register_protocol(proto_sdp, NULL);
2059    prefs_register_bool_preference(sdp_module, "establish_conversation",
2060        "Establish Media Conversation",
2061        "Specifies that RTP/RTCP/T.38/MSRP/etc streams are decoded based "
2062        "upon port numbers found in SDP payload",
2063        &global_sdp_establish_conversation);
2064
2065   /*
2066    * Register the dissector by name, so other dissectors can
2067    * grab it by name rather than just referring to it directly.
2068    */
2069   register_dissector("sdp", dissect_sdp, proto_sdp);
2070
2071   /* Register for tapping */
2072   sdp_tap = register_tap("sdp");
2073 }
2074
2075 void
2076 proto_reg_handoff_sdp(void)
2077 {
2078   dissector_handle_t sdp_handle;
2079
2080   rtp_handle = find_dissector("rtp");
2081   rtcp_handle = find_dissector("rtcp");
2082   msrp_handle = find_dissector("msrp");
2083   t38_handle = find_dissector("t38");
2084   h264_handle = find_dissector("h264");
2085   mp4ves_handle = find_dissector("mp4ves");
2086
2087   sdp_handle = find_dissector("sdp");
2088   dissector_add_string("media_type", "application/sdp", sdp_handle);
2089   dissector_add_uint("bctp.tpi", 0x20, sdp_handle);
2090 }