Allow try_conversation_dissector() to pass data to subdissectors.
[metze/wireshark/wip.git] / epan / dissectors / packet-dccp.c
1 /* packet-dccp.c
2  * Routines for Datagram Congestion Control Protocol, "DCCP" dissection:
3  * it should conform to RFC 4340
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30  */
31
32 /* NOTES:
33  *
34  * Nov 13, 2006: makes checksum computation dependent
35  * upon the header CsCov field (cf. RFC 4340, 5.1)
36  * (Gerrit Renker)
37  *
38  * Nov 13, 2006: removes the case where checksums are zero
39  * (unlike UDP/packet-udp, from which the code stems,
40  * zero checksums are illegal in DCCP (as in TCP))
41  * (Gerrit Renker)
42  *
43  * Jan 29, 2007: updates the offsets of the timestamps to be
44  * compliant to (cf. RFC 4342, sec. 13).
45  * (Gerrit Renker)
46  *
47  * Mar 11, 2012: add support for RFC 5596 (DCCP-Listen Packet)
48  * (Francesco Fondelli)
49  */
50
51 #include "config.h"
52
53 #include <glib.h>
54
55 #include <epan/packet.h>
56 #include <epan/addr_resolv.h>
57 #include <epan/ipproto.h>
58 #include <epan/in_cksum.h>
59 #include <epan/prefs.h>
60 #include <epan/expert.h>
61 #include <epan/wmem/wmem.h>
62 #include "packet-ip.h"
63 #include <epan/conversation.h>
64 #include <epan/tap.h>
65 #include "packet-dccp.h"
66
67 /*
68  * Some definitions and the dissect_options() logic have been taken
69  * from Arnaldo Carvalho de Melo's DCCP implementation, thanks!
70  */
71 #define DCCP_GEN_HDR_LEN_NO_X 12      /* generic header length, without extended sequence numbers */
72 #define DCCP_GEN_HDR_LEN_X    16      /* generic header length, with extended sequence numbers */
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
76                                        * header length
77                                        */
78 #define DCCP_OPT_LEN_MAX 1008
79 #define DCCP_HDR_LEN_MAX (DCCP_HDR_LEN + DCCP_HDR_PKT_TYPES_LEN_MAX + \
80                           DCCP_OPT_LEN_MAX)
81
82 void proto_register_dccp(void);
83 void proto_reg_handoff_dccp(void);
84
85 /*
86  * FF: please keep this list in sync with
87  * http://www.iana.org/assignments/dccp-parameters/dccp-parameters.xml
88  * Registry Name: 'Packet Types'
89  */
90 static const value_string dccp_packet_type_vals[] = {
91     {0x0, "Request" },
92     {0x1, "Response"},
93     {0x2, "Data"    },
94     {0x3, "Ack"     },
95     {0x4, "DataAck" },
96     {0x5, "CloseReq"},
97     {0x6, "Close"   },
98     {0x7, "Reset"   },
99     {0x8, "Sync"    },
100     {0x9, "SyncAck" },
101     {0xA, "Listen"  },
102     {0xB, "Reserved"},
103     {0xC, "Reserved"},
104     {0xD, "Reserved"},
105     {0xE, "Reserved"},
106     {0xF, "Reserved"},
107     {0,   NULL      }
108 };
109
110 static const value_string dccp_reset_code_vals[] = {
111     {0x00, "Unspecified"       },
112     {0x01, "Closed"            },
113     {0x02, "Aborted"           },
114     {0x03, "No Connection"     },
115     {0x04, "Packet Error"      },
116     {0x05, "Option Error"      },
117     {0x06, "Mandatory Error"   },
118     {0x07, "Connection Refused"},
119     {0x08, "Bad Service Code"  },
120     {0x09, "Too Busy"          },
121     {0x0A, "Bad Init Cookie"   },
122     {0x0B, "Aggression Penalty"},
123     {0x0C, "Reserved"          },
124     {0,    NULL                }
125 };
126
127 static const value_string dccp_feature_options_vals[] = {
128     {0x20, "Change L" },
129     {0x21, "Confirm L"},
130     {0x22, "Change R" },
131     {0x23, "Confirm R"},
132     {0,    NULL       }
133 };
134
135 static const value_string dccp_feature_numbers_vals[] = {
136     {0x01, "CCID"                     },
137     {0x02, "Allow Short Seqnums"      },
138     {0x03, "Sequence Window"          },
139     {0x04, "ECN Incapable"            },
140     {0x05, "Ack Ratio"                },
141     {0x06, "Send Ack Vector"          },
142     {0x07, "Send NDP Count"           },
143     {0x08, "Minimum Checksum Coverage"},
144     {0x09, "Check Data Checksum"      },
145     {0xC0, "Send Loss Event Rate"     }, /* CCID3, RFC 4342, 8.5 */
146     {0,    NULL                       }
147 };
148
149 static int proto_dccp = -1;
150 static int dccp_tap = -1;
151
152 static int hf_dccp_srcport = -1;
153 static int hf_dccp_dstport = -1;
154 static int hf_dccp_port = -1;
155 static int hf_dccp_data_offset = -1;
156 static int hf_dccp_ccval = -1;
157 static int hf_dccp_cscov = -1;
158 static int hf_dccp_checksum = -1;
159 static int hf_dccp_checksum_bad = -1;
160 static int hf_dccp_res1 = -1;
161 static int hf_dccp_type = -1;
162 static int hf_dccp_x = -1;
163 static int hf_dccp_res2 = -1;
164 static int hf_dccp_seq = -1;
165
166 static int hf_dccp_ack_res = -1;
167 static int hf_dccp_ack = -1;
168
169 static int hf_dccp_service_code = -1;
170 static int hf_dccp_reset_code = -1;
171 static int hf_dccp_data1 = -1;
172 static int hf_dccp_data2 = -1;
173 static int hf_dccp_data3 = -1;
174
175 static int hf_dccp_options = -1;
176 static int hf_dccp_option_type = -1;
177 static int hf_dccp_feature_number = -1;
178 /* static int hf_dccp_ndp_count = -1; */
179 static int hf_dccp_timestamp = -1;
180 static int hf_dccp_timestamp_echo = -1;
181 static int hf_dccp_elapsed_time = -1;
182 static int hf_dccp_data_checksum = -1;
183
184 static gint ett_dccp = -1;
185 static gint ett_dccp_options = -1;
186
187 static expert_field ei_dccp_option_len_bad = EI_INIT;
188 static expert_field ei_dccp_advertised_header_length_bad = EI_INIT;
189 static expert_field ei_dccp_packet_type_reserved = EI_INIT;
190
191 static dissector_table_t dccp_subdissector_table;
192 static heur_dissector_list_t heur_subdissector_list;
193 static dissector_handle_t data_handle;
194
195 /* preferences */
196 static gboolean dccp_summary_in_tree = TRUE;
197 static gboolean try_heuristic_first  = FALSE;
198 static gboolean dccp_check_checksum  = TRUE;
199
200 static void
201 decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
202                   proto_tree *tree, int sport, int dport)
203 {
204     tvbuff_t *next_tvb;
205     int       low_port, high_port;
206
207     next_tvb = tvb_new_subset_remaining(tvb, offset);
208
209     /*
210      * determine if this packet is part of a conversation and call dissector
211      * for the conversation if available
212      */
213     if (try_conversation_dissector(&pinfo->src, &pinfo->dst, PT_DCCP, sport,
214                                    dport, next_tvb, pinfo, tree, NULL)) {
215         return;
216     }
217
218     if (try_heuristic_first) {
219         /* do lookup with the heuristic subdissector table */
220         if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo,
221                                     tree, NULL)) {
222             return;
223         }
224     }
225
226     /*
227      * Do lookups with the subdissector table.
228      * We try the port number with the lower value first, followed by the
229      * port number with the higher value.  This means that, for packets
230      * where a dissector is registered for *both* port numbers:
231      *
232      * 1) we pick the same dissector for traffic going in both directions;
233      *
234      * 2) we prefer the port number that's more likely to be the right
235      * one (as that prefers well-known ports to reserved ports);
236      *
237      * although there is, of course, no guarantee that any such strategy
238      * will always pick the right port number.
239      * XXX - we ignore port numbers of 0, as some dissectors use a port
240      * number of 0 to disable the port.
241      */
242     if (sport > dport) {
243         low_port  = dport;
244         high_port = sport;
245     } else {
246         low_port  = sport;
247         high_port = dport;
248     }
249
250     if (low_port != 0 &&
251         dissector_try_uint(dccp_subdissector_table, low_port,
252                            next_tvb, pinfo, tree)) {
253         return;
254     }
255
256     if (high_port != 0 &&
257         dissector_try_uint(dccp_subdissector_table, high_port,
258                            next_tvb, pinfo, tree)) {
259         return;
260     }
261
262     if (!try_heuristic_first) {
263         /* do lookup with the heuristic subdissector table */
264         if (dissector_try_heuristic(heur_subdissector_list, next_tvb,
265                                     pinfo, tree, NULL)) {
266             return;
267         }
268     }
269
270     /* Oh, well, we don't know this; dissect it as data. */
271     call_dissector(data_handle, next_tvb, pinfo, tree);
272 }
273
274 /*
275  * decode a variable-length number of nbytes starting at offset.  Based on
276  * a concept by Arnaldo de Melo
277  */
278 static guint64
279 tvb_get_ntoh_var(tvbuff_t *tvb, gint offset, guint nbytes)
280 {
281     const guint8 *ptr;
282     guint64       value = 0;
283
284     ptr = tvb_get_ptr(tvb, offset, nbytes);
285     if (nbytes > 5)
286         value += ((guint64) * ptr++) << 40;
287     if (nbytes > 4)
288         value += ((guint64) * ptr++) << 32;
289     if (nbytes > 3)
290         value += ((guint64) * ptr++) << 24;
291     if (nbytes > 2)
292         value += ((guint64) * ptr++) << 16;
293     if (nbytes > 1)
294         value += ((guint64) * ptr++) << 8;
295     if (nbytes > 0)
296         value += *ptr;
297
298     return value;
299 }
300
301 static void
302 dissect_feature_options(proto_tree *dccp_options_tree, tvbuff_t *tvb,
303                         int offset, guint8 option_len,
304                         guint8 option_type)
305 {
306     guint8      feature_number = tvb_get_guint8(tvb, offset + 2);
307     proto_item *dccp_item, *hidden_item;
308     int         i;
309
310     hidden_item =
311         proto_tree_add_uint(dccp_options_tree, hf_dccp_feature_number, tvb,
312                             offset + 2, 1, feature_number);
313     PROTO_ITEM_SET_HIDDEN(hidden_item);
314
315     dccp_item =
316         proto_tree_add_text(dccp_options_tree, tvb, offset, option_len, "%s(",
317                             val_to_str_const(option_type,
318                                              dccp_feature_options_vals,
319                                              "Unknown Type"));
320
321     /*
322      * decode the feature according to whether it is server-priority (list)
323      * or NN (single number)
324      */
325     switch (feature_number) {
326
327     /* Server Priority features (RFC 4340, 6.3.1) */
328
329     case 1:       /* Congestion Control ID (CCID); fall through    */
330     case 2:       /* Allow Short Seqnums; fall through             */
331     case 4:       /* ECN Incapable; fall through                   */
332     case 6:       /* Send Ack Vector; fall through                 */
333     case 7:       /* Send NDP Count; fall through                  */
334     case 8:       /* Minimum Checksum Coverage; fall through       */
335     case 9:       /* Check Data Checksum; fall through             */
336     case 192:     /* Send Loss Event Rate, RFC 4342, section 8.4   */
337         proto_item_append_text(dccp_item, "%s",
338                                val_to_str_const(feature_number,
339                                                 dccp_feature_numbers_vals,
340                                                 "Unknown Type"));
341         for (i = 0; i < option_len - 3; i++)
342             proto_item_append_text(dccp_item, "%s %d", i ? "," : "",
343                                    tvb_get_guint8(tvb,
344                                                   offset + 3 + i));
345         break;
346
347     /* Non-negotiable features (RFC 4340, 6.3.2) */
348
349     case 3:       /* Sequence Window; fall through                 */
350     case 5:       /* Ack Ratio                                     */
351         proto_item_append_text(dccp_item, "%s",
352                                val_to_str_const(feature_number,
353                                                 dccp_feature_numbers_vals,
354                                                 "Unknown Type"));
355
356         if (option_len > 3) /* could be empty Confirm */
357             proto_item_append_text(dccp_item, " %" G_GINT64_MODIFIER "u",
358                                    tvb_get_ntoh_var(tvb, offset + 3,
359                                                     option_len - 3));
360         break;
361
362     /* Reserved, specific, or unknown features */
363     default:
364         if (feature_number == 0 ||
365             (feature_number >= 10 && feature_number <= 127))
366             proto_item_append_text(dccp_item, "Reserved feature number %d",
367                                    feature_number);
368         else if (feature_number >= 193)
369             proto_item_append_text(dccp_item, "CCID-specific feature number %d",
370                                    feature_number);
371         else
372             proto_item_append_text(dccp_item, "Unknown feature number %d",
373                                    feature_number);
374         break;
375     }
376     proto_item_append_text(dccp_item, ")");
377 }
378
379 /*
380  * This function dissects DCCP options
381  */
382 static void
383 dissect_options(tvbuff_t *tvb, packet_info *pinfo _U_,
384                 proto_tree *dccp_options_tree, proto_tree *tree _U_,
385                 e_dccphdr *dccph _U_,
386                 int offset_start,
387                 int offset_end)
388 {
389     /*
390      * if here I'm sure there is at least offset_end - offset_start bytes
391      * in tvb and it should be options
392      */
393     int         offset      = offset_start;
394     guint8      option_type = 0;
395     guint8      option_len  = 0;
396     int         i;
397     guint32     p;
398     proto_item *dccp_item   = NULL;
399     proto_item *option_item;
400
401     while (offset < offset_end) {
402         /* first byte is the option type */
403         option_type = tvb_get_guint8(tvb, offset);
404         option_item =
405             proto_tree_add_uint(dccp_options_tree, hf_dccp_option_type, tvb,
406                                 offset,
407                                 1,
408                                 option_type);
409         PROTO_ITEM_SET_HIDDEN(option_item);
410
411         if (option_type >= 32) { /* variable length options */
412             option_len = tvb_get_guint8(tvb, offset + 1);
413
414             if (option_len < 2) {
415                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
416                     "Option length incorrect, must be >= 2");
417                 return;
418             }
419         } else { /* 1byte options */
420             option_len = 1;
421         }
422
423         switch (option_type) {
424         case 0:
425             proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
426                                 "Padding");
427             break;
428         case 1:
429             proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
430                                 "Mandatory");
431             break;
432         case 2:
433             proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
434                                 "Slow Receiver");
435             break;
436         case 32:
437         case 33:
438         case 34:
439         case 35:
440             dissect_feature_options(dccp_options_tree, tvb, offset, option_len,
441                                     option_type);
442             break;
443         case 36:
444             dccp_item =
445                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
446                                     "Init Cookie(");
447             for (i = 0; i < option_len - 2; i++) {
448                 if (i == 0)
449                     proto_item_append_text(dccp_item, "%02x",
450                                            tvb_get_guint8(tvb, offset + 2 + i));
451                 else
452                     proto_item_append_text(dccp_item, " %02x",
453                                            tvb_get_guint8(tvb, offset + 2 + i));
454             }
455             proto_item_append_text(dccp_item, ")");
456             break;
457         case 37:
458             if (option_len > 8)
459                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
460                                         "NDP Count too long (max 6 bytes)");
461             else
462                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
463                                     "NDP Count: %" G_GINT64_MODIFIER "u",
464                                     tvb_get_ntoh_var(tvb, offset + 2,
465                                                      option_len - 2));
466             break;
467         case 38:
468             dccp_item =
469                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
470                                     "Ack Vector [Nonce 0]:");
471             for (i = 0; i < option_len - 2; i++)
472                 proto_item_append_text(dccp_item, " %02x",
473                                        tvb_get_guint8(tvb, offset + 2 + i));
474             break;
475         case 39:
476             dccp_item =
477                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
478                                     "Ack Vector [Nonce 1]:");
479             for (i = 0; i < option_len - 2; i++)
480                 proto_item_append_text(dccp_item, " %02x",
481                                        tvb_get_guint8(tvb, offset + 2 + i));
482             proto_item_append_text(dccp_item, ")");
483             break;
484         case 40:
485             dccp_item =
486                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
487                                     "Data Dropped:");
488             for (i = 0; i < option_len - 2; i++)
489                 proto_item_append_text(dccp_item, " %02x",
490                                        tvb_get_guint8(tvb, offset + 2 + i));
491             break;
492         case 41:
493             if (option_len == 6)
494                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp, tvb,
495                                     offset + 2, 4,
496                                     tvb_get_ntohl(tvb, offset + 2));
497             else
498                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
499                                         "Timestamp too long [%u != 6]", option_len);
500             break;
501         case 42:
502             if (option_len == 6)
503                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo,
504                                     tvb, offset + 2, 4,
505                                     tvb_get_ntohl(tvb, offset + 2));
506             else if (option_len == 8) {
507                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo,
508                                     tvb, offset + 2, 4,
509                                     tvb_get_ntohl(tvb, offset + 2));
510                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time,
511                                     tvb, offset + 6, 2,
512                                     tvb_get_ntohs(tvb, offset + 6));
513             } else if (option_len == 10) {
514                 proto_tree_add_uint(dccp_options_tree, hf_dccp_timestamp_echo,
515                                     tvb, offset + 2, 4,
516                                     tvb_get_ntohl(tvb, offset + 2));
517                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time,
518                                     tvb, offset + 6, 4,
519                                     tvb_get_ntohl(tvb, offset + 6));
520             } else
521                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
522                                         "Wrong Timestamp Echo length");
523             break;
524         case 43:
525             if (option_len == 4)
526                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time,
527                                     tvb, offset + 2, 2,
528                                     tvb_get_ntohs(tvb, offset + 2));
529             else if (option_len == 6)
530                 proto_tree_add_uint(dccp_options_tree, hf_dccp_elapsed_time,
531                                     tvb, offset + 2, 4,
532                                     tvb_get_ntohl(tvb, offset + 2));
533             else
534                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
535                                         "Wrong Elapsed Time length");
536             break;
537         case 44:
538             if (option_len == 6) {
539                 proto_tree_add_uint(dccp_options_tree, hf_dccp_data_checksum,
540                                     tvb, offset + 2, 4,
541                                     tvb_get_ntohl(tvb, offset + 2));
542             } else
543                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
544                                         "Wrong Data checksum length");
545             break;
546         case 192: /* RFC 4342, 8.5 */
547             if (option_len == 6) {
548                 p = tvb_get_ntohl(tvb, offset + 2);
549                 /*
550                  * According to the comment in section 8.5 of RFC 4342,
551                  * 0xffffffff can mean zero
552                  */
553                 if (p == 0xFFFFFFFF)
554                     proto_tree_add_text(dccp_options_tree, tvb, offset,
555                                         option_len,
556                                         "CCID3 Loss Event Rate: 0 (or max)");
557                 else
558                     proto_tree_add_text(dccp_options_tree, tvb, offset,
559                                         option_len, "CCID3 Loss Event Rate: %u",
560                                         p);
561             } else
562                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
563                                         "Wrong CCID3 Loss Event Rate length");
564             break;
565         case 193: /* RFC 4342, 8.6 */
566             proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
567                                 "CCID3 Loss Intervals");
568             /*
569              * FIXME: not implemented and apparently not used by any
570              * implementation so far
571              */
572             break;
573         case 194: /* RFC 4342, 8.3 */
574             if (option_len == 6)
575                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
576                                     "CCID3 Receive Rate: %u bytes/sec",
577                                     tvb_get_ntohl(tvb, offset + 2));
578             else
579                 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
580                                         "Wrong CCID3 Receive Rate length");
581             break;
582         default:
583             if (((option_type >= 45) && (option_type <= 127)) ||
584                 ((option_type >= 3) && (option_type <= 31))) {
585                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
586                                     "Reserved");
587                 break;
588             }
589
590             if (option_type >= 128) {
591                 proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
592                                     "CCID option %d",
593                                     option_type);
594                 break;
595             }
596
597             /* if here we don't know this option */
598             proto_tree_add_text(dccp_options_tree, tvb, offset, option_len,
599                                 "Unknown");
600             break;
601         } /* end switch() */
602         offset += option_len; /* move offset past the dissected option */
603     } /* end while() */
604 }
605
606 /*
607  * compute DCCP checksum coverage according to RFC 4340, section 9
608 */
609 static inline guint
610 dccp_csum_coverage(const e_dccphdr *dccph, guint len)
611 {
612     guint cov;
613
614     if (dccph->cscov == 0)
615         return len;
616
617     cov = (dccph->data_offset + dccph->cscov - 1) * (guint)sizeof (guint32);
618     return (cov > len) ? len : cov;
619 }
620
621 static int
622 dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
623 {
624     proto_tree *dccp_tree;
625     proto_tree *dccp_options_tree = NULL;
626     proto_item *dccp_item         = NULL;
627     proto_item *hidden_item, *offset_item;
628
629     vec_t      cksum_vec[4];
630     guint32    phdr[2];
631     guint16    computed_cksum;
632     guint      offset                     = 0;
633     guint      len                        = 0;
634     guint      reported_len               = 0;
635     guint      advertised_dccp_header_len = 0;
636     guint      options_len                = 0;
637     e_dccphdr *dccph;
638
639     dccph = wmem_new0(wmem_packet_scope(), e_dccphdr);
640
641     SET_ADDRESS(&dccph->ip_src, pinfo->src.type, pinfo->src.len,
642                 pinfo->src.data);
643     SET_ADDRESS(&dccph->ip_dst, pinfo->dst.type, pinfo->dst.len,
644                 pinfo->dst.data);
645
646     col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
647     col_clear(pinfo->cinfo, COL_INFO);
648
649     dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1, ENC_NA);
650     dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
651
652     /* Extract generic header */
653     dccph->sport = tvb_get_ntohs(tvb, offset);
654     proto_tree_add_uint_format_value(dccp_tree, hf_dccp_srcport, tvb,
655                                      offset, 2, dccph->sport,
656                                      "%s (%u)",
657                                      get_dccp_port(dccph->sport),
658                                      dccph->sport);
659     if (dccp_summary_in_tree) {
660         proto_item_append_text(dccp_item, ", Src Port: %s (%u)",
661                                get_dccp_port(dccph->sport), dccph->sport);
662     }
663     col_add_fstr(pinfo->cinfo, COL_INFO,
664                  "%s ", get_dccp_port(dccph->sport));
665     hidden_item =
666         proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2,
667                             dccph->sport);
668     PROTO_ITEM_SET_HIDDEN(hidden_item);
669     offset += 2;
670
671     dccph->dport = tvb_get_ntohs(tvb, offset);
672     proto_tree_add_uint_format_value(dccp_tree, hf_dccp_dstport, tvb,
673                                      offset, 2, dccph->dport,
674                                      "%s (%u)",
675                                      get_dccp_port(dccph->dport),
676                                      dccph->dport);
677     if (dccp_summary_in_tree) {
678         proto_item_append_text(dccp_item, ", Dst Port: %s (%u)",
679                                get_dccp_port(dccph->dport), dccph->dport);
680     }
681     col_append_fstr(pinfo->cinfo, COL_INFO, " > %s",
682                     get_dccp_port(dccph->dport));
683     hidden_item =
684         proto_tree_add_uint(dccp_tree, hf_dccp_port, tvb, offset, 2,
685                             dccph->dport);
686     PROTO_ITEM_SET_HIDDEN(hidden_item);
687     offset += 2;
688
689     /*
690      * update pinfo structure. I guess I have to do it, because this
691      * is a transport protocol dissector.
692      */
693     pinfo->ptype = PT_DCCP;
694     pinfo->srcport = dccph->sport;
695     pinfo->destport = dccph->dport;
696
697     dccph->data_offset = tvb_get_guint8(tvb, offset);
698     advertised_dccp_header_len = dccph->data_offset * 4;
699     offset_item = proto_tree_add_uint(dccp_tree, hf_dccp_data_offset, tvb, offset, 1,
700                                       dccph->data_offset);
701     offset += 1;
702
703     dccph->cscov = tvb_get_guint8(tvb, offset) & 0x0F;
704     dccph->ccval = tvb_get_guint8(tvb, offset) & 0xF0;
705     dccph->ccval >>= 4;
706     proto_tree_add_uint(dccp_tree, hf_dccp_ccval, tvb, offset, 1,
707                         dccph->ccval);
708     proto_tree_add_uint(dccp_tree, hf_dccp_cscov, tvb, offset, 1,
709                         dccph->cscov);
710     offset += 1;
711
712     dccph->checksum = tvb_get_ntohs(tvb, offset);
713
714     /*
715      * checksum analysis taken from packet-udp (difference: mandatory
716      * checksums in DCCP)
717      */
718     reported_len = tvb_reported_length(tvb);
719     len = tvb_length(tvb);
720
721     if (!pinfo->fragmented && len >= reported_len) {
722         /* The packet isn't part of a fragmented datagram and isn't
723             * truncated, so we can checksum it.
724             * XXX - make a bigger scatter-gather list once we do fragment
725             * reassembly? */
726         if (dccp_check_checksum) {
727             /* Set up the fields of the pseudo-header. */
728             cksum_vec[0].ptr = (const guint8 *)pinfo->src.data;
729             cksum_vec[0].len = pinfo->src.len;
730             cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data;
731             cksum_vec[1].len = pinfo->dst.len;
732             cksum_vec[2].ptr = (const guint8 *) &phdr;
733             switch (pinfo->src.type) {
734             case AT_IPv4:
735                 phdr[0] = g_htonl((IP_PROTO_DCCP << 16) + reported_len);
736                 cksum_vec[2].len = 4;
737                 break;
738             case AT_IPv6:
739                 phdr[0] = g_htonl(reported_len);
740                 phdr[1] = g_htonl(IP_PROTO_DCCP);
741                 cksum_vec[2].len = 8;
742                 break;
743
744             default:
745                 /* DCCP runs only atop IPv4 and IPv6... */
746                 break;
747             }
748             cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, len);
749             cksum_vec[3].len = dccp_csum_coverage(dccph, reported_len);
750             computed_cksum = in_cksum(&cksum_vec[0], 4);
751             if (computed_cksum == 0) {
752                 proto_tree_add_uint_format_value(dccp_tree,
753                                                  hf_dccp_checksum, tvb,
754                                                  offset, 2,
755                                                  dccph->checksum,
756                                                  "0x%04x [correct]",
757                                                  dccph->checksum);
758             } else {
759                 hidden_item =
760                     proto_tree_add_boolean(dccp_tree, hf_dccp_checksum_bad,
761                                            tvb, offset, 2, TRUE);
762                 PROTO_ITEM_SET_HIDDEN(hidden_item);
763                 proto_tree_add_uint_format_value(
764                     dccp_tree, hf_dccp_checksum, tvb, offset, 2,
765                     dccph->checksum,
766                     "0x%04x [incorrect, should be 0x%04x]",
767                     dccph->checksum,
768                     in_cksum_shouldbe(dccph->checksum, computed_cksum));
769             }
770         } else {
771             proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum,
772                                              tvb,
773                                              offset, 2, dccph->checksum,
774                                              "0x%04x", dccph->checksum);
775         }
776     } else {
777         proto_tree_add_uint_format_value(dccp_tree, hf_dccp_checksum, tvb,
778                                          offset, 2, dccph->checksum,
779                                          "0x%04x", dccph->checksum);
780     }
781     offset += 2;
782
783     dccph->reserved1 = tvb_get_guint8(tvb, offset) & 0xE0;
784     dccph->reserved1 >>= 5;
785     hidden_item =
786         proto_tree_add_uint(dccp_tree, hf_dccp_res1, tvb, offset, 1,
787                             dccph->reserved1);
788     PROTO_ITEM_SET_HIDDEN(hidden_item);
789
790     dccph->type = tvb_get_guint8(tvb, offset) & 0x1E;
791     dccph->type >>= 1;
792     proto_tree_add_uint(dccp_tree, hf_dccp_type, tvb, offset, 1,
793                         dccph->type);
794     if (dccp_summary_in_tree) {
795         proto_item_append_text(dccp_item, " [%s]",
796                                val_to_str_const(dccph->type, dccp_packet_type_vals,
797                                                 "Unknown Type"));
798     }
799     col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]",
800                     val_to_str_const(dccph->type, dccp_packet_type_vals,
801                                      "Unknown Type"));
802
803     dccph->x = tvb_get_guint8(tvb, offset) & 0x01;
804     proto_tree_add_boolean(dccp_tree, hf_dccp_x, tvb, offset, 1,
805                            dccph->x);
806     offset += 1;
807
808     if (dccph->x) {
809         if (advertised_dccp_header_len < DCCP_GEN_HDR_LEN_X) {
810             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
811                 "Advertised header length (%u) is smaller than the minimum (%u)",
812                 advertised_dccp_header_len, DCCP_GEN_HDR_LEN_X);
813             return tvb_length(tvb);
814         }
815         dccph->reserved2 = tvb_get_guint8(tvb, offset);
816         hidden_item =
817             proto_tree_add_uint(dccp_tree, hf_dccp_res2, tvb, offset, 1,
818                                 dccph->reserved2);
819         PROTO_ITEM_SET_HIDDEN(hidden_item);
820         offset += 1;
821
822         dccph->seq = tvb_get_ntoh48(tvb, offset);
823         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset, 6,
824                               dccph->seq);
825         offset += 6;
826     } else {
827         if (advertised_dccp_header_len < DCCP_GEN_HDR_LEN_NO_X) {
828             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
829                 "Advertised header length (%u) is smaller than the minimum (%u)",
830                 advertised_dccp_header_len, DCCP_GEN_HDR_LEN_NO_X);
831             return tvb_length(tvb);
832         }
833         dccph->seq = tvb_get_ntoh24(tvb, offset);
834         proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset, 3,
835                               dccph->seq);
836         offset += 3;
837     }
838     if (dccp_summary_in_tree) {
839         proto_item_append_text(dccp_item, " Seq=%" G_GINT64_MODIFIER "u",
840                                dccph->seq);
841     }
842     col_append_fstr(pinfo->cinfo, COL_INFO,
843                     " Seq=%" G_GINT64_MODIFIER "u",
844                     dccph->seq);
845
846     /* dissecting type dependant additional fields */
847     switch (dccph->type) {
848     case 0x0: /* DCCP-Request */
849     case 0xA: /* DCCP-Listen */
850         if (advertised_dccp_header_len < offset + 4) {
851             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
852                 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
853                 advertised_dccp_header_len, offset + 4,
854                 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
855             return tvb_length(tvb);
856         }
857         dccph->service_code = tvb_get_ntohl(tvb, offset);
858         if (tree)
859             proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4,
860                                 dccph->service_code);
861         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)",
862                         dccph->service_code);
863         offset += 4; /* move offset past the service code */
864         break;
865     case 0x1: /* DCCP-Response */
866         if (advertised_dccp_header_len < offset + 12) {
867             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
868                 "Advertised header length (%u) is smaller than the minimum (%u) for Response",
869                 advertised_dccp_header_len, offset + 12);
870             return tvb_length(tvb);
871         }
872         dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
873         if (tree) {
874             hidden_item =
875                 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
876                                     dccph->ack_reserved);
877             PROTO_ITEM_SET_HIDDEN(hidden_item);
878         }
879         dccph->ack = tvb_get_ntohs(tvb, offset + 2);
880         dccph->ack <<= 32;
881         dccph->ack += tvb_get_ntohl(tvb, offset + 4);
882
883         if (tree)
884             proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6,
885                                   dccph->ack);
886         col_append_fstr(pinfo->cinfo, COL_INFO,
887                         " (Ack=%" G_GINT64_MODIFIER "u)",
888                         dccph->ack);
889         offset += 8; /* move offset past the Acknowledgement Number Subheader */
890
891         dccph->service_code = tvb_get_ntohl(tvb, offset);
892         if (tree)
893             proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4,
894                                 dccph->service_code);
895         col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%u)",
896                         dccph->service_code);
897
898         offset += 4; /* move offset past the service code */
899         break;
900     case 0x2: /* DCCP-Data */
901         /* nothing to dissect */
902         break;
903     case 0x3: /* DCCP-Ack */
904     case 0x4: /* DCCP-DataAck */
905         if (dccph->x) {
906             if (advertised_dccp_header_len < offset + 8) {
907                 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
908                     "Advertised header length (%u) is smaller than the minimum (%u) for %s",
909                     advertised_dccp_header_len, offset + 8,
910                     val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
911                 return tvb_length(tvb);
912             }
913             dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
914             if (tree) {
915                 hidden_item =
916                     proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset,
917                                         2, dccph->ack_reserved);
918                 PROTO_ITEM_SET_HIDDEN(hidden_item);
919             }
920             dccph->ack = tvb_get_ntohs(tvb, offset + 2);
921             dccph->ack <<= 32;
922             dccph->ack += tvb_get_ntohl(tvb, offset + 4);
923             if (tree)
924                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2,
925                                       6, dccph->ack);
926             col_append_fstr(pinfo->cinfo, COL_INFO,
927                             " (Ack=%" G_GINT64_MODIFIER "u)",
928                             dccph->ack);
929             offset += 8; /* move offset past the Ack Number Subheader */
930         } else {
931             if (advertised_dccp_header_len < offset + 4) {
932                 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
933                     "Advertised header length (%u) is smaller than the minimum (%u) for %s",
934                     advertised_dccp_header_len, offset + 4,
935                     val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
936                 return tvb_length(tvb);
937             }
938             dccph->ack_reserved = tvb_get_guint8(tvb, offset);
939             if (tree) {
940                 hidden_item =
941                     proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset,
942                                         1, dccph->ack_reserved);
943                 PROTO_ITEM_SET_HIDDEN(hidden_item);
944             }
945             dccph->ack = tvb_get_guint8(tvb, offset + 1);
946             dccph->ack <<= 16;
947             dccph->ack += tvb_get_ntohs(tvb, offset + 2);
948             if (tree)
949                 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 1,
950                                       3, dccph->ack);
951             col_append_fstr(pinfo->cinfo, COL_INFO,
952                             " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
953             offset += 4; /* move offset past the Ack. Number Subheader */
954         }
955         break;
956     case 0x7: /* DCCP-Reset */
957         if (advertised_dccp_header_len < offset + 4) {
958             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
959                 "Advertised header length (%u) is smaller than the minimum (%u) for Reset",
960                 advertised_dccp_header_len, offset + 4);
961             return tvb_length(tvb);
962         }
963         dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
964
965         if (tree) {
966             hidden_item =
967                 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
968                                     dccph->ack_reserved);
969             PROTO_ITEM_SET_HIDDEN(hidden_item);
970         }
971
972         dccph->ack = tvb_get_ntohs(tvb, offset + 2);
973         dccph->ack <<= 32;
974         dccph->ack += tvb_get_ntohl(tvb, offset + 4);
975
976         if (tree)
977             proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6,
978                                   dccph->ack);
979         col_append_fstr(pinfo->cinfo, COL_INFO,
980                         " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
981         offset += 8; /* move offset past the Ack. Number Subheader */
982
983         dccph->reset_code = tvb_get_guint8(tvb, offset);
984         dccph->data1 = tvb_get_guint8(tvb, offset + 1);
985         dccph->data2 = tvb_get_guint8(tvb, offset + 2);
986         dccph->data3 = tvb_get_guint8(tvb, offset + 3);
987
988         if (tree) {
989             proto_tree_add_uint(dccp_tree, hf_dccp_reset_code, tvb, offset, 1,
990                                 dccph->reset_code);
991             proto_tree_add_uint(dccp_tree, hf_dccp_data1, tvb, offset + 1, 1,
992                                 dccph->data1);
993             proto_tree_add_uint(dccp_tree, hf_dccp_data2, tvb, offset + 2, 1,
994                                 dccph->data2);
995             proto_tree_add_uint(dccp_tree, hf_dccp_data3, tvb, offset + 3, 1,
996                                 dccph->data3);
997         }
998         col_append_fstr(pinfo->cinfo, COL_INFO, " (code=%s)",
999                         val_to_str_const(dccph->reset_code, dccp_reset_code_vals,
1000                                          "Unknown"));
1001
1002         offset += 4; /* move offset past the Reset Code and data123 */
1003         break;
1004     case 0x5: /* DCCP-CloseReq */
1005     case 0x6: /* DCCP-Close */
1006     case 0x8: /* DCCP-Sync */
1007     case 0x9: /* DCCP-SyncAck */
1008         if (advertised_dccp_header_len < offset + 8) {
1009             expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1010                 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
1011                 advertised_dccp_header_len, offset + 8,
1012                 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
1013             return tvb_length(tvb);
1014         }
1015         dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
1016         if (tree) {
1017             hidden_item =
1018                 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
1019                                     dccph->ack_reserved);
1020             PROTO_ITEM_SET_HIDDEN(hidden_item);
1021         }
1022         dccph->ack = tvb_get_ntohs(tvb, offset + 2);
1023         dccph->ack <<= 32;
1024         dccph->ack += tvb_get_ntohl(tvb, offset + 4);
1025         if (tree)
1026             proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6,
1027                                   dccph->ack);
1028         col_append_fstr(pinfo->cinfo, COL_INFO,
1029                         " (Ack=%" G_GINT64_MODIFIER "u)", dccph->ack);
1030         offset += 8; /* move offset past the Ack. Number Subheader */
1031         break;
1032     default:
1033         expert_add_info(pinfo, dccp_item, &ei_dccp_packet_type_reserved);
1034         return tvb_length(tvb);
1035     }
1036
1037     /*
1038      * note: data_offset is the offset from the start of the packet's
1039      * DCCP header to the start of its application data area, in 32-bit words.
1040      */
1041     if (advertised_dccp_header_len > DCCP_HDR_LEN_MAX) {
1042         expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1043             "Advertised header length (%u) is larger than the maximum (%u)",
1044             advertised_dccp_header_len, DCCP_HDR_LEN_MAX);
1045         return tvb_length(tvb);
1046     }
1047
1048     /*
1049      * The checks done above ensure that
1050      * advertised_dccp_header_len >= offset.
1051      *
1052      * advertised_dccp_header_len - offset is the number of bytes of
1053      * options.
1054      */
1055     if (advertised_dccp_header_len > offset) {
1056         options_len = advertised_dccp_header_len - offset;
1057         if (dccp_tree) {
1058             dccp_item =
1059                 proto_tree_add_none_format(dccp_tree, hf_dccp_options, tvb,
1060                                            offset,
1061                                            options_len, "Options: (%u byte%s)",
1062                                            options_len,
1063                                            plurality(options_len, "", "s"));
1064             dccp_options_tree = proto_item_add_subtree(dccp_item,
1065                                                        ett_dccp_options);
1066         }
1067         dissect_options(tvb, pinfo, dccp_options_tree, tree, dccph, offset,
1068                         offset + options_len);
1069     }
1070
1071     offset += options_len; /* move offset past the Options */
1072     proto_item_set_end(dccp_item, tvb, offset);
1073
1074     /* queuing tap data */
1075     tap_queue_packet(dccp_tap, pinfo, dccph);
1076
1077     /* call sub-dissectors */
1078     if (!pinfo->flags.in_error_pkt || tvb_reported_length_remaining(tvb, offset) > 0)
1079         decode_dccp_ports(tvb, offset, pinfo, tree, dccph->sport, dccph->dport);
1080
1081     return tvb_length(tvb);
1082 }
1083
1084 void
1085 proto_register_dccp(void)
1086 {
1087     module_t *dccp_module;
1088
1089     static hf_register_info hf[] = {
1090         {
1091             &hf_dccp_srcport,
1092             {
1093                 "Source Port", "dccp.srcport",
1094                 FT_UINT16, BASE_DEC, NULL, 0x0,
1095                 NULL, HFILL
1096             }
1097         },
1098         {
1099             &hf_dccp_dstport,
1100             {
1101                 "Destination Port", "dccp.dstport",
1102                 FT_UINT16, BASE_DEC, NULL, 0x0,
1103                 NULL, HFILL
1104             }
1105         },
1106         {
1107             &hf_dccp_port,
1108             {
1109                 "Source or Destination Port", "dccp.port",
1110                 FT_UINT16, BASE_DEC, NULL, 0x0,
1111                 NULL, HFILL
1112             }
1113         },
1114         {
1115             &hf_dccp_data_offset,
1116             {
1117                 "Data Offset", "dccp.data_offset",
1118                 FT_UINT8, BASE_DEC, NULL, 0x0,
1119                 NULL, HFILL
1120             }
1121         },
1122         {
1123             &hf_dccp_ccval,
1124             {
1125                 "CCVal", "dccp.ccval",
1126                 FT_UINT8, BASE_DEC, NULL, 0x0,
1127                 NULL, HFILL
1128             }
1129         },
1130         {
1131             &hf_dccp_cscov,
1132             {
1133                 "Checksum Coverage", "dccp.cscov",
1134                 FT_UINT8, BASE_DEC, NULL, 0x0,
1135                 NULL, HFILL
1136             }
1137         },
1138         {
1139             &hf_dccp_checksum_bad,
1140             {
1141                 "Bad Checksum", "dccp.checksum_bad",
1142                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1143                 NULL, HFILL
1144             }
1145         },
1146         {
1147             &hf_dccp_checksum,
1148             {
1149                 "Checksum", "dccp.checksum",
1150                 FT_UINT16, BASE_HEX, NULL, 0x0,
1151                 NULL, HFILL
1152             }
1153         },
1154         {
1155             &hf_dccp_res1,
1156             {
1157                 "Reserved", "dccp.res1",
1158                 FT_UINT8, BASE_HEX, NULL, 0x0,
1159                 NULL, HFILL
1160             }
1161         },
1162         {
1163             &hf_dccp_res2,
1164             {
1165                 "Reserved", "dccp.res2",
1166                 FT_UINT8, BASE_HEX, NULL, 0x0,
1167                 NULL, HFILL
1168             }
1169         },
1170         {
1171             &hf_dccp_type,
1172             {
1173                 "Type", "dccp.type",
1174                 FT_UINT8, BASE_DEC, VALS(dccp_packet_type_vals), 0x0,
1175                 NULL, HFILL
1176             }
1177         },
1178         {
1179             &hf_dccp_x,
1180             {
1181                 "Extended Sequence Numbers", "dccp.x",
1182                 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1183                 NULL, HFILL
1184             }
1185         },
1186         {
1187             &hf_dccp_seq,
1188             {
1189                 "Sequence Number", "dccp.seq",
1190                 FT_UINT64, BASE_DEC, NULL, 0x0,
1191                 NULL, HFILL
1192             }
1193         },
1194         {
1195             &hf_dccp_ack_res,
1196             {
1197                 "Reserved", "dccp.ack_res",
1198                 FT_UINT16, BASE_HEX, NULL, 0x0,
1199                 NULL, HFILL
1200             }
1201         },
1202         {
1203             &hf_dccp_ack,
1204             {
1205                 "Acknowledgement Number", "dccp.ack",
1206                 FT_UINT64, BASE_DEC, NULL, 0x0,
1207                 NULL, HFILL
1208             }
1209         },
1210         {
1211             &hf_dccp_service_code,
1212             {
1213                 "Service Code", "dccp.service_code",
1214                 FT_UINT32, BASE_DEC, NULL, 0x0,
1215                 NULL, HFILL
1216             }
1217         },
1218         {
1219             &hf_dccp_reset_code,
1220             {
1221                 "Reset Code", "dccp.reset_code",
1222                 FT_UINT8, BASE_DEC, VALS(dccp_reset_code_vals), 0x0,
1223                 NULL, HFILL
1224             }
1225         },
1226         {
1227             &hf_dccp_data1,
1228             {
1229                 "Data 1", "dccp.data1",
1230                 FT_UINT8, BASE_DEC, NULL, 0x0,
1231                 NULL, HFILL
1232             }
1233         },
1234         {
1235             &hf_dccp_data2,
1236             {
1237                 "Data 2", "dccp.data2",
1238                 FT_UINT8, BASE_DEC, NULL, 0x0,
1239                 NULL, HFILL
1240             }
1241         },
1242         {
1243             &hf_dccp_data3,
1244             {
1245                 "Data 3", "dccp.data3",
1246                 FT_UINT8, BASE_DEC, NULL, 0x0,
1247                 NULL, HFILL
1248             }
1249         },
1250         {
1251             &hf_dccp_option_type,
1252             {
1253                 "Option Type", "dccp.option_type",
1254                 FT_UINT8, BASE_DEC, NULL, 0x0,
1255                 NULL, HFILL
1256             }
1257         },
1258         {
1259             &hf_dccp_feature_number,
1260             {
1261                 "Feature Number", "dccp.feature_number",
1262                 FT_UINT8, BASE_DEC, NULL, 0x0,
1263                 NULL, HFILL
1264             }
1265         },
1266 #if 0
1267         {
1268             &hf_dccp_ndp_count,
1269             {
1270                 "NDP Count", "dccp.ndp_count",
1271                 FT_UINT64, BASE_DEC, NULL, 0x0,
1272                 NULL, HFILL
1273             }
1274         },
1275 #endif
1276         {
1277             &hf_dccp_timestamp,
1278             {
1279                 "Timestamp", "dccp.timestamp",
1280                 FT_UINT32, BASE_DEC, NULL, 0x0,
1281                 NULL, HFILL
1282             }
1283         },
1284         {
1285             &hf_dccp_timestamp_echo,
1286             {
1287                 "Timestamp Echo", "dccp.timestamp_echo",
1288                 FT_UINT32, BASE_DEC, NULL, 0x0,
1289                 NULL, HFILL
1290             }
1291         },
1292         {
1293             &hf_dccp_elapsed_time,
1294             {
1295                 "Elapsed Time", "dccp.elapsed_time",
1296                 FT_UINT32, BASE_DEC, NULL, 0x0,
1297                 NULL, HFILL
1298             }
1299         },
1300         {
1301             &hf_dccp_data_checksum,
1302             {
1303                 "Data Checksum", "dccp.checksum_data",
1304                 FT_UINT32, BASE_HEX, NULL, 0x0,
1305                 NULL, HFILL
1306             }
1307         },
1308         {
1309             &hf_dccp_options,
1310             {
1311                 "Options", "dccp.options",
1312                 FT_NONE, BASE_NONE, NULL, 0x0,
1313                 "DCCP Options fields", HFILL
1314             }
1315         }
1316     };
1317
1318     static gint *ett[] = {
1319         &ett_dccp,
1320         &ett_dccp_options
1321     };
1322
1323     static ei_register_info ei[] = {
1324         { &ei_dccp_option_len_bad, { "dccp.option.len.bad", PI_PROTOCOL, PI_WARN, "Bad option length", EXPFILL }},
1325         { &ei_dccp_advertised_header_length_bad, { "dccp.advertised_header_length.bad", PI_MALFORMED, PI_ERROR, "Advertised header length bad", EXPFILL }},
1326         { &ei_dccp_packet_type_reserved, { "dccp.packet_type.reserved", PI_PROTOCOL, PI_WARN, "Reserved packet type: unable to dissect further", EXPFILL }},
1327     };
1328
1329     expert_module_t* expert_dccp;
1330
1331     proto_dccp =
1332         proto_register_protocol("Datagram Congestion Control Protocol", "DCCP",
1333                                 "dccp");
1334     proto_register_field_array(proto_dccp, hf, array_length(hf));
1335     proto_register_subtree_array(ett, array_length(ett));
1336     expert_dccp = expert_register_protocol(proto_dccp);
1337     expert_register_field_array(expert_dccp, ei, array_length(ei));
1338
1339     /* subdissectors */
1340     dccp_subdissector_table =
1341         register_dissector_table("dccp.port", "DCCP port", FT_UINT16,
1342                                  BASE_DEC);
1343     register_heur_dissector_list("dccp", &heur_subdissector_list);
1344
1345     /* reg preferences */
1346     dccp_module = prefs_register_protocol(proto_dccp, NULL);
1347     prefs_register_bool_preference(
1348         dccp_module, "summary_in_tree",
1349         "Show DCCP summary in protocol tree",
1350         "Whether the DCCP summary line should be shown in the protocol tree",
1351         &dccp_summary_in_tree);
1352
1353     prefs_register_bool_preference(
1354         dccp_module, "try_heuristic_first",
1355         "Try heuristic sub-dissectors first",
1356         "Try to decode a packet using an heuristic sub-dissector before "
1357         "using a sub-dissector "
1358         "registered to a specific port",
1359         &try_heuristic_first);
1360
1361     prefs_register_bool_preference(
1362         dccp_module, "check_checksum",
1363         "Check the validity of the DCCP checksum when possible",
1364         "Whether to check the validity of the DCCP checksum",
1365         &dccp_check_checksum);
1366 }
1367
1368 void
1369 proto_reg_handoff_dccp(void)
1370 {
1371     dissector_handle_t dccp_handle;
1372
1373     dccp_handle = new_create_dissector_handle(dissect_dccp, proto_dccp);
1374     dissector_add_uint("ip.proto", IP_PROTO_DCCP, dccp_handle);
1375     data_handle = find_dissector("data");
1376     dccp_tap    = register_tap("dccp");
1377 }
1378
1379 /*
1380  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1381  *
1382  * Local variables:
1383  * c-basic-offset: 4
1384  * tab-width: 8
1385  * indent-tabs-mode: nil
1386  * End:
1387  *
1388  * vi: set shiftwidth=4 tabstop=8 expandtab:
1389  * :indentSize=4:tabSize=8:noTabs=true:
1390  */