From: Martin Schwenke Date: Fri, 5 Jul 2024 05:51:25 +0000 (+1000) Subject: ctdb-tcp: Factor out listening code to avoid repetition X-Git-Tag: tdb-1.4.13~1346 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b43366341456e6848c401727e9d71633ad8aeef9;p=thirdparty%2Fsamba.git ctdb-tcp: Factor out listening code to avoid repetition Modernise debug and comments while here. Signed-off-by: Martin Schwenke Reviewed-by: Volker Lendecke --- diff --git a/ctdb/tcp/tcp_connect.c b/ctdb/tcp/tcp_connect.c index 7d2a3e649ea..61f7918e3b5 100644 --- a/ctdb/tcp/tcp_connect.c +++ b/ctdb/tcp/tcp_connect.c @@ -386,24 +386,105 @@ static void ctdb_listen_event(struct tevent_context *ev, struct tevent_fd *fde, } } +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. */ @@ -412,13 +493,15 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) 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; } @@ -429,7 +512,7 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) 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; } @@ -438,91 +521,36 @@ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) 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; } @@ -531,67 +559,15 @@ failed: */ 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; } -