@ -4,7 +4,6 @@
# include "../lib/debug_config.h"
# include "../lib/u_async.h"
# include "etcp_connections.h"
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
@ -21,75 +20,81 @@
# include <linux/if_tun.h>
# include <errno.h>
// Helper for interface ioctl operations
static int if_ioctl ( const char * ifname , unsigned long request , struct ifreq * ifr ) {
int sock = socket ( AF_INET , SOCK_DGRAM , 0 ) ;
if ( sock < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to create ioctl socket: %s " , strerror ( errno ) ) ;
return - 1 ;
}
strncpy ( ifr - > ifr_name , ifname , IFNAMSIZ - 1 ) ;
ifr - > ifr_name [ IFNAMSIZ - 1 ] = ' \0 ' ;
int ret = ioctl ( sock , request , ifr ) ;
if ( ret < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " ioctl failed for %s (request=0x%lx): %s " , ifname , request , strerror ( errno ) ) ;
}
close ( sock ) ;
return ret ;
}
// Parse IP address and CIDR mask
static int parse_ip_mask ( const char * ip_addr , struct in_addr * ip , struct in_addr * netmask ) {
if ( ! ip_addr | | ! ip | | ! netmask ) return - 1 ;
char ip_str [ INET_ADDRSTRLEN ] ;
char * slash = strchr ( ip_addr , ' / ' ) ;
if ( ! slash ) return - 1 ; // Require /mask
size_t ip_len = slash - ip_addr ;
if ( ip_len > = sizeof ( ip_str ) ) return - 1 ;
strncpy ( ip_str , ip_addr , ip_len ) ;
ip_str [ ip_len ] = ' \0 ' ;
if ( inet_pton ( AF_INET , ip_str , ip ) < = 0 ) return - 1 ;
char * endptr ;
long cidr = strtol ( slash + 1 , & endptr , 10 ) ;
if ( * endptr ! = ' \0 ' | | cidr < 0 | | cidr > 32 ) return - 1 ;
uint32_t mask = ( cidr = = 0 ) ? 0 : ~ ( ( 1U < < ( 32 - cidr ) ) - 1 ) ;
netmask - > s_addr = htonl ( mask ) ;
return 0 ;
}
// Create TUN device
static int create_tun_device ( char * ifname , size_t ifname_len ) {
struct ifreq ifr ;
int fd ;
fd = open ( " /dev/net/tun " , O_RDWR ) ;
if ( fd < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to open /dev/net/tun: %s " , strerror ( errno ) ) ;
return - 1 ;
}
memset ( & ifr , 0 , sizeof ( ifr ) ) ;
ifr . ifr_flags = IFF_TUN | IFF_NO_PI ;
if ( ifname & & ifname_len > 0 & & ifname [ 0 ] ! = ' \0 ' ) {
strncpy ( ifr . ifr_name , ifname , IFNAMSIZ - 1 ) ;
}
if ( ioctl ( fd , TUNSETIFF , & ifr ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to configure TUN device: %s " , strerror ( errno ) ) ;
close ( fd ) ;
return - 1 ;
}
if ( ifname & & ifname_len > 0 ) {
strncpy ( ifname , ifr . ifr_name , ifname_len - 1 ) ;
ifname [ ifname_len - 1 ] = ' \0 ' ;
}
return fd ;
}
// Run system command
static int run_command ( const char * cmd ) {
int ret = system ( cmd ) ;
if ( ret = = - 1 ) {
perror ( " system " ) ;
return - 1 ;
}
if ( WIFEXITED ( ret ) & & WEXITSTATUS ( ret ) ! = 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Command failed: %s " , cmd ) ;
return - 1 ;
}
return 0 ;
}
// Parse IP address and mask
static int parse_ip_mask ( const char * ip_addr , char * ip , size_t ip_len , int * mask ) {
if ( ! ip_addr | | ! ip | | ! mask ) return - 1 ;
char * slash = strchr ( ip_addr , ' / ' ) ;
if ( ! slash ) {
// Default mask /32
* mask = 32 ;
strncpy ( ip , ip_addr , ip_len - 1 ) ;
ip [ ip_len - 1 ] = ' \0 ' ;
} else {
size_t ip_size = slash - ip_addr ;
if ( ip_size > = ip_len ) return - 1 ;
strncpy ( ip , ip_addr , ip_size ) ;
ip [ ip_size ] = ' \0 ' ;
char * endptr ;
long mask_val = strtol ( slash + 1 , & endptr , 10 ) ;
if ( * endptr ! = ' \0 ' | | mask_val < 0 | | mask_val > 32 ) return - 1 ;
* mask = ( int ) mask_val ;
}
return 0 ;
return fd ;
}
int tun_create ( struct tun_config * config ) {
@ -97,15 +102,15 @@ int tun_create(struct tun_config *config) {
errno = EINVAL ;
return - 1 ;
}
// Create TUN device
int fd = create_tun_device ( config - > ifname , sizeof ( config - > ifname ) ) ;
if ( fd < 0 ) {
return - 1 ;
}
config - > fd = fd ;
// Configure IP if specified
if ( config - > ip_addr [ 0 ] ! = ' \0 ' ) {
if ( tun_set_ip ( config - > ifname , config - > ip_addr ) < 0 ) {
@ -113,20 +118,20 @@ int tun_create(struct tun_config *config) {
return - 1 ;
}
}
// Set MTU if specified
if ( config - > mtu > 0 ) {
if ( tun_set_mtu ( config - > ifname , config - > mtu ) < 0 ) {
DEBUG_WARN ( DEBUG_CATEGORY_TUN , " Failed to set MTU %d on %s: %s " , config - > mtu , config - > ifname , strerror ( errno ) ) ;
}
}
// Bring interface up
if ( tun_set_up ( config - > ifname ) < 0 ) {
close ( fd ) ;
return - 1 ;
}
config - > is_up = 1 ;
return 0 ;
}
@ -136,21 +141,29 @@ int tun_set_ip(const char *ifname, const char *ip_addr) {
errno = EINVAL ;
return - 1 ;
}
char ip [ 64 ] ;
int mask ;
if ( parse_ip_mask ( ip_addr , ip , sizeof ( ip ) , & mask ) < 0 ) {
struct in_addr ip , netmask ;
if ( parse_ip_mask ( ip_addr , & ip , & netmask ) < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_CONFIG , " Invalid IP address format: %s " , ip_addr ) ;
errno = EINVAL ;
return - 1 ;
}
char cmd [ 256 ] ;
snprintf ( cmd , sizeof ( cmd ) , " ip addr add %s dev %s " , ip_addr , ifname ) ;
if ( run_command ( cmd ) < 0 ) {
return - 1 ;
}
struct ifreq ifr ;
memset ( & ifr , 0 , sizeof ( ifr ) ) ;
// Set IP address
struct sockaddr_in * addr = ( struct sockaddr_in * ) & ifr . ifr_addr ;
addr - > sin_family = AF_INET ;
addr - > sin_addr = ip ;
if ( if_ioctl ( ifname , SIOCSIFADDR , & ifr ) < 0 ) return - 1 ;
// Set netmask
addr = ( struct sockaddr_in * ) & ifr . ifr_netmask ;
addr - > sin_family = AF_INET ;
addr - > sin_addr = netmask ;
if ( if_ioctl ( ifname , SIOCSIFNETMASK , & ifr ) < 0 ) return - 1 ;
return 0 ;
}
@ -159,13 +172,17 @@ int tun_set_up(const char *ifname) {
errno = EINVAL ;
return - 1 ;
}
char cmd [ 256 ] ;
snprintf ( cmd , sizeof ( cmd ) , " ip link set %s up " , ifname ) ;
if ( run_command ( cmd ) < 0 ) {
return - 1 ;
}
struct ifreq ifr ;
memset ( & ifr , 0 , sizeof ( ifr ) ) ;
// Get current flags
if ( if_ioctl ( ifname , SIOCGIFFLAGS , & ifr ) < 0 ) return - 1 ;
// Set UP and RUNNING
ifr . ifr_flags | = IFF_UP | IFF_RUNNING ;
if ( if_ioctl ( ifname , SIOCSIFFLAGS , & ifr ) < 0 ) return - 1 ;
return 0 ;
}
@ -174,13 +191,13 @@ int tun_set_mtu(const char *ifname, int mtu) {
errno = EINVAL ;
return - 1 ;
}
char cmd [ 256 ] ;
snprintf ( cmd , sizeof ( cmd ) , " ip link set %s mtu %d " , ifname , mtu ) ;
if ( run_command ( cmd ) < 0 ) {
return - 1 ;
}
struct ifreq ifr ;
memset ( & ifr , 0 , sizeof ( ifr ) ) ;
ifr . ifr_mtu = mtu ;
if ( if_ioctl ( ifname , SIOCSIFMTU , & ifr ) < 0 ) return - 1 ;
return 0 ;
}
@ -189,12 +206,12 @@ ssize_t tun_read(int fd, uint8_t *buffer, size_t size) {
errno = EINVAL ;
return - 1 ;
}
ssize_t nread = read ( fd , buffer , size ) ;
if ( nread < 0 ) {
perror ( " tun_read " ) ;
}
return nread ;
}
@ -203,23 +220,23 @@ ssize_t tun_write(int fd, const uint8_t *buffer, size_t size) {
errno = EINVAL ;
return - 1 ;
}
ssize_t nwritten = write ( fd , buffer , size ) ;
if ( nwritten < 0 ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to write to TUN device fd=%d: %s " , fd , strerror ( errno ) ) ;
}
return nwritten ;
}
void tun_close ( struct tun_config * config ) {
if ( ! config ) return ;
if ( config - > fd > = 0 ) {
close ( config - > fd ) ;
config - > fd = - 1 ;
}
config - > is_up = 0 ;
}
@ -228,27 +245,15 @@ int tun_get_config(const char *ifname, struct tun_config *config) {
errno = EINVAL ;
return - 1 ;
}
// TODO: Implement reading current interface configuration
// This would require parsing ip addr show output
// This would require ioctl SIOCGIFADDR, SIOCGIFNETMASK, etc.
memset ( config , 0 , sizeof ( * config ) ) ;
strncpy ( config - > ifname , ifname , sizeof ( config - > ifname ) - 1 ) ;
config - > fd = - 1 ;
return 0 ;
}
// Extract destination IPv4 address from packet
static uint32_t tun_get_dest_ip ( const uint8_t * packet , size_t len ) {
if ( len < 20 ) return 0 ; // Minimum IPv4 header size
// Check IP version (first nibble)
uint8_t version = ( packet [ 0 ] > > 4 ) & 0x0F ;
if ( version ! = 4 ) return 0 ;
// Destination IP is at offset 16
uint32_t dest_ip ;
memcpy ( & dest_ip , packet + 16 , 4 ) ;
return dest_ip ;
return 0 ;
}
// Extract destination IPv4 address from packet
@ -263,12 +268,11 @@ static uint32_t get_dest_ip(const uint8_t *packet, size_t len) {
return dest_ip ;
}
// Callback for TUN device read events
void tun_read_callback ( int fd , void * user_arg ) {
struct UTUN_INSTANCE * instance = ( struct UTUN_INSTANCE * ) user_arg ;
uint8_t buffer [ MAX_PACKET_SIZE ] ;
// Read from TUN device
ssize_t nread = tun_read ( fd , buffer , sizeof ( buffer ) ) ;
if ( nread < 0 ) {
@ -276,12 +280,11 @@ void tun_read_callback(int fd, void* user_arg) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to read from TUN device %s: %s " , instance - > tun . ifname , strerror ( errno ) ) ;
return ;
}
if ( nread > 0 ) {
// Route packet based on destination IP
uint32_t dest_ip = get_dest_ip ( buffer , nread ) ;
//...
// ... (rest of the routing logic)
}
}
@ -291,15 +294,15 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Invalid instance or TUN fd " ) ;
return - 1 ;
}
// Register TUN file descriptor
instance - > tun_socket_id = uasync_add_socket ( instance - > ua , instance - > tun . fd ,
instance - > tun_socket_id = uasync_add_socket ( instance - > ua , instance - > tun . fd ,
tun_read_callback , NULL , NULL , instance ) ;
if ( ! instance - > tun_socket_id ) {
DEBUG_ERROR ( DEBUG_CATEGORY_TUN , " Failed to register TUN socket " ) ;
return - 1 ;
}
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " Registered TUN socket (fd=%d) " , instance - > tun . fd ) ;
return 0 ;
}
@ -307,11 +310,10 @@ int utun_instance_register_sockets(struct UTUN_INSTANCE *instance) {
// Unregister sockets
void utun_instance_unregister_sockets ( struct UTUN_INSTANCE * instance ) {
if ( ! instance | | ! instance - > ua ) return ;
if ( instance - > tun_socket_id ) {
uasync_remove_socket ( instance - > ua , instance - > tun_socket_id ) ;
instance - > tun_socket_id = NULL ;
DEBUG_INFO ( DEBUG_CATEGORY_TUN , " Unregistered TUN socket: %s " , instance - > tun . ifname ) ;
}
}
}