diff --git a/CMakeLists.txt b/CMakeLists.txt index 404c7ae319bd9f786997da4e19dc4c388dc21dcc..e9838e4e4aa47bce6da51f9445f5ebb8b3ebaaa8 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,7 @@ project (dap_chain_net_srv_vpn) set(DAP_CHAIN_NET_SRV_VPN_SRCS dap_chain_net_srv_vpn.c + dap_chain_net_srv_vpn_cdb.c dap_chain_net_srv_vpn_cdb_server_list.c dap_chain_net_vpn_client.c dap_chain_net_vpn_client_tun.c @@ -10,7 +11,8 @@ set(DAP_CHAIN_NET_SRV_VPN_SRCS set(DAP_CHAIN_NET_SRV_VPN_HEADERS dap_chain_net_srv_vpn.h - dap_chain_net_srv_vpn_cdb_server_list.h + dap_chain_net_srv_vpn_cdb.h + dap_chain_net_srv_vpn_cdb_server_list.h dap_chain_net_vpn_client.h dap_chain_net_vpn_client_tun.h @@ -28,7 +30,7 @@ endif() add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRV_VPN_SRCS} ${DAP_CHAIN_NET_SRV_VPN_HEADERS}) -target_link_libraries(dap_chain_net_srv_vpn dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net dap_chain_net_srv) +target_link_libraries(dap_chain_net_srv_vpn dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net dap_chain_net_srv dap_server_http_db dap_server_http_db_auth) target_include_directories(dap_chain_net_srv_vpn INTERFACE .) set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE) diff --git a/dap_chain_net_srv_vpn.c b/dap_chain_net_srv_vpn.c index ca36c8246c8119a3485f1dec856e34508d322f7a..80c776a5b60f4ad302dbac7233bc903cd6ecd422 100755 --- a/dap_chain_net_srv_vpn.c +++ b/dap_chain_net_srv_vpn.c @@ -63,6 +63,7 @@ #include "dap_chain_net.h" #include "dap_chain_net_srv_vpn.h" +#include "dap_chain_net_vpn_client.h" #include "dap_chain_ledger.h" #define LOG_TAG "dap_chain_net_srv_vpn" @@ -97,28 +98,29 @@ static list_addr_element *list_addr_head = NULL; static ch_vpn_socket_proxy_t * sf_socks = NULL; static ch_vpn_socket_proxy_t * sf_socks_client = NULL; -static pthread_mutex_t sf_socks_mutex; -static pthread_cond_t sf_socks_cond; +static pthread_mutex_t s_sf_socks_mutex; +static pthread_cond_t s_sf_socks_cond; static int sf_socks_epoll_fd; static pthread_t srv_sf_socks_pid; static pthread_t srv_sf_socks_raw_pid; +static vpn_local_network_t *s_raw_server; -vpn_local_network_t *raw_server; +static const char *s_addr; -void *srv_ch_sf_thread(void * arg); -void *srv_ch_sf_thread_raw(void *arg); -void srv_ch_sf_tun_create(); -void srv_ch_sf_tun_destroy(); +static void *srv_ch_sf_thread(void * arg); +static void *srv_ch_sf_thread_raw(void *arg); +static void s_tun_create(void); +static void s_tun_destroy(void); -void srv_ch_sf_new(dap_stream_ch_t* ch, void* arg); -void srv_ch_sf_delete(dap_stream_ch_t* ch, void* arg); -void srv_ch_sf_packet_in(dap_stream_ch_t* ch, void* arg); -void srv_ch_sf_packet_out(dap_stream_ch_t* ch, void* arg); +static void s_new(dap_stream_ch_t* ch, void* arg); +static void srv_ch_sf_delete(dap_stream_ch_t* ch, void* arg); +static void srv_ch_sf_packet_in(dap_stream_ch_t* ch, void* arg); +static void srv_ch_sf_packet_out(dap_stream_ch_t* ch, void* arg); //static int srv_ch_sf_raw_write(uint8_t op_code, const void * data, size_t data_size); -//void srv_stream_sf_disconnect(ch_vpn_socket_proxy_t * sf_sock); +//static void srv_stream_sf_disconnect(ch_vpn_socket_proxy_t * sf_sock); -static const char *s_srv_vpn_addr, *s_srv_vpn_mask; +static char *s_srv_vpn_addr, *s_srv_vpn_mask; /** * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel @@ -128,20 +130,20 @@ static const char *s_srv_vpn_addr, *s_srv_vpn_mask; */ int dap_chain_net_srv_vpn_init(dap_config_t * g_config) { - const char *s_addr = dap_config_get_item_str(g_config, "vpn", "network_address"); - const char *s_mask = dap_config_get_item_str(g_config, "vpn", "network_mask"); - if(s_addr && s_mask) { - s_srv_vpn_addr = strdup(s_addr); - s_srv_vpn_mask = strdup(s_mask); - - raw_server = calloc(1, sizeof(vpn_local_network_t)); - pthread_mutex_init(&raw_server->clients_mutex, NULL); - pthread_mutex_init(&raw_server->pkt_out_mutex, NULL); - pthread_mutex_init(&sf_socks_mutex, NULL); - pthread_cond_init(&sf_socks_cond, NULL); + const char *c_addr = dap_config_get_item_str(g_config, "vpn", "network_address"); + const char *c_mask = dap_config_get_item_str(g_config, "vpn", "network_mask"); + if(c_addr && c_mask) { + s_srv_vpn_addr = strdup(c_addr); + s_srv_vpn_mask = strdup(c_mask); + + s_raw_server = DAP_NEW_Z(vpn_local_network_t); + pthread_mutex_init(&s_raw_server->clients_mutex, NULL); + pthread_mutex_init(&s_raw_server->pkt_out_mutex, NULL); + pthread_mutex_init(&s_sf_socks_mutex, NULL); + pthread_cond_init(&s_sf_socks_cond, NULL); pthread_create(&srv_sf_socks_raw_pid, NULL, srv_ch_sf_thread_raw, NULL); pthread_create(&srv_sf_socks_pid, NULL, srv_ch_sf_thread, NULL); - dap_stream_ch_proc_add(SERVICE_CHANNEL_ID, srv_ch_sf_new, srv_ch_sf_delete, srv_ch_sf_packet_in, + dap_stream_ch_proc_add(DAP_STREAM_CH_ID_NET_SRV_VPN, s_new, srv_ch_sf_delete, srv_ch_sf_packet_in, srv_ch_sf_packet_out); return 0; } @@ -151,43 +153,46 @@ int dap_chain_net_srv_vpn_init(dap_config_t * g_config) /** * @brief ch_sf_deinit */ -void dap_chain_net_srv_vpn_deinit() +void dap_chain_net_srv_vpn_deinit(void) { - pthread_mutex_destroy(&sf_socks_mutex); - pthread_cond_destroy(&sf_socks_cond); + pthread_mutex_destroy(&s_sf_socks_mutex); + pthread_cond_destroy(&s_sf_socks_cond); free((char*) s_srv_vpn_addr); free((char*) s_srv_vpn_mask); - if(raw_server) - free(raw_server); + if(s_raw_server) + free(s_raw_server); } -void srv_ch_sf_tun_create() +/** + * @brief s_tun_create + */ +static void s_tun_create(void) { - inet_aton(s_srv_vpn_addr, &raw_server->client_addr); - inet_aton(s_srv_vpn_mask, &raw_server->client_addr_mask); - raw_server->client_addr_host.s_addr = (raw_server->client_addr.s_addr | 0x01000000); // grow up some shit here! - raw_server->client_addr_last.s_addr = raw_server->client_addr_host.s_addr; + inet_aton(s_srv_vpn_addr, &s_raw_server->client_addr); + inet_aton(s_srv_vpn_mask, &s_raw_server->client_addr_mask); + s_raw_server->client_addr_host.s_addr = (s_raw_server->client_addr.s_addr | 0x01000000); // grow up some shit here! + s_raw_server->client_addr_last.s_addr = s_raw_server->client_addr_host.s_addr; - if((raw_server->tun_ctl_fd = open("/dev/net/tun", O_RDWR)) < 0) { + if((s_raw_server->tun_ctl_fd = open("/dev/net/tun", O_RDWR)) < 0) { log_it(L_ERROR, "Opening /dev/net/tun error: '%s'", strerror(errno)); } else { int err; - memset(&raw_server->ifr, 0, sizeof(raw_server->ifr)); - raw_server->ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - if((err = ioctl(raw_server->tun_ctl_fd, TUNSETIFF, (void *) &raw_server->ifr)) < 0) { + memset(&s_raw_server->ifr, 0, sizeof(s_raw_server->ifr)); + s_raw_server->ifr.ifr_flags = IFF_TUN | IFF_NO_PI; + if((err = ioctl(s_raw_server->tun_ctl_fd, TUNSETIFF, (void *) &s_raw_server->ifr)) < 0) { log_it(L_CRITICAL, "ioctl(TUNSETIFF) error: '%s' ", strerror(errno)); - close(raw_server->tun_ctl_fd); - raw_server->tun_ctl_fd = -1; + close(s_raw_server->tun_ctl_fd); + s_raw_server->tun_ctl_fd = -1; } else { char buf[256]; - log_it(L_NOTICE, "Bringed up %s virtual network interface (%s/%s)", raw_server->ifr.ifr_name, - inet_ntoa(raw_server->client_addr_host), s_srv_vpn_mask); - raw_server->tun_fd = raw_server->tun_ctl_fd; // Looks yes, its so - snprintf(buf, sizeof(buf), "ip link set %s up", raw_server->ifr.ifr_name); + log_it(L_NOTICE, "Bringed up %s virtual network interface (%s/%s)", s_raw_server->ifr.ifr_name, + inet_ntoa(s_raw_server->client_addr_host), s_srv_vpn_mask); + s_raw_server->tun_fd = s_raw_server->tun_ctl_fd; // Looks yes, its so + snprintf(buf, sizeof(buf), "ip link set %s up", s_raw_server->ifr.ifr_name); int res = system(buf); - snprintf(buf, sizeof(buf), "ip addr add %s/%s dev %s ", inet_ntoa(raw_server->client_addr_host), + snprintf(buf, sizeof(buf), "ip addr add %s/%s dev %s ", inet_ntoa(s_raw_server->client_addr_host), s_srv_vpn_mask, - raw_server->ifr.ifr_name); + s_raw_server->ifr.ifr_name); res = system(buf); res = 0; } @@ -195,13 +200,21 @@ void srv_ch_sf_tun_create() } -void srv_ch_sf_tun_destroy() +/** + * @brief s_tun_destroy + */ +static void s_tun_destroy(void) { - close(raw_server->tun_fd); - raw_server->tun_fd = -1; + close(s_raw_server->tun_fd); + s_raw_server->tun_fd = -1; } -static void callback_trafic(dap_client_remote_t *a_client, dap_stream_ch_t* a_ch) +/** + * @brief s_callback_trafic + * @param a_client + * @param a_ch + */ +static void s_callback_trafic(dap_client_remote_t *a_client, dap_stream_ch_t* a_ch) { dap_chain_net_srv_vpn_t *l_ch_vpn = CH_VPN(a_ch); //dap_stream_ch_vpn_t *l_ch_vpn = (dap_stream_ch_vpn_t*)(a_ch->internal); @@ -233,32 +246,34 @@ static void callback_trafic(dap_client_remote_t *a_client, dap_stream_ch_t* a_ch * @brief ch_sf_socket_delete * @param sf */ -static void ch_sf_socket_delete(ch_vpn_socket_proxy_t * sf) +static void ch_sf_socket_delete(ch_vpn_socket_proxy_t * a_vpn_socket_proxy) { - close(sf->sock); - pthread_mutex_destroy(& (sf->mutex) ); - if (sf) - free(sf); + close(a_vpn_socket_proxy->sock); + pthread_mutex_destroy(& (a_vpn_socket_proxy->mutex) ); + if (a_vpn_socket_proxy) + DAP_DELETE(a_vpn_socket_proxy); } /** - * @brief stream_sf_new Callback to constructor of object of Ch + * @brief s_new Callback to constructor of object of Ch * @param ch * @param arg */ -void srv_ch_sf_new(dap_stream_ch_t* ch, void* arg) +void s_new(dap_stream_ch_t* a_stream_ch, void* a_arg) { - ch->internal = calloc(1, sizeof(dap_chain_net_srv_vpn_t)); - dap_chain_net_srv_vpn_t * sf = CH_VPN(ch); + (void) a_arg; + + a_stream_ch->internal = DAP_NEW_Z(dap_chain_net_srv_vpn_t); + dap_chain_net_srv_vpn_t * sf = CH_VPN(a_stream_ch); pthread_mutex_init(&sf->mutex, NULL); sf->raw_l3_sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); // - if(ch->stream->session->service_key) { + if(a_stream_ch->stream->session->service_key) { char *l_addr_base58; char *l_sign_hash_str; - ch->stream->session->service_key = + a_stream_ch->stream->session->service_key = "RpiDC8c1SxrT7TUExyGWNErgV6HtwkKhSd1yLEkTA9qHcSiYA4GXjE67KJQay2TzHdG2ouk42d8GgLyABu6rP55JeFYzBkqZ7CqijDEw;12345"; const dap_chain_net_srv_abstract_t *l_cond = NULL; @@ -266,14 +281,14 @@ void srv_ch_sf_new(dap_stream_ch_t* ch, void* arg) const char *l_net_name = "kelvin-testnet"; dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(l_net_name); // get value for service and fill l_cond struct - uint64_t l_value = dap_chain_net_srv_client_auth(l_ledger, ch->stream->session->service_key, &l_cond); + uint64_t l_value = dap_chain_net_srv_client_auth(l_ledger, a_stream_ch->stream->session->service_key, &l_cond); // add service if(l_cond && l_value > 0) { dap_chain_net_srv_t l_srv; memset(&l_srv, 0, sizeof(dap_chain_net_srv_t)); - l_srv.callback_trafic = callback_trafic; + l_srv.callback_trafic = s_callback_trafic; // debug l_srv.srv_common.proposal_params.vpn.limit_bytes = 2000; if(l_cond) @@ -308,11 +323,11 @@ void srv_ch_sf_delete(dap_stream_ch_t* ch, void* arg) LL_APPEND(list_addr_head, el); // LL_FOREACH(list_addr_head,el) log_it(L_INFO,"addr = %s", inet_ntoa(el->addr)); - pthread_mutex_lock(&raw_server->clients_mutex); + pthread_mutex_lock(&s_raw_server->clients_mutex); - HASH_FIND_INT(raw_server->clients, &raw_client_addr, raw_client); + HASH_FIND_INT(s_raw_server->clients, &raw_client_addr, raw_client); if(raw_client) { - HASH_DEL(raw_server->clients, raw_client); + HASH_DEL(s_raw_server->clients, raw_client); log_it(L_DEBUG, "ch_sf_delete() %s removed from hash table", inet_ntoa(ch->stream->session->tun_client_addr)); free(raw_client); @@ -320,7 +335,7 @@ void srv_ch_sf_delete(dap_stream_ch_t* ch, void* arg) log_it(L_DEBUG, "ch_sf_delete() %s is not present in raw sockets hash table", inet_ntoa(ch->stream->session->tun_client_addr)); - pthread_mutex_unlock(&raw_server->clients_mutex); + pthread_mutex_unlock(&s_raw_server->clients_mutex); } HASH_ITER(hh, CH_VPN(ch)->socks , cur, tmp) { @@ -363,17 +378,17 @@ static void stream_sf_socket_ready_to_write(dap_stream_ch_t * ch, bool is_ready) static ch_vpn_pkt_t* srv_ch_sf_raw_read() { ch_vpn_pkt_t*ret = NULL; - pthread_mutex_lock(&raw_server->pkt_out_mutex); - if(raw_server->pkt_out_rindex == (sizeof(raw_server->pkt_out) / sizeof(raw_server->pkt_out[0]))) { - raw_server->pkt_out_rindex = 0; // ring the buffer! + pthread_mutex_lock(&s_raw_server->pkt_out_mutex); + if(s_raw_server->pkt_out_rindex == (sizeof(s_raw_server->pkt_out) / sizeof(s_raw_server->pkt_out[0]))) { + s_raw_server->pkt_out_rindex = 0; // ring the buffer! } - if((raw_server->pkt_out_rindex != raw_server->pkt_out_windex) || (raw_server->pkt_out_size == 0)) { - ret = raw_server->pkt_out[raw_server->pkt_out_rindex]; - raw_server->pkt_out_rindex++; - raw_server->pkt_out_size--; + if((s_raw_server->pkt_out_rindex != s_raw_server->pkt_out_windex) || (s_raw_server->pkt_out_size == 0)) { + ret = s_raw_server->pkt_out[s_raw_server->pkt_out_rindex]; + s_raw_server->pkt_out_rindex++; + s_raw_server->pkt_out_size--; } //else // log_it(L_WARNING, "Packet drop on raw_read() operation, ring buffer is full"); - pthread_mutex_unlock(&raw_server->pkt_out_mutex); + pthread_mutex_unlock(&s_raw_server->pkt_out_mutex); return ret; } @@ -386,280 +401,285 @@ void srv_ch_sf_packet_in(dap_stream_ch_t* ch, void* arg) { dap_stream_ch_pkt_t * pkt = (dap_stream_ch_pkt_t *) arg; - static bool client_connected = false; - ch_vpn_pkt_t * sf_pkt = (ch_vpn_pkt_t *) pkt->data; + if ( pkt->hdr.type == DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT ) + dap_chain_net_vpn_client_pkt_in( ch, pkt); + else { + static bool client_connected = false; + ch_vpn_pkt_t * sf_pkt = (ch_vpn_pkt_t *) pkt->data; - int remote_sock_id = sf_pkt->header.sock_id; + int remote_sock_id = sf_pkt->header.sock_id; - //log_it(L_DEBUG, "Got SF packet with id %d op_code 0x%02x", remote_sock_id, sf_pkt->header.op_code); - if(sf_pkt->header.op_code >= 0xb0) { // Raw packets - switch (sf_pkt->header.op_code) { - case VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST: { // Client request after L3 connection the new IP address - log_it(L_DEBUG, "Got SF packet with id %d op_code 0x%02x", remote_sock_id, sf_pkt->header.op_code); - struct in_addr n_addr = { 0 }; + //log_it(L_DEBUG, "Got SF packet with id %d op_code 0x%02x", remote_sock_id, sf_pkt->header.op_code); + if(sf_pkt->header.op_code >= 0xb0) { // Raw packets + switch (sf_pkt->header.op_code) { + case VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST: { // Client request after L3 connection the new IP address + log_it(L_DEBUG, "Got SF packet with id %d op_code 0x%02x", remote_sock_id, sf_pkt->header.op_code); + struct in_addr n_addr = { 0 }; - if(n_addr.s_addr == 0) { // If the addres still in the network + if(n_addr.s_addr == 0) { // If the addres still in the network - pthread_mutex_lock(&raw_server->clients_mutex); + pthread_mutex_lock(&s_raw_server->clients_mutex); - int count_free_addr = -1; - list_addr_element *el; - LL_COUNT(list_addr_head, el, count_free_addr); + int count_free_addr = -1; + list_addr_element *el; + LL_COUNT(list_addr_head, el, count_free_addr); - dap_stream_ch_vpn_remote_single_t * n_client = (dap_stream_ch_vpn_remote_single_t*) calloc(1, - sizeof(dap_stream_ch_vpn_remote_single_t)); - n_client->ch = ch; + dap_stream_ch_vpn_remote_single_t * n_client = (dap_stream_ch_vpn_remote_single_t*) calloc(1, + sizeof(dap_stream_ch_vpn_remote_single_t)); + n_client->ch = ch; - if(count_free_addr > 0) { - n_addr.s_addr = list_addr_head->addr.s_addr; - LL_DELETE(list_addr_head, list_addr_head); + if(count_free_addr > 0) { + n_addr.s_addr = list_addr_head->addr.s_addr; + LL_DELETE(list_addr_head, list_addr_head); + } + else + { + n_addr.s_addr = ntohl(s_raw_server->client_addr_last.s_addr); + n_addr.s_addr++; + n_addr.s_addr = ntohl(n_addr.s_addr); + } + + n_client->addr = n_addr.s_addr; + s_raw_server->client_addr_last.s_addr = n_addr.s_addr; + ch->stream->session->tun_client_addr.s_addr = n_addr.s_addr; + HASH_ADD_INT(s_raw_server->clients, addr, n_client); + + pthread_mutex_unlock(&s_raw_server->clients_mutex); + + log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(n_addr)); + log_it(L_INFO, "\tgateway %s", inet_ntoa(s_raw_server->client_addr_host)); + log_it(L_INFO, "\tmask %s", inet_ntoa(s_raw_server->client_addr_mask)); + log_it(L_INFO, "\taddr %s", inet_ntoa(s_raw_server->client_addr)); + log_it(L_INFO, "\tlast_addr %s", inet_ntoa(s_raw_server->client_addr_last)); + + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, + sizeof(pkt_out->header) + sizeof(n_addr) + sizeof(s_raw_server->client_addr_host)); + pkt_out->header.sock_id = s_raw_server->tun_fd; + pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; + pkt_out->header.op_data.data_size = sizeof(n_addr) + sizeof(s_raw_server->client_addr_host); + + memcpy(pkt_out->data, &n_addr, sizeof(n_addr)); + memcpy(pkt_out->data + sizeof(n_addr), &s_raw_server->client_addr_host, + sizeof(s_raw_server->client_addr_host)); + dap_stream_ch_pkt_write(ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + stream_sf_socket_ready_to_write(ch, true); + + //ch_sf_raw_write(n_addr.s_addr,STREAM_SF_PACKET_OP_CODE_RAW_L3_ADDR_REPLY,&n_addr,sizeof(n_addr)); + } else { // All the network is filled with clients, can't lease a new address + log_it(L_WARNING, "All the network is filled with clients, can't lease a new address"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.sock_id = s_raw_server->tun_fd; + pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; + pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_NO_FREE_ADDR; + dap_stream_ch_pkt_write(ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + stream_sf_socket_ready_to_write(ch, true); } - else - { - n_addr.s_addr = ntohl(raw_server->client_addr_last.s_addr); - n_addr.s_addr++; - n_addr.s_addr = ntohl(n_addr.s_addr); + } + break; + case VPN_PACKET_OP_CODE_VPN_SEND: { + struct in_addr in_saddr, in_daddr; + in_saddr.s_addr = ((struct iphdr*) sf_pkt->data)->saddr; + in_daddr.s_addr = ((struct iphdr*) sf_pkt->data)->daddr; + + char str_daddr[42], str_saddr[42]; + strncpy(str_saddr, inet_ntoa(in_saddr), sizeof(str_saddr)); + strncpy(str_daddr, inet_ntoa(in_daddr), sizeof(str_daddr)); + int ret; + //if( ch_sf_raw_write(STREAM_SF_PACKET_OP_CODE_RAW_SEND, sf_pkt->data, sf_pkt->op_data.data_size)<0){ + struct sockaddr_in sin = { 0 }; + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = in_daddr.s_addr; + + //if((ret=sendto(CH_SF(ch)->raw_l3_sock , sf_pkt->data,sf_pkt->header.op_data.data_size,0,(struct sockaddr *) &sin, sizeof (sin)))<0){ + if((ret = write(s_raw_server->tun_fd, sf_pkt->data, sf_pkt->header.op_data.data_size)) < 0) { + log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno)); + //log_it(L_ERROR,"raw socket ring buffer overflowed"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; + pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST; + pkt_out->header.sock_id = s_raw_server->tun_fd; + dap_stream_ch_pkt_write(ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + stream_sf_socket_ready_to_write(ch, true); + } else { + //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", + // str_saddr, str_daddr, sf_pkt->header.op_data.data_size, ret); + //log_it(L_DEBUG, "Raw IP sent %u bytes ", ret); } - - n_client->addr = n_addr.s_addr; - raw_server->client_addr_last.s_addr = n_addr.s_addr; - ch->stream->session->tun_client_addr.s_addr = n_addr.s_addr; - HASH_ADD_INT(raw_server->clients, addr, n_client); - - pthread_mutex_unlock(&raw_server->clients_mutex); - - log_it(L_NOTICE, "VPN client address %s leased", inet_ntoa(n_addr)); - log_it(L_INFO, "\tgateway %s", inet_ntoa(raw_server->client_addr_host)); - log_it(L_INFO, "\tmask %s", inet_ntoa(raw_server->client_addr_mask)); - log_it(L_INFO, "\taddr %s", inet_ntoa(raw_server->client_addr)); - log_it(L_INFO, "\tlast_addr %s", inet_ntoa(raw_server->client_addr_last)); - - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, - sizeof(pkt_out->header) + sizeof(n_addr) + sizeof(raw_server->client_addr_host)); - pkt_out->header.sock_id = raw_server->tun_fd; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REPLY; - pkt_out->header.op_data.data_size = sizeof(n_addr) + sizeof(raw_server->client_addr_host); - memcpy(pkt_out->data, &n_addr, sizeof(n_addr)); - memcpy(pkt_out->data + sizeof(n_addr), &raw_server->client_addr_host, - sizeof(raw_server->client_addr_host)); - dap_stream_ch_pkt_write(ch, DATA_CHANNEL_ID, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - stream_sf_socket_ready_to_write(ch, true); - - //ch_sf_raw_write(n_addr.s_addr,STREAM_SF_PACKET_OP_CODE_RAW_L3_ADDR_REPLY,&n_addr,sizeof(n_addr)); - } else { // All the network is filled with clients, can't lease a new address - log_it(L_WARNING, "All the network is filled with clients, can't lease a new address"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.sock_id = raw_server->tun_fd; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_NO_FREE_ADDR; - dap_stream_ch_pkt_write(ch, DATA_CHANNEL_ID, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - stream_sf_socket_ready_to_write(ch, true); + //} } - } - break; - case VPN_PACKET_OP_CODE_VPN_SEND: { - struct in_addr in_saddr, in_daddr; - in_saddr.s_addr = ((struct iphdr*) sf_pkt->data)->saddr; - in_daddr.s_addr = ((struct iphdr*) sf_pkt->data)->daddr; - - char str_daddr[42], str_saddr[42]; - strncpy(str_saddr, inet_ntoa(in_saddr), sizeof(str_saddr)); - strncpy(str_daddr, inet_ntoa(in_daddr), sizeof(str_daddr)); - int ret; - //if( ch_sf_raw_write(STREAM_SF_PACKET_OP_CODE_RAW_SEND, sf_pkt->data, sf_pkt->op_data.data_size)<0){ - struct sockaddr_in sin = { 0 }; - sin.sin_family = AF_INET; - sin.sin_port = 0; - sin.sin_addr.s_addr = in_daddr.s_addr; - - //if((ret=sendto(CH_SF(ch)->raw_l3_sock , sf_pkt->data,sf_pkt->header.op_data.data_size,0,(struct sockaddr *) &sin, sizeof (sin)))<0){ - if((ret = write(raw_server->tun_fd, sf_pkt->data, sf_pkt->header.op_data.data_size)) < 0) { - log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno)); - //log_it(L_ERROR,"raw socket ring buffer overflowed"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM; - pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST; - pkt_out->header.sock_id = raw_server->tun_fd; - dap_stream_ch_pkt_write(ch, DATA_CHANNEL_ID, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - stream_sf_socket_ready_to_write(ch, true); - } else { - //log_it(L_DEBUG, "Raw IP packet daddr:%s saddr:%s %u from %d bytes sent to tun/tap interface", - // str_saddr, str_daddr, sf_pkt->header.op_data.data_size, ret); - //log_it(L_DEBUG, "Raw IP sent %u bytes ", ret); + break; + default: + log_it(L_WARNING, "Can't process SF type 0x%02x", sf_pkt->header.op_code); } - //} - } - break; - default: - log_it(L_WARNING, "Can't process SF type 0x%02x", sf_pkt->header.op_code); - } - } else { // All except CONNECT - ch_vpn_socket_proxy_t * sf_sock = NULL; - if(sf_pkt->header.op_code != VPN_PACKET_OP_CODE_CONNECT) { + } else { // All except CONNECT + ch_vpn_socket_proxy_t * sf_sock = NULL; + if(sf_pkt->header.op_code != VPN_PACKET_OP_CODE_CONNECT) { + + pthread_mutex_lock(&( CH_VPN(ch)->mutex)); + // log_it(L_DEBUG,"Looking in hash table with %d",remote_sock_id); + HASH_FIND_INT((CH_VPN(ch)->socks), &remote_sock_id, sf_sock); + pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); + + if(sf_sock != NULL) { + pthread_mutex_lock(&sf_sock->mutex); // Unlock it in your case as soon as possible to reduce lock time + sf_sock->time_lastused = time(NULL); + switch (sf_pkt->header.op_code) { + case VPN_PACKET_OP_CODE_SEND: { + if(client_connected == false) + { + log_it(L_WARNING, "Drop Packet! User not connected!"); // Client need send + pthread_mutex_unlock(&s_sf_socks_mutex); + break; + } + int ret; + if((ret = send(sf_sock->sock, sf_pkt->data, sf_pkt->header.op_data.data_size, 0)) < 0) { + log_it(L_INFO, "Disconnected from the remote host"); + pthread_mutex_unlock(&sf_sock->mutex); + pthread_mutex_lock(&( CH_VPN(ch)->mutex)); + HASH_DEL(CH_VPN(ch)->socks, sf_sock); + pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); - pthread_mutex_lock(&( CH_VPN(ch)->mutex)); - // log_it(L_DEBUG,"Looking in hash table with %d",remote_sock_id); - HASH_FIND_INT((CH_VPN(ch)->socks), &remote_sock_id, sf_sock); - pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); + pthread_mutex_lock(&s_sf_socks_mutex); + HASH_DELETE(hh2, sf_socks, sf_sock); + HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - if(sf_sock != NULL) { - pthread_mutex_lock(&sf_sock->mutex); // Unlock it in your case as soon as possible to reduce lock time - sf_sock->time_lastused = time(NULL); - switch (sf_pkt->header.op_code) { - case VPN_PACKET_OP_CODE_SEND: { - if(client_connected == false) - { - log_it(L_WARNING, "Drop Packet! User not connected!"); // Client need send - pthread_mutex_unlock(&sf_socks_mutex); - break; + struct epoll_event ev; + ev.data.fd = sf_sock->sock; + ev.events = EPOLLIN; + if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { + log_it(L_ERROR, "Can't remove sock_id %d from the epoll fd", remote_sock_id); + //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=-2",sf_pkt->sock_id, sf_pkt->op_code); + } else { + log_it(L_NOTICE, "Removed sock_id %d from the the epoll fd", remote_sock_id); + //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=0",sf_pkt->sock_id, sf_pkt->op_code); + } + pthread_mutex_unlock(&s_sf_socks_mutex); + + stream_sf_socket_delete(sf_sock); + } else { + sf_sock->bytes_sent += ret; + pthread_mutex_unlock(&sf_sock->mutex); + } + //log_it(L_INFO, "Send action from %d sock_id (sf_packet size %lu, ch packet size %lu, have sent %d)" + // , sf_sock->id, sf_pkt->header.op_data.data_size, pkt->hdr.size, ret); } - int ret; - if((ret = send(sf_sock->sock, sf_pkt->data, sf_pkt->header.op_data.data_size, 0)) < 0) { - log_it(L_INFO, "Disconnected from the remote host"); - pthread_mutex_unlock(&sf_sock->mutex); + break; + case VPN_PACKET_OP_CODE_DISCONNECT: { + log_it(L_INFO, "Disconnect action from %d sock_id", sf_sock->id); + pthread_mutex_lock(&( CH_VPN(ch)->mutex)); HASH_DEL(CH_VPN(ch)->socks, sf_sock); pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); - pthread_mutex_lock(&sf_socks_mutex); + pthread_mutex_lock(&s_sf_socks_mutex); HASH_DELETE(hh2, sf_socks, sf_sock); HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - struct epoll_event ev; ev.data.fd = sf_sock->sock; ev.events = EPOLLIN; if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=-2",sf_pkt->sock_id, sf_pkt->op_code); + log_it(L_ERROR, "Can't remove sock_id %d to the epoll fd", remote_sock_id); + //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); } else { - log_it(L_NOTICE, "Removed sock_id %d from the the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=0x%02x result=0",sf_pkt->sock_id, sf_pkt->op_code); + log_it(L_NOTICE, "Removed sock_id %d from the epoll fd", remote_sock_id); + //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=0",sf_pkt->sock_id, sf_pkt->op_code); } - pthread_mutex_unlock(&sf_socks_mutex); + pthread_mutex_unlock(&s_sf_socks_mutex); + pthread_mutex_unlock(&sf_sock->mutex); stream_sf_socket_delete(sf_sock); - } else { - sf_sock->bytes_sent += ret; + } + break; + default: { + log_it(L_WARNING, "Unprocessed op code 0x%02x", sf_pkt->header.op_code); pthread_mutex_unlock(&sf_sock->mutex); } - //log_it(L_INFO, "Send action from %d sock_id (sf_packet size %lu, ch packet size %lu, have sent %d)" - // , sf_sock->id, sf_pkt->header.op_data.data_size, pkt->hdr.size, ret); - } - break; - case VPN_PACKET_OP_CODE_DISCONNECT: { - log_it(L_INFO, "Disconnect action from %d sock_id", sf_sock->id); - - pthread_mutex_lock(&( CH_VPN(ch)->mutex)); - HASH_DEL(CH_VPN(ch)->socks, sf_sock); - pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); - - pthread_mutex_lock(&sf_socks_mutex); - HASH_DELETE(hh2, sf_socks, sf_sock); - HASH_DELETE(hh_sock, sf_socks_client, sf_sock); - struct epoll_event ev; - ev.data.fd = sf_sock->sock; - ev.events = EPOLLIN; - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_DEL, sf_sock->sock, &ev) < 0) { - log_it(L_ERROR, "Can't remove sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); - } else { - log_it(L_NOTICE, "Removed sock_id %d from the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=0",sf_pkt->sock_id, sf_pkt->op_code); } - pthread_mutex_unlock(&sf_socks_mutex); - - pthread_mutex_unlock(&sf_sock->mutex); - stream_sf_socket_delete(sf_sock); - } - break; - default: { - log_it(L_WARNING, "Unprocessed op code 0x%02x", sf_pkt->header.op_code); - pthread_mutex_unlock(&sf_sock->mutex); - } - } - } //else - // log_it(L_WARNING, "Packet input: packet with sock_id %d thats not present in current stream channel", - // remote_sock_id); - } else { - HASH_FIND_INT(CH_VPN(ch)->socks, &remote_sock_id, sf_sock); - if(sf_sock) { - log_it(L_WARNING, "Socket id %d is already used, take another number for socket id", remote_sock_id); - } else { // Connect action - struct sockaddr_in remote_addr; - char addr_str[1024]; - size_t addr_str_size = - (sf_pkt->header.op_connect.addr_size > (sizeof(addr_str) - 1)) ? - (sizeof(addr_str) - 1) : - sf_pkt->header.op_connect.addr_size; - memset(&remote_addr, 0, sizeof(remote_addr)); - remote_addr.sin_family = AF_INET; - remote_addr.sin_port = htons(sf_pkt->header.op_connect.port); - - memcpy(addr_str, sf_pkt->data, addr_str_size); - addr_str[addr_str_size] = 0; - - log_it(L_DEBUG, "Connect action to %s:%u (addr_size %lu)", addr_str, sf_pkt->header.op_connect.port, - sf_pkt->header.op_connect.addr_size); - if(inet_pton(AF_INET, addr_str, &(remote_addr.sin_addr)) < 0) { - log_it(L_ERROR, "Wrong remote address '%s:%u'", addr_str, sf_pkt->header.op_connect.port); - } else { - int s; - if((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0) { - log_it(L_DEBUG, "Socket is created (%d)", s); - if(connect(s, (struct sockaddr *) &remote_addr, sizeof(remote_addr)) >= 0) { - fcntl(s, F_SETFL, O_NONBLOCK); - log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", addr_str, - sf_pkt->header.op_connect.port, remote_sock_id); - ch_vpn_socket_proxy_t * sf_sock = NULL; - sf_sock = DAP_NEW_Z(ch_vpn_socket_proxy_t); - sf_sock->id = remote_sock_id; - sf_sock->sock = s; - sf_sock->ch = ch; - pthread_mutex_init(&sf_sock->mutex, NULL); - - pthread_mutex_lock(&sf_socks_mutex); - pthread_mutex_lock(&( CH_VPN(ch)->mutex)); - HASH_ADD_INT(CH_VPN(ch)->socks, id, sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh2, sf_socks, id, sizeof(sf_sock->id), sf_sock); - log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, - sf_sock->sock); - HASH_ADD(hh_sock, sf_socks_client, sock, sizeof(int), sf_sock); - //log_it(L_DEBUG,"Added %d sock_id with sock %d to the socks hash table",sf->id,sf->sock); - pthread_mutex_unlock(&sf_socks_mutex); - pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); - - struct epoll_event ev; - ev.data.fd = s; - ev.events = EPOLLIN | EPOLLERR; - - if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_ADD, s, &ev) == -1) { - log_it(L_ERROR, "Can't add sock_id %d to the epoll fd", remote_sock_id); - //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); + } //else + // log_it(L_WARNING, "Packet input: packet with sock_id %d thats not present in current stream channel", + // remote_sock_id); + } else { + HASH_FIND_INT(CH_VPN(ch)->socks, &remote_sock_id, sf_sock); + if(sf_sock) { + log_it(L_WARNING, "Socket id %d is already used, take another number for socket id", remote_sock_id); + } else { // Connect action + struct sockaddr_in remote_addr; + char addr_str[1024]; + size_t addr_str_size = + (sf_pkt->header.op_connect.addr_size > (sizeof(addr_str) - 1)) ? + (sizeof(addr_str) - 1) : + sf_pkt->header.op_connect.addr_size; + memset(&remote_addr, 0, sizeof(remote_addr)); + remote_addr.sin_family = AF_INET; + remote_addr.sin_port = htons(sf_pkt->header.op_connect.port); + + memcpy(addr_str, sf_pkt->data, addr_str_size); + addr_str[addr_str_size] = 0; + + log_it(L_DEBUG, "Connect action to %s:%u (addr_size %lu)", addr_str, sf_pkt->header.op_connect.port, + sf_pkt->header.op_connect.addr_size); + if(inet_pton(AF_INET, addr_str, &(remote_addr.sin_addr)) < 0) { + log_it(L_ERROR, "Wrong remote address '%s:%u'", addr_str, sf_pkt->header.op_connect.port); + } else { + int s; + if((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0) { + log_it(L_DEBUG, "Socket is created (%d)", s); + if(connect(s, (struct sockaddr *) &remote_addr, sizeof(remote_addr)) >= 0) { + fcntl(s, F_SETFL, O_NONBLOCK); + log_it(L_INFO, "Remote address connected (%s:%u) with sock_id %d", addr_str, + sf_pkt->header.op_connect.port, remote_sock_id); + ch_vpn_socket_proxy_t * sf_sock = NULL; + sf_sock = DAP_NEW_Z(ch_vpn_socket_proxy_t); + sf_sock->id = remote_sock_id; + sf_sock->sock = s; + sf_sock->ch = ch; + pthread_mutex_init(&sf_sock->mutex, NULL); + + pthread_mutex_lock(&s_sf_socks_mutex); + pthread_mutex_lock(&( CH_VPN(ch)->mutex)); + HASH_ADD_INT(CH_VPN(ch)->socks, id, sf_sock); + log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, + sf_sock->sock); + HASH_ADD(hh2, sf_socks, id, sizeof(sf_sock->id), sf_sock); + log_it(L_DEBUG, "Added %d sock_id with sock %d to the hash table", sf_sock->id, + sf_sock->sock); + HASH_ADD(hh_sock, sf_socks_client, sock, sizeof(int), sf_sock); + //log_it(L_DEBUG,"Added %d sock_id with sock %d to the socks hash table",sf->id,sf->sock); + pthread_mutex_unlock(&s_sf_socks_mutex); + pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); + + struct epoll_event ev; + ev.data.fd = s; + ev.events = EPOLLIN | EPOLLERR; + + if(epoll_ctl(sf_socks_epoll_fd, EPOLL_CTL_ADD, s, &ev) == -1) { + log_it(L_ERROR, "Can't add sock_id %d to the epoll fd", remote_sock_id); + //stream_ch_pkt_write_f(ch,'i',"sock_id=%d op_code=%uc result=-2",sf_pkt->sock_id, sf_pkt->op_code); + } else { + log_it(L_NOTICE, "Added sock_id %d with sock %d to the epoll fd", remote_sock_id, s); + log_it(L_NOTICE, "Send Connected packet to User"); + ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); + pkt_out->header.sock_id = remote_sock_id; + pkt_out->header.op_code = VPN_PACKET_OP_CODE_CONNECTED; + dap_stream_ch_pkt_write(ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT, pkt_out, + pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); + free(pkt_out); + client_connected = true; + } + stream_sf_socket_ready_to_write(ch, true); } else { - log_it(L_NOTICE, "Added sock_id %d with sock %d to the epoll fd", remote_sock_id, s); - log_it(L_NOTICE, "Send Connected packet to User"); - ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header)); - pkt_out->header.sock_id = remote_sock_id; - pkt_out->header.op_code = VPN_PACKET_OP_CODE_CONNECTED; - dap_stream_ch_pkt_write(ch, SERVICE_CHANNEL_ID, pkt_out, - pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - free(pkt_out); - client_connected = true; + log_it(L_INFO, "Can't connect to the remote server %s", addr_str); + dap_stream_ch_pkt_write_f(ch, 'i', "sock_id=%d op_code=%c result=-1", + sf_pkt->header.sock_id, sf_pkt->header.op_code); + stream_sf_socket_ready_to_write(ch, true); } - stream_sf_socket_ready_to_write(ch, true); } else { - log_it(L_INFO, "Can't connect to the remote server %s", addr_str); - dap_stream_ch_pkt_write_f(ch, 'i', "sock_id=%d op_code=%c result=-1", - sf_pkt->header.sock_id, sf_pkt->header.op_code); - stream_sf_socket_ready_to_write(ch, true); + log_it(L_ERROR, "Can't create the socket"); } - } else { - log_it(L_ERROR, "Can't create the socket"); } } } @@ -723,9 +743,9 @@ void * srv_ch_sf_thread(void * arg) int s = events[n].data.fd; ch_vpn_socket_proxy_t * sf = NULL; - pthread_mutex_lock(&sf_socks_mutex); + pthread_mutex_lock(&s_sf_socks_mutex); HASH_FIND(hh_sock, sf_socks_client, &s, sizeof(s), sf); - pthread_mutex_unlock(&sf_socks_mutex); + pthread_mutex_unlock(&s_sf_socks_mutex); if(sf) { if(events[n].events & EPOLLERR) { log_it(L_NOTICE, "Socket id %d has EPOLLERR flag on", s); @@ -784,9 +804,9 @@ void * srv_ch_sf_thread(void * arg) **/ void* srv_ch_sf_thread_raw(void *arg) { - srv_ch_sf_tun_create(); + s_tun_create(); - if(raw_server->tun_fd <= 0) { + if(s_raw_server->tun_fd <= 0) { log_it(L_CRITICAL, "Tun/tap file descriptor is not initialized"); return NULL; } @@ -810,7 +830,7 @@ void* srv_ch_sf_thread_raw(void *arg) fd_set fds_read, fds_read_active; FD_ZERO(&fds_read); - FD_SET(raw_server->tun_fd, &fds_read); + FD_SET(s_raw_server->tun_fd, &fds_read); FD_SET(get_select_breaker(), &fds_read); /// Main cycle do { @@ -821,7 +841,7 @@ void* srv_ch_sf_thread_raw(void *arg) if(FD_ISSET(get_select_breaker(), &fds_read_active)) { // Smth to send ch_vpn_pkt_t* pkt = srv_ch_sf_raw_read(); if(pkt) { - int write_ret = write(raw_server->tun_fd, pkt->data, pkt->header.op_data.data_size); + int write_ret = write(s_raw_server->tun_fd, pkt->data, pkt->header.op_data.data_size); if(write_ret > 0) { //log_it(L_DEBUG, "Wrote out %d bytes to the tun/tap interface", write_ret); } else { @@ -830,8 +850,8 @@ void* srv_ch_sf_thread_raw(void *arg) } } } - if(FD_ISSET(raw_server->tun_fd, &fds_read_active)) { - int read_ret = read(raw_server->tun_fd, tmp_buf, tun_MTU); + if(FD_ISSET(s_raw_server->tun_fd, &fds_read_active)) { + int read_ret = read(s_raw_server->tun_fd, tmp_buf, tun_MTU); if(read_ret < 0) { log_it(L_CRITICAL, "Tun/tap read returned '%s' error, code (%d)", strerror(errno), read_ret); break; @@ -847,21 +867,21 @@ void* srv_ch_sf_thread_raw(void *arg) //log_it(L_DEBUG, "Read IP packet from tun/tap interface daddr=%s saddr=%s total_size = %d " // , str_daddr, str_saddr, read_ret); dap_stream_ch_vpn_remote_single_t * raw_client = NULL; - pthread_mutex_lock(&raw_server->clients_mutex); - HASH_FIND_INT(raw_server->clients, &in_daddr.s_addr, raw_client); + pthread_mutex_lock(&s_raw_server->clients_mutex); + HASH_FIND_INT(s_raw_server->clients, &in_daddr.s_addr, raw_client); // HASH_ADD_INT(CH_SF(ch)->socks, id, sf_sock ); // HASH_DEL(CH_SF(ch)->socks,sf_sock); if(raw_client) { // Is present in hash table such destination address ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + read_ret); pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_RECV; - pkt_out->header.sock_id = raw_server->tun_fd; + pkt_out->header.sock_id = s_raw_server->tun_fd; pkt_out->header.op_data.data_size = read_ret; memcpy(pkt_out->data, tmp_buf, read_ret); - dap_stream_ch_pkt_write(raw_client->ch, DATA_CHANNEL_ID, pkt_out, + dap_stream_ch_pkt_write(raw_client->ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); stream_sf_socket_ready_to_write(raw_client->ch, true); } - pthread_mutex_unlock(&raw_server->clients_mutex); + pthread_mutex_unlock(&s_raw_server->clients_mutex); } }/*else { log_it(L_CRITICAL,"select() has no tun handler in the returned set"); @@ -874,7 +894,7 @@ void* srv_ch_sf_thread_raw(void *arg) } } while(1); log_it(L_NOTICE, "Raw sockets listen thread is stopped"); - srv_ch_sf_tun_destroy(); + s_tun_destroy(); return NULL; } @@ -898,7 +918,7 @@ void srv_ch_sf_packet_out(dap_stream_ch_t* ch, void* arg) for(i = 0; i < cur->pkt_out_size; i++) { ch_vpn_pkt_t * pout = cur->pkt_out[i]; if(pout) { - if(dap_stream_ch_pkt_write(ch, DATA_CHANNEL_ID, pout, + if(dap_stream_ch_pkt_write(ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pout, pout->header.op_data.data_size + sizeof(pout->header))) { isSmthOut = true; free(pout); @@ -925,10 +945,10 @@ void srv_ch_sf_packet_out(dap_stream_ch_t* ch, void* arg) HASH_DEL(CH_VPN(ch)->socks, cur); pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); - pthread_mutex_lock(&(sf_socks_mutex)); + pthread_mutex_lock(&(s_sf_socks_mutex)); HASH_DELETE(hh2, sf_socks, cur); HASH_DELETE(hh_sock, sf_socks_client, cur); - pthread_mutex_unlock(&(sf_socks_mutex)); + pthread_mutex_unlock(&(s_sf_socks_mutex)); pthread_mutex_unlock(&(cur->mutex)); stream_sf_socket_delete(cur); diff --git a/dap_chain_net_srv_vpn.h b/dap_chain_net_srv_vpn.h index 9cf9bee52740e67c617d66e770bb3d36f321bfba..115faaaec4390e2a22d93591ef4871189c2feac8 100755 --- a/dap_chain_net_srv_vpn.h +++ b/dap_chain_net_srv_vpn.h @@ -28,6 +28,12 @@ #include "dap_config.h" #include "dap_chain_net_srv.h" + +#define DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_CLIENT 0x01 +#define DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA 0x02 + +#define DAP_STREAM_CH_ID_NET_SRV_VPN 'S' + #define DAP_CHAIN_NET_SRV_VPN_ID 0x0000000000000001 #define VPN_PACKET_OP_CODE_CONNECTED 0x000000a9 @@ -140,6 +146,6 @@ typedef struct dap_chain_net_srv_vpn #define CH_VPN(a) ((dap_chain_net_srv_vpn_t *) ((a)->internal) ) int dap_chain_net_srv_vpn_init(dap_config_t * g_config); -void dap_chain_net_srv_vpn_deinit(); +void dap_chain_net_srv_vpn_deinit(void); diff --git a/dap_chain_net_srv_vpn_cdb.c b/dap_chain_net_srv_vpn_cdb.c new file mode 100644 index 0000000000000000000000000000000000000000..9e1e4dc68cf8b1274d06c923d3dbc17e8334d459 --- /dev/null +++ b/dap_chain_net_srv_vpn_cdb.c @@ -0,0 +1,294 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * CellFrame https://cellframe.net + * Sources https://gitlab.demlabs.net/cellframe + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of CellFrame SDK the open source project + + CellFrame SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CellFrame SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + 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 + along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#include "utlist.h" +#include "dap_common.h" +#include "dap_config.h" +#include "dap_enc_http.h" +#include "dap_http.h" + +#include "db_core.h" +#include "db_auth.h" +#include "db_http.h" +#include "db_http_file.h" + +#include "dap_chain.h" +#include "dap_chain_net.h" +#include "dap_chain_ledger.h" +#include "dap_chain_wallet.h" +#include "dap_chain_datum_tx.h" +#include "dap_chain_datum_tx_in.h" +#include "dap_chain_datum_tx_in_cond.h" +#include "dap_chain_datum_tx_out_cond.h" +#include "dap_chain_datum_tx_out.h" +#include "dap_chain_datum_tx_pkey.h" +#include "dap_chain_datum_tx_receipt.h" +#include "dap_chain_datum_tx_sig.h" +#include "dap_chain_global_db.h" +#include "dap_pkey.h" + +#include "dap_chain_net_srv_vpn_cdb.h" +#include "dap_chain_net_srv_vpn_cdb_server_list.h" + + +#define LOG_TAG "dap_chain_net_srv_vpn_cdb" + +#define DB_URL "/db" +#define DB_FILE_URL "/db_file" +#define SLIST_URL "/nodelist" + +typedef struct tx_cond_template{ + char * wallet_name; + dap_chain_wallet_t * wallet; + + long double value_coins; + uint128_t value_datoshi; + + char * token_ticker; + char * net_name; + dap_chain_net_t * net; + dap_ledger_t * ledger; + time_t min_time; // Minimum time between transactions + + struct tx_cond_template * prev; + struct tx_cond_template * next; +} tx_cond_template_t; + +static tx_cond_template_t * s_tx_cond_templates = NULL; +const char *c_wallets_path = NULL; + +static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg); + +/** + * @brief dap_chain_net_srv_vpn_cdb_init + * @return + */ +int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http) +{ + int rc; + int ret=0; + c_wallets_path = dap_chain_wallet_get_path(g_config); + if (dap_config_get_item_bool_default( g_config, + "cdb", + "servers_list_enabled", + false)) { + + if (dap_chain_net_srv_vpn_cdb_server_list_init() != 0) { + log_it(L_CRITICAL,"Can't init vpn servers list"); + return -10; + } + } + + + if((rc=db_core_init(dap_config_get_item_str_default(g_config, + "cdb", + "db_path", + "mongodb://localhost/db")))!=0 ){ + log_it(L_CRITICAL,"Can't init CDB module, return code %d",rc); + return -3; + } + db_http_add_proc( a_http , DB_URL ); + db_http_file_proc_add( a_http , DB_FILE_URL ); + + // Load all chain networks + if (dap_config_get_item_bool_default( g_config, + "cdb", + "servers_list_enabled", + false)) { + dap_chain_net_srv_vpn_cdb_server_list_add_proc ( a_http, SLIST_URL); + } + if( dap_config_get_item_bool_default( g_config,"cdb_auth","enabled",false) ){ + db_auth_init( dap_config_get_item_str_default(g_config,"cdb_auth","collection_name","cdb") ); + // Produce transaction for authorized users + if (dap_config_get_item_bool_default( g_config, + "cdb_auth", + "tx_cond_create", + false)) { + + // Parse tx cond templates + size_t l_tx_cond_tpls_count=0; + char ** l_tx_cond_tpls =dap_config_get_array_str( g_config,"cdb_auth", "tx_cond_templates",&l_tx_cond_tpls_count); + for ( size_t i = 0 ; i< l_tx_cond_tpls_count; i++){ + char * l_wallet_name = NULL; + long double l_value = 0.0L; + char * l_token_ticker = NULL; + char * l_net_name = NULL; + int l_step = 0; + time_t l_min_time = 0; + char * l_tpl_parse_old = l_tx_cond_tpls[i]; + // Parse template entries + for(char * l_tpl_parse = index(l_tx_cond_tpls[i],':'); l_tpl_parse ;l_tpl_parse = index(l_tpl_parse,':') ){ + size_t l_tpl_entry_size = l_tpl_parse - l_tpl_parse_old; + if (l_tpl_entry_size){ // if not empty entry + char *l_tpl_entry = DAP_NEW_Z_SIZE(char,l_tpl_entry_size); + strncpy(l_tpl_entry,l_tpl_parse_old,l_tpl_entry_size-1); + switch ( l_step) { // Parse entries by order + case 0: l_wallet_name = l_tpl_entry; break; + case 1: l_value = strtold( l_tpl_entry, NULL); DAP_DELETE( l_tpl_entry); break; + case 2: l_min_time =(time_t) atoll(l_tpl_entry); DAP_DELETE( l_tpl_entry); break; + case 3: l_token_ticker = l_tpl_entry; break; + case 4: l_net_name = l_tpl_entry; break; + default: log_it( L_WARNING, "Too many ':' (%d) characters in condition template", l_step); + } + l_step++; + if( l_step > 4) + break; + } + l_tpl_parse_old = l_tpl_parse; + } + // If all what we need is present + if ( l_step >4 ) { + if ( l_wallet_name && l_value > 0.0L && l_token_ticker && l_net_name && l_min_time){ + // we create condition template + tx_cond_template_t * l_tx_cond_template = DAP_NEW_Z(tx_cond_template_t); + + l_tx_cond_template->wallet = dap_chain_wallet_open( l_wallet_name,c_wallets_path ); + if( l_tx_cond_template->wallet){ + l_tx_cond_template->wallet_name = l_wallet_name; + + l_tx_cond_template->net = dap_chain_net_by_name( l_net_name ); + if ( l_tx_cond_template->net){ + l_tx_cond_template->net_name = l_net_name; + l_tx_cond_template->ledger = dap_chain_ledger_by_net_name( l_net_name ); + if ( l_tx_cond_template->ledger ){ + l_tx_cond_template->min_time = l_min_time; + l_tx_cond_template->value_coins = l_value; + l_tx_cond_template->value_datoshi = dap_chain_coins_to_balance ( l_value ); + l_tx_cond_template->token_ticker = l_token_ticker; + // and put it in list + l_tx_cond_template->prev = s_tx_cond_templates; + if ( s_tx_cond_templates) + s_tx_cond_templates->next = l_tx_cond_template; + s_tx_cond_templates = l_tx_cond_template; + }else{ + log_it(L_ERROR, "Can't open ledger in network \"%s\" for condition transaction template \"%s\"", l_net_name, l_tx_cond_tpls[i]); + DAP_DELETE( l_wallet_name ); + DAP_DELETE( l_net_name); + DAP_DELETE( l_token_ticker); + DAP_DELETE( l_tx_cond_template); + l_tx_cond_template = NULL; + ret = -4; + } + }else{ + log_it(L_ERROR, "Can't open network \"%s\" for condition transaction template \"%s\"", l_net_name, l_tx_cond_tpls[i]); + DAP_DELETE( l_wallet_name ); + DAP_DELETE( l_net_name); + DAP_DELETE( l_token_ticker); + DAP_DELETE( l_tx_cond_template); + l_tx_cond_template = NULL; + ret = -2; + } + }else{ + log_it(L_ERROR, "Can't open wallet \"%s\" for condition transaction template \"%s\"", l_wallet_name, l_tx_cond_tpls[i]); + DAP_DELETE( l_wallet_name ); + DAP_DELETE( l_net_name); + DAP_DELETE( l_token_ticker); + DAP_DELETE( l_tx_cond_template); + l_tx_cond_template = NULL; + ret = -3; + } + } + } + } + if ( l_tx_cond_tpls_count ) + db_auth_set_callbacks( s_auth_callback ); + else{ + log_it( L_ERROR, "No condition tpl, can't setup auth callback"); + ret=-1; + } + } + } + + return ret; +} + +/** + * @brief dap_chain_net_srv_vpn_cdb_deinit + */ +void dap_chain_net_srv_vpn_cdb_deinit() +{ + +} + + + +/** + * @brief s_auth_callback + * @param a_delegate + * @param a_arg + */ +static void s_auth_callback(enc_http_delegate_t* a_delegate, void * a_arg) +{ + db_auth_info_t *l_auth_info = (db_auth_info_t *) a_arg; + log_it( L_DEBUG, "Authorized, now need to create conditioned transaction if not present"); + + for ( tx_cond_template_t * l_tpl = s_tx_cond_templates; l_tpl; l_tpl=l_tpl->next) { + enc_http_reply_f(a_delegate,"\t<tx_cond_tpl>\n"); + enc_http_reply_f(a_delegate,"\t\t<net>%s</net>\n",l_tpl->net_name); + enc_http_reply_f(a_delegate,"\t\t<token>%s</token>\n",l_tpl->token_ticker); + + size_t l_gdb_group_size=0; + + // Try to load from gdb + char * l_tx_cond_gdb_group = dap_strdup_printf("%s.%s.tx_cond", l_tpl->net->pub.name, DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX ); + dap_chain_hash_fast_t * l_tx_cond_hash = (dap_hash_type_t*) dap_chain_global_db_gr_get( + l_auth_info->user,&l_gdb_group_size, l_tx_cond_gdb_group ); + + // Check for entry size + if (l_gdb_group_size && l_gdb_group_size != sizeof (dap_chain_hash_fast_t) ){ + log_it(L_ERROR, "Wrong size of tx condition on database (%zd but expected %zd), may be old entry", + l_gdb_group_size, sizeof (dap_chain_hash_fast_t)); + } + + time_t l_tx_cond_ts = 0; + // If loaded lets check is it spent or not + if ( l_tx_cond_hash ){ + dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash( l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET_UNSPENT ); + if ( ! l_tx ){ // If not found - all outs are used. Create new one + // pass all chains + l_tx = dap_chain_net_get_tx_by_hash( l_tpl->net, l_tx_cond_hash, TX_SEARCH_TYPE_NET ); + DAP_DELETE(l_tx_cond_hash); + l_tx_cond_hash = NULL; + if ( l_tx ){ + l_tx_cond_ts =(time_t) l_tx->header.ts_created; + } + } + + } + // Try to create condition + if (! l_tx_cond_hash ) { + + } + + // If we loaded or created hash + if( l_tx_cond_hash ){ + char * l_tx_cond_hash_str = dap_chain_hash_fast_to_str_new(l_tx_cond_hash); + enc_http_reply_f(a_delegate,"\t\t<tx_cond>%s</tx_cond>\n",l_tx_cond_hash_str); + DAP_DELETE(l_tx_cond_hash); + DAP_DELETE(l_tx_cond_hash_str); + } + enc_http_reply_f(a_delegate,"\t</tx_cond_tpl>\n"); + } + +} diff --git a/dap_chain_net_srv_vpn_cdb.h b/dap_chain_net_srv_vpn_cdb.h new file mode 100644 index 0000000000000000000000000000000000000000..dc0c5842a7ef94d59614df0771ba9c09a0201fa8 --- /dev/null +++ b/dap_chain_net_srv_vpn_cdb.h @@ -0,0 +1,31 @@ +/* + * Authors: + * Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net> + * DeM Labs Inc. https://demlabs.net + * CellFrame https://cellframe.net + * Sources https://gitlab.demlabs.net/cellframe + * Copyright (c) 2017-2019 + * All rights reserved. + + This file is part of CellFrame SDK the open source project + + CellFrame SDK is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + CellFrame SDK is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + 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 + along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ +#pragma once +#include "dap_http.h" + +#define DAP_CHAIN_NET_SRV_VPN_CDB_GDB_PREFIX "local.srv.vpn" + +int dap_chain_net_srv_vpn_cdb_init(dap_http_t * a_http); +void dap_chain_net_srv_vpn_cdb_deinit(); diff --git a/dap_chain_net_srv_vpn_cdb_server_list.c b/dap_chain_net_srv_vpn_cdb_server_list.c index a40e0ec6404d94c99fa8cc613c8dd8010e507df8..87b5cc52148758244cb4552fb2d62311bef86046 100644 --- a/dap_chain_net_srv_vpn_cdb_server_list.c +++ b/dap_chain_net_srv_vpn_cdb_server_list.c @@ -59,13 +59,14 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg); int dap_chain_net_srv_vpn_cdb_server_list_init() { char **l_cdb_networks; - size_t l_cdb_networks_size = 0; + uint16_t l_cdb_networks_count = 0; log_it(L_NOTICE,"Initialized Server List Module"); - l_cdb_networks = dap_config_get_array_str( g_config, "cdb", "networks", &l_cdb_networks_size ); + l_cdb_networks = dap_config_get_array_str( g_config, "cdb", "servers_list_networks", &l_cdb_networks_count ); - if ( l_cdb_networks_size ){ - s_cdb_net = DAP_NEW_Z_SIZE(dap_chain_net_t*, sizeof (dap_chain_net_t*)* l_cdb_networks_size ); - for ( size_t i = 0; i < l_cdb_networks_size ; i++) { + if ( l_cdb_networks_count ){ + s_cdb_net = DAP_NEW_Z_SIZE(dap_chain_net_t*, sizeof (dap_chain_net_t*)* l_cdb_networks_count ); + s_cdb_net_count = l_cdb_networks_count; + for ( size_t i = 0; i < l_cdb_networks_count ; i++) { s_cdb_net[i] = dap_chain_net_by_name( l_cdb_networks[i] ); if ( s_cdb_net[i] ) log_it( L_INFO, "Added \"%s\" network for server list fetchs", l_cdb_networks[i]); @@ -86,7 +87,10 @@ void dap_chain_net_srv_vpn_cdb_server_list_deinit(void) static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) { http_status_code_t * l_ret_code = (http_status_code_t*)a_arg; - dap_http_simple_reply_f( a_http_simple, "[\n"); + dap_string_t *l_reply_str = dap_string_new("[\n"); + + + log_it(L_DEBUG, "Have %zd chain networks for cdb lists", s_cdb_net_count ); for ( size_t i = 0; i < s_cdb_net_count ; i++ ) { dap_chain_net_t * l_net = s_cdb_net[i]; @@ -95,45 +99,47 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) size_t l_orders_count = 0; dap_chain_net_srv_price_unit_uid_t l_unit_uid = {{0}}; dap_chain_net_srv_uid_t l_srv_uid = { .uint64 =DAP_CHAIN_NET_SRV_VPN_ID }; - dap_chain_net_srv_order_find_all_by( l_net, SERV_DIR_SELL, l_srv_uid, SERV_CLASS_PERMANENT ,l_unit_uid ,NULL,0,0, &l_orders, &l_orders_count ); - log_it(L_DEBUG, "Found %sd orders in \"%s\" network", l_orders_count, l_net->pub.name ); + dap_chain_net_srv_order_find_all_by( l_net, SERV_DIR_SELL, l_srv_uid, SERV_CLASS_PERMANENT ,l_unit_uid , + NULL,0,0, &l_orders, &l_orders_count ); + log_it(L_DEBUG, "Found %zd orders in \"%s\" network", l_orders_count, l_net->pub.name ); for ( size_t j = 0; j < l_orders_count ; j++ ) { dap_chain_node_info_t * l_node_info = dap_chain_node_info_read( l_net, &l_orders[j].node_addr ); if ( l_node_info ){ char l_node_ext_ipv4_str[INET_ADDRSTRLEN]={0}; char l_node_ext_ipv6_str[INET6_ADDRSTRLEN]={0}; - inet_ntop(AF_INET,&l_node_info->hdr.ext_addr_v4,l_node_ext_ipv4_str,sizeof(l_node_ext_ipv4_str)); - inet_ntop(AF_INET6,&l_node_info->hdr.ext_addr_v6,l_node_ext_ipv6_str,sizeof(l_node_ext_ipv6_str)); - - dap_http_simple_reply_f( a_http_simple, - " {\n" - " \"Location\":\"NETHERLANDS\",\n" - " \"Name\":\"%s.Cell-%s.%sd\",\n" - " \"Address\":\"%s\",\n" - " \"Address6\":\"%s\",\n" - " \"Port\":%hu,\n" - " \"Description\":\"%s\",\n" - " \"Price\":%lu,\n" - " \"PriceUnits\":%u,\n" - " \"PriceToken\":\"%s\"\n" - " },\n", - l_net->pub.name, l_node_info->hdr.cell_id.uint64, j, - l_node_ext_ipv4_str, - l_node_ext_ipv6_str, - l_node_info->hdr.ext_port, - l_orders[j].ext, - l_orders[j].price, - l_orders[j].price_unit.uint32, - l_orders[j].price_ticker - ); + if (l_node_info->hdr.ext_addr_v4.s_addr) + inet_ntop(AF_INET,&l_node_info->hdr.ext_addr_v4,l_node_ext_ipv4_str,sizeof(l_node_ext_ipv4_str)); + if ( *((uint128_t *) l_node_info->hdr.ext_addr_v6.__in6_u.__u6_addr8 ) ) + inet_ntop(AF_INET6,&l_node_info->hdr.ext_addr_v6,l_node_ext_ipv6_str,sizeof(l_node_ext_ipv6_str)); + dap_string_append_printf( l_reply_str, " {\n"); + + dap_string_append_printf( l_reply_str, " \"Location\":\"NETHERLANDS\",\n"); + dap_string_append_printf( l_reply_str, " \"ChainNet\":\"%s\",\n",l_net->pub.name ); + dap_string_append_printf( l_reply_str, " \"Name\":\"%s.Cell-%lu.%zd\",\n",l_net->pub.name, l_node_info->hdr.cell_id.uint64, j); + if ( l_node_ext_ipv4_str[0] ) + dap_string_append_printf( l_reply_str," \"Address\":\"%s\",\n",l_node_ext_ipv4_str); + if ( l_node_ext_ipv6_str[0] ) + dap_string_append_printf( l_reply_str, " \"Address6\":\"%s\",\n",l_node_ext_ipv6_str); + dap_string_append_printf( l_reply_str, " \"Port\":%hu,\n",l_node_info->hdr.ext_port?l_node_info->hdr.ext_port:80); + dap_string_append_printf( l_reply_str, " \"Ext\":\"%s\",\n",l_orders[j].ext); + dap_string_append_printf( l_reply_str, " \"Price\":%lu,\n",l_orders[j].price); + dap_string_append_printf( l_reply_str, " \"PriceUnits\":%u,\n",l_orders[j].price_unit.uint32); + dap_string_append_printf( l_reply_str, " \"PriceToken\":\"%s\"\n",l_orders[j].price_ticker); + if ( j != l_orders_count-1) + dap_string_append_printf( l_reply_str, " },\n"); + else + dap_string_append_printf( l_reply_str, " }\n"); }else - log_it( L_WARNING, "Order %sd in \"%s\" network issued by node without ext_ipv4 field"); + log_it( L_WARNING, "Order %zd in \"%s\" network issued by node without ext_ipv4 field",j,l_net->pub.name); } } } - dap_http_simple_reply_f( a_http_simple, "]\n"); + dap_string_append_printf( l_reply_str, "]\n\n"); + dap_http_simple_reply( a_http_simple, l_reply_str->str, l_reply_str->len ); + dap_string_free(l_reply_str, true); + //log_it(L_DEBUG,"Reply in buffer: %s", a_http_simple->reply_str ); *l_ret_code = Http_Status_OK; } @@ -145,5 +151,5 @@ static void s_http_simple_proc(dap_http_simple_t *a_http_simple, void *a_arg) */ void dap_chain_net_srv_vpn_cdb_server_list_add_proc(dap_http_t *a_http, const char *a_url) { - dap_http_simple_proc_add(a_http,a_url,1000000,s_http_simple_proc); + dap_http_simple_proc_add(a_http,a_url,100000,s_http_simple_proc); } diff --git a/dap_chain_net_srv_vpn_cdb_server_list.h b/dap_chain_net_srv_vpn_cdb_server_list.h index ed45ed384ffa94bfc8f9806e8f7f3d110bb27b00..6aaacc975870a5f18986c1754649272a6a9731e0 100644 --- a/dap_chain_net_srv_vpn_cdb_server_list.h +++ b/dap_chain_net_srv_vpn_cdb_server_list.h @@ -8,20 +8,20 @@ * Copyright (c) 2017-2019 * All rights reserved. - This file is part of DAP (Deus Applications Prototypes) the open source project + This file is part of CellFrame SDK the open source project - DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify + CellFrame SDK is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - DAP is distributed in the hope that it will be useful, + CellFrame SDK is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 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 - along with any DAP based project. If not, see <http://www.gnu.org/licenses/>. + along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #pragma once diff --git a/dap_chain_net_vpn_client.c b/dap_chain_net_vpn_client.c index e378db5402cc2abfa7e537244599255e869b12ec..6ffa1cf15aa45c33d5fba3202e315c2edb701a21 100644 --- a/dap_chain_net_vpn_client.c +++ b/dap_chain_net_vpn_client.c @@ -68,14 +68,49 @@ static pthread_mutex_t sf_socks_mutex; static dap_chain_node_info_t *s_node_info = NULL; static dap_chain_node_client_t *s_vpn_client = NULL; -dap_stream_ch_t* dap_chain_net_vpn_client_get_stream(void) +dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void) { if(!s_vpn_client) return NULL; - dap_stream_ch_t *l_stream = dap_client_get_stream_ch(s_vpn_client->client, VPN_CLIENT_ID); + dap_stream_ch_t *l_stream = dap_client_get_stream_ch(s_vpn_client->client, DAP_STREAM_CH_ID_NET_SRV_VPN ); return l_stream; } + + +/// TODO convert below callback to processor of stage +/* +void s_stage_callback() +{ + char* l_full_path = NULL; + const char * l_path = "stream"; + const char *l_suburl = "globaldb"; + int l_full_path_size = snprintf(l_full_path, 0, "%s/%s?session_id=%s", DAP_UPLINK_PATH_STREAM, l_suburl, + dap_client_get_stream_id(a_client_pvt->client)); + l_full_path = DAP_NEW_Z_SIZE(char, l_full_path_size + 1); + snprintf(l_full_path, l_full_path_size + 1, "%s/%s?session_id=%s", DAP_UPLINK_PATH_STREAM, l_suburl, + dap_client_get_stream_id(a_client_pvt->client)); + + //dap_client_request(a_client_pvt->client, l_full_path, "12345", 0, m_stream_response, m_stream_error); + + const char *l_add_str = ""; + // if connect to vpn server + const char l_active_vpn_channels[] = { VPN_CLIENT_ID, 0 }; + if(!dap_strcmp(a_client_pvt->active_channels, l_active_vpn_channels)) + l_add_str = "\r\nService-Key: test"; + + { + char *l_message = dap_strdup_printf("GET /%s HTTP/1.1\r\nHost: %s:%d%s\r\n\r\n", + l_full_path, a_client_pvt->uplink_addr, a_client_pvt->uplink_port, l_add_str); + size_t l_message_size = dap_strlen(l_message); + int count = send(a_client_pvt->stream_socket, l_message, l_message_size, 0); + DAP_DELETE(l_message); + } + DAP_DELETE(l_full_path); + +}*/ + + /** * Start VPN client * @@ -101,11 +136,14 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st s_node_info->hdr.ext_port = a_port; dap_client_stage_t l_stage_target = STAGE_STREAM_STREAMING; //DAP_CLIENT_STAGE_STREAM_CTL;//STAGE_STREAM_STREAMING; - const char l_active_channels[] = { VPN_CLIENT_ID, 0 }; + const char l_active_channels[] = { DAP_STREAM_CH_ID_NET_SRV_VPN , 0 }; if(a_ipv4_str) inet_pton(AF_INET, a_ipv4_str, &(s_node_info->hdr.ext_addr_v4)); if(a_ipv6_str) inet_pton(AF_INET6, a_ipv6_str, &(s_node_info->hdr.ext_addr_v6)); + + + s_vpn_client = dap_chain_client_connect(s_node_info, l_stage_target, l_active_channels); if(!s_vpn_client) { log_it(L_ERROR, "Can't connect to VPN server=%s:%d", a_ipv4_str, a_port); @@ -132,8 +170,8 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st // send first packet to server // if(0) { - dap_stream_ch_t *l_stream = dap_chain_net_vpn_client_get_stream(); - if(l_stream) { // Is present in hash table such destination address + dap_stream_ch_t *l_ch = dap_chain_net_vpn_client_get_stream_ch(); + if(l_ch) { // Is present in hash table such destination address size_t l_ipv4_str_len = 0; //dap_strlen(a_ipv4_str); ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + l_ipv4_str_len); @@ -142,9 +180,9 @@ int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_st //pkt_out->header.op_connect.addr_size = l_ipv4_str_len; //remoteAddrBA.length(); //pkt_out->header.op_connect.port = a_port; //memcpy(pkt_out->data, a_ipv4_str, l_ipv4_str_len); - dap_stream_ch_pkt_write(l_stream, DATA_CHANNEL_ID, pkt_out, + dap_stream_ch_pkt_write(l_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); - dap_stream_ch_set_ready_to_write(l_stream, true); + dap_stream_ch_set_ready_to_write(l_ch, true); DAP_DELETE(pkt_out); } } @@ -240,62 +278,16 @@ static void send_pong_pkt(dap_stream_ch_t* a_ch) } /** - * @brief ch_sf_new Callback to constructor of object of Ch - * @param ch - * @param arg - */ -static void ch_sf_new(dap_stream_ch_t* a_ch, void* arg) -{ - log_it(L_INFO, "SF channel created"); - - a_ch->internal = DAP_NEW_Z(dap_chain_net_srv_vpn_t); - dap_chain_net_srv_vpn_t * l_sf = CH_VPN(a_ch); - l_sf->ch = a_ch; - pthread_mutex_init(&l_sf->mutex, NULL); - - pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - - l_sf->raw_l3_sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW); - //a_ch->stream->events_socket->is_pingable = true; //set up connection to be pingable by main loop - -} - -/** - * @brief ch_sf_delete - * @param ch - * @param arg - */ -static void ch_sf_delete(dap_stream_ch_t* a_ch, void* arg) -{ - - log_it(L_DEBUG, "ch_sf_delete() for %s", a_ch->stream->events_socket->hostaddr); - /* ch_vpn_socket_proxy_t * cur, *tmp; - ch_sf_tun_delete(CH_SF(a_ch)); - HASH_ITER(hh, CH_SF(a_ch)->socks , cur, tmp) { - log_it(L_DEBUG,"delete socket: %i", cur->sock); - HASH_DEL(CH_SF(a_ch)->socks,cur); - if (cur) - free(cur); - }*/ - pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); - if(CH_VPN(a_ch)->raw_l3_sock) - close(CH_VPN(a_ch)->raw_l3_sock); -} - -/** - * @brief ch_sf_packet_in - * @param ch - * @param arg + * @brief dap_chain_net_vpn_client_pkt_in + * @param a_ch + * @param a_arg */ -static void ch_sf_packet_in(dap_stream_ch_t* a_ch, void* a_arg) +void dap_chain_net_vpn_client_pkt_in(dap_stream_ch_t* a_ch, dap_stream_ch_pkt_t* a_pkt) { - dap_stream_ch_pkt_t * l_pkt = (dap_stream_ch_pkt_t *) a_arg; - - ch_vpn_pkt_t * l_sf_pkt = (ch_vpn_pkt_t *) l_pkt->data; - size_t l_sf_pkt_data_size = l_pkt->hdr.size - sizeof(l_sf_pkt->header); + ch_vpn_pkt_t * l_sf_pkt = (ch_vpn_pkt_t *) a_pkt->data; + size_t l_sf_pkt_data_size = a_pkt->hdr.size - sizeof(l_sf_pkt->header); - if(!l_pkt->hdr.size) { + if(!a_pkt->hdr.size) { log_it(L_WARNING, "Bad input packet"); return; } @@ -381,7 +373,7 @@ static void ch_sf_packet_in(dap_stream_ch_t* a_ch, void* a_arg) pthread_mutex_unlock(&sf_sock->mutex); } log_it(L_INFO, "Send action from %d sock_id (sf_packet size %lu, ch packet size %lu, have sent %d)" - , sf_sock->id, l_sf_pkt->header.op_data.data_size, l_pkt->hdr.size, ret); + , sf_sock->id, l_sf_pkt->header.op_data.data_size, a_pkt->hdr.size, ret); } break; case VPN_PACKET_OP_CODE_DISCONNECT: { @@ -530,61 +522,60 @@ static void ch_sf_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } /** - * @brief stream_sf_packet_out Packet Out Ch callback - * @param ch - * @param arg + * @brief dap_chain_net_vpn_client_pkt_out + * @param a_ch */ -static void ch_sf_packet_out(dap_stream_ch_t* ch, void* arg) +void dap_chain_net_vpn_client_pkt_out(dap_stream_ch_t* a_ch) { - ch_vpn_socket_proxy_t * cur = NULL, *tmp; - bool isSmthOut = false; + ch_vpn_socket_proxy_t * l_cur = NULL, *l_tmp; + bool l_is_smth_out = false; // log_it(L_DEBUG,"Socket forwarding packet out callback: %u sockets in hashtable", HASH_COUNT(CH_VPN(ch)->socks) ); - HASH_ITER(hh, CH_VPN(ch)->socks , cur, tmp) + HASH_ITER(hh, CH_VPN(a_ch)->socks , l_cur, l_tmp) { - bool signalToBreak = false; - pthread_mutex_lock(&(cur->mutex)); + bool l_signal_to_break = false; + pthread_mutex_lock(&(l_cur->mutex)); int i; // log_it(L_DEBUG,"Socket with id %d has %u packets in output buffer", cur->id, cur->pkt_out_size ); - if(cur->pkt_out_size) { - for(i = 0; i < cur->pkt_out_size; i++) { - ch_vpn_pkt_t * pout = cur->pkt_out[i]; + if(l_cur->pkt_out_size) { + for(i = 0; i < l_cur->pkt_out_size; i++) { + ch_vpn_pkt_t * pout = l_cur->pkt_out[i]; if(pout) { - if(dap_stream_ch_pkt_write(ch, 'd', pout, pout->header.op_data.data_size + sizeof(pout->header))) { - isSmthOut = true; + if(dap_stream_ch_pkt_write(a_ch, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pout, pout->header.op_data.data_size + sizeof(pout->header))) { + l_is_smth_out = true; if(pout) free(pout); - cur->pkt_out[i] = NULL; + l_cur->pkt_out[i] = NULL; } else { log_it(L_WARNING, "Buffer is overflowed, breaking cycle to let the upper level cycle drop data to the output socket"); - isSmthOut = true; - signalToBreak = true; + l_is_smth_out = true; + l_signal_to_break = true; break; } } } } - if(signalToBreak) { - pthread_mutex_unlock(&(cur->mutex)); + if(l_signal_to_break) { + pthread_mutex_unlock(&(l_cur->mutex)); break; } - cur->pkt_out_size = 0; - if(cur->signal_to_delete) { - log_it(L_NOTICE, "Socket id %d got signal to be deleted", cur->id); - pthread_mutex_lock(&( CH_VPN(ch)->mutex)); - HASH_DEL(CH_VPN(ch)->socks, cur); - pthread_mutex_unlock(&( CH_VPN(ch)->mutex)); + l_cur->pkt_out_size = 0; + if(l_cur->signal_to_delete) { + log_it(L_NOTICE, "Socket id %d got signal to be deleted", l_cur->id); + pthread_mutex_lock(&( CH_VPN(a_ch)->mutex)); + HASH_DEL(CH_VPN(a_ch)->socks, l_cur); + pthread_mutex_unlock(&( CH_VPN(a_ch)->mutex)); pthread_mutex_lock(&(sf_socks_mutex)); - HASH_DELETE(hh2, sf_socks, cur); - HASH_DELETE(hh_sock, sf_socks_client, cur); + HASH_DELETE(hh2, sf_socks, l_cur); + HASH_DELETE(hh_sock, sf_socks_client, l_cur); pthread_mutex_unlock(&(sf_socks_mutex)); - pthread_mutex_unlock(&(cur->mutex)); - vpn_socket_delete(cur); + pthread_mutex_unlock(&(l_cur->mutex)); + vpn_socket_delete(l_cur); } else - pthread_mutex_unlock(&(cur->mutex)); + pthread_mutex_unlock(&(l_cur->mutex)); } /* ch->writable = isSmthOut; if(isSmthOut) { @@ -597,8 +588,6 @@ int dap_chain_net_vpn_client_init(dap_config_t * g_config) { pthread_mutex_init(&sf_socks_mutex, NULL); - dap_stream_ch_proc_add(VPN_CLIENT_ID, ch_sf_new, ch_sf_delete, ch_sf_packet_in, - ch_sf_packet_out); return 0; } diff --git a/dap_chain_net_vpn_client.h b/dap_chain_net_vpn_client.h index e31a0b9cef417bdb581b9e680e6a1b2bb2d48fe2..a75a307f737ace6e859c22fe88ee3bd58e9719b8 100644 --- a/dap_chain_net_vpn_client.h +++ b/dap_chain_net_vpn_client.h @@ -25,9 +25,11 @@ #pragma once #include "dap_stream_ch.h" +#include "dap_stream_ch_pkt.h" #include "dap_chain_net.h" +#include "dap_chain_net_srv_vpn.h" -dap_stream_ch_t* dap_chain_net_vpn_client_get_stream(void); +dap_stream_ch_t* dap_chain_net_vpn_client_get_stream_ch(void); int dap_chain_net_vpn_client_start(dap_chain_net_t *a_net, const char *a_ipv4_str, const char *a_ipv6_str, int a_port); int dap_chain_net_vpn_client_stop(void); @@ -35,3 +37,7 @@ int dap_chain_net_vpn_client_status(void); int dap_chain_net_vpn_client_init(dap_config_t * g_config); void dap_chain_net_vpn_client_deinit(); + + +void dap_chain_net_vpn_client_pkt_out(dap_stream_ch_t* a_ch); +void dap_chain_net_vpn_client_pkt_in(dap_stream_ch_t* a_ch, dap_stream_ch_pkt_t* a_pkt); diff --git a/dap_chain_net_vpn_client_tun.c b/dap_chain_net_vpn_client_tun.c index 68ad35486d3f76597720a88d93014a1bd0b78668..d77b8c35b50867dde707b4e95c1563a9a2a8bbe5 100644 --- a/dap_chain_net_vpn_client_tun.c +++ b/dap_chain_net_vpn_client_tun.c @@ -310,7 +310,7 @@ static void* thread_read_tun(void *arg) // HASH_ADD_INT(CH_SF(ch)->socks, id, sf_sock ); // HASH_DEL(CH_SF(ch)->socks,sf_sock); // if(l_stream) { // Is present in hash table such destination address - dap_stream_ch_t *l_stream = dap_chain_net_vpn_client_get_stream(); + dap_stream_ch_t *l_stream = dap_chain_net_vpn_client_get_stream_ch(); if(l_stream) { // form packet to vpn-server ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + read_ret); @@ -321,7 +321,7 @@ static void* thread_read_tun(void *arg) pthread_mutex_lock(&s_clients_mutex); // sent packet to vpn server - dap_stream_ch_pkt_write(l_stream, DATA_CHANNEL_ID, pkt_out, + dap_stream_ch_pkt_write(l_stream, DAP_STREAM_CH_PKT_TYPE_NET_SRV_VPN_DATA, pkt_out, pkt_out->header.op_data.data_size + sizeof(pkt_out->header)); dap_stream_ch_set_ready_to_write(l_stream, true); pthread_mutex_unlock(&s_clients_mutex);