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
*/
# include "includes.h"
# include "lib/events/events.h"
2007-01-23 03:38:45 +03:00
# include "lib/tdb/include/tdb.h"
2006-11-18 02:41:20 +03:00
# include "system/network.h"
# include "system/filesys.h"
2007-01-23 03:38:45 +03:00
# include "../include/ctdb_private.h"
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
/*
stop any connecting ( established or pending ) to a node
*/
void ctdb_tcp_stop_connection ( struct ctdb_node * node )
{
struct ctdb_tcp_node * tnode = talloc_get_type (
node - > private_data , struct ctdb_tcp_node ) ;
ctdb_queue_set_fd ( tnode - > out_queue , - 1 ) ;
talloc_free ( tnode - > connect_te ) ;
talloc_free ( tnode - > connect_fde ) ;
tnode - > connect_fde = NULL ;
tnode - > connect_te = NULL ;
if ( tnode - > fd ! = - 1 ) {
close ( tnode - > fd ) ;
tnode - > fd = - 1 ;
}
}
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-11 22:12:15 +04:00
struct ctdb_tcp_node * tnode = talloc_get_type (
node - > private_data , struct ctdb_tcp_node ) ;
2007-04-10 13:33:21 +04:00
2007-04-17 13:41:29 +04:00
if ( data = = NULL ) {
node - > ctdb - > upcalls - > node_dead ( node ) ;
}
2007-10-22 10:41:11 +04:00
ctdb_tcp_stop_connection ( node ) ;
2008-12-02 05:26:30 +03:00
tnode - > connect_te = event_add_timed ( node - > ctdb - > ev , tnode ,
timeval_current_ofs ( 3 , 0 ) ,
2007-10-22 10:41:11 +04:00
ctdb_tcp_node_connect , node ) ;
2007-04-10 13:33:21 +04:00
}
2006-11-18 02:41:20 +03:00
/*
called when socket becomes writeable on connect
*/
static void ctdb_node_connect_write ( struct event_context * ev , struct fd_event * 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 ) ;
struct ctdb_tcp_node * tnode = talloc_get_type ( node - > private_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 ;
2006-11-18 02:41:20 +03:00
2007-05-25 16:07:45 +04:00
talloc_free ( tnode - > connect_te ) ;
tnode - > connect_te = NULL ;
2006-11-27 13:38:13 +03:00
if ( getsockopt ( tnode - > fd , SOL_SOCKET , SO_ERROR , & error , & len ) ! = 0 | |
2006-11-18 07:27:36 +03:00
error ! = 0 ) {
2007-10-22 10:41:11 +04:00
ctdb_tcp_stop_connection ( node ) ;
tnode - > connect_te = event_add_timed ( ctdb - > ev , tnode ,
timeval_current_ofs ( 1 , 0 ) ,
ctdb_tcp_node_connect , node ) ;
2006-11-18 02:41:20 +03:00
return ;
}
2007-10-22 08:07:35 +04:00
talloc_free ( tnode - > connect_fde ) ;
tnode - > connect_fde = NULL ;
2007-10-22 10:41:11 +04:00
2007-04-10 13:33:21 +04:00
setsockopt ( tnode - > fd , IPPROTO_TCP , TCP_NODELAY , ( char * ) & one , sizeof ( one ) ) ;
2007-05-15 12:40:56 +04:00
setsockopt ( tnode - > fd , SOL_SOCKET , SO_KEEPALIVE , ( char * ) & one , sizeof ( one ) ) ;
2007-04-10 13:33:21 +04:00
2007-07-02 08:26:50 +04:00
ctdb_queue_set_fd ( tnode - > out_queue , tnode - > fd ) ;
2006-11-28 09:56:10 +03:00
2007-10-22 10:41:11 +04:00
/* the queue subsystem now owns this fd */
tnode - > fd = - 1 ;
2006-11-18 02:41:20 +03:00
}
2007-02-20 05:22:18 +03:00
static int ctdb_tcp_get_address ( struct ctdb_context * ctdb ,
2008-08-19 08:58:29 +04:00
const char * address , ctdb_sock_addr * addr )
2007-02-20 05:22:18 +03:00
{
2008-08-19 08:58:29 +04:00
if ( parse_ip ( address , addr ) = = 0 ) {
DEBUG ( DEBUG_CRIT , ( __location__ " Unparsable address : %s. \n " , address ) ) ;
return - 1 ;
2007-02-20 05:22:18 +03:00
}
return 0 ;
}
2006-11-18 02:41:20 +03:00
/*
called when we should try and establish a tcp connection to a node
*/
2006-11-28 03:51:33 +03:00
void ctdb_tcp_node_connect ( struct event_context * ev , struct timed_event * te ,
2007-04-11 22:12:15 +04:00
struct timeval t , 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 ) ;
struct ctdb_tcp_node * tnode = talloc_get_type ( node - > private_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 ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock_out ;
2006-11-18 02:41:20 +03:00
2007-10-22 10:41:11 +04:00
ctdb_tcp_stop_connection ( node ) ;
2007-05-25 16:07:45 +04:00
2007-05-15 03:42:52 +04:00
ZERO_STRUCT ( sock_out ) ;
# ifdef HAVE_SOCK_SIN_LEN
2008-08-19 08:58:29 +04:00
sock_out . ip . sin_len = sizeof ( sock_out ) ;
2007-05-15 03:42:52 +04:00
# endif
2008-08-19 08:58:29 +04:00
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 ) ) ;
2007-02-20 05:22:18 +03:00
return ;
}
2007-04-06 03:08:41 +04:00
2008-12-05 02:33:38 +03:00
DEBUG ( DEBUG_ERR , ( " create socket... \n " ) ) ;
2008-08-19 08:58:29 +04:00
tnode - > fd = socket ( sock_out . sa . sa_family , SOCK_STREAM , IPPROTO_TCP ) ;
set_nonblocking ( tnode - > fd ) ;
set_close_on_exec ( tnode - > fd ) ;
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 .
*/
2007-05-15 03:42:52 +04:00
ZERO_STRUCT ( sock_in ) ;
2008-08-19 08:58:29 +04:00
if ( ctdb_tcp_get_address ( ctdb , ctdb - > address . address , & sock_in ) ! = 0 ) {
2007-04-06 03:08:41 +04:00
return ;
}
2008-12-05 02:33:38 +03:00
switch ( sock_in . sa . sa_family ) {
case AF_INET :
sockin_size = sizeof ( sock_in . ip ) ;
break ;
case AF_INET6 :
sockin_size = sizeof ( sock_in . ip6 ) ;
break ;
default :
DEBUG ( DEBUG_ERR , ( __location__ " unknown family %u \n " ,
sock_in . sa . sa_family ) ) ;
return ;
}
# ifdef HAVE_SOCK_SIN_LEN
sock_in . ip . sin_len = sockin_size ;
# endif
bind ( tnode - > fd , ( struct sockaddr * ) & sock_in , sockin_size ) ;
2007-04-06 03:08:41 +04:00
2007-01-23 03:38:45 +03:00
if ( connect ( tnode - > fd , ( struct sockaddr * ) & sock_out , sizeof ( sock_out ) ) ! = 0 & &
2006-11-18 02:41:20 +03:00
errno ! = EINPROGRESS ) {
2007-10-22 10:41:11 +04:00
ctdb_tcp_stop_connection ( node ) ;
tnode - > connect_te = event_add_timed ( ctdb - > ev , tnode ,
timeval_current_ofs ( 1 , 0 ) ,
ctdb_tcp_node_connect , node ) ;
2006-11-18 02:41:20 +03:00
return ;
}
/* non-blocking connect - wait for write event */
2007-06-02 02:41:19 +04:00
tnode - > connect_fde = event_add_fd ( node - > ctdb - > ev , tnode , tnode - > fd ,
2007-05-25 16:07:45 +04:00
EVENT_FD_WRITE | EVENT_FD_READ ,
ctdb_node_connect_write , node ) ;
/* 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 ) */
2007-06-02 02:41:19 +04:00
tnode - > connect_te = event_add_timed ( ctdb - > ev , tnode , timeval_current_ofs ( 1 , 0 ) ,
2007-05-25 16:07:45 +04:00
ctdb_tcp_node_connect , node ) ;
2006-11-18 02:41:20 +03:00
}
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
*/
static void ctdb_listen_event ( struct event_context * ev , struct fd_event * 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 ) ;
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > private_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 ;
2007-07-02 08:10:20 +04:00
int fd , nodeid ;
2006-11-18 05:45:04 +03:00
struct ctdb_incoming * in ;
2007-05-15 12:40:56 +04:00
int one = 1 ;
2007-07-02 08:10:20 +04:00
const char * incoming_node ;
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 ;
2008-08-19 08:58:29 +04:00
incoming_node = ctdb_addr_to_str ( & addr ) ;
2007-11-26 02:52:55 +03:00
nodeid = ctdb_ip_to_nodeid ( ctdb , incoming_node ) ;
if ( nodeid = = - 1 ) {
2008-05-06 01:57:43 +04:00
DEBUG ( DEBUG_ERR , ( " Refused connection from unknown node %s \n " , incoming_node ) ) ;
2007-07-02 08:10:20 +04:00
close ( fd ) ;
return ;
}
2007-06-02 02:41:19 +04:00
in = talloc_zero ( ctcp , struct ctdb_incoming ) ;
2006-11-18 05:45:04 +03:00
in - > fd = fd ;
in - > ctdb = ctdb ;
2006-11-28 06:15:46 +03:00
set_nonblocking ( in - > fd ) ;
2007-05-30 09:43:25 +04:00
set_close_on_exec ( in - > fd ) ;
2006-11-28 06:15:46 +03:00
2007-05-15 12:40:56 +04:00
setsockopt ( in - > fd , SOL_SOCKET , SO_KEEPALIVE , ( char * ) & one , sizeof ( one ) ) ;
2007-04-10 13:33:21 +04:00
in - > queue = ctdb_queue_setup ( ctdb , in , in - > fd , CTDB_TCP_ALIGNMENT ,
ctdb_tcp_read_cb , in ) ;
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
{
2007-04-11 22:12:15 +04:00
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > private_data ,
struct ctdb_tcp ) ;
2008-08-19 08:58:29 +04:00
ctdb_sock_addr sock ;
2007-05-01 00:34:55 +04:00
int lock_fd , i ;
const char * lock_path = " /tmp/.ctdb_socket_lock " ;
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 ;
2007-05-01 00:34:55 +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 ) {
2008-02-04 12:07:15 +03:00
DEBUG ( DEBUG_CRIT , ( " Unable to open %s \n " , lock_path ) ) ;
2007-05-01 00:34:55 +04:00
return - 1 ;
}
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
2007-05-01 00:34:55 +04:00
if ( fcntl ( lock_fd , F_SETLKW , & lock ) ! = 0 ) {
2008-02-04 12:07:15 +03:00
DEBUG ( DEBUG_CRIT , ( " Unable to lock %s \n " , lock_path ) ) ;
2007-05-01 00:34:55 +04:00
close ( lock_fd ) ;
2007-02-20 05:22:18 +03:00
return - 1 ;
}
2006-11-18 05:45:04 +03:00
2007-05-01 00:34:55 +04:00
for ( i = 0 ; i < ctdb - > num_nodes ; i + + ) {
2007-11-26 02:52:55 +03:00
/* if node_ip is specified we will only try to bind to that
ip .
*/
if ( ctdb - > node_ip ! = NULL ) {
if ( strcmp ( ctdb - > node_ip , ctdb - > nodes [ i ] - > address . address ) ) {
continue ;
}
}
2007-05-15 03:42:52 +04:00
ZERO_STRUCT ( sock ) ;
2007-11-26 02:52:55 +03:00
if ( ctdb_tcp_get_address ( ctdb ,
ctdb - > nodes [ i ] - > address . address ,
2008-08-19 08:58:29 +04:00
& sock ) ! = 0 ) {
2007-05-01 00:34:55 +04:00
continue ;
}
2007-11-26 02:52:55 +03:00
2008-08-19 08:58:29 +04:00
switch ( sock . sa . sa_family ) {
case AF_INET :
sock . ip . sin_port = htons ( ctdb - > nodes [ i ] - > address . port ) ;
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 :
sock . ip6 . sin6_port = htons ( ctdb - > nodes [ i ] - > address . port ) ;
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 ;
}
2008-12-05 02:33:38 +03:00
# ifdef HAVE_SOCK_SIN_LEN
sock . ip . sin_len = sock_size ;
# endif
2008-08-19 08:58:29 +04:00
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 ) ;
setsockopt ( ctcp - > listen_fd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & one , sizeof ( one ) ) ;
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
break ;
}
}
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 ;
}
2008-02-19 06:35:15 +03:00
ctdb - > address . address = talloc_strdup ( ctdb , ctdb - > nodes [ i ] - > address . address ) ;
ctdb - > address . port = ctdb - > nodes [ i ] - > address . port ;
2007-05-01 00:34:55 +04:00
ctdb - > name = talloc_asprintf ( ctdb , " %s:%u " ,
ctdb - > address . address ,
ctdb - > address . port ) ;
2007-09-04 04:06:36 +04:00
ctdb - > pnn = ctdb - > nodes [ i ] - > pnn ;
2007-06-07 09:18:55 +04:00
ctdb - > nodes [ i ] - > flags & = ~ NODE_FLAGS_DISCONNECTED ;
2008-02-04 09:44:24 +03:00
DEBUG ( DEBUG_INFO , ( " ctdb chose network address %s:%u pnn %u \n " ,
2007-05-01 00:34:55 +04:00
ctdb - > address . address ,
ctdb - > address . port ,
2007-09-04 04:06:36 +04:00
ctdb - > pnn ) ) ;
2008-02-22 01:42:52 +03:00
/* do we start out in DISABLED mode? */
if ( ctdb - > start_as_disabled ! = 0 ) {
2008-02-22 01:52:57 +03:00
DEBUG ( DEBUG_INFO , ( " This node is configured to start in DISABLED state \n " ) ) ;
2008-02-22 01:42:52 +03:00
ctdb - > nodes [ i ] - > flags | = NODE_FLAGS_DISABLED ;
}
2007-05-01 00:34:55 +04:00
if ( listen ( ctcp - > listen_fd , 10 ) = = - 1 ) {
goto failed ;
}
2007-06-02 02:41:19 +04:00
event_add_fd ( ctdb - > ev , ctcp , ctcp - > listen_fd , EVENT_FD_READ | EVENT_FD_AUTOCLOSE ,
2007-05-01 00:34:55 +04:00
ctdb_listen_event , ctdb ) ;
close ( lock_fd ) ;
return 0 ;
failed :
close ( lock_fd ) ;
close ( ctcp - > listen_fd ) ;
ctcp - > listen_fd = - 1 ;
return - 1 ;
}
/*
listen on our own address
*/
int ctdb_tcp_listen ( struct ctdb_context * ctdb )
{
struct ctdb_tcp * ctcp = talloc_get_type ( ctdb - > private_data ,
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 ;
/* we can either auto-bind to the first available address, or we can
use a specified address */
if ( ! ctdb - > address . address ) {
return ctdb_tcp_listen_automatic ( ctdb ) ;
}
2007-05-15 03:42:52 +04:00
ZERO_STRUCT ( sock ) ;
2007-05-01 00:34:55 +04:00
if ( ctdb_tcp_get_address ( ctdb , ctdb - > address . address ,
2008-08-19 08:58:29 +04:00
& sock ) ! = 0 ) {
2007-05-01 00:34:55 +04:00
goto failed ;
}
2008-08-19 08:58:29 +04:00
switch ( sock . sa . sa_family ) {
case AF_INET :
sock . ip . sin_port = htons ( ctdb - > address . port ) ;
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 :
sock . ip6 . sin6_port = htons ( ctdb - > address . port ) ;
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 ;
}
2008-12-05 02:33:38 +03:00
# ifdef HAVE_SOCK_SIN_LEN
sock . ip . sin_len = sock_size ;
# endif
2008-08-19 08:58:29 +04:00
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 ) ;
setsockopt ( ctcp - > listen_fd , SOL_SOCKET , SO_REUSEADDR , ( char * ) & one , sizeof ( one ) ) ;
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
}
2007-06-02 02:41:19 +04:00
event_add_fd ( ctdb - > ev , ctcp , ctcp - > listen_fd , EVENT_FD_READ | EVENT_FD_AUTOCLOSE ,
2006-11-18 05:45:04 +03:00
ctdb_listen_event , ctdb ) ;
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
}