}
}
+static int ctdb_tcp_listen_addr(struct ctdb_context *ctdb,
+ ctdb_sock_addr *addr,
+ bool strict)
+{
+ struct ctdb_tcp *ctcp = talloc_get_type_abort(
+ ctdb->transport_data, struct ctdb_tcp);
+ ctdb_sock_addr sock;
+ int sock_size;
+ int one = 1;
+ struct tevent_fd *fde = NULL;
+ int ret;
+
+ sock = *addr;
+ ctcp->listen_fd = -1;
+
+ switch (sock.sa.sa_family) {
+ case AF_INET:
+ sock_size = sizeof(sock.ip);
+ break;
+ case AF_INET6:
+ sock_size = sizeof(sock.ip6);
+ break;
+ default:
+ DBG_ERR("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) {
+ DBG_ERR("Socket failed - %s (%d)\n", strerror(errno), errno);
+ goto failed;
+ }
+
+ set_close_on_exec(ctcp->listen_fd);
+
+ ret = setsockopt(ctcp->listen_fd,
+ SOL_SOCKET,
+ SO_REUSEADDR,
+ (char *)&one,
+ sizeof(one));
+ if (ret == -1) {
+ DBG_WARNING("Failed to set REUSEADDR on fd - %s (%d)\n",
+ strerror(errno),
+ errno);
+ }
+
+ ret =bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size);
+ if (ret != 0) {
+ if (strict || errno != EADDRNOTAVAIL) {
+ DBG_ERR("Failed to bind() to socket - %s (%d)\n",
+ strerror(errno),
+ errno);
+ } else {
+ DBG_DEBUG("Failed to bind() to socket - %s (%d)\n",
+ strerror(errno),
+ errno);
+ }
+ goto failed;
+ }
+
+ ret = listen(ctcp->listen_fd, 10);
+ if (ret == -1) {
+ DBG_ERR("Failed to listen() on socket - %s (%d)\n",
+ strerror(errno),
+ errno);
+ goto failed;
+ }
+
+ fde = tevent_add_fd(ctdb->ev,
+ ctcp,
+ ctcp->listen_fd,
+ TEVENT_FD_READ,
+ ctdb_listen_event,
+ ctdb);
+ tevent_fd_set_auto_close(fde);
+
+ return 0;
+
+failed:
+ if (ctcp->listen_fd != -1) {
+ close(ctcp->listen_fd);
+ ctcp->listen_fd = -1;
+ }
+ return -1;
+}
/*
automatically find which address to listen on
*/
static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb)
{
- struct ctdb_tcp *ctcp = talloc_get_type(ctdb->transport_data,
- struct ctdb_tcp);
- ctdb_sock_addr sock;
int lock_fd;
unsigned int i;
const char *lock_path = CTDB_RUNDIR "/.socket_lock";
struct flock lock;
- int one = 1;
- int sock_size;
- struct tevent_fd *fde;
+ int ret;
- /* If there are no nodes, then it won't be possible to find
+ /*
+ * If there are no nodes, then it won't be possible to find
* the first one. Log a failure and short circuit the whole
* process.
*/
return -1;
}
- /* in order to ensure that we don't get two nodes with the
- same address, we must make the bind() and listen() calls
- atomic. The SO_REUSEADDR setsockopt only prevents double
- binds if the first socket is in LISTEN state */
+ /*
+ * In order to ensure that we don't get two nodes with the
+ * same address, we must make the bind() and listen() calls
+ * atomic. The SO_REUSEADDR setsockopt only prevents double
+ * binds if the first socket is in LISTEN state.
+ */
lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666);
if (lock_fd == -1) {
- DEBUG(DEBUG_CRIT,("Unable to open %s\n", lock_path));
+ DBG_ERR("Unable to open %s\n", lock_path);
return -1;
}
lock.l_pid = 0;
if (fcntl(lock_fd, F_SETLKW, &lock) != 0) {
- DEBUG(DEBUG_CRIT,("Unable to lock %s\n", lock_path));
+ DBG_ERR("Unable to lock %s\n", lock_path);
close(lock_fd);
return -1;
}
if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) {
continue;
}
- sock = ctdb->nodes[i]->address;
-
- switch (sock.sa.sa_family) {
- case AF_INET:
- sock_size = sizeof(sock.ip);
- break;
- case AF_INET6:
- sock_size = sizeof(sock.ip6);
- 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);
-
- if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,
- (char *)&one,sizeof(one)) == -1) {
- DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n",
- strerror(errno)));
- }
- if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) {
+ ret = ctdb_tcp_listen_addr(ctdb,
+ &ctdb->nodes[i]->address,
+ false);
+ if (ret == 0) {
break;
}
-
- if (errno == EADDRNOTAVAIL) {
- DEBUG(DEBUG_DEBUG,(__location__ " Failed to bind() to socket. %s(%d)\n",
- strerror(errno), errno));
- } else {
- DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n",
- strerror(errno), errno));
- }
-
- close(ctcp->listen_fd);
- ctcp->listen_fd = -1;
}
if (i == ctdb->num_nodes) {
- DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n"));
- goto failed;
+ D_ERR("Unable to bind to any node address - giving up\n");
+ return -1;
}
+
ctdb->address = talloc_memdup(ctdb,
&ctdb->nodes[i]->address,
sizeof(ctdb_sock_addr));
if (ctdb->address == NULL) {
- ctdb_set_error(ctdb, "Out of memory at %s:%d",
- __FILE__, __LINE__);
- goto failed;
+ DBG_ERR("Memory allocation error\n");
+ return -1;
}
ctdb->name = talloc_strdup(ctdb, ctdb->nodes[i]->name);
if (ctdb->name == NULL) {
- ctdb_set_error(ctdb, "Out of memory at %s:%d",
- __FILE__, __LINE__);
- goto failed;
- }
- DEBUG(DEBUG_INFO,("ctdb chose network address %s\n", ctdb->name));
-
- if (listen(ctcp->listen_fd, 10) == -1) {
- goto failed;
+ DBG_ERR("Memory allocation error\n");
+ return -1;
}
- fde = tevent_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, TEVENT_FD_READ,
- ctdb_listen_event, ctdb);
- tevent_fd_set_auto_close(fde);
-
- close(lock_fd);
-
+ D_INFO("ctdb chose network address %s\n", ctdb->name);
return 0;
-
-failed:
- close(lock_fd);
- if (ctcp->listen_fd != -1) {
- close(ctcp->listen_fd);
- ctcp->listen_fd = -1;
- }
- return -1;
}
*/
int ctdb_tcp_listen(struct ctdb_context *ctdb)
{
- struct ctdb_tcp *ctcp = talloc_get_type(ctdb->transport_data,
- struct ctdb_tcp);
- ctdb_sock_addr sock;
- int sock_size;
- int one = 1;
- struct tevent_fd *fde;
+ int ret;
/* we can either auto-bind to the first available address, or we can
use a specified address */
if (!ctdb->address) {
- return ctdb_tcp_listen_automatic(ctdb);
- }
-
- sock = *ctdb->address;
-
- switch (sock.sa.sa_family) {
- case AF_INET:
- sock_size = sizeof(sock.ip);
- break;
- case AF_INET6:
- sock_size = sizeof(sock.ip6);
- 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);
-
- if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)) == -1) {
- DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n",
- strerror(errno)));
+ ret = ctdb_tcp_listen_automatic(ctdb);
+ return ret;
}
- if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) != 0) {
- DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno));
- goto failed;
- }
-
- if (listen(ctcp->listen_fd, 10) == -1) {
- goto failed;
- }
-
- fde = tevent_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, TEVENT_FD_READ,
- ctdb_listen_event, ctdb);
- tevent_fd_set_auto_close(fde);
-
- return 0;
-
-failed:
- if (ctcp->listen_fd != -1) {
- close(ctcp->listen_fd);
- }
- ctcp->listen_fd = -1;
- return -1;
+ ret = ctdb_tcp_listen_addr(ctdb, ctdb->address, true);
+ return ret;
}
-