@ -10,6 +10,8 @@
# include <stdio.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdlib.h>
# include <string.h>
# include <string.h>
# include <errno.h>
# include <sys/socket.h>
# include "../lib/mem.h"
# include "../lib/mem.h"
# ifdef _WIN32
# ifdef _WIN32
@ -126,6 +128,7 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config)
tun - > ua = ua ;
tun - > ua = ua ;
tun - > test_mode = test_mode ;
tun - > test_mode = test_mode ;
tun - > fd = - 1 ;
tun - > fd = - 1 ;
tun - > test_fd = - 1 ;
const char * name = config - > global . tun_ifname ;
const char * name = config - > global . tun_ifname ;
if ( name & & name [ 0 ] ) strncpy ( tun - > ifname , name , sizeof ( tun - > ifname ) - 1 ) ;
if ( name & & name [ 0 ] ) strncpy ( tun - > ifname , name , sizeof ( tun - > ifname ) - 1 ) ;
@ -145,8 +148,16 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config)
u_free ( tun ) ;
u_free ( tun ) ;
return NULL ;
return NULL ;
}
}
} else if ( tun - > ifname [ 0 ] = = ' \0 ' ) {
} else {
strncpy ( tun - > ifname , " tun_test " , sizeof ( tun - > ifname ) - 1 ) ;
if ( tun - > ifname [ 0 ] = = ' \0 ' ) strncpy ( tun - > ifname , " tun_test " , sizeof ( tun - > ifname ) - 1 ) ;
int fds [ 2 ] ;
if ( socketpair ( AF_UNIX , SOCK_DGRAM , 0 , fds ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " TUN %s test_mode socketpair failed: %s " , tun - > ifname , strerror ( errno ) ) ;
u_free ( tun ) ;
return NULL ;
}
tun - > fd = fds [ 0 ] ;
tun - > test_fd = fds [ 1 ] ;
}
}
tun - > pool = memory_pool_init ( sizeof ( struct ll_entry ) ) ;
tun - > pool = memory_pool_init ( sizeof ( struct ll_entry ) ) ;
@ -158,36 +169,37 @@ struct tun_if* tun_init(struct UASYNC* ua, struct utun_config* config)
queue_set_callback ( tun - > input_queue , tun_input_queue_callback , tun ) ;
queue_set_callback ( tun - > input_queue , tun_input_queue_callback , tun ) ;
if ( ! test_mode ) {
int poll_fd = tun_platform_get_poll_fd ( tun ) ;
if ( poll_fd > = 0 ) {
# ifndef _WIN32
# ifndef _WIN32
// ==================== LINUX ====================
{
int poll_fd = test_mode ? tun - > fd : tun_platform_get_poll_fd ( tun ) ;
if ( poll_fd > = 0 ) {
tun - > socket_id = uasync_add_socket ( ua , poll_fd , tun_read_callback , NULL , NULL , tun ) ;
tun - > socket_id = uasync_add_socket ( ua , poll_fd , tun_read_callback , NULL , NULL , tun ) ;
if ( ! tun - > socket_id ) goto fail ;
if ( ! tun - > socket_id ) goto fail ;
}
}
# endif
# endif
} else {
# ifdef _WIN32
# ifdef _WIN32
// ==================== WINDOWS ====================
if ( ! test_mode ) {
int poll_fd = tun_platform_get_poll_fd ( tun ) ;
if ( poll_fd < 0 ) {
tun - > running = 1 ;
tun - > running = 1 ;
tun - > stop_event = CreateEvent ( NULL , TRUE , FALSE , NULL ) ;
tun - > stop_event = CreateEvent ( NULL , TRUE , FALSE , NULL ) ;
if ( ! tun - > stop_event ) goto fail ;
if ( ! tun - > stop_event ) goto fail ;
tun - > read_thread = CreateThread ( NULL , 0 , tun_read_thread_proc , tun , 0 , NULL ) ;
tun - > read_thread = CreateThread ( NULL , 0 , tun_read_thread_proc , tun , 0 , NULL ) ;
if ( ! tun - > read_thread ) {
if ( ! tun - > read_thread ) {
CloseHandle ( tun - > stop_event ) ;
CloseHandle ( tun - > stop_event ) ;
goto fail ;
goto fail ;
}
}
# endif
}
}
}
}
# endif
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " TUN %s initialized (%s mode) " , tun - > ifname ,
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " TUN %s initialized (%s mode) " , tun - > ifname ,
test_mode ? " TEST " : " REAL " ) ;
test_mode ? " TEST " : " REAL " ) ;
return tun ;
return tun ;
fail :
fail :
if ( tun - > test_fd > = 0 ) { close ( tun - > test_fd ) ; tun - > test_fd = - 1 ; }
# ifdef _WIN32
# ifdef _WIN32
if ( tun - > stop_event ) CloseHandle ( tun - > stop_event ) ;
if ( tun - > stop_event ) CloseHandle ( tun - > stop_event ) ;
if ( tun - > read_thread ) {
if ( tun - > read_thread ) {
@ -218,6 +230,7 @@ struct tun_if* tun_init_nat(struct UASYNC* ua, const char* ifname, const char* i
tun - > ua = ua ;
tun - > ua = ua ;
tun - > test_mode = test_mode ;
tun - > test_mode = test_mode ;
tun - > fd = - 1 ;
tun - > fd = - 1 ;
tun - > test_fd = - 1 ;
strncpy ( tun - > ifname , ifname , sizeof ( tun - > ifname ) - 1 ) ;
strncpy ( tun - > ifname , ifname , sizeof ( tun - > ifname ) - 1 ) ;
char ip_str [ 64 ] ;
char ip_str [ 64 ] ;
@ -228,6 +241,15 @@ struct tun_if* tun_init_nat(struct UASYNC* ua, const char* ifname, const char* i
u_free ( tun ) ;
u_free ( tun ) ;
return NULL ;
return NULL ;
}
}
} else {
int fds [ 2 ] ;
if ( socketpair ( AF_UNIX , SOCK_DGRAM , 0 , fds ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " NAT TUN %s test_mode socketpair failed: %s " , tun - > ifname , strerror ( errno ) ) ;
u_free ( tun ) ;
return NULL ;
}
tun - > fd = fds [ 0 ] ;
tun - > test_fd = fds [ 1 ] ;
}
}
tun - > pool = memory_pool_init ( sizeof ( struct ll_entry ) ) ;
tun - > pool = memory_pool_init ( sizeof ( struct ll_entry ) ) ;
@ -239,21 +261,22 @@ struct tun_if* tun_init_nat(struct UASYNC* ua, const char* ifname, const char* i
queue_set_callback ( tun - > input_queue , tun_input_queue_callback , tun ) ;
queue_set_callback ( tun - > input_queue , tun_input_queue_callback , tun ) ;
if ( ! test_mode ) {
int poll_fd = tun_platform_get_poll_fd ( tun ) ;
if ( poll_fd > = 0 ) {
# ifndef _WIN32
# ifndef _WIN32
{
int poll_fd = test_mode ? tun - > fd : tun_platform_get_poll_fd ( tun ) ;
if ( poll_fd > = 0 ) {
tun - > socket_id = uasync_add_socket ( ua , poll_fd , tun_read_callback , NULL , NULL , tun ) ;
tun - > socket_id = uasync_add_socket ( ua , poll_fd , tun_read_callback , NULL , NULL , tun ) ;
if ( ! tun - > socket_id ) goto fail2 ;
if ( ! tun - > socket_id ) goto fail2 ;
# endif
}
}
}
}
# endif
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " NAT TUN %s initialized (%s mode) " , tun - > ifname ,
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " NAT TUN %s initialized (%s mode) " , tun - > ifname ,
test_mode ? " TEST " : " REAL " ) ;
test_mode ? " TEST " : " REAL " ) ;
return tun ;
return tun ;
fail2 :
fail2 :
if ( tun - > test_fd > = 0 ) { close ( tun - > test_fd ) ; tun - > test_fd = - 1 ; }
if ( tun - > output_queue ) queue_free ( tun - > output_queue ) ;
if ( tun - > output_queue ) queue_free ( tun - > output_queue ) ;
if ( tun - > input_queue ) queue_free ( tun - > input_queue ) ;
if ( tun - > input_queue ) queue_free ( tun - > input_queue ) ;
if ( tun - > pool ) memory_pool_destroy ( tun - > pool ) ;
if ( tun - > pool ) memory_pool_destroy ( tun - > pool ) ;
@ -283,6 +306,8 @@ void tun_close(struct tun_if* tun)
uasync_remove_socket ( tun - > ua , tun - > socket_id ) ;
uasync_remove_socket ( tun - > ua , tun - > socket_id ) ;
}
}
if ( tun - > test_fd > = 0 ) { close ( tun - > test_fd ) ; tun - > test_fd = - 1 ; }
struct ll_entry * pkt ;
struct ll_entry * pkt ;
while ( ( pkt = queue_data_get ( tun - > input_queue ) ) ! = NULL ) {
while ( ( pkt = queue_data_get ( tun - > input_queue ) ) ! = NULL ) {
queue_dgram_free ( pkt ) ;
queue_dgram_free ( pkt ) ;
@ -306,11 +331,9 @@ ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len)
if ( ! tun | | ! buf | | len < = 1 ) return - 1 ;
if ( ! tun | | ! buf | | len < = 1 ) return - 1 ;
if ( tun - > test_mode ) {
if ( tun - > test_mode ) {
// Skip prefix byte for test mode injection
return tun_inject_packet ( tun , buf + 1 , len - 1 ) = = 0 ? ( ssize_t ) ( len - 1 ) : - 1 ;
return tun_inject_packet ( tun , buf + 1 , len - 1 ) = = 0 ? ( ssize_t ) ( len - 1 ) : - 1 ;
}
}
// Skip prefix byte, write from second byte
ssize_t n = tun_platform_write ( tun , buf + 1 , len - 1 ) ;
ssize_t n = tun_platform_write ( tun , buf + 1 , len - 1 ) ;
if ( n > 0 ) {
if ( n > 0 ) {
tun - > bytes_written + = n ;
tun - > bytes_written + = n ;
@ -327,6 +350,7 @@ ssize_t tun_write(struct tun_if* tun, const uint8_t* buf, size_t len)
struct ll_queue * tun_get_input_queue ( struct tun_if * tun ) { return tun ? tun - > input_queue : NULL ; }
struct ll_queue * tun_get_input_queue ( struct tun_if * tun ) { return tun ? tun - > input_queue : NULL ; }
struct ll_queue * tun_get_output_queue ( struct tun_if * tun ) { return tun ? tun - > output_queue : NULL ; }
struct ll_queue * tun_get_output_queue ( struct tun_if * tun ) { return tun ? tun - > output_queue : NULL ; }
int tun_is_test_mode ( struct tun_if * tun ) { return tun ? tun - > test_mode : - 1 ; }
int tun_is_test_mode ( struct tun_if * tun ) { return tun ? tun - > test_mode : - 1 ; }
int tun_get_test_fd ( struct tun_if * tun ) { return tun ? tun - > test_fd : - 1 ; }
// ===================================================================
// ===================================================================
// Callback для обработки пакетов из TUN в main thread
// Callback для обработки пакетов из TUN в main thread
@ -364,10 +388,9 @@ int tun_inject_packet(struct tun_if* tun, const uint8_t* buf, size_t len)
{
{
if ( ! tun | | ! buf | | len = = 0 | | len > TUN_MAX_PACKET_SIZE ) return - 1 ;
if ( ! tun | | ! buf | | len = = 0 | | len > TUN_MAX_PACKET_SIZE ) return - 1 ;
// Allocate with +1 for prefix byte
uint8_t * data = u_malloc ( len + 1 ) ;
uint8_t * data = u_malloc ( len + 1 ) ;
if ( ! data ) { tun - > read_errors + + ; return - 1 ; }
if ( ! data ) { tun - > read_errors + + ; return - 1 ; }
data [ 0 ] = 0 ; // Prefix byte
data [ 0 ] = 0 ;
memcpy ( data + 1 , buf , len ) ;
memcpy ( data + 1 , buf , len ) ;
struct ll_entry * pkt = queue_entry_new_from_pool ( tun - > pool ) ;
struct ll_entry * pkt = queue_entry_new_from_pool ( tun - > pool ) ;
@ -402,7 +425,6 @@ ssize_t tun_read_packet(struct tun_if* tun, uint8_t* buf, size_t len)
return - 1 ;
return - 1 ;
}
}
// Add prefix byte at start
buf [ 0 ] = 0 ;
buf [ 0 ] = 0 ;
memcpy ( buf + 1 , pkt - > dgram , pkt - > len ) ;
memcpy ( buf + 1 , pkt - > dgram , pkt - > len ) ;
ssize_t ret = pkt - > len + 1 ;
ssize_t ret = pkt - > len + 1 ;