[SCM] CTDB repository - branch master updated - 406a2a1e364cf71eb15e5aeec3b87c62f825da92

Ronnie Sahlberg sahlberg at samba.org
Wed May 14 05:52:10 GMT 2008


The branch, master has been updated
       via  406a2a1e364cf71eb15e5aeec3b87c62f825da92 (commit)
       via  93b98838824fae5f47e4ed6b95ae9e4e7597bec3 (commit)
       via  6131f4b4fc7b65f83f3d57927b23393c84bd2a2b (commit)
       via  7f4c7cf6355a88b1a02d3a4d1fa25427106953f9 (commit)
       via  b712762a1b8a3028625085e32136df4458b292c0 (commit)
      from  13d3eb9a8bc7fad14fcd3e7e023c1336657424d6 (commit)

http://gitweb.samba.org/?p=sahlberg/ctdb.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 406a2a1e364cf71eb15e5aeec3b87c62f825da92
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed May 14 15:47:47 2008 +1000

    Start implementing support for ipv6.
    
    This enhances the framework for sending tcp tickles to be able to send ipv6 tickles as well.
    
    Since we can not use one single RAW socket to send both handcrafted ipv4 and ipv6 packets, instead of always opening TWO sockets, one ipv4 and one ipv6 we get rid of the helper ctdb_sys_open_sending_socket() and just open (and close)  a raw socket of the appropriate type inside ctdb_sys_send_tcp().
    We know which type of socket v4/v6 to use based on the sin_family of the destination address.
    
    Since ctdb_sys_send_tcp() opens its own socket  we no longer nede to pass a socket
    descriptor as a parameter.  Get rid of this redundant parameter and fixup all callers.

commit 93b98838824fae5f47e4ed6b95ae9e4e7597bec3
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed May 14 15:40:44 2008 +1000

    add a new container to hold a socketaddr for either ipv4 or ipv6

commit 6131f4b4fc7b65f83f3d57927b23393c84bd2a2b
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed May 14 15:37:20 2008 +1000

    Add a missing include

commit 7f4c7cf6355a88b1a02d3a4d1fa25427106953f9
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed May 14 15:33:01 2008 +1000

    move the function to open a sending socket into the main executable since this function will dissapear soon...

commit b712762a1b8a3028625085e32136df4458b292c0
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Wed May 14 12:25:55 2008 +1000

    add a checksum routine for tcp over ipv6

-----------------------------------------------------------------------

Summary of changes:
 common/ctdb_util.c     |   70 ++++++++++++++++-
 common/system_aix.c    |    5 +-
 common/system_linux.c  |  194 ++++++++++++++++++++++++++++++++---------------
 include/ctdb_private.h |   18 +++-
 server/ctdb_takeover.c |   51 +++++--------
 tools/ctdb.c           |   17 +---
 utils/ipmux/ipmux.c    |   29 +++++++
 7 files changed, 266 insertions(+), 118 deletions(-)


Changeset truncated at 500 lines:

diff --git a/common/ctdb_util.c b/common/ctdb_util.c
index 8ae4df7..cb53511 100644
--- a/common/ctdb_util.c
+++ b/common/ctdb_util.c
@@ -296,18 +296,78 @@ static bool parse_ip_num(const char *s, struct in_addr *addr, unsigned *num, con
 }
 
 
+static bool parse_ipv4(const char *s, unsigned port, ctdb_sock_addr *saddr)
+{
+	saddr->ip.sin_family = AF_INET;
+	saddr->ip.sin_port   = htons(port);
+
+	if (inet_pton(AF_INET, s, &saddr->ip.sin_addr) != 1) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to translate %s into sin_addr\n", s));
+		return false;
+	}
+
+	return true;
+}
+
+static bool parse_ipv6(const char *s, unsigned port, ctdb_sock_addr *saddr)
+{
+	saddr->ip6.sin6_family   = AF_INET6;
+	saddr->ip6.sin6_port     = htons(port);
+	saddr->ip6.sin6_flowinfo = 0;
+	saddr->ip6.sin6_scope_id = 0;
+
+	if (inet_pton(AF_INET6, s, &saddr->ip6.sin6_addr) != 1) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed to translate %s into sin6_addr\n", s));
+		return false;
+	}
+
+	return true;
+}
 /*
   parse a ip:port pair
  */
-bool parse_ip_port(const char *s, struct sockaddr_in *ip)
+bool parse_ip_port(const char *addr, ctdb_sock_addr *saddr)
 {
+	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+	char *s, *p;
 	unsigned port;
-	if (!parse_ip_num(s, &ip->sin_addr, &port, ':')) {
+	char *endp = NULL;
+	bool ret;
+
+	s = talloc_strdup(tmp_ctx, addr);
+	if (s == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed strdup()\n"));
+		talloc_free(tmp_ctx);
 		return false;
 	}
-	ip->sin_family = AF_INET;
-	ip->sin_port   = htons(port);
-	return true;
+
+	p = rindex(s, ':');
+	if (p == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " This addr: %s does not contain a port number\n", s));
+		talloc_free(tmp_ctx);
+		return false;
+	}
+
+	port = strtoul(p+1, &endp, 10);
+	if (endp == NULL || *endp != 0) {
+		/* trailing garbage */
+		DEBUG(DEBUG_ERR, (__location__ " Trailing garbage after the port in %s\n", s));
+		talloc_free(tmp_ctx);
+		return false;
+	}
+	*p = 0;
+
+
+	/* now is this a ipv4 or ipv6 address ?*/
+	p = index(s, ':');
+	if (p == NULL) {
+		ret = parse_ipv4(s, port, saddr);
+	} else {
+		ret = parse_ipv6(s, port, saddr);
+	}
+
+	talloc_free(tmp_ctx);
+	return ret;
 }
 
 /*
diff --git a/common/system_aix.c b/common/system_aix.c
index 50f1418..d455ac7 100644
--- a/common/system_aix.c
+++ b/common/system_aix.c
@@ -31,6 +31,9 @@
 
 
 
+#if 0
+This function is no longer used and its code should be moved into
+send tcp packet   after that function has been enhanced to do ipv6 as well.
 
 /* This function is used to open a raw socket to send tickles from
  */
@@ -59,7 +62,7 @@ int ctdb_sys_open_sending_socket(void)
 
 	return s;
 }
-
+#endif
 
 /*
   uint16 checksum for n bytes
diff --git a/common/system_linux.c b/common/system_linux.c
index 207387f..fb50c6b 100644
--- a/common/system_linux.c
+++ b/common/system_linux.c
@@ -25,6 +25,7 @@
 #include "../include/ctdb_private.h"
 #include "lib/events/events.h"
 #include <netinet/if_ether.h>
+#include <netinet/ip6.h>
 #include <net/if_arp.h>
 
 
@@ -177,6 +178,29 @@ static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
 }
 
 /*
+  calculate the tcp checksum for tcp over ipv6
+*/
+static uint16_t tcp_checksum6(uint16_t *data, size_t n, struct ip6_hdr *ip6)
+{
+	uint32_t sum = uint16_checksum(data, n);
+	uint16_t sum2;
+
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16);
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16);
+	sum += ip6->ip6_plen;
+	sum += ip6->ip6_nxt;
+			
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum2 = htons(sum);
+	sum2 = ~sum2;
+	if (sum2 == 0) {
+		return 0xFFFF;
+	}
+	return sum2;
+}
+
+/*
   Send tcp segment from the specified IP/port to the specified
   destination IP/port. 
 
@@ -187,48 +211,122 @@ static uint16_t tcp_checksum(uint16_t *data, size_t n, struct iphdr *ip)
   This can also be used to send RST segments (if rst is true) and also
   if correct seq and ack numbers are provided.
  */
-int ctdb_sys_send_tcp(int s,
-		      const struct sockaddr_in *dest, 
-		      const struct sockaddr_in *src,
+int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 
+		      const ctdb_sock_addr *src,
 		      uint32_t seq, uint32_t ack, int rst)
 {
+	int s;
 	int ret;
+	uint32_t one = 1;
+	uint16_t tmpport;
+	ctdb_sock_addr *tmpdest;
 	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(DEBUG_CRIT,(__location__ " not an ipv4 address\n"));
-		return -1;
-	}
+	} ip4pkt;
+	struct {
+		struct ip6_hdr ip6;
+		struct tcphdr tcp;
+	} ip6pkt;
+
+	switch (src->ip.sin_family) {
+	case AF_INET:
+		ZERO_STRUCT(ip4pkt);
+		ip4pkt.ip.version  = 4;
+		ip4pkt.ip.ihl      = sizeof(ip4pkt.ip)/4;
+		ip4pkt.ip.tot_len  = htons(sizeof(ip4pkt));
+		ip4pkt.ip.ttl      = 255;
+		ip4pkt.ip.protocol = IPPROTO_TCP;
+		ip4pkt.ip.saddr    = src->ip.sin_addr.s_addr;
+		ip4pkt.ip.daddr    = dest->ip.sin_addr.s_addr;
+		ip4pkt.ip.check    = 0;
+
+		ip4pkt.tcp.source   = src->ip.sin_port;
+		ip4pkt.tcp.dest     = dest->ip.sin_port;
+		ip4pkt.tcp.seq      = seq;
+		ip4pkt.tcp.ack_seq  = ack;
+		ip4pkt.tcp.ack      = 1;
+		if (rst) {
+			ip4pkt.tcp.rst      = 1;
+		}
+		ip4pkt.tcp.doff     = sizeof(ip4pkt.tcp)/4;
+		/* this makes it easier to spot in a sniffer */
+		ip4pkt.tcp.window   = htons(1234);
+		ip4pkt.tcp.check    = tcp_checksum((uint16_t *)&ip4pkt.tcp, sizeof(ip4pkt.tcp), &ip4pkt.ip);
+
+		/* open a raw socket to send this segment from */
+		s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
+		if (s == -1) {
+			DEBUG(DEBUG_CRIT,(__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(DEBUG_CRIT,(__location__ " failed to setup IP headers (%s)\n",
+				 strerror(errno)));
+			close(s);
+			return -1;
+		}
+
+		set_nonblocking(s);
+		set_close_on_exec(s);
+
+		ret = sendto(s, &ip4pkt, sizeof(ip4pkt), 0, &dest->ip, sizeof(dest->ip));
+		close(s);
+		if (ret != sizeof(ip4pkt)) {
+			DEBUG(DEBUG_CRIT,(__location__ " failed sendto (%s)\n", strerror(errno)));
+			return -1;
+		}
+		break;
+	case AF_INET6:
+		ZERO_STRUCT(ip6pkt);
+		ip6pkt.ip6.ip6_vfc  = 0x60;
+		ip6pkt.ip6.ip6_plen = 20;
+		ip6pkt.ip6.ip6_nxt  = IPPROTO_TCP;
+		ip6pkt.ip6.ip6_hlim = 64;
+		ip6pkt.ip6.ip6_src  = src->ip6.sin6_addr;
+		ip6pkt.ip6.ip6_dst  = dest->ip6.sin6_addr;
+
+		ip6pkt.tcp.source   = src->ip6.sin6_port;
+		ip6pkt.tcp.dest     = dest->ip6.sin6_port;
+		ip6pkt.tcp.seq      = seq;
+		ip6pkt.tcp.ack_seq  = ack;
+		ip6pkt.tcp.ack      = 1;
+		if (rst) {
+			ip6pkt.tcp.rst      = 1;
+		}
+		ip6pkt.tcp.doff     = sizeof(ip6pkt.tcp)/4;
+		/* this makes it easier to spot in a sniffer */
+		ip6pkt.tcp.window   = htons(1234);
+		ip6pkt.tcp.check    = tcp_checksum6((uint16_t *)&ip6pkt.tcp, sizeof(ip6pkt.tcp), &ip6pkt.ip6);
+
+		s = socket(PF_INET6, SOCK_RAW, IPPROTO_RAW);
+		if (s == -1) {
+			DEBUG(DEBUG_CRIT, (__location__ " Failed to open sending socket\n"));
+			return -1;
+
+		}
+		/* sendto() dont like if the port is set and the socket is
+		   in raw mode.
+		*/
+		tmpdest = discard_const(dest);
+		tmpport = tmpdest->ip6.sin6_port;
+
+		tmpdest->ip6.sin6_port = 0;
+		ret = sendto(s, &ip6pkt, sizeof(ip6pkt), 0, &dest->ip6, sizeof(dest->ip6));
+		tmpdest->ip6.sin6_port = tmpport;
+		close(s);
 
-	ZERO_STRUCT(pkt);
-	pkt.ip.version  = 4;
-	pkt.ip.ihl      = sizeof(pkt.ip)/4;
-	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    = 0;
-
-	pkt.tcp.source   = src->sin_port;
-	pkt.tcp.dest     = dest->sin_port;
-	pkt.tcp.seq      = seq;
-	pkt.tcp.ack_seq  = ack;
-	pkt.tcp.ack      = 1;
-	if (rst) {
-		pkt.tcp.rst      = 1;
-	}
-	pkt.tcp.doff     = sizeof(pkt.tcp)/4;
-	pkt.tcp.window   = htons(1234); /* this makes it easier to spot in a sniffer */
-	pkt.tcp.check    = tcp_checksum((uint16_t *)&pkt.tcp, sizeof(pkt.tcp), &pkt.ip);
+		if (ret != sizeof(ip6pkt)) {
+			DEBUG(DEBUG_CRIT,(__location__ " failed sendto (%s)\n", strerror(errno)));
+			return -1;
+		}
+		break;
 
-	ret = sendto(s, &pkt, sizeof(pkt), 0, dest, sizeof(*dest));
-	if (ret != sizeof(pkt)) {
-		DEBUG(DEBUG_CRIT,(__location__ " failed sendto (%s)\n", strerror(errno)));
+	default:
+		DEBUG(DEBUG_CRIT,(__location__ " not an ipv4/v6 address\n"));
 		return -1;
 	}
 
@@ -290,34 +388,6 @@ int ctdb_sys_close_capture_socket(void *private_data)
 	return 0;
 }
 
-/* 
-   This function is used to open a raw socket to send tickles from
- */
-int ctdb_sys_open_sending_socket(void)
-{
-	int s, ret;
-	uint32_t one = 1;
-
-	s = socket(AF_INET, SOCK_RAW, htons(IPPROTO_RAW));
-	if (s == -1) {
-		DEBUG(DEBUG_CRIT,(__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(DEBUG_CRIT,(__location__ " failed to setup IP headers (%s)\n",
-			 strerror(errno)));
-		close(s);
-		return -1;
-	}
-
-	set_nonblocking(s);
-	set_close_on_exec(s);
-
-	return s;
-}
 
 /*
   called when the raw socket becomes readable
diff --git a/include/ctdb_private.h b/include/ctdb_private.h
index bc8bde3..4eccc84 100644
--- a/include/ctdb_private.h
+++ b/include/ctdb_private.h
@@ -47,6 +47,16 @@ struct rd_memdump_reply {
 };
 
 /*
+  definitions for different socket structures
+ */
+typedef struct sockaddr_in ctdb_addr_in;
+typedef struct sockaddr_in6 ctdb_addr_in6;
+typedef union {
+	ctdb_addr_in	ip;
+	ctdb_addr_in6	ip6;
+} ctdb_sock_addr;
+
+/*
   a tcp connection description
  */
 struct ctdb_tcp_connection {
@@ -1153,9 +1163,8 @@ int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb,
 /* from takeover/system.c */
 int ctdb_sys_send_arp(const struct sockaddr_in *saddr, const char *iface);
 bool ctdb_sys_have_ip(struct sockaddr_in ip);
-int ctdb_sys_send_tcp(int fd,
-		      const struct sockaddr_in *dest, 
-		      const struct sockaddr_in *src,
+int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, 
+		      const ctdb_sock_addr *src,
 		      uint32_t seq, uint32_t ack, int rst);
 
 int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist);
@@ -1210,11 +1219,10 @@ int ctdb_ctrl_get_all_tunables(struct ctdb_context *ctdb,
 
 void ctdb_start_freeze(struct ctdb_context *ctdb);
 
-bool parse_ip_port(const char *s, struct sockaddr_in *ip);
+bool parse_ip_port(const char *s, ctdb_sock_addr *saddr);
 
 int ctdb_sys_open_capture_socket(const char *iface, void **private_data);
 int ctdb_sys_close_capture_socket(void *private_data);
-int ctdb_sys_open_sending_socket(void);
 int ctdb_sys_read_tcp_packet(int s, void *private_data, struct sockaddr_in *src, struct sockaddr_in *dst,
 			     uint32_t *ack_seq, uint32_t *seq);
 
diff --git a/server/ctdb_takeover.c b/server/ctdb_takeover.c
index 26f75bf..e3f0a83 100644
--- a/server/ctdb_takeover.c
+++ b/server/ctdb_takeover.c
@@ -69,7 +69,7 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
 {
 	struct ctdb_takeover_arp *arp = talloc_get_type(private_data, 
 							struct ctdb_takeover_arp);
-	int i, s, ret;
+	int i, ret;
 	struct ctdb_tcp_array *tcparray;
 
 
@@ -78,12 +78,6 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
 		DEBUG(DEBUG_CRIT,(__location__ " sending of arp failed (%s)\n", strerror(errno)));
 	}
 
-	s = ctdb_sys_open_sending_socket();
-	if (s == -1) {
-		DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket for sending tickles\n"));
-		return;
-	}
-
 	tcparray = arp->tcparray;
 	if (tcparray) {
 		for (i=0;i<tcparray->num;i++) {
@@ -91,8 +85,10 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
 				 (unsigned)ntohs(tcparray->connections[i].daddr.sin_port), 
 				 inet_ntoa(tcparray->connections[i].saddr.sin_addr),
 				 (unsigned)ntohs(tcparray->connections[i].saddr.sin_port)));
-			ret = ctdb_sys_send_tcp(s, &tcparray->connections[i].saddr, 
-						&tcparray->connections[i].daddr, 0, 0, 0);
+			ret = ctdb_sys_send_tcp(
+				(ctdb_sock_addr *)&tcparray->connections[i].saddr, 
+				(ctdb_sock_addr *)&tcparray->connections[i].daddr,
+				0, 0, 0);
 			if (ret != 0) {
 				DEBUG(DEBUG_CRIT,(__location__ " Failed to send tcp tickle ack for %s\n",
 					 inet_ntoa(tcparray->connections[i].saddr.sin_addr)));
@@ -100,7 +96,6 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *
 		}
 	}
 
-	close(s);
 	arp->count++;
 
 	if (arp->count == CTDB_ARP_REPEAT) {
@@ -1266,7 +1261,6 @@ struct ctdb_kill_tcp {
 	struct ctdb_vnn *vnn;
 	struct ctdb_context *ctdb;
 	int capture_fd;
-	int sending_fd;
 	struct fd_event *fde;
 	trbt_tree_t *connections;
 	void *private_data;
@@ -1338,8 +1332,10 @@ static void capture_tcp_handler(struct event_context *ev, struct fd_event *fde,
 	 */
 	DEBUG(DEBUG_INFO, ("sending a tcp reset to kill connection :%d -> %s:%d\n", ntohs(con->dst.sin_port), inet_ntoa(con->src.sin_addr), ntohs(con->src.sin_port)));
 
-	ctdb_sys_send_tcp(killtcp->sending_fd, &con->dst, 
-			  &con->src, ack_seq, seq, 1);
+	ctdb_sys_send_tcp(
+			(ctdb_sock_addr *)&con->dst, 
+			(ctdb_sock_addr *)&con->src,
+			ack_seq, seq, 1);
 	talloc_free(con);
 }
 
@@ -1352,7 +1348,6 @@ static void capture_tcp_handler(struct event_context *ev, struct fd_event *fde,
 static void tickle_connection_traverse(void *param, void *data)
 {
 	struct ctdb_killtcp_con *con = talloc_get_type(data, struct ctdb_killtcp_con);
-	struct ctdb_kill_tcp *killtcp = talloc_get_type(param, struct ctdb_kill_tcp);
 
 	/* have tried too many times, just give up */
 	if (con->count >= 5) {
@@ -1362,7 +1357,10 @@ static void tickle_connection_traverse(void *param, void *data)
 
 	/* othervise, try tickling it again */
 	con->count++;
-	ctdb_sys_send_tcp(killtcp->sending_fd, &con->dst, &con->src, 0, 0, 0);
+	ctdb_sys_send_tcp(
+		(ctdb_sock_addr *)&con->dst,
+		(ctdb_sock_addr *)&con->src,
+		0, 0, 0);
 }
 
 
@@ -1376,7 +1374,7 @@ static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct t
 
 
 	/* loop over all connections sending tickle ACKs */
-	trbt_traversearray32(killtcp->connections, KILLTCP_KEYLEN, tickle_connection_traverse, killtcp);
+	trbt_traversearray32(killtcp->connections, KILLTCP_KEYLEN, tickle_connection_traverse, NULL);
 
 
 	/* If there are no more connections to kill we can remove the
@@ -1399,10 +1397,6 @@ static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct t
  */
 static int ctdb_killtcp_destructor(struct ctdb_kill_tcp *killtcp)
 {
-	if (killtcp->sending_fd != -1) {
-		close(killtcp->sending_fd);
-		killtcp->sending_fd = -1;
-	}
 	killtcp->vnn->killtcp = NULL;
 	return 0;
 }
@@ -1459,7 +1453,6 @@ static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb,


-- 
CTDB repository


More information about the samba-cvs mailing list