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