/src/wireshark/epan/dissectors/packet-dcc.c
Line | Count | Source |
1 | | /* packet-dcc.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 | | * Wireshark - Network traffic analyzer |
8 | | * By Gerald Combs <gerald@wireshark.org> |
9 | | * Copyright 1998 Gerald Combs |
10 | | * |
11 | | * Copied from packet-tftp.c |
12 | | * |
13 | | * SPDX-License-Identifier: GPL-2.0-or-later |
14 | | */ |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | #include <epan/packet.h> |
19 | | #include "packet-udp.h" |
20 | | |
21 | | void proto_register_dcc(void); |
22 | | void proto_reg_handoff_dcc(void); |
23 | | |
24 | | static int proto_dcc; |
25 | | static int hf_dcc_len; |
26 | | static int hf_dcc_pkt_vers; |
27 | | static int hf_dcc_op; |
28 | | static int hf_dcc_clientid; |
29 | | static int hf_dcc_opnums_host; |
30 | | static int hf_dcc_opnums_pid; |
31 | | static int hf_dcc_opnums_report; |
32 | | static int hf_dcc_opnums_retrans; |
33 | | |
34 | | static int hf_dcc_signature; |
35 | | static int hf_dcc_max_pkt_vers; |
36 | | static int hf_dcc_qdelay_ms; |
37 | | static int hf_dcc_brand; |
38 | | |
39 | | static int hf_dcc_ck_type; |
40 | | static int hf_dcc_ck_len; |
41 | | static int hf_dcc_ck_sum; |
42 | | |
43 | | static int hf_dcc_date; |
44 | | |
45 | | static int hf_dcc_target; |
46 | | static int hf_dcc_response_text; |
47 | | |
48 | | static int hf_dcc_adminop; |
49 | | static int hf_dcc_adminval; |
50 | | static int hf_dcc_floodop; |
51 | | static int hf_dcc_trace; |
52 | | static int hf_dcc_trace_admin; |
53 | | static int hf_dcc_trace_anon; |
54 | | static int hf_dcc_trace_client; |
55 | | static int hf_dcc_trace_rlim; |
56 | | static int hf_dcc_trace_query; |
57 | | static int hf_dcc_trace_ridc; |
58 | | static int hf_dcc_trace_flood; |
59 | | |
60 | | static int hf_dcc_addr; |
61 | | static int hf_dcc_id; |
62 | | static int hf_dcc_last_used; |
63 | | static int hf_dcc_requests; |
64 | | static int hf_dcc_pad; |
65 | | static int hf_dcc_unused; |
66 | | |
67 | | static int ett_dcc; |
68 | | static int ett_dcc_opnums; |
69 | | static int ett_dcc_op; |
70 | | static int ett_dcc_ck; |
71 | | static int ett_dcc_trace; |
72 | | |
73 | | |
74 | | /* Inserted below is dcc_proto.h from the dcc source distribution, with the |
75 | | following changes made: |
76 | | |
77 | | :%s/u_in*t16_t/uint16_t/g |
78 | | :%s/u_in*t32_t/uint32_t/g |
79 | | :%s/u_ch*ar/unsigned char/g |
80 | | :%s/in*t32_t/int32_t/g |
81 | | |
82 | | This includes more than is really necessary, but easier to just include whole |
83 | | header. |
84 | | |
85 | | */ |
86 | | |
87 | | |
88 | | /* Distributed Checksum Clearinghouse protocol |
89 | | * |
90 | | * Copyright (c) 2002 by Rhyolite Software |
91 | | * |
92 | | * SPDX-License-Identifier: ISC |
93 | | * |
94 | | * Rhyolite Software DCC 1.0.53-1.45 $Revision: 1.3 $ |
95 | | */ |
96 | | |
97 | | #ifndef DCC_PROTO_H |
98 | | #define DCC_PROTO_H |
99 | | |
100 | | |
101 | 39 | #define DCC_PORT 6277 /* default UDP port #, MAPS in DTMF */ |
102 | | |
103 | | |
104 | | /* No client's retransmission can be delayed by more than this |
105 | | * This matters for how long a DCC server must remember old requests |
106 | | * to recognize retransmissions */ |
107 | | #define DCC_MAX_DELAY_SEC 30 |
108 | | |
109 | | typedef uint16_t DCC_MS; |
110 | | |
111 | | /* anonymous client delay */ |
112 | | #define DCC_MAX_QDELAY_MS (DCC_MAX_DELAY_SEC*1000) |
113 | | #define DCC_DEF_QDELAY_MS 0 |
114 | | |
115 | | |
116 | | /* types of checksums */ |
117 | | typedef enum { |
118 | | DCC_CK_INVALID =0, /* deleted from database when seen */ |
119 | | DCC_CK_IP =1, /* MD5 of binary source IPv6 address */ |
120 | | DCC_CK_ENV_FROM =2, /* " " envelope Mail From value */ |
121 | | DCC_CK_FROM =3, /* " " header From: line */ |
122 | | DCC_CK_SUB =4, /* " " substitute header line */ |
123 | | DCC_CK_MESSAGE_ID=5, /* " " header Message-ID: line */ |
124 | | DCC_CK_RECEIVED =6, /* " " last header Received: line */ |
125 | | DCC_CK_BODY =7, /* " " body */ |
126 | | DCC_CK_FUZ1 =8, /* " " filtered body */ |
127 | | DCC_CK_FUZ2 =9, /* " " " " */ |
128 | | DCC_CK_FUZ3 =10, /* " " " " */ |
129 | | DCC_CK_FUZ4 =11, /* " " " " */ |
130 | | DCC_CK_SRVR_ID =12, /* hostname for server-ID check */ |
131 | | DCC_CK_ENV_TO =13 /* MD5 of envelope Rcpt To value */ |
132 | | # define DCC_CK_FLOD_PATH DCC_CK_ENV_TO /* flooding path in server-IDs */ |
133 | | } DCC_CK_TYPES; |
134 | | #define DCC_CK_TYPE_FIRST DCC_CK_IP |
135 | 50 | #define DCC_CK_TYPE_LAST DCC_CK_ENV_TO |
136 | | #define DCC_NUM_CKS DCC_CK_TYPE_LAST /* # of valid types */ |
137 | | |
138 | | /* DCC_DIM_CKS dimensions arrays of checksum types including DCC_CK_INVALID |
139 | | * Beware that DCC_DIM_CKS is used in the database header. */ |
140 | 100 | #define DCC_DIM_CKS (DCC_CK_TYPE_LAST+1) |
141 | | |
142 | | /* Ensure that arrays of DCC_CKs contain an even number so that structures |
143 | | * containing them will have no extra structure packing */ |
144 | | #define DCC_COMP_DIM_CKS ((((DCC_NUM_CKS+1)+1)/2)*2) /* == DCC_DIM_CKS */ |
145 | | |
146 | | /* keep in the database longer than others */ |
147 | | #define DCC_CK_LONG_TERM(t) ((t) >= DCC_CK_FUZ1 && (t) <= DCC_CK_FUZ4) |
148 | | |
149 | | #define DCC_CK_IS_BODY(t) ((t) >= DCC_CK_BODY && (t) <= DCC_CK_FUZ4) |
150 | | |
151 | | /* ok for users to talk about */ |
152 | | #define DCC_CK_OK_USER(t) ((t) > DCC_CK_INVALID && (t) <= DCC_CK_FUZ4) |
153 | | /* ok in the database */ |
154 | | #define DCC_CK_OK_DB(t) ((t) > DCC_CK_INVALID && (t) <= DCC_CK_TYPE_LAST) |
155 | | #define DCC_CK_OK_PROTO(t) DCC_CK_OK_USER(t) /* ok from clients */ |
156 | | #define DCC_CK_OK_FLOD(t) DCC_CK_OK_DB(t) /* ok in floods */ |
157 | | |
158 | | typedef unsigned char DCC_CK_TYPE; |
159 | | |
160 | | |
161 | | typedef enum { |
162 | | DCC_OP_INVALID=0, |
163 | | DCC_OP_NOP, /* see if the server is alive */ |
164 | | DCC_OP_REPORT, /* client reporting and querying */ |
165 | | DCC_OP_QUERY, /* client querying */ |
166 | | DCC_OP_QUERY_RESP, /* server responding */ |
167 | | DCC_OP_ADMN, /* local control of the server */ |
168 | | DCC_OP_OK, /* administrative operation ok */ |
169 | | DCC_OP_ERROR, /* server failing or complaining */ |
170 | | DCC_OP_DELETE /* delete some checksums */ |
171 | | } DCC_OPS; |
172 | | |
173 | | typedef uint32_t DCC_CLNT_ID; |
174 | | #define DCC_ID_INVALID 0 |
175 | | #define DCC_ID_ANON 1 /* anonymous (non-paying) client */ |
176 | | #define DCC_ID_WHITE 2 /* white-listed */ |
177 | | #define DCC_ID_COMP 3 /* compressed */ |
178 | | #define DCC_SRVR_ID_MIN 100 /* below reserved for special uses */ |
179 | | #define DCC_SRVR_ID_MAX 32767 /* below are servers--must be 2**n-1 */ |
180 | | #define DCC_CLNT_ID_MIN (DCC_SRVR_ID_MAX+1) |
181 | | #define DCC_CLNT_ID_MAX 16777215 |
182 | | typedef uint16_t DCC_SRVR_ID; |
183 | | #define DCC_SRVR_ID_AUTH (DCC_SRVR_ID_MAX+1) /* client was authenticated */ |
184 | | |
185 | | /* client's identification of its transaction */ |
186 | | typedef struct { |
187 | | uint32_t h; /* client host ID, e.g. IP address */ |
188 | | uint32_t p; /* process ID, serial #, timestamp */ |
189 | | uint32_t r; /* report ID */ |
190 | | uint32_t t; /* client (re)transmission # */ |
191 | | } DCC_OP_NUMS; |
192 | | |
193 | | /* The inter-DCC server flooding algorithm depends on unique-per-server |
194 | | * timestamps to detect duplicates. That imposes a requirement on |
195 | | * timestamps that they have resolution enough to separate reports |
196 | | * from clients arriving at any single server. |
197 | | * The timestamps are 48 bits consisting of 17 bits of 8's of microseconds |
198 | | * and 31 bits of seconds. That's sufficient for the UNIX epoch. |
199 | | * If the DCC is still around in the 2030's (and in the unlikely case that |
200 | | * 8 microseconds are still fine enough), we can make the 31 bits be |
201 | | * an offset in a bigger window. |
202 | | */ |
203 | | #define DCC_TS_USEC_RSHIFT 3 |
204 | | #define DCC_TS_USEC_MULT (1<<DCC_TS_USEC_RSHIFT) |
205 | | #define DCC_TS_SEC_LSHIFT 17 |
206 | | #define DCC_TS_USEC_MASK ((1<<DCC_TS_SEC_LSHIFT) - 1) |
207 | | typedef unsigned char DCC_TS[6]; |
208 | | |
209 | | /* The start of any DCC packet. |
210 | | * The length and version are early, since they are they only fields |
211 | | * that are constrained in future versions. */ |
212 | | typedef struct { |
213 | | uint16_t len; /* total DCC packet length (for TCP) */ |
214 | | unsigned char pkt_vers; /* packet protocol version */ |
215 | | # define DCC_PKT_VERSION 4 |
216 | | # define DCC_PKT_VERSION_MIN DCC_PKT_VERSION |
217 | | # define DCC_PKT_VERSION_MAX DCC_PKT_VERSION |
218 | | unsigned char op; /* one of DCC_OPS */ |
219 | | /* Identify the transaction. |
220 | | * Each client can have many hosts, each host can be multi-homed, |
221 | | * and each host can be running many processes talking to the |
222 | | * server. Each packet needs to be uniquely numbered, so that the |
223 | | * server can recognize as interchangeable all of the (re)transmissions |
224 | | * of a single report (rid) from a client process (pid) on a single |
225 | | * host (hid), and the client can know which transmission (tid) |
226 | | * produced a given server response to maintain the client's RTT |
227 | | * value for the server. */ |
228 | | DCC_CLNT_ID sender; /* official DCC client-ID */ |
229 | | DCC_OP_NUMS op_nums; /* op_num.t must be last */ |
230 | | } DCC_HDR; |
231 | | |
232 | | typedef unsigned char DCC_SIGNATURE[16]; |
233 | | |
234 | | typedef struct { |
235 | | DCC_HDR hdr; |
236 | | DCC_SIGNATURE signature; |
237 | | } DCC_NOP; |
238 | | |
239 | | |
240 | | /* administrative requests from localhost |
241 | | * These can be freely changed, because the administrative tools |
242 | | * should match the daemon. */ |
243 | | typedef enum { |
244 | | DCC_AOP_OK=-1, /* never really sent */ |
245 | | DCC_AOP_STOP=1, /* stop gracefully */ |
246 | | DCC_AOP_NEW_IDS, /* load keys and client-IDs */ |
247 | | DCC_AOP_FLOD, /* start or stop flooding */ |
248 | | DCC_AOP_DB_UNLOCK, /* start switch to new database */ |
249 | | DCC_AOP_DB_NEW, /* finish switch to new database */ |
250 | | DCC_AOP_STATS, /* return counters--val=buffer size */ |
251 | | DCC_AOP_STATS_CLEAR, /* return and zero counters */ |
252 | | DCC_AOP_TRACE_ON, |
253 | | DCC_AOP_TRACE_OFF, |
254 | | DCC_AOP_CUR_CLIENTS /* some client IP addresses */ |
255 | | } DCC_AOPS; |
256 | | |
257 | | /* for DCC_AOP_FLOD */ |
258 | | typedef enum { |
259 | | DCC_AOP_FLOD_CHECK=0, |
260 | | DCC_AOP_FLOD_SHUTDOWN, |
261 | | DCC_AOP_FLOD_HALT, |
262 | | DCC_AOP_FLOD_RESUME, |
263 | | DCC_AOP_FLOD_REWIND, |
264 | | DCC_AOP_FLOD_LIST, |
265 | | DCC_AOP_FLOD_STATS, |
266 | | DCC_AOP_FLOD_STATS_CLEAR |
267 | | } DCC_AOP_FLODS; |
268 | | |
269 | | typedef struct { /* with operation DCC_OP_ADMN */ |
270 | | DCC_HDR hdr; |
271 | | int32_t date; /* seconds since epoch on caller */ |
272 | | uint32_t val; /* request type, buffer size, etc. */ |
273 | | unsigned char aop; /* one of DCC_AOPS */ |
274 | | unsigned char pad[3]; |
275 | | DCC_SIGNATURE signature; |
276 | | } DCC_ADMN_REQ; |
277 | | |
278 | | /* noisy response to some DCC_AOPS with operation DCC_OP_ADMN */ |
279 | | typedef struct { |
280 | | unsigned char addr[16]; |
281 | | DCC_CLNT_ID id; |
282 | | uint32_t last_used; |
283 | | uint32_t requests; |
284 | | } DCC_ADMN_RESP_CLIENTS; |
285 | | typedef union { |
286 | | char string[80*22]; |
287 | | DCC_ADMN_RESP_CLIENTS clients[1]; |
288 | | } DCC_ADMN_RESP_VAL; |
289 | | typedef struct { |
290 | | DCC_HDR hdr; |
291 | | DCC_ADMN_RESP_VAL val; |
292 | | DCC_SIGNATURE signature; |
293 | | } DCC_ADMN_RESP; |
294 | | |
295 | | |
296 | | #define DCC_TRACE_ADMN_BIT 0x0001 /* administrative requests */ |
297 | | #define DCC_TRACE_ANON_BIT 0x0002 /* anonymous client errors */ |
298 | | #define DCC_TRACE_CLNT_BIT 0x0004 /* authenticated client errors */ |
299 | | #define DCC_TRACE_RLIM_BIT 0x0008 /* rate limited messages */ |
300 | | #define DCC_TRACE_QUERY_BIT 0x0010 /* all queries and reports */ |
301 | | #define DCC_TRACE_RIDC_BIT 0x0020 /* RID cache messages */ |
302 | | #define DCC_TRACE_FLOD_BIT 0x0040 /* input and output flooding */ |
303 | | /* INFO must always be on */ |
304 | | #define DCC_TRACE_ALL_BITS (DCC_TRACE_ADMN_BIT | DCC_TRACE_ANON_BIT \ |
305 | | | DCC_TRACE_CLNT_BIT | DCC_TRACE_RLIM_BIT \ |
306 | | | DCC_TRACE_QUERY_BIT | DCC_TRACE_RIDC_BIT \ |
307 | | | DCC_TRACE_FLOD_BIT) |
308 | | |
309 | | |
310 | | typedef char DCC_BRAND[64]; |
311 | | |
312 | | /* administrative or NOP ok */ |
313 | | typedef struct { |
314 | | DCC_HDR hdr; |
315 | | unsigned char max_pkt_vers; /* can handle this version */ |
316 | | unsigned char unused; |
317 | | DCC_MS qdelay_ms; |
318 | | DCC_BRAND brand; /* identity or brandname of sender */ |
319 | | DCC_SIGNATURE signature; |
320 | | } DCC_OK; |
321 | | |
322 | | |
323 | | /* a reported checksum from a client */ |
324 | | typedef unsigned char DCC_SUM[16]; /* for now all have 16 bytes */ |
325 | | typedef struct { |
326 | | DCC_CK_TYPE type; |
327 | | unsigned char len; /* total length of this checksum */ |
328 | | DCC_SUM sum; |
329 | | } DCC_CK; |
330 | | |
331 | | typedef uint32_t DCC_TGTS; /* database is limited to 24 bits */ |
332 | | #define DCC_TGTS_TOO_MANY 0x00fffff0 /* >= 16777200 targets */ |
333 | | #define DCC_TGTS_OK 0x00fffff1 /* certified not spam */ |
334 | | #define DCC_TGTS_OK2 0x00fffff2 /* half certified not spam */ |
335 | | #define DCC_TGTS_DEL 0x00fffff3 /* a deleted checksum */ |
336 | | #define DCC_TGTS_INVALID 0x01000000 |
337 | | |
338 | | /* query or query/report packet from client to server */ |
339 | | typedef struct { |
340 | | DCC_HDR hdr; |
341 | | DCC_TGTS tgts; /* # of addressees */ |
342 | 50 | # define DCC_QUERY_MAX DCC_DIM_CKS |
343 | | DCC_CK cks[DCC_QUERY_MAX]; /* even to prevent structure padding */ |
344 | | DCC_SIGNATURE signature; |
345 | | } DCC_QUERY_REPORT; |
346 | | |
347 | | |
348 | | typedef struct { |
349 | | DCC_TGTS tgts[DCC_QUERY_MAX]; /* individual answers */ |
350 | | } DCC_QUERY_RESP_BODY; |
351 | | |
352 | | /* response to a query or query/report */ |
353 | | typedef struct { |
354 | | DCC_HDR hdr; |
355 | | DCC_QUERY_RESP_BODY body; |
356 | | DCC_SIGNATURE signature; |
357 | | } DCC_QUERY_RESP; |
358 | | |
359 | | |
360 | | /* DCC_OP_DELETE request to delete checksums */ |
361 | | typedef struct { |
362 | | DCC_HDR hdr; |
363 | | int32_t date; /* seconds since epoch on caller */ |
364 | | DCC_CK ck; |
365 | | unsigned char pad[2]; /* structure padding */ |
366 | | DCC_SIGNATURE signature; |
367 | | } DCC_DELETE; |
368 | | |
369 | | |
370 | | /* error response from server to client */ |
371 | | typedef struct { |
372 | | DCC_HDR hdr; |
373 | | # define DCC_ERROR_MSG_LEN 128 |
374 | | char msg[DCC_ERROR_MSG_LEN]; |
375 | | DCC_SIGNATURE signature; |
376 | | } DCC_ERROR; |
377 | | |
378 | | |
379 | | /* sender's position or serial number |
380 | | * Only the sender understands sender positions except for these |
381 | | * special values. However, the special values imply that the position |
382 | | * must be big endian. */ |
383 | | typedef unsigned char DCC_FLOD_POS[8]; |
384 | | /* special cases sent by the receiver back to the sender */ |
385 | | #define DCC_FLOD_POS_END 0 /* receiver closing with message */ |
386 | | #define DCC_FLOD_POS_END_REQ 1 /* receiver wants to stop */ |
387 | | #define DCC_FLOD_POS_NOTE 2 /* receiver has a tracing message */ |
388 | | #define DCC_FLOD_POS_COMPLAINT 3 /* receiver has a problem message */ |
389 | | #define DCC_FLOD_POS_REWIND 4 /* receiver's database emptied */ |
390 | | #define DCC_FLOD_POS_MIN 10 |
391 | | |
392 | | #define DCC_FLOD_OK_STR "DCC flod ok: " |
393 | | #define DCC_FLOD_MAX_RESP 200 |
394 | | |
395 | | /* report forwarded among servers */ |
396 | | typedef struct { |
397 | | DCC_FLOD_POS pos; |
398 | | unsigned char tgts[sizeof(DCC_TGTS)]; |
399 | | unsigned char srvr_id_auth[sizeof(DCC_SRVR_ID)]; /* receiving server */ |
400 | | DCC_TS ts; /* date reported */ |
401 | | unsigned char num_cks; |
402 | | DCC_CK cks[DCC_QUERY_MAX]; |
403 | | } DCC_FLOD; |
404 | | |
405 | | /* record of path taken by a report */ |
406 | | #define DCC_NUM_FLOD_PATH ((int)(sizeof(DCC_SUM)/sizeof(DCC_SRVR_ID))) |
407 | | typedef struct { |
408 | | unsigned char hi, lo; |
409 | | } DCC_FLOD_PATH_ID; |
410 | | |
411 | | typedef struct { |
412 | | DCC_FLOD_POS z; |
413 | | char msg[DCC_FLOD_MAX_RESP]; |
414 | | char null; |
415 | | } FLOD_END; |
416 | | typedef struct { |
417 | | DCC_FLOD_POS op; |
418 | | unsigned char len; |
419 | | char str[DCC_FLOD_MAX_RESP]; |
420 | | } FLOD_NOTE; |
421 | | #define FLOD_NOTE_OVHD ((int)sizeof(FLOD_NOTE)-DCC_FLOD_MAX_RESP) |
422 | | |
423 | | #define DCC_FLOD_VERSION_STR_BASE "DCC flod version " |
424 | | #define DCC_FLOD_VERSION5_STR DCC_FLOD_VERSION_STR_BASE"5" |
425 | | #define DCC_FLOD_VERSION5 5 |
426 | | #define DCC_FLOD_VERSION6_STR DCC_FLOD_VERSION_STR_BASE"6" |
427 | | #define DCC_FLOD_VERSION6 6 |
428 | | #define DCC_FLOD_VERSION7_STR DCC_FLOD_VERSION_STR_BASE"7" |
429 | | #define DCC_FLOD_VERSION7 7 |
430 | | #define DCC_FLOD_VERSION_DEF 0 |
431 | | #define DCC_FLOD_VERSION_CUR_STR DCC_FLOD_VERSION7_STR |
432 | | #define DCC_FLOD_VERSION_CUR DCC_FLOD_VERSION7 |
433 | | typedef struct { |
434 | | # define DCC_FLOD_VERSION_STR_LEN 64 |
435 | | char str[DCC_FLOD_VERSION_STR_LEN]; |
436 | | DCC_SRVR_ID sender_srvr_id; |
437 | | unsigned char turn; |
438 | | unsigned char unused[3]; |
439 | | } DCC_FLOD_VERSION_BODY; |
440 | | typedef struct { |
441 | | DCC_FLOD_VERSION_BODY body; |
442 | | char pad[256-sizeof(DCC_FLOD_VERSION_BODY)-sizeof(DCC_SIGNATURE)]; |
443 | | DCC_SIGNATURE signature; |
444 | | } DCC_FLOD_VERSION_HDR; |
445 | | |
446 | | |
447 | | #endif /* DCC_PROTO_H */ |
448 | | |
449 | | |
450 | | |
451 | | |
452 | | |
453 | | |
454 | | |
455 | | |
456 | | /* Lookup string tables */ |
457 | | static const value_string dcc_op_vals[] = { |
458 | | {DCC_OP_INVALID, "Invalid Op"}, |
459 | | {DCC_OP_NOP, "No-Op"}, |
460 | | {DCC_OP_REPORT, "Report and Query"}, |
461 | | {DCC_OP_QUERY, "Query"}, |
462 | | {DCC_OP_QUERY_RESP, "Server Response"}, |
463 | | {DCC_OP_ADMN, "Admin"}, |
464 | | {DCC_OP_OK, "Ok"}, |
465 | | {DCC_OP_ERROR, "Server Failing"}, |
466 | | {DCC_OP_DELETE, "Delete Checksum(s)"}, |
467 | | {0, NULL} |
468 | | }; |
469 | | |
470 | | static const value_string dcc_cktype_vals[] = { |
471 | | {DCC_CK_INVALID, "Invalid/Deleted from DB when seen"}, |
472 | | {DCC_CK_IP, "MD5 of binary source IPv6 address"}, |
473 | | {DCC_CK_ENV_FROM, "MD5 of envelope Mail From value"}, |
474 | | {DCC_CK_FROM, "MD5 of header From: line"}, |
475 | | {DCC_CK_SUB, "MD5 of substitute header line"}, |
476 | | {DCC_CK_MESSAGE_ID, "MD5 of header Message-ID: line"}, |
477 | | {DCC_CK_RECEIVED, "MD5 of last header Received: line"}, |
478 | | {DCC_CK_BODY, "MD5 of body"}, |
479 | | {DCC_CK_FUZ1, "MD5 of filtered body - FUZ1"}, |
480 | | {DCC_CK_FUZ2, "MD5 of filtered body - FUZ2"}, |
481 | | {DCC_CK_FUZ3, "MD5 of filtered body - FUZ3"}, |
482 | | {DCC_CK_FUZ4, "MD5 of filtered body - FUZ4"}, |
483 | | {DCC_CK_SRVR_ID, "hostname for server-ID check "}, |
484 | | {DCC_CK_ENV_TO, "MD5 of envelope Rcpt To value"}, |
485 | | {0, NULL}, |
486 | | }; |
487 | | |
488 | | static const value_string dcc_adminop_vals[] = { |
489 | | {DCC_AOP_OK, "Never sent"}, |
490 | | {DCC_AOP_STOP, "Stop Gracefully"}, |
491 | | {DCC_AOP_NEW_IDS, "Load keys and client IDs"}, |
492 | | {DCC_AOP_FLOD, "Flood control"}, |
493 | | {DCC_AOP_DB_UNLOCK, "Start Switch to new database"}, |
494 | | {DCC_AOP_DB_NEW, "Finish Switch to new database"}, |
495 | | {DCC_AOP_STATS, "Return counters"}, |
496 | | {DCC_AOP_STATS_CLEAR, "Return and zero counters"}, |
497 | | {DCC_AOP_TRACE_ON, "Enable tracing"}, |
498 | | {DCC_AOP_TRACE_OFF, "Disable tracing"}, |
499 | | {DCC_AOP_CUR_CLIENTS, "List clients"}, |
500 | | {0, NULL}, |
501 | | }; |
502 | | |
503 | | static const value_string dcc_target_vals[] = { |
504 | | {DCC_TGTS_TOO_MANY, "Targets (>= 16777200)"}, |
505 | | {DCC_TGTS_OK, "Certified not spam"}, |
506 | | {DCC_TGTS_OK2, "Half certified not spam"}, |
507 | | {DCC_TGTS_DEL, "Deleted checksum"}, |
508 | | {DCC_TGTS_INVALID, "Invalid"}, |
509 | | {0, NULL}, |
510 | | }; |
511 | | |
512 | | static const value_string dcc_floodop_vals[] = { |
513 | | {DCC_AOP_FLOD_CHECK, "Check"}, |
514 | | {DCC_AOP_FLOD_SHUTDOWN, "Shutdown"}, |
515 | | {DCC_AOP_FLOD_HALT, "Halt"}, |
516 | | {DCC_AOP_FLOD_RESUME, "Resume"}, |
517 | | {DCC_AOP_FLOD_REWIND, "Rewind"}, |
518 | | {DCC_AOP_FLOD_LIST, "List"}, |
519 | | {DCC_AOP_FLOD_STATS, "Stats"}, |
520 | | {DCC_AOP_FLOD_STATS_CLEAR, "Clear Stats"}, |
521 | | {0,NULL}, |
522 | | }; |
523 | | |
524 | | static int* const trace_flags[] = { |
525 | | &hf_dcc_trace_admin, |
526 | | &hf_dcc_trace_anon, |
527 | | &hf_dcc_trace_client, |
528 | | &hf_dcc_trace_rlim, |
529 | | &hf_dcc_trace_query, |
530 | | &hf_dcc_trace_ridc, |
531 | | &hf_dcc_trace_flood, |
532 | | NULL |
533 | | }; |
534 | | |
535 | | static int |
536 | | dissect_dcc_pdu(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) |
537 | 23 | { |
538 | 23 | proto_tree *dcc_tree, *dcc_optree, *dcc_opnumtree, *ti; |
539 | 23 | uint32_t packet_length, op; |
540 | 23 | unsigned offset = 0; |
541 | 23 | int client_is_le = 0; |
542 | 23 | int i; |
543 | 23 | bool is_response = (pinfo->srcport == DCC_PORT); |
544 | | |
545 | 23 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCC"); |
546 | | |
547 | 23 | col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", |
548 | 23 | is_response ? "Response" : "Request", |
549 | 23 | val_to_str(pinfo->pool, tvb_get_uint8(tvb, offset+3), |
550 | 23 | dcc_op_vals, "Unknown Op: %u")); |
551 | | |
552 | 23 | ti = proto_tree_add_item(tree, proto_dcc, tvb, offset, -1, ENC_NA); |
553 | 23 | dcc_tree = proto_item_add_subtree(ti, ett_dcc); |
554 | | |
555 | 23 | proto_tree_add_item_ret_uint(dcc_tree, hf_dcc_len, tvb, offset, 2, ENC_BIG_ENDIAN, &packet_length); |
556 | 23 | offset += 2; |
557 | | |
558 | 23 | proto_tree_add_item(dcc_tree, hf_dcc_pkt_vers, tvb, offset, 1, ENC_BIG_ENDIAN); |
559 | 23 | offset += 1; |
560 | | |
561 | 23 | proto_tree_add_item_ret_uint(dcc_tree, hf_dcc_op, tvb, offset, 1, ENC_BIG_ENDIAN, &op); |
562 | 23 | offset += 1; |
563 | | |
564 | 23 | proto_tree_add_item(dcc_tree, hf_dcc_clientid, tvb, offset, 4, ENC_BIG_ENDIAN); |
565 | 23 | offset += 4; |
566 | | |
567 | 23 | dcc_opnumtree = proto_tree_add_subtree(dcc_tree, tvb, offset, -1, ett_dcc_opnums, NULL, "Operation Numbers (Opaque to Server)"); |
568 | | |
569 | | /* Note - these are indeterminate - they are sortof considered opaque to the client */ |
570 | | /* Make some attempt to figure out if this data is little endian, not guaranteed to be |
571 | | correct if connection went through a firewall or similar. */ |
572 | | |
573 | | /* Very hokey check - if all three of pid/report/retrans look like little-endian |
574 | | numbers, host is probably little endian. Probably inaccurate on super-heavily-used |
575 | | DCC clients though. This should be good enough for now. */ |
576 | 23 | client_is_le = (( (tvb_get_uint8(tvb, offset+4) | tvb_get_uint8(tvb, offset+5)) && |
577 | 18 | (tvb_get_uint8(tvb, offset+8) | tvb_get_uint8(tvb, offset+9)) && |
578 | 17 | (tvb_get_uint8(tvb, offset+12) | tvb_get_uint8(tvb, offset+13)) )) ? ENC_LITTLE_ENDIAN : ENC_BIG_ENDIAN; |
579 | | |
580 | 23 | proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_host, tvb, offset, 4, client_is_le); |
581 | 23 | offset += 4; |
582 | | |
583 | 23 | proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_pid, tvb, offset, 4, client_is_le); |
584 | 23 | offset += 4; |
585 | | |
586 | 23 | proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_report, tvb, offset, 4, client_is_le); |
587 | 23 | offset += 4; |
588 | | |
589 | 23 | proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_retrans, tvb, offset, 4, client_is_le); |
590 | 23 | offset += 4; |
591 | | |
592 | 23 | dcc_optree = proto_tree_add_subtree_format(dcc_tree, tvb, offset, -1, ett_dcc_op, NULL, |
593 | 23 | "Operation: %s", val_to_str(pinfo->pool, op, dcc_op_vals, "Unknown Op: %u")); |
594 | | |
595 | 23 | switch(op) { |
596 | 2 | case DCC_OP_NOP: |
597 | 2 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
598 | 2 | break; |
599 | | |
600 | 3 | case DCC_OP_REPORT: |
601 | 3 | proto_tree_add_item(dcc_optree, hf_dcc_target, tvb, offset, (int)sizeof(DCC_TGTS), ENC_BIG_ENDIAN); |
602 | 3 | offset += (int)sizeof(DCC_TGTS); |
603 | | |
604 | 18 | for (i = 0; i <= DCC_QUERY_MAX && (tvb_reported_length_remaining(tvb, offset + sizeof(DCC_SIGNATURE)) > 0); i++) |
605 | 15 | { |
606 | 15 | proto_tree* cktree; |
607 | 15 | cktree = proto_tree_add_subtree_format(dcc_optree, tvb, offset, (int)sizeof(DCC_CK), |
608 | 15 | ett_dcc_ck, NULL, "Checksum - %s", |
609 | 15 | val_to_str(pinfo->pool, tvb_get_uint8(tvb, offset), dcc_cktype_vals, "Unknown Type: %u")); |
610 | 15 | proto_tree_add_item(cktree, hf_dcc_ck_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
611 | 15 | offset += 1; |
612 | 15 | proto_tree_add_item(cktree, hf_dcc_ck_len, tvb, offset, 1, ENC_BIG_ENDIAN); |
613 | 15 | offset += 1; |
614 | 15 | proto_tree_add_item(cktree, hf_dcc_ck_sum, tvb, offset, (int)sizeof(DCC_SUM), ENC_NA); |
615 | 15 | offset += (int)sizeof(DCC_SUM); |
616 | 15 | } |
617 | 3 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
618 | 3 | break; |
619 | | |
620 | 2 | case DCC_OP_QUERY_RESP: |
621 | 32 | for (i=0; i<=DCC_QUERY_MAX && (tvb_reported_length_remaining(tvb, offset+sizeof(DCC_SIGNATURE)) > 0); i++) |
622 | 30 | { |
623 | 30 | proto_tree_add_item(dcc_optree, hf_dcc_target, tvb, offset, (int)sizeof(DCC_TGTS), ENC_BIG_ENDIAN); |
624 | 30 | offset += (int)sizeof(DCC_TGTS); |
625 | 30 | } |
626 | 2 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
627 | 2 | break; |
628 | | |
629 | 6 | case DCC_OP_ADMN: |
630 | 6 | if ( is_response ) |
631 | 6 | { |
632 | 6 | unsigned left_local = tvb_reported_length_remaining(tvb, offset) - (int)sizeof(DCC_SIGNATURE); |
633 | 6 | if ( left_local == sizeof(DCC_ADMN_RESP_CLIENTS) ) |
634 | 0 | { |
635 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_addr, tvb, offset, 16, ENC_NA); |
636 | 0 | offset += 16; |
637 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_id, tvb, offset, (int)sizeof(DCC_CLNT_ID), ENC_BIG_ENDIAN); |
638 | 0 | offset += (int)sizeof(DCC_CLNT_ID); |
639 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_last_used, tvb, offset, 4, ENC_BIG_ENDIAN); |
640 | 0 | offset += 4; |
641 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_requests, tvb, offset, 4, ENC_BIG_ENDIAN); |
642 | 0 | offset += 4; |
643 | 0 | } |
644 | 6 | else |
645 | 6 | { |
646 | 6 | unsigned next_offset, left; |
647 | 24 | while (tvb_reported_length_remaining(tvb, offset+(int)sizeof(DCC_SIGNATURE)) > 0) { |
648 | 18 | left = tvb_reported_length_remaining(tvb,offset) - (int)sizeof(DCC_SIGNATURE); |
649 | 18 | tvb_find_line_end_length(tvb, offset, left, NULL, &next_offset); |
650 | 18 | proto_tree_add_item(dcc_optree, hf_dcc_response_text, tvb, offset, |
651 | 18 | next_offset - offset, ENC_ASCII); |
652 | 18 | offset = next_offset; |
653 | 18 | } |
654 | 6 | } |
655 | 6 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
656 | 6 | } |
657 | 0 | else |
658 | 0 | { |
659 | 0 | uint32_t aop; |
660 | |
|
661 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_date, tvb, offset, 4, ENC_TIME_SECS | ENC_BIG_ENDIAN); |
662 | 0 | offset += 4; |
663 | |
|
664 | 0 | proto_tree_add_item_ret_uint(dcc_optree, hf_dcc_adminop, tvb, offset+4, 1, ENC_BIG_ENDIAN, &aop); |
665 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", |
666 | 0 | val_to_str(pinfo->pool, aop, dcc_adminop_vals, "Unknown (%u)")); |
667 | |
|
668 | 0 | if (aop == DCC_AOP_TRACE_ON || aop == DCC_AOP_TRACE_OFF ) |
669 | 0 | { |
670 | 0 | proto_tree_add_bitmask(dcc_optree, tvb, offset, hf_dcc_trace, ett_dcc_trace, trace_flags, ENC_BIG_ENDIAN); |
671 | 0 | } |
672 | 0 | else if ( aop == DCC_AOP_FLOD ) |
673 | 0 | { |
674 | 0 | uint32_t floodop; |
675 | 0 | proto_tree_add_item_ret_uint(dcc_optree, hf_dcc_floodop, tvb, offset, 4, ENC_BIG_ENDIAN, &floodop); |
676 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", |
677 | 0 | val_to_str(pinfo->pool, floodop, dcc_floodop_vals, "Unknown (%u)")); |
678 | 0 | } |
679 | 0 | else |
680 | 0 | { |
681 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_adminval, tvb, offset, 4, ENC_BIG_ENDIAN); |
682 | 0 | } |
683 | 0 | offset += 4; |
684 | |
|
685 | 0 | offset += 1; /* admin op we did in reverse order */ |
686 | |
|
687 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_pad, tvb, offset, 3, ENC_NA); |
688 | 0 | offset += 3; |
689 | 0 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
690 | 0 | } |
691 | 6 | break; |
692 | | |
693 | 1 | case DCC_OP_OK: |
694 | 1 | proto_tree_add_item(dcc_optree, hf_dcc_max_pkt_vers, tvb, |
695 | 1 | offset, 1, ENC_BIG_ENDIAN); |
696 | 1 | offset += 1; |
697 | | |
698 | 1 | proto_tree_add_item(dcc_optree, hf_dcc_unused, tvb, offset, 1, ENC_NA); |
699 | 1 | offset += 1; |
700 | | |
701 | 1 | proto_tree_add_item(dcc_optree, hf_dcc_qdelay_ms, tvb, offset, 2, ENC_BIG_ENDIAN); |
702 | 1 | offset += 2; |
703 | | |
704 | 1 | proto_tree_add_item(dcc_optree, hf_dcc_brand, tvb, offset, (int)sizeof(DCC_BRAND), ENC_ASCII); |
705 | 1 | offset += (int)sizeof(DCC_BRAND); |
706 | | |
707 | 1 | proto_tree_add_item(dcc_optree, hf_dcc_signature, tvb, offset, (int)sizeof(DCC_SIGNATURE), ENC_NA); |
708 | 1 | break; |
709 | | |
710 | 7 | default: |
711 | | /* do nothing */ |
712 | 7 | break; |
713 | 23 | } |
714 | | |
715 | 13 | return tvb_captured_length(tvb); |
716 | 23 | } |
717 | | |
718 | | static unsigned |
719 | | dissect_dcc_pdu_len(packet_info* pinfo _U_, tvbuff_t* tvb, int offset, void* data _U_) |
720 | 24 | { |
721 | 24 | return tvb_get_ntohs(tvb, offset); |
722 | 24 | } |
723 | | |
724 | | static int |
725 | | dissect_dcc_udp(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree, void* data _U_) |
726 | 15 | { |
727 | 15 | udp_dissect_pdus(tvb, pinfo, tree, sizeof(DCC_HDR), NULL, |
728 | 15 | dissect_dcc_pdu_len, dissect_dcc_pdu, data); |
729 | 15 | return tvb_captured_length(tvb); |
730 | 15 | } |
731 | | |
732 | | void |
733 | | proto_register_dcc(void) |
734 | 16 | { |
735 | 16 | static hf_register_info hf[] = { |
736 | 16 | { &hf_dcc_len, { |
737 | 16 | "Packet Length", "dcc.len", FT_UINT16, BASE_DEC, |
738 | 16 | NULL, 0, NULL, HFILL }}, |
739 | | |
740 | 16 | { &hf_dcc_pkt_vers, { |
741 | 16 | "Packet Version", "dcc.pkt_vers", FT_UINT16, BASE_DEC, |
742 | 16 | NULL, 0, NULL, HFILL }}, |
743 | | |
744 | 16 | { &hf_dcc_op, { |
745 | 16 | "Operation Type", "dcc.op", FT_UINT8, BASE_DEC, |
746 | 16 | VALS(dcc_op_vals), 0, NULL, HFILL }}, |
747 | | |
748 | 16 | { &hf_dcc_clientid, { |
749 | 16 | "Client ID", "dcc.clientid", FT_UINT32, BASE_DEC, |
750 | 16 | NULL, 0, NULL, HFILL }}, |
751 | | |
752 | 16 | { &hf_dcc_opnums_host, { |
753 | 16 | "Host", "dcc.opnums.host", FT_UINT32, BASE_DEC, |
754 | 16 | NULL, 0, NULL, HFILL }}, |
755 | | |
756 | 16 | { &hf_dcc_opnums_pid, { |
757 | 16 | "Process ID", "dcc.opnums.pid", FT_UINT32, BASE_DEC, |
758 | 16 | NULL, 0, NULL, HFILL }}, |
759 | | |
760 | 16 | { &hf_dcc_opnums_report, { |
761 | 16 | "Report", "dcc.opnums.report", FT_UINT32, BASE_DEC, |
762 | 16 | NULL, 0, NULL, HFILL }}, |
763 | | |
764 | 16 | { &hf_dcc_opnums_retrans, { |
765 | 16 | "Retransmission", "dcc.opnums.retrans", FT_UINT32, BASE_DEC, |
766 | 16 | NULL, 0, NULL, HFILL }}, |
767 | | |
768 | 16 | { &hf_dcc_signature, { |
769 | 16 | "Signature", "dcc.signature", FT_BYTES, BASE_NONE, |
770 | 16 | NULL, 0, NULL, HFILL }}, |
771 | | |
772 | 16 | { &hf_dcc_max_pkt_vers, { |
773 | 16 | "Maximum Packet Version", "dcc.max_pkt_vers", FT_UINT8, BASE_DEC, |
774 | 16 | NULL, 0, NULL, HFILL }}, |
775 | | |
776 | 16 | { &hf_dcc_qdelay_ms, { |
777 | 16 | "Client Delay", "dcc.qdelay_ms", FT_UINT16, BASE_DEC, |
778 | 16 | NULL, 0, NULL, HFILL }}, |
779 | | |
780 | 16 | { &hf_dcc_brand, { |
781 | 16 | "Server Brand", "dcc.brand", FT_STRING, BASE_NONE, |
782 | 16 | NULL, 0, NULL, HFILL }}, |
783 | | |
784 | 16 | { &hf_dcc_ck_type, { |
785 | 16 | "Type", "dcc.checksum.type", FT_UINT8, BASE_DEC, |
786 | 16 | VALS(dcc_cktype_vals), 0, "Checksum Type", HFILL }}, |
787 | | |
788 | 16 | { &hf_dcc_ck_len, { |
789 | 16 | "Length", "dcc.checksum.length", FT_UINT8, BASE_DEC, |
790 | 16 | NULL, 0, "Checksum Length", HFILL }}, |
791 | | |
792 | 16 | { &hf_dcc_ck_sum, { |
793 | 16 | "Sum", "dcc.checksum.sum", FT_BYTES, BASE_NONE, |
794 | 16 | NULL, 0, "Checksum", HFILL }}, |
795 | | |
796 | 16 | { &hf_dcc_target, { |
797 | 16 | "Target", "dcc.target", FT_UINT32, BASE_HEX, |
798 | 16 | VALS(dcc_target_vals), 0, NULL, HFILL }}, |
799 | | |
800 | 16 | { &hf_dcc_response_text, { |
801 | 16 | "Response Text", "dcc.response_text", FT_STRING, BASE_NONE, |
802 | 16 | NULL, 0, NULL, HFILL }}, |
803 | | |
804 | 16 | { &hf_dcc_date, { |
805 | 16 | "Date", "dcc.date", FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, |
806 | 16 | NULL, 0, NULL, HFILL }}, |
807 | | |
808 | 16 | { &hf_dcc_adminop, { |
809 | 16 | "Admin Op", "dcc.adminop", FT_UINT8, BASE_DEC, |
810 | 16 | VALS(dcc_adminop_vals), 0, NULL, HFILL }}, |
811 | | |
812 | 16 | { &hf_dcc_adminval, { |
813 | 16 | "Admin Value", "dcc.adminval", FT_UINT32, BASE_DEC, |
814 | 16 | NULL, 0, NULL, HFILL }}, |
815 | | |
816 | 16 | { &hf_dcc_trace, { |
817 | 16 | "Trace Bits", "dcc.trace", FT_UINT32, BASE_HEX, |
818 | 16 | NULL, 0, NULL, HFILL }}, |
819 | | |
820 | 16 | { &hf_dcc_trace_admin, { |
821 | 16 | "Admin Requests", "dcc.trace.admin", FT_BOOLEAN, 32, |
822 | 16 | NULL, 0x00000001, NULL, HFILL }}, |
823 | | |
824 | 16 | { &hf_dcc_trace_anon, { |
825 | 16 | "Anonymous Requests", "dcc.trace.anon", FT_BOOLEAN, 32, |
826 | 16 | NULL, 0x00000002, NULL, HFILL }}, |
827 | | |
828 | 16 | { &hf_dcc_trace_client, { |
829 | 16 | "Authenticated Client Requests", "dcc.trace.client", FT_BOOLEAN, 32, |
830 | 16 | NULL, 0x00000004, NULL, HFILL }}, |
831 | | |
832 | 16 | { &hf_dcc_trace_rlim, { |
833 | 16 | "Rate-Limited Requests", "dcc.trace.rlim", FT_BOOLEAN, 32, |
834 | 16 | NULL, 0x00000008, NULL, HFILL }}, |
835 | | |
836 | 16 | { &hf_dcc_trace_query, { |
837 | 16 | "Queries and Reports", "dcc.trace.query", FT_BOOLEAN, 32, |
838 | 16 | NULL, 0x00000010, NULL, HFILL }}, |
839 | | |
840 | 16 | { &hf_dcc_trace_ridc, { |
841 | 16 | "RID Cache Messages", "dcc.trace.ridc", FT_BOOLEAN, 32, |
842 | 16 | NULL, 0x00000020, NULL, HFILL }}, |
843 | | |
844 | 16 | { &hf_dcc_trace_flood, { |
845 | 16 | "Input/Output Flooding", "dcc.trace.flood", FT_BOOLEAN, 32, |
846 | 16 | NULL, 0x00000040, NULL, HFILL }}, |
847 | | |
848 | 16 | { &hf_dcc_floodop, { |
849 | 16 | "Flood Control Operation", "dcc.floodop", FT_UINT32, BASE_DEC, |
850 | 16 | VALS(dcc_floodop_vals), 0, NULL, HFILL }}, |
851 | | |
852 | 16 | { &hf_dcc_id, { |
853 | 16 | "Id", "dcc.id", FT_UINT32, BASE_DEC, |
854 | 16 | NULL, 0, NULL, HFILL }}, |
855 | | |
856 | 16 | { &hf_dcc_last_used, { |
857 | 16 | "Last Used", "dcc.last_used", FT_UINT32, BASE_DEC, |
858 | 16 | NULL, 0, NULL, HFILL }}, |
859 | | |
860 | 16 | { &hf_dcc_requests, { |
861 | 16 | "Requests", "dcc.requests", FT_UINT32, BASE_DEC, |
862 | 16 | NULL, 0, NULL, HFILL }}, |
863 | | |
864 | 16 | { &hf_dcc_addr, { |
865 | 16 | "Addr", "dcc.addr", FT_BYTES, BASE_NONE, |
866 | 16 | NULL, 0, NULL, HFILL }}, |
867 | | |
868 | 16 | { &hf_dcc_pad, { |
869 | 16 | "Pad", "dcc.pad", FT_BYTES, BASE_NONE, |
870 | 16 | NULL, 0, NULL, HFILL }}, |
871 | | |
872 | 16 | { &hf_dcc_unused, { |
873 | 16 | "Unused", "dcc.unused", FT_BYTES, BASE_NONE, |
874 | 16 | NULL, 0, NULL, HFILL }}, |
875 | 16 | }; |
876 | | |
877 | 16 | static int *ett[] = { |
878 | 16 | &ett_dcc, |
879 | 16 | &ett_dcc_op, |
880 | 16 | &ett_dcc_ck, |
881 | 16 | &ett_dcc_opnums, |
882 | 16 | &ett_dcc_trace, |
883 | 16 | }; |
884 | | |
885 | 16 | proto_dcc = proto_register_protocol("Distributed Checksum Clearinghouse protocol", "DCC", "dcc"); |
886 | | |
887 | 16 | proto_register_field_array(proto_dcc, hf, array_length(hf)); |
888 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
889 | 16 | } |
890 | | |
891 | | void |
892 | | proto_reg_handoff_dcc(void) |
893 | 16 | { |
894 | 16 | dissector_handle_t udp_handle = register_dissector("dcc_udp", dissect_dcc_udp, proto_dcc); |
895 | 16 | dissector_add_uint_with_preference("udp.port", DCC_PORT, udp_handle); |
896 | 16 | } |
897 | | |
898 | | /* |
899 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
900 | | * |
901 | | * Local variables: |
902 | | * c-basic-offset: 8 |
903 | | * tab-width: 8 |
904 | | * indent-tabs-mode: t |
905 | | * End: |
906 | | * |
907 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
908 | | * :indentSize=8:tabSize=8:noTabs=false: |
909 | | */ |