From 9d4597a842417e368ec70438fc4ecbe3fd220b15 Mon Sep 17 00:00:00 2001 From: Dmitry Gerasimov <dmitriy.gerasimov@demlabs.net> Date: Wed, 29 Jun 2022 15:31:23 +0700 Subject: [PATCH] [+] Added Darwin-based OS support for VPN service and client --- modules/CMakeLists.txt | 6 +- .../cdb/dap_modules_dynamic_cdb.c | 2 + modules/service/vpn/dap_chain_net_srv_vpn.c | 162 ++++++++++++++++-- .../service/vpn/dap_chain_net_srv_vpn_cmd.c | 2 +- .../service/vpn/dap_chain_net_vpn_client.c | 27 ++- .../vpn/dap_chain_net_vpn_client_tun.c | 111 +++++++++++- 6 files changed, 271 insertions(+), 39 deletions(-) diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt index ef1bd8dca8..72ceb6de6d 100644 --- a/modules/CMakeLists.txt +++ b/modules/CMakeLists.txt @@ -99,10 +99,8 @@ if (CELLFRAME_MODULES MATCHES "srv-datum") endif() # Service VPN -if(LINUX) - if (CELLFRAME_MODULES MATCHES "srv-vpn") - add_subdirectory(service/vpn) - endif() +if (CELLFRAME_MODULES MATCHES "srv-vpn") + add_subdirectory(service/vpn) endif() # Service eXchange diff --git a/modules/modules_dynamic/cdb/dap_modules_dynamic_cdb.c b/modules/modules_dynamic/cdb/dap_modules_dynamic_cdb.c index 5d63d36f86..3457c9f8d0 100644 --- a/modules/modules_dynamic/cdb/dap_modules_dynamic_cdb.c +++ b/modules/modules_dynamic/cdb/dap_modules_dynamic_cdb.c @@ -42,7 +42,9 @@ static bool s_cdb_was_init = false; void dap_modules_dynamic_close_cdb() { if (s_cdb_handle) { +#if defined (DAP_OS_LINUX) && !defined (__ANDROID__) dlclose(s_cdb_handle); +#endif s_cdb_handle = NULL; } s_cdb_was_init = false; diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index a606e4a8a9..b2dabe10d7 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -32,13 +32,28 @@ #include <sys/epoll.h> #endif -#ifdef DAP_OS_BSD +#ifdef DAP_OS_DARWIN +#include <net/if.h> +#include <net/if_utun.h> +#include <sys/kern_control.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sys_domain.h> +#include <netinet/in.h> + +#elif defined(DAP_OS_BSD) #include <netinet/in.h> #include <net/if.h> #include <net/if_tun.h> #include <sys/ioctl.h> #endif +#if defined (DAP_OS_BSD) +typedef struct ip dap_os_iphdr_t; +#else +typedef struct iphdr dap_os_iphdr_t; +#endif #include <sys/select.h> @@ -97,6 +112,7 @@ typedef struct vpn_local_network { struct in_addr ipv4_network_addr; struct in_addr ipv4_gw; int tun_ctl_fd; + char * tun_device_name; int tun_fd; struct ifreq ifr; bool auto_cpu_reassignment; @@ -200,9 +216,11 @@ static void s_tun_send_msg_ip_assigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn static void s_tun_send_msg_ip_unassigned(uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); static void s_tun_send_msg_ip_unassigned_all(dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr); +#if !defined(DAP_OS_DARWIN) && (defined(DAP_OS_LINUX) || defined (DAP_OS_BSD)) + static int s_tun_deattach_queue(int fd); static int s_tun_attach_queue(int fd); - +#endif static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * a_ch_vpn_info, const void * a_data, size_t a_data_size); static bool s_tun_client_send_data_unsafe(dap_chain_net_srv_ch_vpn_t * l_ch_vpn, ch_vpn_pkt_t * l_pkt_out); @@ -233,7 +251,7 @@ static bool s_tun_client_send_data_unsafe(dap_chain_net_srv_ch_vpn_t * l_ch_vpn, static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_info, const void * a_data, size_t a_data_size) { - assert(a_data_size > sizeof (struct iphdr)); + assert(a_data_size > sizeof (dap_os_iphdr_t)); ch_vpn_pkt_t *l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, sizeof(l_pkt_out->header) + a_data_size); l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; l_pkt_out->header.sock_id = s_raw_server->tun_fd; @@ -242,7 +260,11 @@ static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_in memcpy(l_pkt_out->data, a_data, a_data_size); struct in_addr l_in_daddr; - l_in_daddr.s_addr = ((struct iphdr* ) l_pkt_out->data)->daddr; +#ifdef DAP_OS_LINUX + l_in_daddr.s_addr = ((dap_os_iphdr_t* ) l_pkt_out->data)->daddr; +#else + l_in_daddr.s_addr = ((dap_os_iphdr_t* ) l_pkt_out->data)->ip_dst.s_addr; +#endif if(l_ch_vpn_info->is_on_this_worker){ dap_events_socket_t * l_es = NULL; @@ -552,24 +574,110 @@ static int s_vpn_tun_create(dap_config_t * g_config) s_raw_server->ipv4_gw.s_addr= (s_raw_server->ipv4_network_addr.s_addr | 0x01000000); // grow up some shit here! s_raw_server->ipv4_lease_last.s_addr = s_raw_server->ipv4_gw.s_addr; +// Not for Darwin +#ifndef DAP_OS_DARWIN s_raw_server->auto_cpu_reassignment = dap_config_get_item_bool_default(g_config, "srv_vpn", "auto_cpu_reassignment", false); +#endif + log_it(L_NOTICE, "Auto cpu reassignment is set to '%s'", s_raw_server->auto_cpu_reassignment ? "true" : "false"); +#if defined (DAP_OS_DARWIN) + s_tun_sockets_count = 1; +#elif defined(DAP_OS_LINUX) || defined(DAP_OS_BSD) + s_tun_sockets_count = dap_get_cpu_count(); memset(&s_raw_server->ifr, 0, sizeof(s_raw_server->ifr)); s_raw_server->ifr.ifr_flags = IFF_TUN | IFF_MULTI_QUEUE| IFF_NO_PI; - - uint32_t l_cpu_count = dap_get_cpu_count(); // maybe replace with getting s_threads_count directly - log_it(L_NOTICE,"%s: trying to initialize multiqueue for %u workers", __PRETTY_FUNCTION__, l_cpu_count); - s_tun_sockets_count = l_cpu_count; +#else +#error "Undefined tun create for your platform" +#endif + log_it(L_NOTICE,"%s: trying to initialize multiqueue for %u workers", __PRETTY_FUNCTION__, s_tun_sockets_count); s_tun_sockets = DAP_NEW_Z_SIZE(dap_chain_net_srv_vpn_tun_socket_t*,s_tun_sockets_count*sizeof(dap_chain_net_srv_vpn_tun_socket_t*)); s_tun_sockets_queue_msg = DAP_NEW_Z_SIZE(dap_events_socket_t*,s_tun_sockets_count*sizeof(dap_events_socket_t*)); s_tun_sockets_mutex_started = DAP_NEW_Z_SIZE(pthread_mutex_t,s_tun_sockets_count*sizeof(pthread_mutex_t)); s_tun_sockets_cond_started = DAP_NEW_Z_SIZE(pthread_cond_t,s_tun_sockets_count*sizeof(pthread_cond_t)); int err = -1; - for( uint8_t i =0; i< l_cpu_count; i++){ +#if defined (DAP_OS_DARWIN) + // Prepare structs + struct ctl_info l_ctl_info = {0}; + + // Copy utun control name + if (strlcpy(l_ctl_info.ctl_name, UTUN_CONTROL_NAME, sizeof(l_ctl_info.ctl_name)) + >= sizeof(l_ctl_info.ctl_name)){ + err = -100; // How its possible to came into this part? Idk + log_it(L_ERROR,"UTUN_CONTROL_NAME \"%s\" too long", UTUN_CONTROL_NAME); + goto lb_err; + } + + // Create utun socket + int l_tun_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + if( l_tun_fd < 0){ + int l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Opening utun device control (SYSPROTO_CONTROL) error: '%s' (code %d)", l_errbuf, l_errno); + err = -101; + goto lb_err; + } + log_it(L_INFO, "Utun SYSPROTO_CONTROL descriptor obtained"); + s_raw_server->tun_ctl_fd = l_tun_fd; + + // Pass control structure to the utun socket + if( ioctl(l_tun_fd, CTLIOCGINFO, &l_ctl_info ) < 0 ){ + int l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't execute ioctl(CTLIOCGINFO): '%s' (code %d)", l_errbuf, l_errno); + err = -102; + goto lb_err; + + } + log_it(L_INFO, "Utun CTLIOCGINFO structure passed through ioctl"); + + // Trying to connect with one of utunX devices + int l_ret = -1; + for(int l_unit = 0; l_unit < 256; l_unit++){ + struct sockaddr_ctl l_sa_ctl = {0}; + l_sa_ctl.sc_id = l_ctl_info.ctl_id; + l_sa_ctl.sc_len = sizeof(l_sa_ctl); + l_sa_ctl.sc_family = AF_SYSTEM; + l_sa_ctl.ss_sysaddr = AF_SYS_CONTROL; + l_sa_ctl.sc_unit = l_unit + 1; + + // If connect successful, new utunX device should be created + l_ret = connect(l_tun_fd, (struct sockaddr *)&l_sa_ctl, sizeof(l_sa_ctl)); + if(l_ret == 0) + break; + } + if (l_ret < 0){ + int l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't create utun device: '%s' (code %d)", l_errbuf, l_errno); + err = -103; + goto lb_err; + + } + + // Get iface name of newly created utun dev. + log_it(L_NOTICE, "Utun device created"); + char l_utunname[20]; + socklen_t l_utunname_len = sizeof(l_utunname); + if (getsockopt(l_tun_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, l_utunname, &l_utunname_len) ){ + int l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't get utun device name: '%s' (code %d)", l_errbuf, l_errno); + err = -104; + goto lb_err; + } + s_raw_server->tun_device_name = strndup(l_utunname, l_utunname_len); + log_it(L_NOTICE, "Utun device name \"%s\"", s_raw_server->tun_device_name); + + for( uint8_t i =0; i< s_tun_sockets_count; i++){ dap_worker_t * l_worker = dap_events_worker_get(i); assert( l_worker ); +#elif defined(DAP_OS_LINUX) || defined(DAP_OS_BSD) int l_tun_fd; if( (l_tun_fd = open("/dev/net/tun", O_RDWR | O_NONBLOCK)) < 0 ) { log_it(L_ERROR,"Opening /dev/net/tun error: '%s'", strerror(errno)); @@ -583,6 +691,10 @@ static int s_vpn_tun_create(dap_config_t * g_config) break; } s_tun_deattach_queue(l_tun_fd); + +#else +#error "Undefined tun interface attach for your platform" +#endif pthread_mutex_init(&s_tun_sockets_mutex_started[i],NULL); pthread_cond_init(&s_tun_sockets_cond_started[i],NULL); pthread_mutex_lock(&s_tun_sockets_mutex_started[i]); @@ -590,7 +702,7 @@ static int s_vpn_tun_create(dap_config_t * g_config) } // Waiting for all the tun sockets - for( uint8_t i =0; i< l_cpu_count; i++){ + for( uint8_t i =0; i< s_tun_sockets_count; i++){ pthread_cond_wait(&s_tun_sockets_cond_started[i], &s_tun_sockets_mutex_started[i]); pthread_mutex_unlock(&s_tun_sockets_mutex_started[i]); } @@ -616,7 +728,7 @@ static int s_vpn_tun_create(dap_config_t * g_config) snprintf(buf,sizeof(buf),"ip addr add %s/%s dev %s ",inet_ntoa(s_raw_server->ipv4_gw),c_mask, s_raw_server->ifr.ifr_name ); system(buf); } - +lb_err: return err; } @@ -1405,21 +1517,35 @@ static void s_es_tun_read(dap_events_socket_t * a_es, void * arg) dap_chain_net_srv_vpn_tun_socket_t * l_tun_socket = CH_SF_TUN_SOCKET(a_es); assert(l_tun_socket); size_t l_buf_in_size = a_es->buf_in_size; - struct iphdr *iph = (struct iphdr*) a_es->buf_in; + dap_os_iphdr_t *iph = ( dap_os_iphdr_t*) a_es->buf_in; if (s_debug_more){ char l_str_daddr[INET_ADDRSTRLEN]={[0]='\0'}; char l_str_saddr[INET_ADDRSTRLEN]={[0]='\0'}; +#ifdef DAP_OS_LINUX struct in_addr l_daddr={ .s_addr = iph->daddr}; struct in_addr l_saddr={ .s_addr = iph->saddr}; inet_ntop(AF_INET,&l_daddr,l_str_daddr,sizeof (iph->daddr)); inet_ntop(AF_INET,&l_saddr,l_str_saddr,sizeof (iph->saddr)); - log_it(L_DEBUG,"m_es_tun_read() received ip packet %s->%s tot_len: %u ", - l_str_saddr, l_str_saddr, iph->tot_len); + size_t l_ip_tot_len = iph->tot_len; +#else + struct in_addr l_daddr={ .s_addr = iph->ip_dst.s_addr }; + struct in_addr l_saddr={ .s_addr = iph->ip_src.s_addr}; + inet_ntop(AF_INET,&l_daddr,l_str_daddr,sizeof (l_daddr)); + inet_ntop(AF_INET,&l_saddr,l_str_saddr,sizeof (l_saddr)); + size_t l_ip_tot_len = iph->ip_len ; +#endif + + log_it(L_DEBUG,"m_es_tun_read() received ip packet %s->%s tot_len: %zu ", + l_str_saddr, l_str_saddr, l_ip_tot_len); } if(l_buf_in_size) { struct in_addr l_in_daddr; +#ifdef DAP_OS_LINUX l_in_daddr.s_addr = iph->daddr; +#else + l_in_daddr.s_addr = iph->ip_dst.s_addr; +#endif // dap_chain_net_srv_ch_vpn_info_t * l_vpn_info = NULL; @@ -1478,8 +1604,10 @@ static void s_es_tun_new(dap_events_socket_t * a_es, void * arg) l_tun_socket->queue_tun_msg_input = DAP_NEW_Z_SIZE(dap_events_socket_t*,sizeof(dap_events_socket_t*)* dap_events_thread_get_count()); a_es->_inheritor = l_tun_socket; - s_tun_attach_queue( a_es->fd ); +#if !defined(DAP_OS_DARWIN) && (defined(DAP_OS_LINUX) || defined (DAP_OS_BSD)) + s_tun_attach_queue( a_es->fd ); +#endif // Signal thats its ready pthread_mutex_lock(&s_tun_sockets_mutex_started[l_worker_id]); pthread_mutex_unlock(&s_tun_sockets_mutex_started[l_worker_id]); @@ -1492,6 +1620,8 @@ static void s_es_tun_new(dap_events_socket_t * a_es, void * arg) } } + +#if !defined(DAP_OS_DARWIN) && (defined(DAP_OS_LINUX) || defined (DAP_OS_BSD)) /** * @brief s_tun_attach_queue * @param fd @@ -1517,3 +1647,5 @@ static int s_tun_deattach_queue(int fd) ifr.ifr_flags = IFF_DETACH_QUEUE; return ioctl(fd, TUNSETQUEUE, (void *)&ifr); } + +#endif diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c index 3e1d171e03..fe8ebe224b 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cmd.c @@ -56,7 +56,7 @@ int com_vpn_statistics(int a_argc, char ** a_argv, char **a_str_reply) l_time_len_sec / 3600, (l_time_len_sec % 3600) / 60, l_time_len_sec % 60); // client ip const int l_tun_client_addr_str_len = 128; - char *l_tun_client_addr_str = DAP_NEW_S_SIZE(char, l_tun_client_addr_str_len); + char *l_tun_client_addr_str = DAP_NEW_STACK_SIZE(char, l_tun_client_addr_str_len); if(inet_ntop(AF_INET, &(l_session->tun_client_addr), l_tun_client_addr_str, l_tun_client_addr_str_len)) dap_string_append_printf(l_str, " client addr........%s\n", l_tun_client_addr_str); else diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c index 3246500704..8a479a2b81 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client.c +++ b/modules/service/vpn/dap_chain_net_vpn_client.c @@ -34,7 +34,7 @@ #include <sys/select.h> #include <sys/ioctl.h> #include <sys/time.h> -#include <sys/epoll.h> + #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> @@ -45,6 +45,7 @@ #ifdef DAP_OS_LINUX #include <dlfcn.h> +#include <sys/epoll.h> #endif #include "dap_client.h" @@ -79,9 +80,6 @@ #define LOG_TAG "vpn_client" -static EPOLL_HANDLE sf_socks_epoll_fd; - - static pthread_mutex_t sf_socks_mutex; static dap_chain_node_info_t *s_node_info = NULL; @@ -212,7 +210,7 @@ static dap_chain_datum_tx_receipt_t * s_callback_client_sign_request(dap_chain_n dap_chain_datum_tx_receipt_t *a_receipt, size_t a_receipt_size) { char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - char *l_wallet_name = (char*) dap_chain_global_db_gr_get(dap_strdup("wallet_name"), NULL, l_gdb_group); + char *l_wallet_name = (char*) dap_global_db_get_sync(l_gdb_group, dap_strdup("wallet_name"), NULL,NULL, NULL); dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_name, dap_chain_wallet_get_path(g_config)); dap_chain_datum_tx_receipt_t *l_ret = NULL; @@ -240,8 +238,8 @@ static dap_chain_hash_fast_t* dap_chain_net_vpn_client_tx_cond_hash(dap_chain_ne // Try to load from gdb size_t l_gdb_group_size = 0; char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - dap_chain_hash_fast_t *l_tx_cond_hash = (dap_chain_hash_fast_t*) dap_chain_global_db_gr_get( - dap_strdup("client_tx_cond_hash"), &l_gdb_group_size, l_gdb_group); + dap_chain_hash_fast_t *l_tx_cond_hash = (dap_chain_hash_fast_t*) dap_global_db_get_sync(l_gdb_group, + dap_strdup("client_tx_cond_hash"), &l_gdb_group_size, NULL, NULL); time_t l_tx_cond_ts = 0; // Check for entry size @@ -335,8 +333,7 @@ static dap_chain_hash_fast_t* dap_chain_net_vpn_client_tx_cond_hash(dap_chain_ne log_it(L_ERROR, "Can't create condition for user"); } else { // save transaction for login - dap_chain_global_db_gr_set( "client_tx_cond_hash", l_tx_cond_hash, sizeof(dap_chain_hash_fast_t), - l_gdb_group); + dap_global_db_set_sync( l_gdb_group,"client_tx_cond_hash", l_tx_cond_hash, sizeof(dap_chain_hash_fast_t), true); } DAP_DELETE(l_client_key); } @@ -360,11 +357,11 @@ int dap_chain_net_vpn_client_update(dap_chain_net_t *a_net, const char *a_wallet } char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); - if(!dap_chain_global_db_gr_set("wallet_name", a_wallet_name, -1, l_gdb_group)) + if(!dap_global_db_set_sync(l_gdb_group, "wallet_name", a_wallet_name, -1,true)) return -2; - if(!dap_chain_global_db_gr_set("token_name", a_str_token, -1, l_gdb_group)) + if(!dap_global_db_set_sync(l_gdb_group, "token_name", a_str_token, -1, true)) return -2; - if(!dap_chain_global_db_gr_set("value_datoshi", &a_value_datoshi, sizeof(a_value_datoshi), l_gdb_group)) + if(!dap_global_db_set_sync(l_gdb_group, "value_datoshi", &a_value_datoshi, sizeof(a_value_datoshi), true)) return -2; DAP_DELETE(l_gdb_group); dap_chain_hash_fast_t *l_hash = dap_chain_net_vpn_client_tx_cond_hash(a_net, l_wallet, a_str_token, @@ -388,11 +385,11 @@ int dap_chain_net_vpn_client_get_wallet_info(dap_chain_net_t *a_net, char **a_wa size_t l_gdb_group_size = 0; char *l_gdb_group = dap_strdup_printf("local.%s", DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX); if(a_wallet_name) - *a_wallet_name = (char*) dap_chain_global_db_gr_get("wallet_name", NULL, l_gdb_group); + *a_wallet_name = (char*) dap_global_db_get_sync(l_gdb_group, "wallet_name", NULL, NULL, NULL); if(a_str_token) - *a_str_token = (char*) dap_chain_global_db_gr_get("token_name", NULL, l_gdb_group); + *a_str_token = (char*) dap_global_db_get_sync(l_gdb_group, "token_name", NULL, NULL, NULL); if(a_value_datoshi) { - uint64_t *l_value_datoshi = (uint64_t*) dap_chain_global_db_gr_get("value_datoshi", NULL, l_gdb_group); + uint64_t *l_value_datoshi = (uint64_t*) dap_global_db_get_sync(l_gdb_group, "value_datoshi", NULL, NULL, NULL); *a_value_datoshi = l_value_datoshi ? *l_value_datoshi : 0; DAP_DELETE(l_value_datoshi); } diff --git a/modules/service/vpn/dap_chain_net_vpn_client_tun.c b/modules/service/vpn/dap_chain_net_vpn_client_tun.c index 0ed4298c8a..f749ab2149 100644 --- a/modules/service/vpn/dap_chain_net_vpn_client_tun.c +++ b/modules/service/vpn/dap_chain_net_vpn_client_tun.c @@ -22,7 +22,6 @@ along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. */ -#include <sys/epoll.h> #include <sys/un.h> #include <sys/ioctl.h> #include <sys/stat.h> @@ -30,7 +29,6 @@ #include <arpa/inet.h> #include <net/ethernet.h> -#include <netpacket/packet.h> #include <netinet/in.h> #include <time.h> @@ -50,7 +48,21 @@ #include <arpa/inet.h> #include <fcntl.h> +#ifdef DAP_OS_LINUX +#include <netpacket/packet.h> #include <linux/if_tun.h> +#elif defined (DAP_OS_DARWIN) +#include <net/if.h> +#include <net/if_utun.h> +#include <sys/kern_control.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sys_domain.h> +#include <netinet/in.h> +#endif + + #include <net/if.h> #include <netinet/in.h> #include <netinet/ip.h> @@ -81,6 +93,7 @@ static dap_events_socket_t * s_tun_events_socket = NULL; int tun_device_create(char *dev) { +#ifdef DAP_OS_LINUX struct ifreq ifr; int fd, err; char clonedev[] = "/dev/net/tun"; @@ -111,6 +124,81 @@ int tun_device_create(char *dev) strcpy(dev, ifr.ifr_name); log_it(L_INFO, "Created %s network interface", ifr.ifr_name); return fd; +#elif defined DAP_OS_DARWIN + // Prepare structs + struct ctl_info l_ctl_info = {0}; + int l_errno = 0; + + // Copy utun control name + if (strlcpy(l_ctl_info.ctl_name, UTUN_CONTROL_NAME, sizeof(l_ctl_info.ctl_name)) + >= sizeof(l_ctl_info.ctl_name)){ + l_errno = -100; // How its possible to came into this part? Idk + log_it(L_ERROR,"UTUN_CONTROL_NAME \"%s\" too long", UTUN_CONTROL_NAME); + goto lb_err; + } + + // Create utun socket + int l_tun_fd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL); + if( l_tun_fd < 0){ + l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Opening utun device control (SYSPROTO_CONTROL) error: '%s' (code %d)", l_errbuf, l_errno); + goto lb_err; + } + log_it(L_INFO, "Utun SYSPROTO_CONTROL descriptor obtained"); + + // Pass control structure to the utun socket + if( ioctl(l_tun_fd, CTLIOCGINFO, &l_ctl_info ) < 0 ){ + l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't execute ioctl(CTLIOCGINFO): '%s' (code %d)", l_errbuf, l_errno); + goto lb_err; + + } + log_it(L_INFO, "Utun CTLIOCGINFO structure passed through ioctl"); + + // Trying to connect with one of utunX devices + int l_ret = -1; + for(int l_unit = 0; l_unit < 256; l_unit++){ + struct sockaddr_ctl l_sa_ctl = {0}; + l_sa_ctl.sc_id = l_ctl_info.ctl_id; + l_sa_ctl.sc_len = sizeof(l_sa_ctl); + l_sa_ctl.sc_family = AF_SYSTEM; + l_sa_ctl.ss_sysaddr = AF_SYS_CONTROL; + l_sa_ctl.sc_unit = l_unit + 1; + + // If connect successful, new utunX device should be created + l_ret = connect(l_tun_fd, (struct sockaddr *)&l_sa_ctl, sizeof(l_sa_ctl)); + if(l_ret == 0) + break; + } + if (l_ret < 0){ + l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't create utun device: '%s' (code %d)", l_errbuf, l_errno); + goto lb_err; + + } + + // Get iface name of newly created utun dev. + log_it(L_NOTICE, "Utun device created"); + char l_utunname[20]; + socklen_t l_utunname_len = sizeof(l_utunname); + if (getsockopt(l_tun_fd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME, l_utunname, &l_utunname_len) ){ + l_errno = errno; + char l_errbuf[256]; + strerror_r(l_errno, l_errbuf,sizeof(l_errbuf)); + log_it(L_ERROR,"Can't get utun device name: '%s' (code %d)", l_errbuf, l_errno); + goto lb_err; + } + log_it(L_NOTICE, "Utun device name \"%s\"", l_utunname); + return l_tun_fd; +lb_err: + return l_errno; +#endif } static char* run_bash_cmd(const char *a_cmd) @@ -266,12 +354,14 @@ void m_client_tun_new(dap_events_socket_t * a_es, void * arg) a_es->_inheritor = l_tun_socket; //s_tun_attach_queue( a_es->fd ); +#ifdef DAP_OS_LINUX { struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); ifr.ifr_flags = IFF_ATTACH_QUEUE; ioctl(a_es->fd, TUNSETQUEUE, (void *)&ifr); } +#endif log_it(L_NOTICE,"New TUN event socket initialized for worker %u" , l_tun_socket->worker_id); }else{ @@ -291,10 +381,16 @@ static void m_client_tun_read(dap_events_socket_t * a_es, void * arg) l_read_ret = dap_events_socket_pop_from_buf_in(a_es, l_tmp_buf, sizeof(l_tmp_buf)); if(l_read_ret > 0) { - struct iphdr *iph = (struct iphdr*) l_tmp_buf; struct in_addr in_daddr, in_saddr; +#ifdef DAP_OS_LINUX + struct iphdr *iph = (struct iphdr*) l_tmp_buf; in_daddr.s_addr = iph->daddr; in_saddr.s_addr = iph->saddr; +#else + struct ip *iph = (struct ip*) l_tmp_buf; + in_daddr.s_addr = iph->ip_dst.s_addr; + in_saddr.s_addr = iph->ip_src.s_addr; +#endif char str_daddr[42], str_saddr[42]; dap_snprintf(str_saddr, sizeof(str_saddr), "%s",inet_ntoa(in_saddr) ); dap_snprintf(str_daddr, sizeof(str_daddr), "%s",inet_ntoa(in_daddr) ); @@ -553,12 +649,14 @@ static void ch_sf_pkt_send(dap_stream_ch_t * a_ch, void * a_data, size_t a_data_ log_it(L_ERROR, "Try to send to NULL channel"); // return; } - l_pkt_out = DAP_NEW_Z_SIZE(ch_vpn_pkt_t, l_pkt_out_size); + l_pkt_out = DAP_NEW_SIZE(ch_vpn_pkt_t, l_pkt_out_size); + memset(&l_pkt_out->header,0,sizeof(l_pkt_out->header)); l_pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; l_pkt_out->header.sock_id = a_ch->stream->esocket->socket; l_pkt_out->header.op_data.data_size = a_data_size; memcpy(l_pkt_out->data, a_data, a_data_size); dap_stream_ch_pkt_write_unsafe(a_ch, 'd', l_pkt_out, l_pkt_out_size); + } /** @@ -571,8 +669,13 @@ void ch_sf_tun_client_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data, log_it(L_CRITICAL, "Unimplemented tun_client_send"); struct in_addr in_saddr, in_daddr, in_daddr_net; +#ifdef DAP_OS_LINUX in_saddr.s_addr = ((struct iphdr*) pkt_data)->saddr; in_daddr.s_addr = ((struct iphdr*) pkt_data)->daddr; +#else + in_saddr.s_addr = ((struct ip*) pkt_data)->ip_src.s_addr; + in_daddr.s_addr = ((struct ip*) pkt_data)->ip_dst.s_addr; +#endif in_daddr_net.s_addr = ch_sf->ch->stream->session->tun_client_addr.s_addr; //in_daddr_net.s_addr = in_daddr.s_addr & m_tun_server->int_network_mask.s_addr; char * in_daddr_str = strdup(inet_ntoa(in_daddr)); char * in_saddr_str = strdup(inet_ntoa(in_saddr)); -- GitLab