1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

initial ipv6 patch

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>

(This used to be ctdb commit 1f131f21386f428bbbbb29098d56c2f64596583b)
This commit is contained in:
Ronnie Sahlberg 2008-08-19 14:58:29 +10:00
parent ed6ca6a84d
commit ef997d344f
17 changed files with 577 additions and 458 deletions

View File

@ -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,

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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; i<num_nodes; i++) {
inet_aton(ctdb->nodes[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;
}

View File

@ -2207,8 +2207,9 @@ static int verify_ip_allocation(struct ctdb_context *ctdb, uint32_t pnn)
*/
for (j=0; j<ips->num; 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"));

View File

@ -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;i<tcparray->num;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;i<nlines;i++) {
unsigned mask;
struct sockaddr_in addr;
ctdb_sock_addr addr;
const char *iface;
char *tok;
@ -474,7 +472,7 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist)
iface = tok;
}
if (ctdb_add_public_address(ctdb, addr, mask, iface)) {
if (ctdb_add_public_address(ctdb, &addr, mask, iface)) {
DEBUG(DEBUG_CRIT,("Failed to add line %u to the public address list\n", i+1));
talloc_free(lines);
return -1;
@ -491,7 +489,7 @@ int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist)
struct ctdb_public_ip_list {
struct ctdb_public_ip_list *next;
uint32_t pnn;
struct sockaddr_in sin;
ctdb_sock_addr addr;
};
@ -529,7 +527,7 @@ static int can_node_serve_ip(struct ctdb_context *ctdb, int32_t pnn,
}
for (i=0;i<public_ips->num;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;i<array->num;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) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
127.0.0.1
127.0.0.2
127.0.0.3
127.0.0.4
::1
::2
::3
::4

11
ctdb/tests/nodes6.txt Normal file
View File

@ -0,0 +1,11 @@
::1
::2
::3
::4
::2
::3
::4
::2
::3
::4

View File

@ -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

View File

@ -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;i<nodemap->num;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;i<list->tickles.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;i<ips->num;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; j<tmp_ips->num;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;j<ips->num;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;i<ips->num;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;i<ips->num;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;i<nodemap->num;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;

View File

@ -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);
}