In the hex dump, generate the offset at the beginning of each line in
[obnox/wireshark/wip.git] / packet-dccp.c
1 /* packet-dccp.c
2  * Routines for Distributed Checksum Clearinghouse packet dissection
3  * DCC Home: http://www.rhyolite.com/anti-spam/dcc/
4  *
5  * Copyright 1999, Nathan Neulinger <nneul@umr.edu>
6  *
7  * $Id: packet-dccp.c,v 1.5 2002/05/03 20:34:14 nneul Exp $
8  *
9  * Ethereal - Network traffic analyzer
10  * By Gerald Combs <gerald@ethereal.com>
11  * Copyright 1998 Gerald Combs
12  *
13  * Copied from packet-tftp.c
14  * 
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  * 
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdio.h>
35
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_NETINET_IN_H
41 # include <netinet/in.h>
42 #endif
43
44 #include <string.h>
45 #include <glib.h>
46 #include <epan/packet.h>
47
48 #include <packet-dccp.h>
49
50 static int proto_dccp = -1;
51 static int hf_dccp_len = -1;
52 static int hf_dccp_pkt_vers = -1;
53 static int hf_dccp_op = -1;
54 static int hf_dccp_clientid = -1;
55 static int hf_dccp_opnums_host = -1;
56 static int hf_dccp_opnums_pid = -1;
57 static int hf_dccp_opnums_report = -1;
58 static int hf_dccp_opnums_retrans = -1;
59
60 static int hf_dccp_signature = -1;
61 static int hf_dccp_max_pkt_vers = -1;
62 static int hf_dccp_qdelay_ms = -1;
63 static int hf_dccp_brand = -1;
64
65 static int hf_dccp_ck_type = -1;
66 static int hf_dccp_ck_len = -1;
67 static int hf_dccp_ck_sum = -1;
68
69 static int hf_dccp_date = -1;
70 static int hf_dccp_msg = -1;
71
72 static int hf_dccp_target = -1;
73
74 static int hf_dccp_adminop = -1;
75 static int hf_dccp_adminval = -1;
76 static int hf_dccp_floodop = -1;
77 static int hf_dccp_trace = -1;
78 static int hf_dccp_trace_admin = -1;
79 static int hf_dccp_trace_anon = -1;
80 static int hf_dccp_trace_client = -1;
81 static int hf_dccp_trace_rlim = -1;
82 static int hf_dccp_trace_query = -1;
83 static int hf_dccp_trace_ridc = -1;
84 static int hf_dccp_trace_flood = -1;
85
86 static gint ett_dccp = -1;
87 static gint ett_dccp_opnums = -1;
88 static gint ett_dccp_op = -1;
89 static gint ett_dccp_ck = -1;
90 static gint ett_dccp_trace = -1;
91
92 /* Utility macros */
93 #define D_SIGNATURE() \
94         proto_tree_add_item(dccp_optree, hf_dccp_signature, tvb, \
95                 offset, sizeof(DCC_SIGNATURE), FALSE); \
96         offset += sizeof(DCC_SIGNATURE);
97
98 #define D_LABEL(label,len) \
99         proto_tree_add_text(dccp_optree, tvb, offset, len, label); \
100         offset += len;
101
102 #define D_TEXT(label, endpad) { \
103         int next_offset,linelen,left; \
104         const char *line; \
105     while (tvb_offset_exists(tvb, offset+endpad)) { \
106                 left = tvb_length_remaining(tvb,offset) - endpad; \
107                 linelen = tvb_find_line_end(tvb, offset, left, &next_offset); \
108                 line = tvb_get_ptr(tvb, offset, linelen); \
109                 proto_tree_add_text(dccp_optree, tvb, offset, \
110                         next_offset - offset, "%s: %s", \
111                         label, tvb_format_text(tvb, offset, next_offset - offset)); \
112                 offset = next_offset; \
113         } \
114 }
115
116
117 #define D_TARGET() \
118         proto_tree_add_item_hidden(dccp_tree, hf_dccp_target, tvb, \
119                 offset, sizeof(DCC_TGTS), FALSE); \
120         proto_tree_add_text(dccp_optree, tvb, offset, sizeof(DCC_TGTS), \
121                 val_to_str(tvb_get_ntohl(tvb,offset), dccp_target_vals, "Targets (%u)")); \
122         offset += sizeof(DCC_TGTS); \
123
124 #define D_DATE() { \
125         nstime_t ts; \
126         ts.nsecs = 0; \
127         ts.secs = tvb_get_ntohl(tvb,offset); \
128         proto_tree_add_time(dccp_optree, hf_dccp_date, tvb, offset, 4, &ts); \
129         offset += 4; \
130 }
131         
132
133 #define D_CHECKSUM() { \
134         proto_tree *cktree, *ti; \
135         ti = proto_tree_add_text(dccp_optree, tvb, offset, sizeof(DCC_CK), \
136                 "Checksum - %s", val_to_str(tvb_get_guint8(tvb,offset), \
137                 dccp_cktype_vals, \
138                 "Unknown Type: %u")); \
139         cktree = proto_item_add_subtree(ti, ett_dccp_ck); \
140         proto_tree_add_item(cktree, hf_dccp_ck_type, tvb, offset, 1, FALSE); \
141         offset += 1; \
142         proto_tree_add_item(cktree, hf_dccp_ck_len, tvb, offset, 1, FALSE); \
143         offset += 1; \
144         proto_tree_add_item(cktree, hf_dccp_ck_sum, tvb, offset, \
145                 sizeof(DCC_SUM), FALSE); \
146         offset += sizeof(DCC_SUM); \
147 }
148
149
150 /* Lookup string tables */
151 static const value_string dccp_op_vals[] = {
152         {DCC_OP_INVALID, "Invalid Op"},
153         {DCC_OP_NOP,    "No-Op"},
154         {DCC_OP_REPORT, "Report and Query"},
155         {DCC_OP_QUERY, "Query"},
156         {DCC_OP_QUERY_RESP, "Server Response"},
157         {DCC_OP_ADMN, "Admin"},
158         {DCC_OP_OK, "Ok"},
159         {DCC_OP_ERROR, "Server Failing"},
160         {DCC_OP_DELETE, "Delete Checksum(s)"},
161         {0, NULL}
162 };
163
164 static const value_string dccp_cktype_vals[] = {
165         {DCC_CK_INVALID, "Invalid/Deleted from DB when seen"},
166         {DCC_CK_IP,     "MD5 of binary source IPv6 address"},
167         {DCC_CK_ENV_FROM, "MD5 of envelope Mail From value"},
168         {DCC_CK_FROM, "MD5 of header From: line"},
169         {DCC_CK_SUB, "MD5 of substitute header line"},
170         {DCC_CK_MESSAGE_ID, "MD5 of header Message-ID: line"},
171         {DCC_CK_RECEIVED, "MD5 of last header Received: line"},
172         {DCC_CK_BODY, "MD5 of body"},
173         {DCC_CK_FUZ1, "MD5 of filtered body - FUZ1"},
174         {DCC_CK_FUZ2, "MD5 of filtered body - FUZ2"},
175         {DCC_CK_FUZ3, "MD5 of filtered body - FUZ3"},
176         {DCC_CK_FUZ4, "MD5 of filtered body - FUZ4"},
177         {DCC_CK_SRVR_ID, "hostname for server-ID check "},
178         {DCC_CK_ENV_TO, "MD5 of envelope Rcpt To value"},
179         {0, NULL},
180 };
181
182 static const value_string dccp_adminop_vals[] = {
183         {DCC_AOP_OK, "Never sent"},
184         {DCC_AOP_STOP, "Stop Gracefully"},
185         {DCC_AOP_NEW_IDS, "Load keys and client IDs"},
186         {DCC_AOP_FLOD, "Flood control"},
187         {DCC_AOP_DB_UNLOCK, "Start Switch to new database"},
188         {DCC_AOP_DB_NEW, "Finish Switch to new database"},
189         {DCC_AOP_STATS, "Return counters"},
190         {DCC_AOP_STATS_CLEAR, "Return and zero counters"},
191         {DCC_AOP_TRACE_ON, "Enable tracing"},
192         {DCC_AOP_TRACE_OFF, "Disable tracing"},
193         {DCC_AOP_CUR_CLIENTS, "List clients"},
194         {0, NULL},
195 };
196
197 static const value_string dccp_target_vals[] = {
198         {DCC_TGTS_TOO_MANY, "Targets (>= 16777200)"},
199         {DCC_TGTS_OK, "Certified not spam"},
200         {DCC_TGTS_OK2, "Half certified not spam"},
201         {DCC_TGTS_DEL, "Deleted checksum"},
202         {DCC_TGTS_INVALID, "Invalid"},
203         {0, NULL},
204 };
205
206 static const value_string dccp_floodop_vals[] = {
207         {DCC_AOP_FLOD_CHECK, "Check"},   
208         {DCC_AOP_FLOD_SHUTDOWN, "Shutdown"},
209         {DCC_AOP_FLOD_HALT, "Halt"},
210         {DCC_AOP_FLOD_RESUME, "Resume"},
211         {DCC_AOP_FLOD_REWIND, "Rewind"},
212         {DCC_AOP_FLOD_LIST, "List"},
213         {DCC_AOP_FLOD_STATS, "Stats"},
214         {DCC_AOP_FLOD_STATS_CLEAR, "Clear Stats"},
215         {0,NULL},
216 };
217
218 static gboolean
219 dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
220 {
221         proto_tree      *dccp_tree, *dccp_optree, *dccp_opnumtree, *ti;
222         proto_tree *dccp_tracetree;
223         int offset = 0;
224         int client_is_le = 0;
225         int op = 0;
226         int i, count, is_response;
227
228         if (pinfo->srcport != DCC_PORT && pinfo->destport != DCC_PORT) {
229                 /* Not the right port - not a DCC packet. */
230                 return FALSE;
231         }
232
233         /* get at least a full packet structure */
234         if ( !tvb_bytes_exist(tvb, 0, sizeof(DCC_HDR)) ) {
235                 /* Doesn't have enough bytes to contain packet header. */
236                 return FALSE;
237         }
238
239         if (check_col(pinfo->cinfo, COL_PROTOCOL))
240                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
241
242         offset = 0;
243         is_response = pinfo->srcport == DCC_PORT;
244         
245         if (check_col(pinfo->cinfo, COL_INFO)) {
246                 col_add_fstr(pinfo->cinfo, COL_INFO, 
247                         "%s: %s", 
248                         is_response ? "Response" : "Request", 
249                         val_to_str(tvb_get_guint8(tvb, offset+3),
250                                  dccp_op_vals, "Unknown Op: %u")
251                 );
252         }
253
254         if (tree) {
255                 ti = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1,
256                         FALSE);
257                 dccp_tree = proto_item_add_subtree(ti, ett_dccp);
258
259                 proto_tree_add_item(dccp_tree, hf_dccp_len, tvb, 
260                         offset, 2, FALSE);
261
262                 if ( !tvb_bytes_exist(tvb, 0, tvb_get_ntohs(tvb, offset))) {
263                         /* Doesn't have number of bytes that header claims. */
264                         proto_tree_add_text(dccp_tree, tvb, offset, 2, "Error - packet is shorter than header claims!");
265                 }
266                 offset += 2;
267
268                 proto_tree_add_item(dccp_tree, hf_dccp_pkt_vers, tvb, 
269                         offset, 1, FALSE);
270                 offset += 1;
271
272                 op = tvb_get_guint8(tvb, offset);
273                 proto_tree_add_item(dccp_tree, hf_dccp_op, tvb, 
274                         offset, 1, FALSE);
275                 offset += 1;
276
277                 proto_tree_add_item(dccp_tree, hf_dccp_clientid, tvb, 
278                         offset, 4, FALSE);
279                 offset += 4;
280
281                 ti = proto_tree_add_text(dccp_tree, tvb, offset, -1, "Operation Numbers (Opaque to Server)");
282                 dccp_opnumtree = proto_item_add_subtree(ti, ett_dccp_opnums);
283
284                 /* Note - these are indeterminate - they are sortof considered opaque to the client */
285                 /* Make some attempt to figure out if this data is little endian, not guaranteed to be
286                 correct if connection went through a firewall or similar. */
287
288                 /* Very hokey check - if all three of pid/report/retrans look like little-endian 
289                         numbers, host is probably little endian. Probably innacurate on super-heavily-used
290                         DCC clients though. This should be good enough for now. */
291                 client_is_le = ( (tvb_get_guint8(tvb, offset+4) | tvb_get_guint8(tvb, offset+4)) &&
292                                                  (tvb_get_guint8(tvb, offset+8) | tvb_get_guint8(tvb, offset+9)) &&
293                                                  (tvb_get_guint8(tvb, offset+12) | tvb_get_guint8(tvb, offset+13)) );
294
295                 proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_host, tvb, 
296                         offset, 4, client_is_le);
297                 offset += 4;
298
299                 proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_pid, tvb, 
300                         offset, 4, client_is_le);
301                 offset += 4;
302
303                 proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_report, tvb, 
304                         offset, 4, client_is_le);
305                 offset += 4;
306
307                 proto_tree_add_item(dccp_opnumtree, hf_dccp_opnums_retrans, tvb, 
308                         offset, 4, client_is_le);
309                 offset += 4;
310
311                 ti = proto_tree_add_text(dccp_tree, tvb, offset, -1, "Operation: %s",
312                         val_to_str(op, dccp_op_vals, "Unknown Op: %u"));
313                 dccp_optree = proto_item_add_subtree(ti, ett_dccp_op);
314
315                 switch(op) {
316                         case DCC_OP_NOP:
317                                 D_SIGNATURE();
318                                 break;
319
320                         case DCC_OP_REPORT:
321                                 D_TARGET();
322                                 for (i=0; i<=DCC_QUERY_MAX &&
323                                         tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
324                                 {
325                                         D_CHECKSUM();
326                                 }
327                                 D_SIGNATURE();
328                                 break;
329
330                         case DCC_OP_QUERY_RESP:
331                                 for (i=0; i<=DCC_QUERY_MAX &&
332                                         tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
333                                 {
334                                         D_TARGET();
335                                 }
336                                 D_SIGNATURE();
337                                 break;
338
339                         case DCC_OP_ADMN:
340                                 if ( is_response )
341                                 {
342                                         int left = tvb_length_remaining(tvb, offset) -
343                                                 sizeof(DCC_SIGNATURE);
344                                         if ( left == sizeof(DCC_ADMN_RESP_CLIENTS) )
345                                         {
346                                                 D_LABEL("Addr", 16);
347                                                 D_LABEL("Id", sizeof(DCC_CLNT_ID));
348                                                 D_LABEL("Last Used", 4);
349                                                 D_LABEL("Requests", 4);
350                                         }
351                                         else
352                                         {
353                                                 D_TEXT("Response Text", sizeof(DCC_SIGNATURE));
354                                         }
355                                         D_SIGNATURE();
356                                 }
357                                 else
358                                 {
359                                         int aop;
360
361                                         D_DATE();
362
363                                         aop = tvb_get_guint8(tvb, offset+4);
364                                         proto_tree_add_item(dccp_optree, hf_dccp_adminop, tvb, offset+4,
365                                                 1, FALSE);
366                                         if (check_col(pinfo->cinfo, COL_INFO)) {
367                                                 col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
368                                                         val_to_str(tvb_get_guint8(tvb,offset+4), 
369                                                         dccp_adminop_vals, "Unknown (%u)"));
370                                         }
371         
372                                         if (aop == DCC_AOP_TRACE_ON || aop == DCC_AOP_TRACE_OFF )
373                                         {
374                                                 ti = proto_tree_add_item(dccp_optree, hf_dccp_trace, tvb, offset,
375                                                         4, FALSE);
376                                                 dccp_tracetree = proto_item_add_subtree(ti, ett_dccp_trace);
377                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_admin, tvb, offset, 4, FALSE);
378                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_anon, tvb, offset, 4, FALSE);
379                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_client, tvb, offset, 4, FALSE);
380                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_rlim, tvb, offset, 4, FALSE);
381                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_query, tvb, offset, 4, FALSE);
382                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_ridc, tvb, offset, 4, FALSE);
383                                                 proto_tree_add_item(dccp_tracetree, hf_dccp_trace_flood, tvb, offset, 4, FALSE);
384                                         }
385                                         else if ( aop == DCC_AOP_FLOD )
386                                         {
387                                                 proto_tree_add_item(dccp_optree, hf_dccp_floodop, 
388                                                         tvb, offset, 4, FALSE);
389                                                 if (check_col(pinfo->cinfo, COL_INFO)) {
390                                                         col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
391                                                                 val_to_str(tvb_get_ntohl(tvb,offset), 
392                                                                 dccp_floodop_vals, "Unknown (%u)"));
393                                                 }
394                                         }
395                                         else
396                                         {
397                                                 proto_tree_add_item(dccp_optree, hf_dccp_adminval, 
398                                                         tvb, offset, 4, FALSE);
399                                         }
400                                         offset += 4;
401
402                                         offset += 1; /* admin op we did in reverse order */
403                                         D_LABEL("Pad", 3);
404                                         D_SIGNATURE();
405                                 }
406                                 break;
407
408                         case DCC_OP_OK:
409                                 proto_tree_add_item(dccp_optree, hf_dccp_max_pkt_vers, tvb,
410                                         offset, 1, FALSE);
411                                 offset += 1;
412
413                                 D_LABEL("Unused", 1);
414
415                                 proto_tree_add_item(dccp_optree, hf_dccp_qdelay_ms, tvb,
416                                         offset, 2, FALSE);
417                                 offset += 2;
418                         
419                                 proto_tree_add_item(dccp_optree, hf_dccp_brand, tvb,
420                                         offset, sizeof(DCC_BRAND), FALSE);
421                                 offset += sizeof(DCC_BRAND);
422
423                                 D_SIGNATURE();
424                                 break;
425                                 
426                         default:
427                                 /* do nothing */
428                                 break;
429                 }
430         }
431
432         return TRUE;
433 }
434
435 void
436 proto_register_dccp(void)
437 {
438         static hf_register_info hf[] = {
439                         { &hf_dccp_len, {       
440                                 "Packet Length", "dccp.len", FT_UINT16, BASE_DEC,
441                                 NULL, 0, "Packet Length", HFILL }},
442
443                         { &hf_dccp_pkt_vers, {  
444                                 "Packet Version", "dccp.pkt_vers", FT_UINT16, BASE_DEC,
445                                 NULL, 0, "Packet Version", HFILL }},
446
447                         { &hf_dccp_op, {        
448                                 "Operation Type", "dccp.op", FT_UINT8, BASE_DEC,
449                                 VALS(dccp_op_vals), 0, "Operation Type", HFILL }},
450
451                         { &hf_dccp_clientid, {  
452                                 "Client ID", "dccp.clientid", FT_UINT32, BASE_DEC,
453                                 NULL, 0, "Client ID", HFILL }},
454
455                         { &hf_dccp_opnums_host, {       
456                                 "Host", "dccp.opnums.host", FT_IPv4, BASE_DEC,
457                                 NULL, 0, "Host", HFILL }},
458
459                         { &hf_dccp_opnums_pid, {        
460                                 "Process ID", "dccp.opnums.pid", FT_UINT32, BASE_DEC,
461                                 NULL, 0, "Process ID", HFILL }},
462
463                         { &hf_dccp_opnums_report, {     
464                                 "Report", "dccp.opnums.report", FT_UINT32, BASE_DEC,
465                                 NULL, 0, "Report", HFILL }},
466
467                         { &hf_dccp_opnums_retrans, {    
468                                 "Retransmission", "dccp.opnums.retrans", FT_UINT32, BASE_DEC,
469                                 NULL, 0, "Retransmission", HFILL }},
470
471                         { &hf_dccp_signature, { 
472                                 "Signature", "dccp.signature", FT_BYTES, BASE_HEX,
473                                 NULL, 0, "Signature", HFILL }},
474
475                         { &hf_dccp_max_pkt_vers, {      
476                                 "Maximum Packet Version", "dccp.max_pkt_vers", FT_UINT8, BASE_DEC,
477                                 NULL, 0, "Maximum Packet Version", HFILL }},
478
479                         { &hf_dccp_qdelay_ms, { 
480                                 "Client Delay", "dccp.qdelay_ms", FT_UINT16, BASE_DEC,
481                                 NULL, 0, "Client Delay", HFILL }},
482
483                         { &hf_dccp_brand, {     
484                                 "Server Brand", "dccp.brand", FT_STRING, BASE_DEC,
485                                 NULL, 0, "Server Brand", HFILL }},
486
487                         { &hf_dccp_ck_type, {   
488                                 "Type", "dccp.checksum.type", FT_UINT8, BASE_DEC,
489                                 VALS(dccp_cktype_vals), 0, "Checksum Type", HFILL }},
490
491                         { &hf_dccp_ck_len, {    
492                                 "Length", "dccp.checksum.length", FT_UINT8, BASE_DEC,
493                                 NULL, 0, "Checksum Length", HFILL }},
494
495                         { &hf_dccp_ck_sum, {    
496                                 "Sum", "dccp.checksum.sum", FT_BYTES, BASE_HEX,
497                                 NULL, 0, "Checksum", HFILL }},
498
499                         { &hf_dccp_target, {    
500                                 "Target", "dccp.target", FT_UINT32, BASE_HEX,
501                                 NULL, 0, "Target", HFILL }},
502
503                         { &hf_dccp_date, {      
504                                 "Date", "dccp.date", FT_ABSOLUTE_TIME, BASE_DEC,
505                                 NULL, 0, "Date", HFILL }},
506
507                         { &hf_dccp_adminop, {   
508                                 "Admin Op", "dccp.adminop", FT_UINT8, BASE_DEC,
509                                 VALS(dccp_adminop_vals), 0, "Admin Op", HFILL }},
510
511                         { &hf_dccp_adminval, {  
512                                 "Admin Value", "dccp.adminval", FT_UINT32, BASE_DEC,
513                                 NULL, 0, "Admin Value", HFILL }},
514
515                         { &hf_dccp_trace, {     
516                                 "Trace Bits", "dccp.trace", FT_UINT32, BASE_HEX,
517                                 NULL, 0, "Trace Bits", HFILL }},
518
519                         { &hf_dccp_trace_admin, {
520                                 "Admin Requests", "dccp.trace.admin", FT_UINT32, BASE_BIN,
521                                 NULL, 0x0001, "Admin Requests", HFILL }},
522
523                         { &hf_dccp_trace_anon, {
524                                 "Anonymous Requests", "dccp.trace.anon", FT_UINT32, BASE_BIN,
525                                 NULL, 0x0002, "Anonymous Requests", HFILL }},
526
527                         { &hf_dccp_trace_client, {
528                                 "Authenticated Client Requests", "dccp.trace.client", FT_UINT32, BASE_BIN,
529                                 NULL, 0x0004, "Authenticated Client Requests", HFILL }},
530
531                         { &hf_dccp_trace_rlim, {
532                                 "Rate-Limited Requests", "dccp.trace.rlim", FT_UINT32, BASE_BIN,
533                                 NULL, 0x0008, "Rate-Limited Requests", HFILL }},
534
535                         { &hf_dccp_trace_query, {
536                                 "Queries and Reports", "dccp.trace.query", FT_UINT32, BASE_BIN,
537                                 NULL, 0x0010, "Queries and Reports", HFILL }},
538
539                         { &hf_dccp_trace_ridc, {
540                                 "RID Cache Messages", "dccp.trace.ridc", FT_UINT32, BASE_BIN,
541                                 NULL, 0x0020, "RID Cache Messages", HFILL }},
542
543                         { &hf_dccp_trace_flood, {
544                                 "Input/Output Flooding", "dccp.trace.flood", FT_UINT32, BASE_BIN,
545                                 NULL, 0x0040, "Input/Output Flooding", HFILL }},
546
547                         { &hf_dccp_floodop, {
548                                 "Flood Control Operation", "dccp.floodop", FT_UINT32, BASE_DEC,
549                                 VALS(dccp_floodop_vals), 0, "Flood Control Operation", HFILL }},
550
551         };
552         static gint *ett[] = {
553                 &ett_dccp,
554                 &ett_dccp_op,
555                 &ett_dccp_ck,
556                 &ett_dccp_opnums,
557                 &ett_dccp_trace,
558         };
559
560         proto_dccp = proto_register_protocol("Distributed Checksum Clearinghouse Prototocl",
561             "DCCP", "dccp");
562
563         proto_register_field_array(proto_dccp, hf, array_length(hf));
564
565         proto_register_subtree_array(ett, array_length(ett));
566 }
567
568 void
569 proto_reg_handoff_dccp(void)
570 {
571         heur_dissector_add("udp", dissect_dccp, proto_dccp);
572 }