parse a IP:port pair
*/
int ctdb_parse_address(TALLOC_CTX *mem_ctx, const char *str,
- struct ctdb_address *address)
+ ctdb_sock_addr *address)
{
struct servent *se;
- ctdb_sock_addr addr;
+ int port;
setservent(0);
se = getservbyname("ctdb", "tcp");
endservent();
- /* Parse IP address and re-convert to string. This ensure correct
- * string form for IPv6 addresses.
- */
- if (! parse_ip(str, NULL, 0, &addr)) {
- return -1;
+ if (se == NULL) {
+ port = CTDB_PORT;
+ } else {
+ port = ntohs(se->s_port);
}
- address->address = talloc_strdup(mem_ctx, ctdb_addr_to_str(&addr));
- if (address->address == NULL) {
- DEBUG(DEBUG_ERR, (__location__ " Out of memory\n"));
+ if (! parse_ip(str, NULL, port, address)) {
return -1;
}
- if (se == NULL) {
- address->port = CTDB_PORT;
- } else {
- address->port = ntohs(se->s_port);
- }
return 0;
}
/*
check if two addresses are the same
*/
-bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2)
+bool ctdb_same_address(ctdb_sock_addr *a1, ctdb_sock_addr *a2)
{
- return strcmp(a1->address, a2->address) == 0 && a1->port == a2->port;
+ return ctdb_same_ip(a1, a2) &&
+ ctdb_addr_to_port(a1) == ctdb_addr_to_port(a2);
}
return false;
}
+#ifdef HAVE_SOCK_SIN_LEN
+ sin->ip.sin_len = sizeof(*sin);
+#endif
return true;
}
saddr->ip6.sin6_scope_id = if_nametoindex(ifaces);
}
+#ifdef HAVE_SOCK_SIN_LEN
+ saddr->ip6.sin6_len = sizeof(*saddr);
+#endif
return true;
}
Check that a specific ip address exists in the node list and returns
the id for the node or -1
*/
-int ctdb_ip_to_nodeid(struct ctdb_context *ctdb, const char *nodeip);
+int ctdb_ip_to_nodeid(struct ctdb_context *ctdb, const ctdb_sock_addr *nodeip);
/*
start the ctdb protocol
ctdb_fn_t fn;
};
-/*
- this address structure might need to be generalised later for some
- transports
-*/
-struct ctdb_address {
- const char *address;
- int port;
-};
-
/*
check that a pnn is valid
*/
*/
struct ctdb_node {
struct ctdb_context *ctdb;
- struct ctdb_address address;
+ ctdb_sock_addr address;
const char *name; /* for debug messages */
void *private_data; /* private to transport */
uint32_t pnn;
struct ctdb_freeze_handle *freeze_handles[NUM_DB_PRIORITIES+1];
bool freeze_transaction_started;
uint32_t freeze_transaction_id;
- struct ctdb_address address;
+ ctdb_sock_addr *address;
const char *name;
const char *db_directory;
const char *db_directory_persistent;
bool ctdb_set_helper(const char *type, char *helper, size_t size,
const char *envvar, const char *dir, const char *file);
void ctdb_external_trace(void);
-bool ctdb_same_address(struct ctdb_address *a1, struct ctdb_address *a2);
+bool ctdb_same_address(ctdb_sock_addr *a1, ctdb_sock_addr *a2);
int ctdb_parse_address(TALLOC_CTX *mem_ctx, const char *str,
- struct ctdb_address *address);
+ ctdb_sock_addr *address);
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);
{
int nodeid;
- if (ctdb->address.address == NULL) {
+ if (ctdb->address == NULL) {
ctdb_fatal(ctdb,
"Can not determine PNN - node address is not set\n");
}
- nodeid = ctdb_ip_to_nodeid(ctdb, ctdb->address.address);
+ nodeid = ctdb_ip_to_nodeid(ctdb, ctdb->address);
if (nodeid == -1) {
ctdb_fatal(ctdb,
"Can not determine PNN - node address not found in node list\n");
node_map = (struct ctdb_node_map *)outdata->dptr;
node_map->num = num_nodes;
for (i=0; i<num_nodes; i++) {
- if (parse_ip(ctdb->nodes[i]->address.address,
- NULL, /* TODO: pass in the correct interface here*/
- 0,
- &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].addr = ctdb->nodes[i]->address;
node_map->nodes[i].pnn = ctdb->nodes[i]->pnn;
node_map->nodes[i].flags = ctdb->nodes[i]->flags;
}
node_map = (struct ctdb_node_mapv4 *)outdata->dptr;
node_map->num = num_nodes;
for (i=0; i<num_nodes; i++) {
- if (parse_ipv4(ctdb->nodes[i]->address.address, 0, &node_map->nodes[i].sin) == 0) {
- DEBUG(DEBUG_ERR, (__location__ " Failed to parse %s into a sockaddr\n", ctdb->nodes[i]->address.address));
- return -1;
- }
-
+ node_map->nodes[i].sin = ctdb->nodes[i]->address.ip;
node_map->nodes[i].pnn = ctdb->nodes[i]->pnn;
node_map->nodes[i].flags = ctdb->nodes[i]->flags;
}
Check whether an ip is a valid node ip
Returns the node id for this ip address or -1
*/
-int ctdb_ip_to_nodeid(struct ctdb_context *ctdb, const char *nodeip)
+int ctdb_ip_to_nodeid(struct ctdb_context *ctdb, const ctdb_sock_addr *nodeip)
{
int nodeid;
if (ctdb->nodes[nodeid]->flags & NODE_FLAGS_DELETED) {
continue;
}
- if (!strcmp(ctdb->nodes[nodeid]->address.address, nodeip)) {
+ if (ctdb_same_ip(&ctdb->nodes[nodeid]->address, nodeip)) {
return nodeid;
}
}
return -1;
}
node->ctdb = ctdb;
- node->name = talloc_asprintf(node, "%s:%u",
- node->address.address,
- node->address.port);
+ node->name = talloc_asprintf(node, "%s:%u",
+ ctdb_addr_to_str(&node->address),
+ ctdb_addr_to_port(&node->address));
/* this assumes that the nodes are kept in sorted order, and no gaps */
node->pnn = ctdb->num_nodes;
*/
int ctdb_set_address(struct ctdb_context *ctdb, const char *address)
{
- if (ctdb_parse_address(ctdb, address, &ctdb->address) != 0) {
+ ctdb->address = talloc(ctdb, ctdb_sock_addr);
+ CTDB_NO_MEMORY(ctdb, ctdb->address);
+
+ if (ctdb_parse_address(ctdb, address, ctdb->address) != 0) {
return -1;
}
-
- ctdb->name = talloc_asprintf(ctdb, "%s:%u",
- ctdb->address.address,
- ctdb->address.port);
+
+ ctdb->name = talloc_asprintf(ctdb, "%s:%u",
+ ctdb_addr_to_str(ctdb->address),
+ ctdb_addr_to_port(ctdb->address));
return 0;
}
}
-static int ctdb_tcp_get_address(struct ctdb_context *ctdb,
- const char *address, ctdb_sock_addr *addr)
-{
- if (parse_ip(address, NULL, 0, addr) == 0) {
- DEBUG(DEBUG_CRIT, (__location__ " Unparsable address : %s.\n", address));
- return -1;
- }
- return 0;
-}
-
/*
called when we should try and establish a tcp connection to a node
*/
ctdb_tcp_stop_connection(node);
- ZERO_STRUCT(sock_out);
-#ifdef HAVE_SOCK_SIN_LEN
- sock_out.ip.sin_len = sizeof(sock_out);
-#endif
- 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 = node->address;
tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if (tnode->fd == -1) {
* the remote side is actually routable in case CTDB traffic will run on
* a dedicated non-routeable network.
*/
- ZERO_STRUCT(sock_in);
- if (ctdb_tcp_get_address(ctdb, ctdb->address.address, &sock_in) != 0) {
- DEBUG(DEBUG_ERR, (__location__ " Failed to find our address. Failing bind.\n"));
- close(tnode->fd);
- return;
- }
+ sock_in = *ctdb->address;
/* AIX libs check to see if the socket address and length
arguments are consistent with each other on calls like
*/
switch (sock_in.sa.sa_family) {
case AF_INET:
+ sock_in.ip.sin_port = 0 /* Any port */;
sockin_size = sizeof(sock_in.ip);
sockout_size = sizeof(sock_out.ip);
break;
case AF_INET6:
+ sock_in.ip6.sin6_port = 0 /* Any port */;
sockin_size = sizeof(sock_in.ip6);
sockout_size = sizeof(sock_out.ip6);
break;
close(tnode->fd);
return;
}
-#ifdef HAVE_SOCK_SIN_LEN
- sock_in.ip.sin_len = sockin_size;
- sock_out.ip.sin_len = sockout_size;
-#endif
+
if (bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size) == -1) {
DEBUG(DEBUG_ERR, (__location__ "Failed to bind socket %s(%d)\n",
strerror(errno), errno));
int fd, nodeid;
struct ctdb_incoming *in;
int one = 1;
- const char *incoming_node;
memset(&addr, 0, sizeof(addr));
len = sizeof(addr);
fd = accept(ctcp->listen_fd, (struct sockaddr *)&addr, &len);
if (fd == -1) return;
- incoming_node = ctdb_addr_to_str(&addr);
- nodeid = ctdb_ip_to_nodeid(ctdb, incoming_node);
+ nodeid = ctdb_ip_to_nodeid(ctdb, &addr);
if (nodeid == -1) {
- DEBUG(DEBUG_ERR, ("Refused connection from unknown node %s\n", incoming_node));
+ DEBUG(DEBUG_ERR, ("Refused connection from unknown node %s\n", ctdb_addr_to_str(&addr)));
close(fd);
return;
}
strerror(errno)));
}
- in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT,
- ctdb_tcp_read_cb, in, "ctdbd-%s", incoming_node);
+ in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT,
+ ctdb_tcp_read_cb, in, "ctdbd-%s", ctdb_addr_to_str(&addr));
}
if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
continue;
}
- ZERO_STRUCT(sock);
- if (ctdb_tcp_get_address(ctdb,
- ctdb->nodes[i]->address.address,
- &sock) != 0) {
- continue;
- }
-
+ sock = ctdb->nodes[i]->address;
+
switch (sock.sa.sa_family) {
case AF_INET:
- sock.ip.sin_port = htons(ctdb->nodes[i]->address.port);
sock_size = sizeof(sock.ip);
break;
case AF_INET6:
- sock.ip6.sin6_port = htons(ctdb->nodes[i]->address.port);
sock_size = sizeof(sock.ip6);
break;
default:
sock.sa.sa_family));
continue;
}
-#ifdef HAVE_SOCK_SIN_LEN
- sock.ip.sin_len = sock_size;
-#endif
ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if (ctcp->listen_fd == -1) {
DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n"));
goto failed;
}
- ctdb->address.address = talloc_strdup(ctdb, ctdb->nodes[i]->address.address);
- ctdb->address.port = ctdb->nodes[i]->address.port;
+ ctdb->address = talloc_memdup(ctdb,
+ &ctdb->nodes[i]->address,
+ sizeof(ctdb_sock_addr));
+ CTDB_NO_MEMORY(ctdb, ctdb->address);
ctdb->name = talloc_asprintf(ctdb, "%s:%u",
- ctdb->address.address,
- ctdb->address.port);
- DEBUG(DEBUG_INFO,("ctdb chose network address %s:%u\n",
- ctdb->address.address,
- ctdb->address.port));
+ ctdb_addr_to_str(ctdb->address),
+ ctdb_addr_to_port(ctdb->address));
+ DEBUG(DEBUG_INFO,("ctdb chose network address %s\n", ctdb->name));
if (listen(ctcp->listen_fd, 10) == -1) {
goto failed;
close(lock_fd);
return 0;
-
+
failed:
close(lock_fd);
if (ctcp->listen_fd != -1) {
/* we can either auto-bind to the first available address, or we can
use a specified address */
- if (!ctdb->address.address) {
+ if (!ctdb->address) {
return ctdb_tcp_listen_automatic(ctdb);
}
- ZERO_STRUCT(sock);
- if (ctdb_tcp_get_address(ctdb, ctdb->address.address,
- &sock) != 0) {
- goto failed;
- }
-
+ sock = *ctdb->address;
+
switch (sock.sa.sa_family) {
case AF_INET:
- sock.ip.sin_port = htons(ctdb->address.port);
sock_size = sizeof(sock.ip);
break;
case AF_INET6:
- sock.ip6.sin6_port = htons(ctdb->address.port);
sock_size = sizeof(sock.ip6);
break;
default:
sock.sa.sa_family));
goto failed;
}
-#ifdef HAVE_SOCK_SIN_LEN
- sock.ip.sin_len = sock_size;
-#endif
ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if (ctcp->listen_fd == -1) {
/* startup connection to the other server - will happen on
next event loop */
- if (!ctdb_same_address(&ctdb->address, &node->address)) {
+ if (!ctdb_same_address(ctdb->address, &node->address)) {
tnode->connect_te = event_add_timed(ctdb->ev, tnode,
timeval_zero(),
ctdb_tcp_node_connect, node);
ctdb->nodes[ctdb->num_nodes]->ctdb = ctdb;
ctdb->nodes[ctdb->num_nodes]->name = "fakectdb";
ctdb->nodes[ctdb->num_nodes]->pnn = pnn;
- ctdb->nodes[ctdb->num_nodes]->address.address = ip;
- ctdb->nodes[ctdb->num_nodes]->address.port = 0;
+ parse_ip(ip, NULL, 0, &ctdb->nodes[ctdb->num_nodes]->address);
ctdb->nodes[ctdb->num_nodes]->flags = flags;
ctdb->nodes[ctdb->num_nodes]->capabilities = capabilities;
ctdb->num_nodes++;
node_map = (struct ctdb_node_map *)outdata->dptr;
node_map->num = num_nodes;
for (i=0; i<num_nodes; i++) {
- if (parse_ip(ctdb->nodes[i]->address.address,
- NULL, /* TODO: pass in the correct interface here*/
- 0,
- &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].addr = ctdb->nodes[i]->address;
node_map->nodes[i].pnn = ctdb->nodes[i]->pnn;
node_map->nodes[i].flags = ctdb->nodes[i]->flags;
}
assert_nodes_set(ctdb);
for (i = 0; i < ctdb->num_nodes; i++) {
- ctdb_sock_addr node_addr;
-
if (ctdb->pnn == ctdb->nodes[i]->pnn) {
- if (!parse_ip(ctdb->nodes[i]->address.address, NULL, 0,
- &node_addr)) {
- continue;
- }
- if (ctdb_same_ip(addr, &node_addr)) {
+ if (ctdb_same_ip(addr, &ctdb->nodes[i]->address)) {
return true;
}
}