]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
fixed tcp data offset and checksum
authorAndrew Tridgell <tridge@samba.org>
Sun, 27 May 2007 06:56:12 +0000 (16:56 +1000)
committerAndrew Tridgell <tridge@samba.org>
Sun, 27 May 2007 06:56:12 +0000 (16:56 +1000)
(This used to be ctdb commit 2df23e0d3df52b746e9aee8d194ad1da16b62657)

ctdb/takeover/ctdb_takeover.c
ctdb/takeover/system.c
ctdb/tools/ctdb_control.c

index 92376e9e3f5d8673a928d1b2d32508308e84c75d..c3bc12e76711097eac80d604181b81bc9c0aed3a 100644 (file)
@@ -71,7 +71,7 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
                         (unsigned)ntohs(tcp->daddr.sin_port), 
                         inet_ntoa(tcp->saddr.sin_addr),
                         (unsigned)ntohs(tcp->saddr.sin_port)));
-               ret = ctdb_sys_send_ack(&tcp->daddr, &tcp->saddr);
+               ret = ctdb_sys_send_ack(&tcp->saddr, &tcp->daddr);
                if (ret != 0) {
                        DEBUG(0,(__location__ " Failed to send tcp tickle ack for %s\n",
                                 inet_ntoa(tcp->saddr.sin_addr)));
index 71df1ee3dd11acdf6218c4e0fd8833e47e60a035..633e995307ec856d2500e90729acac09ad7abe21 100644 (file)
@@ -127,20 +127,42 @@ int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface)
        return 0;
 }
 
+
 /*
-  simple IP checksum - assumes data is multiple of 2 bytes long
+  uint16 checksum for n bytes
  */
-static uint16_t ip_checksum(uint16_t *data, size_t n)
+static uint32_t uint16_checksum(uint16_t *data, size_t n)
 {
-       uint16_t sum=0;
-       while (n--) {
-               sum += ntohs(*data);
+       uint32_t sum=0;
+       while (n>=2) {
+               sum += (uint32_t)ntohs(*data);
                data++;
+               n -= 2;
+       }
+       if (n == 1) {
+               sum += (uint32_t)ntohs(*(uint8_t *)data);
        }
-       if (sum == 0) {
+       return sum;
+}
+
+/*
+  simple TCP checksum - assumes data is multiple of 2 bytes long
+ */
+static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
+{
+       uint32_t sum = uint16_checksum(data, n);
+       uint16_t sum2;
+       sum += uint16_checksum((uint16_t *)&ip->saddr, sizeof(ip->saddr));
+       sum += uint16_checksum((uint16_t *)&ip->daddr, sizeof(ip->daddr));
+       sum += ip->protocol + n;
+       sum = (sum & 0xFFFF) + (sum >> 16);
+       sum = (sum & 0xFFFF) + (sum >> 16);
+       sum2 = htons(sum);
+       sum2 = ~sum2;
+       if (sum2 == 0) {
                return 0xFFFF;
        }
-       return htons(sum);
+       return sum2;
 }
 
 /*
@@ -185,20 +207,21 @@ int ctdb_sys_send_ack(const struct sockaddr_in *dest,
        ZERO_STRUCT(pkt);
        pkt.ip.version  = 4;
        pkt.ip.ihl      = sizeof(pkt.ip)/4;
-       pkt.ip.tot_len  = sizeof(pkt);
+       pkt.ip.tot_len  = htons(sizeof(pkt));
        pkt.ip.ttl      = 255;
        pkt.ip.protocol = IPPROTO_TCP;
        pkt.ip.saddr    = src->sin_addr.s_addr;
        pkt.ip.daddr    = dest->sin_addr.s_addr;
-       pkt.ip.check    = ip_checksum((uint16_t *)&pkt.ip, sizeof(pkt.ip)/2);
+       pkt.ip.check    = 0;
 
        pkt.tcp.source   = src->sin_port;
        pkt.tcp.dest     = dest->sin_port;
        pkt.tcp.ack      = 1;
-       pkt.tcp.check    = 0;
+       pkt.tcp.doff     = sizeof(pkt.tcp)/4;
+       pkt.tcp.check    = tcp_checksum((uint16_t *)&pkt.tcp, sizeof(pkt.tcp), &pkt.ip);
 
        ret = sendto(s, &pkt, sizeof(pkt), 0, dest, sizeof(*dest));
-       if (ret != 0) {
+       if (ret != sizeof(pkt)) {
                DEBUG(0,(__location__ " failed sendto (%s)\n", strerror(errno)));
        }
        close(s);
index 0a6580985df7e63eb7266ea6d31120450883d055..47e05f42e0b7ad34a85f1972f7e189908adbd5f7 100644 (file)
@@ -1139,6 +1139,20 @@ int main(int argc, const char *argv[])
                { "thaw", control_thaw },
        };
 
+       {
+               struct sockaddr_in saddr, daddr;
+               inet_aton("192.168.115.128", &daddr.sin_addr);
+               inet_aton("192.168.115.1",   &saddr.sin_addr);
+               daddr.sin_port = htons(1234);
+               saddr.sin_port = htons(445);
+               daddr.sin_family = AF_INET;
+               saddr.sin_family = AF_INET;
+               ctdb_sys_send_ack(&daddr, &saddr);
+               exit(0);
+       }
+
+
+
        pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
 
        while ((opt = poptGetNextOpt(pc)) != -1) {