2006-11-18 02:41:20 +03:00
/*
ctdb over TCP
Copyright ( C ) Andrew Tridgell 2006
2008-12-05 02:33:38 +03:00
Copyright ( C ) Ronnie Sahlberg 2008
2006-11-18 02:41:20 +03:00
2007-05-31 07:50:53 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 09:29:31 +04:00
the Free Software Foundation ; either version 3 of the License , or
2007-05-31 07:50:53 +04:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
2006-11-18 02:41:20 +03:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
2007-05-31 07:50:53 +04:00
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 09:29:31 +04:00
along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2006-11-18 02:41:20 +03:00
*/
2015-10-26 08:50:46 +03:00
# include "replace.h"
2006-11-18 02:41:20 +03:00
# include "system/network.h"
# include "system/filesys.h"
2015-10-26 08:50:46 +03:00
# include <talloc.h>
# include <tevent.h>
# include "lib/util/debug.h"
# include "lib/util/time.h"
2016-05-27 06:50:06 +03:00
# include "lib/util/blocking.h"
2015-10-26 08:50:46 +03:00
# include "ctdb_private.h"
2015-10-23 06:11:53 +03:00
# include "common/system.h"
2015-10-23 06:17:34 +03:00
# include "common/common.h"
2015-11-11 07:22:52 +03:00
# include "common/logging.h"
2015-10-26 08:50:46 +03:00
2006-11-27 13:38:13 +03:00
# include "ctdb_tcp.h"
2006-11-18 02:41:20 +03:00
2007-10-22 10:41:11 +04:00
/*
2020-02-28 13:36:00 +03:00
stop any outgoing connection ( established or pending ) to a node
2007-10-22 10:41:11 +04:00
*/
2020-02-28 13:36:00 +03:00
void ctdb_tcp_stop_outgoing ( struct ctdb_node * node )
2007-10-22 10:41:11 +04:00
{
struct ctdb_tcp_node * tnode = talloc_get_type (
2019-11-12 04:04:22 +03:00
node - > transport_data , struct ctdb_tcp_node ) ;
2019-08-15 08:57:31 +03:00
TALLOC_FREE ( tnode - > out_queue ) ;
2019-08-15 08:45:16 +03:00
TALLOC_FREE ( tnode - > connect_te ) ;
TALLOC_FREE ( tnode - > connect_fde ) ;
2019-08-09 08:06:34 +03:00
if ( tnode - > out_fd ! = - 1 ) {
close ( tnode - > out_fd ) ;
tnode - > out_fd = - 1 ;
2007-10-22 10:41:11 +04:00
}
}
2020-02-29 13:54:51 +03:00
/*
stop incoming connection to a node
*/
void ctdb_tcp_stop_incoming ( struct ctdb_node * node )
{
struct ctdb_tcp_node * tnode = talloc_get_type (
node - > transport_data , struct ctdb_tcp_node ) ;
TALLOC_FREE ( tnode - > in_queue ) ;
}
2007-10-22 10:41:11 +04:00
2007-04-10 13:33:21 +04:00
/*
called when a complete packet has come in - should not happen on this socket
2008-12-02 05:26:30 +03:00
unless the other side closes the connection with RST or FIN
2007-04-10 13:33:21 +04:00
*/
2007-04-13 14:38:24 +04:00
void ctdb_tcp_tnode_cb ( uint8_t * data , size_t cnt , void * private_data )
2007-04-10 13:33:21 +04:00
{
2007-04-13 14:38:24 +04:00
struct ctdb_node * node = talloc_get_type ( private_data , struct ctdb_node ) ;
2007-04-10 13:33:21 +04:00
2020-02-29 14:13:12 +03:00
node - > ctdb - > upcalls - > node_dead ( node ) ;
2007-04-17 13:41:29 +04:00
2018-03-13 11:42:24 +03:00
TALLOC_FREE ( data ) ;
2007-04-10 13:33:21 +04:00
}
2006-11-18 02:41:20 +03:00
/*
called when socket becomes writeable on connect
*/
2015-10-26 08:50:09 +03:00
static void ctdb_node_connect_write ( struct tevent_context * ev ,
struct tevent_fd * fde ,
2007-04-11 22:12:15 +04:00
uint16_t flags , void * private_data )
2006-11-18 02:41:20 +03:00
{
2007-04-11 22:12:15 +04:00
struct ctdb_node * node = talloc_get_type ( private_data ,
struct ctdb_node ) ;
2019-11-12 04:04:22 +03:00
struct ctdb_tcp_node * tnode = talloc_get_type ( node - > transport_data ,
2006-11-27 13:38:13 +03:00
struct ctdb_tcp_node ) ;
2006-11-18 02:41:20 +03:00
struct ctdb_context * ctdb = node - > ctdb ;
2006-11-28 09:56:10 +03:00
int error = 0 ;
2006-12-01 07:45:24 +03:00
socklen_t len = sizeof ( error ) ;
2007-02-20 06:57:13 +03:00
int one = 1 ;
2019-08-09 08:06:34 +03:00
int ret ;
2006-11-18 02:41:20 +03:00
2019-11-07 14:12:45 +03:00
TALLOC_FREE ( tnode - > connect_te ) ;
2007-05-25 16:07:45 +04:00
2019-08-09 08:06:34 +03:00
ret = getsockopt ( tnode - > out_fd , SOL_SOCKET , SO_ERROR , & error , & len ) ;
if ( ret ! = 0 | | error ! = 0 ) {
2020-02-28 13:36:00 +03:00
ctdb_tcp_stop_outgoing ( node ) ;
2015-10-26 08:50:09 +03:00
tnode - > connect_te = tevent_add_timer ( ctdb - > ev , tnode ,
2007-10-22 10:41:11 +04:00
timeval_current_ofs ( 1 , 0 ) ,
ctdb_tcp_node_connect , node ) ;
2006-11-18 02:41:20 +03:00
return ;
}
2019-11-07 14:12:45 +03:00
TALLOC_FREE ( tnode - > connect_fde ) ;
2007-10-22 10:41:11 +04:00
2019-08-09 08:06:34 +03:00
ret = setsockopt ( tnode - > out_fd ,
IPPROTO_TCP ,
TCP_NODELAY ,
( char * ) & one ,
sizeof ( one ) ) ;
if ( ret = = - 1 ) {
DBG_WARNING ( " Failed to set TCP_NODELAY on fd - %s \n " ,
strerror ( errno ) ) ;
2013-11-11 05:41:00 +04:00
}
2019-08-09 08:06:34 +03:00
ret = setsockopt ( tnode - > out_fd ,
SOL_SOCKET ,
SO_KEEPALIVE , ( char * ) & one ,
sizeof ( one ) ) ;
if ( ret = = - 1 ) {
DBG_WARNING ( " Failed to set KEEPALIVE on fd - %s \n " ,
strerror ( errno ) ) ;
2013-11-11 05:41:00 +04:00
}
2007-04-10 13:33:21 +04:00
2019-08-15 08:57:31 +03:00
tnode - > out_queue = ctdb_queue_setup ( node - > ctdb ,
tnode ,
tnode - > out_fd ,
CTDB_TCP_ALIGNMENT ,
ctdb_tcp_tnode_cb ,
node ,
" to-node-%s " ,
node - > name ) ;
if ( tnode - > out_queue = = NULL ) {
DBG_ERR ( " Failed to set up outgoing queue \n " ) ;
2020-02-28 13:36:00 +03:00
ctdb_tcp_stop_outgoing ( node ) ;
2019-08-15 08:57:31 +03:00
tnode - > connect_te = tevent_add_timer ( ctdb - > ev ,
tnode ,
timeval_current_ofs ( 1 , 0 ) ,
ctdb_tcp_node_connect ,
node ) ;
return ;
}
2006-11-28 09:56:10 +03:00
2007-10-22 10:41:11 +04:00
/* the queue subsystem now owns this fd */
2019-08-09 08:06:34 +03:00
tnode - > out_fd = - 1 ;
2019-04-05 08:17:35 +03:00
2019-08-09 08:33:05 +03:00
/*
* Mark the node to which this connection has been established
* as connected , but only if the corresponding listening
* socket is also connected
*/
2019-10-29 07:25:26 +03:00
if ( tnode - > in_queue ! = NULL ) {
2019-08-09 08:33:05 +03:00
node - > ctdb - > upcalls - > node_connected ( node ) ;
}
2006-11-18 02:41:20 +03:00
}
2007-02-20 05:22:18 +03:00
2020-03-06 08:11:23 +03:00
static void ctdb_tcp_node_connect_timeout ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval t ,
void * private_data ) ;
2006-11-18 02:41:20 +03:00
/*
called when we should try and establish a tcp connection to a node
*/
2020-03-06 07:59:32 +03:00
static void ctdb_tcp_start_outgoing ( struct ctdb_node * node )
2006-11-18 02:41:20 +03:00
{
2019-11-12 04:04:22 +03:00
struct ctdb_tcp_node * tnode = talloc_get_type ( node - > transport_data ,
2006-11-27 13:38:13 +03:00
struct ctdb_tcp_node ) ;
2006-11-18 02:41:20 +03:00
struct ctdb_context * ctdb = node - > ctdb ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock_in ;
2008-12-05 02:33:38 +03:00
int sockin_size ;
2009-03-16 01:21:24 +03:00
int sockout_size ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock_out ;
2016-08-10 10:12:21 +03:00
int ret ;
2006-11-18 02:41:20 +03:00
2015-02-20 03:47:23 +03:00
sock_out = node - > address ;
2007-04-06 03:08:41 +04:00
2019-08-09 08:06:34 +03:00
tnode - > out_fd = socket ( sock_out . sa . sa_family , SOCK_STREAM , IPPROTO_TCP ) ;
if ( tnode - > out_fd = = - 1 ) {
DBG_ERR ( " Failed to create socket \n " ) ;
2020-01-28 08:49:14 +03:00
goto failed ;
2011-08-10 19:53:56 +04:00
}
2016-08-10 10:12:21 +03:00
2019-08-09 08:06:34 +03:00
ret = set_blocking ( tnode - > out_fd , false ) ;
2016-08-10 10:12:21 +03:00
if ( ret ! = 0 ) {
2019-08-09 08:06:34 +03:00
DBG_ERR ( " Failed to set socket non-blocking (%s) \n " ,
strerror ( errno ) ) ;
2020-01-28 08:49:14 +03:00
goto failed ;
2016-08-10 10:12:21 +03:00
}
2019-08-09 08:06:34 +03:00
set_close_on_exec ( tnode - > out_fd ) ;
2007-04-06 03:08:41 +04:00
2019-08-09 08:06:34 +03:00
DBG_DEBUG ( " Created TCP SOCKET FD:%d \n " , tnode - > out_fd ) ;
2009-10-15 04:24:54 +04:00
2007-04-06 03:08:41 +04:00
/* Bind our side of the socketpair to the same address we use to listen
* on incoming CTDB traffic .
* We must specify this address to make sure that the address we expose to
* the remote side is actually routable in case CTDB traffic will run on
* a dedicated non - routeable network .
*/
2015-02-20 03:47:23 +03:00
sock_in = * ctdb - > address ;
2009-03-16 01:21:24 +03:00
/* AIX libs check to see if the socket address and length
arguments are consistent with each other on calls like
connect ( ) . Can not get by with just sizeof ( sock_in ) ,
need sizeof ( sock_in . ip ) .
*/
2008-12-05 02:33:38 +03:00
switch ( sock_in . sa . sa_family ) {
case AF_INET :
2015-02-20 03:47:23 +03:00
sock_in . ip . sin_port = 0 /* Any port */ ;
2008-12-05 02:33:38 +03:00
sockin_size = sizeof ( sock_in . ip ) ;
2009-03-16 01:21:24 +03:00
sockout_size = sizeof ( sock_out . ip ) ;
2008-12-05 02:33:38 +03:00
break ;
case AF_INET6 :
2015-02-20 03:47:23 +03:00
sock_in . ip6 . sin6_port = 0 /* Any port */ ;
2008-12-05 02:33:38 +03:00
sockin_size = sizeof ( sock_in . ip6 ) ;
2009-03-16 01:21:24 +03:00
sockout_size = sizeof ( sock_out . ip6 ) ;
2008-12-05 02:33:38 +03:00
break ;
default :
2020-01-28 08:49:14 +03:00
DBG_ERR ( " Unknown address family %u \n " , sock_in . sa . sa_family ) ;
/* Can't happen to due to address parsing restrictions */
goto failed ;
2008-12-05 02:33:38 +03:00
}
2015-02-20 03:47:23 +03:00
2019-08-09 08:06:34 +03:00
ret = bind ( tnode - > out_fd , ( struct sockaddr * ) & sock_in , sockin_size ) ;
if ( ret = = - 1 ) {
DBG_ERR ( " Failed to bind socket (%s) \n " , strerror ( errno ) ) ;
2020-01-28 08:49:14 +03:00
goto failed ;
2011-08-10 19:53:56 +04:00
}
2007-04-06 03:08:41 +04:00
2019-08-09 08:06:34 +03:00
ret = connect ( tnode - > out_fd ,
( struct sockaddr * ) & sock_out ,
sockout_size ) ;
if ( ret ! = 0 & & errno ! = EINPROGRESS ) {
2020-01-28 08:49:14 +03:00
goto failed ;
2006-11-18 02:41:20 +03:00
}
/* non-blocking connect - wait for write event */
2019-08-09 08:06:34 +03:00
tnode - > connect_fde = tevent_add_fd ( node - > ctdb - > ev ,
tnode ,
tnode - > out_fd ,
2015-10-26 08:50:09 +03:00
TEVENT_FD_WRITE | TEVENT_FD_READ ,
2019-08-09 08:06:34 +03:00
ctdb_node_connect_write ,
node ) ;
2007-05-25 16:07:45 +04:00
/* don't give it long to connect - retry in one second. This ensures
that we find a node is up quickly ( tcp normally backs off a syn reply
delay by quite a lot ) */
2019-08-09 08:06:34 +03:00
tnode - > connect_te = tevent_add_timer ( ctdb - > ev ,
tnode ,
2015-10-26 08:50:09 +03:00
timeval_current_ofs ( 1 , 0 ) ,
2020-03-06 08:11:23 +03:00
ctdb_tcp_node_connect_timeout ,
2019-08-09 08:06:34 +03:00
node ) ;
2020-01-28 08:49:14 +03:00
return ;
failed :
2020-02-28 13:36:00 +03:00
ctdb_tcp_stop_outgoing ( node ) ;
2020-01-28 08:49:14 +03:00
tnode - > connect_te = tevent_add_timer ( ctdb - > ev ,
tnode ,
timeval_current_ofs ( 1 , 0 ) ,
ctdb_tcp_node_connect ,
node ) ;
2006-11-18 02:41:20 +03:00
}
2020-03-06 07:59:32 +03:00
void ctdb_tcp_node_connect ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval t ,
void * private_data )
{
struct ctdb_node * node = talloc_get_type_abort ( private_data ,
struct ctdb_node ) ;
2020-03-06 08:11:23 +03:00
ctdb_tcp_start_outgoing ( node ) ;
}
static void ctdb_tcp_node_connect_timeout ( struct tevent_context * ev ,
struct tevent_timer * te ,
struct timeval t ,
void * private_data )
{
struct ctdb_node * node = talloc_get_type_abort ( private_data ,
struct ctdb_node ) ;
2020-03-06 07:59:32 +03:00
ctdb_tcp_stop_outgoing ( node ) ;
ctdb_tcp_start_outgoing ( node ) ;
}
2006-11-18 05:45:04 +03:00
/*
called when we get contacted by another node
currently makes no attempt to check if the connection is really from a ctdb
node in our cluster
*/
2015-10-26 08:50:09 +03:00
static void ctdb_listen_event ( struct tevent_context * ev , struct tevent_fd * fde ,
2007-04-13 14:38:24 +04:00
uint16_t flags , void * private_data )
2006-11-18 05:45:04 +03:00
{
2007-06-02 02:41:19 +04:00
struct ctdb_context * ctdb = talloc_get_type ( private_data , struct ctdb_context ) ;
2019-11-12 04:12:46 +03:00
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > transport_data ,
struct ctdb_tcp ) ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr addr ;
2006-11-18 05:45:04 +03:00
socklen_t len ;
2019-06-21 22:53:15 +03:00
int fd ;
2019-08-09 08:29:36 +03:00
struct ctdb_node * node ;
struct ctdb_tcp_node * tnode ;
2007-05-15 12:40:56 +04:00
int one = 1 ;
2016-08-10 10:31:52 +03:00
int ret ;
2006-11-18 05:45:04 +03:00
2006-11-18 07:27:36 +03:00
memset ( & addr , 0 , sizeof ( addr ) ) ;
len = sizeof ( addr ) ;
2006-11-27 13:38:13 +03:00
fd = accept ( ctcp - > listen_fd , ( struct sockaddr * ) & addr , & len ) ;
2006-11-18 05:45:04 +03:00
if ( fd = = - 1 ) return ;
2017-12-10 23:37:28 +03:00
smb_set_close_on_exec ( fd ) ;
2006-11-18 05:45:04 +03:00
2019-08-09 08:29:36 +03:00
node = ctdb_ip_to_node ( ctdb , & addr ) ;
if ( node = = NULL ) {
2019-06-21 22:53:15 +03:00
D_ERR ( " Refused connection from unknown node %s \n " ,
ctdb_addr_to_str ( & addr ) ) ;
2007-07-02 08:10:20 +04:00
close ( fd ) ;
return ;
}
2019-11-12 04:04:22 +03:00
tnode = talloc_get_type_abort ( node - > transport_data ,
2019-08-09 08:29:36 +03:00
struct ctdb_tcp_node ) ;
if ( tnode = = NULL ) {
/* This can't happen - see ctdb_tcp_initialise() */
DBG_ERR ( " INTERNAL ERROR setting up connection from node %s \n " ,
ctdb_addr_to_str ( & addr ) ) ;
close ( fd ) ;
2019-10-29 07:29:11 +03:00
return ;
}
if ( tnode - > in_queue ! = NULL ) {
DBG_ERR ( " Incoming queue active, rejecting connection from %s \n " ,
ctdb_addr_to_str ( & addr ) ) ;
close ( fd ) ;
2019-08-09 08:29:36 +03:00
return ;
}
2006-11-18 05:45:04 +03:00
2019-08-09 08:29:36 +03:00
ret = set_blocking ( fd , false ) ;
2016-08-10 10:31:52 +03:00
if ( ret ! = 0 ) {
2019-08-09 08:29:36 +03:00
DBG_ERR ( " Failed to set socket non-blocking (%s) \n " ,
strerror ( errno ) ) ;
close ( fd ) ;
2016-08-10 10:31:52 +03:00
return ;
}
2019-08-09 08:29:36 +03:00
set_close_on_exec ( fd ) ;
2006-11-28 06:15:46 +03:00
2019-08-09 08:29:36 +03:00
DBG_DEBUG ( " Created SOCKET FD:%d to incoming ctdb connection \n " , fd ) ;
2009-10-15 04:24:54 +04:00
2019-08-09 08:29:36 +03:00
ret = setsockopt ( fd ,
SOL_SOCKET ,
SO_KEEPALIVE ,
( char * ) & one ,
sizeof ( one ) ) ;
if ( ret = = - 1 ) {
DBG_WARNING ( " Failed to set KEEPALIVE on fd - %s \n " ,
strerror ( errno ) ) ;
}
tnode - > in_queue = ctdb_queue_setup ( ctdb ,
tnode ,
fd ,
CTDB_TCP_ALIGNMENT ,
ctdb_tcp_read_cb ,
2019-08-13 10:08:43 +03:00
node ,
2019-08-09 08:29:36 +03:00
" ctdbd-%s " ,
ctdb_addr_to_str ( & addr ) ) ;
if ( tnode - > in_queue = = NULL ) {
DBG_ERR ( " Failed to set up incoming queue \n " ) ;
close ( fd ) ;
return ;
2013-11-11 05:41:00 +04:00
}
2007-05-15 12:40:56 +04:00
2019-08-09 08:33:05 +03:00
/*
* Mark the connecting node as connected , but only if the
* corresponding outbound connected is also up
*/
if ( tnode - > out_queue ! = NULL ) {
node - > ctdb - > upcalls - > node_connected ( node ) ;
}
}
2006-11-18 05:45:04 +03:00
/*
2007-05-01 00:34:55 +04:00
automatically find which address to listen on
2006-11-18 05:45:04 +03:00
*/
2007-05-01 00:34:55 +04:00
static int ctdb_tcp_listen_automatic ( struct ctdb_context * ctdb )
2006-11-18 05:45:04 +03:00
{
2019-11-12 04:12:46 +03:00
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > transport_data ,
2007-04-11 22:12:15 +04:00
struct ctdb_tcp ) ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock ;
2019-06-21 22:29:53 +03:00
int lock_fd ;
unsigned int i ;
2014-06-23 09:20:44 +04:00
const char * lock_path = CTDB_RUNDIR " /.socket_lock " ;
2007-05-01 00:34:55 +04:00
struct flock lock ;
2008-08-19 08:58:29 +04:00
int one = 1 ;
2008-12-05 02:33:38 +03:00
int sock_size ;
2010-08-18 03:46:31 +04:00
struct tevent_fd * fde ;
2007-05-01 00:34:55 +04:00
2012-07-04 01:21:01 +04:00
/* 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 .
*/
if ( ctdb - > num_nodes = = 0 ) {
DEBUG ( DEBUG_CRIT , ( " No nodes available to attempt bind to - is the nodes file empty? \n " ) ) ;
return - 1 ;
}
2012-12-03 08:44:12 +04:00
/* in order to ensure that we don't get two nodes with the
same adddress , 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 ) ) ;
return - 1 ;
}
2007-05-01 00:34:55 +04:00
2012-12-03 08:44:12 +04:00
lock . l_type = F_WRLCK ;
lock . l_whence = SEEK_SET ;
lock . l_start = 0 ;
lock . l_len = 1 ;
lock . l_pid = 0 ;
2006-11-18 05:45:04 +03:00
2012-12-03 08:44:12 +04:00
if ( fcntl ( lock_fd , F_SETLKW , & lock ) ! = 0 ) {
DEBUG ( DEBUG_CRIT , ( " Unable to lock %s \n " , lock_path ) ) ;
close ( lock_fd ) ;
return - 1 ;
2007-02-20 05:22:18 +03:00
}
2006-11-18 05:45:04 +03:00
2009-06-01 08:18:34 +04:00
for ( i = 0 ; i < ctdb - > num_nodes ; i + + ) {
if ( ctdb - > nodes [ i ] - > flags & NODE_FLAGS_DELETED ) {
continue ;
}
2015-02-20 03:47:23 +03:00
sock = ctdb - > nodes [ i ] - > address ;
2008-08-19 08:58:29 +04:00
switch ( sock . sa . sa_family ) {
case AF_INET :
2008-12-05 02:33:38 +03:00
sock_size = sizeof ( sock . ip ) ;
2008-08-19 08:58:29 +04:00
break ;
case AF_INET6 :
2008-12-05 02:33:38 +03:00
sock_size = sizeof ( sock . ip6 ) ;
2008-08-19 08:58:29 +04:00
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 ) ;
2013-11-11 05:41:00 +04:00
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 ) ) ) ;
}
2008-08-19 08:58:29 +04:00
2008-12-05 02:33:38 +03:00
if ( bind ( ctcp - > listen_fd , ( struct sockaddr * ) & sock , sock_size ) = = 0 ) {
2007-05-01 00:34:55 +04:00
break ;
}
2009-10-21 19:06:48 +04:00
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 ) ) ;
}
2015-09-08 11:01:31 +03:00
close ( ctcp - > listen_fd ) ;
2015-09-15 11:19:03 +03:00
ctcp - > listen_fd = - 1 ;
2007-05-01 00:34:55 +04:00
}
2015-02-17 07:21:15 +03:00
2007-05-01 00:34:55 +04:00
if ( i = = ctdb - > num_nodes ) {
2008-02-04 12:07:15 +03:00
DEBUG ( DEBUG_CRIT , ( " Unable to bind to any of the node addresses - giving up \n " ) ) ;
2007-05-01 00:34:55 +04:00
goto failed ;
}
2015-02-20 03:47:23 +03:00
ctdb - > address = talloc_memdup ( ctdb ,
& ctdb - > nodes [ i ] - > address ,
sizeof ( ctdb_sock_addr ) ) ;
2015-03-31 16:13:36 +03:00
if ( ctdb - > address = = NULL ) {
ctdb_set_error ( ctdb , " Out of memory at %s:%d " ,
__FILE__ , __LINE__ ) ;
goto failed ;
}
2015-02-17 07:21:15 +03:00
ctdb - > name = talloc_asprintf ( ctdb , " %s:%u " ,
2015-02-20 03:47:23 +03:00
ctdb_addr_to_str ( ctdb - > address ) ,
ctdb_addr_to_port ( ctdb - > address ) ) ;
2015-03-31 19:06:43 +03:00
if ( ctdb - > name = = NULL ) {
ctdb_set_error ( ctdb , " Out of memory at %s:%d " ,
__FILE__ , __LINE__ ) ;
goto failed ;
}
2015-02-20 03:47:23 +03:00
DEBUG ( DEBUG_INFO , ( " ctdb chose network address %s \n " , ctdb - > name ) ) ;
2015-02-17 07:21:15 +03:00
2007-05-01 00:34:55 +04:00
if ( listen ( ctcp - > listen_fd , 10 ) = = - 1 ) {
goto failed ;
}
2015-10-26 08:50:09 +03:00
fde = tevent_add_fd ( ctdb - > ev , ctcp , ctcp - > listen_fd , TEVENT_FD_READ ,
ctdb_listen_event , ctdb ) ;
2010-08-18 03:46:31 +04:00
tevent_fd_set_auto_close ( fde ) ;
2007-05-01 00:34:55 +04:00
2012-12-03 08:44:12 +04:00
close ( lock_fd ) ;
2007-05-01 00:34:55 +04:00
return 0 ;
2015-02-20 03:47:23 +03:00
2007-05-01 00:34:55 +04:00
failed :
2012-12-03 08:44:12 +04:00
close ( lock_fd ) ;
2013-11-11 05:41:00 +04:00
if ( ctcp - > listen_fd ! = - 1 ) {
close ( ctcp - > listen_fd ) ;
ctcp - > listen_fd = - 1 ;
}
2007-05-01 00:34:55 +04:00
return - 1 ;
}
/*
listen on our own address
*/
int ctdb_tcp_listen ( struct ctdb_context * ctdb )
{
2019-11-12 04:12:46 +03:00
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > transport_data ,
2007-05-01 00:34:55 +04:00
struct ctdb_tcp ) ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock ;
2008-12-05 02:33:38 +03:00
int sock_size ;
2007-05-01 00:34:55 +04:00
int one = 1 ;
2010-08-18 03:46:31 +04:00
struct tevent_fd * fde ;
2007-05-01 00:34:55 +04:00
/* we can either auto-bind to the first available address, or we can
use a specified address */
2015-02-20 03:47:23 +03:00
if ( ! ctdb - > address ) {
2007-05-01 00:34:55 +04:00
return ctdb_tcp_listen_automatic ( ctdb ) ;
}
2015-02-20 03:47:23 +03:00
sock = * ctdb - > address ;
2008-08-19 08:58:29 +04:00
switch ( sock . sa . sa_family ) {
case AF_INET :
2008-12-05 02:33:38 +03:00
sock_size = sizeof ( sock . ip ) ;
2008-08-19 08:58:29 +04:00
break ;
case AF_INET6 :
2008-12-05 02:33:38 +03:00
sock_size = sizeof ( sock . ip6 ) ;
2008-08-19 08:58:29 +04:00
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 ) ;
2013-11-11 05:41:00 +04:00
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 ) ) ) ;
}
2008-08-19 08:58:29 +04:00
2008-12-05 02:33:38 +03:00
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 ) ) ;
2007-05-01 00:34:55 +04:00
goto failed ;
}
2006-11-18 05:45:04 +03:00
2006-11-27 13:38:13 +03:00
if ( listen ( ctcp - > listen_fd , 10 ) = = - 1 ) {
2007-05-01 00:34:55 +04:00
goto failed ;
2006-11-18 05:45:04 +03:00
}
2015-10-26 08:50:09 +03:00
fde = tevent_add_fd ( ctdb - > ev , ctcp , ctcp - > listen_fd , TEVENT_FD_READ ,
ctdb_listen_event , ctdb ) ;
2010-08-18 03:46:31 +04:00
tevent_fd_set_auto_close ( fde ) ;
2006-11-18 05:45:04 +03:00
return 0 ;
2007-05-01 00:34:55 +04:00
failed :
2008-08-19 08:58:29 +04:00
if ( ctcp - > listen_fd ! = - 1 ) {
close ( ctcp - > listen_fd ) ;
}
2007-05-01 00:34:55 +04:00
ctcp - > listen_fd = - 1 ;
return - 1 ;
2006-11-18 05:45:04 +03:00
}