[SCM] CTDB repository - branch master updated - 7da0c65c8526d66d4f2a788bd646d39237befa54

Ronnie Sahlberg sahlberg at samba.org
Sun Aug 24 22:58:24 GMT 2008


The branch, master has been updated
       via  7da0c65c8526d66d4f2a788bd646d39237befa54 (commit)
       via  12bc85c90a640a72ff538c003eb81da9dd1f2e3f (commit)
       via  4dfbfb4618433d9ed79ca1bdb1e2e51d96d4ee62 (commit)
       via  293d12a40501320a21efaf592b8f20e8590a5197 (commit)
       via  2f8b33948e395228cbac3450c0c684e49069abf0 (commit)
       via  1157d61a0bc557d8ffc453c518dfc48473492bfd (commit)
       via  b0fe4c45fc5ba1ecf62ebb921092c8a34e28a2bd (commit)
       via  6da7b36b7ccc4ee9b809867ea32036f09a801bb3 (commit)
       via  83735951352a243da185031e4853e7e40c43a0fb (commit)
       via  0a38ea11af9237501f2951fee698a59b46f8750d (commit)
       via  bf6effef0cc9e5f2eeeb38fce855a90624a76239 (commit)
       via  1f131f21386f428bbbbb29098d56c2f64596583b (commit)
      from  48fad9c06185a1f2580473cac02b3722e35c2023 (commit)

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


- Log -----------------------------------------------------------------
commit 7da0c65c8526d66d4f2a788bd646d39237befa54
Author: Ronnie Sahlberg <ronniesahlberg at gmail.com>
Date:   Mon Aug 25 08:52:29 2008 +1000

    version 1.0.57   : initial ipv6 support

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

Summary of changes:
 client/ctdb_client.c         |    6 +-
 common/ctdb_util.c           |  141 ++++++++++------
 common/system_aix.c          |   85 +++++----
 common/system_linux.c        |  260 ++++++++++++++++++++---------
 config/events.d/10.interface |    1 -
 config/functions             |   14 +-
 include/ctdb.h               |    1 -
 include/ctdb_private.h       |   55 ++++---
 packaging/RPM/ctdb.spec      |    4 +-
 server/ctdb_control.c        |    4 +-
 server/ctdb_daemon.c         |    2 +-
 server/ctdb_recover.c        |    5 +-
 server/ctdb_recoverd.c       |   11 +-
 server/ctdb_takeover.c       |  381 +++++++++++++++++++++++-------------------
 server/ctdbd.c               |    6 +-
 tcp/tcp_connect.c            |  131 +++++++++------
 tests/nodes.txt              |    3 -
 tests/start_daemons.sh       |    9 +-
 tools/ctdb.c                 |  135 +++++++++------
 utils/ipmux/ipmux.c          |    8 +-
 20 files changed, 751 insertions(+), 511 deletions(-)


Changeset truncated at 500 lines:

diff --git a/client/ctdb_client.c b/client/ctdb_client.c
index 0d85374..dfcd4d9 100644
--- a/client/ctdb_client.c
+++ b/client/ctdb_client.c
@@ -2422,15 +2422,15 @@ int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
 int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb, 
 			      struct timeval timeout, uint32_t destnode, 
 			      TALLOC_CTX *mem_ctx, 
-			      struct sockaddr_in *ip,
+			      ctdb_sock_addr *addr,
 			      struct ctdb_control_tcp_tickle_list **list)
 {
 	int ret;
 	TDB_DATA data, outdata;
 	int32_t status;
 
-	data.dptr = (uint8_t*)ip;
-	data.dsize = sizeof(struct sockaddr_in);
+	data.dptr = (uint8_t*)addr;
+	data.dsize = sizeof(ctdb_sock_addr);
 
 	ret = ctdb_control(ctdb, destnode, 0, 
 			   CTDB_CONTROL_GET_TCP_TICKLE_LIST, 0, data, 
diff --git a/common/ctdb_util.c b/common/ctdb_util.c
index b096a52..792ff3c 100644
--- a/common/ctdb_util.c
+++ b/common/ctdb_util.c
@@ -362,40 +362,6 @@ void set_close_on_exec(int fd)
 }
 
 
-/*
-  parse a ip:num pair with the given separator
- */
-static bool parse_ip_num(const char *s, struct in_addr *addr, unsigned *num, const char sep)
-{
-	const char *p;
-	char *endp = NULL;
-	char buf[16];
-
-	p = strchr(s, sep);
-	if (p == NULL) {
-		return false;
-	}
-
-	if (p - s > 15) {
-		return false;
-	}
-
-	*num = strtoul(p+1, &endp, 10);
-	if (endp == NULL || *endp != 0) {
-		/* trailing garbage */
-		return false;
-	}
-
-	strlcpy(buf, s, 1+p-s);
-
-	if (inet_aton(buf, addr) == 0) {
-		return false;
-	}
-
-	return true;
-}
-
-
 static bool parse_ipv4(const char *s, unsigned port, ctdb_sock_addr *saddr)
 {
 	saddr->ip.sin_family = AF_INET;
@@ -492,45 +458,91 @@ bool parse_ip(const char *addr, ctdb_sock_addr *saddr)
 /*
   parse a ip/mask pair
  */
-bool parse_ip_mask(const char *s, struct sockaddr_in *ip, unsigned *mask)
+bool parse_ip_mask(const char *str, ctdb_sock_addr *addr, unsigned *mask)
 {
-	ZERO_STRUCT(*ip);
+	TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+	char *s, *p;
+	char *endp = NULL;
+	bool ret;
 
-	if (!parse_ip_num(s, &ip->sin_addr, mask, '/')) {
+	ZERO_STRUCT(*addr);
+	s = talloc_strdup(tmp_ctx, str);
+	if (s == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " Failed strdup()\n"));
+		talloc_free(tmp_ctx);
 		return false;
 	}
-	if (*mask > 32) {
+
+	p = rindex(s, '/');
+	if (p == NULL) {
+		DEBUG(DEBUG_ERR, (__location__ " This addr: %s does not contain a mask\n", s));
+		talloc_free(tmp_ctx);
 		return false;
 	}
-	ip->sin_family = AF_INET;
-	ip->sin_port   = 0;
-	return true;
+
+	*mask = strtoul(p+1, &endp, 10);
+	if (endp == NULL || *endp != 0) {
+		/* trailing garbage */
+		DEBUG(DEBUG_ERR, (__location__ " Trailing garbage after the mask 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, 0, addr);
+	} else {
+		ret = parse_ipv6(s, 0, addr);
+	}
+
+	talloc_free(tmp_ctx);
+	return ret;
 }
 
 /*
-  compare two sockaddr_in structures - matching only on IP
- */
-bool ctdb_same_ipv4(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2)
+   This is used to canonicalize a ctdb_sock_addr structure.
+*/
+void ctdb_canonicalize_ip(const ctdb_sock_addr *ip, ctdb_sock_addr *cip)
 {
-	return ip1->sin_family == ip2->sin_family &&
-		ip1->sin_addr.s_addr == ip2->sin_addr.s_addr;
+	char prefix[12] = { 0,0,0,0,0,0,0,0,0,0,0xff,0xff };
+
+	memcpy(cip, ip, sizeof (*cip));
+
+	if ( (ip->sa.sa_family == AF_INET6)
+	&& !memcmp(&ip->ip6.sin6_addr, prefix, 12)) {
+		memset(cip, 0, sizeof(*cip));
+#ifdef HAVE_SOCK_SIN_LEN
+		cip->ip.sin_len = sizeof(*cip);
+#endif
+		cip->ip.sin_family = AF_INET;
+		cip->ip.sin_port   = ip->ip6.sin6_port;
+		memcpy(&cip->ip.sin_addr, &ip->ip6.sin6_addr.s6_addr32[3], 4);
+	}
 }
 
-bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2)
+bool ctdb_same_ip(const ctdb_sock_addr *tip1, const ctdb_sock_addr *tip2)
 {
-	if (ip1->sa.sa_family != ip2->sa.sa_family) {
+	ctdb_sock_addr ip1, ip2;
+
+	ctdb_canonicalize_ip(tip1, &ip1);
+	ctdb_canonicalize_ip(tip2, &ip2);
+	
+	if (ip1.sa.sa_family != ip2.sa.sa_family) {
 		return false;
 	}
 
-	switch (ip1->sa.sa_family) {
+	switch (ip1.sa.sa_family) {
 	case AF_INET:
-		return ip1->ip.sin_addr.s_addr == ip2->ip.sin_addr.s_addr;
+		return ip1.ip.sin_addr.s_addr == ip2.ip.sin_addr.s_addr;
 	case AF_INET6:
-		return !memcmp(&ip1->ip6.sin6_addr.s6_addr[0],
-				&ip2->ip6.sin6_addr.s6_addr[0],
+		return !memcmp(&ip1.ip6.sin6_addr.s6_addr[0],
+				&ip2.ip6.sin6_addr.s6_addr[0],
 				16);
 	default:
-		DEBUG(DEBUG_ERR, (__location__ " CRITICAL Can not compare sockaddr structures of type %u\n", ip1->sa.sa_family));
+		DEBUG(DEBUG_ERR, (__location__ " CRITICAL Can not compare sockaddr structures of type %u\n", ip1.sa.sa_family));
 		return false;
 	}
 
@@ -538,13 +550,30 @@ bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2)
 }
 
 /*
-  compare two sockaddr_in structures
+  compare two ctdb_sock_addr structures
  */
-bool ctdb_same_sockaddr(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2)
+bool ctdb_same_sockaddr(const ctdb_sock_addr *ip1, const ctdb_sock_addr *ip2)
 {
-	return ctdb_same_ipv4(ip1, ip2) && ip1->sin_port == ip2->sin_port;
+	return ctdb_same_ip(ip1, ip2) && ip1->ip.sin_port == ip2->ip.sin_port;
 }
 
+char *ctdb_addr_to_str(ctdb_sock_addr *addr)
+{
+	static char cip[128] = "";
+
+	switch (addr->sa.sa_family) {
+	case AF_INET:
+		inet_ntop(addr->ip.sin_family, &addr->ip.sin_addr, cip, sizeof(cip));
+		break;
+	case AF_INET6:
+		inet_ntop(addr->ip6.sin6_family, &addr->ip6.sin6_addr, cip, sizeof(cip));
+		break;
+	default:
+		DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family %u\n", addr->sa.sa_family));
+	}
+
+	return cip;
+}
 
 
 void ctdb_block_signal(int signum)
diff --git a/common/system_aix.c b/common/system_aix.c
index b08692d..03d997f 100644
--- a/common/system_aix.c
+++ b/common/system_aix.c
@@ -194,17 +194,17 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest,
   we try to bind to it, and if that fails then we don't have that IP
   on an interface
  */
-bool ctdb_sys_have_ip(struct sockaddr_in ip)
+bool ctdb_sys_have_ip(ctdb_sock_addr *addr)
 {
 	int s;
 	int ret;
 	
-	ip.sin_port = 0;
-	s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	addr->sa.sa_port = 0;
+	s = socket(addr->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
 	if (s == -1) {
 		return false;
 	}
-	ret = bind(s, (struct sockaddr *)&ip, sizeof(ip));
+	ret = bind(s, (struct sockaddr *)addr, sizeof(ctdb_sock_addr));
 	close(s);
 	return ret == 0;
 }
@@ -306,7 +306,7 @@ static int aix_get_mac_addr(const char *device_name, uint8_t mac[6])
 }
 
 int ctdb_sys_read_tcp_packet(int s, void *private_data, 
-			struct sockaddr_in *src, struct sockaddr_in *dst,
+			ctdb_sock_addr *src, ctdb_sock_addr *dst,
 			uint32_t *ack_seq, uint32_t *seq)
 {
 	int ret;
@@ -326,44 +326,53 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data,
 	/* Ethernet */
 	eth = (struct ether_header *)buffer;
 
-	/* We are only interested in IP packets */
-	if (eth->ether_type != htons(ETHERTYPE_IP)) {
-		return -1;
-	}
+	/* we want either IPv4 or IPv6 */
+	if (eth->ether_type == htons(ETHERTYPE_IP)) {
+		/* IP */
+		ip = (struct ip *)(eth+1);
 
-	/* IP */
-	ip = (struct ip *)(eth+1);
+		/* We only want IPv4 packets */
+		if (ip->ip_v != 4) {
+			return -1;
+		}
+		/* Dont look at fragments */
+		if ((ntohs(ip->ip_off)&0x1fff) != 0) {
+			return -1;
+		}
+		/* we only want TCP */
+		if (ip->ip_p != IPPROTO_TCP) {
+			return -1;
+		}
 
-	/* We only want IPv4 packets */
-	if (ip->ip_v != 4) {
-		return -1;
-	}
-	/* Dont look at fragments */
-	if ((ntohs(ip->ip_off)&0x1fff) != 0) {
-		return -1;
-	}
-	/* we only want TCP */
-	if (ip->ip_p != IPPROTO_TCP) {
-		return -1;
-	}
+		/* make sure its not a short packet */
+		if (offsetof(struct tcphdr, th_ack) + 4 + 
+		    (ip->ip_hl*4) > ret) {
+			return -1;
+		}
+		/* TCP */
+		tcp = (struct tcphdr *)((ip->ip_hl*4) + (char *)ip);
+	
+		/* tell the caller which one we've found */
+		src->ip.sin_family   = AF_INET;
+		src->sin_addr.s_addr = ip->ip_src.s_addr;
+		src->sin_port        = tcp->th_sport;
+		dst->ip.sin_family   = AF_INET;
+		dst->sin_addr.s_addr = ip->ip_dst.s_addr;
+		dst->sin_port        = tcp->th_dport;
+		*ack_seq             = tcp->th_ack;
+		*seq                 = tcp->th_seq;
 
-	/* make sure its not a short packet */
-	if (offsetof(struct tcphdr, th_ack) + 4 + 
-	    (ip->ip_hl*4) > ret) {
-		return -1;
+
+		return 0;
+#ifndef ETHERTYPE_IP6
+#define ETHERTYPE_IP6 0x86dd
+#endif
+	} else if (eth->ether_type == htons(ETHERTYPE_IP)) {
+see system_linux.c for what should go in here
+		return 0;
 	}
-	/* TCP */
-	tcp = (struct tcphdr *)((ip->ip_hl*4) + (char *)ip);
-	
-	/* tell the caller which one we've found */
-	src->sin_addr.s_addr = ip->ip_src.s_addr;
-	src->sin_port        = tcp->th_sport;
-	dst->sin_addr.s_addr = ip->ip_dst.s_addr;
-	dst->sin_port        = tcp->th_dport;
-	*ack_seq             = tcp->th_ack;
-	*seq                 = tcp->th_seq;
 
-	return 0;
+	return -1;
 }
 
 
diff --git a/common/system_linux.c b/common/system_linux.c
index 32db545..1bf4903 100644
--- a/common/system_linux.c
+++ b/common/system_linux.c
@@ -26,9 +26,58 @@
 #include "lib/events/events.h"
 #include <netinet/if_ether.h>
 #include <netinet/ip6.h>
+#include <netinet/icmp6.h>
 #include <net/if_arp.h>
 
 
+#ifndef ETHERTYPE_IP6
+#define ETHERTYPE_IP6 0x86dd
+#endif
+
+/*
+  uint16 checksum for n bytes
+ */
+static uint32_t uint16_checksum(uint16_t *data, size_t n)
+{
+	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);
+	}
+	return sum;
+}
+
+/*
+  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 phdr[2];
+	uint32_t sum = 0;
+	uint16_t sum2;
+
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_src, 16);
+	sum += uint16_checksum((uint16_t *)(void *)&ip6->ip6_dst, 16);
+
+	phdr[0] = htonl(n);
+	phdr[1] = htonl(ip6->ip6_nxt);
+	sum += uint16_checksum((uint16_t *)phdr, 8);
+
+	sum += uint16_checksum(data, n);
+
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum = (sum & 0xFFFF) + (sum >> 16);
+	sum2 = htons(sum);
+	sum2 = ~sum2;
+	if (sum2 == 0) {
+		return 0xFFFF;
+	}
+	return sum2;
+}
 
 /*
   send gratuitous arp reply after we have taken over an ip address
@@ -42,8 +91,10 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
 	struct sockaddr sa;
 	struct ether_header *eh;
 	struct arphdr *ah;
+	struct ip6_hdr *ip6;
+	struct icmp6_hdr *icmp6;
 	struct ifreq if_hwaddr;
-	unsigned char buffer[64]; /*minimum eth frame size */
+	unsigned char buffer[78]; /* ipv6 neigh solicitation size */
 	char *ptr;
 
 	ZERO_STRUCT(sa);
@@ -131,8 +182,66 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
 
 		close(s);
 		break;
+	case AF_INET6:
+		s = socket(AF_INET, SOCK_PACKET, htons(ETHERTYPE_IP6));
+		if (s == -1){
+			DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket\n"));
+			return -1;
+		}
+
+		/* get the mac address */
+		strcpy(if_hwaddr.ifr_name, iface);
+		ret = ioctl(s, SIOCGIFHWADDR, &if_hwaddr);
+		if ( ret < 0 ) {
+			close(s);
+			DEBUG(DEBUG_CRIT,(__location__ " ioctl failed\n"));
+			return -1;
+		}
+		if (ARPHRD_LOOPBACK == if_hwaddr.ifr_hwaddr.sa_family) {
+			DEBUG(DEBUG_DEBUG,("Ignoring loopback arp request\n"));
+			close(s);
+			return 0;
+		}
+		if (if_hwaddr.ifr_hwaddr.sa_family != AF_LOCAL) {
+			close(s);
+			errno = EINVAL;
+			DEBUG(DEBUG_CRIT,(__location__ " not an ethernet address family (0x%x)\n",
+				 if_hwaddr.ifr_hwaddr.sa_family));
+			return -1;
+		}
+
+		memset(buffer, 0 , sizeof(buffer));
+		eh = (struct ether_header *)buffer;
+		memset(eh->ether_dhost, 0xff, ETH_ALEN);
+		memcpy(eh->ether_shost, if_hwaddr.ifr_hwaddr.sa_data, ETH_ALEN);
+		eh->ether_type = htons(ETHERTYPE_IP6);
+
+		ip6 = (struct ip6_hdr *)(eh+1);
+		ip6->ip6_vfc  = 0x60;
+		ip6->ip6_plen = htons(24);
+		ip6->ip6_nxt  = IPPROTO_ICMPV6;
+		ip6->ip6_hlim = 255;
+		ip6->ip6_dst  = addr->ip6.sin6_addr;
+
+		icmp6 = (struct icmp6_hdr *)(ip6+1);
+		icmp6->icmp6_type = ND_NEIGHBOR_SOLICIT;
+		icmp6->icmp6_code = 0;
+		memcpy(&icmp6->icmp6_data32[1], &addr->ip6.sin6_addr, 16);
+
+		icmp6->icmp6_cksum = tcp_checksum6((uint16_t *)icmp6, ntohs(ip6->ip6_plen), ip6);
+
+		strncpy(sa.sa_data, iface, sizeof(sa.sa_data));
+		ret = sendto(s, buffer, 78, 0, &sa, sizeof(sa));
+		if (ret < 0 ){
+			close(s);
+			DEBUG(DEBUG_CRIT,(__location__ " failed sendto\n"));
+			return -1;
+		}	
+
+		close(s);
+		break;
 	default:
-		DEBUG(DEBUG_CRIT,(__location__ " not an ipv4 address (family is %u)\n", addr->ip.sin_family));
+		DEBUG(DEBUG_CRIT,(__location__ " not an ipv4/ipv6 address (family is %u)\n", addr->ip.sin_family));
 		return -1;
 	}
 
@@ -141,23 +250,6 @@ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface)
 
 
 /*
-  uint16 checksum for n bytes
- */
-static uint32_t uint16_checksum(uint16_t *data, size_t n)
-{
-	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);
-	}
-	return sum;
-}
-
-/*
   simple TCP checksum - assumes data is multiple of 2 bytes long


-- 
CTDB repository


More information about the samba-cvs mailing list