]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-dccp.c
gre: add support for MikroTik Ethernet-over-IP hack.
[tcpdump] / print-dccp.c
index 80951cf060a1aaa5427c70727cd7aa99d35a3306..5a0890a9a481923ca5b423ac1665593be9cc66eb 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "netdissect-stdinc.h"
 
+#define ND_LONGJMP_FROM_TCHECK
 #include "netdissect.h"
 #include "addrtoname.h"
 #include "extract.h"
@@ -182,14 +183,14 @@ 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 }
 };
 
 static u_int
 dccp_csum_coverage(netdissect_options *ndo,
-                  const struct dccp_hdrdh, u_int len)
+                  const struct dccp_hdr *dh, u_int len)
 {
        u_int cov;
 
@@ -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;
 }