#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.2 2005-09-20 06:25:20 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.8 2007-11-09 00:44:09 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
"check data checksum",
};
+static inline int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len)
+{
+ u_int cov;
+
+ if (DCCPH_CSCOV(dh) == 0)
+ return len;
+ cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(u_int32_t);
+ return (cov > len)? len : cov;
+}
+
static int dccp_cksum(const struct ip *ip,
const struct dccp_hdr *dh, u_int len)
{
+ int cov = dccp_csum_coverage(dh, len);
union phu {
struct phdr {
u_int32_t src;
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]);
+ return in_cksum((u_short *)dh, cov, 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;
- const u_int16_t *sp;
- u_int32_t sum;
+ u_int32_t sum = 0;
+ int cov = dccp_csum_coverage(dh, len);
union {
struct {
struct in6_addr ph_src;
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);
+ return in_cksum((u_short *)dh, cov, sum);
}
#endif
u_int64_t seqno = EXTRACT_24BITS(&seq_high) & 0xFFFFFF;
if (DCCPH_X(dh) != 0) {
- const struct dccp_hdr_ext *dhx = (void *)dh + sizeof(*dh);
+ const struct dccp_hdr_ext *dhx = (void *)(dh + 1);
u_int32_t seq_low = dhx->dccph_seq_low;
seqno &= 0x00FFFF; /* clear reserved field */
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)
+static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh)
{
- u_int32_t ack_high = DCCPH_ACK(dh_ack);
- u_int64_t ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF;
+ return sizeof(*dh) + (DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : 0);
+}
+
+static void dccp_print_ack_no(const u_char *bp)
+{
+ const struct dccp_hdr *dh = (const struct dccp_hdr *)bp;
+ const struct dccp_hdr_ack_bits *dh_ack =
+ (struct dccp_hdr_ack_bits *)(bp + dccp_basic_hdr_len(dh));
+ u_int32_t ack_high;
+ u_int64_t ackno;
+
+ TCHECK2(*dh_ack,4);
+ ack_high = DCCPH_ACK(dh_ack);
+ ackno = EXTRACT_24BITS(&ack_high) & 0xFFFFFF;
if (DCCPH_X(dh) != 0) {
- u_int32_t ack_low = dh_ack->dccph_ack_nr_low;
-
+ u_int32_t ack_low;
+
+ TCHECK2(*dh_ack,8);
+ ack_low = dh_ack->dccph_ack_nr_low;
+
ackno &= 0x00FFFF; /* clear reserved field */
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);
+ (void)printf("(ack=%" PRIu64 ") ", ackno);
+trunc:
+ return;
}
static inline unsigned int dccp_packet_hdr_len(const u_int8_t type)
}
/* checksum calculation */
-#ifdef INET6
- if (ip6) {
- if (ip6->ip6_plen && vflag) {
- u_int16_t sum, dccp_sum;
+ if (vflag && TTEST2(bp[0], len)) {
+ u_int16_t sum = 0, dccp_sum;
+ dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
+ (void)printf("cksum 0x%04x ", dccp_sum);
+ if (IP_V(ip) == 4)
+ sum = dccp_cksum(ip, dh, len);
+#ifdef INET6
+ else if (IP_V(ip) == 6)
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), ");
+#endif
+ if (sum != 0)
+ (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
+ else
+ (void)printf("(correct), ");
}
switch (DCCPH_TYPE(dh)) {
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);
+ (void)printf("request (service=%d) ",
+ EXTRACT_32BITS(&dhr->dccph_req_service));
extlen += 4;
break;
}
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)));
+ (void)printf("response (service=%d) ",
+ EXTRACT_32BITS(&dhr->dccph_resp_service));
extlen += 12;
break;
}
(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));
+ (void)printf("ack ");
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));
+ (void)printf("dataack ");
extlen += 8;
break;
}
break;
}
+ if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) &&
+ (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
+ dccp_print_ack_no(bp);
+
if (vflag < 2)
return;
static int dccp_print_option(const u_char *option)
{
u_int8_t optlen, i;
- u_int32_t *ts;
- u_int16_t *var16;
- u_int32_t *var32;
TCHECK(*option);
for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i));
break;
case 41:
- ts = (u_int32_t *)(option + 2);
- printf("timestamp %u", (u_int32_t)ntohl(*ts));
+ printf("timestamp %u", EXTRACT_32BITS(option + 2));
break;
case 42:
- ts = (u_int32_t *)(option + 2);
- printf("timestamp_echo %u", (u_int32_t)ntohl(*ts));
+ printf("timestamp_echo %u", EXTRACT_32BITS(option + 2));
break;
case 43:
printf("elapsed_time ");
- if (optlen == 6){
- ts = (u_int32_t *)(option + 2);
- printf("%u", (u_int32_t)ntohl(*ts));
- } else {
- var16 = (u_int16_t *)(option + 2);
- printf("%u", ntohs(*var16));
- }
+ if (optlen == 6)
+ printf("%u", EXTRACT_32BITS(option + 2));
+ else
+ printf("%u", EXTRACT_16BITS(option + 2));
break;
case 44:
printf("data_checksum ");
printf("CCID option %d",*option);
switch (optlen) {
case 4:
- var16 = (u_int16_t *)(option + 2);
- printf(" %u",ntohs(*var16));
+ printf(" %u", EXTRACT_16BITS(option + 2));
break;
case 6:
- var32 = (u_int32_t *)(option + 2);
- printf(" %u",(u_int32_t)ntohl(*var32));
+ printf(" %u", EXTRACT_32BITS(option + 2));
break;
default:
break;