mirror of
https://github.com/samba-team/samba.git
synced 2025-03-11 16:58:40 +03:00
ctdb-tcp: Factor out listening code to avoid repetition
Modernise debug and comments while here. Signed-off-by: Martin Schwenke <mschwenke@ddn.com> Reviewed-by: Volker Lendecke <vl@samba.org>
This commit is contained in:
parent
2c75bb8687
commit
b433663414
@ -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);
|
||||
ret = ctdb_tcp_listen_automatic(ctdb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user