@ -7,6 +7,7 @@
# include "etcp_api.h"
# include "etcp_api.h"
# include "etcp_router.h"
# include "etcp_router.h"
# include "utun_instance.h"
# include "utun_instance.h"
# include "config_parser.h"
# include "../lib/u_async.h"
# include "../lib/u_async.h"
# include "../lib/debug_config.h"
# include "../lib/debug_config.h"
# include "../lib/ll_queue.h"
# include "../lib/ll_queue.h"
@ -27,36 +28,33 @@
static struct remote_proxy_ctx * g_rp_ctx = NULL ;
static struct remote_proxy_ctx * g_rp_ctx = NULL ;
static void rp_sock_read_cb ( socket_t sock , void * arg ) ;
static void rp_sock_read_cb ( socket_t sock , void * arg ) ;
static void rp_sock_write_cb ( socket_t sock , void * arg ) ;
static void rp_sock_write_cb ( socket_t sock , void * arg ) ;
static void rp_sock_error_cb ( socket_t sock , void * arg ) ;
static void rp_sock_error_cb ( socket_t sock , void * arg ) ;
static void rp_conn_free ( struct remote_proxy_conn * rc ) ;
void rp_conn_free ( struct remote_proxy_conn * rc ) ;
static int rp_send_msg ( struct UTUN_INSTANCE * inst , uint64_t dst , uint8_t subcmd ,
static int rp_send_msg ( struct UTUN_INSTANCE * inst , uint64_t dst , uint8_t subcmd ,
uint64 _t sid , uint16_t seq , const uint8_t * data , size_t len ) {
uint32 _t sid , uint16_t seq , const uint8_t * data , size_t len ) {
struct ll_entry * e = queue_entry_new ( 0 ) ;
struct ll_entry * e = queue_entry_new ( 0 ) ;
if ( ! e ) return - 1 ;
if ( ! e ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " rp_send_msg: queue_entry_new failed subcmd=%02x sid=%08x " , subcmd , sid ) ; return - 1 ; }
e - > dgram = u_malloc ( TCP_PROXY_HDR_SIZE + len ) ;
e - > dgram = u_malloc ( TCP_PROXY_HDR_SIZE + len ) ;
if ( ! e - > dgram ) { queue_entry_free ( e ) ; return - 1 ; }
if ( ! e - > dgram ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " rp_send_msg: malloc(%zu) failed subcmd=%02x sid=%08x " , TCP_PROXY_HDR_SIZE + len , subcmd , sid ) ; queue_entry_free ( e ) ; return - 1 ; }
e - > dgram [ 0 ] = ETCP_ID_TCP_PROXY ;
e - > dgram [ 0 ] = ETCP_ID_TCP_PROXY ;
e - > dgram [ 1 ] = subcmd ;
e - > dgram [ 1 ] = subcmd ;
memcpy ( e - > dgram + 2 , & sid , 8 ) ;
memcpy ( e - > dgram + 2 , & sid , 4 ) ;
memcpy ( e - > dgram + 10 , & seq , 2 ) ;
memcpy ( e - > dgram + 6 , & seq , 2 ) ;
if ( len > 0 ) memcpy ( e - > dgram + TCP_PROXY_HDR_SIZE , data , len ) ;
if ( len > 0 ) memcpy ( e - > dgram + TCP_PROXY_HDR_SIZE , data , len ) ;
e - > len = TCP_PROXY_HDR_SIZE + len ;
e - > len = TCP_PROXY_HDR_SIZE + len ;
return etcp_route_send ( inst , dst , e ) ;
return etcp_route_send ( inst , dst , e ) ;
}
}
static int rp_send_connected ( struct UTUN_INSTANCE * inst , uint64_t dst , uint64 _t sid ,
static int rp_send_connected ( struct UTUN_INSTANCE * inst , uint64_t dst , uint32 _t sid ,
uint16_t local_port , uint8_t status ) {
uint16_t local_port , uint8_t status ) {
uint8_t buf [ 3 ] ;
uint8_t buf [ 3 ] ;
memcpy ( buf , & local_port , 2 ) ; buf [ 2 ] = status ;
memcpy ( buf , & local_port , 2 ) ; buf [ 2 ] = status ;
return rp_send_msg ( inst , dst , TCP_PROXY_SUBCMD_CONNECTED , sid , 0 , buf , 3 ) ;
return rp_send_msg ( inst , dst , TCP_PROXY_SUBCMD_CONNECTED , sid , 0 , buf , 3 ) ;
}
}
// ====================================================================
// Socket event logging helper
// ====================================================================
static int rp_conn_total ( struct remote_proxy_conn * rc ) {
static int rp_conn_total ( struct remote_proxy_conn * rc ) {
if ( ! rc | | ! rc - > ctx ) return 0 ;
if ( ! rc | | ! rc - > ctx ) return 0 ;
int n = 0 ; struct remote_proxy_conn * c ;
int n = 0 ; struct remote_proxy_conn * c ;
@ -69,64 +67,76 @@ static int rp_conn_total(struct remote_proxy_conn* rc) {
// ====================================================================
// ====================================================================
static void rp_sock_read_cb ( socket_t sock , void * arg ) {
static void rp_sock_read_cb ( socket_t sock , void * arg ) {
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " RP rp_sock_read_cb: rc=%p sock=%d " , ( void * ) rc , rc ? ( int ) rc - > sock : - 1 ) ; return ; }
if ( ! rc | | rc - > sock = = SOCKET_INVALID ) return ;
uint8_t buf [ 8192 ] ; ssize_t n = recv ( rc - > sock , buf , sizeof ( buf ) , 0 ) ;
uint8_t buf [ 8192 ] ; ssize_t n = recv ( rc - > sock , buf , sizeof ( buf ) , 0 ) ;
if ( n > 0 ) {
if ( n > 0 ) {
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:RECV fd=%d stream=%016llx len=%zd total=%d " , ( int ) rc - > sock , ( unsigned long long ) rc - > stream_id , n , rp_conn_total ( rc ) ) ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
if ( inst ) {
if ( ! inst ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:RECV fd=%d sid=%08x — inst is NULL, drop " , ( int ) rc - > sock , rc - > stream_id ) ; return ; }
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:RECV fd=%d sid=%08x len=%zd total=%d " , ( int ) rc - > sock , rc - > stream_id , n , rp_conn_total ( rc ) ) ;
if ( ! rc - > error ) {
rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_DATA , rc - > stream_id , rc - > send_seq , buf , ( size_t ) n ) ;
rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_DATA , rc - > stream_id , rc - > send_seq , buf , ( size_t ) n ) ;
rc - > send_seq + + ;
rc - > send_seq + + ;
}
}
} else {
} else if ( n = = 0 ) {
if ( n = = 0 ) DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " remote_proxy: EOF stream=%016llx " , ( unsigned long long ) rc - > stream_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:EOF fd=%d sid=%08x total=%d cli_closed=%d sock_closed=%d " ,
else DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: recv error %s " , strerror ( errno ) ) ;
( int ) rc - > sock , rc - > stream_id , rp_conn_total ( rc ) , rc - > cli_closed , rc - > sock_closed ) ;
rc - > sock_closed = 1 ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
if ( inst ) rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_CLOSE , rc - > stream_id , 0 , NULL , 0 ) ;
if ( inst ) rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_CLOSE , rc - > stream_id , 0 , NULL , 0 ) ;
rc - > connected = - 1 ;
else DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:EOF fd=%d sid=%08x — inst is NULL, can't send CLOSE " , ( int ) rc - > sock , rc - > stream_id ) ;
if ( rc - > read_id ) { uasync_remove_socket_t ( rc - > ua , rc - > sock ) ; rc - > read_id = NULL ; }
if ( rc - > cli_closed ) rp_conn_free ( rc ) ;
} else if ( errno ! = EAGAIN & & errno ! = EWOULDBLOCK & & errno ! = EINTR ) {
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:ERROR fd=%d sid=%08x errno=%d %s total=%d " ,
( int ) rc - > sock , rc - > stream_id , errno , strerror ( errno ) , rp_conn_total ( rc ) ) ;
rc - > error = 1 ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
if ( inst ) rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_ERROR , rc - > stream_id , 0 , NULL , 0 ) ;
else DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:ERROR fd=%d sid=%08x — inst is NULL, can't send ERROR " , ( int ) rc - > sock , rc - > stream_id ) ;
rp_conn_free ( rc ) ;
rp_conn_free ( rc ) ;
}
}
}
}
static void rp_sock_write_cb ( socket_t sock , void * arg ) {
static void rp_sock_write_cb ( socket_t sock , void * arg ) {
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID ) return ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID | | rc - > connected ) return ;
if ( ! rc - > connected ) {
int err = 0 ; socklen_t len = sizeof ( err ) ;
if ( ! rc - > connect_called ) return ;
if ( getsockopt ( rc - > sock , SOL_SOCKET , SO_ERROR , & err , & len ) = = 0 & & err = = 0 ) {
int err = 0 ; socklen_t len = sizeof ( err ) ;
rc - > connected = 1 ;
if ( getsockopt ( rc - > sock , SOL_SOCKET , SO_ERROR , & err , & len ) = = 0 & & err = = 0 ) {
struct sockaddr_in local ; socklen_t llen = sizeof ( local ) ;
rc - > connected = 1 ;
uint16_t local_port = 0 ;
struct sockaddr_in local ; socklen_t llen = sizeof ( local ) ;
if ( getsockname ( rc - > sock , ( struct sockaddr * ) & local , & llen ) = = 0 ) local_port = local . sin_port ;
uint16_t local_port = 0 ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:CONN fd=%d sid=%08x local=%d dest=%d.%d.%d.%d:%d total=%d " ,
if ( getsockname ( rc - > sock , ( struct sockaddr * ) & local , & llen ) = = 0 ) local_port = local . sin_port ;
( int ) rc - > sock , rc - > stream_id , ntohs ( local_port ) ,
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:CONN fd=%d stream=%016llx local=%d dest=%d.%d.%d.%d:%d total=%d " ,
rc - > dest_ip [ 0 ] , rc - > dest_ip [ 1 ] , rc - > dest_ip [ 2 ] , rc - > dest_ip [ 3 ] , ntohs ( rc - > dest_port ) ,
( int ) rc - > sock , ( unsigned long long ) rc - > stream_id , ntohs ( local_port ) ,
rp_conn_total ( rc ) ) ;
rc - > dest_ip [ 0 ] , rc - > dest_ip [ 1 ] , rc - > dest_ip [ 2 ] , rc - > dest_ip [ 3 ] , ntohs ( rc - > dest_port ) ,
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
rp_conn_total ( rc ) ) ;
if ( inst ) rp_send_connected ( inst , rc - > peer_node_id , rc - > stream_id , local_port , TCP_PROXY_CONNECTED_OK ) ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
} else {
if ( inst ) rp_send_connected ( inst , rc - > peer_node_id , rc - > stream_id , local_port , TCP_PROXY_CONNECTED_OK ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:FAIL fd=%d sid=%08x err=%d %s " ,
} else {
( int ) rc - > sock , rc - > stream_id , err , err ? strerror ( err ) : " unknown " ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: connect failed %s " , err ? strerror ( err ) : " unknown " ) ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
if ( inst ) rp_send_connected ( inst , rc - > peer_node_id , rc - > stream_id , 0 , TCP_PROXY_CONNECTED_REFUSED ) ;
if ( inst ) rp_send_connected ( inst , rc - > peer_node_id , rc - > stream_id , 0 , TCP_PROXY_CONNECTED_REFUSED ) ;
rp_conn_free ( rc ) ;
rc - > connected = - 1 ;
rp_conn_free ( rc ) ;
}
}
}
}
}
static void rp_sock_error_cb ( socket_t sock , void * arg ) {
static void rp_sock_error_cb ( socket_t sock , void * arg ) {
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
( void ) sock ; struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID ) return ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID ) return ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: socket error stream=%016ll x" , ( unsigned long long ) ( rc ? rc - > stream_id : 0 ) ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:ERR fd=%d sid=%08 x" , ( int ) rc - > sock , rc - > stream_id ) ;
rc - > connected = - 1 ;
rc - > error = 1 ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
struct UTUN_INSTANCE * inst = rc - > ctx ? rc - > ctx - > inst : NULL ;
if ( inst ) rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_CLOSE , rc - > stream_id , 0 , NULL , 0 ) ;
if ( inst ) rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_ERROR , rc - > stream_id , 0 , NULL , 0 ) ;
else DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " SOCK:ERR fd=%d sid=%08x — inst is NULL " , ( int ) rc - > sock , rc - > stream_id ) ;
rp_conn_free ( rc ) ;
rp_conn_free ( rc ) ;
}
}
static void rp_conn_free ( struct remote_proxy_conn * rc ) {
void rp_conn_free ( struct remote_proxy_conn * rc ) {
if ( ! rc ) return ;
if ( ! rc ) return ;
int total = rp_conn_total ( rc ) ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:FREE fd=%d sid=%08x total=%d cli_closed=%d sock_closed=%d error=%d " ,
( int ) rc - > sock , rc - > stream_id , total , rc - > cli_closed , rc - > sock_closed , rc - > error ) ;
if ( rc - > ctx ) {
if ( rc - > ctx ) {
struct remote_proxy_conn * * prev = & rc - > ctx - > conns ;
struct remote_proxy_conn * * prev = & rc - > ctx - > conns ;
while ( * prev ) { if ( * prev = = rc ) { * prev = rc - > next ; rc - > ctx - > conn_count - - ; break ; } prev = & ( * prev ) - > next ; }
while ( * prev ) { if ( * prev = = rc ) { * prev = rc - > next ; rc - > ctx - > conn_count - - ; break ; } prev = & ( * prev ) - > next ; }
@ -138,65 +148,47 @@ static void rp_conn_free(struct remote_proxy_conn* rc) {
u_free ( rc ) ;
u_free ( rc ) ;
}
}
// ====================================================================
// Standalone handler (registered when tcp_proxy doesn't have remote mappings)
// ====================================================================
static void rp_standalone_recv_cb ( struct ETCP_CONN * conn , struct ll_entry * entry ) {
struct UTUN_INSTANCE * i = conn ? conn - > instance : ( g_rp_ctx ? g_rp_ctx - > inst : NULL ) ;
if ( ! i | | ! entry | | entry - > dgram = = NULL | | entry - > len < TCP_PROXY_HDR_SIZE ) {
if ( entry ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; }
return ;
}
uint8_t subcmd = entry - > dgram [ 1 ] ;
uint64_t sid = 0 ; memcpy ( & sid , entry - > dgram + 2 , 8 ) ;
uint64_t src = conn ? conn - > peer_node_id : i - > node_id ;
if ( subcmd = = TCP_PROXY_SUBCMD_CONNECT ) { remote_proxy_handle_connect ( i , entry , sid , src ) ; return ; }
if ( subcmd = = TCP_PROXY_SUBCMD_DATA ) { remote_proxy_handle_data ( i , entry , sid ) ; return ; }
if ( subcmd = = TCP_PROXY_SUBCMD_CLOSE ) { remote_proxy_handle_close ( i , sid ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return ; }
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ;
}
// ====================================================================
// ====================================================================
// Public API
// Public API
// ====================================================================
// ====================================================================
struct remote_proxy_conn * remote_proxy_find_conn ( struct remote_proxy_ctx * ctx , uint64 _t stream_id ) {
struct remote_proxy_conn * remote_proxy_find_conn ( struct remote_proxy_ctx * ctx , uint32_t stream_id ) {
struct remote_proxy_conn * c ;
struct remote_proxy_conn * c ;
for ( c = ctx - > conns ; c ; c = c - > next ) if ( c - > stream_id = = stream_id ) return c ;
for ( c = ctx - > conns ; c ; c = c - > next ) if ( c - > stream_id = = stream_id ) return c ;
return NULL ;
return NULL ;
}
}
int remote_proxy_handle_connect ( struct UTUN_INSTANCE * inst , struct ll_entry * entry ,
int remote_proxy_handle_connect ( struct UTUN_INSTANCE * inst , struct ll_entry * entry ,
uint64 _t stream_id , uint64_t src_node_id ) {
uint32_t stream_id , uint64_t src_node_id ) {
if ( ! inst | | ! inst - > remote_proxy . enabled ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( ! inst | | ! inst - > remote_proxy . enabled ) { if ( entry ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; } return - 1 ; }
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
if ( entry - > len < TCP_PROXY_CONNECT_HDR_SIZE ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( entry - > len < TCP_PROXY_CONNECT_HDR_SIZE ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: CONNECT too short len=%u " , entry - > len ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
uint8_t * dest_ip = entry - > dgram + TCP_PROXY_HDR_SIZE ;
uint8_t * dest_ip = entry - > dgram + TCP_PROXY_HDR_SIZE ;
uint16_t dest_port = 0 ; memcpy ( & dest_port , dest_ip + 4 , 2 ) ;
uint16_t dest_port = 0 ; memcpy ( & dest_port , dest_ip + 4 , 2 ) ;
struct remote_proxy_conn * rc = u_calloc ( 1 , sizeof ( struct remote_proxy_conn ) ) ;
struct remote_proxy_conn * rc = u_calloc ( 1 , sizeof ( struct remote_proxy_conn ) ) ;
if ( ! rc ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( ! rc ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: u_calloc failed for sid=%08x " , stream_id ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
rc - > ctx = ctx ; rc - > stream_id = stream_id ; rc - > peer_node_id = src_node_id ;
rc - > ctx = ctx ; rc - > stream_id = stream_id ; rc - > peer_node_id = src_node_id ;
memcpy ( rc - > dest_ip , dest_ip , 4 ) ; rc - > dest_port = dest_port ;
memcpy ( rc - > dest_ip , dest_ip , 4 ) ; rc - > dest_port = dest_port ;
rc - > ua = inst - > ua ; rc - > sock = SOCKET_INVALID ;
rc - > ua = inst - > ua ; rc - > sock = SOCKET_INVALID ;
rc - > send_seq = 0 ; rc - > recv_seq_init = 0 ;
rc - > sock = socket ( AF_INET , SOCK_STREAM , 0 ) ;
rc - > sock = socket ( AF_INET , SOCK_STREAM , 0 ) ;
if ( rc - > sock = = SOCKET_INVALID ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: socket() failed " ) ; rp_conn _free( rc ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( rc - > sock = = SOCKET_INVALID ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: socket() failed " ) ; u _free( rc ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
ctx - > conn_count + + ;
ctx - > conn_count + + ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:NEW fd=%d stream=%016ll x dest=%d.%d.%d.%d:%d total=%d " , ( int ) rc - > sock , ( unsigned long long ) stream_id ,
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:NEW fd=%d sid=%08 x dest=%d.%d.%d.%d:%d total=%d " ,
dest_ip [ 0 ] , dest_ip [ 1 ] , dest_ip [ 2 ] , dest_ip [ 3 ] , ntohs ( dest_port ) , ctx - > conn_count ) ;
( int ) rc - > sock , stream_id , dest_ip [ 0 ] , dest_ip [ 1 ] , dest_ip [ 2 ] , dest_ip [ 3 ] , ntohs ( dest_port ) , ctx - > conn_count ) ;
socket_set_nonblocking ( rc - > sock ) ;
socket_set_nonblocking ( rc - > sock ) ;
rc - > read_id = uasync_add_socket_t ( rc - > ua , rc - > sock , rp_sock_read_cb , rp_sock_write_cb , rp_sock_error_cb , rc ) ;
rc - > read_id = uasync_add_socket_t ( rc - > ua , rc - > sock , rp_sock_read_cb , rp_sock_write_cb , rp_sock_error_cb , rc ) ;
if ( ! rc - > read_id ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: uasync_add_socket_t failed " ) ; rp_conn _free( rc ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( ! rc - > read_id ) { DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: uasync_add_socket_t failed " ) ; u _free( rc ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
struct sockaddr_in addr ; memset ( & addr , 0 , sizeof ( addr ) ) ;
struct sockaddr_in addr ; memset ( & addr , 0 , sizeof ( addr ) ) ;
addr . sin_family = AF_INET ; memcpy ( & addr . sin_addr . s_addr , dest_ip , 4 ) ; addr . sin_port = dest_port ;
addr . sin_family = AF_INET ; memcpy ( & addr . sin_addr . s_addr , dest_ip , 4 ) ; addr . sin_port = dest_port ;
rc - > connect_called = 1 ;
int ret = connect ( rc - > sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) ;
int ret = connect ( rc - > sock , ( struct sockaddr * ) & addr , sizeof ( addr ) ) ;
if ( ret < 0 & & errno ! = EINPROGRESS ) {
if ( ret < 0 & & errno ! = EINPROGRESS ) {
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: connect() failed: %s " , strerror ( errno ) ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: connect() to %d.%d.%d.%d:%d failed: %s " ,
dest_ip [ 0 ] , dest_ip [ 1 ] , dest_ip [ 2 ] , dest_ip [ 3 ] , ntohs ( dest_port ) , strerror ( errno ) ) ;
rp_send_connected ( inst , src_node_id , stream_id , 0 , TCP_PROXY_CONNECTED_REFUSED ) ;
rp_send_connected ( inst , src_node_id , stream_id , 0 , TCP_PROXY_CONNECTED_REFUSED ) ;
rp_conn_free ( rc ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ;
uasync_remove_socket_t ( rc - > ua , rc - > sock ) ; socket_close_wrapper ( rc - > sock ) ; u_free ( rc ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ;
}
}
rc - > next = ctx - > conns ; ctx - > conns = rc ;
rc - > next = ctx - > conns ; ctx - > conns = rc ;
@ -204,90 +196,86 @@ int remote_proxy_handle_connect(struct UTUN_INSTANCE* inst, struct ll_entry* ent
return 0 ;
return 0 ;
}
}
int remote_proxy_handle_data ( struct UTUN_INSTANCE * inst , struct ll_entry * entry , uint64 _t stream_id ) {
int remote_proxy_handle_data ( struct UTUN_INSTANCE * inst , struct ll_entry * entry , uint32 _t stream_id ) {
if ( ! inst ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
if ( ! inst ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_conn * rc = remote_proxy_find_conn ( ctx , stream_id ) ;
struct remote_proxy_conn * rc = remote_proxy_find_conn ( ctx , stream_id ) ;
if ( ! rc | | rc - > sock = = SOCKET_INVALID | | rc - > connected ! = 1 ) {
if ( ! rc | | rc - > sock = = SOCKET_INVALID | | rc - > connected ! = 1 ) { DEBUG_WARN ( DEBUG_CATEGORY_SOCKET , " RP handle_data drop: no active conn for sid=%08x " , stream_id ) ; queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " RP handle_data drop: rc=%p stream=%016llx sock=%d connected=%d " ,
if ( rc - > error ) { queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ; }
( void * ) rc , ( unsigned long long ) stream_id , rc ? ( int ) rc - > sock : - 1 , rc ? rc - > connected : - 1 ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ;
uint16_t seq ; memcpy ( & seq , entry - > dgram + 6 , 2 ) ;
}
if ( ! rc - > recv_init ) {
uint16_t seq ; memcpy ( & seq , entry - > dgram + 10 , 2 ) ;
rc - > recv_last_seq = seq ; rc - > recv_init = 1 ;
if ( ! rc - > recv_seq_init ) {
rc - > recv_last_seq = seq ; rc - > recv_seq_init = 1 ;
} else {
} else {
int16_t delta = ( int16_t ) ( seq - rc - > recv_last_seq ) ;
uint16_t delta = seq - rc - > recv_last_seq ;
if ( delta < = 0 ) {
if ( delta = = 0 ) {
DEBUG_WARN ( DEBUG_CATEGORY_SOCKET , " remote_proxy: duplicate DATA seq=%u stream=%016llx, discard " , seq , ( unsigned long long ) stream_id ) ;
DEBUG_WARN ( DEBUG_CATEGORY_SOCKET , " remote_proxy: duplicate DATA seq=%u sid=%08x " , seq , stream_id ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return 0 ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return 0 ;
}
}
if ( delta > 1 ) {
if ( delta ! = 1 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: seq gap seq=%u last=%u stream=%016llx, tearing down " , seq , rc - > recv_last_seq , ( unsigned long long ) stream_id ) ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: seq gap seq=%u last=%u sid=%08x " , seq , rc - > recv_last_seq , stream_id ) ;
rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_CLOSE , rc - > stream_id , 0 , NULL , 0 ) ;
rc - > error = 1 ;
rp_send_msg ( inst , rc - > peer_node_id , TCP_PROXY_SUBCMD_ERROR , rc - > stream_id , 0 , NULL , 0 ) ;
rp_conn_free ( rc ) ;
rp_conn_free ( rc ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ; return - 1 ;
}
}
rc - > recv_last_seq = seq ;
rc - > recv_last_seq = seq ;
}
}
size_t data_len = entry - > len - TCP_PROXY_HDR_SIZE ;
size_t data_len = entry - > len - TCP_PROXY_HDR_SIZE ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:SEND fd=%d stream=%016llx len=%zu total=%d " , ( int ) rc - > sock , ( unsigned long long ) stream_id , data_len , rp_conn_total ( rc ) ) ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:SEND fd=%d sid=%08x len=%zu total=%d " ,
uint8_t * data = entry - > dgram + TCP_PROXY_HDR_SIZE ;
( int ) rc - > sock , stream_id , data_len , rp_conn_total ( rc ) ) ;
ssize_t n = send ( rc - > sock , data , data_len , MSG_NOSIGNAL ) ;
if ( data_len > 0 ) {
if ( n < 0 & & errno ! = EAGAIN & & errno ! = EWOULDBLOCK ) {
uint8_t * data = entry - > dgram + TCP_PROXY_HDR_SIZE ;
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: send error %s " , strerror ( errno ) ) ;
ssize_t n = send ( rc - > sock , data , data_len , MSG_NOSIGNAL ) ;
if ( n < 0 & & errno ! = EAGAIN & & errno ! = EWOULDBLOCK ) {
DEBUG_ERROR ( DEBUG_CATEGORY_SOCKET , " remote_proxy: send error %s " , strerror ( errno ) ) ;
}
}
}
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ;
queue_dgram_free ( entry ) ; queue_entry_free ( entry ) ;
return 0 ;
return 0 ;
}
}
static void rp_close_timer_cb ( void * arg ) {
void remote_proxy_handle_close ( struct UTUN_INSTANCE * inst , uint32_t stream_id ) {
struct remote_proxy_conn * rc = ( struct remote_proxy_conn * ) arg ;
if ( ! rc | | rc - > connected = = - 1 ) return ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:TIMER stream=%016llx total=%d " , ( unsigned long long ) rc - > stream_id , rp_conn_total ( rc ) ) ;
rp_conn_free ( rc ) ;
}
void remote_proxy_handle_close ( struct UTUN_INSTANCE * inst , uint64_t stream_id ) {
if ( ! inst ) return ;
if ( ! inst ) return ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_conn * * prev = & ctx - > conns ;
struct remote_proxy_conn * * prev = & ctx - > conns ;
while ( * prev ) {
while ( * prev ) {
struct remote_proxy_conn * rc = * prev ;
struct remote_proxy_conn * rc = * prev ;
if ( rc - > stream_id = = stream_id ) {
if ( rc - > stream_id = = stream_id ) {
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:CLOSE fd=%d stream=%016llx total=%d " , ( int ) rc - > sock , ( unsigned long long ) stream_id , rp_conn_total ( rc ) ) ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " SOCK:CLOSE_RECV fd=%d sid=%08x total=%d sock_closed=%d connected=%d " ,
* prev = rc - > next ;
( int ) rc - > sock , stream_id , rp_conn_total ( rc ) , rc - > sock_closed , rc - > connected ) ;
rc - > cli_closed = 1 ;
if ( rc - > sock ! = SOCKET_INVALID & & rc - > connected = = 1 ) shutdown ( rc - > sock , SHUT_WR ) ;
if ( rc - > sock ! = SOCKET_INVALID & & rc - > connected = = 1 ) shutdown ( rc - > sock , SHUT_WR ) ;
if ( rc - > read_id ) { uasync_remove_socket_t ( rc - > ua , rc - > sock ) ; rc - > read_id = NULL ; }
if ( rc - > sock_closed ) rp_conn_free ( rc ) ;
uasync_set_timeout ( rc - > ua , 20000 , rc , rp_close_timer_cb , " rp_close " ) ;
return ;
return ;
}
}
prev = & rc - > next ;
prev = & rc - > next ;
}
}
DEBUG_WARN ( DEBUG_CATEGORY_SOCKET , " remote_proxy: CLOSE sid=%08x — no conn " , stream_id ) ;
}
}
int remote_proxy_init ( struct UTUN_INSTANCE * inst ) {
int remote_proxy_init ( struct UTUN_INSTANCE * inst ) {
if ( ! inst ) return - 1 ;
if ( ! inst ) return - 1 ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
memset ( ctx , 0 , sizeof ( * ctx ) ) ;
memset ( ctx , 0 , sizeof ( * ctx ) ) ;
ctx - > enabled = inst - > config & & inst - > config - > global . remote_proxy_enabled ;
if ( ! inst - > config ) return 0 ;
ctx - > enabled = inst - > config - > global . remote_proxy_enabled ;
ctx - > inst = inst ;
ctx - > inst = inst ;
if ( ! ctx - > enabled ) return 0 ;
if ( ! ctx - > enabled ) return 0 ;
g_rp_ctx = ctx ;
g_rp_ctx = ctx ;
// Register standalone handler for when tcp_proxy is not using remote mappings
etcp_router_bind ( inst , ETCP_ID_TCP_PROXY , tcp_proxy_etcp_recv_cb ) ;
// (tcp_proxy_create will overwrite this handler if it has remote mappings)
if ( ! inst - > config - > global . tcp_proxy_enabled ) {
etcp_router_bind ( inst , ETCP_ID_TCP_PROXY , rp_standalone_recv_cb ) ;
if ( ! inst - > config | | ! inst - > config - > global . tcp_proxy_enabled ) {
udp_proxy_init ( inst , inst - > ua ) ;
udp_proxy_init ( inst , inst - > ua ) ;
icmp_proxy_init ( inst , inst - > ua ) ;
icmp_proxy_init ( inst , inst - > ua ) ;
}
}
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " remote_proxy initialized on node %016llx " , ( unsigned long long ) inst - > node_id ) ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " remote_proxy initialized node= %016llx " , ( unsigned long long ) inst - > node_id ) ;
return 0 ;
return 0 ;
}
}
void remote_proxy_destroy ( struct UTUN_INSTANCE * inst ) {
void remote_proxy_destroy ( struct UTUN_INSTANCE * inst ) {
if ( ! inst ) return ;
if ( ! inst ) return ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
struct remote_proxy_ctx * ctx = & inst - > remote_proxy ;
DEBUG_INFO ( DEBUG_CATEGORY_SOCKET , " remote_proxy destroying: conn_count=%d " , ctx - > conn_count ) ;
struct remote_proxy_conn * rc = ctx - > conns ;
struct remote_proxy_conn * rc = ctx - > conns ;
while ( rc ) { struct remote_proxy_conn * next = rc - > next ; rp_conn_free ( rc ) ; rc = next ; }
while ( rc ) { struct remote_proxy_conn * next = rc - > next ; rp_conn_free ( rc ) ; rc = next ; }
ctx - > conns = NULL ; ctx - > enabled = 0 ;
ctx - > conns = NULL ; ctx - > enabled = 0 ;