b4c67b0a3bdc0671ebb2a1de3240545036409f35
[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 seqnums */
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 Seqnums"},
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 Seqnums; 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                 col_set_str(pinfo->cinfo, COL_INFO, "Packet too short");
589                 THROW(ReportedBoundsError);
590         }
591
592         dccph=ep_alloc(sizeof(e_dccphdr));
593
594         memset(dccph, 0, sizeof(e_dccphdr));
595
596         SET_ADDRESS(&dccph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
597         SET_ADDRESS(&dccph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);
598
599         col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
600         if (check_col(pinfo->cinfo, COL_INFO))
601                 col_clear(pinfo->cinfo, COL_INFO);
602
603         /* Extract generic header */
604         dccph->sport=tvb_get_ntohs(tvb, offset);
605         /* DBG("dccph->sport: %d\n", dccph->sport); */
606         dccph->dport=tvb_get_ntohs(tvb, offset+2);
607         /* DBG("dccph->dport: %d\n", dccph->dport); */
608
609         /* update pinfo structure. I guess I have to do it, because this is a transport protocol dissector. Right? */
610         pinfo->ptype=PT_DCCP;
611         pinfo->srcport=dccph->sport;
612         pinfo->destport=dccph->dport;
613
614         dccph->data_offset=tvb_get_guint8(tvb, offset+4);
615         /* DBG("dccph->data_offset: %d\n", dccph->data_offset); */
616         dccph->cscov=tvb_get_guint8(tvb, offset+5)&0x0F;
617         /* DBG("dccph->cscov: %d\n", dccph->cscov); */
618         dccph->ccval=tvb_get_guint8(tvb, offset+5) &0xF0;
619         dccph->ccval >>= 4;
620         /* DBG("dccph->ccval: %d\n", dccph->ccval); */
621         dccph->checksum=tvb_get_ntohs(tvb, offset+6);
622         /* DBG("dccph->checksum: %d\n", dccph->checksum); */
623         dccph->reserved1=tvb_get_guint8(tvb, offset+8)&0xE0;
624         dccph->reserved1>>=5;
625         /* DBG("dccph->reserved1: %d\n", dccph->reserved1); */
626         dccph->type=tvb_get_guint8(tvb, offset+8)&0x1E;
627         dccph->type>>=1;
628         /* DBG("dccph->type: %d\n", dccph->type); */
629         dccph->x=tvb_get_guint8(tvb, offset+8)&0x01;
630         /* DBG("dccph->x: %d\n", dccph->x); */
631         if(dccph->x) {
632                 if(tvb_length(tvb) < DCCP_HDR_LEN) { /* at least 16 bytes */
633                         /* DBG("malformed\n"); */
634                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
635                         PROTO_ITEM_SET_HIDDEN(hidden_item);
636                         THROW(ReportedBoundsError);
637                 }
638                 dccph->reserved2=tvb_get_guint8(tvb, offset+9);
639                 /* DBG("dccph->reserved2: %u\n", dccph->reserved2); */
640                 dccph->seq=tvb_get_ntohs(tvb, offset+10);
641                 dccph->seq<<=32;
642                 dccph->seq+=tvb_get_ntohl(tvb, offset+12);
643                 /* DBG("dccph->seq[48bits]: %" G_GINT64_MODIFIER "u\n", dccph->seq); */
644         } else {
645                 dccph->seq=tvb_get_guint8(tvb, offset+9);
646                 dccph->seq<<=16;
647                 dccph->seq+=tvb_get_ntohs(tvb, offset+10);
648                 /* DBG("dccph->seq[24bits]: %" G_GINT64_MODIFIER "u\n", dccph->seq); */
649         }
650
651         if (check_col(pinfo->cinfo, COL_INFO))
652                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s > %s [%s] Seq=%" G_GINT64_MODIFIER "u",
653                              get_dccp_port(dccph->sport),
654                              get_dccp_port(dccph->dport),
655                              val_to_str(dccph->type, dccp_packet_type_vals, "Unknown Type"),
656                              dccph->seq);
657
658
659         if (tree) {
660                 if(dccp_summary_in_tree) {
661                         dccp_item =
662                                 proto_tree_add_protocol_format(tree, proto_dccp, tvb, offset, dccph->data_offset*4,
663                                                                "Datagram Congestion Control Protocol, Src Port: %s (%u), Dst Port: %s (%u)"
664                                                                " [%s] Seq=%" G_GINT64_MODIFIER "u",
665                                                                get_dccp_port(dccph->sport), dccph->sport,
666                                                                get_dccp_port(dccph->dport), dccph->dport,
667                                                                val_to_str(dccph->type, dccp_packet_type_vals, "Unknown Type"),
668                                                                dccph->seq);
669                 } else {
670                         dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, 8, FALSE);
671                 }
672
673                 dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
674
675                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_srcport, tvb, offset, 2, dccph->sport,
676                                            "%s (%u)", get_dccp_port(dccph->sport), dccph->sport);
677                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_dstport, tvb, offset + 2, 2, dccph->dport,
678                                            "%s (%u)", get_dccp_port(dccph->dport), dccph->dport);
679
680                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2, dccph->sport);
681                 PROTO_ITEM_SET_HIDDEN(hidden_item);
682                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset + 2, 2, dccph->dport);
683                 PROTO_ITEM_SET_HIDDEN(hidden_item);
684
685                 proto_tree_add_uint(dccp_tree, hf_dccp_data_offset, tvb, offset + 4, 1, dccph->data_offset);
686                 proto_tree_add_uint(dccp_tree, hf_dccp_ccval, tvb, offset + 5, 1, dccph->ccval);
687                 proto_tree_add_uint(dccp_tree, hf_dccp_cscov, tvb, offset + 5, 1, dccph->cscov);
688
689                 /* checksum analysis taken from packet-udp (difference: mandatory checksums in DCCP) */
690
691                 reported_len = tvb_reported_length(tvb);
692                 len = tvb_length(tvb);
693                 if (!pinfo->fragmented && len >= reported_len) {
694
695                         /* The packet isn't part of a fragmented datagram and isn't
696                            truncated, so we can checksum it.
697                            XXX - make a bigger scatter-gather list once we do fragment
698                            reassembly? */
699
700                         if (dccp_check_checksum) {
701
702                                 /* Set up the fields of the pseudo-header. */
703                                 cksum_vec[0].ptr = pinfo->src.data;
704                                 cksum_vec[0].len = pinfo->src.len;
705                                 cksum_vec[1].ptr = pinfo->dst.data;
706                                 cksum_vec[1].len = pinfo->dst.len;
707                                 cksum_vec[2].ptr = (const guint8 *)&phdr;
708                                 switch (pinfo->src.type) {
709
710                                 case AT_IPv4:
711                                         phdr[0] = g_htonl((IP_PROTO_DCCP<<16) + reported_len);
712                                         cksum_vec[2].len = 4;
713                                         break;
714                                 case AT_IPv6:
715                                         phdr[0] = g_htonl(reported_len);
716                                         phdr[1] = g_htonl(IP_PROTO_DCCP);
717                                         cksum_vec[2].len = 8;
718                                         break;
719
720                                 default:
721                                         /* DCCP runs only atop IPv4 and IPv6.... */
722                                   /*DISSECTOR_ASSERT_NOT_REACHED();*/
723                                         break;
724                                 }
725                                 cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, len);
726                                 cksum_vec[3].len = dccp_csum_coverage(dccph, reported_len);
727                                 computed_cksum = in_cksum(&cksum_vec[0], 4);
728                                 if (computed_cksum == 0) {
729                                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
730                                                                          offset + 6, 2, dccph->checksum,
731                                                                          "0x%04x [correct]", dccph->checksum);
732                                 } else {
733                                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_checksum_bad, tvb, offset + 6, 2, TRUE);;
734                                         PROTO_ITEM_SET_HIDDEN(hidden_item);
735                                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb, offset + 6, 2, dccph->checksum,
736                                                                          "0x%04x [incorrect, should be 0x%04x]", dccph->checksum,
737                                                                          in_cksum_shouldbe(dccph->checksum, computed_cksum));
738                                 }
739                         } else {
740                                 proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
741                                                                  offset + 6, 2, dccph->checksum, "0x%04x", dccph->checksum);
742                         }
743                 } else {
744                         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
745                                                          offset + 6, 2, dccph->checksum, "0x%04x", dccph->checksum);
746                 }
747
748                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_res1, tvb, offset + 8, 1, dccph->reserved1);
749                 PROTO_ITEM_SET_HIDDEN(hidden_item);
750                 proto_tree_add_uint(dccp_tree, hf_dccp_type, tvb, offset + 8, 1, dccph->type);
751                 proto_tree_add_boolean(dccp_tree, hf_dccp_x, tvb, offset + 8, 1, dccph->x);
752                 if(dccph->x) {
753                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_res2, tvb, offset + 9, 1, dccph->reserved2);
754                         PROTO_ITEM_SET_HIDDEN(hidden_item);
755                         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset + 10, 6, dccph->seq);
756                 } else {
757                         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset + 9, 3, dccph->seq);
758
759                 }
760         }
761
762         if(dccph->x)
763                 offset+=16; /* Skip over extended Generic header */
764         else
765                 offset+=12; /* Skip over not extended Generic header */
766
767         /* dissecting type depending additional fields */
768         switch(dccph->type) {
769
770         case 0x0: /* DCCP-Request */
771                 if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
772                         if(tree)
773                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
774                         return;
775                 }
776                 dccph->service_code=tvb_get_ntohl(tvb, offset);
777                 if(tree)
778                         proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4, dccph->service_code);
779                 if (check_col(pinfo->cinfo, COL_INFO))
780                         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)", dccph->service_code);
781
782                 offset+=4; /* Skip over service code */
783                 break;
784
785         case 0x1: /* DCCP-Response */
786                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
787                         if(tree)
788                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
789                         return;
790                 }
791                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
792                 if(tree) {
793                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
794                         PROTO_ITEM_SET_HIDDEN(hidden_item);
795                 }
796                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
797                 dccph->ack<<=32;
798                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
799
800                 if(tree)
801                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
802                 if (check_col(pinfo->cinfo, COL_INFO))
803                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
804
805                 offset+=8; /* Skip over Acknowledgement Number Subheader */
806
807                 if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
808                         if(tree)
809                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
810                         return;
811                 }
812                 dccph->service_code=tvb_get_ntohl(tvb, offset);
813                 if(tree)
814                         proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4, dccph->service_code);
815                 if (check_col(pinfo->cinfo, COL_INFO))
816                         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)", dccph->service_code);
817
818                 offset+=4; /* Skip over service code */
819                 break;
820
821         case 0x2: /* DCCP-Data */
822                 /* nothing to dissect */
823                 break;
824
825         case 0x3: /* DCCP-Ack */
826         case 0x4: /* DCCP-DataAck */
827                 if(dccph->x) {
828                         if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
829                                 if(tree)
830                                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
831                                 return;
832                         }
833                         dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
834                         if(tree) {
835                                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
836                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
837                         }
838                         dccph->ack=tvb_get_ntohs(tvb, offset+2);
839                         dccph->ack<<=32;
840                         dccph->ack+=tvb_get_ntohl(tvb, offset+4);
841                         if(tree)
842                                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
843                         if (check_col(pinfo->cinfo, COL_INFO))
844                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
845
846                         offset+=8; /* Skip over Acknowledgement Number Subheader */
847                 } else {
848                         if(!tvb_bytes_exist(tvb, offset, 4)) { /* at least 4 byte */
849                                 if(tree)
850                                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
851                                 return;
852                         }
853                         dccph->ack_reserved=tvb_get_guint8(tvb, offset);
854                         if(tree) {
855                                 hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 1, dccph->ack_reserved);
856                                 PROTO_ITEM_SET_HIDDEN(hidden_item);
857                         }
858                         dccph->ack=tvb_get_guint8(tvb, offset+1);
859                         dccph->ack<<=16;
860                         dccph->ack+=tvb_get_ntohs(tvb, offset+2);
861                         if(tree)
862                                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 1, 3, dccph->ack);
863                         if (check_col(pinfo->cinfo, COL_INFO))
864                                 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
865
866                         offset+=4; /* Skip over Acknowledgement Number Subheader */
867                 }
868                 break;
869
870         case 0x7: /* DCCP-Reset */
871                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
872                         if(tree)
873                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
874                         return;
875                 }
876                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
877                 if(tree) {
878                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
879                         PROTO_ITEM_SET_HIDDEN(hidden_item);
880                 }
881                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
882                 dccph->ack<<=32;
883                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
884                 if(tree)
885                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
886                 if (check_col(pinfo->cinfo, COL_INFO))
887                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
888
889                 offset+=8; /* Skip over Acknowledgement Number Subheader */
890
891                 dccph->reset_code=tvb_get_guint8(tvb, offset);
892                 dccph->data1=tvb_get_guint8(tvb, offset+1);
893                 dccph->data2=tvb_get_guint8(tvb, offset+2);
894                 dccph->data3=tvb_get_guint8(tvb, offset+3);
895                 if(tree) {
896                         proto_tree_add_uint(dccp_tree, hf_dccp_reset_code, tvb, offset, 1, dccph->reset_code);
897                         proto_tree_add_uint(dccp_tree, hf_dccp_data1, tvb, offset + 1, 1, dccph->data1);
898                         proto_tree_add_uint(dccp_tree, hf_dccp_data2, tvb, offset + 2, 1, dccph->data2);
899                         proto_tree_add_uint(dccp_tree, hf_dccp_data3, tvb, offset + 3, 1, dccph->data3);
900                 }
901                 if (check_col(pinfo->cinfo, COL_INFO))
902                         col_append_fstr(pinfo->cinfo, COL_INFO, " (code=%s)", val_to_str(dccph->reset_code, dccp_reset_code_vals, "Unknown"));
903
904                 offset+=4; /* Skip over Reset Code and data123 */
905                 break;
906
907         case 0x5: /* DCCP-CloseReq */
908         case 0x6: /* DCCP-Close */
909         case 0x8: /* DCCP-Sync */
910         case 0x9: /* DCCP-SyncAck */
911                 if(!tvb_bytes_exist(tvb, offset, 8)) { /* at least 8 byte */
912                         if(tree)
913                                 proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet");
914                         return;
915                 }
916                 dccph->ack_reserved=tvb_get_ntohs(tvb, offset);
917                 if(tree) {
918                         hidden_item = proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2, dccph->ack_reserved);
919                         PROTO_ITEM_SET_HIDDEN(hidden_item);
920                 }
921                 dccph->ack=tvb_get_ntohs(tvb, offset+2);
922                 dccph->ack<<=32;
923                 dccph->ack+=tvb_get_ntohl(tvb, offset+4);
924                 if(tree)
925                         proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, dccph->ack);
926                 if (check_col(pinfo->cinfo, COL_INFO))
927                         col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
928
929                 offset+=8; /* Skip over Acknowledgement Number Subheader */
930                 break;
931
932         default:
933                 if(tree)
934                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "Reserved packet type: unable to dissect further");
935                 return;
936         }
937
938
939         /*  note: data_offset is the offset from the start of the packet's DCCP header to the
940          *  start of its application data area, in 32-bit words.
941          */
942
943         /* it's time to do some checks */
944         advertised_dccp_header_len = dccph->data_offset*4;
945         options_len = advertised_dccp_header_len - offset;
946
947         if ( advertised_dccp_header_len > DCCP_HDR_LEN_MAX ) {
948                 if(tree)
949                         proto_tree_add_text(dccp_tree, tvb, 4, 2,
950                                             "bogus data offset, advertised header length (%d) is larger than max (%d)",
951                                             advertised_dccp_header_len, DCCP_HDR_LEN_MAX);
952                 return;
953         }
954
955         if(tvb_length(tvb) < advertised_dccp_header_len) {
956                 if(tree)
957                         proto_tree_add_text(dccp_tree, tvb, offset, -1, "too short packet: missing %d bytes of DCCP header",
958                                             advertised_dccp_header_len - tvb_reported_length_remaining(tvb, offset));
959                 return;
960         }
961
962         if(options_len > DCCP_OPT_LEN_MAX) {
963                 /* DBG("malformed\n"); */
964                 if(tree) {
965                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
966                         PROTO_ITEM_SET_HIDDEN(hidden_item);
967                 }
968                 THROW(ReportedBoundsError);
969         }
970
971
972         /* Dissecting Options (if here we have at least (advertised_dccp_header_len - offset) bytes of options) */
973         if(advertised_dccp_header_len == offset) {
974                 ; /* ok no options, no need to skip over */
975         } else if (advertised_dccp_header_len < offset) {
976                 if(tree) {
977                         proto_tree_add_text(dccp_tree, tvb, 4, 2,
978                                             "bogus data offset, advertised header length (%d) is shorter than expected",
979                                             advertised_dccp_header_len);
980                         hidden_item = proto_tree_add_boolean(dccp_tree, hf_dccp_malformed, tvb, offset, 0, TRUE);
981                         PROTO_ITEM_SET_HIDDEN(hidden_item);
982                 }
983                 THROW(ReportedBoundsError);
984         } else {
985                 if(dccp_tree) {
986                         dccp_item = proto_tree_add_none_format(dccp_tree, hf_dccp_options, tvb, offset, options_len, "Options: (%u bytes)", options_len);
987                         dccp_options_tree = proto_item_add_subtree(dccp_item, ett_dccp_options);
988                 }
989                 dissect_options(tvb, pinfo, dccp_options_tree, tree, dccph, offset, offset + options_len);
990         }
991
992         offset+=options_len; /* Skip over Options */
993
994         /* Queuing tap data */
995         tap_queue_packet(dccp_tap, pinfo, dccph);
996
997         /* Call sub-dissectors */
998
999         if (!pinfo->in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
1000                 decode_dccp_ports(tvb, offset, pinfo, tree, dccph->sport, dccph->dport);
1001 }
1002
1003
1004 void proto_register_dccp(void)
1005 {
1006         module_t *dccp_module;
1007
1008         static hf_register_info hf[] = {
1009                 { &hf_dccp_srcport,
1010                 { "Source Port",        "dccp.srcport", FT_UINT16, BASE_DEC, NULL, 0x0,
1011                   NULL, HFILL }},
1012
1013                 { &hf_dccp_dstport,
1014                 { "Destination Port",   "dccp.dstport", FT_UINT16, BASE_DEC, NULL, 0x0,
1015                   NULL, HFILL }},
1016
1017                 { &hf_dccp_port,
1018                 { "Source or Destination Port", "dccp.port", FT_UINT16, BASE_DEC,  NULL, 0x0,
1019                   NULL, HFILL }},
1020
1021                 { &hf_dccp_data_offset,
1022                 { "Data Offset",        "dccp.data_offset", FT_UINT8, BASE_DEC, NULL, 0x0,
1023                   NULL, HFILL }},
1024
1025                 { &hf_dccp_ccval,
1026                 { "CCVal",              "dccp.ccval", FT_UINT8, BASE_DEC,  NULL, 0x0,
1027                   NULL, HFILL }},
1028
1029                 { &hf_dccp_cscov,
1030                 { "Checksum Coverage",  "dccp.cscov", FT_UINT8, BASE_DEC,  NULL, 0x0,
1031                   NULL, HFILL }},
1032
1033                 { &hf_dccp_checksum_bad,
1034                 { "Bad Checksum",       "dccp.checksum_bad", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1035                   NULL, HFILL }},
1036
1037                 { &hf_dccp_checksum,
1038                 { "Checksum",           "dccp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
1039                   NULL, HFILL }},
1040
1041                 { &hf_dccp_res1,
1042                 { "Reserved",           "dccp.res1", FT_UINT8, BASE_HEX, NULL, 0x0,
1043                   NULL, HFILL }},
1044
1045                 { &hf_dccp_res2,
1046                 { "Reserved",           "dccp.res2", FT_UINT8, BASE_HEX, NULL, 0x0,
1047                   NULL, HFILL }},
1048
1049                 { &hf_dccp_type,
1050                 { "Type",               "dccp.type", FT_UINT8, BASE_DEC, VALS(dccp_packet_type_vals), 0x0,
1051                   NULL, HFILL }},
1052
1053                 { &hf_dccp_x,
1054                 { "Extended Sequence Numbers", "dccp.x", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1055                   NULL, HFILL }},
1056
1057                 { &hf_dccp_seq,
1058                 { "Sequence Number",    "dccp.seq", FT_UINT64, BASE_DEC, NULL, 0x0,
1059                   NULL, HFILL }},
1060
1061                 { &hf_dccp_ack_res,
1062                 { "Reserved",           "dccp.ack_res", FT_UINT16, BASE_HEX, NULL, 0x0,
1063                   NULL, HFILL }},
1064
1065                 { &hf_dccp_ack,
1066                 { "Acknowledgement Number", "dccp.ack", FT_UINT64, BASE_DEC, NULL, 0x0,
1067                   NULL, HFILL }},
1068
1069                 { &hf_dccp_service_code,
1070                 { "Service Code", "dccp.service_code", FT_UINT32, BASE_DEC, NULL, 0x0,
1071                   NULL, HFILL }},
1072
1073                 { &hf_dccp_reset_code,
1074                 { "Reset Code", "dccp.reset_code", FT_UINT8, BASE_DEC, VALS(dccp_reset_code_vals), 0x0,
1075                   NULL, HFILL }},
1076
1077                 { &hf_dccp_data1,
1078                 { "Data 1",     "dccp.data1", FT_UINT8, BASE_DEC, NULL, 0x0,
1079                   NULL, HFILL }},
1080
1081                 { &hf_dccp_data2,
1082                 { "Data 2",     "dccp.data2", FT_UINT8, BASE_DEC, NULL, 0x0,
1083                   NULL, HFILL }},
1084
1085                 { &hf_dccp_data3,
1086                 { "Data 3",     "dccp.data3", FT_UINT8, BASE_DEC, NULL, 0x0,
1087                   NULL, HFILL }},
1088
1089                 { &hf_dccp_option_type,
1090                 { "Option Type",     "dccp.option_type", FT_UINT8, BASE_DEC, NULL, 0x0,
1091                   NULL, HFILL }},
1092
1093                 { &hf_dccp_feature_number,
1094                 { "Feature Number",   "dccp.feature_number", FT_UINT8, BASE_DEC, NULL, 0x0,
1095                   NULL, HFILL }},
1096
1097                 { &hf_dccp_ndp_count,
1098                 { "NDP Count",   "dccp.ndp_count", FT_UINT64, BASE_DEC, NULL, 0x0,
1099                   NULL, HFILL }},
1100
1101                 { &hf_dccp_timestamp,
1102                 { "Timestamp",   "dccp.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
1103                   NULL, HFILL }},
1104
1105                 { &hf_dccp_timestamp_echo,
1106                 { "Timestamp Echo",   "dccp.timestamp_echo", FT_UINT32, BASE_DEC, NULL, 0x0,
1107                   NULL, HFILL }},
1108
1109                 { &hf_dccp_elapsed_time,
1110                 { "Elapsed Time",   "dccp.elapsed_time", FT_UINT32, BASE_DEC, NULL, 0x0,
1111                   NULL, HFILL }},
1112
1113                 { &hf_dccp_data_checksum,
1114                 { "Data Checksum",  "dccp.checksum_data", FT_UINT32, BASE_HEX, NULL, 0x0,
1115                   NULL, HFILL }},
1116
1117                 { &hf_dccp_malformed,
1118                 { "Malformed", "dccp.malformed", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1119                   NULL, HFILL }},
1120
1121                 { &hf_dccp_options,
1122                 { "Options", "dccp.options", FT_NONE, BASE_NONE, NULL, 0x0,
1123                   "DCCP Options fields", HFILL }}
1124
1125         };
1126
1127         static gint *ett[] = {
1128                 &ett_dccp,
1129                 &ett_dccp_options
1130         };
1131
1132         proto_dccp = proto_register_protocol("Datagram Congestion Control Protocol", "DCCP", "dccp");
1133         proto_register_field_array(proto_dccp, hf, array_length(hf));
1134         proto_register_subtree_array(ett, array_length(ett));
1135
1136         /* subdissectors */
1137         dccp_subdissector_table = register_dissector_table("dccp.port", "DCCP port", FT_UINT16, BASE_DEC);
1138         register_heur_dissector_list("dccp", &heur_subdissector_list);
1139
1140         /* reg preferences */
1141         dccp_module = prefs_register_protocol(proto_dccp, NULL);
1142         prefs_register_bool_preference(dccp_module, "summary_in_tree",
1143                                        "Show DCCP summary in protocol tree",
1144                                        "Whether the DCCP summary line should be shown in the protocol tree",
1145                                        &dccp_summary_in_tree);
1146
1147         prefs_register_bool_preference(dccp_module, "try_heuristic_first",
1148                                        "Try heuristic sub-dissectors first",
1149                                        "Try to decode a packet using an heuristic sub-dissector before using a sub-dissector "
1150                                        "registered to a specific port",
1151                                        &try_heuristic_first);
1152
1153         prefs_register_bool_preference(dccp_module, "check_checksum",
1154                                        "Check the validity of the DCCP checksum when possible",
1155                                        "Whether to check the validity of the DCCP checksum",
1156                                        &dccp_check_checksum);
1157 }
1158
1159 void proto_reg_handoff_dccp(void)
1160 {
1161         dissector_handle_t dccp_handle;
1162
1163         dccp_handle = create_dissector_handle(dissect_dccp, proto_dccp);
1164         dissector_add("ip.proto", IP_PROTO_DCCP, dccp_handle);
1165         data_handle = find_dissector("data");
1166         dccp_tap = register_tap("dccp");
1167 }