Hi there,

Please find attached a reworked patch which I believe addresses all of
Guy's original  concerns and also adds options processing and other
enhancements.

It has been tested on 32 and 64 bit, little and big endian but hasn't
been tested on Darwin - I have however done what was asked.

Can you please accept this into the tcpdump program or advise what
else needs to be done?

More information on DCCP can be obtained at http://wlug.org.nz/DCCP

Regards,

Ian

On 03/08/05, Guy Harris <[EMAIL PROTECTED]> wrote:
> Ian McDonald wrote:
> 
> > +#define __LITTLE_ENDIAN_BITFIELD
> > +
> > +/**
> > + * struct dccp_hdr - generic part of DCCP packet header
> > + *
> > + * @dccph_sport - Relevant port on the endpoint that sent this packet
> > + * @dccph_dport - Relevant port on the other endpoint
> > + * @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit 
> > words
> > + * @dccph_ccval - Used by the HC-Sender CCID
> > + * @dccph_cscov - Parts of the packet that are covered by the Checksum 
> > field
> > + * @dccph_checksum - Internet checksum, depends on dccph_cscov
> > + * @dccph_x - 0 = 24 bit sequence number, 1 = 48
> > + * @dccph_type - packet type, see DCCP_PKT_ prefixed macros
> > + * @dccph_seq - sequence number high or low order 24 bits, depends on 
> > dccph_x
> > + */
> > +struct dccp_hdr {
> > +     u_int16_t       dccph_sport,
> > +                     dccph_dport;
> > +     u_int8_t        dccph_doff;
> > +#if defined(__LITTLE_ENDIAN_BITFIELD)
> > +     u_int8_t        dccph_cscov:4,
> > +                     dccph_ccval:4;
> > +#elif defined(__BIG_ENDIAN_BITFIELD)
> > +     u_int8_t        dccph_ccval:4,
> > +                     dccph_cscov:4;
> > +#else
> > +#error  "Adjust your <asm/byteorder.h> defines"
> > +#endif
> 
> The fact that __LITTLE_ENDIAN_BITFIELD is predefined means that the code
> assumes that bitfields are stored in an order such that in
> 
>         u_int8_t        dccph_cscov:4,
>                         dccph_ccval:4;
> 
> the low-order 4 bits of the byte are dccph_cscov and the high-order 4
> bits are dccph_ccval.
> 
> The C language doesn't specify the order of bitfields in the bits of a
> structure, so that won't work.
> 
> If I remove that #define, I get the errors
> 
>         dccp.h:35:2: #error "Adjust your <asm/byteorder.h> defines"
>         dccp.h:49:2: #error "Adjust your <asm/byteorder.h> defines"
>         dccp.h:114: error: structure has no member named `dccph_x'
>         print-dccp.c:57:2: #error "Adjust your <asm/byteorder.h> defines"
> 
> Unfortunately, the suggestion made by the errors doesn't help:
> 
>         Guy-Harris-Computer.local$ ls -l /usr/include/asm/byteorder.h
>         ls: /usr/include/asm/byteorder.h: No such file or directory
>         Guy-Harris-Computer.local$ ls -ld /usr/include/asm
>         ls: /usr/include/asm: No such file or directory
> 
> because:
> 
>         Guy-Harris-Computer.local$ uname -sr
>         Darwin 7.9.0
> 
> this ain't Linux.
> 
> Try, instead:
> 
>         u_int8_t        dccph_ccval_cscov;
> 
>                 ...
> 
>         #define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov) & 0x0F)
>         #define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov >> 4) & 0x0F)
> 
> And, for the Res, Type, X, and Sequence number fields, I'd declare the
> first 4 bytes as a u_int32_t, extract it with EXTRACT_32BITS(), and
> define macros that take a 32-bit value and extract the Res, Type, X, and
> Sequence Number fields from it.  I'd do something similar with the Ack
> sequence numbers.
> 
> In addition, zero-length arrays such as
> 
>         u_int32_t       dccph_options[0];
> 
> are not supported by all C compilers people use to compile tcpdump;
> either make it an array of 1 element (and subtract sizeof(u_int32_t)
> from anything based on the size of the structure), or leave that field
> out (and, if code is written that looks at options, add the length of
> the header to a pointer to the start of the packet and use that pointer
> as a pointer to the options), and do similar things in other places
> where there are zero-length arrays.
> 
> (Also, remove the include of <assert.h>; the assert macro isn't used.)
> 
> In addition, there are no TCHECK(), TCHECK2(), TTEST(), or TTEST2()
> calls, and the "dh_end" variable isn't used, so no check appears to be
> done to prevent the print routine from running past the end of the
> captured data in the packet.
diff -urN tcpdump-2005.08.22/dccp.h dccpdump/dccp.h
--- tcpdump-2005.08.22/dccp.h	1970-01-01 12:00:00.000000000 +1200
+++ dccpdump/dccp.h	2005-09-05 11:49:48.000000000 +1200
@@ -0,0 +1,136 @@
+#ifndef __DCCP_HDR__
+#define __DCCP_HDR__
+/*
+ * Copyright (C) Arnaldo Carvalho de Melo 2004
+ * Copyright (C) Ian McDonald 2005 <[EMAIL PROTECTED]>
+ * Copyright (C) Yoshifumi Nishida 2005
+ *
+ * This software may be distributed either under the terms of the
+ * BSD-style license that accompanies tcpdump or the GNU GPL version 2
+ */
+
+/**
+ * struct dccp_hdr - generic part of DCCP packet header
+ *
+ * @dccph_sport - Relevant port on the endpoint that sent this packet
+ * @dccph_dport - Relevant port on the other endpoint
+ * @dccph_doff - Data Offset from the start of the DCCP header, in 32-bit words
+ * @dccph_ccval - Used by the HC-Sender CCID
+ * @dccph_cscov - Parts of the packet that are covered by the Checksum field
+ * @dccph_checksum - Internet checksum, depends on dccph_cscov
+ * @dccph_x - 0 = 24 bit sequence number, 1 = 48
+ * @dccph_type - packet type, see DCCP_PKT_ prefixed macros
+ * @dccph_seq - sequence number high or low order 24 bits, depends on dccph_x
+ */
+struct dccp_hdr {
+	u_int16_t	dccph_sport,
+			dccph_dport;
+	u_int8_t	dccph_doff;
+	u_int8_t	dccph_ccval_cscov;
+	u_int16_t	dccph_checksum;
+	union {
+	u_int8_t	dccph_xtr;
+	u_int32_t	dccph_seq;
+	}		dccph_xtrs;
+};
+
+#define DCCPH_CCVAL(dh)	(((dh)->dccph_ccval_cscov) & 0x0F)
+#define DCCPH_CSCOV(dh)	(((dh)->dccph_ccval_cscov >> 4) & 0x0F)
+
+#define DCCPH_X(dh)	((dh)->dccph_xtrs.dccph_xtr & 1)
+#define DCCPH_TYPE(dh)	(((dh)->dccph_xtrs.dccph_xtr >> 1) & 0xF)
+
+#define DCCPH_SEQ(dh)	(((dh)->dccph_xtrs.dccph_seq >> 8) & 0x0FFF)
+
+/**
+ * struct dccp_hdr_ext - the low bits of a 48 bit seq packet
+ *
+ * @dccph_seq_low - low 24 bits of a 48 bit seq packet
+ */
+struct dccp_hdr_ext {
+	u_int32_t	dccph_seq_low;
+};
+
+/**
+ * struct dccp_hdr_request - Conection initiation request header
+ *
+ * @dccph_req_service - Service to which the client app wants to connect
+ */
+struct dccp_hdr_request {
+	u_int32_t	dccph_req_service;
+};
+
+/**
+ * struct dccp_hdr_ack_bits - acknowledgment bits common to most packets
+ *
+ * @dccph_resp_ack_nr_high - 48 bit ack number high order bits, contains GSR
+ * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR
+ */
+struct dccp_hdr_ack_bits {
+	u_int32_t	dccph_ra;
+	u_int32_t	dccph_ack_nr_low;
+};
+
+#define DCCPH_ACK(dh_ack)	(((dh_ack)->dccph_ra >> 8) & 0x0FFF)
+
+/**
+ * struct dccp_hdr_response - Conection initiation response header
+ *
+ * @dccph_resp_ack_nr_high - 48 bit ack number high order bits, contains GSR
+ * @dccph_resp_ack_nr_low - 48 bit ack number low order bits, contains GSR
+ * @dccph_resp_service - Echoes the Service Code on a received DCCP-Request
+ */
+struct dccp_hdr_response {
+	struct dccp_hdr_ack_bits	dccph_resp_ack;
+	u_int32_t			dccph_resp_service;
+};
+
+static inline struct dccp_hdr_data *dccp_hdr_data(struct dccp_hdr *hdrg)
+{
+	const int ext = DCCPH_X(hdrg) ? sizeof(struct dccp_hdr_ext) : 0;
+
+	return (struct dccp_hdr_data *)(((u_char *)hdrg) + sizeof(hdrg) + ext);
+}
+
+/**
+ * struct dccp_hdr_reset - Unconditionally shut down a connection
+ *
+ * @dccph_reset_service - Echoes the Service Code on a received DCCP-Request
+ */
+struct dccp_hdr_reset {
+	struct dccp_hdr_ack_bits	dccph_reset_ack;
+	u_int8_t			dccph_reset_code,
+					dccph_reset_data[3];
+};
+
+enum dccp_pkt_type {
+	DCCP_PKT_REQUEST = 0,
+	DCCP_PKT_RESPONSE,
+	DCCP_PKT_DATA,
+	DCCP_PKT_ACK,
+	DCCP_PKT_DATAACK,
+	DCCP_PKT_CLOSEREQ,
+	DCCP_PKT_CLOSE,
+	DCCP_PKT_RESET,
+	DCCP_PKT_SYNC,
+	DCCP_PKT_SYNCACK,
+	DCCP_PKT_INVALID,
+};
+
+enum dccp_reset_codes {
+	DCCP_RESET_CODE_UNSPECIFIED = 0,
+	DCCP_RESET_CODE_CLOSED,
+	DCCP_RESET_CODE_ABORTED,
+	DCCP_RESET_CODE_NO_CONNECTION,
+	DCCP_RESET_CODE_PACKET_ERROR,
+	DCCP_RESET_CODE_OPTION_ERROR,
+	DCCP_RESET_CODE_MANDATORY_ERROR,
+	DCCP_RESET_CODE_CONNECTION_REFUSED,
+	DCCP_RESET_CODE_BAD_SERVICE_CODE,
+	DCCP_RESET_CODE_TOO_BUSY,
+	DCCP_RESET_CODE_BAD_INIT_COOKIE,
+	DCCP_RESET_CODE_AGGRESSION_PENALTY,
+	__DCCP_RESET_CODE_LAST,
+};
+
+#endif /* __DCCP_HDR__ */
diff -urN tcpdump-2005.08.22/interface.h dccpdump/interface.h
--- tcpdump-2005.08.22/interface.h	2005-07-21 10:12:39.000000000 +1200
+++ dccpdump/interface.h	2005-09-05 11:47:05.000000000 +1200
@@ -293,6 +293,7 @@
 extern void radius_print(const u_char *, u_int);
 extern void lwres_print(const u_char *, u_int);
 extern void pptp_print(const u_char *);
+extern void dccp_print(const u_char *, const u_char *, u_int);
 extern void sctp_print(const u_char *, const u_char *, u_int);
 extern void mpls_print(const u_char *, u_int);
 extern void mpls_lsp_ping_print(const u_char *, u_int);
diff -urN tcpdump-2005.08.22/ipproto.c dccpdump/ipproto.c
--- tcpdump-2005.08.22/ipproto.c	2005-05-21 09:02:30.000000000 +1200
+++ dccpdump/ipproto.c	2005-09-05 11:47:05.000000000 +1200
@@ -36,6 +36,7 @@
     { IPPROTO_EGP, "EGP" },
     { IPPROTO_PIGP, "IGRP" },
     { IPPROTO_UDP, "UDP" },
+    { IPPROTO_DCCP, "DCCP" },
     { IPPROTO_IPV6, "IPv6" },
     { IPPROTO_ROUTING, "Routing" },
     { IPPROTO_FRAGMENT, "Fragment" },
diff -urN tcpdump-2005.08.22/ipproto.h dccpdump/ipproto.h
--- tcpdump-2005.08.22/ipproto.h	2005-05-21 09:02:30.000000000 +1200
+++ dccpdump/ipproto.h	2005-09-05 11:47:05.000000000 +1200
@@ -66,6 +66,9 @@
 #ifndef IPPROTO_UDP
 #define	IPPROTO_UDP		17		/* user datagram protocol */
 #endif
+#ifndef IPPROTO_DCCP
+#define	IPPROTO_DCCP		33		/* datagram congestion control protocol */
+#endif
 #ifndef IPPROTO_IPV6
 #define IPPROTO_IPV6		41
 #endif
diff -urN tcpdump-2005.08.22/Makefile.in dccpdump/Makefile.in
--- tcpdump-2005.08.22/Makefile.in	2005-07-11 02:44:50.000000000 +1200
+++ dccpdump/Makefile.in	2005-09-05 11:47:05.000000000 +1200
@@ -70,7 +70,7 @@
 	print-802_11.c print-ap1394.c print-ah.c print-arcnet.c \
 	print-aodv.c print-arp.c print-ascii.c print-atalk.c print-atm.c \
 	print-beep.c print-bfd.c print-bgp.c print-bootp.c print-cdp.c \
-	print-chdlc.c print-cip.c print-cnfp.c print-decnet.c \
+	print-chdlc.c print-cip.c print-cnfp.c print-dccp.c print-decnet.c \
 	print-domain.c print-dvmrp.c print-enc.c print-egp.c \
 	print-eap.c print-eigrp.c\
 	print-esp.c print-ether.c print-fddi.c print-fr.c \
@@ -98,7 +98,7 @@
 # We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
 # hack the extra indirection
 OBJ =	$(CSRC:.c=.o) $(GENSRC:.c=.o) $(LOCALSRC:.c=.o) $(LIBOBJS)
-HDR =   addrtoname.h appletalk.h bootp.h cpack.h decnet.h \
+HDR =   addrtoname.h appletalk.h bootp.h cpack.h dccp.h decnet.h \
 	ethertype.h extract.h fddi.h gmt2local.h igrp.h interface.h \
 	ipx.h llc.h machdep.h mib.h nfsfh.h nfsv2.h ntp.h ospf.h \
 	setsignal.h \
diff -urN tcpdump-2005.08.22/print-dccp.c dccpdump/print-dccp.c
--- tcpdump-2005.08.22/print-dccp.c	1970-01-01 12:00:00.000000000 +1200
+++ dccpdump/print-dccp.c	2005-09-05 11:47:05.000000000 +1200
@@ -0,0 +1,524 @@
+/*
+ * Copyright (C) Arnaldo Carvalho de Melo 2004
+ * Copyright (C) Ian McDonald 2005
+ * Copyright (C) Yoshifumi Nishida 2005
+ *
+ * This software may be distributed either under the terms of the
+ * BSD-style license that accompanies tcpdump or the GNU GPL version 2
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include "dccp.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"			/* must come after interface.h */
+#include "ip.h"
+#ifdef INET6
+#include "ip6.h"
+#endif
+#include "ipproto.h"
+
+static const char *dccp_reset_codes[] = {
+	"unspecified",
+	"closed",
+	"aborted",
+	"no_connection",
+	"packet_error",
+	"option_error",
+	"mandatory_error",
+	"connection_refused",
+	"bad_service_code",
+	"too_busy",
+	"bad_init_cookie",
+	"aggression_penalty",
+};
+
+static const char *dccp_feature_nums[] = {
+	"reserved", 
+	"ccid",
+	"allow_short_seqno",
+	"sequence_window",
+	"ecn_incapable", 
+	"ack_ratio",     
+	"send_ack_vector",
+	"send_ndp_count", 
+	"minimum checksum coverage", 
+	"check data checksum",
+};
+
+static int dccp_cksum(register const struct ip *ip,
+	register const struct dccp_hdr *dh, register u_int len)
+{
+	union phu {
+		struct phdr {
+			u_int32_t src;
+			u_int32_t dst;
+			u_char mbz;
+			u_char proto;
+			u_int16_t len;
+		} ph;
+		u_int16_t pa[6];
+	} phu;
+	const u_int16_t *sp;
+
+	/* pseudo-header.. */
+	phu.ph.mbz = 0;
+	phu.ph.len = htons(len);
+	phu.ph.proto = IPPROTO_DCCP;
+	memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
+	if (IP_HL(ip) == 5)
+		memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
+	else
+		phu.ph.dst = ip_finddst(ip);
+
+	sp = &phu.pa[0];
+	return in_cksum((u_short *)dh, len, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
+}
+
+#ifdef INET6
+static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len)
+{
+	size_t i;
+	register const u_int16_t *sp;
+	u_int32_t sum;
+	union {
+		struct {
+			struct in6_addr ph_src;
+			struct in6_addr ph_dst;
+			u_int32_t   ph_len;
+			u_int8_t    ph_zero[3];
+			u_int8_t    ph_nxt;
+		} ph;
+		u_int16_t pa[20];
+	} phu;
+
+	/* pseudo-header */
+	memset(&phu, 0, sizeof(phu));
+	phu.ph.ph_src = ip6->ip6_src;
+	phu.ph.ph_dst = ip6->ip6_dst;
+	phu.ph.ph_len = htonl(len);
+	phu.ph.ph_nxt = IPPROTO_DCCP;
+
+	sum = 0;
+	for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
+		sum += phu.pa[i];
+
+	sp = (const u_int16_t *)dh;
+
+	for (i = 0; i < (len & ~1); i += 2)
+		sum += *sp++;
+
+	if (len & 1)
+		sum += htons((*(const u_int8_t *)sp) << 8);
+
+	while (sum > 0xffff)
+		sum = (sum & 0xffff) + (sum >> 16);
+	sum = ~sum & 0xffff;
+
+	return (sum);
+}
+#endif
+
+static const char *dccp_reset_code(u_int8_t code)
+{
+	if (code >= __DCCP_RESET_CODE_LAST)
+		return "invalid";
+	return dccp_reset_codes[code];
+}
+
+static u_int64_t dccp_seqno(const struct dccp_hdr *dh)
+{
+	u_int32_t seq_high = DCCPH_SEQ(dh);
+	u_int64_t seqno = EXTRACT_24BITS(&seq_high);
+
+	if (DCCPH_X(dh) != 0) {
+		const struct dccp_hdr_ext *dhx = (void *)dh + sizeof(*dh);
+		u_int32_t seq_low = dhx->dccph_seq_low;
+		
+		seqno = (seqno << 32) + EXTRACT_32BITS(&seq_low);
+	}
+
+	return seqno;
+}
+
+static u_int64_t dccp_ack_no(const struct dccp_hdr *dh,
+		const struct dccp_hdr_ack_bits *dh_ack)
+{
+	u_int32_t ack_high = DCCPH_ACK(dh_ack);
+	u_int64_t ackno = EXTRACT_24BITS(&ack_high);
+
+	if (DCCPH_X(dh) != 0) {
+		u_int32_t ack_low = dh_ack->dccph_ack_nr_low;
+		
+		ackno = (ackno << 32) + EXTRACT_32BITS(&ack_low);
+	}
+
+	return ackno;
+}
+
+static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
+{
+	return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0);
+}
+
+static inline unsigned int dccp_packet_hdr_len(const u_int8_t type)
+{
+	if (type == DCCP_PKT_DATA)
+		return 0;
+	if (type == DCCP_PKT_DATAACK	||
+	    type == DCCP_PKT_ACK	||
+	    type == DCCP_PKT_SYNC	||
+	    type == DCCP_PKT_SYNCACK	||
+	    type == DCCP_PKT_CLOSE	||
+	    type == DCCP_PKT_CLOSEREQ)
+		return sizeof(struct dccp_hdr_ack_bits);
+	if (type == DCCP_PKT_REQUEST)
+		return sizeof(struct dccp_hdr_request);
+	if (type == DCCP_PKT_RESPONSE)
+		return sizeof(struct dccp_hdr_response);
+	return sizeof(struct dccp_hdr_reset);
+}
+
+static int dccp_print_option(u_char *option);
+
+/**
+ * dccp_print - show dccp packet
+ * @bp - beginning of dccp packet
+ * @data2 - beginning of enclosing 
+ * @len - lenght of ip packet
+ */
+void dccp_print(const u_char *bp, const u_char *data2, u_int len)
+{
+	const struct dccp_hdr *dh;
+	const struct ip *ip;
+#ifdef INET6
+	const struct ip6_hdr *ip6;
+#endif
+	const u_char *cp;
+	const void *dh_end;
+	u_short sport, dport;
+	int hlen;
+	u_int extlen = 0;
+	u_int64_t seq;
+
+	dh = (const struct dccp_hdr *)bp;
+	dh_end = (const u_char *)dh + len;
+
+	if ((u_long)dh_end > (u_long)snapend)
+		dh_end = (const void *)snapend;
+	ip = (struct ip *)data2;
+#ifdef INET6
+	if (IP_V(ip) == 6)
+		ip6 = (const struct ip6_hdr *)data2;
+	else
+		ip6 = NULL;
+#endif /*INET6*/
+	cp = (const u_char *)(dh + 1);
+	if (cp > snapend) {
+		printf("[Invalid packet|dccp]");
+		return;
+	}
+
+	if (len < sizeof(struct dccp_hdr)) {
+		printf("truncated-dccp - %ld bytes missing!",
+			     (long)len - sizeof(struct dccp_hdr));
+		return;
+	}
+
+	sport = EXTRACT_16BITS(&dh->dccph_sport);
+	dport = EXTRACT_16BITS(&dh->dccph_dport);
+	hlen = dh->dccph_doff * 4;
+
+#ifdef INET6
+	if (ip6) {
+		(void)printf("%s.%d > %s.%d: ",
+			     ip6addr_string(&ip6->ip6_src), sport,
+			     ip6addr_string(&ip6->ip6_dst), dport);
+	} else
+#endif /*INET6*/
+	{
+		(void)printf("%s.%d > %s.%d: ",
+			     ipaddr_string(&ip->ip_src), sport,
+			     ipaddr_string(&ip->ip_dst), dport);
+	}
+	fflush(stdout);
+
+	if (qflag) {
+		(void)printf(" %d", len - hlen);
+		if (hlen > len) {
+			(void)printf("dccp [bad hdr length %u - too long, > %u]",
+			    hlen, len);
+		}
+		return;
+	}
+
+	/* other variables in generic header */
+	if (vflag) {
+		(void)printf("CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh));
+	}
+
+	/* checksum calculation */
+#ifdef INET6
+	if (ip6) {
+		if (ip6->ip6_plen && vflag) {
+			u_int16_t sum, dccp_sum;
+
+			sum = dccp6_cksum(ip6, dh, len);
+			dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);		
+			printf("cksum 0x%04x", dccp_sum);		
+			if (sum != 0) {
+				(void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
+			} else
+				(void)printf(" (correct), ");
+		}					
+	} else 
+#endif /* INET6 */
+	if (vflag)
+	{
+		u_int16_t sum, dccp_sum;
+
+		sum = dccp_cksum(ip, dh, len);
+		dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);		
+		printf("cksum 0x%04x", dccp_sum);		
+		if (sum != 0) {
+			(void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
+		} else
+			(void)printf(" (correct), ");
+	}
+
+	switch (DCCPH_TYPE(dh)) {
+	case DCCP_PKT_REQUEST: {
+		struct dccp_hdr_request *dhr =
+			(struct dccp_hdr_request *)(bp + dccp_basic_hdr_len(dh));
+		TCHECK(*dhr);
+		(void)printf("request (service=%d) ", dhr->dccph_req_service);
+		extlen += 4;
+		break;
+	}
+	case DCCP_PKT_RESPONSE: {
+		struct dccp_hdr_response *dhr =
+			(struct dccp_hdr_response *)(bp + dccp_basic_hdr_len(dh));
+		TCHECK(*dhr);
+		(void)printf("response (service=%d, ack=%" PRIu64 ") ",
+			     dhr->dccph_resp_service,
+			     dccp_ack_no(dh,&(dhr->dccph_resp_ack)));
+		extlen += 12;
+		break;
+	}
+	case DCCP_PKT_DATA:
+		(void)printf("data ");
+		break;
+	case DCCP_PKT_ACK: {
+		struct dccp_hdr_ack_bits *dha =
+			(struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
+		TCHECK(*dha);
+		(void)printf("ack (ack=%" PRIu64 ") ",
+			     dccp_ack_no(dh,dha));
+		extlen += 8;
+		break;
+	}
+	case DCCP_PKT_DATAACK: {
+		struct dccp_hdr_ack_bits *dha =
+			(struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
+		TCHECK(*dha);
+		(void)printf("dataack (ack=%" PRIu64 ") ",
+			     dccp_ack_no(dh,dha));
+		extlen += 8;
+		break;
+	}
+	case DCCP_PKT_CLOSEREQ:
+		(void)printf("closereq ");
+		extlen += 8;
+		break;
+	case DCCP_PKT_CLOSE:
+		(void)printf("close ");
+		extlen += 8;
+		break;
+	case DCCP_PKT_RESET: {
+		struct dccp_hdr_reset *dhr =
+			(struct dccp_hdr_reset *)(bp + dccp_basic_hdr_len(dh));
+		TCHECK(*dhr);
+		(void)printf("reset (code=%s) ",
+			     dccp_reset_code(dhr->dccph_reset_code));
+		extlen += 12;
+		break;
+	}
+	case DCCP_PKT_SYNC:
+		(void)printf("sync ");
+		extlen += 8;
+		break;
+	case DCCP_PKT_SYNCACK:
+		(void)printf("syncack ");
+		extlen += 8;
+		break;
+	default:
+		(void)printf("invalid ");
+		break;
+	}
+
+	if (vflag < 2)
+		return;
+
+	(void)printf("seq %" PRIu64, dccp_seqno(dh));
+
+	/* process options */
+	if (hlen > dccp_basic_hdr_len(dh) + extlen){
+		register const u_char *cp;
+		u_int optlen;
+		cp = bp + dccp_basic_hdr_len(dh) + extlen;
+		printf(" <");	
+
+		hlen -= dccp_basic_hdr_len(dh) + extlen;
+		while(1){
+			TCHECK(*cp);
+			optlen = dccp_print_option(cp);
+			if (!optlen) goto trunc2;
+			hlen -= optlen;
+			if (hlen <= 0) break; 
+			cp += optlen;
+			printf(", ");
+		}
+		printf(">");	
+	}
+	return;
+trunc:
+	printf("[|dccp]");
+trunc2:
+	return;
+}
+
+static int dccp_print_option(u_char *option)
+{	
+	u_int8_t optlen, i;
+	u_int32_t *ts;
+	u_int16_t *var16;
+	u_int32_t *var32;
+
+	TCHECK(*option);
+
+	if (*option >= 32) {
+		TCHECK(*(option+1));
+		optlen = *(option +1);
+		if (optlen < 2) {
+			printf("Option %d optlen too short",*option);
+			return 1;
+		}
+	} else optlen = 1;
+
+	TCHECK2(*option,optlen);
+
+	switch (*option){
+	case 0:
+		printf("nop");
+		break;	
+	case 1:
+		printf("mandatory");
+		break;	
+	case 2:
+		printf("slowreceiver");
+		break;	
+	case 32:
+		printf("change_l");
+		if (*(option +2) < 10){
+			printf(" %s", dccp_feature_nums[*(option +2)]);
+			for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));	
+		}
+		break;	
+	case 33:
+		printf("confirm_l");
+		if (*(option +2) < 10){
+			printf(" %s", dccp_feature_nums[*(option +2)]);
+			for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));	
+		}
+		break;
+	case 34:
+	        printf("change_r");
+		if (*(option +2) < 10){
+			printf(" %s", dccp_feature_nums[*(option +2)]);
+			for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));	
+		}
+		break;
+	case 35:
+		printf("confirm_r");
+		if (*(option +2) < 10){
+			printf(" %s", dccp_feature_nums[*(option +2)]);
+			for (i = 0; i < optlen -3; i ++) printf(" %d", *(option +3 + i));	
+		}
+		break;
+	case 36:
+		printf("initcookie 0x");
+		for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));	
+		break;
+	case 37:
+		printf("ndp_count");
+		for (i = 0; i < optlen -2; i ++) printf(" %d", *(option +2 + i));	
+		break;
+	case 38:
+		printf("ack_vector0 0x");
+		for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));	
+		break;
+	case 39:
+		printf("ack_vector1 0x");
+		for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));	
+		break;
+	case 40:
+		printf("data_dropped 0x");
+		for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));	
+		break;
+	case 41:
+		ts = (u_int32_t *)(option + 2);
+		printf("timestamp %u", ntohl(*ts));
+		break;
+	case 42:
+		ts = (u_int32_t *)(option + 2);
+		printf("timestamp_echo %u", ntohl(*ts));
+		break;
+	case 43:
+		printf("elapsed_time ");
+		if (optlen == 6){
+			ts = (u_int32_t *)(option + 2);
+			printf("%u", ntohl(*ts));
+		} else {
+			var16 = (u_int16_t *)(option + 2);
+			printf("%u", ntohs(*var16));
+		}	
+		break;
+	case 44:
+		printf("data_checksum %x");
+		for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));	
+		break;
+	default :
+		if (*option >= 128) {
+			printf("CCID option %d",*option);
+			switch (optlen) {
+				case 4:
+					var16 = (u_int16_t *)(option + 2);
+					printf(" %u",ntohs(*var16));
+					break;
+				case 6:
+					var32 = (u_int32_t *)(option + 2);
+					printf(" %u",ntohl(*var32));
+					break;
+				default:
+					break;
+			}
+			break;
+		}
+			
+		printf("unknown_opt %d", *option);
+		break;
+	}
+
+	return optlen;
+trunc:
+	printf("[|dccp]");
+	return 0;
+}
diff -urN tcpdump-2005.08.22/print-ip6.c dccpdump/print-ip6.c
--- tcpdump-2005.08.22/print-ip6.c	2005-07-04 08:33:06.000000000 +1200
+++ dccpdump/print-ip6.c	2005-09-05 11:47:05.000000000 +1200
@@ -116,7 +116,7 @@
 
 		if (cp == (const u_char *)(ip6 + 1) &&
 		    nh != IPPROTO_TCP && nh != IPPROTO_UDP &&
-		    nh != IPPROTO_SCTP) {
+		    nh != IPPROTO_DCCP && nh != IPPROTO_SCTP) {
 			(void)printf("%s > %s: ", ip6addr_string(&ip6->ip6_src),
 				     ip6addr_string(&ip6->ip6_dst));
 		}
@@ -160,6 +160,9 @@
 		case IPPROTO_SCTP:
 			sctp_print(cp, (const u_char *)ip6, len);
 			return;
+		case IPPROTO_DCCP:
+			dccp_print(cp, (const u_char *)ip6, len);
+			return;
 		case IPPROTO_TCP:
 			tcp_print(cp, len, (const u_char *)ip6, fragmented);
 			return;
diff -urN tcpdump-2005.08.22/print-ip.c dccpdump/print-ip.c
--- tcpdump-2005.08.22/print-ip.c	2005-05-21 09:02:30.000000000 +1200
+++ dccpdump/print-ip.c	2005-09-05 11:47:05.000000000 +1200
@@ -411,6 +411,10 @@
 	case IPPROTO_SCTP:
 		sctp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
 		break;
+
+	case IPPROTO_DCCP:
+		dccp_print(ipds->cp, (const u_char *)ipds->ip, ipds->len);
+		break;
 		
 	case IPPROTO_TCP:
 		tcp_print(ipds->cp, ipds->len, (const u_char *)ipds->ip,
@@ -665,7 +669,7 @@
 		ipds->nh = ipds->ip->ip_p;
 
 		if (ipds->nh != IPPROTO_TCP && ipds->nh != IPPROTO_UDP &&
-		    ipds->nh != IPPROTO_SCTP) {
+		    ipds->nh != IPPROTO_SCTP && ipds->nh != IPPROTO_DCCP) {
 			(void)printf("%s > %s: ",
 				     ipaddr_string(&ipds->ip->ip_src),
 				     ipaddr_string(&ipds->ip->ip_dst));
-
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.

Reply via email to