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