From Lars Roland:
[obnox/wireshark/wip.git] / packet-rtp.c
1 /* packet-rtp.c
2  *
3  * Routines for RTP dissection
4  * RTP = Real time Transport Protocol
5  *
6  * Copyright 2000, Philips Electronics N.V.
7  * Written by Andreas Sikkema <andreas.sikkema@philips.com>
8  *
9  * $Id: packet-rtp.c,v 1.43 2003/11/20 23:34:29 guy Exp $
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 /*
31  * This dissector tries to dissect the RTP protocol according to Annex A
32  * of ITU-T Recommendation H.225.0 (02/98) or RFC 1889
33  *
34  * RTP traffic is handled by an even UDP portnumber. This can be any
35  * port number, but there is a registered port available, port 5004
36  * See Annex B of ITU-T Recommendation H.225.0, section B.7
37  *
38  * This doesn't dissect older versions of RTP, such as:
39  *
40  *    the vat protocol ("version 0") - see
41  *
42  *      ftp://ftp.ee.lbl.gov/conferencing/vat/alpha-test/vatsrc-4.0b2.tar.gz
43  *
44  *    and look in "session-vat.cc" if you want to write a dissector
45  *    (have fun - there aren't any nice header files showing the packet
46  *    format);
47  *
48  *    version 1, as documented in
49  *
50  *      ftp://gaia.cs.umass.edu/pub/hgschulz/rtp/draft-ietf-avt-rtp-04.txt
51  */
52
53
54 #ifdef HAVE_CONFIG_H
55 # include "config.h"
56 #endif
57
58 #include <glib.h>
59 #include <epan/packet.h>
60
61 #include <stdio.h>
62 #include <string.h>
63
64 #include "packet-rtp.h"
65 #include "rtp_pt.h"
66 #include <epan/conversation.h>
67 #include "tap.h"
68
69 static int rtp_tap = -1;
70
71 static dissector_table_t rtp_pt_dissector_table;
72
73 /* RTP header fields             */
74 static int proto_rtp           = -1;
75 static int hf_rtp_version      = -1;
76 static int hf_rtp_padding      = -1;
77 static int hf_rtp_extension    = -1;
78 static int hf_rtp_csrc_count   = -1;
79 static int hf_rtp_marker       = -1;
80 static int hf_rtp_payload_type = -1;
81 static int hf_rtp_seq_nr       = -1;
82 static int hf_rtp_timestamp    = -1;
83 static int hf_rtp_ssrc         = -1;
84 static int hf_rtp_csrc_item    = -1;
85 static int hf_rtp_data         = -1;
86 static int hf_rtp_padding_data = -1;
87 static int hf_rtp_padding_count= -1;
88
89 /* RTP header extension fields   */
90 static int hf_rtp_prof_define  = -1;
91 static int hf_rtp_length       = -1;
92 static int hf_rtp_hdr_ext      = -1;
93
94 /* RTP fields defining a sub tree */
95 static gint ett_rtp       = -1;
96 static gint ett_csrc_list = -1;
97 static gint ett_hdr_ext   = -1;
98
99 static dissector_handle_t data_handle;
100
101 static gboolean dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo,
102     proto_tree *tree );
103 static void dissect_rtp( tvbuff_t *tvb, packet_info *pinfo,
104     proto_tree *tree );
105
106 /*
107  * Fields in the first octet of the RTP header.
108  */
109
110 /* Version is the first 2 bits of the first octet*/
111 #define RTP_VERSION(octet)      ((octet) >> 6)
112
113 /* Padding is the third bit; No need to shift, because true is any value
114    other than 0! */
115 #define RTP_PADDING(octet)      ((octet) & 0x20)
116
117 /* Extension bit is the fourth bit */
118 #define RTP_EXTENSION(octet)    ((octet) & 0x10)
119
120 /* CSRC count is the last four bits */
121 #define RTP_CSRC_COUNT(octet)   ((octet) & 0xF)
122
123 static const value_string rtp_version_vals[] =
124 {
125         { 0, "Old VAT Version" },
126         { 1, "First Draft Version" },
127         { 2, "RFC 1889 Version" },
128         { 0, NULL },
129 };
130
131 /*
132  * Fields in the second octet of the RTP header.
133  */
134
135 /* Marker is the first bit of the second octet */
136 #define RTP_MARKER(octet)       ((octet) & 0x80)
137
138 /* Payload type is the last 7 bits */
139 #define RTP_PAYLOAD_TYPE(octet) ((octet) & 0x7F)
140
141 static const value_string rtp_payload_type_vals[] =
142 {
143         { PT_PCMU,      "ITU-T G.711 PCMU" },
144         { PT_1016,      "USA Federal Standard FS-1016" },
145         { PT_G721,      "ITU-T G.721" },
146         { PT_GSM,       "GSM 06.10" },
147         { PT_G723,      "ITU-T G.723" },
148         { PT_DVI4_8000, "DVI4 8000 samples/s" },
149         { PT_DVI4_16000, "DVI4 16000 samples/s" },
150         { PT_LPC,       "Experimental linear predictive encoding from Xerox PARC" },
151         { PT_PCMA,      "ITU-T G.711 PCMA" },
152         { PT_G722,      "ITU-T G.722" },
153         { PT_L16_STEREO, "16-bit uncompressed audio, stereo" },
154         { PT_L16_MONO,  "16-bit uncompressed audio, monaural" },
155         { PT_QCELP,     "Qualcomm Code Excited Linear Predictive coding" },
156         { PT_CN,        "Comfort noise" },
157         { PT_MPA,       "MPEG-I/II Audio"},
158         { PT_G728,      "ITU-T G.728" },
159         { PT_DVI4_11025, "DVI4 11025 samples/s" },
160         { PT_DVI4_22050, "DVI4 22050 samples/s" },
161         { PT_G729,      "ITU-T G.729" },
162         { PT_CELB,      "Sun CellB video encoding" },
163         { PT_JPEG,      "JPEG-compressed video" },
164         { PT_NV,        "'nv' program" },
165         { PT_H261,      "ITU-T H.261" },
166         { PT_MPV,       "MPEG-I/II Video"},
167         { PT_MP2T,      "MPEG-II transport streams"},
168         { PT_H263,      "ITU-T H.263" },
169         { 0,            NULL },
170 };
171
172 static address fake_addr;
173 static int heur_init = FALSE;
174
175 void rtp_add_address( packet_info *pinfo, const unsigned char* ip_addr,
176     int prt )
177 {
178         address src_addr;
179         conversation_t* pconv;
180
181         /*
182          * If this isn't the first time this packet has been processed,
183          * we've already done this work, so we don't need to do it
184          * again.
185          */
186         if (pinfo->fd->flags.visited)
187                 return;
188
189         src_addr.type = AT_IPv4;
190         src_addr.len = 4;
191         src_addr.data = ip_addr;
192
193         /*
194          * The first time the function is called let the tcp dissector
195          * know that we're interested in traffic
196          */
197         if ( ! heur_init ) {
198                 heur_dissector_add( "udp", dissect_rtp_heur, proto_rtp );
199                 heur_init = TRUE;
200         }
201
202         /*
203          * Check if the ip address an dport combination is not
204          * already registered
205          */
206         pconv = find_conversation( &src_addr, &fake_addr, PT_UDP, prt, 0, 0 );
207
208         /*
209          * If not, add
210          * XXX - use wildcard address and port B?
211          */
212         if ( ! pconv ) {
213                 pconv = conversation_new( &src_addr, &fake_addr, PT_UDP,
214                     (guint32) prt, (guint32) 0, 0 );
215                 conversation_add_proto_data(pconv, proto_rtp, NULL);
216         }
217
218 }
219
220 #if 0
221 static void rtp_init( void )
222 {
223         unsigned char* tmp_data;
224         int i;
225
226         /* Create a fake adddress... */
227         fake_addr.type = AT_IPv4;
228         fake_addr.len = 4;
229
230         tmp_data = malloc( fake_addr.len );
231         for ( i = 0; i < fake_addr.len; i++) {
232                 tmp_data[i] = 0;
233         }
234         fake_addr.data = tmp_data;
235 }
236 #endif
237
238 static gboolean
239 dissect_rtp_heur( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
240 {
241         conversation_t* pconv;
242
243         /* This is a heuristic dissector, which means we get all the TCP
244          * traffic not sent to a known dissector and not claimed by
245          * a heuristic dissector called before us!
246          * So we first check if the frame is really meant for us.
247          */
248         if ( ( pconv = find_conversation( &pinfo->src, &fake_addr, pinfo->ptype,
249             pinfo->srcport, 0, 0 ) ) == NULL ) {
250                 /*
251                  * The source ip:port combination was not what we were
252                  * looking for, check the destination
253                  */
254                 if ( ( pconv = find_conversation( &pinfo->dst, &fake_addr,
255                     pinfo->ptype, pinfo->destport, 0, 0 ) ) == NULL ) {
256                         return FALSE;
257                 }
258         }
259
260         /*
261          * An RTP conversation always has a data item for RTP.
262          * (Its existence is sufficient to indicate that this is an RTP
263          * conversation.)
264          */
265         if (conversation_get_proto_data(pconv, proto_rtp) == NULL)
266                 return FALSE;
267
268         dissect_rtp( tvb, pinfo, tree );
269
270         return TRUE;
271 }
272
273 static void
274 dissect_rtp_data( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
275     proto_tree *rtp_tree, int offset, unsigned int data_len,
276     unsigned int data_reported_len, unsigned int payload_type )
277 {
278         tvbuff_t *newtvb;
279
280         newtvb = tvb_new_subset( tvb, offset, data_len, data_reported_len );
281         if (!dissector_try_port(rtp_pt_dissector_table, payload_type, newtvb,
282             pinfo, tree))
283                 proto_tree_add_item( rtp_tree, hf_rtp_data, newtvb, 0, -1, FALSE );
284 }
285
286 static void
287 dissect_rtp( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
288 {
289         proto_item *ti            = NULL;
290         proto_tree *rtp_tree      = NULL;
291         proto_tree *rtp_csrc_tree = NULL;
292         guint8      octet1, octet2;
293         unsigned int version;
294         gboolean    padding_set;
295         gboolean    extension_set;
296         unsigned int csrc_count;
297         gboolean    marker_set;
298         unsigned int payload_type;
299         unsigned int i            = 0;
300         unsigned int hdr_extension= 0;
301         unsigned int padding_count;
302         int         data_len;
303         unsigned int offset = 0;
304         guint16     seq_num;
305         guint32     timestamp;
306         guint32     sync_src;
307         guint32     csrc_item;
308
309         static struct _rtp_info rtp_info;
310
311         /* Get the fields in the first octet */
312         octet1 = tvb_get_guint8( tvb, offset );
313         version = RTP_VERSION( octet1 );
314
315         if (version != 2) {
316                 /*
317                  * Unknown or unsupported version.
318                  */
319                 if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )   {
320                         col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP" );
321                 }
322
323                 if ( check_col( pinfo->cinfo, COL_INFO) ) {
324                         col_add_fstr( pinfo->cinfo, COL_INFO,
325                             "Unknown RTP version %u", version);
326                 }
327
328                 if ( tree ) {
329                         ti = proto_tree_add_item( tree, proto_rtp, tvb, offset, -1, FALSE );
330                         rtp_tree = proto_item_add_subtree( ti, ett_rtp );
331
332                         proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
333                             offset, 1, octet1);
334                 }
335                 return;
336         }
337
338         padding_set = RTP_PADDING( octet1 );
339         extension_set = RTP_EXTENSION( octet1 );
340         csrc_count = RTP_CSRC_COUNT( octet1 );
341
342         /* Get the fields in the second octet */
343         octet2 = tvb_get_guint8( tvb, offset + 1 );
344         marker_set = RTP_MARKER( octet2 );
345         payload_type = RTP_PAYLOAD_TYPE( octet2 );
346
347         /* Get the subsequent fields */
348         seq_num = tvb_get_ntohs( tvb, offset + 2 );
349         timestamp = tvb_get_ntohl( tvb, offset + 4 );
350         sync_src = tvb_get_ntohl( tvb, offset + 8 );
351
352         /* fill in the rtp_info structure */
353         rtp_info.info_padding_set = padding_set;
354         rtp_info.info_padding_count = 0;
355         rtp_info.info_marker_set = marker_set;
356         rtp_info.info_payload_type = payload_type;
357         rtp_info.info_seq_num = seq_num;
358         rtp_info.info_timestamp = timestamp;
359         rtp_info.info_sync_src = sync_src;
360         rtp_info.info_data_len = tvb_reported_length_remaining( tvb, offset );
361
362         /*
363         * Save the pointer to raw rtp data (header + payload incl. padding)
364         * That should be safe because the "epan_dissect_t" constructed for the packet
365         *  has not yet been freed when the taps are called.
366         * (destroying the "epan_dissect_t" will end up freeing all the tvbuffs
367         *  and hence invalidating pointers to their data).
368         * See "add_packet_to_packet_list()" for details.
369         */
370         rtp_info.info_data = tvb_get_ptr(tvb, 0, -1);
371
372         if ( check_col( pinfo->cinfo, COL_PROTOCOL ) )   {
373                 col_set_str( pinfo->cinfo, COL_PROTOCOL, "RTP" );
374         }
375
376         if ( check_col( pinfo->cinfo, COL_INFO) ) {
377                 col_add_fstr( pinfo->cinfo, COL_INFO,
378                     "Payload type=%s, SSRC=%u, Seq=%u, Time=%u%s",
379                     val_to_str( payload_type, rtp_payload_type_vals,
380                         "Unknown (%u)" ),
381                     sync_src,
382                     seq_num,
383                     timestamp,
384                     marker_set ? ", Mark" : "");
385         }
386         if ( tree ) {
387                 ti = proto_tree_add_item( tree, proto_rtp, tvb, offset, -1, FALSE );
388                 rtp_tree = proto_item_add_subtree( ti, ett_rtp );
389
390                 proto_tree_add_uint( rtp_tree, hf_rtp_version, tvb,
391                     offset, 1, octet1 );
392                 proto_tree_add_boolean( rtp_tree, hf_rtp_padding, tvb,
393                     offset, 1, octet1 );
394                 proto_tree_add_boolean( rtp_tree, hf_rtp_extension, tvb,
395                     offset, 1, octet1 );
396                 proto_tree_add_uint( rtp_tree, hf_rtp_csrc_count, tvb,
397                     offset, 1, octet1 );
398                 offset++;
399
400                 proto_tree_add_boolean( rtp_tree, hf_rtp_marker, tvb, offset,
401                     1, octet2 );
402                 proto_tree_add_uint( rtp_tree, hf_rtp_payload_type, tvb,
403                     offset, 1, octet2 );
404                 offset++;
405
406                 /* Sequence number 16 bits (2 octets) */
407                 proto_tree_add_uint( rtp_tree, hf_rtp_seq_nr, tvb, offset, 2, seq_num );
408                 offset += 2;
409
410                 /* Timestamp 32 bits (4 octets) */
411                 proto_tree_add_uint( rtp_tree, hf_rtp_timestamp, tvb, offset, 4, timestamp );
412                 offset += 4;
413
414                 /* Synchronization source identifier 32 bits (4 octets) */
415                 proto_tree_add_uint( rtp_tree, hf_rtp_ssrc, tvb, offset, 4, sync_src );
416                 offset += 4;
417         } else {
418                 offset += 12;
419         } 
420         /* CSRC list*/
421         if ( csrc_count > 0 ) {
422                 if ( tree ) {
423                         ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Contributing Source identifiers");
424                         rtp_csrc_tree = proto_item_add_subtree( ti, ett_csrc_list );
425                 }
426                 for (i = 0; i < csrc_count; i++ ) {
427                         csrc_item = tvb_get_ntohl( tvb, offset );
428                         if ( tree ) proto_tree_add_uint_format( rtp_csrc_tree,
429                             hf_rtp_csrc_item, tvb, offset, 4,
430                             csrc_item,
431                             "CSRC item %d: %u",
432                             i, csrc_item );
433                         offset += 4;
434                 }
435         }
436
437         /* Optional RTP header extension */
438         if ( extension_set ) {
439                 /* Defined by profile field is 16 bits (2 octets) */
440                 if ( tree ) proto_tree_add_uint( rtp_tree, hf_rtp_prof_define, tvb, offset, 2, tvb_get_ntohs( tvb, offset ) );
441                 offset += 2;
442
443                 hdr_extension = tvb_get_ntohs( tvb, offset );
444                 if ( tree ) proto_tree_add_uint( rtp_tree, hf_rtp_length, tvb,
445                     offset, 2, hdr_extension);
446                 offset += 2;
447                 if ( hdr_extension > 0 ) {
448                         if ( tree ) { ti = proto_tree_add_text(rtp_tree, tvb, offset, csrc_count * 4, "Header extensions");
449                         /* I'm re-using the old tree variable here
450                            from the CSRC list!*/
451                         rtp_csrc_tree = proto_item_add_subtree( ti,
452                             ett_hdr_ext );
453             }
454                         for (i = 0; i < hdr_extension; i++ ) {
455                                 if ( tree ) proto_tree_add_uint( rtp_csrc_tree, hf_rtp_hdr_ext, tvb, offset, 4, tvb_get_ntohl( tvb, offset ) );
456                                 offset += 4;
457                         }
458                 }
459         }
460
461         if ( padding_set ) {
462                 /*
463                  * This RTP frame has padding - find it.
464                  *
465                  * The padding count is found in the LAST octet of
466                  * the packet; it contains the number of octets
467                  * that can be ignored at the end of the packet.
468                  */
469                 if (tvb_length(tvb) < tvb_reported_length(tvb)) {
470                         /*
471                          * We don't *have* the last octet of the
472                          * packet, so we can't get the padding
473                          * count.
474                          *
475                          * Put an indication of that into the
476                          * tree, and just put in a raw data
477                          * item.
478                          */
479                         if ( tree ) proto_tree_add_text(rtp_tree, tvb, 0, 0,
480                             "Frame has padding, but not all the frame data was captured");
481                         call_dissector(data_handle,
482                             tvb_new_subset(tvb, offset, -1, -1),
483                             pinfo, rtp_tree);
484                         return;
485                 }
486
487                 padding_count = tvb_get_guint8( tvb,
488                     tvb_reported_length( tvb ) - 1 );
489                 data_len =
490                     tvb_reported_length_remaining( tvb, offset ) - padding_count;
491
492                 rtp_info.info_payload_offset = offset;
493                 rtp_info.info_payload_len = tvb_length_remaining(tvb, offset);
494                 rtp_info.info_padding_count = padding_count;
495
496                 if (data_len > 0) {
497                         /*
498                          * There's data left over when you take out
499                          * the padding; dissect it.
500                          */
501                         dissect_rtp_data( tvb, pinfo, tree, rtp_tree,
502                             offset,
503                             data_len,
504                             data_len,
505                             payload_type );
506                         offset += data_len;
507                 } else if (data_len < 0) {
508                         /*
509                          * The padding count is bigger than the
510                          * amount of RTP payload in the packet!
511                          * Clip the padding count.
512                          *
513                          * XXX - put an item in the tree to indicate
514                          * that the padding count is bogus?
515                          */
516                         padding_count =
517                             tvb_reported_length_remaining(tvb, offset);
518                 }
519                 if (padding_count > 1) {
520                         /*
521                          * There's more than one byte of padding;
522                          * show all but the last byte as padding
523                          * data.
524                          */
525                         if ( tree ) proto_tree_add_item( rtp_tree, hf_rtp_padding_data,
526                             tvb, offset, padding_count - 1, FALSE );
527                         offset += padding_count - 1;
528                 }
529                 /*
530                  * Show the last byte in the PDU as the padding
531                  * count.
532                  */
533                 if ( tree ) proto_tree_add_item( rtp_tree, hf_rtp_padding_count,
534                     tvb, offset, 1, FALSE );
535         }
536         else {
537                 /*
538                  * No padding.
539                  */
540                 dissect_rtp_data( tvb, pinfo, tree, rtp_tree, offset,
541                     tvb_length_remaining( tvb, offset ),
542                     tvb_reported_length_remaining( tvb, offset ),
543                     payload_type );
544                 rtp_info.info_payload_offset = offset;
545                 rtp_info.info_payload_len = tvb_length_remaining(tvb, offset);
546         }
547         if (!pinfo->in_error_pkt)
548                 tap_queue_packet(rtp_tap, pinfo, &rtp_info);
549 }
550
551 void
552 proto_register_rtp(void)
553 {
554         static hf_register_info hf[] =
555         {
556                 {
557                         &hf_rtp_version,
558                         {
559                                 "Version",
560                                 "rtp.version",
561                                 FT_UINT8,
562                                 BASE_DEC,
563                                 VALS(rtp_version_vals),
564                                 0xC0,
565                                 "", HFILL
566                         }
567                 },
568                 {
569                         &hf_rtp_padding,
570                         {
571                                 "Padding",
572                                 "rtp.padding",
573                                 FT_BOOLEAN,
574                                 8,
575                                 NULL,
576                                 0x20,
577                                 "", HFILL
578                         }
579                 },
580                 {
581                         &hf_rtp_extension,
582                         {
583                                 "Extension",
584                                 "rtp.ext",
585                                 FT_BOOLEAN,
586                                 8,
587                                 NULL,
588                                 0x10,
589                                 "", HFILL
590                         }
591                 },
592                 {
593                         &hf_rtp_csrc_count,
594                         {
595                                 "Contributing source identifiers count",
596                                 "rtp.cc",
597                                 FT_UINT8,
598                                 BASE_DEC,
599                                 NULL,
600                                 0x0F,
601                                 "", HFILL
602                         }
603                 },
604                 {
605                         &hf_rtp_marker,
606                         {
607                                 "Marker",
608                                 "rtp.marker",
609                                 FT_BOOLEAN,
610                                 8,
611                                 NULL,
612                                 0x80,
613                                 "", HFILL
614                         }
615                 },
616                 {
617                         &hf_rtp_payload_type,
618                         {
619                                 "Payload type",
620                                 "rtp.p_type",
621                                 FT_UINT8,
622                                 BASE_DEC,
623                                 VALS(rtp_payload_type_vals),
624                                 0x7F,
625                                 "", HFILL
626                         }
627                 },
628                 {
629                         &hf_rtp_seq_nr,
630                         {
631                                 "Sequence number",
632                                 "rtp.seq",
633                                 FT_UINT16,
634                                 BASE_DEC,
635                                 NULL,
636                                 0x0,
637                                 "", HFILL
638                         }
639                 },
640                 {
641                         &hf_rtp_timestamp,
642                         {
643                                 "Timestamp",
644                                 "rtp.timestamp",
645                                 FT_UINT32,
646                                 BASE_DEC,
647                                 NULL,
648                                 0x0,
649                                 "", HFILL
650                         }
651                 },
652                 {
653                         &hf_rtp_ssrc,
654                         {
655                                 "Synchronization Source identifier",
656                                 "rtp.ssrc",
657                                 FT_UINT32,
658                                 BASE_DEC,
659                                 NULL,
660                                 0x0,
661                                 "", HFILL
662                         }
663                 },
664                 {
665                         &hf_rtp_prof_define,
666                         {
667                                 "Defined by profile",
668                                 "rtp.ext.profile",
669                                 FT_UINT16,
670                                 BASE_DEC,
671                                 NULL,
672                                 0x0,
673                                 "", HFILL
674                         }
675                 },
676                 {
677                         &hf_rtp_length,
678                         {
679                                 "Extension length",
680                                 "rtp.ext.len",
681                                 FT_UINT16,
682                                 BASE_DEC,
683                                 NULL,
684                                 0x0,
685                                 "", HFILL
686                         }
687                 },
688                 {
689                         &hf_rtp_csrc_item,
690                         {
691                                 "CSRC item",
692                                 "rtp.csrc.item",
693                                 FT_UINT32,
694                                 BASE_DEC,
695                                 NULL,
696                                 0x0,
697                                 "", HFILL
698                         }
699                 },
700                 {
701                         &hf_rtp_hdr_ext,
702                         {
703                                 "Header extension",
704                                 "rtp.hdr_ext",
705                                 FT_UINT32,
706                                 BASE_DEC,
707                                 NULL,
708                                 0x0,
709                                 "", HFILL
710                         }
711                 },
712                 {
713                         &hf_rtp_data,
714                         {
715                                 "Payload",
716                                 "rtp.payload",
717                                 FT_BYTES,
718                                 BASE_HEX,
719                                 NULL,
720                                 0x0,
721                                 "", HFILL
722                         }
723                 },
724                 {
725                         &hf_rtp_padding_data,
726                         {
727                                 "Padding data",
728                                 "rtp.padding.data",
729                                 FT_BYTES,
730                                 BASE_HEX,
731                                 NULL,
732                                 0x0,
733                                 "", HFILL
734                         }
735                 },
736                 {
737                         &hf_rtp_padding_count,
738                         {
739                                 "Padding count",
740                                 "rtp.padding.count",
741                                 FT_UINT8,
742                                 BASE_DEC,
743                                 NULL,
744                                 0x0,
745                                 "", HFILL
746                         }
747                 },
748 };
749
750         static gint *ett[] =
751         {
752                 &ett_rtp,
753                 &ett_csrc_list,
754                 &ett_hdr_ext,
755         };
756
757
758         proto_rtp = proto_register_protocol("Real-Time Transport Protocol",
759             "RTP", "rtp");
760         proto_register_field_array(proto_rtp, hf, array_length(hf));
761         proto_register_subtree_array(ett, array_length(ett));
762
763         register_dissector("rtp", dissect_rtp, proto_rtp);
764         rtp_tap = register_tap("rtp");
765
766         rtp_pt_dissector_table = register_dissector_table("rtp.pt",
767             "RTP payload type", FT_UINT8, BASE_DEC);
768
769 #if 0
770         register_init_routine( &rtp_init );
771 #endif
772 }
773
774 void
775 proto_reg_handoff_rtp(void)
776 {
777         dissector_handle_t rtp_handle;
778
779         data_handle = find_dissector("data");
780
781         /*
782          * Register this dissector as one that can be selected by a
783          * UDP port number.
784          */
785         rtp_handle = find_dissector("rtp");
786         dissector_add_handle("udp.port", rtp_handle);
787 }