From ef997d344f189891ec201a71e8f57bc1ca88992c Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 19 Aug 2008 14:58:29 +1000 Subject: [PATCH] initial ipv6 patch Signed-off-by: Ronnie Sahlberg (This used to be ctdb commit 1f131f21386f428bbbbb29098d56c2f64596583b) --- ctdb/client/ctdb_client.c | 6 +- ctdb/common/ctdb_util.c | 111 +++++------ ctdb/common/system_aix.c | 87 +++++---- ctdb/common/system_linux.c | 112 +++++++---- ctdb/include/ctdb_private.h | 53 ++--- ctdb/server/ctdb_control.c | 4 +- ctdb/server/ctdb_daemon.c | 2 +- ctdb/server/ctdb_recover.c | 5 +- ctdb/server/ctdb_recoverd.c | 11 +- ctdb/server/ctdb_takeover.c | 377 +++++++++++++++++++----------------- ctdb/server/ctdbd.c | 6 +- ctdb/tcp/tcp_connect.c | 131 ++++++++----- ctdb/tests/nodes.txt | 8 +- ctdb/tests/nodes6.txt | 11 ++ ctdb/tests/start_daemons.sh | 9 +- ctdb/tools/ctdb.c | 94 ++++----- ctdb/utils/ipmux/ipmux.c | 8 +- 17 files changed, 577 insertions(+), 458 deletions(-) create mode 100644 ctdb/tests/nodes6.txt diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c index 0d853746aac..dfcd4d90e79 100644 --- a/ctdb/client/ctdb_client.c +++ b/ctdb/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/ctdb/common/ctdb_util.c b/ctdb/common/ctdb_util.c index b096a52946b..20238363b60 100644 --- a/ctdb/common/ctdb_util.c +++ b/ctdb/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,31 +458,51 @@ 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) -{ - return ip1->sin_family == ip2->sin_family && - ip1->sin_addr.s_addr == ip2->sin_addr.s_addr; -} - -bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2) +bool ctdb_same_ip(const ctdb_sock_addr *ip1, const ctdb_sock_addr *ip2) { if (ip1->sa.sa_family != ip2->sa.sa_family) { return false; @@ -538,13 +524,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/ctdb/common/system_aix.c b/ctdb/common/system_aix.c index b08692d1774..03d997ff6fc 100644 --- a/ctdb/common/system_aix.c +++ b/ctdb/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); + /* 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->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; + /* 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; - return 0; + + 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; + } + + return -1; } diff --git a/ctdb/common/system_linux.c b/ctdb/common/system_linux.c index 32db545b09f..760877fe3ad 100644 --- a/ctdb/common/system_linux.c +++ b/ctdb/common/system_linux.c @@ -344,17 +344,17 @@ int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, ifname, if non-NULL, will return the name of the interface this ip is tied to */ -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->ip.sin_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; @@ -395,7 +395,7 @@ int ctdb_sys_close_capture_socket(void *private_data) called when the raw socket becomes readable */ 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; @@ -403,6 +403,7 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data, char pkt[RCVPKTSIZE]; struct ether_header *eth; struct iphdr *ip; + struct ip6_hdr *ip6; struct tcphdr *tcp; ret = recv(s, pkt, RCVPKTSIZE, MSG_TRUNC); @@ -413,45 +414,74 @@ int ctdb_sys_read_tcp_packet(int s, void *private_data, /* Ethernet */ eth = (struct ether_header *)pkt; - /* We only want IP packets */ - if (ntohs(eth->ether_type) != ETHERTYPE_IP) { - return -1; - } - - /* IP */ - ip = (struct iphdr *)(eth+1); + /* we want either IPv4 or IPv6 */ + if (ntohs(eth->ether_type) == ETHERTYPE_IP) { + /* IP */ + ip = (struct iphdr *)(eth+1); - /* We only want IPv4 packets */ - if (ip->version != 4) { - return -1; - } - /* Dont look at fragments */ - if ((ntohs(ip->frag_off)&0x1fff) != 0) { - return -1; - } - /* we only want TCP */ - if (ip->protocol != IPPROTO_TCP) { - return -1; + /* We only want IPv4 packets */ + if (ip->version != 4) { + return -1; + } + /* Dont look at fragments */ + if ((ntohs(ip->frag_off)&0x1fff) != 0) { + return -1; + } + /* we only want TCP */ + if (ip->protocol != IPPROTO_TCP) { + return -1; + } + + /* make sure its not a short packet */ + if (offsetof(struct tcphdr, ack_seq) + 4 + + (ip->ihl*4) + sizeof(*eth) > ret) { + return -1; + } + /* TCP */ + tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); + + /* tell the caller which one we've found */ + src->ip.sin_family = AF_INET; + src->ip.sin_addr.s_addr = ip->saddr; + src->ip.sin_port = tcp->source; + dst->ip.sin_family = AF_INET; + dst->ip.sin_addr.s_addr = ip->daddr; + dst->ip.sin_port = tcp->dest; + *ack_seq = tcp->ack_seq; + *seq = tcp->seq; + + return 0; +#ifndef ETHERTYPE_IP6 +#define ETHERTYPE_IP6 0x86dd +#endif + } else if (ntohs(eth->ether_type) == ETHERTYPE_IP6) { + /* IP6 */ + ip6 = (struct ip6_hdr *)(eth+1); + + /* we only want TCP */ + if (ip6->ip6_nxt != IPPROTO_TCP) { + return -1; + } + + /* TCP */ + tcp = (struct tcphdr *)(ip6+1); + + /* tell the caller which one we've found */ + src->ip6.sin6_family = AF_INET6; + src->ip6.sin6_port = tcp->source; + src->ip6.sin6_addr = ip6->ip6_src; + + dst->ip6.sin6_family = AF_INET6; + dst->ip6.sin6_port = tcp->source; + dst->ip6.sin6_addr = ip6->ip6_dst; + + *ack_seq = tcp->ack_seq; + *seq = tcp->seq; + + return 0; } - /* make sure its not a short packet */ - if (offsetof(struct tcphdr, ack_seq) + 4 + - (ip->ihl*4) + sizeof(*eth) > ret) { - return -1; - } - - /* TCP */ - tcp = (struct tcphdr *)((ip->ihl*4) + (char *)ip); - - /* tell the caller which one we've found */ - src->sin_addr.s_addr = ip->saddr; - src->sin_port = tcp->source; - dst->sin_addr.s_addr = ip->daddr; - dst->sin_port = tcp->dest; - *ack_seq = tcp->ack_seq; - *seq = tcp->seq; - - return 0; + return -1; } diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index f44a940a84e..f73f9ef963f 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -61,8 +61,8 @@ typedef union { a tcp connection description */ struct ctdb_tcp_connection { - struct sockaddr_in saddr; - struct sockaddr_in daddr; + ctdb_sock_addr src_addr; + ctdb_sock_addr dst_addr; }; /* the wire representation for a tcp tickle array */ @@ -73,7 +73,7 @@ struct ctdb_tcp_wire_array { /* the list of tcp tickles used by get/set tcp tickle list */ struct ctdb_control_tcp_tickle_list { - struct sockaddr_in ip; + ctdb_sock_addr addr; struct ctdb_tcp_wire_array tickles; }; @@ -170,7 +170,7 @@ struct ctdb_vnn { struct ctdb_vnn *prev, *next; const char *iface; - struct sockaddr_in public_address; + ctdb_sock_addr public_address; uint8_t public_netmask_bits; /* the node number that is serving this public address, if any. @@ -563,26 +563,27 @@ struct ctdb_control_set_call { /* struct for tcp_client control + used by samba can not modify */ -struct ctdb_control_tcp { - struct sockaddr_in src; - struct sockaddr_in dest; +struct ctdb_tcp_client { + struct sockaddr_in src; // samba uses this + struct sockaddr_in dest;// samba uses this }; /* struct for kill_tcp control */ struct ctdb_control_killtcp { - struct sockaddr_in src; - struct sockaddr_in dst; + ctdb_sock_addr src_addr; + ctdb_sock_addr dst_addr; }; /* - struct holding a sockaddr_in and an interface name, + struct holding a ctdb_sock_addr and an interface name, used to add/remove public addresses */ struct ctdb_control_ip_iface { - struct sockaddr_in sin; + ctdb_sock_addr addr; uint32_t mask; uint32_t len; char iface[1]; @@ -603,8 +604,8 @@ struct ctdb_control_gratious_arp { struct for tcp_add and tcp_remove controls */ struct ctdb_control_tcp_vnn { - struct sockaddr_in src; - struct sockaddr_in dest; + ctdb_sock_addr src; + ctdb_sock_addr dest; }; /* @@ -804,13 +805,11 @@ enum ctdb_trans2_commit_error { void ctdb_set_error(struct ctdb_context *ctdb, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); void ctdb_fatal(struct ctdb_context *ctdb, const char *msg); bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2); -bool parse_ip_mask(const char *s, struct sockaddr_in *ip, unsigned *mask); int ctdb_parse_address(struct ctdb_context *ctdb, TALLOC_CTX *mem_ctx, const char *str, struct ctdb_address *address); -bool ctdb_same_ipv4(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2); -bool ctdb_same_ip(ctdb_sock_addr *ip1, ctdb_sock_addr *ip2); -bool ctdb_same_sockaddr(const struct sockaddr_in *ip1, const struct sockaddr_in *ip2); +bool ctdb_same_ip(const ctdb_sock_addr *ip1, const ctdb_sock_addr *ip2); +bool ctdb_same_sockaddr(const ctdb_sock_addr *ip1, const ctdb_sock_addr *ip2); uint32_t ctdb_hash(const TDB_DATA *key); uint32_t ctdb_hash_string(const char *str); void ctdb_request_call(struct ctdb_context *ctdb, struct ctdb_req_header *hdr); @@ -1085,8 +1084,7 @@ struct ctdb_control_list_tunable { struct ctdb_node_and_flags { uint32_t pnn; uint32_t flags; - struct sockaddr_in sin; - + ctdb_sock_addr addr; }; struct ctdb_node_map { @@ -1191,7 +1189,7 @@ int32_t ctdb_control_end_recovery(struct ctdb_context *ctdb, struct ctdb_public_ip { uint32_t pnn; - struct sockaddr_in sin; + ctdb_sock_addr addr; }; int ctdb_ctrl_takeover_ip(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, struct ctdb_public_ip *ip); @@ -1210,7 +1208,7 @@ int ctdb_ctrl_get_public_ips(struct ctdb_context *ctdb, /* from takeover/system.c */ int ctdb_sys_send_arp(const ctdb_sock_addr *addr, const char *iface); -bool ctdb_sys_have_ip(struct sockaddr_in ip); +bool ctdb_sys_have_ip(ctdb_sock_addr *addr); int ctdb_sys_send_tcp(const ctdb_sock_addr *dest, const ctdb_sock_addr *src, uint32_t seq, uint32_t ack, int rst); @@ -1266,13 +1264,14 @@ 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, ctdb_sock_addr *saddr); -bool parse_ip(const char *s, ctdb_sock_addr *saddr); +bool parse_ip_mask(const char *s, ctdb_sock_addr *addr, unsigned *mask); +bool parse_ip_port(const char *s, ctdb_sock_addr *addr); +bool parse_ip(const char *s, ctdb_sock_addr *addr); + int ctdb_sys_open_capture_socket(const char *iface, void **private_data); int ctdb_sys_close_capture_socket(void *private_data); -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); +int ctdb_sys_read_tcp_packet(int s, void *private_data, ctdb_sock_addr *src, ctdb_sock_addr *dst, uint32_t *ack_seq, uint32_t *seq); int ctdb_ctrl_killtcp(struct ctdb_context *ctdb, struct timeval timeout, @@ -1299,7 +1298,7 @@ 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); @@ -1376,4 +1375,6 @@ int32_t ctdb_control_trans2_finished(struct ctdb_context *ctdb, int32_t ctdb_control_trans2_error(struct ctdb_context *ctdb, struct ctdb_req_control *c); +char *ctdb_addr_to_str(ctdb_sock_addr *addr); + #endif diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index edfe344fdb9..68635d6b439 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -296,7 +296,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, return ctdb_control_get_public_ips(ctdb, c, outdata); case CTDB_CONTROL_TCP_CLIENT: - CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_control_tcp)); + CHECK_CONTROL_DATA_SIZE(sizeof(struct ctdb_tcp_client)); return ctdb_control_tcp_client(ctdb, client_id, indata); case CTDB_CONTROL_STARTUP: @@ -325,7 +325,7 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, return ctdb_control_kill_tcp(ctdb, indata); case CTDB_CONTROL_GET_TCP_TICKLE_LIST: - CHECK_CONTROL_DATA_SIZE(sizeof(struct sockaddr_in)); + CHECK_CONTROL_DATA_SIZE(sizeof(ctdb_sock_addr)); return ctdb_control_get_tcp_tickle_list(ctdb, indata, outdata); case CTDB_CONTROL_SET_TCP_TICKLE_LIST: diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c index 3978e28fdf4..efe3d753498 100644 --- a/ctdb/server/ctdb_daemon.c +++ b/ctdb/server/ctdb_daemon.c @@ -535,7 +535,7 @@ static void ctdb_daemon_read_cb(uint8_t *data, size_t cnt, void *args) static void ctdb_accept_client(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *private_data) { - struct sockaddr_in addr; + struct sockaddr_un addr; socklen_t len; int fd; struct ctdb_context *ctdb = talloc_get_type(private_data, struct ctdb_context); diff --git a/ctdb/server/ctdb_recover.c b/ctdb/server/ctdb_recover.c index f0b97acdeed..3243f42faa7 100644 --- a/ctdb/server/ctdb_recover.c +++ b/ctdb/server/ctdb_recover.c @@ -163,7 +163,10 @@ ctdb_control_getnodemap(struct ctdb_context *ctdb, uint32_t opcode, TDB_DATA ind node_map = (struct ctdb_node_map *)outdata->dptr; node_map->num = num_nodes; for (i=0; inodes[i]->address.address, &node_map->nodes[i].sin.sin_addr); + if (parse_ip(ctdb->nodes[i]->address.address, &node_map->nodes[i].addr) == 0) { + DEBUG(DEBUG_ERR, (__location__ " Failed to parse %s into a sockaddr\n", ctdb->nodes[i]->address.address)); + } + node_map->nodes[i].pnn = ctdb->nodes[i]->pnn; node_map->nodes[i].flags = ctdb->nodes[i]->flags; } diff --git a/ctdb/server/ctdb_recoverd.c b/ctdb/server/ctdb_recoverd.c index c503aa5489a..c6a4ab322a3 100644 --- a/ctdb/server/ctdb_recoverd.c +++ b/ctdb/server/ctdb_recoverd.c @@ -2207,8 +2207,9 @@ static int verify_ip_allocation(struct ctdb_context *ctdb, uint32_t pnn) */ for (j=0; jnum; j++) { if (ips->ips[j].pnn == pnn) { - if (!ctdb_sys_have_ip(ips->ips[j].sin)) { - DEBUG(DEBUG_CRIT,("Public address '%s' is missing and we should serve this ip\n", inet_ntoa(ips->ips[j].sin.sin_addr))); + if (!ctdb_sys_have_ip(&ips->ips[j].addr)) { + DEBUG(DEBUG_CRIT,("Public address '%s' is missing and we should serve this ip\n", + ctdb_addr_to_str(&ips->ips[j].addr))); ret = ctdb_ctrl_freeze(ctdb, CONTROL_TIMEOUT(), CTDB_CURRENT_NODE); if (ret != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to freeze node due to public ip address mismatches\n")); @@ -2225,8 +2226,10 @@ static int verify_ip_allocation(struct ctdb_context *ctdb, uint32_t pnn) } } } else { - if (ctdb_sys_have_ip(ips->ips[j].sin)) { - DEBUG(DEBUG_CRIT,("We are still serving a public address '%s' that we should not be serving.\n", inet_ntoa(ips->ips[j].sin.sin_addr))); + if (ctdb_sys_have_ip(&ips->ips[j].addr)) { + DEBUG(DEBUG_CRIT,("We are still serving a public address '%s' that we should not be serving.\n", + ctdb_addr_to_str(&ips->ips[j].addr))); + ret = ctdb_ctrl_freeze(ctdb, CONTROL_TIMEOUT(), CTDB_CURRENT_NODE); if (ret != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to freeze node due to public ip address mismatches\n")); diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c index 53f48c175a1..54581909961 100644 --- a/ctdb/server/ctdb_takeover.c +++ b/ctdb/server/ctdb_takeover.c @@ -56,7 +56,7 @@ struct ctdb_tcp_list { struct ctdb_client_ip { struct ctdb_client_ip *prev, *next; struct ctdb_context *ctdb; - struct sockaddr_in ip; + ctdb_sock_addr addr; uint32_t client_id; }; @@ -72,7 +72,6 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event * int i, ret; struct ctdb_tcp_array *tcparray; - ret = ctdb_sys_send_arp(&arp->addr, arp->vnn->iface); if (ret != 0) { DEBUG(DEBUG_CRIT,(__location__ " sending of arp failed (%s)\n", strerror(errno))); @@ -81,17 +80,20 @@ static void ctdb_control_send_arp(struct event_context *ev, struct timed_event * tcparray = arp->tcparray; if (tcparray) { for (i=0;inum;i++) { + struct ctdb_tcp_connection *tcon; + + tcon = &tcparray->connections[i]; DEBUG(DEBUG_INFO,("sending tcp tickle ack for %u->%s:%u\n", - (unsigned)ntohs(tcparray->connections[i].daddr.sin_port), - inet_ntoa(tcparray->connections[i].saddr.sin_addr), - (unsigned)ntohs(tcparray->connections[i].saddr.sin_port))); + (unsigned)ntohs(tcon->dst_addr.ip.sin_port), + ctdb_addr_to_str(&tcon->src_addr), + (unsigned)ntohs(tcon->src_addr.ip.sin_port))); ret = ctdb_sys_send_tcp( - (ctdb_sock_addr *)&tcparray->connections[i].saddr, - (ctdb_sock_addr *)&tcparray->connections[i].daddr, + &tcon->src_addr, + &tcon->dst_addr, 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))); + ctdb_addr_to_str(&tcon->src_addr))); } } } @@ -126,14 +128,9 @@ static void takeover_ip_callback(struct ctdb_context *ctdb, int status, struct ctdb_tcp_array *tcparray; if (status != 0) { - char ip[128] = ""; - - if (inet_ntop(state->addr->sa.sa_family, &state->addr->sa.sa_data[0], ip, sizeof(ip)) == NULL) { - DEBUG(DEBUG_ERR, (__location__ " inet_ntop() failed\n")); - } - DEBUG(DEBUG_ERR,(__location__ " Failed to takeover IP %s on interface %s\n", - ip, state->vnn->iface)); + ctdb_addr_to_str(state->addr), + state->vnn->iface)); ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL); talloc_free(state); return; @@ -181,12 +178,12 @@ failed: Find the vnn of the node that has a public ip address returns -1 if the address is not known as a public address */ -static struct ctdb_vnn *find_public_ip_vnn(struct ctdb_context *ctdb, struct sockaddr_in ip) +static struct ctdb_vnn *find_public_ip_vnn(struct ctdb_context *ctdb, ctdb_sock_addr *addr) { struct ctdb_vnn *vnn; for (vnn=ctdb->vnn;vnn;vnn=vnn->next) { - if (ctdb_same_ipv4(&vnn->public_address, &ip)) { + if (ctdb_same_ip(&vnn->public_address, addr)) { return vnn; } } @@ -209,16 +206,16 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb, struct ctdb_vnn *vnn; /* update out vnn list */ - vnn = find_public_ip_vnn(ctdb, pip->sin); + vnn = find_public_ip_vnn(ctdb, &pip->addr); if (vnn == NULL) { DEBUG(DEBUG_ERR,("takeoverip called for an ip '%s' that is not a public address\n", - inet_ntoa(pip->sin.sin_addr))); + ctdb_addr_to_str(&pip->addr))); return 0; } vnn->pnn = pip->pnn; /* if our kernel already has this IP, do nothing */ - if (ctdb_sys_have_ip(pip->sin)) { + if (ctdb_sys_have_ip(&pip->addr)) { return 0; } @@ -229,24 +226,26 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb, state->addr = talloc(ctdb, ctdb_sock_addr); CTDB_NO_MEMORY(ctdb, state->addr); - state->addr->ip = pip->sin; //qqq pip must be converted - state->vnn = vnn; + *state->addr = pip->addr; + state->vnn = vnn; DEBUG(DEBUG_NOTICE,("Takeover of IP %s/%u on interface %s\n", - inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits, - vnn->iface)); + ctdb_addr_to_str(&pip->addr), + vnn->public_netmask_bits, + vnn->iface)); ret = ctdb_event_script_callback(ctdb, timeval_current_ofs(ctdb->tunable.script_timeout, 0), state, takeover_ip_callback, state, "takeip %s %s %u", vnn->iface, - inet_ntoa(pip->sin.sin_addr), + talloc_strdup(state, ctdb_addr_to_str(&pip->addr)), vnn->public_netmask_bits); if (ret != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to takeover IP %s on interface %s\n", - inet_ntoa(pip->sin.sin_addr), vnn->iface)); + ctdb_addr_to_str(&pip->addr), + vnn->iface)); talloc_free(state); return -1; } @@ -263,27 +262,32 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb, static void release_kill_clients(struct ctdb_context *ctdb, ctdb_sock_addr *addr) { struct ctdb_client_ip *ip; - char cip[128] = ""; - DEBUG(DEBUG_INFO,("release_kill_clients for ip %s\n", inet_ntop(addr->sa.sa_family, &addr->sa.sa_data[0], cip, sizeof(cip)))); + DEBUG(DEBUG_INFO,("release_kill_clients for ip %s\n", + ctdb_addr_to_str(addr))); for (ip=ctdb->client_ip_list; ip; ip=ip->next) { ctdb_sock_addr tmp_addr; - tmp_addr.ip = ip->ip; //qqq until ip->ip is no longer a sockaddr_in + tmp_addr = ip->addr; DEBUG(DEBUG_INFO,("checking for client %u with IP %s\n", - ip->client_id, inet_ntoa(ip->ip.sin_addr))); + ip->client_id, + ctdb_addr_to_str(&ip->addr))); + if (ctdb_same_ip(&tmp_addr, addr)) { struct ctdb_client *client = ctdb_reqid_find(ctdb, ip->client_id, struct ctdb_client); DEBUG(DEBUG_INFO,("matched client %u with IP %s and pid %u\n", - ip->client_id, inet_ntoa(ip->ip.sin_addr), client->pid)); + ip->client_id, + ctdb_addr_to_str(&ip->addr), + client->pid)); + if (client->pid != 0) { DEBUG(DEBUG_INFO,(__location__ " Killing client pid %u for IP %s on client_id %u\n", - (unsigned)client->pid, - inet_ntop(addr->sa.sa_family, &addr->sa.sa_data[0], cip, sizeof(cip)), - ip->client_id)); + (unsigned)client->pid, + ctdb_addr_to_str(addr), + ip->client_id)); kill(client->pid, SIGKILL); } } @@ -298,21 +302,13 @@ static void release_ip_callback(struct ctdb_context *ctdb, int status, { struct takeover_callback_state *state = talloc_get_type(private_data, struct takeover_callback_state); - char ip[128] = ""; TDB_DATA data; /* send a message to all clients of this node telling them that the cluster has been reconfigured and they should release any sockets on this IP */ -#if 1 - strncpy(ip, inet_ntoa(state->addr->ip.sin_addr), sizeof(ip)-1); -#else - if (inet_ntop(state->addr->sa.sa_family, &state->addr->sa.sa_data[0], ip, sizeof(ip)) == NULL) { - DEBUG(DEBUG_ERR, (__location__ " inet_ntop() failed\n")); - } -#endif - data.dptr = (uint8_t *)ip; - data.dsize = strlen(ip)+1; + data.dptr = (uint8_t *)talloc_strdup(state, ctdb_addr_to_str(state->addr)); + data.dsize = strlen((char *)data.dptr)+1; DEBUG(DEBUG_INFO,(__location__ " sending RELEASE_IP for '%s'\n", data.dptr)); @@ -340,10 +336,10 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, struct ctdb_vnn *vnn; /* update our vnn list */ - vnn = find_public_ip_vnn(ctdb, pip->sin); + vnn = find_public_ip_vnn(ctdb, &pip->addr); if (vnn == NULL) { - DEBUG(DEBUG_INFO,("releaseip called for an ip '%s' that is not a public address\n", - inet_ntoa(pip->sin.sin_addr))); + DEBUG(DEBUG_ERR,("takeoverip called for an ip '%s' that is not a public address\n", + ctdb_addr_to_str(&pip->addr))); return 0; } vnn->pnn = pip->pnn; @@ -352,16 +348,18 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, talloc_free(vnn->takeover_ctx); vnn->takeover_ctx = NULL; - if (!ctdb_sys_have_ip(pip->sin)) { + if (!ctdb_sys_have_ip(&pip->addr)) { DEBUG(DEBUG_INFO,("Redundant release of IP %s/%u on interface %s (ip not held)\n", - inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits, - vnn->iface)); + ctdb_addr_to_str(&pip->addr), + vnn->public_netmask_bits, + vnn->iface)); return 0; } DEBUG(DEBUG_NOTICE,("Release of IP %s/%u on interface %s\n", - inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits, - vnn->iface)); + ctdb_addr_to_str(&pip->addr), + vnn->public_netmask_bits, + vnn->iface)); state = talloc(ctdb, struct takeover_callback_state); CTDB_NO_MEMORY(ctdb, state); @@ -369,20 +367,20 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, state->c = talloc_steal(state, c); state->addr = talloc(state, ctdb_sock_addr); CTDB_NO_MEMORY(ctdb, state->addr); - state->addr->ip = pip->sin; //qqq pip must be converted - - state->vnn = vnn; + *state->addr = pip->addr; + state->vnn = vnn; ret = ctdb_event_script_callback(ctdb, timeval_current_ofs(ctdb->tunable.script_timeout, 0), state, release_ip_callback, state, "releaseip %s %s %u", vnn->iface, - inet_ntoa(pip->sin.sin_addr), + talloc_strdup(state, ctdb_addr_to_str(&pip->addr)), vnn->public_netmask_bits); if (ret != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to release IP %s on interface %s\n", - inet_ntoa(pip->sin.sin_addr), vnn->iface)); + ctdb_addr_to_str(&pip->addr), + vnn->iface)); talloc_free(state); return -1; } @@ -394,15 +392,15 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb, -static int ctdb_add_public_address(struct ctdb_context *ctdb, struct sockaddr_in addr, unsigned mask, const char *iface) +static int ctdb_add_public_address(struct ctdb_context *ctdb, ctdb_sock_addr *addr, unsigned mask, const char *iface) { struct ctdb_vnn *vnn; /* Verify that we dont have an entry for this ip yet */ for (vnn=ctdb->vnn;vnn;vnn=vnn->next) { - if (ctdb_same_sockaddr(&addr, &vnn->public_address)) { + if (ctdb_same_sockaddr(addr, &vnn->public_address)) { DEBUG(DEBUG_CRIT,("Same ip '%s' specified multiple times in the public address list \n", - inet_ntoa(addr.sin_addr))); + ctdb_addr_to_str(addr))); return -1; } } @@ -411,7 +409,7 @@ static int ctdb_add_public_address(struct ctdb_context *ctdb, struct sockaddr_in vnn = talloc_zero(ctdb, struct ctdb_vnn); CTDB_NO_MEMORY_FATAL(ctdb, vnn); vnn->iface = talloc_strdup(vnn, iface); - vnn->public_address = addr; + vnn->public_address = *addr; vnn->public_netmask_bits = mask; vnn->pnn = -1; @@ -451,7 +449,7 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist) for (i=0;inum;i++) { - if (ip->sin.sin_addr.s_addr == public_ips->ips[i].sin.sin_addr.s_addr) { + if (ctdb_same_ip(&ip->addr, &public_ips->ips[i].addr)) { /* yes, this node can serve this public ip */ return 0; } @@ -579,7 +577,9 @@ static int find_takeover_node(struct ctdb_context *ctdb, } } if (pnn == -1) { - DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n", inet_ntoa(ip->sin.sin_addr))); + DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n", + ctdb_addr_to_str(&ip->addr))); + return -1; } @@ -598,8 +598,8 @@ add_ip_to_merged_list(struct ctdb_context *ctdb, /* do we already have this ip in our merged list ?*/ for (tmp_ip=ip_list;tmp_ip;tmp_ip=tmp_ip->next) { - /* we already have this public ip in the list */ - if (tmp_ip->sin.sin_addr.s_addr == ip->sin.sin_addr.s_addr) { + /* we already have this public ip in the list */ + if (ctdb_same_ip(&tmp_ip->addr, &ip->addr)) { return ip_list; } } @@ -608,7 +608,7 @@ add_ip_to_merged_list(struct ctdb_context *ctdb, tmp_ip = talloc_zero(tmp_ctx, struct ctdb_public_ip_list); CTDB_NO_MEMORY_NULL(ctdb, tmp_ip); tmp_ip->pnn = ip->pnn; - tmp_ip->sin = ip->sin; + tmp_ip->addr = ip->addr; tmp_ip->next = ip_list; return tmp_ip; @@ -734,7 +734,8 @@ try_again: for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) { if (tmp_ip->pnn == -1) { if (find_takeover_node(ctdb, nodemap, mask, tmp_ip, all_ips)) { - DEBUG(DEBUG_WARNING,("Failed to find node to cover ip %s\n", inet_ntoa(tmp_ip->sin.sin_addr))); + DEBUG(DEBUG_WARNING,("Failed to find node to cover ip %s\n", + ctdb_addr_to_str(&tmp_ip->addr))); } } } @@ -801,7 +802,9 @@ try_again: } } if (maxnode == -1) { - DEBUG(DEBUG_WARNING,(__location__ " Could not find maxnode. May not be able to serve ip '%s'\n", inet_ntoa(tmp_ip->sin.sin_addr))); + DEBUG(DEBUG_WARNING,(__location__ " Could not find maxnode. May not be able to serve ip '%s'\n", + ctdb_addr_to_str(&tmp_ip->addr))); + continue; } @@ -864,9 +867,8 @@ finished: */ continue; } - ip.pnn = tmp_ip->pnn; - ip.sin.sin_family = AF_INET; - ip.sin.sin_addr = tmp_ip->sin.sin_addr; + ip.pnn = tmp_ip->pnn; + ip.addr = tmp_ip->addr; timeout = TAKEOVER_TIMEOUT(); data.dsize = sizeof(ip); @@ -900,9 +902,8 @@ finished: /* this IP won't be taken over */ continue; } - ip.pnn = tmp_ip->pnn; - ip.sin.sin_family = AF_INET; - ip.sin.sin_addr = tmp_ip->sin.sin_addr; + ip.pnn = tmp_ip->pnn; + ip.addr = tmp_ip->addr; timeout = TAKEOVER_TIMEOUT(); data.dsize = sizeof(ip); @@ -936,7 +937,10 @@ finished: static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip) { DEBUG(DEBUG_DEBUG,("destroying client tcp for %s:%u (client_id %u)\n", - inet_ntoa(ip->ip.sin_addr), ntohs(ip->ip.sin_port), ip->client_id)); + ctdb_addr_to_str(&ip->addr), + ntohs(ip->addr.ip.sin_port), + ip->client_id)); + DLIST_REMOVE(ip->ctdb->client_ip_list, ip); return 0; } @@ -945,31 +949,36 @@ static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip) called by a client to inform us of a TCP connection that it is managing that should tickled with an ACK when IP takeover is done */ +//qqq we need a new version of this control that takes ctdb_sock_addr +//and have samba move to that instead. +// This is IPV4 ONLY int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, TDB_DATA indata) { struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client); - struct ctdb_control_tcp *p = (struct ctdb_control_tcp *)indata.dptr; + struct ctdb_tcp_client *p = (struct ctdb_tcp_client *)indata.dptr; struct ctdb_tcp_list *tcp; struct ctdb_control_tcp_vnn t; int ret; TDB_DATA data; struct ctdb_client_ip *ip; struct ctdb_vnn *vnn; + ctdb_sock_addr addr; - vnn = find_public_ip_vnn(ctdb, p->dest); + addr.ip = p->dest; + vnn = find_public_ip_vnn(ctdb, &addr); if (vnn == NULL) { if (ntohl(p->dest.sin_addr.s_addr) != INADDR_LOOPBACK) { DEBUG(DEBUG_INFO,("Could not add client IP %s. This is not a public address.\n", - inet_ntoa(p->dest.sin_addr))); + ctdb_addr_to_str((ctdb_sock_addr *)&p->dest))); } return 0; } if (vnn->pnn != ctdb->pnn) { DEBUG(DEBUG_ERR,("Attempt to register tcp client for IP %s we don't hold - failing (client_id %u pid %u)\n", - inet_ntoa(p->dest.sin_addr), - client_id, client->pid)); + ctdb_addr_to_str((ctdb_sock_addr *)&p->dest), + client_id, client->pid)); /* failing this call will tell smbd to die */ return -1; } @@ -977,8 +986,8 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, ip = talloc(client, struct ctdb_client_ip); CTDB_NO_MEMORY(ctdb, ip); - ip->ctdb = ctdb; - ip->ip = p->dest; + ip->ctdb = ctdb; + ip->addr.ip = p->dest; ip->client_id = client_id; talloc_set_destructor(ip, ctdb_client_ip_destructor); DLIST_ADD(ctdb->client_ip_list, ip); @@ -986,21 +995,21 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, tcp = talloc(client, struct ctdb_tcp_list); CTDB_NO_MEMORY(ctdb, tcp); - tcp->connection.saddr = p->src; - tcp->connection.daddr = p->dest; + tcp->connection.src_addr.ip = p->src; + tcp->connection.dst_addr.ip = p->dest; DLIST_ADD(client->tcp_list, tcp); - t.src = p->src; - t.dest = p->dest; + t.src.ip = p->src; + t.dest.ip = p->dest; data.dptr = (uint8_t *)&t; data.dsize = sizeof(t); DEBUG(DEBUG_INFO,("registered tcp client for %u->%s:%u (client_id %u pid %u)\n", - (unsigned)ntohs(p->dest.sin_port), - inet_ntoa(p->src.sin_addr), - (unsigned)ntohs(p->src.sin_port), client_id, client->pid)); + (unsigned)ntohs(p->dest.sin_port), + ctdb_addr_to_str((ctdb_sock_addr *)&p->src), + (unsigned)ntohs(p->src.sin_port), client_id, client->pid)); /* tell all nodes about this tcp connection */ ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0, @@ -1014,16 +1023,6 @@ int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id, return 0; } -/* - see if two sockaddr_in are the same - */ -static bool same_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2) -{ - return in1->sin_family == in2->sin_family && - in1->sin_port == in2->sin_port && - in1->sin_addr.s_addr == in2->sin_addr.s_addr; -} - /* find a tcp address on a list */ @@ -1037,8 +1036,8 @@ static struct ctdb_tcp_connection *ctdb_tcp_find(struct ctdb_tcp_array *array, } for (i=0;inum;i++) { - if (same_sockaddr_in(&array->connections[i].saddr, &tcp->saddr) && - same_sockaddr_in(&array->connections[i].daddr, &tcp->daddr)) { + if (ctdb_same_sockaddr(&array->connections[i].src_addr, &tcp->src_addr) && + ctdb_same_sockaddr(&array->connections[i].dst_addr, &tcp->dst_addr)) { return &array->connections[i]; } } @@ -1057,10 +1056,11 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata) struct ctdb_tcp_connection tcp; struct ctdb_vnn *vnn; - vnn = find_public_ip_vnn(ctdb, p->dest); + vnn = find_public_ip_vnn(ctdb, &p->dest); if (vnn == NULL) { - DEBUG(DEBUG_ERR,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n", - inet_ntoa(p->dest.sin_addr))); + DEBUG(DEBUG_ERR,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n", + ctdb_addr_to_str(&p->dest))); + return -1; } @@ -1079,21 +1079,21 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata) tcparray->connections = talloc_size(tcparray, sizeof(struct ctdb_tcp_connection)); CTDB_NO_MEMORY(ctdb, tcparray->connections); - tcparray->connections[tcparray->num].saddr = p->src; - tcparray->connections[tcparray->num].daddr = p->dest; + tcparray->connections[tcparray->num].src_addr = p->src; + tcparray->connections[tcparray->num].dst_addr = p->dest; tcparray->num++; return 0; } /* Do we already have this tickle ?*/ - tcp.saddr = p->src; - tcp.daddr = p->dest; + tcp.src_addr = p->src; + tcp.dst_addr = p->dest; if (ctdb_tcp_find(vnn->tcp_array, &tcp) != NULL) { DEBUG(DEBUG_DEBUG,("Already had tickle info for %s:%u for vnn:%u\n", - inet_ntoa(tcp.daddr.sin_addr), - ntohs(tcp.daddr.sin_port), - vnn->pnn)); + ctdb_addr_to_str(&tcp.dst_addr), + ntohs(tcp.dst_addr.ip.sin_port), + vnn->pnn)); return 0; } @@ -1104,14 +1104,14 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata) CTDB_NO_MEMORY(ctdb, tcparray->connections); vnn->tcp_array = tcparray; - tcparray->connections[tcparray->num].saddr = p->src; - tcparray->connections[tcparray->num].daddr = p->dest; + tcparray->connections[tcparray->num].src_addr = p->src; + tcparray->connections[tcparray->num].dst_addr = p->dest; tcparray->num++; DEBUG(DEBUG_INFO,("Added tickle info for %s:%u from vnn %u\n", - inet_ntoa(tcp.daddr.sin_addr), - ntohs(tcp.daddr.sin_port), - vnn->pnn)); + ctdb_addr_to_str(&tcp.dst_addr), + ntohs(tcp.dst_addr.ip.sin_port), + vnn->pnn)); return 0; } @@ -1125,10 +1125,11 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata) static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tcp_connection *conn) { struct ctdb_tcp_connection *tcpp; - struct ctdb_vnn *vnn = find_public_ip_vnn(ctdb, conn->daddr); + struct ctdb_vnn *vnn = find_public_ip_vnn(ctdb, &conn->dst_addr); if (vnn == NULL) { - DEBUG(DEBUG_ERR,(__location__ " unable to find public address %s\n", inet_ntoa(conn->daddr.sin_addr))); + DEBUG(DEBUG_ERR,(__location__ " unable to find public address %s\n", + ctdb_addr_to_str(&conn->dst_addr))); return; } @@ -1137,8 +1138,8 @@ static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tc */ if (vnn->tcp_array == NULL) { DEBUG(DEBUG_INFO,("Trying to remove tickle that doesnt exist (array is empty) %s:%u\n", - inet_ntoa(conn->daddr.sin_addr), - ntohs(conn->daddr.sin_port))); + ctdb_addr_to_str(&conn->dst_addr), + ntohs(conn->dst_addr.ip.sin_port))); return; } @@ -1149,8 +1150,8 @@ static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tc tcpp = ctdb_tcp_find(vnn->tcp_array, conn); if (tcpp == NULL) { DEBUG(DEBUG_INFO,("Trying to remove tickle that doesnt exist %s:%u\n", - inet_ntoa(conn->daddr.sin_addr), - ntohs(conn->daddr.sin_port))); + ctdb_addr_to_str(&conn->dst_addr), + ntohs(conn->dst_addr.ip.sin_port))); return; } @@ -1174,8 +1175,8 @@ static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tc vnn->tcp_update_needed = true; DEBUG(DEBUG_INFO,("Removed tickle info for %s:%u\n", - inet_ntoa(conn->saddr.sin_addr), - ntohs(conn->saddr.sin_port))); + ctdb_addr_to_str(&conn->src_addr), + ntohs(conn->src_addr.ip.sin_port))); } @@ -1212,15 +1213,14 @@ void ctdb_release_all_ips(struct ctdb_context *ctdb) struct ctdb_vnn *vnn; for (vnn=ctdb->vnn;vnn;vnn=vnn->next) { - if (!ctdb_sys_have_ip(vnn->public_address)) { + if (!ctdb_sys_have_ip(&vnn->public_address)) { continue; } ctdb_event_script(ctdb, "releaseip %s %s %u", vnn->iface, - inet_ntoa(vnn->public_address.sin_addr), + talloc_strdup(ctdb, ctdb_addr_to_str(&vnn->public_address)), vnn->public_netmask_bits); -// convert when vnn->public_address is no longer a sockaddr_in - release_kill_clients(ctdb, (ctdb_sock_addr *)&vnn->public_address); + release_kill_clients(ctdb, &vnn->public_address); } } @@ -1252,8 +1252,8 @@ int32_t ctdb_control_get_public_ips(struct ctdb_context *ctdb, ips->num = num; i = 0; for (vnn=ctdb->vnn;vnn;vnn=vnn->next) { - ips->ips[i].pnn = vnn->pnn; - ips->ips[i].sin = vnn->public_address; + ips->ips[i].pnn = vnn->pnn; + ips->ips[i].addr = vnn->public_address; i++; } @@ -1279,8 +1279,8 @@ struct ctdb_kill_tcp { a tcp connection that is to be killed */ struct ctdb_killtcp_con { - struct sockaddr_in src; - struct sockaddr_in dst; + ctdb_sock_addr src_addr; + ctdb_sock_addr dst_addr; int count; struct ctdb_kill_tcp *killtcp; }; @@ -1290,15 +1290,41 @@ struct ctdb_killtcp_con { this key is used to insert and lookup matching socketpairs that are to be tickled and RST */ -#define KILLTCP_KEYLEN 4 -static uint32_t *killtcp_key(struct sockaddr_in *src, struct sockaddr_in *dst) +#define KILLTCP_KEYLEN 10 +static uint32_t *killtcp_key(ctdb_sock_addr *src, ctdb_sock_addr *dst) { static uint32_t key[KILLTCP_KEYLEN]; - key[0] = dst->sin_addr.s_addr; - key[1] = src->sin_addr.s_addr; - key[2] = dst->sin_port; - key[3] = src->sin_port; + bzero(key, sizeof(key)); + + if (src->sa.sa_family != dst->sa.sa_family) { + DEBUG(DEBUG_ERR, (__location__ " ERROR, different families passed :%u vs %u\n", src->sa.sa_family, dst->sa.sa_family)); + return key; + } + + switch (src->sa.sa_family) { + case AF_INET: + key[0] = dst->ip.sin_addr.s_addr; + key[1] = src->ip.sin_addr.s_addr; + key[2] = dst->ip.sin_port; + key[3] = src->ip.sin_port; + break; + case AF_INET6: + key[0] = dst->ip6.sin6_addr.s6_addr32[3]; + key[1] = src->ip6.sin6_addr.s6_addr32[3]; + key[2] = dst->ip6.sin6_addr.s6_addr32[2]; + key[3] = src->ip6.sin6_addr.s6_addr32[2]; + key[4] = dst->ip6.sin6_addr.s6_addr32[1]; + key[5] = src->ip6.sin6_addr.s6_addr32[1]; + key[6] = dst->ip6.sin6_addr.s6_addr32[0]; + key[7] = src->ip6.sin6_addr.s6_addr32[0]; + key[8] = dst->ip6.sin6_port; + key[9] = src->ip6.sin6_port; + break; + default: + DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", src->sa.sa_family)); + return key; + } return key; } @@ -1311,7 +1337,7 @@ static void capture_tcp_handler(struct event_context *ev, struct fd_event *fde, { struct ctdb_kill_tcp *killtcp = talloc_get_type(private_data, struct ctdb_kill_tcp); struct ctdb_killtcp_con *con; - struct sockaddr_in src, dst; + ctdb_sock_addr src, dst; uint32_t ack_seq, seq; if (!(flags & EVENT_FD_READ)) { @@ -1339,12 +1365,12 @@ static void capture_tcp_handler(struct event_context *ev, struct fd_event *fde, /* This one has been tickled ! now reset him and remove him from the list. */ - 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))); + DEBUG(DEBUG_INFO, ("sending a tcp reset to kill connection :%d -> %s:%d\n", + ntohs(con->dst_addr.ip.sin_port), + ctdb_addr_to_str(&con->src_addr), + ntohs(con->src_addr.ip.sin_port))); - ctdb_sys_send_tcp( - (ctdb_sock_addr *)&con->dst, - (ctdb_sock_addr *)&con->src, - ack_seq, seq, 1); + ctdb_sys_send_tcp(&con->dst_addr, &con->src_addr, ack_seq, seq, 1); talloc_free(con); } @@ -1367,8 +1393,8 @@ static void tickle_connection_traverse(void *param, void *data) /* othervise, try tickling it again */ con->count++; ctdb_sys_send_tcp( - (ctdb_sock_addr *)&con->dst, - (ctdb_sock_addr *)&con->src, + (ctdb_sock_addr *)&con->dst_addr, + (ctdb_sock_addr *)&con->src_addr, 0, 0, 0); } @@ -1427,20 +1453,21 @@ static void *add_killtcp_callback(void *parm, void *data) add a tcp socket to the list of connections we want to RST */ static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, - struct sockaddr_in *src, struct sockaddr_in *dst) + ctdb_sock_addr *src, + ctdb_sock_addr *dst) { struct ctdb_kill_tcp *killtcp; struct ctdb_killtcp_con *con; struct ctdb_vnn *vnn; - vnn = find_public_ip_vnn(ctdb, *dst); + vnn = find_public_ip_vnn(ctdb, dst); if (vnn == NULL) { - vnn = find_public_ip_vnn(ctdb, *src); + vnn = find_public_ip_vnn(ctdb, src); } if (vnn == NULL) { /* if it is not a public ip it could be our 'single ip' */ if (ctdb->single_ip_vnn) { - if (ctdb_same_ipv4(&ctdb->single_ip_vnn->public_address, dst)) { + if (ctdb_same_ip(&ctdb->single_ip_vnn->public_address, dst)) { vnn = ctdb->single_ip_vnn; } } @@ -1475,14 +1502,14 @@ static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, */ con = talloc(killtcp, struct ctdb_killtcp_con); CTDB_NO_MEMORY(ctdb, con); - con->src = *src; - con->dst = *dst; - con->count = 0; - con->killtcp = killtcp; + con->src_addr = *src; + con->dst_addr = *dst; + con->count = 0; + con->killtcp = killtcp; trbt_insertarray32_callback(killtcp->connections, - KILLTCP_KEYLEN, killtcp_key(&con->dst, &con->src), + KILLTCP_KEYLEN, killtcp_key(&con->dst_addr, &con->src_addr), add_killtcp_callback, con); /* @@ -1511,8 +1538,8 @@ static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb, /* tickle him once now */ ctdb_sys_send_tcp( - (ctdb_sock_addr *)&con->dst, - (ctdb_sock_addr *)&con->src, + &con->dst_addr, + &con->src_addr, 0, 0, 0); return 0; @@ -1530,7 +1557,7 @@ int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata) { struct ctdb_control_killtcp *killtcp = (struct ctdb_control_killtcp *)indata.dptr; - return ctdb_killtcp_add_connection(ctdb, &killtcp->src, &killtcp->dst); + return ctdb_killtcp_add_connection(ctdb, &killtcp->src_addr, &killtcp->dst_addr); } /* @@ -1563,10 +1590,11 @@ int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA ind return -1; } - vnn = find_public_ip_vnn(ctdb, list->ip); + vnn = find_public_ip_vnn(ctdb, &list->addr); if (vnn == NULL) { DEBUG(DEBUG_INFO,(__location__ " Could not set tcp tickle list, '%s' is not a public address\n", - inet_ntoa(list->ip.sin_addr))); + ctdb_addr_to_str(&list->addr))); + return 1; } @@ -1597,16 +1625,17 @@ int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA ind */ int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata) { - struct sockaddr_in *ip = (struct sockaddr_in *)indata.dptr; + ctdb_sock_addr *addr = (ctdb_sock_addr *)indata.dptr; struct ctdb_control_tcp_tickle_list *list; struct ctdb_tcp_array *tcparray; int num; struct ctdb_vnn *vnn; - vnn = find_public_ip_vnn(ctdb, *ip); + vnn = find_public_ip_vnn(ctdb, addr); if (vnn == NULL) { DEBUG(DEBUG_ERR,(__location__ " Could not get tcp tickle list, '%s' is not a public address\n", - inet_ntoa(ip->sin_addr))); + ctdb_addr_to_str(addr))); + return 1; } @@ -1625,7 +1654,7 @@ int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA ind CTDB_NO_MEMORY(ctdb, outdata->dptr); list = (struct ctdb_control_tcp_tickle_list *)outdata->dptr; - list->ip = *ip; + list->addr = *addr; list->tickles.num = num; if (num) { memcpy(&list->tickles.connections[0], tcparray->connections, @@ -1641,7 +1670,7 @@ int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA ind */ static int ctdb_ctrl_set_tcp_tickles(struct ctdb_context *ctdb, struct timeval timeout, uint32_t destnode, - struct sockaddr_in *ip, + ctdb_sock_addr *addr, struct ctdb_tcp_array *tcparray) { int ret, num; @@ -1661,7 +1690,7 @@ static int ctdb_ctrl_set_tcp_tickles(struct ctdb_context *ctdb, CTDB_NO_MEMORY(ctdb, data.dptr); list = (struct ctdb_control_tcp_tickle_list *)data.dptr; - list->ip = *ip; + list->addr = *addr; list->tickles.num = num; if (tcparray) { memcpy(&list->tickles.connections[0], tcparray->connections, sizeof(struct ctdb_tcp_connection) * num); @@ -1709,8 +1738,8 @@ static void ctdb_update_tcp_tickles(struct event_context *ev, &vnn->public_address, vnn->tcp_array); if (ret != 0) { - DEBUG(DEBUG_ERR,("Failed to send the tickle update for public address %s\n", - inet_ntoa(vnn->public_address.sin_addr))); + DEBUG(DEBUG_ERR,("Failed to send the tickle update for public address %s\n", + ctdb_addr_to_str(&vnn->public_address))); } } @@ -1833,7 +1862,7 @@ int32_t ctdb_control_add_public_address(struct ctdb_context *ctdb, TDB_DATA inda return -1; } - return ctdb_add_public_address(ctdb, pub->sin, pub->mask, &pub->iface[0]); + return ctdb_add_public_address(ctdb, &pub->addr, pub->mask, &pub->iface[0]); } /* @@ -1869,7 +1898,7 @@ int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA inda /* walk over all public addresses until we find a match */ for (vnn=ctdb->vnn;vnn;vnn=vnn->next) { - if (ctdb_same_ipv4(&vnn->public_address, &pub->sin)) { + if (ctdb_same_ip(&vnn->public_address, &pub->addr)) { TALLOC_CTX *mem_ctx = talloc_new(ctdb); DLIST_REMOVE(ctdb->vnn, vnn); @@ -1879,7 +1908,7 @@ int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA inda mem_ctx, delete_ip_callback, mem_ctx, "releaseip %s %s %u", vnn->iface, - inet_ntoa(vnn->public_address.sin_addr), + talloc_strdup(mem_ctx, ctdb_addr_to_str(&vnn->public_address)), vnn->public_netmask_bits); talloc_free(vnn); if (ret != 0) { diff --git a/ctdb/server/ctdbd.c b/ctdb/server/ctdbd.c index b7979049c19..4dc0f74b209 100644 --- a/ctdb/server/ctdbd.c +++ b/ctdb/server/ctdbd.c @@ -271,13 +271,11 @@ int main(int argc, const char *argv[]) svnn->iface = talloc_strdup(svnn, options.public_interface); CTDB_NO_MEMORY(ctdb, svnn->iface); - if (inet_aton(options.single_public_ip, - &svnn->public_address.sin_addr) == 0) { + if (parse_ip(options.single_public_ip, + &svnn->public_address) == 0) { DEBUG(DEBUG_ALERT,("Invalid --single-public-ip argument : %s . This is not a valid ip address. Exiting.\n", options.single_public_ip)); exit(10); } - svnn->public_address.sin_family = AF_INET; - svnn->public_address.sin_port = 0; } if (options.public_address_list) { diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 906a665d044..0e892affe91 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -104,16 +104,11 @@ static void ctdb_node_connect_write(struct event_context *ev, struct fd_event *f static int ctdb_tcp_get_address(struct ctdb_context *ctdb, - const char *address, struct in_addr *addr) + const char *address, ctdb_sock_addr *addr) { - if (inet_pton(AF_INET, address, addr) <= 0) { - struct hostent *he = gethostbyname(address); - if (he == NULL || he->h_length > sizeof(*addr)) { - ctdb_set_error(ctdb, "invalid nework address '%s'\n", - address); - return -1; - } - memcpy(addr, he->h_addr, he->h_length); + if (parse_ip(address, addr) == 0) { + DEBUG(DEBUG_CRIT, (__location__ " Unparsable address : %s.\n", address)); + return -1; } return 0; } @@ -129,26 +124,34 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, struct ctdb_tcp_node); struct ctdb_context *ctdb = node->ctdb; - struct sockaddr_in sock_in; - struct sockaddr_in sock_out; + ctdb_sock_addr sock_in; + ctdb_sock_addr sock_out; ctdb_tcp_stop_connection(node); - tnode->fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - - set_nonblocking(tnode->fd); - set_close_on_exec(tnode->fd); - ZERO_STRUCT(sock_out); #ifdef HAVE_SOCK_SIN_LEN - sock_out.sin_len = sizeof(sock_out); + sock_out.ip.sin_len = sizeof(sock_out); #endif - if (ctdb_tcp_get_address(ctdb, node->address.address, &sock_out.sin_addr) != 0) { + if (ctdb_tcp_get_address(ctdb, node->address.address, &sock_out) != 0) { + return; + } + switch (sock_out.sa.sa_family) { + case AF_INET: + sock_out.ip.sin_port = htons(node->address.port); + break; + case AF_INET6: + sock_out.ip6.sin6_port = htons(node->address.port); + break; + default: + DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", + sock_out.sa.sa_family)); return; } - sock_out.sin_port = htons(node->address.port); - sock_out.sin_family = PF_INET; + tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + set_nonblocking(tnode->fd); + set_close_on_exec(tnode->fd); /* Bind our side of the socketpair to the same address we use to listen * on incoming CTDB traffic. @@ -158,13 +161,11 @@ void ctdb_tcp_node_connect(struct event_context *ev, struct timed_event *te, */ ZERO_STRUCT(sock_in); #ifdef HAVE_SOCK_SIN_LEN - sock_in.sin_len = sizeof(sock_in); + sock_in.ip.sin_len = sizeof(sock_in); #endif - if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock_in.sin_addr) != 0) { + if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock_in) != 0) { return; } - sock_in.sin_port = htons(0); /* INPORT_ANY is not always available */ - sock_in.sin_family = PF_INET; bind(tnode->fd, (struct sockaddr *)&sock_in, sizeof(sock_in)); if (connect(tnode->fd, (struct sockaddr *)&sock_out, sizeof(sock_out)) != 0 && @@ -198,7 +199,7 @@ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde, { struct ctdb_context *ctdb = talloc_get_type(private_data, struct ctdb_context); struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); - struct sockaddr_in addr; + ctdb_sock_addr addr; socklen_t len; int fd, nodeid; struct ctdb_incoming *in; @@ -210,7 +211,7 @@ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde, fd = accept(ctcp->listen_fd, (struct sockaddr *)&addr, &len); if (fd == -1) return; - incoming_node = inet_ntoa(addr.sin_addr); + incoming_node = ctdb_addr_to_str(&addr); nodeid = ctdb_ip_to_nodeid(ctdb, incoming_node); if (nodeid == -1) { @@ -240,10 +241,11 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); - struct sockaddr_in sock; + ctdb_sock_addr sock; int lock_fd, i; const char *lock_path = "/tmp/.ctdb_socket_lock"; struct flock lock; + int one = 1; /* in order to ensure that we don't get two nodes with the same adddress, we must make the bind() and listen() calls @@ -279,16 +281,37 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) ZERO_STRUCT(sock); #ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); + sock.ip.sin_len = sizeof(sock); #endif - sock.sin_port = htons(ctdb->nodes[i]->address.port); - sock.sin_family = PF_INET; if (ctdb_tcp_get_address(ctdb, ctdb->nodes[i]->address.address, - &sock.sin_addr) != 0) { + &sock) != 0) { continue; } + switch (sock.sa.sa_family) { + case AF_INET: + sock.ip.sin_port = htons(ctdb->nodes[i]->address.port); + break; + case AF_INET6: + sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port); + break; + default: + DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", + sock.sa.sa_family)); + continue; + } + + ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + if (ctcp->listen_fd == -1) { + ctdb_set_error(ctdb, "socket failed\n"); + continue; + } + + set_close_on_exec(ctcp->listen_fd); + + setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); + if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) == 0) { break; @@ -341,19 +364,9 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); - struct sockaddr_in sock; + ctdb_sock_addr sock; int one = 1; - ctcp->listen_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ctcp->listen_fd == -1) { - ctdb_set_error(ctdb, "socket failed\n"); - return -1; - } - - set_close_on_exec(ctcp->listen_fd); - - setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); - /* we can either auto-bind to the first available address, or we can use a specified address */ if (!ctdb->address.address) { @@ -362,16 +375,36 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb) ZERO_STRUCT(sock); #ifdef HAVE_SOCK_SIN_LEN - sock.sin_len = sizeof(sock); + sock.ip.sin_len = sizeof(sock); #endif - sock.sin_port = htons(ctdb->address.port); - sock.sin_family = PF_INET; - if (ctdb_tcp_get_address(ctdb, ctdb->address.address, - &sock.sin_addr) != 0) { + &sock) != 0) { goto failed; } + switch (sock.sa.sa_family) { + case AF_INET: + sock.ip.sin_port = htons(ctdb->address.port); + break; + case AF_INET6: + sock.ip6.sin6_port = htons(ctdb->address.port); + break; + default: + DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", + sock.sa.sa_family)); + goto failed; + } + + ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + if (ctcp->listen_fd == -1) { + ctdb_set_error(ctdb, "socket failed\n"); + return -1; + } + + set_close_on_exec(ctcp->listen_fd); + + setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)); + if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sizeof(sock)) != 0) { goto failed; } @@ -386,7 +419,9 @@ int ctdb_tcp_listen(struct ctdb_context *ctdb) return 0; failed: - close(ctcp->listen_fd); + if (ctcp->listen_fd != -1) { + close(ctcp->listen_fd); + } ctcp->listen_fd = -1; return -1; } diff --git a/ctdb/tests/nodes.txt b/ctdb/tests/nodes.txt index 99b07328b38..2563adcc702 100644 --- a/ctdb/tests/nodes.txt +++ b/ctdb/tests/nodes.txt @@ -1,4 +1,4 @@ -127.0.0.1 -127.0.0.2 -127.0.0.3 -127.0.0.4 +::1 +::2 +::3 +::4 diff --git a/ctdb/tests/nodes6.txt b/ctdb/tests/nodes6.txt new file mode 100644 index 00000000000..7e1d085fdf0 --- /dev/null +++ b/ctdb/tests/nodes6.txt @@ -0,0 +1,11 @@ +::1 +::2 +::3 +::4 + +::2 +::3 +::4 +::2 +::3 +::4 diff --git a/ctdb/tests/start_daemons.sh b/ctdb/tests/start_daemons.sh index afcf23e0095..cf6b738f4a1 100755 --- a/ctdb/tests/start_daemons.sh +++ b/ctdb/tests/start_daemons.sh @@ -4,12 +4,17 @@ NUMNODES=2 if [ $# -gt 0 ]; then NUMNODES=$1 fi -NODES="./tests/nodes.txt" shift +NODES="./tests/nodes.txt" rm -f $NODES for i in `seq 1 $NUMNODES`; do - echo 127.0.0.$i >> $NODES + if [ "${CTDB_USE_IPV6}x" != "x" ]; then + echo ::$i >> $NODES + ip addr add ::$i/128 dev lo + else + echo 127.0.0.$i >> $NODES + fi done killall -q ctdbd diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c index eed92d3773d..90af2a8e1bd 100644 --- a/ctdb/tools/ctdb.c +++ b/ctdb/tools/ctdb.c @@ -332,7 +332,7 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:\n"); for(i=0;inum;i++){ printf(":%d:%s:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn, - inet_ntoa(nodemap->nodes[i].sin.sin_addr), + ctdb_addr_to_str(&nodemap->nodes[i].addr), !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED), !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED), !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED), @@ -370,7 +370,7 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv CTDB_NO_MEMORY_FATAL(ctdb, flags_str); } printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn, - inet_ntoa(nodemap->nodes[i].sin.sin_addr), + ctdb_addr_to_str(&nodemap->nodes[i].addr), flags_str, nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":""); talloc_free(flags_str); @@ -414,30 +414,29 @@ static int control_status(struct ctdb_context *ctdb, int argc, const char **argv static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv) { struct ctdb_control_tcp_tickle_list *list; - struct sockaddr_in ip; + ctdb_sock_addr addr; int i, ret; if (argc < 1) { usage(); } - ip.sin_family = AF_INET; - if (inet_aton(argv[0], &ip.sin_addr) == 0) { + if (parse_ip(argv[0], &addr) == 0) { DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0])); return -1; } - ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &ip, &list); + ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list); if (ret == -1) { DEBUG(DEBUG_ERR, ("Unable to list tickles\n")); return -1; } - printf("Tickles for ip:%s\n", inet_ntoa(list->ip.sin_addr)); + printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr)); printf("Num tickles:%u\n", list->tickles.num); for (i=0;itickles.num;i++) { - printf("SRC: %s:%u ", inet_ntoa(list->tickles.connections[i].saddr.sin_addr), ntohs(list->tickles.connections[i].saddr.sin_port)); - printf("DST: %s:%u\n", inet_ntoa(list->tickles.connections[i].daddr.sin_addr), ntohs(list->tickles.connections[i].daddr.sin_port)); + printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port)); + printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)); } talloc_free(list); @@ -447,7 +446,7 @@ static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char * /* send a release ip to all nodes */ static int control_send_release(struct ctdb_context *ctdb, uint32_t pnn, -struct sockaddr_in *sin) +ctdb_sock_addr *addr) { int ret; struct ctdb_public_ip pip; @@ -461,11 +460,10 @@ struct sockaddr_in *sin) } /* send a moveip message to the recovery master */ - pip.pnn = pnn; - pip.sin.sin_family = AF_INET; - pip.sin.sin_addr = sin->sin_addr; + pip.pnn = pnn; + pip.addr = *addr; data.dsize = sizeof(pip); - data.dptr = (unsigned char *)&pip; + data.dptr = (unsigned char *)&pip; /* send release ip to all nodes */ @@ -486,7 +484,7 @@ struct sockaddr_in *sin) static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv) { uint32_t pnn; - struct sockaddr_in ip; + ctdb_sock_addr addr; uint32_t value; struct ctdb_all_public_ips *ips; int i, ret; @@ -495,8 +493,7 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv usage(); } - ip.sin_family = AF_INET; - if (inet_aton(argv[0], &ip.sin_addr) == 0) { + if (parse_ip(argv[0], &addr) == 0) { DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0])); return -1; } @@ -535,22 +532,22 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv } for (i=0;inum;i++) { - if (ctdb_same_ipv4(&ip, &ips->ips[i].sin)) { + if (ctdb_same_ip(&addr, &ips->ips[i].addr)) { break; } } if (i==ips->num) { DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n", - pnn, inet_ntoa(ip.sin_addr))); + pnn, ctdb_addr_to_str(&addr))); return -1; } if (ips->ips[i].pnn == pnn) { DEBUG(DEBUG_ERR, ("Host %u is already hosting '%s'\n", - pnn, inet_ntoa(ips->ips[i].sin.sin_addr))); + pnn, ctdb_addr_to_str(&ips->ips[i].addr))); return -1; } - ret = control_send_release(ctdb, pnn, &ips->ips[i].sin); + ret = control_send_release(ctdb, pnn, &ips->ips[i].addr); if (ret != 0) { DEBUG(DEBUG_ERR, ("Failed to send 'change ip' to all nodes\n"));; return -1; @@ -559,20 +556,15 @@ static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv return 0; } -struct node_ip { - uint32_t pnn; - struct sockaddr_in sin; -}; - void getips_store_callback(void *param, void *data) { - struct node_ip *node_ip = (struct node_ip *)data; + struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data; struct ctdb_all_public_ips *ips = param; int i; i = ips->num++; - ips->ips[i].pnn = node_ip->pnn; - ips->ips[i].sin = node_ip->sin; + ips->ips[i].pnn = node_ip->pnn; + ips->ips[i].addr = node_ip->addr; } void getips_count_callback(void *param, void *data) @@ -612,13 +604,13 @@ control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struc } for (j=0; jnum;j++) { - struct node_ip *node_ip; + struct ctdb_public_ip *node_ip; - node_ip = talloc(tmp_ctx, struct node_ip); - node_ip->pnn = tmp_ips->ips[j].pnn; - node_ip->sin = tmp_ips->ips[j].sin; + node_ip = talloc(tmp_ctx, struct ctdb_public_ip); + node_ip->pnn = tmp_ips->ips[j].pnn; + node_ip->addr = tmp_ips->ips[j].addr; - trbt_insert32(tree, tmp_ips->ips[j].sin.sin_addr.s_addr, node_ip); + trbt_insert32(tree, tmp_ips->ips[j].addr.ip.sin_addr.s_addr, node_ip); } talloc_free(tmp_ips); } @@ -643,7 +635,7 @@ control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struc * ip address or -1 */ static int -find_other_host_for_public_ip(struct ctdb_context *ctdb, struct sockaddr_in *addr) +find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr) { TALLOC_CTX *tmp_ctx = talloc_new(ctdb); struct ctdb_all_public_ips *ips; @@ -673,7 +665,7 @@ find_other_host_for_public_ip(struct ctdb_context *ctdb, struct sockaddr_in *add } for (j=0;jnum;j++) { - if (ctdb_same_ipv4(addr, &ips->ips[j].sin)) { + if (ctdb_same_ip(addr, &ips->ips[j].addr)) { talloc_free(tmp_ctx); return nodemap->nodes[i].pnn; } @@ -693,7 +685,7 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv) int i, ret; int len; unsigned mask; - struct sockaddr_in addr; + ctdb_sock_addr addr; struct ctdb_control_ip_iface *pub; TALLOC_CTX *tmp_ctx = talloc_new(ctdb); struct ctdb_all_public_ips *ips; @@ -721,7 +713,7 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv) pub = talloc_size(tmp_ctx, len); CTDB_NO_MEMORY(ctdb, pub); - pub->sin = addr; + pub->addr = addr; pub->mask = mask; pub->len = strlen(argv[1])+1; memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1); @@ -738,7 +730,7 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv) * we will claim it */ for (i=0;inum;i++) { - if (ctdb_same_ipv4(&addr, &ips->ips[i].sin)) { + if (ctdb_same_ip(&addr, &ips->ips[i].addr)) { break; } } @@ -764,7 +756,7 @@ static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv) static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv) { int i, ret; - struct sockaddr_in addr; + ctdb_sock_addr addr; struct ctdb_control_ip_iface pub; TALLOC_CTX *tmp_ctx = talloc_new(ctdb); struct ctdb_all_public_ips *ips; @@ -774,13 +766,12 @@ static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv) usage(); } - addr.sin_family = AF_INET; - if (inet_aton(argv[0], &addr.sin_addr) == 0) { + if (parse_ip(argv[0], &addr) == 0) { DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0])); return -1; } - pub.sin = addr; + pub.addr = addr; pub.mask = 0; pub.len = 0; @@ -792,14 +783,14 @@ static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv) } for (i=0;inum;i++) { - if (ctdb_same_ipv4(&addr, &ips->ips[i].sin)) { + if (ctdb_same_ip(&addr, &ips->ips[i].addr)) { break; } } if (i==ips->num) { DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n", - inet_ntoa(addr.sin_addr))); + ctdb_addr_to_str(&addr))); talloc_free(tmp_ctx); return -1; } @@ -837,12 +828,12 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv) usage(); } - if (!parse_ip_port(argv[0], (ctdb_sock_addr *)&killtcp.src)) { + if (!parse_ip_port(argv[0], &killtcp.src_addr)) { DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0])); return -1; } - if (!parse_ip_port(argv[1], (ctdb_sock_addr *)&killtcp.dst)) { + if (!parse_ip_port(argv[1], &killtcp.dst_addr)) { DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1])); return -1; } @@ -1052,9 +1043,9 @@ static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv) for (i=1;i<=ips->num;i++) { if (options.machinereadable){ - printf(":%s:%d:\n", inet_ntoa(ips->ips[ips->num-i].sin.sin_addr), ips->ips[ips->num-i].pnn); + printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn); } else { - printf("%s %d\n", inet_ntoa(ips->ips[ips->num-i].sin.sin_addr), ips->ips[ips->num-i].pnn); + printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn); } } @@ -1316,7 +1307,8 @@ static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv) } } - printf("%d:%s\n", i, inet_ntoa(nodemap->nodes[i].sin.sin_addr)); + printf("%d:%s\n", i, + ctdb_addr_to_str(&nodemap->nodes[i].addr)); } return 0; @@ -2194,7 +2186,7 @@ static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **a } for(i=0;inum;i++){ - printf("%s\n", inet_ntoa(nodemap->nodes[i].sin.sin_addr)); + printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr)); } return 0; diff --git a/ctdb/utils/ipmux/ipmux.c b/ctdb/utils/ipmux/ipmux.c index 539490e674d..598e9dcb6f2 100644 --- a/ctdb/utils/ipmux/ipmux.c +++ b/ctdb/utils/ipmux/ipmux.c @@ -34,7 +34,7 @@ struct ipmux_node { uint32_t pnn; - struct sockaddr_in sin; + ctdb_sock_addr addr; }; struct ipmux_node *ipmux_nodes; @@ -188,8 +188,8 @@ int main(int argc, const char *argv[]) if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) { continue; } - ipmux_nodes[num_nodes].pnn = i; - ipmux_nodes[num_nodes].sin = nodemap->nodes[i].sin; + ipmux_nodes[num_nodes].pnn = i; + ipmux_nodes[num_nodes].addr = nodemap->nodes[i].addr; num_nodes++; } @@ -251,7 +251,7 @@ int main(int argc, const char *argv[]) send the packet off and tell the kernel to not worry about this packet any more */ - ret = sendto(s, &ipqp->payload[0], ipqp->data_len, 0, &ipmux_nodes[hash].sin, sizeof(struct sockaddr_in)); + ret = sendto(s, &ipqp->payload[0], ipqp->data_len, 0, (struct sockaddr_in *)&ipmux_nodes[hash].addr, sizeof(ctdb_sock_addr)); ipq_set_verdict(ipqh, ipqp->packet_id, NF_DROP, 0, pktbuf); }