Skip to content

Commit

Permalink
implement ip range connector
Browse files Browse the repository at this point in the history
  • Loading branch information
radkesvat committed Jun 29, 2024
1 parent ccb1dac commit 27163ab
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 24 deletions.
148 changes: 138 additions & 10 deletions tunnels/adapters/connector/tcp/tcp_connector.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include "tcp_connector.h"
#include "basic_types.h"
#include "frand.h"
#include "hsocket.h"
#include "loggers/network_logger.h"
#include "sync_dns.h"
#include "tunnel.h"
#include "types.h"
#include "utils/jsonutils.h"
#include "utils/mathutils.h"
#include "utils/sockutils.h"

static void cleanup(tcp_connector_con_state_t *cstate, bool write_queue)
Expand Down Expand Up @@ -242,19 +244,62 @@ static void upStream(tunnel_t *self, context_t *c)
break;
}

// sockaddr_set_ipport(&(dest_ctx.addr), "127.0.0.1", 443);
// LOGD("TcpConnector: initiating connection");

if (dest_ctx->address_type == kSatDomainName && ! dest_ctx->domain_resolved)
switch (dest_ctx->address_type)
{
if (! resolveContextSync(dest_ctx))
case kSatDomainName:
if (! dest_ctx->domain_resolved)
{
if (! resolveContextSync(dest_ctx))
{
CSTATE_DROP(c);
cleanup(cstate, false);
goto fail;
}
}
break;

case kSatIPV4:
if (state->outbound_ip_range > 0)
{
unsigned int seed = fastRand();
// no probelm if overflows
#ifdef OS_UNIX
const uint32_t large_random = 1 + (((uint32_t) rand_r(&seed)) % state->outbound_ip_range);
#else
const uint32_t large_random = 1 + (((uint32_t) rand_s(&seed)) % state->outbound_ip_range);
#endif
uint32_t calc = htonl(ntohl((uint32_t) dest_ctx->address.sin.sin_addr.s_addr) + large_random);
memcpy(&(dest_ctx->address.sin.sin_addr), &calc, sizeof(struct in_addr));
}
break;
case kSatIPV6:

if (state->outbound_ip_range > 0)
{
CSTATE_DROP(c);
cleanup(cstate, false);
goto fail;
unsigned int seed = fastRand();
// no probelm if overflows
#ifdef OS_UNIX
const uint64_t large_random = 1 + (((uint64_t) rand_r(&seed)) % state->outbound_ip_range);
#else
const uint64_t large_random = 1 + (((uint64_t) rand_s(&seed)) % state->outbound_ip_range);
#endif
uint64_t *addr_ptr = (uint64_t *) &dest_ctx->address.sin6.sin6_addr;
addr_ptr += 64 / (sizeof(uint64_t));
uint64_t calc = htonll(ntohll(*addr_ptr) + large_random);
memcpy(&(dest_ctx->address.sin.sin_addr), &calc, sizeof(struct in_addr));
}

break;

default:
LOGE("TcpConnector: invalid destination address type");
CSTATE_DROP(c);
cleanup(cstate, false);
goto fail;
}

// sockaddr_set_ipport(&(dest_ctx.addr), "127.0.0.1", 443);

hloop_t *loop = loops[c->line->tid];
int sockfd = socket(dest_ctx->address.sa.sa_family, SOCK_STREAM, 0);
if (sockfd < 0)
Expand All @@ -270,7 +315,6 @@ static void upStream(tunnel_t *self, context_t *c)
tcp_nodelay(sockfd, 1);
}


if (state->tcp_fast_open)
{
const int yes = 1;
Expand Down Expand Up @@ -375,14 +419,98 @@ tunnel_t *newTcpConnector(node_instance_context_t *instance_info)
}
if (state->dest_addr_selected.status == kDvsConstant)
{
state->constant_dest_addr.address_type = getHostAddrType(state->dest_addr_selected.value_ptr);
char *slash = strchr(state->dest_addr_selected.value_ptr, '/');
if (slash != NULL)
{
*slash = '\0';
int prefix_length = atoi(slash + 1);
state->constant_dest_addr.address_type = getHostAddrType(state->dest_addr_selected.value_ptr);

if (0 > prefix_length || prefix_length > 64) // 64-bits are the maximum
{
LOGF("TcpConnector: outbound ip/subnet range is invalid");
exit(1);
}

if (state->constant_dest_addr.address_type != kSatIPV6)
{
if (prefix_length > 32)
{
LOGF("TcpConnector: outbound ip/subnet range is invalid");
exit(1);
}

if (prefix_length > 0)
{
state->outbound_ip_range = htonl(0xFFFFFFFF & (0x1 << (32 - prefix_length)));
state->outbound_ip_range -= 1;
}
else
{
state->outbound_ip_range = 0;
}
state->outbound_ip_range = 0xFFFFFFFF & (0xFFFFFFFF << (32 - prefix_length));

uint32_t mask;
if (prefix_length > 0)
{
mask = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - prefix_length)));
}
else
{
mask = 0;
}
uint32_t calc = ((uint32_t) state->constant_dest_addr.address.sin.sin_addr.s_addr) & mask;
memcpy(&(state->constant_dest_addr.address.sin.sin_addr), &calc, sizeof(struct in_addr));
}
else
{
if (64 > prefix_length) // limit to 64
{
LOGF("TcpConnector: outbound ip/subnet range is invalid");
exit(1);
}

if (prefix_length > 0)
{
if (prefix_length == 64)
{
state->outbound_ip_range = 0xFFFFFFFFFFFFFFFFULL;
}
else
{
state->outbound_ip_range = htonl(0xFFFFFFFFFFFFFFFFULL & (0x1ULL << (128 - prefix_length)));
state->outbound_ip_range -= 1;
}
}
else
{
state->outbound_ip_range = 0;
}

uint8_t *addr_ptr = (uint8_t *) &(state->constant_dest_addr.address.sin6.sin6_addr);

for (int i = 0; i < 16; i++)
{
int bits = prefix_length >= 8 ? 8 : prefix_length;
addr_ptr[i] = bits == 0 ? 0 : addr_ptr[i] & (0xFF << (8 - bits));
prefix_length -= bits;
}
}
}
else
{
state->constant_dest_addr.address_type = getHostAddrType(state->dest_addr_selected.value_ptr);
}

if (state->constant_dest_addr.address_type == kSatDomainName)
{
socketContextDomainSetConstMem(&(state->constant_dest_addr), state->dest_addr_selected.value_ptr,
strlen(state->dest_addr_selected.value_ptr));
}
else
{

sockaddr_set_ip(&(state->constant_dest_addr.address), state->dest_addr_selected.value_ptr);
}
}
Expand Down
3 changes: 2 additions & 1 deletion tunnels/adapters/connector/tcp/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ typedef struct tcp_connector_state_s
// settings
bool tcp_no_delay;
bool tcp_fast_open;
bool reuse_addr;
bool reuse_addr; /* 8-bit pad*/
int domain_strategy;
dynamic_value_t dest_addr_selected;
dynamic_value_t dest_port_selected;
socket_context_t constant_dest_addr;
uint64_t outbound_ip_range;

} tcp_connector_state_t;

Expand Down
18 changes: 5 additions & 13 deletions ww/managers/socket_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,21 +280,13 @@ int parseIPWithSubnetMask(struct in6_addr *base_addr, const char *input, struct
return -1;
}
uint32_t mask;
if (sizeof(unsigned long long) == 8)
if (prefix_length > 0)
{
mask = htonl(0xFFFFFFFF &
((unsigned long long) 0x00000000FFFFFFFF << (unsigned long long) (32 - prefix_length)));
mask = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - prefix_length)));
}
else
{
if (prefix_length > 0)
{
mask = htonl(0xFFFFFFFF & (0xFFFFFFFF << (32 - prefix_length)));
}
else
{
mask = 0;
}
mask = 0;
}
struct in_addr mask_addr = {.s_addr = mask};
memcpy(subnet_mask, &mask_addr, 4);
Expand All @@ -309,8 +301,8 @@ int parseIPWithSubnetMask(struct in6_addr *base_addr, const char *input, struct
fprintf(stderr, "Invalid subnet mask length.\n");
return -1;
}
int i;
for (i = 0; i < 16; i++)

for (int i = 0; i < 16; i++)
{
int bits = prefix_length >= 8 ? 8 : prefix_length;
((uint8_t *) subnet_mask)[i] = bits == 0 ? 0 : (0xFF << (8 - bits));
Expand Down
8 changes: 8 additions & 0 deletions ww/utils/mathutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ static inline ssize_t max(ssize_t x, ssize_t y)
#define SMAXOF(t) (((0x1ULL << ((sizeof(t) * 8ULL) - 1ULL)) - 1ULL) | (0x7ULL << ((sizeof(t) * 8ULL) - 4ULL)))

#define MAXOF(t) ((unsigned long long) (ISSIGNED(t) ? SMAXOF(t) : UMAXOF(t)))

#if __BIG_ENDIAN__
#define htonll(x) (x)
#define ntohll(x) (x)
#else
#define htonll(x) (((uint64_t) htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32)) // NOLINT
#define ntohll(x) (((uint64_t) ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32)) // NOLINT
#endif

0 comments on commit 27163ab

Please sign in to comment.