--- print-dccp.c.orig 2005-08-04 03:09:21.000000000 +0900 +++ print-dccp.c 2005-08-04 03:08:42.000000000 +0900 @@ -24,6 +24,7 @@ #ifdef INET6 #include "ip6.h" #endif +#include "ipproto.h" static const char *dccp_reset_codes[] = { "unspecified", @@ -40,6 +41,92 @@ static const char *dccp_reset_codes[] = "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) @@ -108,7 +195,9 @@ void dccp_print(const u_char *bp, const const u_char *cp; const void *dh_end; u_short sport, dport; - u_int hlen; + u_int hlen, extlen = 0; + u_int64_t seq; + static int dccp_print_option(); dh = (const struct dccp_hdr *)bp; dh_end = (const u_char *)dh + len; @@ -161,11 +250,46 @@ void dccp_print(const u_char *bp, const return; } + /* other variables in generic header */ + if (vflag) { + (void)printf("CCVal %d, CsCov %d, ", dh->dccph_ccval, dh->dccph_cscov); + } + + /* 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 (dh->dccph_type) { case DCCP_PKT_REQUEST: { struct dccp_hdr_request *dhr = (struct dccp_hdr_request *)(bp + dccp_hdr_len(dh)); (void)printf("request (service=%d) ", dhr->dccph_req_service); + extlen += 4; break; } case DCCP_PKT_RESPONSE: { @@ -174,6 +298,7 @@ void dccp_print(const u_char *bp, const (void)printf("response (service=%d, ack=%" PRIu64 ") ", dhr->dccph_resp_service, dccp_ack_no(&(dhr->dccph_resp_ack))); + extlen += 12; break; } case DCCP_PKT_DATA: @@ -184,6 +309,7 @@ void dccp_print(const u_char *bp, const (struct dccp_hdr_data *)(bp + dccp_hdr_len(dh)); (void)printf("ack (ack=%" PRIu64 ") ", dccp_ack_no(&(dhr->dccph_data_ack))); + extlen += 8; break; } case DCCP_PKT_DATAACK: { @@ -191,26 +317,32 @@ void dccp_print(const u_char *bp, const (struct dccp_hdr_data *)(bp + dccp_hdr_len(dh)); (void)printf("dataack (ack=%" PRIu64 ") ", dccp_ack_no(&(dhr->dccph_data_ack))); + 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_hdr_len(dh)); (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 "); @@ -221,4 +353,117 @@ void dccp_print(const u_char *bp, const return; (void)printf("seq %" PRIu64, dccp_seqno(dh)); + + /* process options */ + if (hlen > dccp_hdr_len(dh) + extlen){ + register const u_char *cp; + u_int optlen; + cp = bp + dccp_hdr_len(dh) + extlen; + printf(" <"); + + hlen -= dccp_hdr_len(dh) + extlen; + while(1){ + optlen = dccp_print_option(cp); + hlen -= optlen; + if (hlen <= 0) break; + cp += optlen; + printf(", "); + } + printf(">"); + } +} + +static int dccp_print_option(u_char *option) +{ + u_int32_t optlen, i, *ts; + + if (*option > 32) optlen = *(option +1); + else optlen = 1; + + 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 { + (u_int16_t *)ts = (u_int16_t *)(option + 2); + printf("%u", ntohs(*ts)); + } + break; + case 44: + printf("data_checksum %x"); + for (i = 0; i < optlen -2; i ++) printf("%02x", *(option +2 + i)); + break; + default : + printf("unknown_opt %d", *option); + break; + } + + return optlen; }