]> The Tcpdump Group git mirrors - tcpdump/blobdiff - print-dccp.c
C compilers can, and some do, optimize away pointer underflow checks.
[tcpdump] / print-dccp.c
index bc19b6abdfbc4016faa64b3caa82ca45bbe29117..fee4a6e50574f8d71eb69fe9eeff552a27cb4022 100644 (file)
@@ -9,7 +9,7 @@
 
 #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
@@ -60,9 +60,20 @@ static const char *dccp_feature_nums[] = {
        "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;
@@ -86,15 +97,15 @@ static int dccp_cksum(const struct ip *ip,
                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;
@@ -113,23 +124,10 @@ static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_i
        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
 
@@ -146,7 +144,7 @@ static u_int64_t dccp_seqno(const struct dccp_hdr *dh)
        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);
@@ -155,25 +153,36 @@ static u_int64_t dccp_seqno(const struct dccp_hdr *dh)
        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)
@@ -268,32 +277,21 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
        }
 
        /* 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)) {
@@ -301,7 +299,8 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
                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;
        }
@@ -309,9 +308,8 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
                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;
        }
@@ -319,20 +317,12 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
                (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;
        }
@@ -366,6 +356,10 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
                break;
        }
 
+       if ((DCCPH_TYPE(dh) != DCCP_PKT_DATA) && 
+                       (DCCPH_TYPE(dh) != DCCP_PKT_REQUEST))
+               dccp_print_ack_no(bp);
+
        if (vflag < 2)
                return;
 
@@ -400,9 +394,6 @@ trunc2:
 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);
 
@@ -476,22 +467,17 @@ static int dccp_print_option(const u_char *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 ");
@@ -502,12 +488,10 @@ static int dccp_print_option(const u_char *option)
                        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;