Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
L
libdap-chain-net-srv-vpn
Manage
Activity
Members
Labels
Plan
Issues
0
Issue boards
Milestones
Wiki
Code
Merge requests
1
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
This is an archived project. Repository and other project resources are read-only.
Show more breadcrumbs
cellframe
libdap-chain-net-srv-vpn
Commits
657f42e1
Commit
657f42e1
authored
5 years ago
by
Aleksandr Lysikov
Browse files
Options
Downloads
Patches
Plain Diff
added vpn service
parent
10476728
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dap_chain_net_srv_vpn.c
+1056
-14
1056 additions, 14 deletions
dap_chain_net_srv_vpn.c
dap_chain_net_srv_vpn.h
+3
-1
3 additions, 1 deletion
dap_chain_net_srv_vpn.h
with
1059 additions
and
15 deletions
dap_chain_net_srv_vpn.c
+
1056
−
14
View file @
657f42e1
...
...
@@ -8,31 +8,1073 @@
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) 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 (Deus Applicaions Prototypes) 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,
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.
DAP 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/>.
*/
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/>.
*/
/*#include "dap_common.h"
//#include "dap_stream_ch_vpn.h"
#include "dap_chain_net_srv_vpn.h"
#define LOG_TAG "chain_net_srv_vpn"
int dap_chain_net_srv_vpn_init()
{
int l_res = dap_stream_ch_vpn_init("addr", "255.255.0.0");
return 0;
}
void dap_chain_net_srv_vpn_deinit()
{
dap_stream_ch_vpn_deinit();
}*/
#include
<sys/select.h>
#include
<sys/types.h>
#include
<sys/socket.h>
#include
<sys/epoll.h>
#include
<sys/un.h>
#include
<sys/ioctl.h>
#include
<netinet/in.h>
#include
<netinet/ip.h>
#include
<arpa/inet.h>
#include
<pthread.h>
#include
<stdint.h>
#include
<unistd.h>
#include
<fcntl.h>
#include
<time.h>
#include
<errno.h>
#include
<signal.h>
#include
<linux/if.h>
#include
<linux/if_tun.h>
#include
"uthash.h"
#include
"utlist.h"
#include
"dap_common.h"
#include
"dap_strfuncs.h"
#include
"dap_config.h"
#include
"dap_client_remote.h"
#include
"dap_http_client.h"
#include
"dap_stream.h"
#include
"dap_stream_ch.h"
#include
"dap_stream_ch_proc.h"
#include
"dap_stream_ch_pkt.h"
#include
"dap_chain_utxo.h"
//datum_tx_cache.h
#include
"dap_chain_net_srv_vpn.h"
#define LOG_TAG "chain_net_srv_vpn"
#define LOG_TAG "srv_vpn"
#define VPN_PACKET_OP_CODE_CONNECTED 0x000000a9
#define VPN_PACKET_OP_CODE_CONNECT 0x000000aa
#define VPN_PACKET_OP_CODE_DISCONNECT 0x000000ab
#define VPN_PACKET_OP_CODE_SEND 0x000000ac
#define VPN_PACKET_OP_CODE_RECV 0x000000ad
#define VPN_PACKET_OP_CODE_PROBLEM 0x000000ae
#define VPN_PROBLEM_CODE_NO_FREE_ADDR 0x00000001
#define VPN_PROBLEM_CODE_TUNNEL_DOWN 0x00000002
#define VPN_PROBLEM_CODE_PACKET_LOST 0x00000003
#define VPN_PACKET_OP_CODE_VPN_METADATA 0x000000b0
#define VPN_PACKET_OP_CODE_VPN_RESERVED 0x000000b1
#define VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST 0x000000b2
#define VPN_PACKET_OP_CODE_VPN_ADDR_REPLY 0x000000b3
#define VPN_PACKET_OP_CODE_VPN_SEND 0x000000bc
#define VPN_PACKET_OP_CODE_VPN_RECV 0x000000bd
#define SF_MAX_EVENTS 256
int
dap_chain_net_srv_vpn_init
()
typedef
struct
ch_vpn_pkt
{
struct
{
int
sock_id
;
// Client's socket id
uint32_t
op_code
;
// Operation code
union
{
struct
{
// L4 connect operation
uint32_t
addr_size
;
uint16_t
port
;
uint16_t
padding
;
}
op_connect
;
struct
{
// For data transmission, usualy for I/O functions
uint32_t
data_size
;
uint32_t
padding
;
}
op_data
;
struct
{
// We have a problem and we know that!
uint32_t
code
;
// I hope we'll have no more than 4B+ problems, not I??
uint32_t
padding_padding_padding_damned_padding_nobody_nowhere_uses_this_fild_but_if_wil_change_me_pls_with_an_auto_rename
;
}
op_problem
;
struct
{
uint32_t
padding1
;
uint32_t
padding2
;
}
raw
;
// Raw access to OP bytes
};
}
__attribute__
((
packed
))
header
;
uint8_t
data
[];
// Binary data nested by packet
}
__attribute__
((
packed
))
ch_vpn_pkt_t
;
/**
* @struct ch_vpn_socket_proxy
* @brief Internal data storage for single socket proxy functions. Usualy helpfull for\
* port forwarding or for protecting single application's connection
*
**/
typedef
struct
ch_vpn_socket_proxy
{
int
id
;
int
sock
;
struct
in_addr
client_addr
;
// Used in raw L3 connections
pthread_mutex_t
mutex
;
dap_stream_ch_t
*
ch
;
bool
signal_to_delete
;
ch_vpn_pkt_t
*
pkt_out
[
100
];
size_t
pkt_out_size
;
uint64_t
bytes_sent
;
uint64_t
bytes_recieved
;
time_t
time_created
;
time_t
time_lastused
;
UT_hash_handle
hh
;
UT_hash_handle
hh2
;
UT_hash_handle
hh_sock
;
}
ch_vpn_socket_proxy_t
;
/**
* @struct dap_stream_ch_vpn
* @brief Object that creates for every remote channel client
*
*
**/
typedef
struct
dap_stream_ch_vpn
{
return
0
;
pthread_mutex_t
mutex
;
ch_vpn_socket_proxy_t
*
socks
;
int
raw_l3_sock
;
dap_chain_net_srv_uid_t
srv_uid
;
// Unique ID for service.
}
dap_stream_ch_vpn_t
;
typedef
struct
dap_stream_ch_vpn_remote_single
{
//
in_addr_t
addr
;
// pthread_mutex_t mutex;
dap_stream_ch_t
*
ch
;
uint64_t
bytes_sent
;
uint64_t
bytes_recieved
;
UT_hash_handle
hh
;
}
dap_stream_ch_vpn_remote_single_t
;
typedef
struct
vpn_local_network
{
struct
in_addr
client_addr_last
;
struct
in_addr
client_addr_mask
;
struct
in_addr
client_addr_host
;
struct
in_addr
client_addr
;
int
tun_ctl_fd
;
int
tun_fd
;
struct
ifreq
ifr
;
dap_stream_ch_vpn_remote_single_t
*
clients
;
// Remote clients identified by destination address
ch_vpn_pkt_t
*
pkt_out
[
400
];
size_t
pkt_out_size
;
size_t
pkt_out_rindex
;
size_t
pkt_out_windex
;
pthread_mutex_t
pkt_out_mutex
;
pthread_mutex_t
clients_mutex
;
}
vpn_local_network_t
;
typedef
struct
list_addr_element
{
struct
in_addr
addr
;
struct
list_addr_element
*
next
;
}
list_addr_element
;
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
int
sf_socks_epoll_fd
;
static
pthread_t
srv_sf_socks_pid
;
static
pthread_t
srv_sf_socks_raw_pid
;
vpn_local_network_t
*
raw_server
;
#define CH_SF(a) ((dap_stream_ch_vpn_t *) ((a)->internal) )
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
();
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 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
const
char
*
s_srv_vpn_addr
,
*
s_srv_vpn_mask
;
/**
* @brief dap_stream_ch_vpn_init Init actions for VPN stream channel
* @param vpn_addr Zero if only client mode. Address if the node shares its local VPN
* @param vpn_mask Zero if only client mode. Mask if the node shares its local VPN
* @return 0 if everything is okay, lesser then zero if errors
*/
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
);
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
,
srv_ch_sf_packet_out
);
return
0
;
}
return
-
1
;
}
/**
* @brief ch_sf_deinit
*/
void
dap_chain_net_srv_vpn_deinit
()
{
pthread_mutex_destroy
(
&
sf_socks_mutex
);
pthread_cond_destroy
(
&
sf_socks_cond
);
free
((
char
*
)
s_srv_vpn_addr
);
free
((
char
*
)
s_srv_vpn_mask
);
if
(
raw_server
)
free
(
raw_server
);
}
void
srv_ch_sf_tun_create
()
{
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
;
if
((
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
)
{
log_it
(
L_CRITICAL
,
"ioctl(TUNSETIFF) error: '%s' "
,
strerror
(
errno
));
close
(
raw_server
->
tun_ctl_fd
);
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
);
int
res
=
system
(
buf
);
snprintf
(
buf
,
sizeof
(
buf
),
"ip addr add %s/%s dev %s "
,
inet_ntoa
(
raw_server
->
client_addr_host
),
s_srv_vpn_mask
,
raw_server
->
ifr
.
ifr_name
);
res
=
system
(
buf
);
res
=
0
;
}
}
}
void
srv_ch_sf_tun_destroy
()
{
close
(
raw_server
->
tun_fd
);
raw_server
->
tun_fd
=
-
1
;
}
/**
* @brief stream_sf_new Callback to constructor of object of Ch
* @param ch
* @param arg
*/
void
srv_ch_sf_new
(
dap_stream_ch_t
*
ch
,
void
*
arg
)
{
ch
->
internal
=
calloc
(
1
,
sizeof
(
dap_stream_ch_vpn_t
));
dap_stream_ch_vpn_t
*
sf
=
CH_SF
(
ch
);
pthread_mutex_init
(
&
sf
->
mutex
,
NULL
);
sf
->
raw_l3_sock
=
socket
(
PF_INET
,
SOCK_RAW
,
IPPROTO_RAW
);
//
if
(
ch
->
stream
->
service_key
)
{
char
**
l_str
=
dap_strsplit
(
ch
->
stream
->
service_key
,
";"
,
-
1
);
char
*
l_addr_base58
=
NULL
;
char
*
l_sign_txt
=
NULL
;
if
(
dap_str_countv
(
l_str
)
==
2
)
{
l_addr_base58
=
l_str
[
0
];
l_sign_txt
=
l_str
[
1
];
}
l_addr_base58
=
"EXh66KVCxChbKJLxXTwipYMooUpoGvpwpkcjpmGLbubwzqR2vVsH9HEgT2LcU2hDs2BTFkaNC8itE8nuCWxskVtRJG4iaubBDcRWAt2awtCVHAULffQGrwe8ocRCzS"
;
l_sign_txt
=
"123"
;
uint8_t
*
l_sign
=
l_sign_txt
;
size_t
l_sign_size
=
0
;
dap_chain_net_srv_abstract_t
*
l_cond
=
NULL
;
uint64_t
l_value
=
dap_chain_net_srv_client_auth
(
l_addr_base58
,
l_sign
,
l_sign_size
,
&
l_cond
);
// add service
{
dap_chain_net_srv_t
l_srv
;
memcpy
(
&
l_srv
.
srv_common
,
l_cond
,
sizeof
(
dap_chain_net_srv_abstract_t
));
dap_chain_net_srv_gen_uid
(
&
l_srv
.
uid
);
dap_chain_net_srv_add
(
&
l_srv
);
memcpy
(
&
sf
->
srv_uid
.
raw
,
&
l_srv
.
uid
,
sizeof
(
dap_chain_net_srv_uid_t
));
// Unique ID for service.
}
}
}
/**
* @brief stream_sf_delete
* @param ch
* @param arg
*/
void
srv_ch_sf_delete
(
dap_stream_ch_t
*
ch
,
void
*
arg
)
{
log_it
(
L_DEBUG
,
"ch_sf_delete() for %s"
,
ch
->
stream
->
conn
->
hostaddr
);
ch_vpn_socket_proxy_t
*
cur
,
*
tmp
;
dap_stream_ch_vpn_remote_single_t
*
raw_client
=
0
;
// in_addr_t raw_client_addr = CH_SF(ch)->tun_client_addr.s_addr;
in_addr_t
raw_client_addr
=
ch
->
stream
->
session
->
tun_client_addr
.
s_addr
;
if
(
raw_client_addr
)
{
log_it
(
L_DEBUG
,
"ch_sf_delete() %s searching in hash table"
,
inet_ntoa
(
ch
->
stream
->
session
->
tun_client_addr
));
list_addr_element
*
el
=
(
list_addr_element
*
)
malloc
(
sizeof
(
list_addr_element
));
//el->addr = CH_SF(ch)->tun_client_addr;
el
->
addr
=
ch
->
stream
->
session
->
tun_client_addr
;
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
);
HASH_FIND_INT
(
raw_server
->
clients
,
&
raw_client_addr
,
raw_client
);
if
(
raw_client
)
{
HASH_DEL
(
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
);
}
else
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
);
}
HASH_ITER
(
hh
,
CH_SF
(
ch
)
->
socks
,
cur
,
tmp
)
{
log_it
(
L_DEBUG
,
"delete socket: %i"
,
cur
->
sock
);
HASH_DEL
(
CH_SF
(
ch
)
->
socks
,
cur
);
if
(
cur
)
free
(
cur
);
}
pthread_mutex_unlock
(
&
(
CH_SF
(
ch
)
->
mutex
));
if
(
CH_SF
(
ch
)
->
raw_l3_sock
)
close
(
CH_SF
(
ch
)
->
raw_l3_sock
);
}
static
void
stream_sf_socket_delete
(
ch_vpn_socket_proxy_t
*
sf
)
{
close
(
sf
->
sock
);
pthread_mutex_destroy
(
&
(
sf
->
mutex
));
if
(
sf
)
free
(
sf
);
}
static
void
stream_sf_socket_ready_to_write
(
dap_stream_ch_t
*
ch
,
bool
is_ready
)
{
pthread_mutex_lock
(
&
ch
->
mutex
);
ch
->
ready_to_write
=
is_ready
;
if
(
is_ready
)
ch
->
stream
->
conn_http
->
state_write
=
DAP_HTTP_CLIENT_STATE_DATA
;
dap_client_remote_ready_to_write
(
ch
->
stream
->
conn
,
is_ready
);
pthread_mutex_unlock
(
&
ch
->
mutex
);
}
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!
}
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
--
;
}
else
log_it
(
L_WARNING
,
"Packet drop on raw_read() operation, ring buffer is full"
);
pthread_mutex_unlock
(
&
raw_server
->
pkt_out_mutex
);
return
ret
;
}
/*
static int srv_ch_sf_raw_write(uint8_t op_code, const void * data, size_t data_size)
{
pthread_mutex_lock(&raw_server->pkt_out_mutex);
if(raw_server->pkt_out_windex == (sizeof(raw_server->pkt_out) / sizeof(raw_server->pkt_out[0])))
raw_server->pkt_out_windex = 0; // ring the buffer!
if((raw_server->pkt_out_windex < raw_server->pkt_out_rindex) || (raw_server->pkt_out_size == 0)) {
ch_vpn_pkt_t * pkt = (ch_vpn_pkt_t *) calloc(1, data_size + sizeof(pkt->header));
pkt->header.op_code = op_code;
pkt->header.sock_id = raw_server->tun_fd;
if(data_size > 0) {
pkt->header.op_data.data_size = data_size;
memcpy(pkt->data, data, data_size);
}
raw_server->pkt_out[raw_server->pkt_out_windex] = pkt;
raw_server->pkt_out_windex++;
raw_server->pkt_out_size++;
pthread_mutex_unlock(&raw_server->pkt_out_mutex);
send_select_break();
return raw_server->pkt_out_windex;
} else {
pthread_mutex_unlock(&raw_server->pkt_out_mutex);
log_it(L_WARNING, "Raw socket buffer overflow");
return -1;
}
}
static int srv_stream_sf_socket_write(ch_vpn_socket_proxy_t * sf, uint8_t op_code, const void * data, size_t data_size)
{
if(sf->pkt_out_size < (sizeof(sf->pkt_out) / sizeof(sf->pkt_out[0]))) {
ch_vpn_pkt_t * pkt = (ch_vpn_pkt_t *) calloc(1, data_size + sizeof(pkt->header));
pkt->header.op_code = op_code;
pkt->header.sock_id = sf->id;
switch (op_code) {
case VPN_PACKET_OP_CODE_RECV: {
pkt->header.op_data.data_size = data_size;
memcpy(pkt->data, data, data_size);
}
break;
default: {
log_it(L_ERROR, "Unprocessed opcode %u for write to sf socket", op_code);
free(pkt);
return -2;
}
}
sf->pkt_out[sf->pkt_out_size] = pkt;
sf->pkt_out_size++;
return sf->pkt_out_size;
} else
return -1;
}*/
/**
* @brief stream_sf_packet_in
* @param ch
* @param arg
*/
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
;
// log_it(L_DEBUG,"stream_sf_packet_in: channel packet hdr size %lu ( last bytes 0x%02x 0x%02x 0x%02x 0x%02x ) ", pkt->hdr.size,
// *((uint8_t *)pkt->data + pkt->hdr.size-4),*((uint8_t *)pkt->data + pkt->hdr.size-3)
// ,*((uint8_t *)pkt->data + pkt->hdr.size-2),*((uint8_t *)pkt->data + pkt->hdr.size-1)
// );
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
;
//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
pthread_mutex_lock
(
&
raw_server
->
clients_mutex
);
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
;
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
(
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
;
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
,
"
\t
gateway %s"
,
inet_ntoa
(
raw_server
->
client_addr_host
));
log_it
(
L_INFO
,
"
\t
mask %s"
,
inet_ntoa
(
raw_server
->
client_addr_mask
));
log_it
(
L_INFO
,
"
\t
addr %s"
,
inet_ntoa
(
raw_server
->
client_addr
));
log_it
(
L_INFO
,
"
\t
last_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
);
}
}
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_SF
(
ch
)
->
mutex
));
// log_it(L_DEBUG,"Looking in hash table with %d",remote_sock_id);
HASH_FIND_INT
((
CH_SF
(
ch
)
->
socks
),
&
remote_sock_id
,
sf_sock
);
pthread_mutex_unlock
(
&
(
CH_SF
(
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
(
&
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_SF
(
ch
)
->
mutex
));
HASH_DEL
(
CH_SF
(
ch
)
->
socks
,
sf_sock
);
pthread_mutex_unlock
(
&
(
CH_SF
(
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 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
(
&
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
);
}
break
;
case
VPN_PACKET_OP_CODE_DISCONNECT
:
{
log_it
(
L_INFO
,
"Disconnect action from %d sock_id"
,
sf_sock
->
id
);
pthread_mutex_lock
(
&
(
CH_SF
(
ch
)
->
mutex
));
HASH_DEL
(
CH_SF
(
ch
)
->
socks
,
sf_sock
);
pthread_mutex_unlock
(
&
(
CH_SF
(
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_SF
(
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_SF
(
ch
)
->
mutex
));
HASH_ADD_INT
(
CH_SF
(
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_SF
(
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
,
SERVICE_CHANNEL_ID
,
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_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
);
}
}
else
{
log_it
(
L_ERROR
,
"Can't create the socket"
);
}
}
}
}
}
}
/**
* @brief stream_sf_disconnect
* @param sf
*/
void
srv_stream_sf_disconnect
(
ch_vpn_socket_proxy_t
*
sf_sock
)
{
struct
epoll_event
ev
;
ev
.
data
.
fd
=
sf_sock
->
sock
;
ev
.
events
=
EPOLLIN
|
EPOLLERR
;
if
(
epoll_ctl
(
sf_socks_epoll_fd
,
EPOLL_CTL_DEL
,
sf_sock
->
sock
,
&
ev
)
==
-
1
)
{
log_it
(
L_ERROR
,
"Can't del sock_id %d from the epoll fd"
,
sf_sock
->
id
);
//stream_ch_pkt_write_f(sf->ch,'i',"sock_id=%d op_code=%uc result=-1",sf->id, STREAM_SF_PACKET_OP_CODE_RECV);
}
else
{
log_it
(
L_ERROR
,
"Removed sock_id %d from the epoll fd"
,
sf_sock
->
id
);
//stream_ch_pkt_write_f(sf->ch,'i',"sock_id=%d op_code=%uc result=0",sf->id, STREAM_SF_PACKET_OP_CODE_RECV);
}
// Compise signal to disconnect to another side, with special opcode STREAM_SF_PACKET_OP_CODE_DISCONNECT
ch_vpn_pkt_t
*
pkt_out
;
pkt_out
=
(
ch_vpn_pkt_t
*
)
calloc
(
1
,
sizeof
(
pkt_out
->
header
)
+
1
);
pkt_out
->
header
.
op_code
=
VPN_PACKET_OP_CODE_DISCONNECT
;
pkt_out
->
header
.
sock_id
=
sf_sock
->
id
;
sf_sock
->
pkt_out
[
sf_sock
->
pkt_out_size
]
=
pkt_out
;
sf_sock
->
pkt_out_size
++
;
sf_sock
->
signal_to_delete
=
true
;
}
/**
Socket forward
**/
void
*
srv_ch_sf_thread
(
void
*
arg
)
{
struct
epoll_event
ev
,
events
[
SF_MAX_EVENTS
]
=
{
0
};
//pthread_mutex_lock(&sf_socks_mutex);
sf_socks_epoll_fd
=
epoll_create
(
SF_MAX_EVENTS
);
sigset_t
sf_sigmask
;
sigemptyset
(
&
sf_sigmask
);
sigaddset
(
&
sf_sigmask
,
SIGUSR2
);
while
(
1
)
{
/*pthread_mutex_lock(&sf_socks_mutex);
if(sf_socks==NULL)
pthread_cond_wait(&sf_socks_cond,&sf_socks_mutex);
pthread_mutex_unlock(&sf_socks_mutex);*/
int
nfds
=
epoll_pwait
(
sf_socks_epoll_fd
,
events
,
SF_MAX_EVENTS
,
10000
,
&
sf_sigmask
);
if
(
nfds
<
0
)
{
//log_it(L_CRITICAL,"Can't run epoll_wait: %s",strerror(errno));
continue
;
}
if
(
nfds
>
0
)
log_it
(
L_DEBUG
,
"Epolled %d fd"
,
nfds
);
else
continue
;
int
n
;
for
(
n
=
0
;
n
<
nfds
;
++
n
)
{
int
s
=
events
[
n
].
data
.
fd
;
ch_vpn_socket_proxy_t
*
sf
=
NULL
;
pthread_mutex_lock
(
&
sf_socks_mutex
);
HASH_FIND
(
hh_sock
,
sf_socks_client
,
&
s
,
sizeof
(
s
),
sf
);
pthread_mutex_unlock
(
&
sf_socks_mutex
);
if
(
sf
)
{
if
(
events
[
n
].
events
&
EPOLLERR
)
{
log_it
(
L_NOTICE
,
"Socket id %d has EPOLLERR flag on"
,
s
);
pthread_mutex_lock
(
&
(
sf
->
mutex
));
srv_stream_sf_disconnect
(
sf
);
pthread_mutex_unlock
(
&
(
sf
->
mutex
));
}
else
if
(
events
[
n
].
events
&
EPOLLIN
)
{
char
buf
[
1000000
];
size_t
buf_size
;
ssize_t
ret
;
pthread_mutex_lock
(
&
(
sf
->
mutex
));
if
(
sf
->
pkt_out_size
<
((
sizeof
(
sf
->
pkt_out
)
/
sizeof
(
sf
->
pkt_out
[
0
]))
-
1
))
{
ret
=
recv
(
sf
->
sock
,
buf
,
sizeof
(
buf
),
0
);
//log_it(L_DEBUG,"recv() returned %d",ret);
if
(
ret
>
0
)
{
buf_size
=
ret
;
ch_vpn_pkt_t
*
pout
;
pout
=
sf
->
pkt_out
[
sf
->
pkt_out_size
]
=
(
ch_vpn_pkt_t
*
)
calloc
(
1
,
buf_size
+
sizeof
(
pout
->
header
));
pout
->
header
.
op_code
=
VPN_PACKET_OP_CODE_RECV
;
pout
->
header
.
sock_id
=
sf
->
id
;
pout
->
header
.
op_data
.
data_size
=
buf_size
;
memcpy
(
pout
->
data
,
buf
,
buf_size
);
sf
->
pkt_out_size
++
;
pthread_mutex_unlock
(
&
(
sf
->
mutex
));
stream_sf_socket_ready_to_write
(
sf
->
ch
,
true
);
}
else
{
log_it
(
L_NOTICE
,
"Socket id %d returned error on recv() function - may be host has disconnected"
,
s
);
pthread_mutex_unlock
(
&
(
sf
->
mutex
));
stream_sf_socket_ready_to_write
(
sf
->
ch
,
true
);
srv_stream_sf_disconnect
(
sf
);
}
}
else
{
log_it
(
L_WARNING
,
"Can't receive data, full of stack"
);
pthread_mutex_unlock
(
&
(
sf
->
mutex
));
}
}
else
{
log_it
(
L_WARNING
,
"Unprocessed flags 0x%08X"
,
events
[
n
].
events
);
}
}
else
{
if
(
epoll_ctl
(
sf_socks_epoll_fd
,
EPOLL_CTL_DEL
,
s
,
&
ev
)
<
0
)
{
log_it
(
L_ERROR
,
"Can't remove sock_id %d to the epoll fd"
,
s
);
}
else
{
log_it
(
L_NOTICE
,
"Socket id %d is removed from the list"
,
s
);
}
}
}
//pthread_mutex_unlock(&sf_socks_mutex);
}
}
/**
*
*
**/
void
*
srv_ch_sf_thread_raw
(
void
*
arg
)
{
srv_ch_sf_tun_create
();
if
(
raw_server
->
tun_fd
<=
0
)
{
log_it
(
L_CRITICAL
,
"Tun/tap file descriptor is not initialized"
);
return
NULL
;
}
/* if (fcntl(raw_server->tun_fd, F_SETFL, O_NONBLOCK) < 0){ ;
log_it(L_CRITICAL,"Can't switch tun/tap socket into the non-block mode");
return NULL;
}
if (fcntl(raw_server->tun_fd, F_SETFD, FD_CLOEXEC) < 0){;
log_it(L_CRITICAL,"Can't switch tun/tap socket to not be passed across execs");
return NULL;
}
*/
uint8_t
*
tmp_buf
;
ssize_t
tmp_buf_size
;
static
int
tun_MTU
=
100000
;
/// TODO Replace with detection of MTU size
tmp_buf
=
(
uint8_t
*
)
calloc
(
1
,
tun_MTU
);
tmp_buf_size
=
0
;
log_it
(
L_INFO
,
"Tun/tap thread starts with MTU = %d"
,
tun_MTU
);
fd_set
fds_read
,
fds_read_active
;
FD_ZERO
(
&
fds_read
);
FD_SET
(
raw_server
->
tun_fd
,
&
fds_read
);
FD_SET
(
get_select_breaker
(),
&
fds_read
);
/// Main cycle
do
{
fds_read_active
=
fds_read
;
int
ret
=
select
(
FD_SETSIZE
,
&
fds_read_active
,
NULL
,
NULL
,
NULL
);
//
if
(
ret
>
0
)
{
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
);
if
(
write_ret
>
0
)
{
log_it
(
L_DEBUG
,
"Wrote out %d bytes to the tun/tap interface"
,
write_ret
);
}
else
{
log_it
(
L_ERROR
,
"Tun/tap write %u bytes returned '%s' error, code (%d)"
,
pkt
->
header
.
op_data
.
data_size
,
strerror
(
errno
),
write_ret
);
}
}
}
if
(
FD_ISSET
(
raw_server
->
tun_fd
,
&
fds_read_active
))
{
int
read_ret
=
read
(
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
;
}
else
{
struct
iphdr
*
iph
=
(
struct
iphdr
*
)
tmp_buf
;
struct
in_addr
in_daddr
,
in_saddr
;
in_daddr
.
s_addr
=
iph
->
daddr
;
in_saddr
.
s_addr
=
iph
->
saddr
;
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
));
if
(
iph
->
tot_len
>
(
uint16_t
)
read_ret
)
{
log_it
(
L_INFO
,
"Tun/Tap interface returned only the fragment (tot_len =%u read_ret=%d) "
,
iph
->
tot_len
,
read_ret
);
}
if
(
iph
->
tot_len
<
(
uint16_t
)
read_ret
)
{
log_it
(
L_WARNING
,
"Tun/Tap interface returned more then one packet (tot_len =%u read_ret=%d) "
,
iph
->
tot_len
,
read_ret
);
}
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
);
// 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
.
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
,
pkt_out
->
header
.
op_data
.
data_size
+
sizeof
(
pkt_out
->
header
));
stream_sf_socket_ready_to_write
(
raw_client
->
ch
,
true
);
}
else
{
log_it
(
L_DEBUG
,
"No remote client for income IP packet with addr %s"
,
inet_ntoa
(
in_daddr
));
}
pthread_mutex_unlock
(
&
raw_server
->
clients_mutex
);
}
}
/*else {
log_it(L_CRITICAL,"select() has no tun handler in the returned set");
break;
}*/
}
else
{
log_it
(
L_CRITICAL
,
"Select returned %d"
,
ret
);
break
;
}
}
while
(
1
);
log_it
(
L_NOTICE
,
"Raw sockets listen thread is stopped"
);
srv_ch_sf_tun_destroy
();
return
NULL
;
}
/**
* @brief stream_sf_packet_out Packet Out Ch callback
* @param ch
* @param arg
*/
void
srv_ch_sf_packet_out
(
dap_stream_ch_t
*
ch
,
void
*
arg
)
{
ch_vpn_socket_proxy_t
*
cur
,
*
tmp
;
bool
isSmthOut
=
false
;
// log_it(L_DEBUG,"Socket forwarding packet out callback: %u sockets in hashtable", HASH_COUNT(CH_SF(ch)->socks) );
HASH_ITER
(
hh
,
CH_SF
(
ch
)
->
socks
,
cur
,
tmp
)
{
bool
signalToBreak
=
false
;
pthread_mutex_lock
(
&
(
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
(
pout
)
{
if
(
dap_stream_ch_pkt_write
(
ch
,
DATA_CHANNEL_ID
,
pout
,
pout
->
header
.
op_data
.
data_size
+
sizeof
(
pout
->
header
)))
{
isSmthOut
=
true
;
free
(
pout
);
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
;
break
;
}
}
}
}
if
(
signalToBreak
)
{
pthread_mutex_unlock
(
&
(
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_SF
(
ch
)
->
mutex
));
HASH_DEL
(
CH_SF
(
ch
)
->
socks
,
cur
);
pthread_mutex_unlock
(
&
(
CH_SF
(
ch
)
->
mutex
));
pthread_mutex_lock
(
&
(
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
(
&
(
cur
->
mutex
));
stream_sf_socket_delete
(
cur
);
}
else
pthread_mutex_unlock
(
&
(
cur
->
mutex
));
}
ch
->
ready_to_write
=
isSmthOut
;
if
(
isSmthOut
)
{
ch
->
stream
->
conn_http
->
state_write
=
DAP_HTTP_CLIENT_STATE_DATA
;
}
dap_client_remote_ready_to_write
(
ch
->
stream
->
conn
,
isSmthOut
);
}
This diff is collapsed.
Click to expand it.
dap_chain_net_srv_vpn.h
+
3
−
1
View file @
657f42e1
...
...
@@ -22,5 +22,7 @@
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
int
dap_chain_net_srv_vpn_init
();
#include
"dap_chain_net_srv.h"
int
dap_chain_net_srv_vpn_init
(
dap_config_t
*
g_config
);
void
dap_chain_net_srv_vpn_deinit
();
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment