X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/794a259a335c367d852959cd88dd9d46d183a74b..a63600a1fc28dbc7ae7ce9f996829c49a25fb33c:/print-dccp.c diff --git a/print-dccp.c b/print-dccp.c index e82b9381..5a0890a9 100644 --- a/print-dccp.c +++ b/print-dccp.c @@ -17,6 +17,7 @@ #include "netdissect-stdinc.h" +#define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "addrtoname.h" #include "extract.h" @@ -182,8 +183,8 @@ static const struct tok dccp_feature_num_str[] = { { 5, "ack_ratio" }, { 6, "send_ack_vector" }, { 7, "send_ndp_count" }, - { 8, "minimum checksum coverage" }, - { 9, "check data checksum" }, + { 8, "minimum_checksum_coverage" }, + { 9, "check_data_checksum" }, { 0, NULL } }; @@ -260,7 +261,7 @@ static u_int dccp_print_option(netdissect_options *, const u_char *, u_int); */ void dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, - u_int len) + u_int length) { const struct dccp_hdr *dh; const struct ip *ip; @@ -280,23 +281,12 @@ dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, else ip6 = NULL; - /* make sure we have enough data to look at the X bit */ cp = (const u_char *)(dh + 1); - if (cp > ndo->ndo_snapend) - goto trunc; - if (len < sizeof(struct dccp_hdr)) { - ND_PRINT("truncated-dccp - %zu bytes missing!", - sizeof(struct dccp_hdr) - len); - return; - } + ND_ICHECK_ZU(length, <, sizeof(struct dccp_hdr)); /* get the length of the generic header */ fixed_hdrlen = dccp_basic_hdr_len(ndo, dh); - if (len < fixed_hdrlen) { - ND_PRINT("truncated-dccp - %u bytes missing!", - fixed_hdrlen - len); - return; - } + ND_ICHECK_U(length, <, fixed_hdrlen); ND_TCHECK_LEN(dh, fixed_hdrlen); sport = GET_BE_U_2(dh->dccph_sport); @@ -316,156 +306,92 @@ dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, nd_print_protocol_caps(ndo); if (ndo->ndo_qflag) { - ND_PRINT(" %u", len - hlen); - if (hlen > len) { - ND_PRINT(" [bad hdr length %u - too long, > %u]", - hlen, len); - } + ND_ICHECK_U(length, <, hlen); + ND_PRINT(" %u", length - hlen); return; } /* other variables in generic header */ if (ndo->ndo_vflag) { - ND_PRINT(" (CCVal %u, CsCov %u, ", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); - } - - /* checksum calculation */ - if (ndo->ndo_vflag && ND_TTEST_LEN(bp, len)) { - uint16_t sum = 0, 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); - else if (IP_V(ip) == 6) - sum = dccp6_cksum(ndo, ip6, dh, len); - if (sum != 0) - ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum)); - else - ND_PRINT("(correct)"); - } - - if (ndo->ndo_vflag) + ND_PRINT(" (CCVal %u, CsCov %u", DCCPH_CCVAL(dh), DCCPH_CSCOV(dh)); + /* checksum calculation */ + if (ND_TTEST_LEN(bp, length)) { + uint16_t sum = 0, 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, length); + else if (IP_V(ip) == 6) + sum = dccp6_cksum(ndo, ip6, dh, length); + if (sum != 0) + ND_PRINT("(incorrect -> 0x%04x)",in_cksum_shouldbe(dccp_sum, sum)); + else + ND_PRINT("(correct)"); + } ND_PRINT(")"); - ND_PRINT(" "); + } dccph_type = DCCPH_TYPE(dh); + ND_PRINT(" %s ", tok2str(dccp_pkt_type_str, "packet-type-%u", + dccph_type)); switch (dccph_type) { case DCCP_PKT_REQUEST: { const struct dccp_hdr_request *dhr = (const struct dccp_hdr_request *)(bp + fixed_hdrlen); fixed_hdrlen += 4; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_TCHECK_SIZE(dhr); - ND_PRINT("%s (service=%u) ", - tok2str(dccp_pkt_type_str, "", dccph_type), - GET_BE_U_4(dhr->dccph_req_service)); + ND_ICHECK_U(length, <, fixed_hdrlen); + ND_PRINT("(service=%u) ", GET_BE_U_4(dhr->dccph_req_service)); break; } case DCCP_PKT_RESPONSE: { const struct dccp_hdr_response *dhr = (const struct dccp_hdr_response *)(bp + fixed_hdrlen); fixed_hdrlen += 12; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_TCHECK_SIZE(dhr); - ND_PRINT("%s (service=%u) ", - tok2str(dccp_pkt_type_str, "", dccph_type), - GET_BE_U_4(dhr->dccph_resp_service)); + ND_ICHECK_U(length, <, fixed_hdrlen); + ND_PRINT("(service=%u) ", GET_BE_U_4(dhr->dccph_resp_service)); break; } case DCCP_PKT_DATA: - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); break; case DCCP_PKT_ACK: { fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); break; } case DCCP_PKT_DATAACK: { fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); break; } case DCCP_PKT_CLOSEREQ: fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); break; case DCCP_PKT_CLOSE: fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); 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("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } + ND_ICHECK_U(length, <, fixed_hdrlen); ND_TCHECK_SIZE(dhr); - ND_PRINT("%s (code=%s) ", - tok2str(dccp_pkt_type_str, "", dccph_type), - tok2str(dccp_reset_code_str, "invalid", GET_U_1(dhr->dccph_reset_code))); + ND_PRINT("(code=%s) ", tok2str(dccp_reset_code_str, + "reset-code-%u (invalid)", GET_U_1(dhr->dccph_reset_code))); break; } case DCCP_PKT_SYNC: fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); break; case DCCP_PKT_SYNCACK: fixed_hdrlen += 8; - if (len < fixed_hdrlen) { - ND_PRINT("truncated-%s - %u bytes missing!", - tok2str(dccp_pkt_type_str, "", dccph_type), - fixed_hdrlen - len); - return; - } - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "", dccph_type)); + ND_ICHECK_U(length, <, fixed_hdrlen); break; default: - ND_PRINT("%s ", tok2str(dccp_pkt_type_str, "unknown-type-%u", dccph_type)); + goto invalid; break; } @@ -488,7 +414,7 @@ dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, while(1){ optlen = dccp_print_option(ndo, cp, hlen); if (!optlen) - break; + goto invalid; if (hlen <= optlen) break; hlen -= optlen; @@ -498,8 +424,8 @@ dccp_print(netdissect_options *ndo, const u_char *bp, const u_char *data2, ND_PRINT(">"); } return; -trunc: - nd_print_trunc(ndo); +invalid: + nd_print_invalid(ndo); } enum dccp_option_type { @@ -542,99 +468,85 @@ static const struct tok dccp_option_values[] = { }; static u_int -dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) +dccp_print_option(netdissect_options *ndo, const u_char *bp, u_int hlen) { - uint8_t optlen, i; - - if (GET_U_1(option) >= 32) { - optlen = GET_U_1(option + 1); - if (optlen < 2) { - if (GET_U_1(option) >= 128) - ND_PRINT("CCID option %u optlen too short", - GET_U_1(option)); - else - ND_PRINT("%s optlen too short", - tok2str(dccp_option_values, "Option %u", GET_U_1(option))); - return 0; - } + uint8_t option, optlen, i; + + option = GET_U_1(bp); + if (option >= 128) + ND_PRINT("CCID option %u", option); + else + ND_PRINT("%s", + tok2str(dccp_option_values, "option-type-%u", option)); + if (option >= 32) { + optlen = GET_U_1(bp + 1); + ND_ICHECK_U(optlen, <, 2); } else optlen = 1; - if (hlen < optlen) { - if (GET_U_1(option) >= 128) - ND_PRINT("CCID option %u optlen goes past header length", - GET_U_1(option)); - else - ND_PRINT("%s optlen goes past header length", - tok2str(dccp_option_values, "Option %u", GET_U_1(option))); - return 0; - } - ND_TCHECK_LEN(option, optlen); + ND_ICHECKMSG_U("remaining length", hlen, <, optlen); - if (GET_U_1(option) >= 128) { - ND_PRINT("CCID option %u", GET_U_1(option)); + if (option >= 128) { switch (optlen) { case 4: - ND_PRINT(" %u", GET_BE_U_2(option + 2)); + ND_PRINT(" %u", GET_BE_U_2(bp + 2)); break; case 6: - ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); break; default: + ND_PRINT(" 0x"); + for (i = 0; i < optlen - 2; i++) + ND_PRINT("%02x", GET_U_1(bp + 2 + i)); break; } } else { - ND_PRINT("%s", - tok2str(dccp_option_values, "Option %u", GET_U_1(option))); - switch (GET_U_1(option)) { + switch (option) { + case DCCP_OPTION_PADDING: + case DCCP_OPTION_MANDATORY: + case DCCP_OPTION_SLOW_RECEIVER: + ND_TCHECK_1(bp); + break; case DCCP_OPTION_CHANGE_L: - case DCCP_OPTION_CONFIRM_L: case DCCP_OPTION_CHANGE_R: + ND_ICHECK_U(optlen, <, 4); + ND_PRINT(" %s", tok2str(dccp_feature_num_str, + "feature-number-%u (invalid)", GET_U_1(bp + 2))); + for (i = 0; i < optlen - 3; i++) + ND_PRINT(" %u", GET_U_1(bp + 3 + i)); + break; + case DCCP_OPTION_CONFIRM_L: case DCCP_OPTION_CONFIRM_R: - if (optlen < 3) { - ND_PRINT(" optlen too short"); - return optlen; - } + ND_ICHECK_U(optlen, <, 3); ND_PRINT(" %s", tok2str(dccp_feature_num_str, - "invalid (%u)", GET_U_1(option + 2))); + "feature-number-%u (invalid)", GET_U_1(bp + 2))); for (i = 0; i < optlen - 3; i++) - ND_PRINT(" %u", GET_U_1(option + 3 + i)); + ND_PRINT(" %u", GET_U_1(bp + 3 + i)); break; case DCCP_OPTION_INIT_COOKIE: - if (optlen > 2) { - ND_PRINT(" 0x"); - for (i = 0; i < optlen - 2; i++) - ND_PRINT("%02x", - GET_U_1(option + 2 + i)); - } + ND_ICHECK_U(optlen, <, 3); + ND_PRINT(" 0x"); + for (i = 0; i < optlen - 2; i++) + ND_PRINT("%02x", GET_U_1(bp + 2 + i)); break; case DCCP_OPTION_NDP_COUNT: + ND_ICHECK_U(optlen, <, 3); + ND_ICHECK_U(optlen, >, 8); for (i = 0; i < optlen - 2; i++) - ND_PRINT(" %u", GET_U_1(option + 2 + i)); + ND_PRINT(" %u", GET_U_1(bp + 2 + i)); break; case DCCP_OPTION_ACK_VECTOR_NONCE_0: - if (optlen > 2) { - ND_PRINT(" 0x"); - for (i = 0; i < optlen - 2; i++) - ND_PRINT("%02x", - GET_U_1(option + 2 + i)); - } - break; case DCCP_OPTION_ACK_VECTOR_NONCE_1: - if (optlen > 2) { - ND_PRINT(" 0x"); - for (i = 0; i < optlen - 2; i++) - ND_PRINT("%02x", - GET_U_1(option + 2 + i)); - } + ND_ICHECK_U(optlen, <, 3); + ND_PRINT(" 0x"); + for (i = 0; i < optlen - 2; i++) + ND_PRINT("%02x", GET_U_1(bp + 2 + i)); break; case DCCP_OPTION_DATA_DROPPED: - if (optlen > 2) { - ND_PRINT(" 0x"); - for (i = 0; i < optlen - 2; i++) - ND_PRINT("%02x", - GET_U_1(option + 2 + i)); - } + ND_ICHECK_U(optlen, <, 3); + ND_PRINT(" 0x"); + for (i = 0; i < optlen - 2; i++) + ND_PRINT("%02x", GET_U_1(bp + 2 + i)); break; case DCCP_OPTION_TIMESTAMP: /* @@ -645,10 +557,8 @@ dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) * +--------+--------+--------+--------+--------+--------+ * Type=41 Length=6 */ - if (optlen == 6) - ND_PRINT(" %u", GET_BE_U_4(option + 2)); - else - ND_PRINT(" [optlen != 6]"); + ND_ICHECK_U(optlen, !=, 6); + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); break; case DCCP_OPTION_TIMESTAMP_ECHO: /* @@ -671,44 +581,49 @@ dccp_print_option(netdissect_options *ndo, const u_char *option, u_int hlen) */ switch (optlen) { case 6: - ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); break; case 8: - ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); ND_PRINT(" (elapsed time %u)", - GET_BE_U_2(option + 6)); + GET_BE_U_2(bp + 6)); break; case 10: - ND_PRINT(" %u", GET_BE_U_4(option + 2)); + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); ND_PRINT(" (elapsed time %u)", - GET_BE_U_4(option + 6)); + GET_BE_U_4(bp + 6)); break; default: ND_PRINT(" [optlen != 6 or 8 or 10]"); + goto invalid; break; } break; case DCCP_OPTION_ELAPSED_TIME: - if (optlen == 6) - ND_PRINT(" %u", GET_BE_U_4(option + 2)); - else if (optlen == 4) - ND_PRINT(" %u", GET_BE_U_2(option + 2)); - else + switch (optlen) { + case 4: + ND_PRINT(" %u", GET_BE_U_2(bp + 2)); + break; + case 6: + ND_PRINT(" %u", GET_BE_U_4(bp + 2)); + break; + default: ND_PRINT(" [optlen != 4 or 6]"); + goto invalid; + } break; case DCCP_OPTION_DATA_CHECKSUM: - if (optlen > 2) { - ND_PRINT(" "); - for (i = 0; i < optlen - 2; i++) - ND_PRINT("%02x", - GET_U_1(option + 2 + i)); - } + ND_ICHECK_U(optlen, !=, 6); + ND_PRINT(" 0x"); + for (i = 0; i < optlen - 2; i++) + ND_PRINT("%02x", GET_U_1(bp + 2 + i)); break; + default: + goto invalid; } } return optlen; -trunc: - nd_print_trunc(ndo); +invalid: return 0; }