Apply udpgw patch from linusyang
This commit is contained in:
@@ -39,6 +39,16 @@
|
||||
#define UDPGW_CLIENT_FLAG_DNS (1 << 2)
|
||||
#define UDPGW_CLIENT_FLAG_IPV6 (1 << 3)
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
B_START_PACKED
|
||||
struct socks_udp_header {
|
||||
uint16_t rsv;
|
||||
uint8_t frag;
|
||||
uint8_t atyp;
|
||||
} B_PACKED;
|
||||
B_END_PACKED
|
||||
#endif
|
||||
|
||||
B_START_PACKED
|
||||
struct udpgw_header {
|
||||
uint8_t flags;
|
||||
@@ -63,7 +73,11 @@ B_END_PACKED
|
||||
static int udpgw_compute_mtu (int dgram_mtu)
|
||||
{
|
||||
bsize_t bs = bsize_add(
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
bsize_fromsize(sizeof(struct socks_udp_header)),
|
||||
#else
|
||||
bsize_fromsize(sizeof(struct udpgw_header)),
|
||||
#endif
|
||||
bsize_add(
|
||||
bsize_max(
|
||||
bsize_fromsize(sizeof(struct udpgw_addr_ipv4)),
|
||||
|
||||
@@ -33,6 +33,13 @@
|
||||
|
||||
#include <generated/blog_channel_SocksUdpGwClient.h>
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
|
||||
#include <misc/socks_proto.h>
|
||||
#define CONNECTION_UDP_BUFFER_SIZE 1
|
||||
|
||||
#else
|
||||
|
||||
static void free_socks (SocksUdpGwClient *o);
|
||||
static void try_connect (SocksUdpGwClient *o);
|
||||
static void reconnect_timer_handler (SocksUdpGwClient *o);
|
||||
@@ -40,6 +47,317 @@ static void socks_client_handler (SocksUdpGwClient *o, int event);
|
||||
static void udpgw_handler_servererror (SocksUdpGwClient *o);
|
||||
static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
static void dgram_handler (SocksUdpGwClient_connection *o, int event);
|
||||
static void dgram_handler_received (SocksUdpGwClient_connection *o, uint8_t *data, int data_len);
|
||||
static int conaddr_comparator (void *unused, SocksUdpGwClient_conaddr *v1, SocksUdpGwClient_conaddr *v2);
|
||||
static SocksUdpGwClient_connection * find_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr);
|
||||
static SocksUdpGwClient_connection * reuse_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr);
|
||||
static void connection_send (SocksUdpGwClient_connection *o, const uint8_t *data, int data_len);
|
||||
static void connection_first_job_handler (SocksUdpGwClient_connection *con);
|
||||
static SocksUdpGwClient_connection *connection_init (SocksUdpGwClient *client, SocksUdpGwClient_conaddr conaddr, const uint8_t *data, int data_len);
|
||||
static void connection_free (SocksUdpGwClient_connection *o);
|
||||
|
||||
static void dgram_handler (SocksUdpGwClient_connection *o, int event)
|
||||
{
|
||||
SocksUdpGwClient *client = o->client;
|
||||
ASSERT(client);
|
||||
|
||||
DebugObject_Access(&client->d_obj);
|
||||
|
||||
BLog(BLOG_INFO, "UDP error");
|
||||
}
|
||||
|
||||
static void dgram_handler_received (SocksUdpGwClient_connection *o, uint8_t *data, int data_len)
|
||||
{
|
||||
SocksUdpGwClient *client = o->client;
|
||||
ASSERT(client);
|
||||
|
||||
DebugObject_Access(&client->d_obj);
|
||||
ASSERT(data_len >= 0)
|
||||
ASSERT(data_len <= client->udpgw_mtu)
|
||||
|
||||
// accept packet
|
||||
PacketPassInterface_Done(&o->udp_recv_if);
|
||||
|
||||
// check header
|
||||
if (data_len < sizeof(struct socks_udp_header)) {
|
||||
BLog(BLOG_ERROR, "missing header");
|
||||
return;
|
||||
}
|
||||
struct socks_udp_header header;
|
||||
memcpy(&header, data, sizeof(header));
|
||||
data += sizeof(header);
|
||||
data_len -= sizeof(header);
|
||||
uint8_t frag = header.frag;
|
||||
uint8_t atyp = header.atyp;
|
||||
|
||||
// check fragment
|
||||
if (frag) {
|
||||
BLog(BLOG_ERROR, "unexpected frag");
|
||||
return;
|
||||
}
|
||||
|
||||
// parse address
|
||||
BAddr remote_addr;
|
||||
if (atyp == SOCKS_ATYP_IPV6) {
|
||||
if (data_len < sizeof(struct udpgw_addr_ipv6)) {
|
||||
BLog(BLOG_ERROR, "missing ipv6 address");
|
||||
return;
|
||||
}
|
||||
struct udpgw_addr_ipv6 addr_ipv6;
|
||||
memcpy(&addr_ipv6, data, sizeof(addr_ipv6));
|
||||
data += sizeof(addr_ipv6);
|
||||
data_len -= sizeof(addr_ipv6);
|
||||
BAddr_InitIPv6(&remote_addr, addr_ipv6.addr_ip, addr_ipv6.addr_port);
|
||||
} else {
|
||||
if (data_len < sizeof(struct udpgw_addr_ipv4)) {
|
||||
BLog(BLOG_ERROR, "missing ipv4 address");
|
||||
return;
|
||||
}
|
||||
struct udpgw_addr_ipv4 addr_ipv4;
|
||||
memcpy(&addr_ipv4, data, sizeof(addr_ipv4));
|
||||
data += sizeof(addr_ipv4);
|
||||
data_len -= sizeof(addr_ipv4);
|
||||
BAddr_InitIPv4(&remote_addr, addr_ipv4.addr_ip, addr_ipv4.addr_port);
|
||||
}
|
||||
|
||||
// check remote addr
|
||||
if (!BAddr_Compare(&remote_addr, &o->conaddr.remote_addr)) {
|
||||
BLog(BLOG_ERROR, "remote addr not match");
|
||||
return;
|
||||
}
|
||||
|
||||
// check remaining data
|
||||
if (data_len > client->udp_mtu) {
|
||||
BLog(BLOG_ERROR, "too much data");
|
||||
return;
|
||||
}
|
||||
|
||||
// submit to user
|
||||
client->handler_received(client->user, o->conaddr.local_addr, remote_addr, data, data_len);
|
||||
}
|
||||
|
||||
static int conaddr_comparator (void *unused, SocksUdpGwClient_conaddr *v1, SocksUdpGwClient_conaddr *v2)
|
||||
{
|
||||
int r = BAddr_CompareOrder(&v1->remote_addr, &v2->remote_addr);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
return BAddr_CompareOrder(&v1->local_addr, &v2->local_addr);
|
||||
}
|
||||
|
||||
static SocksUdpGwClient_connection * find_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr)
|
||||
{
|
||||
BAVLNode *tree_node = BAVL_LookupExact(&o->connections_tree, &conaddr);
|
||||
if (!tree_node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return UPPER_OBJECT(tree_node, SocksUdpGwClient_connection, connections_tree_node);
|
||||
}
|
||||
|
||||
static SocksUdpGwClient_connection * reuse_connection (SocksUdpGwClient *o, SocksUdpGwClient_conaddr conaddr)
|
||||
{
|
||||
ASSERT(!find_connection(o, conaddr))
|
||||
ASSERT(o->num_connections > 0)
|
||||
|
||||
// get least recently used connection
|
||||
SocksUdpGwClient_connection *con = UPPER_OBJECT(LinkedList1_GetFirst(&o->connections_list), SocksUdpGwClient_connection, connections_list_node);
|
||||
|
||||
// remove from connections tree by conaddr
|
||||
BAVL_Remove(&o->connections_tree, &con->connections_tree_node);
|
||||
|
||||
// set new conaddr
|
||||
con->conaddr = conaddr;
|
||||
|
||||
// insert to connections tree by conaddr
|
||||
ASSERT_EXECUTE(BAVL_Insert(&o->connections_tree, &con->connections_tree_node, NULL))
|
||||
|
||||
return con;
|
||||
}
|
||||
|
||||
static void connection_send (SocksUdpGwClient_connection *o, const uint8_t *data, int data_len)
|
||||
{
|
||||
// get buffer location
|
||||
uint8_t *out;
|
||||
if (!BufferWriter_StartPacket(&o->udp_send_writer, &out)) {
|
||||
BLog(BLOG_ERROR, "out of UDP buffer");
|
||||
return;
|
||||
}
|
||||
int out_pos = 0;
|
||||
|
||||
// write header
|
||||
BAddr remote_addr = o->conaddr.remote_addr;
|
||||
struct socks_udp_header header;
|
||||
header.rsv = 0;
|
||||
header.frag = 0;
|
||||
if (remote_addr.type == BADDR_TYPE_IPV4) {
|
||||
header.atyp = SOCKS_ATYP_IPV4;
|
||||
} else {
|
||||
header.atyp = SOCKS_ATYP_IPV6;
|
||||
}
|
||||
memcpy(out + out_pos, &header, sizeof(header));
|
||||
out_pos += sizeof(header);
|
||||
|
||||
// write address
|
||||
switch (remote_addr.type) {
|
||||
case BADDR_TYPE_IPV4: {
|
||||
struct udpgw_addr_ipv4 addr_ipv4;
|
||||
addr_ipv4.addr_ip = remote_addr.ipv4.ip;
|
||||
addr_ipv4.addr_port = remote_addr.ipv4.port;
|
||||
memcpy(out + out_pos, &addr_ipv4, sizeof(addr_ipv4));
|
||||
out_pos += sizeof(addr_ipv4);
|
||||
} break;
|
||||
case BADDR_TYPE_IPV6: {
|
||||
struct udpgw_addr_ipv6 addr_ipv6;
|
||||
memcpy(addr_ipv6.addr_ip, remote_addr.ipv6.ip, sizeof(addr_ipv6.addr_ip));
|
||||
addr_ipv6.addr_port = remote_addr.ipv6.port;
|
||||
memcpy(out + out_pos, &addr_ipv6, sizeof(addr_ipv6));
|
||||
out_pos += sizeof(addr_ipv6);
|
||||
} break;
|
||||
}
|
||||
|
||||
// write packet to buffer
|
||||
memcpy(out + out_pos, data, data_len);
|
||||
out_pos += data_len;
|
||||
|
||||
// submit written message
|
||||
BufferWriter_EndPacket(&o->udp_send_writer, out_pos);
|
||||
}
|
||||
|
||||
static void connection_first_job_handler (SocksUdpGwClient_connection *con)
|
||||
{
|
||||
connection_send(con, con->first_data, con->first_data_len);
|
||||
}
|
||||
|
||||
static SocksUdpGwClient_connection *connection_init (SocksUdpGwClient *client, SocksUdpGwClient_conaddr conaddr, const uint8_t *data, int data_len)
|
||||
{
|
||||
// allocate structure
|
||||
SocksUdpGwClient_connection *o = (SocksUdpGwClient_connection *) malloc(sizeof(*o));
|
||||
if (!o) {
|
||||
BLog(BLOG_ERROR, "malloc failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// init arguments
|
||||
o->client = client;
|
||||
o->conaddr = conaddr;
|
||||
o->first_data = data;
|
||||
o->first_data_len = data_len;
|
||||
|
||||
// init first job
|
||||
BPending_Init(&o->first_job, BReactor_PendingGroup(client->reactor), (BPending_handler)connection_first_job_handler, o);
|
||||
BPending_Set(&o->first_job);
|
||||
|
||||
// init UDP dgram
|
||||
if (!BDatagram_Init(&o->udp_dgram, client->socks_server_addr.type, client->reactor, o, (BDatagram_handler)dgram_handler)) {
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
// set SO_REUSEADDR
|
||||
if (!BDatagram_SetReuseAddr(&o->udp_dgram, 1)) {
|
||||
BLog(BLOG_ERROR, "set SO_REUSEADDR failed");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
// set UDP dgram send address
|
||||
BIPAddr ipaddr;
|
||||
memset(&ipaddr, 0, sizeof(ipaddr));
|
||||
ipaddr.type = client->socks_server_addr.type;
|
||||
BDatagram_SetSendAddrs(&o->udp_dgram, client->socks_server_addr, ipaddr);
|
||||
|
||||
// init UDP dgram interfaces
|
||||
BDatagram_SendAsync_Init(&o->udp_dgram, client->udp_mtu);
|
||||
BDatagram_RecvAsync_Init(&o->udp_dgram, client->udp_mtu);
|
||||
|
||||
// init UDP writer
|
||||
BufferWriter_Init(&o->udp_send_writer, client->udp_mtu, BReactor_PendingGroup(client->reactor));
|
||||
|
||||
// init UDP buffer
|
||||
if (!PacketBuffer_Init(&o->udp_send_buffer, BufferWriter_GetOutput(&o->udp_send_writer), BDatagram_SendAsync_GetIf(&o->udp_dgram), CONNECTION_UDP_BUFFER_SIZE, BReactor_PendingGroup(client->reactor))) {
|
||||
BLog(BLOG_ERROR, "PacketBuffer_Init failed");
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
// init UDP recv interface
|
||||
PacketPassInterface_Init(&o->udp_recv_if, client->udp_mtu, (PacketPassInterface_handler_send)dgram_handler_received, o, BReactor_PendingGroup(client->reactor));
|
||||
|
||||
// init UDP recv buffer
|
||||
if (!SinglePacketBuffer_Init(&o->udp_recv_buffer, BDatagram_RecvAsync_GetIf(&o->udp_dgram), &o->udp_recv_if, BReactor_PendingGroup(client->reactor))) {
|
||||
BLog(BLOG_ERROR, "SinglePacketBuffer_Init failed");
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
// insert to connections tree by conaddr
|
||||
ASSERT_EXECUTE(BAVL_Insert(&client->connections_tree, &o->connections_tree_node, NULL));
|
||||
|
||||
// insert to connections list
|
||||
LinkedList1_Append(&client->connections_list, &o->connections_list_node);
|
||||
|
||||
// increment number of connections
|
||||
client->num_connections++;
|
||||
|
||||
// succeed to init
|
||||
return o;
|
||||
|
||||
fail3:
|
||||
PacketPassInterface_Free(&o->udp_recv_if);
|
||||
PacketBuffer_Free(&o->udp_send_buffer);
|
||||
fail2:
|
||||
BufferWriter_Free(&o->udp_send_writer);
|
||||
BDatagram_RecvAsync_Free(&o->udp_dgram);
|
||||
BDatagram_SendAsync_Free(&o->udp_dgram);
|
||||
fail1:
|
||||
BDatagram_Free(&o->udp_dgram);
|
||||
|
||||
fail0:
|
||||
BPending_Free(&o->first_job);
|
||||
free(o);
|
||||
fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void connection_free (SocksUdpGwClient_connection *o)
|
||||
{
|
||||
SocksUdpGwClient *client = o->client;
|
||||
|
||||
// decrement number of connections
|
||||
client->num_connections--;
|
||||
|
||||
// remove from connections list
|
||||
LinkedList1_Remove(&client->connections_list, &o->connections_list_node);
|
||||
|
||||
// remove from connections tree by conaddr
|
||||
BAVL_Remove(&client->connections_tree, &o->connections_tree_node);
|
||||
|
||||
// free UDP receive buffer
|
||||
SinglePacketBuffer_Free(&o->udp_recv_buffer);
|
||||
|
||||
// free UDP receive interface
|
||||
PacketPassInterface_Free(&o->udp_recv_if);
|
||||
|
||||
// free UDP buffer
|
||||
PacketBuffer_Free(&o->udp_send_buffer);
|
||||
|
||||
// free UDP writer
|
||||
BufferWriter_Free(&o->udp_send_writer);
|
||||
|
||||
// free UDP dgram interfaces
|
||||
BDatagram_RecvAsync_Free(&o->udp_dgram);
|
||||
BDatagram_SendAsync_Free(&o->udp_dgram);
|
||||
|
||||
// free UDP dgram
|
||||
BDatagram_Free(&o->udp_dgram);
|
||||
|
||||
// free structure
|
||||
free(o);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void free_socks (SocksUdpGwClient *o)
|
||||
{
|
||||
ASSERT(o->have_socks)
|
||||
@@ -158,6 +476,8 @@ static void udpgw_handler_received (SocksUdpGwClient *o, BAddr local_addr, BAddr
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections, int send_buffer_size, btime_t keepalive_time,
|
||||
BAddr socks_server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info,
|
||||
BAddr remote_udpgw_addr, btime_t reconnect_time, BReactor *reactor, void *user,
|
||||
@@ -165,7 +485,9 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections
|
||||
{
|
||||
// see asserts in UdpGwClient_Init
|
||||
ASSERT(!BAddr_IsInvalid(&socks_server_addr))
|
||||
#ifndef BADVPN_SOCKS_UDP_RELAY
|
||||
ASSERT(remote_udpgw_addr.type == BADDR_TYPE_IPV4 || remote_udpgw_addr.type == BADDR_TYPE_IPV6)
|
||||
#endif
|
||||
|
||||
// init arguments
|
||||
o->udp_mtu = udp_mtu;
|
||||
@@ -177,6 +499,22 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections
|
||||
o->user = user;
|
||||
o->handler_received = handler_received;
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
// compute MTUs
|
||||
o->udpgw_mtu = udpgw_compute_mtu(o->udp_mtu);
|
||||
o->max_connections = max_connections;
|
||||
|
||||
// limit max connections to number of conid's
|
||||
if (o->max_connections > UINT16_MAX + 1) {
|
||||
o->max_connections = UINT16_MAX + 1;
|
||||
}
|
||||
|
||||
// init connections tree by conaddr
|
||||
BAVL_Init(&o->connections_tree, OFFSET_DIFF(SocksUdpGwClient_connection, conaddr, connections_tree_node), (BAVL_comparator)conaddr_comparator, NULL);
|
||||
|
||||
// init connections list
|
||||
LinkedList1_Init(&o->connections_list);
|
||||
#else
|
||||
// init udpgw client
|
||||
if (!UdpGwClient_Init(&o->udpgw_client, udp_mtu, max_connections, send_buffer_size, keepalive_time, o->reactor, o,
|
||||
(UdpGwClient_handler_servererror)udpgw_handler_servererror,
|
||||
@@ -193,6 +531,7 @@ int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections
|
||||
|
||||
// try connecting
|
||||
try_connect(o);
|
||||
#endif
|
||||
|
||||
DebugObject_Init(&o->d_obj);
|
||||
return 1;
|
||||
@@ -205,6 +544,13 @@ void SocksUdpGwClient_Free (SocksUdpGwClient *o)
|
||||
{
|
||||
DebugObject_Free(&o->d_obj);
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
// free connections
|
||||
while (!LinkedList1_IsEmpty(&o->connections_list)) {
|
||||
SocksUdpGwClient_connection *con = UPPER_OBJECT(LinkedList1_GetFirst(&o->connections_list), SocksUdpGwClient_connection, connections_list_node);
|
||||
connection_free(con);
|
||||
}
|
||||
#else
|
||||
// free SOCKS
|
||||
if (o->have_socks) {
|
||||
free_socks(o);
|
||||
@@ -215,6 +561,7 @@ void SocksUdpGwClient_Free (SocksUdpGwClient *o)
|
||||
|
||||
// free udpgw client
|
||||
UdpGwClient_Free(&o->udpgw_client);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SocksUdpGwClient_SubmitPacket (SocksUdpGwClient *o, BAddr local_addr, BAddr remote_addr, int is_dns, const uint8_t *data, int data_len)
|
||||
@@ -222,7 +569,39 @@ void SocksUdpGwClient_SubmitPacket (SocksUdpGwClient *o, BAddr local_addr, BAddr
|
||||
DebugObject_Access(&o->d_obj);
|
||||
// see asserts in UdpGwClient_SubmitPacket
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
ASSERT(local_addr.type == BADDR_TYPE_IPV4 || local_addr.type == BADDR_TYPE_IPV6)
|
||||
ASSERT(remote_addr.type == BADDR_TYPE_IPV4 || remote_addr.type == BADDR_TYPE_IPV6)
|
||||
ASSERT(data_len >= 0)
|
||||
ASSERT(data_len <= o->udp_mtu)
|
||||
|
||||
// build conaddr
|
||||
SocksUdpGwClient_conaddr conaddr;
|
||||
conaddr.local_addr = local_addr;
|
||||
conaddr.remote_addr = remote_addr;
|
||||
|
||||
// lookup connection
|
||||
SocksUdpGwClient_connection *con = find_connection(o, conaddr);
|
||||
|
||||
// if no connection and can't create a new one, reuse the least recently used une
|
||||
if (!con && o->num_connections == o->max_connections) {
|
||||
con = reuse_connection(o, conaddr);
|
||||
}
|
||||
|
||||
if (!con) {
|
||||
// create new connection
|
||||
con = connection_init(o, conaddr, data, data_len);
|
||||
} else {
|
||||
// move connection to front of the list
|
||||
LinkedList1_Remove(&o->connections_list, &con->connections_list_node);
|
||||
LinkedList1_Append(&o->connections_list, &con->connections_list_node);
|
||||
|
||||
// send packet to existing connection
|
||||
connection_send(con, data, data_len);
|
||||
}
|
||||
#else
|
||||
// submit to udpgw client
|
||||
UdpGwClient_SubmitPacket(&o->udpgw_client, local_addr, remote_addr, is_dns, data, data_len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,20 @@
|
||||
#include <misc/debug.h>
|
||||
#include <base/DebugObject.h>
|
||||
#include <system/BReactor.h>
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
#include <protocol/udpgw_proto.h>
|
||||
#include <protocol/packetproto.h>
|
||||
#include <system/BDatagram.h>
|
||||
#include <flow/PacketBuffer.h>
|
||||
#include <flow/SinglePacketBuffer.h>
|
||||
#include <flow/BufferWriter.h>
|
||||
#include <structure/BAVL.h>
|
||||
#include <structure/LinkedList1.h>
|
||||
#include <misc/offset.h>
|
||||
#else
|
||||
#include <udpgw_client/UdpGwClient.h>
|
||||
#include <socksclient/BSocksClient.h>
|
||||
#endif
|
||||
|
||||
typedef void (*SocksUdpGwClient_handler_received) (void *user, BAddr local_addr, BAddr remote_addr, const uint8_t *data, int data_len);
|
||||
|
||||
@@ -46,14 +58,44 @@ typedef struct {
|
||||
BReactor *reactor;
|
||||
void *user;
|
||||
SocksUdpGwClient_handler_received handler_received;
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
int udpgw_mtu;
|
||||
int num_connections;
|
||||
int max_connections;
|
||||
BAVL connections_tree;
|
||||
LinkedList1 connections_list;
|
||||
#else
|
||||
UdpGwClient udpgw_client;
|
||||
BTimer reconnect_timer;
|
||||
int have_socks;
|
||||
BSocksClient socks_client;
|
||||
int socks_up;
|
||||
#endif
|
||||
DebugObject d_obj;
|
||||
} SocksUdpGwClient;
|
||||
|
||||
#ifdef BADVPN_SOCKS_UDP_RELAY
|
||||
typedef struct {
|
||||
BAddr local_addr;
|
||||
BAddr remote_addr;
|
||||
} SocksUdpGwClient_conaddr;
|
||||
|
||||
typedef struct {
|
||||
SocksUdpGwClient *client;
|
||||
SocksUdpGwClient_conaddr conaddr;
|
||||
BPending first_job;
|
||||
const uint8_t *first_data;
|
||||
int first_data_len;
|
||||
BDatagram udp_dgram;
|
||||
BufferWriter udp_send_writer;
|
||||
PacketBuffer udp_send_buffer;
|
||||
SinglePacketBuffer udp_recv_buffer;
|
||||
PacketPassInterface udp_recv_if;
|
||||
BAVLNode connections_tree_node;
|
||||
LinkedList1Node connections_list_node;
|
||||
} SocksUdpGwClient_connection;
|
||||
#endif
|
||||
|
||||
int SocksUdpGwClient_Init (SocksUdpGwClient *o, int udp_mtu, int max_connections, int send_buffer_size, btime_t keepalive_time,
|
||||
BAddr socks_server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info,
|
||||
BAddr remote_udpgw_addr, btime_t reconnect_time, BReactor *reactor, void *user,
|
||||
|
||||
@@ -585,10 +585,15 @@ void print_help (const char *name)
|
||||
" [--password <password>]\n"
|
||||
" [--password-file <file>]\n"
|
||||
" [--append-source-to-username]\n"
|
||||
#ifdef ANDROID
|
||||
" [--enable-udprelay]\n"
|
||||
" [--udprelay-max-connections <number>]\n"
|
||||
#else
|
||||
" [--udpgw-remote-server-addr <addr>]\n"
|
||||
" [--udpgw-max-connections <number>]\n"
|
||||
" [--udpgw-connection-buffer-size <number>]\n"
|
||||
" [--udpgw-transparent-dns]\n"
|
||||
#endif
|
||||
"Address format is a.b.c.d:port (IPv4) or [addr]:port (IPv6).\n",
|
||||
name
|
||||
);
|
||||
@@ -820,6 +825,10 @@ int parse_arguments (int argc, char *argv[])
|
||||
else if (!strcmp(arg, "--append-source-to-username")) {
|
||||
options.append_source_to_username = 1;
|
||||
}
|
||||
#ifdef ANDROID
|
||||
else if (!strcmp(arg, "--enable-udprelay")) {
|
||||
options.udpgw_remote_server_addr = "0.0.0.0:0";
|
||||
#else
|
||||
else if (!strcmp(arg, "--udpgw-remote-server-addr")) {
|
||||
if (1 >= argc - i) {
|
||||
fprintf(stderr, "%s: requires an argument\n", arg);
|
||||
@@ -827,8 +836,13 @@ int parse_arguments (int argc, char *argv[])
|
||||
}
|
||||
options.udpgw_remote_server_addr = argv[i + 1];
|
||||
i++;
|
||||
#endif
|
||||
}
|
||||
#ifdef ANDROID
|
||||
else if (!strcmp(arg, "--udprelay-max-connections")) {
|
||||
#else
|
||||
else if (!strcmp(arg, "--udpgw-max-connections")) {
|
||||
#endif
|
||||
if (1 >= argc - i) {
|
||||
fprintf(stderr, "%s: requires an argument\n", arg);
|
||||
return 0;
|
||||
@@ -839,6 +853,7 @@ int parse_arguments (int argc, char *argv[])
|
||||
}
|
||||
i++;
|
||||
}
|
||||
#ifndef ANDROID
|
||||
else if (!strcmp(arg, "--udpgw-connection-buffer-size")) {
|
||||
if (1 >= argc - i) {
|
||||
fprintf(stderr, "%s: requires an argument\n", arg);
|
||||
@@ -853,6 +868,7 @@ int parse_arguments (int argc, char *argv[])
|
||||
else if (!strcmp(arg, "--udpgw-transparent-dns")) {
|
||||
options.udpgw_transparent_dns = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
fprintf(stderr, "unknown option: %s\n", arg);
|
||||
return 0;
|
||||
@@ -959,7 +975,11 @@ int process_arguments (void)
|
||||
// resolve remote udpgw server address
|
||||
if (options.udpgw_remote_server_addr) {
|
||||
if (!BAddr_Parse2(&udpgw_remote_server_addr, options.udpgw_remote_server_addr, NULL, 0, 0)) {
|
||||
#ifdef ANDROID
|
||||
BLog(BLOG_ERROR, "udprelay server addr: BAddr_Parse2 failed");
|
||||
#else
|
||||
BLog(BLOG_ERROR, "remote udpgw server addr: BAddr_Parse2 failed");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -2080,7 +2100,11 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
|
||||
|
||||
switch (local_addr.type) {
|
||||
case BADDR_TYPE_IPV4: {
|
||||
#ifdef ANDROID
|
||||
BLog(BLOG_INFO, "UDP: from udprelay %d bytes", data_len);
|
||||
#else
|
||||
BLog(BLOG_INFO, "UDP: from udpgw %d bytes", data_len);
|
||||
#endif
|
||||
|
||||
if (data_len > UINT16_MAX - (sizeof(struct ipv4_header) + sizeof(struct udp_header)) ||
|
||||
data_len > BTap_GetMTU(&device) - (int)(sizeof(struct ipv4_header) + sizeof(struct udp_header))
|
||||
@@ -2119,10 +2143,18 @@ void udpgw_client_handler_received (void *unused, BAddr local_addr, BAddr remote
|
||||
} break;
|
||||
|
||||
case BADDR_TYPE_IPV6: {
|
||||
#ifdef ANDROID
|
||||
BLog(BLOG_INFO, "UDP/IPv6: from udprelay %d bytes", data_len);
|
||||
#else
|
||||
BLog(BLOG_INFO, "UDP/IPv6: from udpgw %d bytes", data_len);
|
||||
#endif
|
||||
|
||||
if (!options.netif_ip6addr) {
|
||||
#ifdef ANDROID
|
||||
BLog(BLOG_ERROR, "got IPv6 packet from udprelay but IPv6 is disabled");
|
||||
#else
|
||||
BLog(BLOG_ERROR, "got IPv6 packet from udpgw but IPv6 is disabled");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
def startShadowsocksDaemon() {
|
||||
val cmd: String = (Path.BASE +
|
||||
"ss-local -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -f " +
|
||||
"ss-local -b 127.0.0.1 -s \"%s\" -p \"%d\" -l \"%d\" -k \"%s\" -m \"%s\" -u -f " +
|
||||
Path.BASE + "ss-local.pid")
|
||||
.format(config.proxy, config.remotePort, config.localPort, config.sitekey, config.encMethod)
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
@@ -186,18 +186,24 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
|
||||
val fd = conn.getFd
|
||||
|
||||
val cmd = (Path.BASE +
|
||||
var cmd = (Path.BASE +
|
||||
"tun2socks --netif-ipaddr %s "
|
||||
+ "--dnsgw %s:8153 "
|
||||
+ "--netif-netmask 255.255.255.0 "
|
||||
+ "--socks-server-addr 127.0.0.1:%d "
|
||||
+ "--tunfd %d "
|
||||
+ "--tunmtu %d "
|
||||
+ "--loglevel 3 "
|
||||
+ "--loglevel 5 "
|
||||
+ "--pid %stun2socks.pid")
|
||||
.format(PRIVATE_VLAN.format("2"), PRIVATE_VLAN.format("1"), config.localPort, fd, VPN_MTU,
|
||||
Path.BASE)
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
|
||||
.format(PRIVATE_VLAN.format("2"), config.localPort, fd, VPN_MTU, Path.BASE)
|
||||
|
||||
if (config.isUdpDns)
|
||||
cmd += " --enable-udprelay"
|
||||
else
|
||||
cmd += " --dnsgw %s:8153".format(PRIVATE_VLAN.format("1"))
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, cmd)
|
||||
|
||||
System.exec(cmd)
|
||||
}
|
||||
|
||||
@@ -205,7 +211,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
|
||||
def handleConnection: Boolean = {
|
||||
startVpn()
|
||||
startShadowsocksDaemon()
|
||||
startDnsDaemon()
|
||||
if (!config.isUdpDns) startDnsDaemon()
|
||||
true
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user