Trivial warning fixes
[obnox/wireshark/wip.git] / epan / dissectors / packet-dccp.c
1 /* packet-dccp.c
2  * Routines for Datagram Congestion Control Protocol, "DCCP" dissection:
3  * it should be conformance to draft-ietf-dccp-spec-11.txt
4  *
5  * Copyright 2005 _FF_
6  *
7  * Francesco Fondelli <francesco dot fondelli, gmail dot com>
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * Copied from packet-udp.c
16  *
17  * This program is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU General Public License
19  * as published by the Free Software Foundation; either version 2
20  * of the License, or (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30  */
31
32
33 /* NOTES:
34  *
35  * Nov 13, 2006: makes checksum computation dependent
36  * upon the header CsCov field (cf. RFC 4340, 5.1)
37  * (Gerrit Renker)
38  *
39  * Nov 13, 2006: removes the case where checksums are zero
40  * (unlike UDP/packet-udp, from which the code stems,
41  * zero checksums are illegal in DCCP (as in TCP))
42  * (Gerrit Renker)
43  *
44  * Jan 29, 2007: updates the offsets of the timestamps to be
45  * compliant to (cf. RFC 4342, sec. 13).
46  * (Gerrit Renker)
47  */
48
49 #ifdef HAVE_CONFIG_H
50 # include "config.h"
51 #endif
52
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56
57 #include <glib.h>
58 #include <epan/packet.h>
59 #include <epan/addr_resolv.h>
60 #include <epan/ipproto.h>
61 #include <epan/in_cksum.h>
62 #include <epan/prefs.h>
63 #include <epan/emem.h>
64
65 #include "packet-dccp.h"
66
67 #include "packet-ip.h"
68 #include <epan/conversation.h>
69 #include <epan/tap.h>
70
71 /* Some definitions and the dissect_options() logic have been taken from Arnaldo Carvalho de Melo's DCCP implementation, thanks! */
72
73 #define DCCP_HDR_LEN                    16      /* base DCCP header length, with 48 bits seqnos */
74 #define DCCP_HDR_LEN_MIN                12      /*                        , with 24 bits seqnum */
75 #define DCCP_HDR_PKT_TYPES_LEN_MAX      12      /* max per packet type extra header length */
76 #define DCCP_OPT_LEN_MAX                1008
77 #define DCCP_HDR_LEN_MAX                (DCCP_HDR_LEN + DCCP_HDR_PKT_TYPES_LEN_MAX + DCCP_OPT_LEN_MAX)
78
79
80 static const value_string dccp_packet_type_vals[] = {
81         {0x0, "Request"},
82         {0x1, "Response"},
83         {0x2, "Data"},
84         {0x3, "Ack"},
85         {0x4, "DataAck"},
86         {0x5, "CloseReq"},
87         {0x6, "Close"},
88         {0x7, "Reset"},
89         {0x8, "Sync"},
90         {0x9, "SyncAck"},
91         {0xA, "Reserved"},
92         {0xB, "Reserved"},
93         {0xC, "Reserved"},
94         {0xD, "Reserved"},
95         {0xE, "Reserved"},
96         {0xF, "Reserved"},
97         {0, NULL}
98 };
99
100 static const value_string dccp_reset_code_vals[] = {
101         {0x00, "Unspecified"},
102         {0x01, "Closed"},
103         {0x02, "Aborted"},
104         {0x03, "No Connection"},
105         {0x04, "Packet Error"},
106         {0x05, "Option Error"},
107         {0x06, "Mandatory Error"},
108         {0x07, "Connection Refused"},
109         {0x08, "Bad Service Code"},
110         {0x09, "Too Busy"},
111         {0x0A, "Bad Init Cookie"},
112         {0x0B, "Aggression Penalty"},
113         {0x0C, "Reserved"},
114         {0, NULL}
115 };
116
117 static const value_string dccp_feature_options_vals[] = {
118         {0x20, "Change L"},
119         {0x21, "Confirm L"},
120         {0x22, "Change R"},
121         {0x23, "Confirm R"},
122         {0, NULL}
123 };
124
125 static const value_string dccp_feature_numbers_vals[] = {
126         {0x01, "CCID"},
127         {0x02, "Allow Short Seqnos"},
128         {0x03, "Sequence Window"},
129         {0x04, "ECN Incapable"},
130         {0x05, "Ack Ratio"},
131         {0x06, "Send Ack Vector"},
132         {0x07, "Send NDP Count"},
133         {0x08, "Minimum Checksum Coverage"},
134         {0x09, "Check Data Checksum"},
135         {0xC0, "Send Loss Event Rate"},         /* CCID3, RFC 4342, 8.5 */
136         {0, NULL}
137 };
138
139
140 #if 0
141 #define DBG(str, args...)       do {\
142                                         fprintf(stdout, \
143                                         "[%s][%s][%d]: ",\
144                                         __FILE__, \
145                                         __FUNCTION__, \
146                                         __LINE__); \
147                                         fflush(stdout); \
148                                         fprintf(stdout, str, ## args); \
149                                 } while (0)
150 #else
151 #define DBG0(format)
152 #define DBG1(format, arg1)
153 #define DBG2(format, arg1, arg2)
154 #endif /* 0/1 */
155
156
157 static int proto_dccp = -1;
158 static int dccp_tap = -1;
159
160 static int hf_dccp_srcport = -1;
161 static int hf_dccp_dstport = -1;
162 static int hf_dccp_port = -1;
163 static int hf_dccp_data_offset = -1;
164 static int hf_dccp_ccval = -1;
165 static int hf_dccp_cscov = -1;
166 static int hf_dccp_checksum = -1;
167 static int hf_dccp_checksum_bad = -1;
168 static int hf_dccp_res1 = -1;
169 static int hf_dccp_type = -1;
170 static int hf_dccp_x = -1;
171 static int hf_dccp_res2 = -1;
172 static int hf_dccp_seq = -1;
173
174 static int hf_dccp_ack_res = -1;
175 static int hf_dccp_ack = -1;
176
177 static int hf_dccp_service_code = -1;
178 static int hf_dccp_reset_code = -1;
179 static int hf_dccp_data1 = -1;
180 static int hf_dccp_data2 = -1;
181 static int hf_dccp_data3 = -1;
182
183 static int hf_dccp_options = -1;
184 static int hf_dccp_option_type = -1;
185 static int hf_dccp_feature_number = -1;
186 static int hf_dccp_ndp_count = -1;
187 static int hf_dccp_timestamp = -1;
188 static int hf_dccp_timestamp_echo = -1;
189 static int hf_dccp_elapsed_time = -1;
190 static int hf_dccp_data_checksum = -1;
191
192 static int hf_dccp_malformed = -1;
193
194 static gint ett_dccp = -1;
195 static gint ett_dccp_options = -1;
196
197 static dissector_table_t dccp_subdissector_table;
198 static heur_dissector_list_t heur_subdissector_list;
199 static dissector_handle_t data_handle;
200
201 /* preferences */
202 static gboolean dccp_summary_in_tree = TRUE;
203 static gboolean try_heuristic_first = FALSE;
204 static gboolean dccp_check_checksum = TRUE;
205
206
207 static void
208 decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, int sport, int dport)
209 {
210         tvbuff_t *next_tvb;
211         int low_port, high_port;
212
213         next_tvb = tvb_new_subset(tvb, offset, -1, -1);
214
215         /* determine if this packet is part of a conversation and call dissector */
216         /* for the conversation if available */
217
218         if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_DCCP, sport, dport, next_tvb, pinfo, tree)) {
219                 return;
220         }
221
222         if (try_heuristic_first) {
223                 /* do lookup with the heuristic subdissector table */
224                 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) {
225                         return;
226                 }
227         }
228
229         /* Do lookups with the subdissector table.
230            We try the port number with the lower value first, followed by the
231            port number with the higher value.  This means that, for packets
232            where a dissector is registered for *both* port numbers:
233
234            1) we pick the same dissector for traffic going in both directions;
235
236            2) we prefer the port number that's more likely to be the right
237            one (as that prefers well-known ports to reserved ports);
238
239            although there is, of course, no guarantee that any such strategy
240            will always pick the right port number.
241            XXX - we ignore port numbers of 0, as some dissectors use a port
242            number of 0 to disable the port. */
243
244         if (sport > dport) {
245                 low_port = dport;
246                 high_port = sport;
247         } else {
248                 low_port = sport;
249                 high_port = dport;
250         }
251         if (low_port != 0 &&
252             dissector_try_port(dccp_subdissector_table, low_port, next_tvb, pinfo, tree)) {
253                 return;
254         }
255         if (high_port != 0 &&
256             dissector_try_port(dccp_subdissector_table, high_port, next_tvb, pinfo, tree)) {
257                 return;
258         }
259
260         if (!try_heuristic_first) {
261                 /* do lookup with the heuristic subdissector table */
262                 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree)) {
263                         return;
264                 }
265         }
266
267         /* Oh, well, we don't know this; dissect it as data. */
268         call_dissector(data_handle, next_tvb, pinfo, tree);
269 }
270
271 /*
272  *      Auxiliary functions to dissect DCCP options
273  */
274 /* decode a variable-length number of nbytes starting at offset. Based on a concept by Arnaldo de Melo */
275 static guint64 tvb_get_ntoh_var(tvbuff_t *tvb, gint offset, guint nbytes)
276 {
277         const guint8* ptr;
278         guint64 value = 0;
279
280         ptr = tvb_get_ptr(tvb, offset, nbytes);
281         if (nbytes > 5)
282                 value += ((guint64)*ptr++) << 40;
283         if (nbytes > 4)
284                 value += ((guint64)*ptr++) << 32;
285         if (nbytes > 3)
286                 value += ((guint64)*ptr++) << 24;
287         if (nbytes > 2)
288                 value += ((guint64)*ptr++) << 16;
289         if (nbytes > 1)
290                 value += ((guint64)*ptr++) << 8;
291         if (nbytes > 0)
292                 value += *ptr;
293
294         return value;
295 }
296
297 static void dissect_feature_options(proto_tree *dccp_options_tree, tvbuff_t *tvb, int offset, guint8 option_len,
298                                     guint8 option_type)
299 {
300         guint8 feature_number = tvb_get_guint8(tvb, offset + 2);
301         proto_item *dccp_item, *hidden_item;
302         int i;
303
304         hidden_item = proto_tree_add_uint(dccp_options_tree, hf_dccp_feature_number, tvb, offset + 2, 1, feature_number);
305         PROTO_ITEM_SET_HIDDEN(hidden_item);
306
307         dccp_item = proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "%s(",
308                                         val_to_str(option_type, dccp_feature_options_vals, "Unknown Type"));
309
310         /* decode the feature according to whether it is server-priority (list) or NN (single number) */
311         switch (feature_number) {
312         /*              Server Priority features (RFC 4340, 6.3.1)              */
313         case 1:                 /* Congestion Control ID (CCID); fall through   */
314         case 2:                 /* Allow Short Seqnos; fall through             */
315         case 4:                 /* ECN Incapable; fall through                  */
316         case 6:                 /* Send Ack Vector; fall through                */
317         case 7:                 /* Send NDP Count; fall through                 */
318         case 8:                 /* Minimum Checksum Coverage; fall through      */
319         case 9:                 /* Check Data Checksum; fall through            */
320         case 192:               /* Send Loss Event Rate, RFC 4342, section 8.4  */
321                 proto_item_append_text(dccp_item, "%s",
322                                        val_to_str(feature_number, dccp_feature_numbers_vals, "Unknown Type"));
323                 for (i = 0; i < option_len - 3; i++)
324                         proto_item_append_text(dccp_item, "%s %d", i? "," : "", tvb_get_guint8(tvb, offset + 3 + i));
325                 break;
326         /*       Non-negotiable features (RFC 4340, 6.3.2)       */
327         case 3:                 /* Sequence Window; fall through */
328         case 5:                 /* Ack Ratio                     */
329                 proto_item_append_text(dccp_item, "%s",
330                                        val_to_str(feature_number, dccp_feature_numbers_vals, "Unknown Type"));
331
332                 if (option_len > 3)     /* could be empty Confirm */
333                         proto_item_append_text(dccp_item, " %" G_GINT64_MODIFIER "u", tvb_get_ntoh_var(tvb, offset + 3, option_len - 3));
334                 break;
335         /* Reserved, specific, or unknown features */
336         default:
337                 if (feature_number == 0 ||
338                     (feature_number >= 10 && feature_number <= 127))
339                         proto_item_append_text(dccp_item, "Reserved feature number %d", feature_number);
340                 else if (feature_number >= 193)
341                         proto_item_append_text(dccp_item, "CCID-specific feature number %d", feature_number);
342                 else
343                         proto_item_append_text(dccp_item, "Unknown feature number %d", feature_number);
344                 break;
345         }
346         proto_item_append_text(dccp_item, ")");
347 }
348
349 /*
350  * This function dissects DCCP options
351  */
352 static void dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *dccp_options_tree, proto_tree *tree _U_, e_dccphdr *dccph _U_,
353                             int offset_start,
354                             int offset_end)
355 {
356         /* if here I'm sure there is at least offset_end - offset_start bytes in tvb and it should be options */
357         int offset=offset_start;
358         guint8 option_type = 0;
359         guint8 option_len  = 0;
360         int i;
361         guint32 p;
362         proto_item *dccp_item = NULL;
363         proto_item *hidden_item;
364
365         while( offset < offset_end ) {
366
367                 /* DBG("offset==%d\n", offset); */
368
369                 /* first byte is the option type */
370                 option_type = tvb_get_guint8(tvb, offset);
371                 hidden_item = proto_tree_add_uint(dccp_options_tree, hf_dccp_option_type, tvb, offset, 1, option_type);
372                 PROTO_ITEM_SET_HIDDEN(hidden_item);
373
374                 if (option_type >= 32) {                               /* variable length options */
375
376                         if(!tvb_bytes_exist(tvb, offset, 1)) {
377                                 /* DBG("malformed\n"); */
378                                 hidden_item = proto_tree_add_boolean(dccp_options_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
379                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
380                                 THROW(ReportedBoundsError);
381                         }
382
383                         option_len = tvb_get_guint8(tvb, offset + 1);
384
385                         if (option_len < 2) {
386                                 /* DBG("malformed\n"); */
387                                 hidden_item = proto_tree_add_boolean(dccp_options_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
388                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
389                                 THROW(ReportedBoundsError);
390                         }
391
392                         if(!tvb_bytes_exist(tvb, offset, option_len)) {
393                                 /* DBG("malformed\n"); */
394                                 hidden_item = proto_tree_add_boolean(dccp_options_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
395                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
396                                 THROW(ReportedBoundsError);
397                         }
398
399                 } else {                                               /* 1byte options */
400                         option_len = 1;
401                 }
402
403                 switch (option_type) {
404
405                 case 0:
406                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Padding");
407                         break;
408
409                 case 1:
410                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Mandatory");
411                         break;
412
413                 case 2:
414                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Slow Receiver");
415                         break;
416
417                 case 32:
418                 case 33:
419                 case 34:
420                 case 35:
421                         dissect_feature_options(dccp_options_tree, tvb, offset, option_len, option_type);
422                         break;
423
424                 case 36:
425                         dccp_item = proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Init Cookie(");
426                         for (i = 0; i < option_len - 2; i++) {
427                                 if(i==0)
428                                         proto_item_append_text(dccp_item, "%02x", tvb_get_guint8(tvb, offset + 2 + i));
429                                 else
430                                         proto_item_append_text(dccp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
431                         }
432                         proto_item_append_text(dccp_item, ")");
433                         break;
434
435                 case 37:
436                         if (option_len > 8)
437                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "NDP Count too long (max 6 bytes)");
438                         else
439                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "NDP Count: %" G_GINT64_MODIFIER "u",
440                                                     tvb_get_ntoh_var(tvb, offset + 2, option_len - 2));
441                         break;
442
443                 case 38:
444                         dccp_item = proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Ack Vector [Nonce 0]:");
445                         for (i = 0; i < option_len - 2; i++)
446                                 proto_item_append_text(dccp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
447                         break;
448
449                 case 39:
450                         dccp_item = proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Ack Vector [Nonce 1]:");
451                         for (i = 0; i < option_len - 2; i++)
452                                 proto_item_append_text(dccp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
453                         proto_item_append_text(dccp_item, ")");
454                         break;
455
456                 case 40:
457                         dccp_item = proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Data Dropped:");
458                         for (i = 0; i < option_len - 2; i++)
459                                 proto_item_append_text(dccp_item, " %02x", tvb_get_guint8(tvb, offset + 2 + i));
460                         break;
461
462                 case 41:
463                         if(option_len==6)
464                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp, tvb, offset + 2, 4,
465                                                     tvb_get_ntohl(tvb, offset + 2));
466                         else
467                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
468                                                     "Timestamp too long [%u != 6]", option_len);
469                         break;
470
471                 case 42:
472                         if(option_len==6)
473                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo, tvb, offset + 2, 4,
474                                                     tvb_get_ntohl(tvb, offset + 2));
475                         else if (option_len==8) {
476                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo, tvb, offset + 2, 4,
477                                                     tvb_get_ntohl(tvb, offset + 2));
478
479                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time, tvb, offset + 6, 2,
480                                                     tvb_get_ntohs(tvb, offset + 6));
481                         } else if (option_len==10) {
482                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo, tvb, offset + 2, 4,
483                                                     tvb_get_ntohl(tvb, offset + 2));
484
485                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time, tvb, offset + 6, 4,
486                                                     tvb_get_ntohl(tvb, offset + 6));
487                         } else
488                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Wrong Timestamp Echo length");
489                         break;
490
491                 case 43:
492                         if(option_len==4)
493                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time, tvb, offset + 2, 2,
494                                                     tvb_get_ntohs(tvb, offset + 2));
495                         else if (option_len==6)
496                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time, tvb, offset + 2, 4,
497                                                     tvb_get_ntohl(tvb, offset + 2));
498                         else
499                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Wrong Elapsed Time length");
500                         break;
501
502                 case 44:
503                         if(option_len==6) {
504                                 proto_tree_add_uint(dccp_options_tree, hf_dccp_data_checksum, tvb, offset + 2, 4,
505                                                     tvb_get_ntohl(tvb, offset + 2));
506                         } else
507                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Wrong Data checksum length");
508                         break;
509                 case 192:       /* RFC 4342, 8.5 */
510                         if(option_len == 6) {
511                                 p = tvb_get_ntohl(tvb, offset + 2);
512                                 /* According to the comment in section 8.5 of RFC 4342, 0xffffffff can mean zero */
513                                 if (p == 0xFFFFFFFF)
514                                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "CCID3 Loss Event Rate: 0 (or max)");
515                                 else
516                                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "CCID3 Loss Event Rate: %u", p);
517                         } else
518                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Wrong CCID3 Loss Event Rate length");
519                         break;
520                 case 193:       /* RFC 4342, 8.6 */
521                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "CCID3 Loss Intervals");
522                                 /* FIXME: not implemented and apparently not used by any implementation so far */
523                         break;
524                 case 194:       /* RFC 4342, 8.3 */
525                         if(option_len == 6)
526                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "CCID3 Receive Rate: %u bytes/sec",
527                                                     tvb_get_ntohl(tvb, offset + 2));
528                         else
529                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Wrong CCID3 Receive Rate length");
530                         break;
531                 default :
532                         if(((option_type >= 45) && (option_type <= 127)) ||
533                            ((option_type >=  3) && (option_type <=  31))) {
534                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Reserved");
535                                 break;
536                         }
537
538                         if (option_type >= 128) {
539                                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "CCID option %d", option_type);
540                                 break;
541                         }
542
543                         /* if here we don't know this option */
544                         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "Unknown");
545                         break;
546
547                 } /* end switch() */
548
549                 offset+=option_len; /* Skip over the dissected option */
550
551         } /* end while() */
552 }
553 /* compute DCCP checksum coverage according to RFC 4340, section 9 */
554 static inline guint dccp_csum_coverage(const e_dccphdr *dccph, guint len)
555 {
556         guint cov;
557
558         if (dccph->cscov == 0)
559                 return len;
560         cov = (dccph->data_offset + dccph->cscov - 1) * sizeof(guint32);
561         return (cov > len)? len : cov;
562 }
563
564 static void dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
565 {
566         proto_tree *dccp_tree = NULL;
567         proto_tree *dccp_options_tree = NULL;
568         proto_item *dccp_item = NULL;
569         proto_item *hidden_item;
570
571         vec_t      cksum_vec[4];
572         guint32    phdr[2];
573         guint16    computed_cksum;
574         guint      offset = 0;
575         guint      len = 0;
576         guint      reported_len = 0;
577         guint      advertised_dccp_header_len = 0;
578         guint      options_len = 0;
579         e_dccphdr   *dccph;
580
581         /* get at least a full message header */
582         if(tvb_length(tvb) < DCCP_HDR_LEN_MIN) {
583                 /* DBG("malformed\n"); */
584                 if (tree) {
585                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
586                         PROTO_ITEM_SET_HIDDEN(hidden_item);
587                 }
588                 if (check_col(pinfo->cinfo, COL_INFO))
589                         col_set_str(pinfo->cinfo, COL_INFO, "Packet too short");
590                 THROW(ReportedBoundsError);
591         }
592
593         dccph=ep_alloc(sizeof(e_dccphdr));
594
595         memset(dccph, 0, sizeof(e_dccphdr));
596
597         SET_ADDRESS(&dccph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
598         SET_ADDRESS(&dccph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
599
600         if (check_col(pinfo->cinfo, COL_PROTOCOL))
601                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
602         if (check_col(pinfo->cinfo, COL_INFO))
603                 col_clear(pinfo->cinfo, COL_INFO);
604
605         /* Extract generic header */
606         dccph->sport=tvb_get_ntohs(tvb, offset);
607         /* DBG("dccph->sport: %d\n", dccph->sport); */
608         dccph->dport=tvb_get_ntohs(tvb, offset+2);
609         /* DBG("dccph->dport: %d\n", dccph->dport); */
610
611         /* update pinfo structure. I guess I have to do it, because this is a transport protocol dissector. Right? */
612         pinfo->ptype=PT_DCCP;
613         pinfo->srcport=dccph->sport;
614         pinfo->destport=dccph->dport;
615
616         dccph->data_offset=tvb_get_guint8(tvb, offset+4);
617         /* DBG("dccph->data_offset: %d\n", dccph->data_offset); */
618         dccph->cscov=tvb_get_guint8(tvb, offset+5)&0x0F;
619         /* DBG("dccph->cscov: %d\n", dccph->cscov); */
620         dccph->ccval=tvb_get_guint8(tvb, offset+5) &0xF0;
621         dccph->ccval >>= 4;
622         /* DBG("dccph->ccval: %d\n", dccph->ccval); */
623         dccph->checksum=tvb_get_ntohs(tvb, offset+6);
624         /* DBG("dccph->checksum: %d\n", dccph->checksum); */
625         dccph->reserved1=tvb_get_guint8(tvb, offset+8)&0xE0;
626         dccph->reserved1>>=5;
627         /* DBG("dccph->reserved1: %d\n", dccph->reserved1); */
628         dccph->type=tvb_get_guint8(tvb, offset+8)&0x1E;
629         dccph->type>>=1;
630         /* DBG("dccph->type: %d\n", dccph->type); */
631         dccph->x=tvb_get_guint8(tvb, offset+8)&0x01;
632         /* DBG("dccph->x: %d\n", dccph->x); */
633         if(dccph->x) {
634                 if(tvb_length(tvb) < DCCP_HDR_LEN) { /* at least 16 bytes */
635                         /* DBG("malformed\n"); */
636                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
637                         PROTO_ITEM_SET_HIDDEN(hidden_item);
638                         THROW(ReportedBoundsError);
639                 }
640                 dccph->reserved2=tvb_get_guint8(tvb, offset+9);
641                 /* DBG("dccph->reserved2: %u\n", dccph->reserved2); */
642                 dccph->seq=tvb_get_ntohs(tvb, offset+10);
643                 dccph->seq<<=32;
644                 dccph->seq+=tvb_get_ntohl(tvb, offset+12);
645                 /* DBG("dccph->seq[48bits]: %" G_GINT64_MODIFIER "u\n", dccph->seq); */
646         } else {
647                 dccph->seq=tvb_get_guint8(tvb, offset+9);
648                 dccph->seq<<=16;
649                 dccph->seq+=tvb_get_ntohs(tvb, offset+10);
650                 /* DBG("dccph->seq[24bits]: %" G_GINT64_MODIFIER "u\n", dccph->seq); */
651         }
652
653         if (check_col(pinfo->cinfo, COL_INFO))
654                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s [%s] Seq=%" G_GINT64_MODIFIER "u",
655                              get_dccp_port(dccph->sport),
656                              get_dccp_port(dccph->dport),
657                              val_to_str(dccph->type, dccp_packet_type_vals, "Unknown Type"),
658                              dccph->seq);
659
660
661         if (tree) {
662                 if(dccp_summary_in_tree) {
663                         dccp_item =
664                                 proto_tree_add_protocol_format(tree, proto_dccp, tvb, offset, dccph->data_offset*4,
665                                                                "Datagram Congestion Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)"
666                                                                " [%s] Seq=%" G_GINT64_MODIFIER "u",
667                                                                get_dccp_port(dccph->sport), dccph->sport,
668                                                                get_dccp_port(dccph->dport), dccph->dport,
669                                                                val_to_str(dccph->type, dccp_packet_type_vals, "Unknown Type"),
670                                                                dccph->seq);
671                 } else {
672                         dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, 8, FALSE);
673                 }
674
675                 dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
676
677                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_srcport, tvb, offset, 2, dccph->sport,
678                                            "%s (%u)", get_dccp_port(dccph->sport), dccph->sport);
679                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_dstport, tvb, offset + 2, 2, dccph->dport,
680                                            "%s (%u)", get_dccp_port(dccph->dport), dccph->dport);
681
682                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2, dccph->sport);
683                 PROTO_ITEM_SET_HIDDEN(hidden_item);
684                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset + 2, 2, dccph->dport);
685                 PROTO_ITEM_SET_HIDDEN(hidden_item);
686
687                 proto_tree_add_uint(dccp_tree, hf_dccp_data_offset, tvb, offset + 4, 1, dccph->data_offset);
688                 proto_tree_add_uint(dccp_tree, hf_dccp_ccval, tvb, offset + 5, 1, dccph->ccval);
689                 proto_tree_add_uint(dccp_tree, hf_dccp_cscov, tvb, offset + 5, 1, dccph->cscov);
690
691                 /* checksum analysis taken from packet-udp (difference: mandatory checksums in DCCP) */
692
693                 reported_len = tvb_reported_length(tvb);
694                 len = tvb_length(tvb);
695                 if (!pinfo->fragmented && len >= reported_len) {
696
697                         /* The packet isn't part of a fragmented datagram and isn't
698                            truncated, so we can checksum it.
699                            XXX - make a bigger scatter-gather list once we do fragment
700                            reassembly? */
701
702                         if (dccp_check_checksum) {
703
704                                 /* Set up the fields of the pseudo-header. */
705                                 cksum_vec[0].ptr = pinfo->src.data;
706                                 cksum_vec[0].len = pinfo->src.len;
707                                 cksum_vec[1].ptr = pinfo->dst.data;
708                                 cksum_vec[1].len = pinfo->dst.len;
709                                 cksum_vec[2].ptr = (const guint8 *)&phdr;
710                                 switch (pinfo->src.type) {
711
712                                 case AT_IPv4:
713                                         phdr[0] = g_htonl((IP_PROTO_DCCP<<16) + reported_len);
714                                         cksum_vec[2].len = 4;
715                                         break;
716                                 case AT_IPv6:
717                                         phdr[0] = g_htonl(reported_len);
718                                         phdr[1] = g_htonl(IP_PROTO_DCCP);
719                                         cksum_vec[2].len = 8;
720                                         break;
721
722                                 default:
723                                         /* DCCP runs only atop IPv4 and IPv6.... */
724                                   /*DISSECTOR_ASSERT_NOT_REACHED();*/
725                                         break;
726                                 }
727                                 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
728                                 cksum_vec[3].len = dccp_csum_coverage(dccph, reported_len);
729                                 computed_cksum = in_cksum(&cksum_vec[0], 4);
730                                 if (computed_cksum == 0) {
731                                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
732                                                                          offset + 6, 2, dccph->checksum,
733                                                                          "0x%04x [correct]", dccph->checksum);
734                                 } else {
735                                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_checksum_bad, tvb, offset + 6, 2, TRUE);;
736                                         PROTO_ITEM_SET_HIDDEN(hidden_item);
737                                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb, offset + 6, 2, dccph->checksum,
738                                                                          "0x%04x [incorrect, should be 0x%04x]", dccph->checksum,
739                                                                          in_cksum_shouldbe(dccph->checksum, computed_cksum));
740                                 }
741                         } else {
742                                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
743                                                                  offset + 6, 2, dccph->checksum, "0x%04x", dccph->checksum);
744                         }
745                 } else {
746                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
747                                                          offset + 6, 2, dccph->checksum, "0x%04x", dccph->checksum);
748                 }
749
750                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_res1, tvb, offset + 8, 1, dccph->reserved1);
751                 PROTO_ITEM_SET_HIDDEN(hidden_item);
752                 proto_tree_add_uint(dccp_tree, hf_dccp_type, tvb, offset + 8, 1, dccph->type);
753                 proto_tree_add_boolean(dccp_tree, hf_dccp_x, tvb, offset + 8, 1, dccph->x);
754                 if(dccph->x) {
755                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_res2, tvb, offset + 9, 1, dccph->reserved2);
756                         PROTO_ITEM_SET_HIDDEN(hidden_item);
757                         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset + 10, 6, dccph->seq);
758                 } else {
759                         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset + 9, 3, dccph->seq);
760
761                 }
762         }
763
764         if(dccph->x)
765                 offset+=16; /* Skip over extended Generic header */
766         else
767                 offset+=12; /* Skip over not extended Generic header */
768
769         /* dissecting type depending additional fields */
770         switch(dccph->type) {
771
772         case 0x0: /* DCCP-Request */
773                 if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
774                         if(tree)
775                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
776                         return;
777                 }
778                 dccph->service_code=tvb_get_ntohl(tvb, offset);
779                 if(tree)
780                         proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4, dccph->service_code);
781                 if (check_col(pinfo->cinfo, COL_INFO))
782                         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)", dccph->service_code);
783
784                 offset+=4; /* Skip over service code */
785                 break;
786
787         case 0x1: /* DCCP-Response */
788                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
789                         if(tree)
790                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
791                         return;
792                 }
793                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
794                 if(tree) {
795                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
796                         PROTO_ITEM_SET_HIDDEN(hidden_item);
797                 }
798                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
799                 dccph->ack<<=32;
800                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
801
802                 if(tree)
803                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
804                 if (check_col(pinfo->cinfo, COL_INFO))
805                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
806
807                 offset+=8; /* Skip over Acknowledgement Number Subheader */
808
809                 if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
810                         if(tree)
811                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
812                         return;
813                 }
814                 dccph->service_code=tvb_get_ntohl(tvb, offset);
815                 if(tree)
816                         proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4, dccph->service_code);
817                 if (check_col(pinfo->cinfo, COL_INFO))
818                         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)", dccph->service_code);
819
820                 offset+=4; /* Skip over service code */
821                 break;
822
823         case 0x2: /* DCCP-Data */
824                 /* nothing to dissect */
825                 break;
826
827         case 0x3: /* DCCP-Ack */
828         case 0x4: /* DCCP-DataAck */
829                 if(dccph->x) {
830                         if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
831                                 if(tree)
832                                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
833                                 return;
834                         }
835                         dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
836                         if(tree) {
837                                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
838                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
839                         }
840                         dccph->ack=tvb_get_ntohs(tvb, offset+2);
841                         dccph->ack<<=32;
842                         dccph->ack+=tvb_get_ntohl(tvb, offset+4);
843                         if(tree)
844                                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
845                         if (check_col(pinfo->cinfo, COL_INFO))
846                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
847
848                         offset+=8; /* Skip over Acknowledgement Number Subheader */
849                 } else {
850                         if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
851                                 if(tree)
852                                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
853                                 return;
854                         }
855                         dccph->ack_reserved=tvb_get_guint8(tvb, offset);
856                         if(tree) {
857                                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 1, dccph->ack_reserved);
858                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
859                         }
860                         dccph->ack=tvb_get_guint8(tvb, offset+1);
861                         dccph->ack<<=16;
862                         dccph->ack+=tvb_get_ntohs(tvb, offset+2);
863                         if(tree)
864                                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 1, 3, dccph->ack);
865                         if (check_col(pinfo->cinfo, COL_INFO))
866                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
867
868                         offset+=4; /* Skip over Acknowledgement Number Subheader */
869                 }
870                 break;
871
872         case 0x7: /* DCCP-Reset */
873                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
874                         if(tree)
875                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
876                         return;
877                 }
878                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
879                 if(tree) {
880                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
881                         PROTO_ITEM_SET_HIDDEN(hidden_item);
882                 }
883                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
884                 dccph->ack<<=32;
885                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
886                 if(tree)
887                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
888                 if (check_col(pinfo->cinfo, COL_INFO))
889                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
890
891                 offset+=8; /* Skip over Acknowledgement Number Subheader */
892
893                 dccph->reset_code=tvb_get_guint8(tvb, offset);
894                 dccph->data1=tvb_get_guint8(tvb, offset+1);
895                 dccph->data2=tvb_get_guint8(tvb, offset+2);
896                 dccph->data3=tvb_get_guint8(tvb, offset+3);
897                 if(tree) {
898                         proto_tree_add_uint(dccp_tree, hf_dccp_reset_code, tvb, offset, 1, dccph->reset_code);
899                         proto_tree_add_uint(dccp_tree, hf_dccp_data1, tvb, offset + 1, 1, dccph->data1);
900                         proto_tree_add_uint(dccp_tree, hf_dccp_data2, tvb, offset + 2, 1, dccph->data2);
901                         proto_tree_add_uint(dccp_tree, hf_dccp_data3, tvb, offset + 3, 1, dccph->data3);
902                 }
903                 if (check_col(pinfo->cinfo, COL_INFO))
904                         col_append_fstr(pinfo->cinfo, COL_INFO, " (code=%s)", val_to_str(dccph->reset_code, dccp_reset_code_vals, "Unknown"));
905
906                 offset+=4; /* Skip over Reset Code and data123 */
907                 break;
908
909         case 0x5: /* DCCP-CloseReq */
910         case 0x6: /* DCCP-Close */
911         case 0x8: /* DCCP-Sync */
912         case 0x9: /* DCCP-SyncAck */
913                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
914                         if(tree)
915                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
916                         return;
917                 }
918                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
919                 if(tree) {
920                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
921                         PROTO_ITEM_SET_HIDDEN(hidden_item);
922                 }
923                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
924                 dccph->ack<<=32;
925                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
926                 if(tree)
927                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
928                 if (check_col(pinfo->cinfo, COL_INFO))
929                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
930
931                 offset+=8; /* Skip over Acknowledgement Number Subheader */
932                 break;
933
934         default:
935                 if(tree)
936                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "Reserved packet type: unable to dissect further");
937                 return;
938         }
939
940
941         /*  note: data_offset is the offset from the start of the packet's DCCP header to the
942          *  start of its application data area, in 32-bit words.
943          */
944
945         /* it's time to do some checks */
946         advertised_dccp_header_len = dccph->data_offset*4;
947         options_len = advertised_dccp_header_len - offset;
948
949         if ( advertised_dccp_header_len > DCCP_HDR_LEN_MAX ) {
950                 if(tree)
951                         proto_tree_add_text(dccp_tree, tvb, 4, 2,
952                                             "bogus data offset, advertised header length (%d) is larger than max (%d)",
953                                             advertised_dccp_header_len, DCCP_HDR_LEN_MAX);
954                 return;
955         }
956
957         if(tvb_length(tvb) < advertised_dccp_header_len) {
958                 if(tree)
959                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet: missing %d bytes of DCCP header",
960                                             advertised_dccp_header_len - tvb_reported_length_remaining(tvb, offset));
961                 return;
962         }
963
964         if(options_len > DCCP_OPT_LEN_MAX) {
965                 /* DBG("malformed\n"); */
966                 if(tree) {
967                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
968                         PROTO_ITEM_SET_HIDDEN(hidden_item);
969                 }
970                 THROW(ReportedBoundsError);
971         }
972
973
974         /* Dissecting Options (if here we have at least (advertised_dccp_header_len - offset) bytes of options) */
975         if(advertised_dccp_header_len == offset) {
976                 ; /* ok no options, no need to skip over */
977         } else if (advertised_dccp_header_len < offset) {
978                 if(tree) {
979                         proto_tree_add_text(dccp_tree, tvb, 4, 2,
980                                             "bogus data offset, advertised header length (%d) is shorter than expected",
981                                             advertised_dccp_header_len);
982                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
983                         PROTO_ITEM_SET_HIDDEN(hidden_item);
984                 }
985                 THROW(ReportedBoundsError);
986         } else {
987                 if(dccp_tree) {
988                         dccp_item = proto_tree_add_none_format(dccp_tree, hf_dccp_options, tvb, offset, options_len, "Options: (%u bytes)", options_len);
989                         dccp_options_tree = proto_item_add_subtree(dccp_item, ett_dccp_options);
990                 }
991                 dissect_options(tvb, pinfo, dccp_options_tree, tree, dccph, offset, offset + options_len);
992         }
993
994         offset+=options_len; /* Skip over Options */
995
996         /* Queuing tap data */
997         tap_queue_packet(dccp_tap, pinfo, dccph);
998
999         /* Call sub-dissectors */
1000
1001         if (!pinfo->in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
1002                 decode_dccp_ports(tvb, offset, pinfo, tree, dccph->sport, dccph->dport);
1003 }
1004
1005
1006 void proto_register_dccp(void)
1007 {
1008         module_t *dccp_module;
1009
1010         static hf_register_info hf[] = {
1011                 { &hf_dccp_srcport,
1012                 { "Source Port",        "dccp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
1013                   "", HFILL }},
1014
1015                 { &hf_dccp_dstport,
1016                 { "Destination Port",   "dccp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
1017                   "", HFILL }},
1018
1019                 { &hf_dccp_port,
1020                 { "Source or Destination Port", "dccp.port", FT_UINT16, BASE_DEC,  NULL, 0x0,
1021                   "", HFILL }},
1022
1023                 { &hf_dccp_data_offset,
1024                 { "Data Offset",        "dccp.data_offset", FT_UINT8, BASE_DEC, NULL, 0x0,
1025                   "", HFILL }},
1026
1027                 { &hf_dccp_ccval,
1028                 { "CCVal",              "dccp.ccval", FT_UINT8, BASE_DEC,  NULL, 0x0,
1029                   "", HFILL }},
1030
1031                 { &hf_dccp_cscov,
1032                 { "Checksum Coverage",  "dccp.cscov", FT_UINT8, BASE_DEC,  NULL, 0x0,
1033                   "", HFILL }},
1034
1035                 { &hf_dccp_checksum_bad,
1036                 { "Bad Checksum",       "dccp.checksum_bad", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1037                   "", HFILL }},
1038
1039                 { &hf_dccp_checksum,
1040                 { "Checksum",           "dccp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1041                   "", HFILL }},
1042
1043                 { &hf_dccp_res1,
1044                 { "Reserved",           "dccp.res1", FT_UINT8, BASE_HEX, NULL, 0x0,
1045                   "", HFILL }},
1046
1047                 { &hf_dccp_res2,
1048                 { "Reserved",           "dccp.res2", FT_UINT8, BASE_HEX, NULL, 0x0,
1049                   "", HFILL }},
1050
1051                 { &hf_dccp_type,
1052                 { "Type",               "dccp.type", FT_UINT8, BASE_DEC, VALS(dccp_packet_type_vals), 0x0,
1053                   "", HFILL }},
1054
1055                 { &hf_dccp_x,
1056                 { "Extended Sequence Numbers", "dccp.x", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1057                   "", HFILL }},
1058
1059                 { &hf_dccp_seq,
1060                 { "Sequence Number",    "dccp.seq", FT_UINT64, BASE_DEC, NULL, 0x0,
1061                   "", HFILL }},
1062
1063                 { &hf_dccp_ack_res,
1064                 { "Reserved",           "dccp.ack_res", FT_UINT16, BASE_HEX, NULL, 0x0,
1065                   "", HFILL }},
1066
1067                 { &hf_dccp_ack,
1068                 { "Acknowledgement Number", "dccp.ack", FT_UINT64, BASE_DEC, NULL, 0x0,
1069                   "", HFILL }},
1070
1071                 { &hf_dccp_service_code,
1072                 { "Service Code", "dccp.service_code", FT_UINT32, BASE_DEC, NULL, 0x0,
1073                   "", HFILL }},
1074
1075                 { &hf_dccp_reset_code,
1076                 { "Reset Code", "dccp.reset_code", FT_UINT8, BASE_DEC, VALS(dccp_reset_code_vals), 0x0,
1077                   "", HFILL }},
1078
1079                 { &hf_dccp_data1,
1080                 { "Data 1",     "dccp.data1", FT_UINT8, BASE_DEC, NULL, 0x0,
1081                   "", HFILL }},
1082
1083                 { &hf_dccp_data2,
1084                 { "Data 2",     "dccp.data2", FT_UINT8, BASE_DEC, NULL, 0x0,
1085                   "", HFILL }},
1086
1087                 { &hf_dccp_data3,
1088                 { "Data 3",     "dccp.data3", FT_UINT8, BASE_DEC, NULL, 0x0,
1089                   "", HFILL }},
1090
1091                 { &hf_dccp_option_type,
1092                 { "Option Type",     "dccp.option_type", FT_UINT8, BASE_DEC, NULL, 0x0,
1093                   "", HFILL }},
1094
1095                 { &hf_dccp_feature_number,
1096                 { "Feature Number",   "dccp.feature_number", FT_UINT8, BASE_DEC, NULL, 0x0,
1097                   "", HFILL }},
1098
1099                 { &hf_dccp_ndp_count,
1100                 { "NDP Count",   "dccp.ndp_count", FT_UINT64, BASE_DEC, NULL, 0x0,
1101                   "", HFILL }},
1102
1103                 { &hf_dccp_timestamp,
1104                 { "Timestamp",   "dccp.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
1105                   "", HFILL }},
1106
1107                 { &hf_dccp_timestamp_echo,
1108                 { "Timestamp Echo",   "dccp.timestamp_echo", FT_UINT32, BASE_DEC, NULL, 0x0,
1109                   "", HFILL }},
1110
1111                 { &hf_dccp_elapsed_time,
1112                 { "Elapsed Time",   "dccp.elapsed_time", FT_UINT32, BASE_DEC, NULL, 0x0,
1113                   "", HFILL }},
1114
1115                 { &hf_dccp_data_checksum,
1116                 { "Data Checksum",  "dccp.checksum_data", FT_UINT32, BASE_HEX, NULL, 0x0,
1117                   "", HFILL }},
1118
1119                 { &hf_dccp_malformed,
1120                 { "Malformed", "dccp.malformed", FT_BOOLEAN, BASE_DEC, NULL, 0x0,
1121                   "", HFILL }},
1122
1123                 { &hf_dccp_options,
1124                 { "Options", "dccp.options", FT_NONE, BASE_DEC, NULL, 0x0,
1125                   "DCCP Options fields", HFILL }}
1126
1127         };
1128
1129         static gint *ett[] = {
1130                 &ett_dccp,
1131                 &ett_dccp_options
1132         };
1133
1134         proto_dccp = proto_register_protocol("Datagram Congestion Control Protocol", "DCCP", "dccp");
1135         proto_register_field_array(proto_dccp, hf, array_length(hf));
1136         proto_register_subtree_array(ett, array_length(ett));
1137
1138         /* subdissectors */
1139         dccp_subdissector_table = register_dissector_table("dccp.port", "DCCP port", FT_UINT16, BASE_DEC);
1140         register_heur_dissector_list("dccp", &heur_subdissector_list);
1141
1142         /* reg preferences */
1143         dccp_module = prefs_register_protocol(proto_dccp, NULL);
1144         prefs_register_bool_preference(dccp_module, "summary_in_tree",
1145                                        "Show DCCP summary in protocol tree",
1146                                        "Whether the DCCP summary line should be shown in the protocol tree",
1147                                        &dccp_summary_in_tree);
1148
1149         prefs_register_bool_preference(dccp_module, "try_heuristic_first",
1150                                        "Try heuristic sub-dissectors first",
1151                                        "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector "
1152                                        "registered to a specific port",
1153                                        &try_heuristic_first);
1154
1155         prefs_register_bool_preference(dccp_module, "check_checksum",
1156                                        "Check the validity of the DCCP checksum when possible",
1157                                        "Whether to check the validity of the DCCP checksum",
1158                                        &dccp_check_checksum);
1159 }
1160
1161 void proto_reg_handoff_dccp(void)
1162 {
1163         dissector_handle_t dccp_handle;
1164
1165         dccp_handle = create_dissector_handle(dissect_dccp, proto_dccp);
1166         dissector_add("ip.proto", IP_PROTO_DCCP, dccp_handle);
1167         data_handle = find_dissector("data");
1168         dccp_tap = register_tap("dccp");
1169 }