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