Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-dccp.c
blobc2c1a48d92bf9ec93e9f04722dd06eb44ebeac06
1 /* packet-dccp.c
2 * Routines for Datagram Congestion Control Protocol, "DCCP" dissection:
3 * it should conform to RFC 4340
5 * Copyright 2005 _FF_
7 * Francesco Fondelli <francesco dot fondelli, gmail dot com>
9 * Copyright 2020-2021 by Thomas Dreibholz <dreibh [AT] simula.no>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * Copied from packet-udp.c
17 * SPDX-License-Identifier: GPL-2.0-or-later
20 /* NOTES:
22 * Nov 13, 2006: makes checksum computation dependent
23 * upon the header CsCov field (cf. RFC 4340, 5.1)
24 * (Gerrit Renker)
26 * Nov 13, 2006: removes the case where checksums are zero
27 * (unlike UDP/packet-udp, from which the code stems,
28 * zero checksums are illegal in DCCP (as in TCP))
29 * (Gerrit Renker)
31 * Jan 29, 2007: updates the offsets of the timestamps to be
32 * compliant to (cf. RFC 4342, sec. 13).
33 * (Gerrit Renker)
35 * Mar 11, 2012: add support for RFC 5596 (DCCP-Listen Packet)
36 * (Francesco Fondelli)
38 * Feb 19, 2021: added service code types
39 * (Thomas Dreibholz)
41 * Nov 16, 2022: added MP-DCCP support
42 * (Gregorio Maglione)
46 #include "config.h"
48 #include <epan/packet.h>
49 #include <epan/addr_resolv.h>
50 #include <epan/dccpservicecodes.h>
51 #include <epan/ipproto.h>
52 #include <epan/in_cksum.h>
53 #include <epan/prefs.h>
54 #include <epan/follow.h>
55 #include <epan/expert.h>
56 #include <epan/conversation.h>
57 #include <epan/conversation_table.h>
58 #include <epan/conversation_filter.h>
59 #include <epan/tap.h>
60 #include <epan/unit_strings.h>
62 #include <wsutil/str_util.h>
64 #include "packet-dccp.h"
67 * Some definitions and the dissect_options() logic have been taken
68 * from Arnaldo Carvalho de Melo's DCCP implementation, thanks!
70 #define DCCP_GEN_HDR_LEN_NO_X 12 /* generic header length, without extended sequence numbers */
71 #define DCCP_GEN_HDR_LEN_X 16 /* generic header length, with extended sequence numbers */
72 #define DCCP_HDR_LEN 16 /* base DCCP header length, with 48 bits seqnums */
73 #define DCCP_HDR_LEN_MIN 12 /* with 24 bits seqnum */
74 #define DCCP_HDR_PKT_TYPES_LEN_MAX 12 /* max per packet type extra
75 * header length
77 #define DCCP_OPT_LEN_MAX 1008
78 #define DCCP_HDR_LEN_MAX (DCCP_HDR_LEN + DCCP_HDR_PKT_TYPES_LEN_MAX + \
79 DCCP_OPT_LEN_MAX)
81 /* Static DCCP flags. Set in dccp_flow_t:static_flags */
82 #define DCCP_S_BASE_SEQ_SET 0x01
84 void proto_register_dccp(void);
85 void proto_reg_handoff_dccp(void);
87 static dissector_handle_t dccp_handle;
90 * FF: please keep this list in sync with
91 * http://www.iana.org/assignments/dccp-parameters/dccp-parameters.xml
92 * Registry Name: 'Packet Types'
94 static const value_string dccp_packet_type_vals[] = {
95 {0x0, "Request" },
96 {0x1, "Response"},
97 {0x2, "Data" },
98 {0x3, "Ack" },
99 {0x4, "DataAck" },
100 {0x5, "CloseReq"},
101 {0x6, "Close" },
102 {0x7, "Reset" },
103 {0x8, "Sync" },
104 {0x9, "SyncAck" },
105 {0xA, "Listen" },
106 {0xB, "Reserved"},
107 {0xC, "Reserved"},
108 {0xD, "Reserved"},
109 {0xE, "Reserved"},
110 {0xF, "Reserved"},
111 {0, NULL }
115 * Based on https://www.iana.org/assignments/service-codes/service-codes.xhtml
116 * as of February 19th, 2021
118 static const value_string dccp_service_code_vals[] = {
119 { NOT_SPECIFIED_SERVICE_CODE, "not specified" },
120 { LTP_SERVICE_CODE, "LTP: Licklider Transmission Protocol" },
121 { DISC_SERVICE_CODE, "DISC: Discard" },
122 { RTCP_SERVICE_CODE, "RTCP: RTCP connection, separate from the corresponding RTP" },
123 { RTPA_SERVICE_CODE, "RTPA: RTP session conveying audio data (and associated RTCP)" },
124 { RTPO_SERVICE_CODE, "RTPO: RTP session conveying other media (and associated RTCP)" },
125 { RTPT_SERVICE_CODE, "RTPT: RTP session conveying text media (and associated RTCP)" },
126 { RTPV_SERVICE_CODE, "RTPV: RTP session conveying video data (and associated RTCP)" },
127 { SYLG_SERVICE_CODE, "SYLG: Syslog Protocol" },
128 { BUNDLES_SERVICE_CODE, "Bundle Protocol" },
129 { NPMP_SERVICE_CODE, "NPMP: NetPerfMeter Data" },
130 { RESERVED_SERVICE_CODE, "Reserved (Invalid)" },
132 { 0, NULL } };
134 static const value_string dccp_reset_code_vals[] = {
135 {0x00, "Unspecified" },
136 {0x01, "Closed" },
137 {0x02, "Aborted" },
138 {0x03, "No Connection" },
139 {0x04, "Packet Error" },
140 {0x05, "Option Error" },
141 {0x06, "Mandatory Error" },
142 {0x07, "Connection Refused"},
143 {0x08, "Bad Service Code" },
144 {0x09, "Too Busy" },
145 {0x0A, "Bad Init Cookie" },
146 {0x0B, "Aggression Penalty"},
147 {0x0C, "Reserved" },
148 {0, NULL }
151 static const range_string dccp_options_rvals[] = {
152 {0x00, 0x00, "Padding" },
153 {0x01, 0x01, "Mandatory" },
154 {0x02, 0x02, "Slow Receiver" },
155 {0x03, 0x1F, "Reserved"},
156 {0x20, 0x20, "Change L" },
157 {0x21, 0x21, "Confirm L"},
158 {0x22, 0x22, "Change R" },
159 {0x23, 0x23, "Confirm R"},
160 {0x24, 0x24, "Init Cookie"},
161 {0x25, 0x25, "NDP Count"},
162 {0x26, 0x26, "Ack Vector [Nonce 0]"},
163 {0x27, 0x27, "Ack Vector [Nonce 1]"},
164 {0x28, 0x28, "Data Dropped"},
165 {0x29, 0x29, "Timestamp"},
166 {0x2A, 0x2A, "Timestamp Echo"},
167 {0x2B, 0x2B, "Elapsed Time"},
168 {0x2C, 0x2C, "Data checksum"},
169 {0x2D, 0x2D, "Quick-Start Response"},
170 {0x2E, 0x2E, "Multipath"},
171 {0x2F, 0x7F, "Reserved"},
172 {0x80, 0xBF, "CCID option"},
173 {0xC0, 0xC0, "CCID3 Loss Event Rate"},
174 {0xC1, 0xC1, "CCID3 Loss Intervals"},
175 {0xC2, 0xC2, "CCID3 Receive Rate"},
176 {0xC3, 0xFF, "CCID option"},
177 {0, 0, NULL}
180 static const range_string dccp_feature_numbers_rvals[] = {
181 {0x00, 0x00, "Reserved" },
182 {0x01, 0x01, "Congestion Control ID (CCID)" },
183 {0x02, 0x02, "Allow Short Seqnums" },
184 {0x03, 0x03, "Sequence Window" },
185 {0x04, 0x04, "ECN Incapable" },
186 {0x05, 0x05, "Ack Ratio" },
187 {0x06, 0x06, "Send Ack Vector" },
188 {0x07, 0x07, "Send NDP Count" },
189 {0x08, 0x08, "Minimum Checksum Coverage" },
190 {0x09, 0x09, "Check Data Checksum" },
191 {0x0A, 0x0A, "MP_CAPABLE" },
192 {0x03, 0x7F, "Reserved"},
193 {0xC0, 0xC0, "Send Loss Event Rate"}, /* CCID3, RFC 4342, 8.5 */
194 {0xC1, 0xFF, "CCID-specific feature"},
195 {0, 0, NULL}
198 static int proto_dccp;
199 static int dccp_tap;
200 static int dccp_follow_tap;
202 static int hf_dccp_srcport;
203 static int hf_dccp_dstport;
204 static int hf_dccp_port;
205 static int hf_dccp_stream;
206 static int hf_dccp_data_offset;
207 static int hf_dccp_ccval;
208 static int hf_dccp_cscov;
209 static int hf_dccp_checksum;
210 static int hf_dccp_checksum_status;
211 static int hf_dccp_res1;
212 static int hf_dccp_type;
213 static int hf_dccp_x;
214 static int hf_dccp_res2;
215 static int hf_dccp_seq;
216 static int hf_dccp_seq_abs;
218 static int hf_dccp_ack_res;
219 static int hf_dccp_ack;
220 static int hf_dccp_ack_abs;
222 static int hf_dccp_service_code;
223 static int hf_dccp_reset_code;
224 static int hf_dccp_data1;
225 static int hf_dccp_data2;
226 static int hf_dccp_data3;
228 static int hf_dccp_options;
229 static int hf_dccp_option_type;
230 static int hf_dccp_feature_number;
231 static int hf_dccp_ndp_count;
232 static int hf_dccp_timestamp;
233 static int hf_dccp_timestamp_echo;
234 static int hf_dccp_elapsed_time;
235 static int hf_dccp_data_checksum;
237 /* MP-DCCP Option fields */
238 static int hf_mpdccp_confirm;
240 static int hf_mpdccp_version;
242 static int hf_mpdccp_join;
243 static int hf_mpdccp_join_id;
244 static int hf_mpdccp_join_token;
245 static int hf_mpdccp_join_nonce;
247 static int hf_mpdccp_fast_close;
249 static int hf_mpdccp_key;
250 static int hf_mpdccp_key_type;
251 static int hf_mpdccp_key_key;
253 static int hf_mpdccp_seq;
255 static int hf_mpdccp_hmac;
256 static int hf_mpdccp_hmac_sha;
258 static int hf_mpdccp_rtt;
259 static int hf_mpdccp_rtt_type;
260 static int hf_mpdccp_rtt_value;
261 static int hf_mpdccp_rtt_age;
263 static int hf_mpdccp_addaddr;
264 static int hf_mpdccp_addrid;
265 //static int hf_mpdccp_addr;
266 static int hf_mpdccp_addr_dec;
267 static int hf_mpdccp_addr_hex;
268 static int hf_mpdccp_addrport;
270 static int hf_mpdccp_removeaddr;
272 static int hf_mpdccp_prio;
273 static int hf_mpdccp_prio_value;
275 static int hf_mpdccp_close;
276 static int hf_mpdccp_close_key;
278 static int hf_mpdccp_exp;
280 static int hf_dccp_option_data;
282 /* Generated from convert_proto_tree_add_text.pl */
283 static int hf_dccp_padding;
284 static int hf_dccp_mandatory;
285 static int hf_dccp_slow_receiver;
286 static int hf_dccp_init_cookie;
287 static int hf_dccp_ack_vector_nonce_0;
288 static int hf_dccp_ack_vector_nonce_1;
289 static int hf_dccp_data_dropped;
290 static int hf_dccp_ccid3_loss_event_rate;
291 static int hf_dccp_ccid3_loss_intervals;
292 static int hf_dccp_ccid3_receive_rate;
293 static int hf_dccp_option_reserved;
294 static int hf_dccp_ccid_option_data;
295 static int hf_dccp_option_unknown;
297 static int ett_dccp;
298 static int ett_dccp_options;
299 static int ett_dccp_options_item;
300 static int ett_dccp_feature;
302 static expert_field ei_dccp_option_len_bad;
303 static expert_field ei_dccp_advertised_header_length_bad;
304 static expert_field ei_dccp_packet_type_reserved;
305 static expert_field ei_dccp_checksum;
307 static dissector_table_t dccp_subdissector_table;
308 static heur_dissector_list_t heur_subdissector_list;
310 /* preferences */
311 static bool dccp_summary_in_tree = true;
312 static bool try_heuristic_first;
313 static bool dccp_check_checksum = true;
314 static bool dccp_relative_seq = true;
315 static uint32_t dccp_stream_count;
317 static void
318 decode_dccp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
319 proto_tree *tree, int sport, int dport)
321 tvbuff_t *next_tvb;
322 int low_port, high_port;
323 heur_dtbl_entry_t *hdtbl_entry;
325 next_tvb = tvb_new_subset_remaining(tvb, offset);
327 /* If the user has a "Follow DCCP Stream" window loading, pass a pointer
328 to the payload tvb through the tap system. */
329 if (have_tap_listener(dccp_follow_tap))
330 tap_queue_packet(dccp_follow_tap, pinfo, next_tvb);
333 * determine if this packet is part of a conversation and call dissector
334 * for the conversation if available
336 if (try_conversation_dissector(&pinfo->src, &pinfo->dst, CONVERSATION_DCCP, sport,
337 dport, next_tvb, pinfo, tree, NULL, 0)) {
338 return;
341 if (try_heuristic_first) {
342 /* do lookup with the heuristic subdissector table */
343 if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo,
344 tree, &hdtbl_entry, NULL)) {
345 return;
350 * Do lookups with the subdissector table.
351 * We try the port number with the lower value first, followed by the
352 * port number with the higher value. This means that, for packets
353 * where a dissector is registered for *both* port numbers:
355 * 1) we pick the same dissector for traffic going in both directions;
357 * 2) we prefer the port number that's more likely to be the right
358 * one (as that prefers well-known ports to reserved ports);
360 * although there is, of course, no guarantee that any such strategy
361 * will always pick the right port number.
362 * XXX - we ignore port numbers of 0, as some dissectors use a port
363 * number of 0 to disable the port.
365 if (sport > dport) {
366 low_port = dport;
367 high_port = sport;
368 } else {
369 low_port = sport;
370 high_port = dport;
373 if (low_port != 0 &&
374 dissector_try_uint(dccp_subdissector_table, low_port,
375 next_tvb, pinfo, tree)) {
376 return;
379 if (high_port != 0 &&
380 dissector_try_uint(dccp_subdissector_table, high_port,
381 next_tvb, pinfo, tree)) {
382 return;
385 if (!try_heuristic_first) {
386 /* do lookup with the heuristic subdissector table */
387 if (dissector_try_heuristic(heur_subdissector_list, next_tvb,
388 pinfo, tree, &hdtbl_entry, NULL)) {
389 return;
393 /* Oh, well, we don't know this; dissect it as data. */
394 call_data_dissector(next_tvb, pinfo, tree);
397 /* Conversation and process code originally copied from packet-udp.c */
398 static struct dccp_analysis *
399 init_dccp_conversation_data(packet_info *pinfo)
401 struct dccp_analysis *dccpd;
403 /* Initialize the dccp protocol data structure to add to the dccp conversation */
404 dccpd = wmem_new0(wmem_file_scope(), struct dccp_analysis);
405 dccpd->flow1.static_flags = 0;
406 dccpd->flow1.base_seq = 0;
407 dccpd->flow2.static_flags = 0;
408 dccpd->flow2.base_seq = 0;
410 dccpd->stream = dccp_stream_count++;
411 dccpd->ts_first = pinfo->abs_ts;
412 dccpd->ts_prev = pinfo->abs_ts;
414 return dccpd;
417 static struct dccp_analysis *
418 get_dccp_conversation_data(conversation_t *conv, packet_info *pinfo)
420 int direction;
421 struct dccp_analysis *dccpd;
423 /* Get the data for this conversation */
424 dccpd=(struct dccp_analysis *)conversation_get_proto_data(conv, proto_dccp);
426 /* If the conversation was just created or it matched a
427 * conversation with template options, dccpd will not
428 * have been initialized. So, initialize
429 * a new dccpd structure for the conversation.
431 if (!dccpd) {
432 dccpd = init_dccp_conversation_data(pinfo);
433 conversation_add_proto_data(conv, proto_dccp, dccpd);
436 /* check direction and get ua lists */
437 direction=cmp_address(&pinfo->src, &pinfo->dst);
438 /* if the addresses are equal, match the ports instead */
439 if (direction == 0) {
440 direction= (pinfo->srcport > pinfo->destport) ? 1 : -1;
442 if (direction >= 0) {
443 dccpd->fwd=&(dccpd->flow1);
444 dccpd->rev=&(dccpd->flow2);
445 } else {
446 dccpd->fwd=&(dccpd->flow2);
447 dccpd->rev=&(dccpd->flow1);
450 return dccpd;
453 static const char* dccp_conv_get_filter_type(conv_item_t* conv, conv_filter_type_e filter)
455 if (filter == CONV_FT_SRC_PORT)
456 return "dccp.srcport";
458 if (filter == CONV_FT_DST_PORT)
459 return "dccp.dstport";
461 if (filter == CONV_FT_ANY_PORT)
462 return "dccp.port";
464 if(!conv) {
465 return CONV_FILTER_INVALID;
468 if (filter == CONV_FT_SRC_ADDRESS) {
469 if (conv->src_address.type == AT_IPv4)
470 return "ip.src";
471 if (conv->src_address.type == AT_IPv6)
472 return "ipv6.src";
475 if (filter == CONV_FT_DST_ADDRESS) {
476 if (conv->dst_address.type == AT_IPv4)
477 return "ip.dst";
478 if (conv->dst_address.type == AT_IPv6)
479 return "ipv6.dst";
482 if (filter == CONV_FT_ANY_ADDRESS) {
483 if (conv->src_address.type == AT_IPv4)
484 return "ip.addr";
485 if (conv->src_address.type == AT_IPv6)
486 return "ipv6.addr";
489 return CONV_FILTER_INVALID;
492 static ct_dissector_info_t dccp_ct_dissector_info = {&dccp_conv_get_filter_type};
494 static tap_packet_status
495 dccpip_conversation_packet(void *pct, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags)
497 conv_hash_t *hash = (conv_hash_t*) pct;
498 hash->flags = flags;
499 const e_dccphdr *dccphdr=(const e_dccphdr *)vip;
501 add_conversation_table_data_with_conv_id(hash, &dccphdr->ip_src, &dccphdr->ip_dst, dccphdr->sport, dccphdr->dport, (conv_id_t) dccphdr->stream, 1, pinfo->fd->pkt_len, &pinfo->rel_ts, &pinfo->abs_ts, &dccp_ct_dissector_info, CONVERSATION_DCCP);
503 return TAP_PACKET_REDRAW;
506 static const char* dccp_endpoint_get_filter_type(endpoint_item_t* endpoint, conv_filter_type_e filter)
509 if (filter == CONV_FT_SRC_PORT)
510 return "dccp.srcport";
512 if (filter == CONV_FT_DST_PORT)
513 return "dccp.dstport";
515 if (filter == CONV_FT_ANY_PORT)
516 return "dccp.port";
518 if(!endpoint) {
519 return CONV_FILTER_INVALID;
523 if (filter == CONV_FT_SRC_ADDRESS) {
524 if (endpoint->myaddress.type == AT_IPv4)
525 return "ip.src";
526 if (endpoint->myaddress.type == AT_IPv6)
527 return "ipv6.src";
530 if (filter == CONV_FT_DST_ADDRESS) {
531 if (endpoint->myaddress.type == AT_IPv4)
532 return "ip.dst";
533 if (endpoint->myaddress.type == AT_IPv6)
534 return "ipv6.dst";
537 if (filter == CONV_FT_ANY_ADDRESS) {
538 if (endpoint->myaddress.type == AT_IPv4)
539 return "ip.addr";
540 if (endpoint->myaddress.type == AT_IPv6)
541 return "ipv6.addr";
544 return CONV_FILTER_INVALID;
547 static et_dissector_info_t dccp_endpoint_dissector_info = {&dccp_endpoint_get_filter_type};
549 static tap_packet_status
550 dccpip_endpoint_packet(void *pit, packet_info *pinfo, epan_dissect_t *edt _U_, const void *vip, tap_flags_t flags )
552 conv_hash_t *hash = (conv_hash_t*) pit;
553 hash->flags = flags;
554 const e_dccphdr *dccphdr=(const e_dccphdr *)vip;
556 /* Take two "add" passes per packet, adding for each direction, ensures that all
557 packets are counted properly (even if address is sending to itself)
558 XXX - this could probably be done more efficiently inside endpoint_table */
559 add_endpoint_table_data(hash, &dccphdr->ip_src, dccphdr->sport, true, 1, pinfo->fd->pkt_len, &dccp_endpoint_dissector_info, ENDPOINT_DCCP);
560 add_endpoint_table_data(hash, &dccphdr->ip_dst, dccphdr->dport, false, 1, pinfo->fd->pkt_len, &dccp_endpoint_dissector_info, ENDPOINT_DCCP);
562 return TAP_PACKET_REDRAW;
565 /* Return the current stream count */
566 uint32_t get_dccp_stream_count(void)
568 return dccp_stream_count;
571 static bool
572 dccp_filter_valid(packet_info *pinfo, void *user_data _U_)
574 return proto_is_frame_protocol(pinfo->layers, "dccp");
577 static char*
578 dccp_build_filter(packet_info *pinfo, void *user_data _U_)
580 if( pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4 ) {
581 /* DCCP over IPv4 */
582 return ws_strdup_printf("(ip.addr eq %s and ip.addr eq %s) and (dccp.port eq %d and dccp.port eq %d)",
583 address_to_str(pinfo->pool, &pinfo->net_src),
584 address_to_str(pinfo->pool, &pinfo->net_dst),
585 pinfo->srcport, pinfo->destport );
588 if( pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6 ) {
589 /* DCCP over IPv6 */
590 return ws_strdup_printf("(ipv6.addr eq %s and ipv6.addr eq %s) and (dccp.port eq %d and dccp.port eq %d)",
591 address_to_str(pinfo->pool, &pinfo->net_src),
592 address_to_str(pinfo->pool, &pinfo->net_dst),
593 pinfo->srcport, pinfo->destport );
596 return NULL;
599 static char *dccp_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream _U_)
601 conversation_t *conv;
602 struct dccp_analysis *dccpd;
604 /* XXX: Since DCCP doesn't use the endpoint API, we can only look
605 * up using the current pinfo addresses and ports. We don't want
606 * to create a new conversation or stream.
607 * Eventually the endpoint API should support storing multiple
608 * endpoints and DCCP should be changed to use the endpoint API.
610 if (((pinfo->net_src.type == AT_IPv4 && pinfo->net_dst.type == AT_IPv4) ||
611 (pinfo->net_src.type == AT_IPv6 && pinfo->net_dst.type == AT_IPv6))
612 && (pinfo->ptype == PT_DCCP) &&
613 (conv=find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, CONVERSATION_DCCP, pinfo->srcport, pinfo->destport, 0)) != NULL)
615 /* DCCP over IPv4/6 */
616 dccpd = get_dccp_conversation_data(conv, pinfo);
617 *stream = dccpd->stream;
618 return ws_strdup_printf("dccp.stream eq %u", dccpd->stream);
621 return NULL;
624 static char *dccp_follow_index_filter(unsigned stream, unsigned sub_stream _U_)
626 return ws_strdup_printf("dccp.stream eq %u", stream);
629 static char *dccp_follow_address_filter(address *src_addr, address *dst_addr, int src_port, int dst_port)
631 const char *ip_version = src_addr->type == AT_IPv6 ? "v6" : "";
632 char src_addr_str[WS_INET6_ADDRSTRLEN];
633 char dst_addr_str[WS_INET6_ADDRSTRLEN];
635 address_to_str_buf(src_addr, src_addr_str, sizeof(src_addr_str));
636 address_to_str_buf(dst_addr, dst_addr_str, sizeof(dst_addr_str));
638 return ws_strdup_printf("((ip%s.src eq %s and dccp.srcport eq %d) and "
639 "(ip%s.dst eq %s and dccp.dstport eq %d))"
640 " or "
641 "((ip%s.src eq %s and dccp.srcport eq %d) and "
642 "(ip%s.dst eq %s and dccp.dstport eq %d))",
643 ip_version, src_addr_str, src_port,
644 ip_version, dst_addr_str, dst_port,
645 ip_version, dst_addr_str, dst_port,
646 ip_version, src_addr_str, src_port);
650 * decode a variable-length number of nbytes starting at offset. Based on
651 * a concept by Arnaldo de Melo
653 static uint64_t
654 dccp_ntoh_var(tvbuff_t *tvb, int offset, unsigned nbytes)
656 uint64_t value = 0;
658 switch (nbytes)
660 case 5:
661 value = tvb_get_ntoh40(tvb, offset);
662 break;
663 case 4:
664 value = tvb_get_ntohl(tvb, offset);
665 break;
666 case 3:
667 value = tvb_get_ntoh24(tvb, offset);
668 break;
669 case 2:
670 value = tvb_get_ntohs(tvb, offset);
671 break;
672 case 1:
673 value = tvb_get_uint8(tvb, offset);
674 break;
675 case 0:
676 // do nothing
677 break;
678 case 6:
679 default:
680 value = tvb_get_ntoh48(tvb, offset);
681 break;
684 return value;
687 static void
688 dissect_feature_options(proto_tree *dccp_options_tree, tvbuff_t *tvb,
689 int offset, uint8_t option_len)
691 uint8_t feature_number = tvb_get_uint8(tvb, offset);
692 proto_item *dccp_item;
693 proto_tree *feature_tree;
694 int i;
696 feature_tree =
697 proto_tree_add_subtree_format(dccp_options_tree, tvb, offset, option_len,
698 ett_dccp_feature, &dccp_item, "%s(",
699 rval_to_str_const(feature_number, dccp_feature_numbers_rvals, "Unknown feature number"));
700 if (feature_number != 10)
701 proto_tree_add_uint(feature_tree, hf_dccp_feature_number, tvb,
702 offset, 1, feature_number);
703 else
704 proto_tree_add_item(feature_tree, hf_mpdccp_version, tvb,
705 offset, option_len, ENC_BIG_ENDIAN);
706 offset++;
707 option_len--;
710 * decode the feature according to whether it is server-priority (list)
711 * or NN (single number)
713 switch (feature_number) {
715 /* Server Priority features (RFC 4340, 6.3.1) */
716 case 1: /* Congestion Control ID (CCID); fall through */
717 case 2: /* Allow Short Seqnums; fall through */
718 case 4: /* ECN Incapable; fall through */
719 case 6: /* Send Ack Vector; fall through */
720 case 7: /* Send NDP Count; fall through */
721 case 8: /* Minimum Checksum Coverage; fall through */
722 case 9: /* Check Data Checksum; fall through */
723 case 192: /* Send Loss Event Rate, RFC 4342, section 8.4 */
724 for (i = 0; i < option_len; i++)
725 proto_item_append_text(dccp_item, "%s %d", i ? "," : "",
726 tvb_get_uint8(tvb,
727 offset + i));
728 break;
730 /* Non-negotiable features (RFC 4340, 6.3.2) */
732 case 3: /* Sequence Window; fall through */
733 case 5: /* Ack Ratio */
735 if (option_len > 0) /* could be empty Confirm */
736 proto_item_append_text(dccp_item, " %" PRIu64,
737 dccp_ntoh_var(tvb, offset, option_len));
738 break;
740 /* Reserved, specific, or unknown features */
741 case 10: /* MP_CAPABLE; fall through */
742 for (i = 0; i < option_len; i++)
743 proto_item_append_text(dccp_item, "%s %d", i ? "," : "", feature_number);
744 break;
745 default:
746 proto_item_append_text(dccp_item, "%d", feature_number);
747 break;
749 proto_item_append_text(dccp_item, ")");
753 * This function dissects DCCP options
755 static void
756 // NOLINTNEXTLINE(misc-no-recursion)
757 dissect_options(tvbuff_t *tvb, packet_info *pinfo,
758 proto_tree *dccp_options_tree, proto_tree *tree _U_,
759 e_dccphdr *dccph _U_,
760 int offset_start,
761 int offset_end)
764 * if here I'm sure there is at least offset_end - offset_start bytes
765 * in tvb and it should be options
767 int offset = offset_start;
768 uint8_t option_type = 0;
769 uint8_t option_len = 0;
770 uint32_t p;
771 uint8_t mp_option_type = 0;
773 proto_item *option_item;
774 proto_tree *option_tree;
775 proto_item *mp_option_sub_item;
776 proto_tree *mp_option_sub_tree;
778 while (offset < offset_end) {
779 /* first byte is the option type */
780 option_type = tvb_get_uint8(tvb, offset);
781 option_item =
782 proto_tree_add_uint(dccp_options_tree, hf_dccp_option_type, tvb,
783 offset,
785 option_type);
786 if (option_type >= 32) { /* variable length options */
787 option_len = tvb_get_uint8(tvb, offset+1);
789 if (option_len < 2) {
790 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
791 "Option length incorrect, must be >= 2");
792 return;
795 proto_item_set_len(option_item, option_len);
796 /* Remove the type and length fields out of length */
797 offset += 2;
798 option_len -= 2;
799 } else { /* 1byte options */
800 option_len = 1;
803 option_tree = proto_item_add_subtree(option_item, ett_dccp_options_item);
804 switch (option_type) {
805 case 0:
806 proto_tree_add_item(option_tree, hf_dccp_padding, tvb, offset, option_len, ENC_NA);
807 break;
808 case 1:
809 proto_tree_add_item(option_tree, hf_dccp_mandatory, tvb, offset, option_len, ENC_NA);
810 break;
811 case 2:
812 proto_tree_add_item(option_tree, hf_dccp_slow_receiver, tvb, offset, option_len, ENC_NA);
813 break;
814 case 32:
815 case 33:
816 case 34:
817 case 35:
818 dissect_feature_options(option_tree, tvb, offset, option_len);
819 break;
820 case 36:
821 proto_tree_add_item(option_tree, hf_dccp_init_cookie, tvb, offset, option_len, ENC_NA);
822 break;
823 case 37:
824 if (option_len > 6)
825 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
826 "NDP Count too long (max 6 bytes)");
827 else
828 proto_tree_add_item(option_tree, hf_dccp_ndp_count, tvb, offset, option_len, ENC_BIG_ENDIAN);
829 break;
830 case 38:
831 proto_tree_add_item(option_tree, hf_dccp_ack_vector_nonce_0, tvb, offset, option_len, ENC_NA);
832 break;
833 case 39:
834 proto_tree_add_item(option_tree, hf_dccp_ack_vector_nonce_1, tvb, offset, option_len, ENC_NA);
835 break;
836 case 40:
837 proto_tree_add_item(option_tree, hf_dccp_data_dropped, tvb, offset, option_len, ENC_NA);
838 break;
839 case 41:
840 if (option_len == 4)
841 proto_tree_add_item(option_tree, hf_dccp_timestamp, tvb,
842 offset, 4, ENC_BIG_ENDIAN);
843 else
844 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
845 "Timestamp too long [%u != 4]", option_len);
846 break;
847 case 42:
848 if (option_len == 4)
849 proto_tree_add_item(option_tree, hf_dccp_timestamp_echo,
850 tvb, offset, 4, ENC_BIG_ENDIAN);
851 else if (option_len == 6) {
852 proto_tree_add_item(option_tree, hf_dccp_timestamp_echo,
853 tvb, offset, 4, ENC_BIG_ENDIAN);
854 proto_tree_add_item(option_tree, hf_dccp_elapsed_time,
855 tvb, offset + 4, 2, ENC_BIG_ENDIAN);
856 } else if (option_len == 8) {
857 proto_tree_add_item(option_tree, hf_dccp_timestamp_echo,
858 tvb, offset, 4, ENC_BIG_ENDIAN);
859 proto_tree_add_item(option_tree, hf_dccp_elapsed_time,
860 tvb, offset + 4, 4, ENC_BIG_ENDIAN);
861 } else
862 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
863 "Wrong Timestamp Echo length");
864 break;
865 case 43:
866 if (option_len == 2)
867 proto_tree_add_item(option_tree, hf_dccp_elapsed_time,
868 tvb, offset, 2, ENC_BIG_ENDIAN);
869 else if (option_len == 4)
870 proto_tree_add_item(option_tree, hf_dccp_elapsed_time,
871 tvb, offset, 4, ENC_BIG_ENDIAN);
872 else
873 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
874 "Wrong Elapsed Time length");
875 break;
876 case 44:
877 if (option_len == 4) {
878 proto_tree_add_item(option_tree, hf_dccp_data_checksum,
879 tvb, offset, 4, ENC_BIG_ENDIAN);
880 } else
881 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
882 "Wrong Data checksum length");
883 break;
884 case 46:
885 mp_option_type = tvb_get_uint8(tvb, offset);
886 option_len -= 1;
887 switch (mp_option_type) {
888 case 0:
889 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_confirm, tvb, offset, 1, ENC_BIG_ENDIAN);
890 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
891 offset += 1;
892 // We recurse here, but we'll run out of packet before we run out of stack.
893 dissect_options(tvb, pinfo, mp_option_sub_tree, tree, dccph, offset, offset + option_len);
894 break;
895 case 1:
896 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_join, tvb, offset, 1, ENC_BIG_ENDIAN);
897 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
898 offset += 1;
899 if (option_len == 9) {
900 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_id, tvb, offset, 1, ENC_BIG_ENDIAN);
901 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_token, tvb, offset+1, 4, ENC_BIG_ENDIAN);
902 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_join_nonce, tvb, offset+5, 4, ENC_BIG_ENDIAN);
903 } else {
904 mp_option_sub_item = proto_tree_add_item(option_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
905 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
906 "Wrong Data checksum length, [%u != 9]", option_len);
908 break;
909 case 2:
910 proto_tree_add_item(option_tree, hf_mpdccp_fast_close, tvb, offset, option_len, ENC_NA);
911 break;
912 case 3:
913 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_key, tvb, offset, 1, ENC_NA);
914 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
915 offset += 1;
916 if (option_len > 8 && option_len < 69) {
917 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_key_type, tvb, offset, 1, ENC_BIG_ENDIAN);
918 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_key_key, tvb, offset+1, option_len-1, ENC_NA);
919 } else {
920 mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
921 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
922 "Wrong Data checksum length, [8 < %u < 69]", option_len);
924 break;
925 case 4:
926 if (option_len == 6) {
927 offset += 1;
928 proto_tree_add_item(option_tree, hf_mpdccp_seq, tvb, offset, 6, ENC_BIG_ENDIAN);
929 } else {
930 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_seq, tvb, offset, option_len, ENC_BIG_ENDIAN);
931 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
932 "Wrong Data checksum length, [%u != 6]", option_len);
934 break;
935 case 5:
936 if (option_len == 20) {
937 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_hmac, tvb, offset, 1, ENC_BIG_ENDIAN);
938 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
939 offset += 1;
940 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_hmac_sha, tvb, offset, 20, ENC_NA);
941 } else {
942 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_hmac, tvb, offset, option_len, ENC_BIG_ENDIAN);
943 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
944 "Wrong Data checksum length, [%u != 20]", option_len);
946 break;
947 case 6:
948 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_rtt, tvb, offset, 1, ENC_BIG_ENDIAN);
949 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
950 offset += 1;
951 if (option_len == 9) {
952 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_type,tvb, offset, 1, ENC_BIG_ENDIAN);
953 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_value,tvb, offset+1, 4, ENC_BIG_ENDIAN);
954 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_rtt_age,tvb, offset+5, 4, ENC_BIG_ENDIAN);
955 } else {
956 mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
957 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
958 "Wrong Data checksum length, [%u != 9]", option_len);
960 break;
961 case 7:
962 mp_option_sub_item=proto_tree_add_item(option_tree,hf_mpdccp_addaddr,tvb,offset,1,ENC_BIG_ENDIAN);
963 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
964 offset += 1;
965 switch (option_len) {
966 case 5:
967 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrid,tvb,offset,1,ENC_BIG_ENDIAN);
968 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addr_dec,tvb,offset+1,4,ENC_LITTLE_ENDIAN);
969 break;
970 case 7:
971 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrid,tvb,offset,1,ENC_BIG_ENDIAN);
972 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addr_dec,tvb,offset+1,4,ENC_LITTLE_ENDIAN);
973 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrport,tvb,offset+5,2,ENC_BIG_ENDIAN);
974 break;
975 case 17:// Check endianness for ipv6
976 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrid,tvb,offset,1,ENC_BIG_ENDIAN);
977 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addr_hex,tvb,offset+1,16,ENC_NA);
978 break;
979 case 19:
980 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrid,tvb,offset,1,ENC_BIG_ENDIAN);
981 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addr_hex,tvb,offset+1,16,ENC_NA);
982 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrport,tvb,offset+17,2,ENC_BIG_ENDIAN);
983 break;
984 default:
985 mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
986 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
987 "Wrong Data checksum length, [%u != 5 || 7 || 17 || 19]", option_len);
988 break;
990 break;
991 case 8:
992 if (option_len == 1) {
993 mp_option_sub_item=proto_tree_add_item(option_tree,hf_mpdccp_removeaddr,tvb,offset,1,ENC_BIG_ENDIAN);
994 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
995 offset += 1;
996 proto_tree_add_item(mp_option_sub_tree,hf_mpdccp_addrid,tvb,offset,1,ENC_BIG_ENDIAN);
998 } else {
999 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_removeaddr, tvb, offset, option_len, ENC_BIG_ENDIAN);
1000 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
1001 "Wrong Data checksum length, [%u != 1]", option_len);
1003 break;
1004 case 9:
1005 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_prio, tvb, offset, 1, ENC_BIG_ENDIAN);
1006 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
1007 offset += 1;
1008 if (option_len == 1) {
1009 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_prio_value, tvb, offset, 1, ENC_BIG_ENDIAN);
1010 } else {
1011 mp_option_sub_item = proto_tree_add_item(mp_option_sub_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
1012 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
1013 "Wrong Data checksum length, [%u != 1]", option_len);
1015 break;
1016 case 10:
1017 mp_option_sub_item = proto_tree_add_item(option_tree, hf_mpdccp_close,
1018 tvb, offset, 1, ENC_BIG_ENDIAN);
1019 mp_option_sub_tree = proto_item_add_subtree(mp_option_sub_item, ett_dccp_options_item);
1020 offset += 1;
1021 proto_tree_add_item(mp_option_sub_tree, hf_mpdccp_close_key, tvb, offset, option_len, ENC_BIG_ENDIAN);
1022 break;
1023 case 11:
1024 proto_tree_add_item(option_tree, hf_mpdccp_exp, tvb, offset, option_len, ENC_NA);
1025 break;
1026 default:
1027 mp_option_sub_item = proto_tree_add_item(option_tree, hf_dccp_option_data, tvb, offset, option_len, ENC_NA);
1028 expert_add_info_format(pinfo, mp_option_sub_item, &ei_dccp_option_len_bad,
1029 "MP-DCCP option [%u] not defined, [len: %u ]", mp_option_type, option_len);
1030 break;
1032 break;
1035 case 192: /* RFC 4342, 8.5 */
1036 if (option_len == 4) {
1037 p = tvb_get_ntohl(tvb, offset);
1039 * According to the comment in section 8.5 of RFC 4342,
1040 * 0xffffffff can mean zero
1042 if (p == 0xFFFFFFFF)
1043 proto_tree_add_uint_format_value(option_tree, hf_dccp_ccid3_loss_event_rate, tvb, offset,
1044 option_len, p, "0 (or max)");
1045 else
1046 proto_tree_add_uint(option_tree, hf_dccp_ccid3_loss_event_rate, tvb, offset, option_len, p);
1047 } else
1048 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
1049 "Wrong CCID3 Loss Event Rate length");
1050 break;
1051 case 193: /* RFC 4342, 8.6 */
1052 proto_tree_add_item(dccp_options_tree, hf_dccp_ccid3_loss_intervals, tvb, offset, option_len, ENC_NA);
1054 * FIXME: not implemented and apparently not used by any
1055 * implementation so far
1057 break;
1058 case 194: /* RFC 4342, 8.3 */
1059 if (option_len == 4)
1060 proto_tree_add_uint_format_value(option_tree, hf_dccp_ccid3_receive_rate, tvb, offset, option_len,
1061 tvb_get_ntohl(tvb, offset), "%u bytes/sec",
1062 tvb_get_ntohl(tvb, offset));
1063 else
1064 expert_add_info_format(pinfo, option_item, &ei_dccp_option_len_bad,
1065 "Wrong CCID3 Receive Rate length");
1066 break;
1067 default:
1068 if (((option_type >= 47) && (option_type <= 127)) ||
1069 ((option_type >= 3) && (option_type <= 31))) {
1070 proto_tree_add_item(option_tree, hf_dccp_option_reserved, tvb, offset, option_len, ENC_NA);
1071 break;
1074 if (option_type >= 128) {
1075 proto_tree_add_bytes_format(option_tree, hf_dccp_ccid_option_data, tvb, offset, option_len,
1076 NULL, "CCID option %d", option_type);
1077 break;
1080 /* if here we don't know this option */
1081 proto_tree_add_item(option_tree, hf_dccp_option_unknown, tvb, offset, option_len, ENC_NA);
1082 break;
1083 } /* end switch() */
1084 offset += option_len; /* move offset past the dissected option */
1085 } /* end while() */
1089 * compute DCCP checksum coverage according to RFC 4340, section 9
1091 static inline unsigned
1092 dccp_csum_coverage(const e_dccphdr *dccph, unsigned len)
1094 unsigned cov;
1096 if (dccph->cscov == 0)
1097 return len;
1099 cov = (dccph->data_offset + dccph->cscov - 1) * (unsigned)sizeof (uint32_t);
1100 return (cov > len) ? len : cov;
1103 static int
1104 dissect_dccp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
1106 proto_tree *dccp_tree;
1107 proto_item *item;
1108 proto_tree *dccp_options_tree = NULL;
1109 proto_item *dccp_item = NULL;
1110 proto_item *hidden_item, *offset_item;
1111 vec_t cksum_vec[4];
1112 uint32_t phdr[2];
1113 unsigned offset = 0;
1114 unsigned len = 0;
1115 unsigned reported_len = 0;
1116 unsigned csum_coverage_len;
1117 unsigned advertised_dccp_header_len = 0;
1118 unsigned options_len = 0;
1119 uint64_t seq; /* Absolute or relative seq number (depending on DCCP_S_BASE_SEQ_SET) */
1120 uint64_t ack; /* Absolute or relative ack number (depending on DCCP_S_BASE_SEQ_SET) */
1121 e_dccphdr *dccph;
1122 conversation_t *conv = NULL;
1123 struct dccp_analysis *dccpd;
1125 dccph = wmem_new0(pinfo->pool, e_dccphdr);
1126 dccph->sport = tvb_get_ntohs(tvb, offset);
1127 dccph->dport = tvb_get_ntohs(tvb, offset + 2);
1128 copy_address_shallow(&dccph->ip_src, &pinfo->src);
1129 copy_address_shallow(&dccph->ip_dst, &pinfo->dst);
1131 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DCCP");
1132 col_clear(pinfo->cinfo, COL_INFO);
1133 col_append_ports(pinfo->cinfo, COL_INFO, PT_DCCP, dccph->sport, dccph->dport);
1135 dccp_item = proto_tree_add_item(tree, proto_dccp, tvb, offset, -1, ENC_NA);
1136 if (dccp_summary_in_tree && tree) {
1137 proto_item_append_text(dccp_item, ", Src Port: %s, Dst Port: %s",
1138 port_with_resolution_to_str(pinfo->pool, PT_DCCP, dccph->sport),
1139 port_with_resolution_to_str(pinfo->pool, PT_DCCP, dccph->dport));
1141 dccp_tree = proto_item_add_subtree(dccp_item, ett_dccp);
1143 proto_tree_add_item(dccp_tree, hf_dccp_srcport, tvb, offset, 2, ENC_BIG_ENDIAN);
1144 hidden_item = proto_tree_add_item(dccp_tree, hf_dccp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1145 proto_item_set_hidden(hidden_item);
1146 offset += 2;
1148 proto_tree_add_item(dccp_tree, hf_dccp_dstport, tvb, offset, 2, ENC_BIG_ENDIAN);
1149 hidden_item = proto_tree_add_item(dccp_tree, hf_dccp_port, tvb, offset, 2, ENC_BIG_ENDIAN);
1150 proto_item_set_hidden(hidden_item);
1151 offset += 2;
1154 * update pinfo structure. I guess I have to do it, because this
1155 * is a transport protocol dissector.
1157 pinfo->ptype = PT_DCCP;
1158 pinfo->srcport = dccph->sport;
1159 pinfo->destport = dccph->dport;
1161 /* find (or create if needed) the conversation for this DCCP session */
1162 conv = find_or_create_conversation(pinfo);
1163 dccpd = get_dccp_conversation_data(conv, pinfo);
1164 item = proto_tree_add_uint(dccp_tree, hf_dccp_stream, tvb, offset, 0, dccpd->stream);
1165 proto_item_set_generated(item);
1167 /* Copy the stream index into the header as well to make it available
1168 * to tap listeners.
1170 dccph->stream = dccpd->stream;
1172 dccph->data_offset = tvb_get_uint8(tvb, offset);
1173 advertised_dccp_header_len = dccph->data_offset * 4;
1174 offset_item = proto_tree_add_uint(dccp_tree, hf_dccp_data_offset, tvb, offset, 1,
1175 dccph->data_offset);
1176 offset += 1;
1178 dccph->cscov = tvb_get_uint8(tvb, offset) & 0x0F;
1179 dccph->ccval = tvb_get_uint8(tvb, offset) & 0xF0;
1180 dccph->ccval >>= 4;
1181 proto_tree_add_uint(dccp_tree, hf_dccp_ccval, tvb, offset, 1,
1182 dccph->ccval);
1183 proto_tree_add_uint(dccp_tree, hf_dccp_cscov, tvb, offset, 1,
1184 dccph->cscov);
1185 offset += 1;
1187 dccph->checksum = tvb_get_ntohs(tvb, offset);
1190 * checksum analysis taken from packet-udp (difference: mandatory
1191 * checksums in DCCP)
1193 reported_len = tvb_reported_length(tvb);
1194 len = tvb_captured_length(tvb);
1195 csum_coverage_len = dccp_csum_coverage(dccph, reported_len);
1197 if (dccp_check_checksum && !pinfo->fragmented && len >= csum_coverage_len) {
1198 /* We're supposed to check the checksum, and the packet isn't part
1199 * of a fragmented datagram and isn't truncated, so we can checksum it.
1200 * XXX - make a bigger scatter-gather list once we do fragment
1201 * reassembly? */
1202 /* Set up the fields of the pseudo-header. */
1203 SET_CKSUM_VEC_PTR(cksum_vec[0], (const uint8_t *)pinfo->src.data, pinfo->src.len);
1204 SET_CKSUM_VEC_PTR(cksum_vec[1], (const uint8_t *)pinfo->dst.data, pinfo->dst.len);
1205 switch (pinfo->src.type) {
1206 case AT_IPv4:
1207 phdr[0] = g_htonl((IP_PROTO_DCCP << 16) + reported_len);
1208 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *) &phdr, 4);
1209 break;
1210 case AT_IPv6:
1211 phdr[0] = g_htonl(reported_len);
1212 phdr[1] = g_htonl(IP_PROTO_DCCP);
1213 SET_CKSUM_VEC_PTR(cksum_vec[2], (const uint8_t *) &phdr, 8);
1214 break;
1216 default:
1217 /* DCCP runs only atop IPv4 and IPv6... */
1218 DISSECTOR_ASSERT_NOT_REACHED();
1219 break;
1221 SET_CKSUM_VEC_TVB(cksum_vec[3], tvb, 0, csum_coverage_len);
1222 proto_tree_add_checksum(dccp_tree, tvb, offset, hf_dccp_checksum, hf_dccp_checksum_status, &ei_dccp_checksum, pinfo, in_cksum(&cksum_vec[0], 4),
1223 ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
1224 } else {
1225 proto_tree_add_checksum(dccp_tree, tvb, offset, hf_dccp_checksum, hf_dccp_checksum_status, &ei_dccp_checksum, pinfo, 0,
1226 ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS);
1228 offset += 2;
1230 dccph->reserved1 = tvb_get_uint8(tvb, offset) & 0xE0;
1231 dccph->reserved1 >>= 5;
1232 hidden_item =
1233 proto_tree_add_uint(dccp_tree, hf_dccp_res1, tvb, offset, 1,
1234 dccph->reserved1);
1235 proto_item_set_hidden(hidden_item);
1237 dccph->type = tvb_get_uint8(tvb, offset) & 0x1E;
1238 dccph->type >>= 1;
1239 proto_tree_add_uint(dccp_tree, hf_dccp_type, tvb, offset, 1,
1240 dccph->type);
1241 if (dccp_summary_in_tree) {
1242 proto_item_append_text(dccp_item, " [%s]",
1243 val_to_str_const(dccph->type, dccp_packet_type_vals,
1244 "Unknown Type"));
1246 col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]",
1247 val_to_str_const(dccph->type, dccp_packet_type_vals,
1248 "Unknown Type"));
1250 dccph->x = tvb_get_uint8(tvb, offset) & 0x01;
1251 proto_tree_add_boolean(dccp_tree, hf_dccp_x, tvb, offset, 1,
1252 dccph->x);
1253 offset += 1;
1255 if (dccph->x) {
1256 if (advertised_dccp_header_len < DCCP_GEN_HDR_LEN_X) {
1257 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1258 "Advertised header length (%u) is smaller than the minimum (%u)",
1259 advertised_dccp_header_len, DCCP_GEN_HDR_LEN_X);
1260 return tvb_reported_length(tvb);
1262 dccph->reserved2 = tvb_get_uint8(tvb, offset);
1263 hidden_item =
1264 proto_tree_add_uint(dccp_tree, hf_dccp_res2, tvb, offset, 1,
1265 dccph->reserved2);
1266 proto_item_set_hidden(hidden_item);
1267 offset += 1;
1269 dccph->seq = tvb_get_ntoh48(tvb, offset);
1270 if((dccp_relative_seq) && (dccpd->fwd->static_flags & DCCP_S_BASE_SEQ_SET)) {
1271 seq = dccph->seq - dccpd->fwd->base_seq;
1272 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_seq, tvb, offset, 6,
1273 seq, "%" PRIu64 " (relative sequence number)", seq);
1275 else {
1276 seq = dccph->seq;
1278 proto_tree_add_uint64(dccp_tree, hf_dccp_seq_abs, tvb, offset, 6, dccph->seq);
1280 offset += 6;
1281 } else {
1282 if (advertised_dccp_header_len < DCCP_GEN_HDR_LEN_NO_X) {
1283 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1284 "Advertised header length (%u) is smaller than the minimum (%u)",
1285 advertised_dccp_header_len, DCCP_GEN_HDR_LEN_NO_X);
1286 return tvb_reported_length(tvb);
1288 dccph->seq = tvb_get_ntoh24(tvb, offset);
1289 proto_tree_add_uint64(dccp_tree, hf_dccp_seq, tvb, offset, 3, dccph->seq);
1290 if((dccp_relative_seq) && (dccpd->fwd->static_flags & DCCP_S_BASE_SEQ_SET)) {
1291 seq = (dccph->seq - dccpd->fwd->base_seq) & 0xffffff;
1292 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_seq, tvb, offset, 3,
1293 seq, "%" PRIu64 " (relative sequence number)", seq);
1295 else {
1296 seq = dccph->seq;
1298 offset += 3;
1300 if (dccp_summary_in_tree) {
1301 proto_item_append_text(dccp_item, " Seq=%" PRIu64, seq);
1303 col_append_fstr(pinfo->cinfo, COL_INFO, " Seq=%" PRIu64, seq);
1305 /* dissecting type dependent additional fields */
1306 switch (dccph->type) {
1307 case 0x0: /* DCCP-Request */
1308 case 0xA: /* DCCP-Listen */
1309 if (advertised_dccp_header_len < offset + 4) {
1310 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1311 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
1312 advertised_dccp_header_len, offset + 4,
1313 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
1314 return tvb_reported_length(tvb);
1316 dccph->service_code = tvb_get_ntohl(tvb, offset);
1317 if (tree)
1318 proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4,
1319 dccph->service_code);
1320 col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%s)",
1321 val_to_str(dccph->service_code, dccp_service_code_vals, "Unknown (%u)"));
1322 offset += 4; /* move offset past the service code */
1324 if( !(dccpd->fwd->static_flags & DCCP_S_BASE_SEQ_SET) ) {
1325 dccpd->fwd->base_seq = dccph->seq;
1326 dccpd->fwd->static_flags |= DCCP_S_BASE_SEQ_SET;
1329 break;
1330 case 0x1: /* DCCP-Response */
1331 if (advertised_dccp_header_len < offset + 12) {
1332 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1333 "Advertised header length (%u) is smaller than the minimum (%u) for Response",
1334 advertised_dccp_header_len, offset + 12);
1335 return tvb_reported_length(tvb);
1337 dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
1338 if (tree) {
1339 hidden_item =
1340 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
1341 dccph->ack_reserved);
1342 proto_item_set_hidden(hidden_item);
1344 dccph->ack = tvb_get_ntohs(tvb, offset + 2);
1345 dccph->ack <<= 32;
1346 dccph->ack += tvb_get_ntohl(tvb, offset + 4);
1348 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1349 ack = dccph->ack - dccpd->rev->base_seq;
1351 else {
1352 ack = dccph->ack;
1355 if (tree) {
1356 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1357 proto_tree_add_uint64(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6, ack);
1359 proto_tree_add_uint64(dccp_tree, hf_dccp_ack_abs, tvb, offset + 2, 6, dccph->ack);
1361 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" PRIu64 ")", ack);
1362 offset += 8; /* move offset past the Acknowledgement Number Subheader */
1364 dccph->service_code = tvb_get_ntohl(tvb, offset);
1365 if (tree)
1366 proto_tree_add_uint(dccp_tree, hf_dccp_service_code, tvb, offset, 4,
1367 dccph->service_code);
1368 col_append_fstr(pinfo->cinfo, COL_INFO, " (service=%s)",
1369 val_to_str(dccph->service_code, dccp_service_code_vals, "Unknown (%u)"));
1371 offset += 4; /* move offset past the service code */
1373 if( !(dccpd->fwd->static_flags & DCCP_S_BASE_SEQ_SET) ) {
1374 dccpd->fwd->base_seq = dccph->seq;
1375 dccpd->fwd->static_flags |= DCCP_S_BASE_SEQ_SET;
1378 break;
1379 case 0x2: /* DCCP-Data */
1380 /* nothing to dissect */
1381 break;
1382 case 0x3: /* DCCP-Ack */
1383 case 0x4: /* DCCP-DataAck */
1384 if (dccph->x) {
1385 if (advertised_dccp_header_len < offset + 8) {
1386 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1387 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
1388 advertised_dccp_header_len, offset + 8,
1389 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
1390 return tvb_reported_length(tvb);
1392 dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
1393 if (tree) {
1394 hidden_item =
1395 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset,
1396 2, dccph->ack_reserved);
1397 proto_item_set_hidden(hidden_item);
1399 dccph->ack = tvb_get_ntohs(tvb, offset + 2);
1400 dccph->ack <<= 32;
1401 dccph->ack += tvb_get_ntohl(tvb, offset + 4);
1403 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1404 ack = dccph->ack - dccpd->rev->base_seq;
1406 else {
1407 ack = dccph->ack;
1410 if (tree) {
1411 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1412 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_ack, tvb, offset + 2, 6,
1413 ack, "%" PRIu64 " (relative acknowledgement number)", ack);
1415 proto_tree_add_uint64(dccp_tree, hf_dccp_ack_abs, tvb, offset + 2, 6, dccph->ack);
1417 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" PRIu64 ")", ack);
1418 offset += 8; /* move offset past the Ack Number Subheader */
1419 } else {
1420 if (advertised_dccp_header_len < offset + 4) {
1421 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1422 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
1423 advertised_dccp_header_len, offset + 4,
1424 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
1425 return tvb_reported_length(tvb);
1427 dccph->ack_reserved = tvb_get_uint8(tvb, offset);
1428 if (tree) {
1429 hidden_item =
1430 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset,
1431 1, dccph->ack_reserved);
1432 proto_item_set_hidden(hidden_item);
1434 dccph->ack = tvb_get_uint8(tvb, offset + 1);
1435 dccph->ack <<= 16;
1436 dccph->ack += tvb_get_ntohs(tvb, offset + 2);
1438 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1439 ack = (dccph->ack - dccpd->rev->base_seq) & 0xffffff;
1441 else {
1442 ack = dccph->ack;
1445 if (tree) {
1446 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1447 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_ack, tvb, offset + 1, 3,
1448 ack, "%" PRIu64 " (relative acknowledgement number)", ack);
1450 proto_tree_add_uint64(dccp_tree, hf_dccp_ack_abs, tvb, offset + 1, 3, dccph->ack);
1452 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" PRIu64 ")", ack);
1453 offset += 4; /* move offset past the Ack. Number Subheader */
1455 break;
1456 case 0x7: /* DCCP-Reset */
1457 if (advertised_dccp_header_len < offset + 4) {
1458 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1459 "Advertised header length (%u) is smaller than the minimum (%u) for Reset",
1460 advertised_dccp_header_len, offset + 4);
1461 return tvb_reported_length(tvb);
1463 dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
1465 if (tree) {
1466 hidden_item =
1467 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
1468 dccph->ack_reserved);
1469 proto_item_set_hidden(hidden_item);
1472 dccph->ack = tvb_get_ntohs(tvb, offset + 2);
1473 dccph->ack <<= 32;
1474 dccph->ack += tvb_get_ntohl(tvb, offset + 4);
1476 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1477 ack = (dccph->ack - dccpd->rev->base_seq) & 0xffffff;
1479 else {
1480 ack = dccph->ack;
1483 if (tree) {
1484 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1485 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_ack, tvb, offset + 1, 3,
1486 ack, "%" PRIu64 " (relative acknowledgement number)", ack);
1488 proto_tree_add_uint64(dccp_tree, hf_dccp_ack_abs, tvb, offset + 1, 3, dccph->ack);
1490 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" PRIu64 ")", ack);
1491 offset += 8; /* move offset past the Ack. Number Subheader */
1493 dccph->reset_code = tvb_get_uint8(tvb, offset);
1494 dccph->data1 = tvb_get_uint8(tvb, offset + 1);
1495 dccph->data2 = tvb_get_uint8(tvb, offset + 2);
1496 dccph->data3 = tvb_get_uint8(tvb, offset + 3);
1498 if (tree) {
1499 proto_tree_add_uint(dccp_tree, hf_dccp_reset_code, tvb, offset, 1,
1500 dccph->reset_code);
1501 proto_tree_add_uint(dccp_tree, hf_dccp_data1, tvb, offset + 1, 1,
1502 dccph->data1);
1503 proto_tree_add_uint(dccp_tree, hf_dccp_data2, tvb, offset + 2, 1,
1504 dccph->data2);
1505 proto_tree_add_uint(dccp_tree, hf_dccp_data3, tvb, offset + 3, 1,
1506 dccph->data3);
1508 col_append_fstr(pinfo->cinfo, COL_INFO, " (code=%s)",
1509 val_to_str_const(dccph->reset_code, dccp_reset_code_vals,
1510 "Unknown"));
1512 offset += 4; /* move offset past the Reset Code and data123 */
1513 break;
1514 case 0x5: /* DCCP-CloseReq */
1515 case 0x6: /* DCCP-Close */
1516 case 0x8: /* DCCP-Sync */
1517 case 0x9: /* DCCP-SyncAck */
1518 if (advertised_dccp_header_len < offset + 8) {
1519 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1520 "Advertised header length (%u) is smaller than the minimum (%u) for %s",
1521 advertised_dccp_header_len, offset + 8,
1522 val_to_str(dccph->type, dccp_packet_type_vals, "Unknown (%u)"));
1523 return tvb_reported_length(tvb);
1525 dccph->ack_reserved = tvb_get_ntohs(tvb, offset);
1526 if (tree) {
1527 hidden_item =
1528 proto_tree_add_uint(dccp_tree, hf_dccp_ack_res, tvb, offset, 2,
1529 dccph->ack_reserved);
1530 proto_item_set_hidden(hidden_item);
1532 dccph->ack = tvb_get_ntohs(tvb, offset + 2);
1533 dccph->ack <<= 32;
1534 dccph->ack += tvb_get_ntohl(tvb, offset + 4);
1536 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1537 ack = (dccph->ack - dccpd->rev->base_seq) & 0xffffff;
1539 else {
1540 ack = dccph->ack;
1543 if (tree) {
1544 if((dccp_relative_seq) && (dccpd->rev->static_flags & DCCP_S_BASE_SEQ_SET)) {
1545 proto_tree_add_uint64_format_value(dccp_tree, hf_dccp_ack, tvb, offset + 1, 3,
1546 ack, "%" PRIu64 " (relative acknowledgement number)", ack);
1548 proto_tree_add_uint64(dccp_tree, hf_dccp_ack_abs, tvb, offset + 1, 3, dccph->ack);
1550 col_append_fstr(pinfo->cinfo, COL_INFO, " (Ack=%" PRIu64 ")", ack);
1551 offset += 8; /* move offset past the Ack. Number Subheader */
1552 break;
1553 default:
1554 expert_add_info(pinfo, dccp_item, &ei_dccp_packet_type_reserved);
1555 return tvb_reported_length(tvb);
1559 * note: data_offset is the offset from the start of the packet's
1560 * DCCP header to the start of its application data area, in 32-bit words.
1562 if (advertised_dccp_header_len > DCCP_HDR_LEN_MAX) {
1563 expert_add_info_format(pinfo, offset_item, &ei_dccp_advertised_header_length_bad,
1564 "Advertised header length (%u) is larger than the maximum (%u)",
1565 advertised_dccp_header_len, DCCP_HDR_LEN_MAX);
1566 return tvb_reported_length(tvb);
1570 * The checks done above ensure that
1571 * advertised_dccp_header_len >= offset.
1573 * advertised_dccp_header_len - offset is the number of bytes of
1574 * options.
1576 if (advertised_dccp_header_len > offset) {
1577 options_len = advertised_dccp_header_len - offset;
1578 if (dccp_tree) {
1579 dccp_item =
1580 proto_tree_add_none_format(dccp_tree, hf_dccp_options, tvb,
1581 offset,
1582 options_len, "Options: (%u byte%s)",
1583 options_len,
1584 plurality(options_len, "", "s"));
1585 dccp_options_tree = proto_item_add_subtree(dccp_item,
1586 ett_dccp_options);
1588 dissect_options(tvb, pinfo, dccp_options_tree, tree, dccph, offset,
1589 offset + options_len);
1592 offset += options_len; /* move offset past the Options */
1593 proto_item_set_end(dccp_item, tvb, offset);
1595 /* queuing tap data */
1596 tap_queue_packet(dccp_tap, pinfo, dccph);
1598 /* call sub-dissectors */
1599 if (!pinfo->flags.in_error_pkt || tvb_reported_length_remaining(tvb, offset) > 0)
1600 decode_dccp_ports(tvb, offset, pinfo, tree, dccph->sport, dccph->dport);
1602 return tvb_reported_length(tvb);
1605 static void
1606 dccp_init(void)
1608 dccp_stream_count = 0;
1611 void
1612 proto_register_dccp(void)
1614 module_t *dccp_module;
1616 static hf_register_info hf[] = {
1618 &hf_dccp_srcport,
1620 "Source Port", "dccp.srcport",
1621 FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
1622 NULL, HFILL
1626 &hf_dccp_dstport,
1628 "Destination Port", "dccp.dstport",
1629 FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
1630 NULL, HFILL
1634 &hf_dccp_port,
1636 "Source or Destination Port", "dccp.port",
1637 FT_UINT16, BASE_PT_DCCP, NULL, 0x0,
1638 NULL, HFILL
1642 &hf_dccp_stream,
1644 "Stream index", "dccp.stream",
1645 FT_UINT32, BASE_DEC, NULL, 0x0,
1646 NULL, HFILL
1650 &hf_dccp_data_offset,
1652 "Data Offset", "dccp.data_offset",
1653 FT_UINT8, BASE_DEC, NULL, 0x0,
1654 NULL, HFILL
1658 &hf_dccp_ccval,
1660 "CCVal", "dccp.ccval",
1661 FT_UINT8, BASE_DEC, NULL, 0x0,
1662 NULL, HFILL
1666 &hf_dccp_cscov,
1668 "Checksum Coverage", "dccp.cscov",
1669 FT_UINT8, BASE_DEC, NULL, 0x0,
1670 NULL, HFILL
1674 &hf_dccp_checksum_status,
1676 "Checksum Status", "dccp.checksum.status",
1677 FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0,
1678 NULL, HFILL
1682 &hf_dccp_checksum,
1684 "Checksum", "dccp.checksum",
1685 FT_UINT16, BASE_HEX, NULL, 0x0,
1686 NULL, HFILL
1690 &hf_dccp_res1,
1692 "Reserved", "dccp.res1",
1693 FT_UINT8, BASE_HEX, NULL, 0x0,
1694 NULL, HFILL
1698 &hf_dccp_res2,
1700 "Reserved", "dccp.res2",
1701 FT_UINT8, BASE_HEX, NULL, 0x0,
1702 NULL, HFILL
1706 &hf_dccp_type,
1708 "Type", "dccp.type",
1709 FT_UINT8, BASE_DEC, VALS(dccp_packet_type_vals), 0x0,
1710 NULL, HFILL
1714 &hf_dccp_x,
1716 "Extended Sequence Numbers", "dccp.x",
1717 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1718 NULL, HFILL
1722 &hf_dccp_seq,
1724 "Sequence Number", "dccp.seq",
1725 FT_UINT64, BASE_DEC, NULL, 0x0,
1726 NULL, HFILL
1730 &hf_dccp_seq_abs,
1732 "Sequence Number (raw)", "dccp.seq_raw",
1733 FT_UINT64, BASE_DEC, NULL, 0x0,
1734 NULL, HFILL
1738 &hf_dccp_ack_res,
1740 "Reserved", "dccp.ack_res",
1741 FT_UINT16, BASE_HEX, NULL, 0x0,
1742 NULL, HFILL
1746 &hf_dccp_ack,
1748 "Acknowledgement Number", "dccp.ack",
1749 FT_UINT64, BASE_DEC, NULL, 0x0,
1750 NULL, HFILL
1754 &hf_dccp_ack_abs,
1756 "Acknowledgement Number (raw)", "dccp.ack_raw",
1757 FT_UINT64, BASE_DEC, NULL, 0x0,
1758 NULL, HFILL
1762 &hf_dccp_service_code,
1764 "Service Code", "dccp.service_code",
1765 FT_UINT32, BASE_DEC, VALS(dccp_service_code_vals), 0x0,
1766 NULL, HFILL
1770 &hf_dccp_reset_code,
1772 "Reset Code", "dccp.reset_code",
1773 FT_UINT8, BASE_DEC, VALS(dccp_reset_code_vals), 0x0,
1774 NULL, HFILL
1778 &hf_dccp_data1,
1780 "Data 1", "dccp.data1",
1781 FT_UINT8, BASE_DEC, NULL, 0x0,
1782 NULL, HFILL
1786 &hf_dccp_data2,
1788 "Data 2", "dccp.data2",
1789 FT_UINT8, BASE_DEC, NULL, 0x0,
1790 NULL, HFILL
1794 &hf_dccp_data3,
1796 "Data 3", "dccp.data3",
1797 FT_UINT8, BASE_DEC, NULL, 0x0,
1798 NULL, HFILL
1802 &hf_dccp_option_type,
1804 "Option Type", "dccp.option_type",
1805 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dccp_options_rvals), 0x0,
1806 NULL, HFILL
1810 &hf_dccp_feature_number,
1812 "Feature Number", "dccp.feature_number",
1813 FT_UINT8, BASE_DEC|BASE_RANGE_STRING, RVALS(dccp_feature_numbers_rvals), 0x0,
1814 NULL, HFILL
1818 &hf_dccp_ndp_count,
1820 "NDP Count", "dccp.ndp_count",
1821 FT_UINT64, BASE_DEC, NULL, 0x0,
1822 NULL, HFILL
1826 &hf_dccp_timestamp,
1828 "Timestamp", "dccp.timestamp",
1829 FT_UINT32, BASE_DEC, NULL, 0x0,
1830 NULL, HFILL
1834 &hf_dccp_timestamp_echo,
1836 "Timestamp Echo", "dccp.timestamp_echo",
1837 FT_UINT32, BASE_DEC, NULL, 0x0,
1838 NULL, HFILL
1842 &hf_dccp_elapsed_time,
1844 "Elapsed Time", "dccp.elapsed_time",
1845 FT_UINT32, BASE_DEC, NULL, 0x0,
1846 NULL, HFILL
1850 &hf_dccp_data_checksum,
1852 "Data Checksum", "dccp.checksum_data",
1853 FT_UINT32, BASE_HEX, NULL, 0x0,
1854 NULL, HFILL
1859 /* MP-DCCP related option fields */
1860 {&hf_mpdccp_confirm,{"MP_CONFIRM", "dccp.mp_confirm",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1861 {&hf_mpdccp_version,{"version", "dccp.mp_version",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1863 {&hf_mpdccp_join,{"MP_JOIN", "dccp.mp_join",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1864 {&hf_mpdccp_join_id,{"Address ID", "dccp.mp_joinid",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1865 {&hf_mpdccp_join_token,{"Path Token", "dccp.mp_path_token",FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
1866 {&hf_mpdccp_join_nonce,{"Nonce", "dccp.mp_nonce",FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL}},
1868 {&hf_mpdccp_fast_close,{"MP_FAST_CLOSE", "dccp.mp_fast_close",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1870 {&hf_mpdccp_key,{"MP_KEY", "dccp.mp_key",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1871 {&hf_mpdccp_key_type,{"Key Type", "dccp.mp_key_type",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1872 {&hf_mpdccp_key_key,{"Key Data", "dccp.mp_key_hash",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1874 {&hf_mpdccp_seq,{"Sequence Number", "dccp.mp_seq",FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1876 {&hf_mpdccp_hmac,{"MP_HMAC", "dccp.mp_hmac",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1877 {&hf_mpdccp_hmac_sha,{"HMAC-SHA256", "dccp.mp_hmac_sha",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1879 {&hf_mpdccp_rtt,{"MP_RTT", "dccp.mp_rtt",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1880 {&hf_mpdccp_rtt_type,{"RTT_Type", "dccp.mp_rtt_type",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1881 {&hf_mpdccp_rtt_value,{"RTT", "dccp.mp_rtt_value",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1882 {&hf_mpdccp_rtt_age,{"Age", "dccp.mp_rtt_age",FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1884 {&hf_mpdccp_addaddr,{"MP_ADDADDR", "dccp.mp_addaddr",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1885 {&hf_mpdccp_addrid,{"Address ID", "dccp.mp_addrid",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1886 {&hf_mpdccp_addr_dec,{"Address", "dccp.mp_ipv4addr",FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1887 {&hf_mpdccp_addr_hex,{"Address", "dccp.mp_ipv6addr",FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1888 {&hf_mpdccp_addrport,{"Port", "dccp.mp_addrport",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1890 {&hf_mpdccp_removeaddr,{"MP_REMOVEADDR", "dccp.mp_removeaddr",FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1892 {&hf_mpdccp_prio,{"MP_PRIO", "dccp.mp_prio",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1893 {&hf_mpdccp_prio_value,{"Priority", "dccp.mp_prioval",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1895 {&hf_mpdccp_close,{"MP_CLOSE", "dccp.mp_close",FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL}},
1897 {&hf_mpdccp_close_key,{"Key Data", "dccp.mp_close_key",FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL}},
1899 {&hf_mpdccp_exp,{"MP_EXP", "dccp.mp_exp",FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1901 {&hf_dccp_option_data,{"Option data", "dccp.mp_option",FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL}},
1905 &hf_dccp_options,
1907 "Options", "dccp.options",
1908 FT_NONE, BASE_NONE, NULL, 0x0,
1909 "DCCP Options fields", HFILL
1913 /* Generated from convert_proto_tree_add_text.pl */
1914 { &hf_dccp_padding, { "Padding", "dccp.padding", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1915 { &hf_dccp_mandatory, { "Mandatory", "dccp.mandatory", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1916 { &hf_dccp_slow_receiver, { "Slow Receiver", "dccp.slow_receiver", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1917 { &hf_dccp_init_cookie, { "Init Cookie", "dccp.init_cookie", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1918 { &hf_dccp_ack_vector_nonce_0, { "Ack Vector [Nonce 0]", "dccp.ack_vector.nonce_0", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1919 { &hf_dccp_ack_vector_nonce_1, { "Ack Vector [Nonce 1]", "dccp.ack_vector.nonce_1", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1920 { &hf_dccp_data_dropped, { "Data Dropped", "dccp.data_dropped", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1921 { &hf_dccp_ccid3_loss_event_rate, { "CCID3 Loss Event Rate", "dccp.ccid3_loss_event_rate", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
1922 { &hf_dccp_ccid3_loss_intervals, { "CCID3 Loss Intervals", "dccp.ccid3_loss_intervals", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1923 { &hf_dccp_ccid3_receive_rate, { "CCID3 Receive Rate", "dccp.ccid3_receive_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_byte_bytespsecond), 0x0, NULL, HFILL }},
1924 { &hf_dccp_option_reserved, { "Reserved", "dccp.option_reserved", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1925 { &hf_dccp_ccid_option_data, { "CCID option", "dccp.ccid_option_data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1926 { &hf_dccp_option_unknown, { "Unknown", "dccp.option_unknown", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
1929 static int *ett[] = {
1930 &ett_dccp,
1931 &ett_dccp_options,
1932 &ett_dccp_options_item,
1933 &ett_dccp_feature
1936 static ei_register_info ei[] = {
1937 { &ei_dccp_option_len_bad, { "dccp.option.len.bad", PI_PROTOCOL, PI_WARN, "Bad option length", EXPFILL }},
1938 { &ei_dccp_advertised_header_length_bad, { "dccp.advertised_header_length.bad", PI_MALFORMED, PI_ERROR, "Advertised header length bad", EXPFILL }},
1939 { &ei_dccp_packet_type_reserved, { "dccp.packet_type.reserved", PI_PROTOCOL, PI_WARN, "Reserved packet type: unable to dissect further", EXPFILL }},
1940 { &ei_dccp_checksum, { "dccp.bad_checksum", PI_CHECKSUM, PI_ERROR, "Bad checksum", EXPFILL }},
1943 expert_module_t* expert_dccp;
1945 proto_dccp =
1946 proto_register_protocol("Datagram Congestion Control Protocol", "DCCP", "dccp");
1947 dccp_handle = register_dissector("dccp", dissect_dccp, proto_dccp);
1948 proto_register_field_array(proto_dccp, hf, array_length(hf));
1949 proto_register_subtree_array(ett, array_length(ett));
1950 expert_dccp = expert_register_protocol(proto_dccp);
1951 expert_register_field_array(expert_dccp, ei, array_length(ei));
1953 /* subdissectors */
1954 dccp_subdissector_table =
1955 register_dissector_table("dccp.port", "DCCP port", proto_dccp, FT_UINT16,
1956 BASE_DEC);
1957 heur_subdissector_list = register_heur_dissector_list_with_description("dccp", "DCCP heuristic", proto_dccp);
1959 /* reg preferences */
1960 dccp_module = prefs_register_protocol(proto_dccp, NULL);
1961 /* For reading older preference files with "dcp." preferences */
1962 prefs_register_module_alias("dcp", dccp_module);
1963 prefs_register_bool_preference(
1964 dccp_module, "summary_in_tree",
1965 "Show DCCP summary in protocol tree",
1966 "Whether the DCCP summary line should be shown in the protocol tree",
1967 &dccp_summary_in_tree);
1969 prefs_register_bool_preference(
1970 dccp_module, "try_heuristic_first",
1971 "Try heuristic sub-dissectors first",
1972 "Try to decode a packet using an heuristic sub-dissector before "
1973 "using a sub-dissector "
1974 "registered to a specific port",
1975 &try_heuristic_first);
1977 prefs_register_bool_preference(
1978 dccp_module, "check_checksum",
1979 "Check the validity of the DCCP checksum when possible",
1980 "Whether to check the validity of the DCCP checksum",
1981 &dccp_check_checksum);
1983 prefs_register_bool_preference(
1984 dccp_module, "relative_sequence_numbers",
1985 "Relative sequence numbers",
1986 "Make the DCCP dissector use relative sequence numbers instead of absolute ones.",
1987 &dccp_relative_seq);
1989 register_conversation_table(proto_dccp, false, dccpip_conversation_packet, dccpip_endpoint_packet);
1990 register_conversation_filter("dccp", "DCCP", dccp_filter_valid, dccp_build_filter, NULL);
1991 register_follow_stream(proto_dccp, "dccp_follow", dccp_follow_conv_filter, dccp_follow_index_filter, dccp_follow_address_filter,
1992 dccp_port_to_display, follow_tvb_tap_listener, get_dccp_stream_count, NULL);
1994 register_init_routine(dccp_init);
1996 dccp_tap = register_tap("dccp");
1997 dccp_follow_tap = register_tap("dccp_follow");
2000 void
2001 proto_reg_handoff_dccp(void)
2003 dissector_add_uint("ip.proto", IP_PROTO_DCCP, dccp_handle);
2007 * Editor modelines - https://www.wireshark.org/tools/modelines.html
2009 * Local variables:
2010 * c-basic-offset: 4
2011 * tab-width: 8
2012 * indent-tabs-mode: nil
2013 * End:
2015 * vi: set shiftwidth=4 tabstop=8 expandtab:
2016 * :indentSize=4:tabSize=8:noTabs=true: