Rev 356: added function to send a raw tcp ack packet in
http://samba.org/~tridge/ctdb
tridge at samba.org
tridge at samba.org
Sun May 27 03:39:37 GMT 2007
------------------------------------------------------------
revno: 356
revision-id: tridge at samba.org-20070527033936-fhaceqmyqu4hrr6r
parent: tridge at samba.org-20070526234325-u41a50wc6bnwahl1
committer: Andrew Tridgell <tridge at samba.org>
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)
More information about the samba-cvs
mailing list