ctdb-common: Improve TCP packet size and offset calculations
authorMartin Schwenke <martin@meltin.net>
Fri, 17 Aug 2018 11:26:04 +0000 (21:26 +1000)
committerAmitay Isaacs <amitay@samba.org>
Thu, 30 Aug 2018 02:48:59 +0000 (04:48 +0200)
The IPv4 check for short packets was strange.  It appeared to ensure
that the capture included everything up to and including the window
size.  The checksum field immediately follows the window size field,
so just ensure that the packet is large enough to contain everything
up to the start of the checksum.

Add a similar check for IPv6 packets.

Signed-off-by: Martin Schwenke <martin@meltin.net>
Reviewed-by: Amitay Isaacs <amitay@gmail.com>
ctdb/common/system_socket.c

index 8de70f8bca628f19a0c0860e5a687c61037b60e4..99c83c0ed5a65b694da4a584afec06389a7745a2 100644 (file)
@@ -768,13 +768,14 @@ static int tcp4_extract(const uint8_t *ip_pkt,
                return ENOMSG;
        }
 
-       /* make sure its not a short packet */
-       if (offsetof(struct tcphdr, th_ack) + 4 + (ip->ip_hl*4) > pktlen) {
+       /* Ensure there is enough of the packet to gather required fields */
+       if (pktlen <
+           (ip->ip_hl * sizeof(uint32_t)) + offsetof(struct tcphdr, th_sum)) {
                return EMSGSIZE;
        }
 
        /* TCP */
-       tcp = (const struct tcphdr *)((ip->ip_hl*4) + (const char *)ip);
+       tcp = (const struct tcphdr *)(ip_pkt + (ip->ip_hl * sizeof(uint32_t)));
 
        /* tell the caller which one we've found */
        src->sin_family      = AF_INET;
@@ -809,7 +810,8 @@ static int tcp6_extract(const uint8_t *ip_pkt,
        const struct ip6_hdr *ip6;
        const struct tcphdr *tcp;
 
-       if (pktlen < sizeof(struct ip6_hdr)) {
+       /* Ensure there is enough of the packet to gather required fields */
+       if (pktlen < sizeof(struct ip6_hdr) + offsetof(struct tcphdr, th_sum)) {
                return EMSGSIZE;
        }
 
@@ -822,7 +824,7 @@ static int tcp6_extract(const uint8_t *ip_pkt,
        }
 
        /* TCP */
-       tcp = (const struct tcphdr *)(ip6+1);
+       tcp = (const struct tcphdr *)(ip_pkt + sizeof(struct ip6_hdr));
 
        /* tell the caller which one we've found */
        src->sin6_family = AF_INET6;