X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/69cb46af9119e8b5554bcc4bf1bf36f39cb82131..d2777156522f139a858bd6b5b51e364826bc95a7:/print-dccp.c diff --git a/print-dccp.c b/print-dccp.c index 09cf72b2..39234575 100644 --- a/print-dccp.c +++ b/print-dccp.c @@ -7,22 +7,21 @@ * BSD-style license that accompanies tcpdump or the GNU GPL version 2 */ +/* \summary: Datagram Congestion Control Protocol (DCCP) printer */ + +/* specification: RFC 4340 */ + #ifdef HAVE_CONFIG_H -#include "config.h" +#include #endif -#include +#include "netdissect-stdinc.h" -#include -#include - -#include "interface.h" +#include "netdissect.h" #include "addrtoname.h" -#include "extract.h" /* must come after interface.h */ +#include "extract.h" #include "ip.h" -#ifdef INET6 #include "ip6.h" -#endif #include "ipproto.h" /* RFC4340: Datagram Congestion Control Protocol (DCCP) */ @@ -42,14 +41,14 @@ * @dccph_seq - 24-bit sequence number */ struct dccp_hdr { - uint16_t dccph_sport, + nd_uint16_t dccph_sport, dccph_dport; - uint8_t dccph_doff; - uint8_t dccph_ccval_cscov; - uint16_t dccph_checksum; - uint8_t dccph_xtr; - uint8_t dccph_seq[3]; -} UNALIGNED; + nd_uint8_t dccph_doff; + nd_uint8_t dccph_ccval_cscov; + nd_uint16_t dccph_checksum; + nd_uint8_t dccph_xtr; + nd_uint24_t dccph_seq; +}; /** * struct dccp_hdr_ext - generic part of DCCP packet header, with a 48-bit @@ -66,41 +65,41 @@ struct dccp_hdr { * @dccph_seq - 48-bit sequence number */ struct dccp_hdr_ext { - uint16_t dccph_sport, + nd_uint16_t dccph_sport, dccph_dport; - uint8_t dccph_doff; - uint8_t dccph_ccval_cscov; - uint16_t dccph_checksum; - uint8_t dccph_xtr; - uint8_t reserved; - uint8_t dccph_seq[6]; -} UNALIGNED; + nd_uint8_t dccph_doff; + nd_uint8_t dccph_ccval_cscov; + nd_uint16_t dccph_checksum; + nd_uint8_t dccph_xtr; + nd_uint8_t reserved; + nd_uint48_t dccph_seq; +}; -#define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov >> 4) & 0xF) -#define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov) & 0xF) +#define DCCPH_CCVAL(dh) ((GET_U_1((dh)->dccph_ccval_cscov) >> 4) & 0xF) +#define DCCPH_CSCOV(dh) (GET_U_1((dh)->dccph_ccval_cscov) & 0xF) -#define DCCPH_X(dh) ((dh)->dccph_xtr & 1) -#define DCCPH_TYPE(dh) (((dh)->dccph_xtr >> 1) & 0xF) +#define DCCPH_X(dh) (GET_U_1((dh)->dccph_xtr) & 1) +#define DCCPH_TYPE(dh) ((GET_U_1((dh)->dccph_xtr) >> 1) & 0xF) /** - * struct dccp_hdr_request - Conection initiation request header + * struct dccp_hdr_request - Connection initiation request header * * @dccph_req_service - Service to which the client app wants to connect */ struct dccp_hdr_request { - uint32_t dccph_req_service; -} UNALIGNED; + nd_uint32_t dccph_req_service; +}; /** - * struct dccp_hdr_response - Conection initiation response header + * struct dccp_hdr_response - Connection initiation response header * * @dccph_resp_ack - 48 bit ack number, contains GSR * @dccph_resp_service - Echoes the Service Code on a received DCCP-Request */ struct dccp_hdr_response { - uint8_t dccph_resp_ack[8]; /* always 8 bytes */ - uint32_t dccph_resp_service; -} UNALIGNED; + nd_uint64_t dccph_resp_ack; /* always 8 bytes, first 2 reserved */ + nd_uint32_t dccph_resp_service; +}; /** * struct dccp_hdr_reset - Unconditionally shut down a connection @@ -109,10 +108,12 @@ struct dccp_hdr_response { * @dccph_reset_service - Echoes the Service Code on a received DCCP-Request */ struct dccp_hdr_reset { - uint8_t dccph_reset_ack[8]; /* always 8 bytes */ - uint8_t dccph_reset_code, - dccph_reset_data[3]; -} UNALIGNED; + nd_uint64_t dccph_reset_ack; /* always 8 bytes, first 2 reserved */ + nd_uint8_t dccph_reset_code; + nd_uint8_t dccph_reset_data1; + nd_uint8_t dccph_reset_data2; + nd_uint8_t dccph_reset_data3; +}; enum dccp_pkt_type { DCCP_PKT_REQUEST = 0, @@ -157,7 +158,6 @@ enum dccp_reset_codes { __DCCP_RESET_CODE_LAST }; -static const char tstr[] = "[|dccp]"; static const char *dccp_reset_codes[] = { "unspecified", @@ -187,30 +187,31 @@ static const char *dccp_feature_nums[] = { "check data checksum", }; -static inline u_int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len) +static u_int +dccp_csum_coverage(netdissect_options *ndo, + 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(uint32_t); + cov = (GET_U_1(dh->dccph_doff) + DCCPH_CSCOV(dh) - 1) * sizeof(uint32_t); return (cov > len)? len : cov; } -static int dccp_cksum(netdissect_options *ndo, const struct ip *ip, +static uint16_t dccp_cksum(netdissect_options *ndo, const struct ip *ip, const struct dccp_hdr *dh, u_int len) { return nextproto4_cksum(ndo, ip, (const uint8_t *)(const void *)dh, len, - dccp_csum_coverage(dh, len), IPPROTO_DCCP); + dccp_csum_coverage(ndo, dh, len), IPPROTO_DCCP); } -#ifdef INET6 -static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len) +static uint16_t dccp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, + const struct dccp_hdr *dh, u_int len) { - return nextproto6_cksum(ip6, (const uint8_t *)(const void *)dh, len, - dccp_csum_coverage(dh, len), IPPROTO_DCCP); + return nextproto6_cksum(ndo, ip6, (const uint8_t *)(const void *)dh, len, + dccp_csum_coverage(ndo, dh, len), IPPROTO_DCCP); } -#endif static const char *dccp_reset_code(uint8_t code) { @@ -219,22 +220,24 @@ static const char *dccp_reset_code(uint8_t code) return dccp_reset_codes[code]; } -static uint64_t dccp_seqno(const u_char *bp) +static uint64_t +dccp_seqno(netdissect_options *ndo, const u_char *bp) { const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; uint64_t seqno; if (DCCPH_X(dh) != 0) { const struct dccp_hdr_ext *dhx = (const struct dccp_hdr_ext *)bp; - seqno = EXTRACT_48BITS(dhx->dccph_seq); + seqno = GET_BE_U_6(dhx->dccph_seq); } else { - seqno = EXTRACT_24BITS(dh->dccph_seq); + seqno = GET_BE_U_3(dh->dccph_seq); } return seqno; } -static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) +static unsigned int +dccp_basic_hdr_len(netdissect_options *ndo, const struct dccp_hdr *dh) { return DCCPH_X(dh) ? sizeof(struct dccp_hdr_ext) : sizeof(struct dccp_hdr); } @@ -242,129 +245,116 @@ static inline unsigned int dccp_basic_hdr_len(const struct dccp_hdr *dh) static void dccp_print_ack_no(netdissect_options *ndo, const u_char *bp) { const struct dccp_hdr *dh = (const struct dccp_hdr *)bp; - const u_char *ackp = bp + dccp_basic_hdr_len(dh); + const u_char *ackp = bp + dccp_basic_hdr_len(ndo, dh); uint64_t ackno; if (DCCPH_X(dh) != 0) { - ND_TCHECK2(*ackp, 8); - ackno = EXTRACT_48BITS(ackp + 2); + ackno = GET_BE_U_6(ackp + 2); } else { - ND_TCHECK2(*ackp, 4); - ackno = EXTRACT_24BITS(ackp + 1); + ackno = GET_BE_U_3(ackp + 1); } - ND_PRINT((ndo, "(ack=%" PRIu64 ") ", ackno)); -trunc: - return; + ND_PRINT("(ack=%" PRIu64 ") ", ackno); } -static int dccp_print_option(netdissect_options *, const u_char *, u_int); +static u_int dccp_print_option(netdissect_options *, const u_char *, u_int); /** * dccp_print - show dccp packet * @bp - beginning of dccp packet * @data2 - beginning of enclosing - * @len - lenght of ip packet + * @len - length of ip packet */ -void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, - u_int len) +void +dccp_print(netdissect_options *ndo, 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; u_short sport, dport; u_int hlen; u_int fixed_hdrlen; uint8_t dccph_type; + ndo->ndo_protocol = "dccp"; dh = (const struct dccp_hdr *)bp; ip = (const struct ip *)data2; -#ifdef INET6 if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)data2; else ip6 = NULL; -#endif /*INET6*/ /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); - if (cp > ndo->ndo_snapend) { - ND_PRINT((ndo, "[Invalid packet|dccp]")); - return; - } + if (cp > ndo->ndo_snapend) + goto trunc; if (len < sizeof(struct dccp_hdr)) { - ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", - len - (u_int)sizeof(struct dccp_hdr))); + ND_PRINT("truncated-dccp - %zu bytes missing!", + sizeof(struct dccp_hdr) - len); return; } /* get the length of the generic header */ - fixed_hdrlen = dccp_basic_hdr_len(dh); + fixed_hdrlen = dccp_basic_hdr_len(ndo, dh); if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-dccp - %u bytes missing!", - len - fixed_hdrlen)); + ND_PRINT("truncated-dccp - %u bytes missing!", + fixed_hdrlen - len); return; } - ND_TCHECK2(*dh, fixed_hdrlen); + ND_TCHECK_LEN(dh, fixed_hdrlen); - sport = EXTRACT_16BITS(&dh->dccph_sport); - dport = EXTRACT_16BITS(&dh->dccph_dport); - hlen = dh->dccph_doff * 4; + sport = GET_BE_U_2(dh->dccph_sport); + dport = GET_BE_U_2(dh->dccph_dport); + hlen = GET_U_1(dh->dccph_doff) * 4; -#ifdef INET6 if (ip6) { - ND_PRINT((ndo, "%s.%d > %s.%d: ", - ip6addr_string(ndo, &ip6->ip6_src), sport, - ip6addr_string(ndo, &ip6->ip6_dst), dport)); - } else -#endif /*INET6*/ - { - ND_PRINT((ndo, "%s.%d > %s.%d: ", - ipaddr_string(ndo, &ip->ip_src), sport, - ipaddr_string(ndo, &ip->ip_dst), dport)); + ND_PRINT("%s.%u > %s.%u: ", + GET_IP6ADDR_STRING(ip6->ip6_src), sport, + GET_IP6ADDR_STRING(ip6->ip6_dst), dport); + } else { + ND_PRINT("%s.%u > %s.%u: ", + GET_IPADDR_STRING(ip->ip_src), sport, + GET_IPADDR_STRING(ip->ip_dst), dport); } - ND_PRINT((ndo, "DCCP")); + nd_print_protocol_caps(ndo); if (ndo->ndo_qflag) { - ND_PRINT((ndo, " %d", len - hlen)); + ND_PRINT(" %u", len - hlen); if (hlen > len) { - ND_PRINT((ndo, " [bad hdr length %u - too long, > %u]", - hlen, len)); + ND_PRINT(" [bad hdr length %u - too long, > %u]", + hlen, len); } return; } /* other variables in generic header */ if (ndo->ndo_vflag) { - ND_PRINT((ndo, " (CCVal %d, CsCov %d, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh))); + ND_PRINT(" (CCVal %u, CsCov %u", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); } /* checksum calculation */ - if (ndo->ndo_vflag && ND_TTEST2(bp[0], len)) { + if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) { uint16_t sum = 0, dccp_sum; - dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum); - ND_PRINT((ndo, "cksum 0x%04x ", dccp_sum)); + dccp_sum = GET_BE_U_2(dh->dccph_checksum); + ND_PRINT(", cksum 0x%04x ", dccp_sum); if (IP_V(ip) == 4) sum = dccp_cksum(ndo, ip, dh, len); -#ifdef INET6 else if (IP_V(ip) == 6) - sum = dccp6_cksum(ip6, dh, len); -#endif + sum = dccp6_cksum(ndo, ip6, dh, len); if (sum != 0) - ND_PRINT((ndo, "(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum))); + ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum)); else - ND_PRINT((ndo, "(correct)")); + ND_PRINT("(correct)"); } if (ndo->ndo_vflag) - ND_PRINT((ndo, ")")); - ND_PRINT((ndo, " ")); + ND_PRINT(")"); + ND_PRINT(" "); dccph_type = DCCPH_TYPE(dh); switch (dccph_type) { @@ -373,15 +363,15 @@ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, (const struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_TCHECK(*dhr); - ND_PRINT((ndo, "%s (service=%d) ", + ND_TCHECK_SIZE(dhr); + ND_PRINT("%s (service=%u) ", tok2str(dccp_pkt_type_str, "", dccph_type), - EXTRACT_32BITS(&dhr->dccph_req_service))); + GET_BE_U_4(dhr->dccph_req_service)); break; } case DCCP_PKT_RESPONSE: { @@ -389,100 +379,100 @@ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, (const struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_TCHECK(*dhr); - ND_PRINT((ndo, "%s (service=%d) ", + ND_TCHECK_SIZE(dhr); + ND_PRINT("%s (service=%u) ", tok2str(dccp_pkt_type_str, "", dccph_type), - EXTRACT_32BITS(&dhr->dccph_resp_service))); + GET_BE_U_4(dhr->dccph_resp_service)); break; } case DCCP_PKT_DATA: - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_RESET: { const struct dccp_hdr_reset *dhr = (const struct dccp_hdr_reset *)(bp + fixed_hdrlen); fixed_hdrlen += 12; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_TCHECK(*dhr); - ND_PRINT((ndo, "%s (code=%s) ", + ND_TCHECK_SIZE(dhr); + ND_PRINT("%s (code=%s) ", tok2str(dccp_pkt_type_str, "", dccph_type), - dccp_reset_code(dhr->dccph_reset_code))); + dccp_reset_code(GET_U_1(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; if (len < fixed_hdrlen) { - ND_PRINT((ndo, "truncated-%s - %u bytes missing!", + ND_PRINT("truncated-%s - %u bytes missing!", tok2str(dccp_pkt_type_str, "", dccph_type), - len - fixed_hdrlen)); + fixed_hdrlen - len); return; } - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; default: - ND_PRINT((ndo, "%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type))); + ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type)); break; } @@ -493,14 +483,13 @@ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, if (ndo->ndo_vflag < 2) return; - ND_PRINT((ndo, "seq %" PRIu64, dccp_seqno(bp))); + ND_PRINT("seq %" PRIu64, dccp_seqno(ndo, bp)); /* process options */ if (hlen > fixed_hdrlen){ - const u_char *cp; u_int optlen; cp = bp + fixed_hdrlen; - ND_PRINT((ndo, " <")); + ND_PRINT(" <"); hlen -= fixed_hdrlen; while(1){ @@ -511,14 +500,13 @@ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, break; hlen -= optlen; cp += optlen; - ND_PRINT((ndo, ", ")); + ND_PRINT(", "); } - ND_PRINT((ndo, ">")); + ND_PRINT(">"); } return; trunc: - ND_PRINT((ndo, "%s", tstr)); - return; + nd_print_trunc(ndo); } static const struct tok dccp_option_values[] = { @@ -541,123 +529,170 @@ static const struct tok dccp_option_values[] = { { 0, NULL } }; -static int dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) +static u_int +dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) { uint8_t optlen, i; - ND_TCHECK(*option); - - if (*option >= 32) { - ND_TCHECK(*(option+1)); - optlen = *(option +1); + if (GET_U_1(option) >= 32) { + optlen = GET_U_1(option + 1); if (optlen < 2) { - if (*option >= 128) - ND_PRINT((ndo, "CCID option %u optlen too short", *option)); + if (GET_U_1(option) >= 128) + ND_PRINT("CCID option %u optlen too short", + GET_U_1(option)); else - ND_PRINT((ndo, "%s optlen too short", - tok2str(dccp_option_values, "Option %u", *option))); + ND_PRINT("%s optlen too short", + tok2str(dccp_option_values, "Option %u", GET_U_1(option))); return 0; } } else optlen = 1; if (hlen < optlen) { - if (*option >= 128) - ND_PRINT((ndo, "CCID option %u optlen goes past header length", - *option)); + if (GET_U_1(option) >= 128) + ND_PRINT("CCID option %u optlen goes past header length", + GET_U_1(option)); else - ND_PRINT((ndo, "%s optlen goes past header length", - tok2str(dccp_option_values, "Option %u", *option))); + ND_PRINT("%s optlen goes past header length", + tok2str(dccp_option_values, "Option %u", GET_U_1(option))); return 0; } - ND_TCHECK2(*option, optlen); + ND_TCHECK_LEN(option, optlen); - if (*option >= 128) { - ND_PRINT((ndo, "CCID option %d", *option)); + if (GET_U_1(option) >= 128) { + ND_PRINT("CCID option %u", GET_U_1(option)); switch (optlen) { case 4: - ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); + ND_PRINT(" %u", GET_BE_U_2(option + 2)); break; case 6: - ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); + ND_PRINT(" %u", GET_BE_U_4(option + 2)); break; default: break; } } else { - ND_PRINT((ndo, "%s", tok2str(dccp_option_values, "Option %u", *option))); - switch (*option) { + ND_PRINT("%s", + tok2str(dccp_option_values, "Option %u", GET_U_1(option))); + switch (GET_U_1(option)) { case 32: case 33: case 34: case 35: if (optlen < 3) { - ND_PRINT((ndo, " optlen too short")); + ND_PRINT(" optlen too short"); return optlen; } - if (*(option + 2) < 10){ - ND_PRINT((ndo, " %s", dccp_feature_nums[*(option + 2)])); + if (GET_U_1(option + 2) < 10){ + ND_PRINT(" %s", + dccp_feature_nums[GET_U_1(option + 2)]); for (i = 0; i < optlen - 3; i++) - ND_PRINT((ndo, " %d", *(option + 3 + i))); + ND_PRINT(" %u", + GET_U_1(option + 3 + i)); } break; case 36: if (optlen > 2) { - ND_PRINT((ndo, " 0x")); + ND_PRINT(" 0x"); for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, "%02x", *(option + 2 + i))); + ND_PRINT("%02x", + GET_U_1(option + 2 + i)); } break; case 37: for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, " %d", *(option + 2 + i))); + ND_PRINT(" %u", GET_U_1(option + 2 + i)); break; case 38: if (optlen > 2) { - ND_PRINT((ndo, " 0x")); + ND_PRINT(" 0x"); for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, "%02x", *(option + 2 + i))); + ND_PRINT("%02x", + GET_U_1(option + 2 + i)); } break; case 39: if (optlen > 2) { - ND_PRINT((ndo, " 0x")); + ND_PRINT(" 0x"); for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, "%02x", *(option + 2 + i))); + ND_PRINT("%02x", + GET_U_1(option + 2 + i)); } break; case 40: if (optlen > 2) { - ND_PRINT((ndo, " 0x")); + ND_PRINT(" 0x"); for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, "%02x", *(option + 2 + i))); + ND_PRINT("%02x", + GET_U_1(option + 2 + i)); } break; case 41: - if (optlen == 4) - ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); + /* + * 13.1. Timestamp Option + * + * +--------+--------+--------+--------+--------+--------+ + * |00101001|00000110| Timestamp Value | + * +--------+--------+--------+--------+--------+--------+ + * Type=41 Length=6 + */ + if (optlen == 6) + ND_PRINT(" %u", GET_BE_U_4(option + 2)); else - ND_PRINT((ndo, " optlen != 4")); + ND_PRINT(" [optlen != 6]"); break; case 42: - if (optlen == 4) - ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); - else - ND_PRINT((ndo, " optlen != 4")); + /* + * 13.3. Timestamp Echo Option + * + * +--------+--------+--------+--------+--------+--------+ + * |00101010|00000110| Timestamp Echo | + * +--------+--------+--------+--------+--------+--------+ + * Type=42 Len=6 + * + * +--------+--------+------- ... -------+--------+--------+ + * |00101010|00001000| Timestamp Echo | Elapsed Time | + * +--------+--------+------- ... -------+--------+--------+ + * Type=42 Len=8 (4 bytes) + * + * +--------+--------+------- ... -------+------- ... -------+ + * |00101010|00001010| Timestamp Echo | Elapsed Time | + * +--------+--------+------- ... -------+------- ... -------+ + * Type=42 Len=10 (4 bytes) (4 bytes) + */ + switch (optlen) { + case 6: + ND_PRINT(" %u", GET_BE_U_4(option + 2)); + break; + case 8: + ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" (elapsed time %u)", + GET_BE_U_2(option + 6)); + break; + case 10: + ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" (elapsed time %u)", + GET_BE_U_4(option + 6)); + break; + default: + ND_PRINT(" [optlen != 6 or 8 or 10]"); + break; + } break; case 43: if (optlen == 6) - ND_PRINT((ndo, " %u", EXTRACT_32BITS(option + 2))); + ND_PRINT(" %u", GET_BE_U_4(option + 2)); else if (optlen == 4) - ND_PRINT((ndo, " %u", EXTRACT_16BITS(option + 2))); + ND_PRINT(" %u", GET_BE_U_2(option + 2)); else - ND_PRINT((ndo, " optlen != 4 or 6")); + ND_PRINT(" [optlen != 4 or 6]"); break; case 44: if (optlen > 2) { - ND_PRINT((ndo, " ")); + ND_PRINT(" "); for (i = 0; i < optlen - 2; i++) - ND_PRINT((ndo, "%02x", *(option + 2 + i))); + ND_PRINT("%02x", + GET_U_1(option + 2 + i)); } break; } @@ -665,6 +700,6 @@ static int dccp_print_option(netdissect_options *ndo, const u_char *option, u_in return optlen; trunc: - ND_PRINT((ndo, "%s", tstr)); + nd_print_trunc(ndo); return 0; }