------------------------------------------------------------
revno: 356
revision-id: [EMAIL PROTECTED]
parent: [EMAIL PROTECTED]
committer: Andrew Tridgell <[EMAIL PROTECTED]>
branch nick: tridge
timestamp: Sun 2007-05-27 13:39:36 +1000
message:
  added function to send a raw tcp ack packet
modified:
  takeover/system.c              system.c-20070525071636-a5n1ihghjtppy08r-3
=== modified file 'takeover/system.c'
--- a/takeover/system.c 2007-05-26 04:01:08 +0000
+++ b/takeover/system.c 2007-05-27 03:39:36 +0000
@@ -28,6 +28,7 @@
 #include <net/if_arp.h>
 
 
+
 /*
   send gratuitous arp reply after we have taken over an ip address
 
@@ -44,7 +45,6 @@
        unsigned char buffer[64]; /*minimum eth frame size */
        char *ptr;
 
-
        /* for now, we only handle AF_INET addresses */
        if (saddr->sin_family != AF_INET) {
                DEBUG(0,(__location__ " not an ipv4 address\n"));
@@ -53,7 +53,7 @@
 
        s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_ARP));
        if (s == -1){
-               DEBUG(0,(__location__ "failed to open raw socket\n"));
+               DEBUG(0,(__location__ " failed to open raw socket\n"));
                return -1;
        }
 
@@ -128,6 +128,87 @@
 }
 
 /*
+  simple IP checksum - assumes data is multiple of 2 bytes long
+ */
+static uint16_t ip_checksum(uint16_t *data, size_t n)
+{
+       uint16_t sum=0;
+       while (n--) {
+               sum += ntohs(*data);
+               data++;
+       }
+       if (sum == 0) {
+               return 0xFFFF;
+       }
+       return htons(sum);
+}
+
+/*
+  send tcp ack packet from the specified IP/port to the specified
+  destination IP/port. 
+
+  This is used to trigger the receiving host into sending its own ACK,
+  which should trigger early detection of TCP reset by the client
+  after IP takeover
+ */
+int ctdb_sys_send_ack(const struct sockaddr_in *dest, 
+                     const struct sockaddr_in *src)
+{
+       int s, ret;
+       uint32_t one = 1;
+       struct {
+               struct iphdr ip;
+               struct tcphdr tcp;
+       } pkt;
+
+       /* for now, we only handle AF_INET addresses */
+       if (src->sin_family != AF_INET || dest->sin_family != AF_INET) {
+               DEBUG(0,(__location__ " not an ipv4 address\n"));
+               return -1;
+       }
+
+       s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+       if (s == -1) {
+               DEBUG(0,(__location__ " failed to open raw socket (%s)\n",
+                        strerror(errno)));
+               return -1;
+       }
+
+       ret = setsockopt(s, SOL_IP, IP_HDRINCL, &one, sizeof(one));
+       if (ret != 0) {
+               DEBUG(0,(__location__ " failed to setup IP headers (%s)\n",
+                        strerror(errno)));
+               close(s);
+               return -1;
+       }
+
+       ZERO_STRUCT(pkt);
+       pkt.ip.version  = 4;
+       pkt.ip.ihl      = sizeof(pkt.ip)/4;
+       pkt.ip.tot_len  = 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.tcp.source   = src->sin_port;
+       pkt.tcp.dest     = dest->sin_port;
+       pkt.tcp.ack      = 1;
+       pkt.tcp.check    = ip_checksum((uint16_t *)&pkt.tcp, sizeof(pkt.tcp)/2);
+
+       ret = sendto(3, &pkt, sizeof(pkt), 0, dest, sizeof(*dest));
+       if (ret != 0) {
+               DEBUG(0,(__location__ " failed sendto (%s)\n", 
strerror(errno)));
+       }
+       close(s);
+
+       return ret;
+}
+
+
+
+/*
   takeover an IP on an interface
  */
 int ctdb_sys_take_ip(const char *ip, const char *interface)

Reply via email to