1
0
mirror of https://github.com/rofl0r/proxychains-ng synced 2025-01-08 22:22:52 +08:00

udp wip 2

This commit is contained in:
hugoc 2023-09-08 14:42:52 +02:00
parent 2c5ad9f81a
commit 8348e42608
3 changed files with 648 additions and 16 deletions

View File

@ -424,16 +424,152 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
}
/* Given a socket connected to a SOCKS5 proxy server, performs a UDP_ASSOCIATE handshake and returns BND_ADDR and BND_PORT if successfull*/
static int udp_associate(int sock, ip_type dst_addr, unsigned short dst_port, ip_type *bnd_addr, unsigned short *bnd_port, char *user, char *pass){
/* Given a socket connected to a SOCKS5 proxy server, performs a UDP_ASSOCIATE handshake and returns BND_ADDR and BND_PORT if successfull.
Pass NULL dst_addr and dst_port to fill those fields with 0 if expected local addr and port for udp sending are unknown (see RFC1928) */
static int udp_associate(int sock, ip_type* dst_addr, unsigned short dst_port, socks5_addr* bnd_addr, unsigned short* bnd_port, char* user, char* pass){
//TODO hugoc
PFUNC();
size_t ulen = strlen(user);
size_t passlen = strlen(pass);
if(ulen > 0xFF || passlen > 0xFF) {
proxychains_write_log(LOG_PREFIX "error: maximum size of 255 for user/pass!\n");
goto err;
}
int len;
unsigned char buff[BUFF_SIZE];
char ip_buf[INET6_ADDRSTRLEN];
int n_methods = ulen ? 2 : 1;
buff[0] = 5; // version
buff[1] = n_methods ; // number of methods
buff[2] = 0; // no auth method
if(ulen) buff[3] = 2; /// auth method -> username / password
if(2+n_methods != write_n_bytes(sock, (char *) buff, 2+n_methods))
goto err;
if(2 != read_n_bytes(sock, (char *) buff, 2))
goto err;
if(buff[0] != 5 || (buff[1] != 0 && buff[1] != 2)) {
if(buff[0] == 5 && buff[1] == 0xFF)
return BLOCKED;
else
goto err;
}
if(buff[1] == 2) {
// authentication
char in[2];
char out[515];
char *cur = out;
size_t c;
*cur++ = 1; // version
c = ulen & 0xFF;
*cur++ = c;
memcpy(cur, user, c);
cur += c;
c = passlen & 0xFF;
*cur++ = c;
memcpy(cur, pass, c);
cur += c;
if((cur - out) != write_n_bytes(sock, out, cur - out))
goto err;
if(2 != read_n_bytes(sock, in, 2))
goto err;
/* according to RFC 1929 the version field for the user/pass auth sub-
negotiation should be 1, which is kinda counter-intuitive, so there
are some socks5 proxies that return 5 instead. other programs like
curl work fine when the version is 5, so let's do the same and accept
either of them. */
if(!(in[0] == 5 || in[0] == 1))
goto err;
if(in[1] != 0)
return BLOCKED;
}
int buff_iter = 0;
buff[buff_iter++] = 5; // version
buff[buff_iter++] = 3; // udp_associate
buff[buff_iter++] = 0; // reserved
if(dst_addr) {
int v6 = dst_addr->is_v6;
buff[buff_iter++] = v6 ? 4 : 1; // ip v4/v6
memcpy(buff + buff_iter, dst_addr->addr.v6, v6?16:4); // dest host
buff_iter += v6?16:4;
memcpy(buff + buff_iter, &dst_port, 2); // dest port
buff_iter += 2;
} else {
buff[buff_iter++] = 1; //we put atyp = 1, should we put 0 ?
buff[buff_iter++] = 0; // v4 byte1
buff[buff_iter++] = 0; // v4 byte2
buff[buff_iter++] = 0; // v4 byte3
buff[buff_iter++] = 0; // v4 byte4
buff[buff_iter++] = 0; // port byte1
buff[buff_iter++] = 0; // port byte2
}
if(buff_iter != write_n_bytes(sock, (char *) buff, buff_iter))
goto err;
if(4 != read_n_bytes(sock, (char *) buff, 4))
goto err;
if(buff[0] != 5 || buff[1] != 0)
goto err;
bnd_addr->atyp = buff[3];
switch (buff[3]) {
case 1:
len = 4;
break;
case 4:
len = 16;
break;
case 3:
PDEBUG("BND_ADDR in UDP_ASSOCIATE response should not be a domain name!\n");
goto err;
break;
default:
goto err;
}
if(len != read_n_bytes(sock, (char *) buff, len))
goto err;
memcpy(bnd_addr->addr.v6, buff+4,(len==16)?16:4);
if(2 != read_n_bytes(sock, (char *) buff, 2))
goto err;
memcpy(bnd_port, buff, 2);
return SUCCESS;
err:
return SOCKET_ERROR;
}
/* Fills buf with the SOCKS5 udp request header for the target dst_addr:dst_port*/
static int udp_header(socks5_addr dst_addr, unsigned short dst_port , char frag, char * buf, size_t buflen) {
static int write_udp_header(socks5_addr dst_addr, unsigned short dst_port , char frag, char * buf, size_t buflen) {
if (buflen <= 262) { //TODO: make something cleaner
int size = 0;
int v6 = dst_addr.atyp == ATYP_V6;
if(dst_addr.atyp == ATYP_DOM){
size = dst_addr.addr.dom.len;
} else {
size = v6?16:4;
}
if (buflen <= size) {
return -1;
}
@ -443,7 +579,7 @@ static int udp_header(socks5_addr dst_addr, unsigned short dst_port , char frag,
buf[buf_iter++] = frag; // frag
buf[buf_iter++] = dst_addr.atyp; // atyp
int v6 = dst_addr.atyp == ATYP_V6;
switch (dst_addr.atyp){
case ATYP_V6:
case ATYP_V4:
@ -464,7 +600,147 @@ static int udp_header(socks5_addr dst_addr, unsigned short dst_port , char frag,
return buf_iter;
}
static int encapsulate_udp_packet(udp_relay_chain rcd, ip_type target_addr, unsigned short target_port, char frag) {
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len) {
if (chain.head == NULL ){
PDEBUG("provided chain is empty\n");
return -1;
}
char *dns_name = NULL;
char hostnamebuf[MSG_LEN_MAX];
size_t dns_len = 0;
socks5_addr target_addr;
// we use ip addresses with 224.* to lookup their dns name in our table, to allow remote DNS resolution
// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
// the results returned from gethostbyname et al.)
// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
if(!target_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && target_ip.addr.v4.octet[0] == remote_dns_subnet) {
target_addr.atyp = ATYP_DOM;
dns_len = rdns_get_host_for_ip(target_ip.addr.v4, target_addr.addr.dom.name);
if(!dns_len) goto err;
else dns_name = target_addr.addr.dom.name;
target_addr.addr.dom.len = dns_len && 0xFF;
} else {
if(target_ip.is_v6){
target_addr.atyp = ATYP_V6;
memcpy(target_addr.addr.v6, target_ip.addr.v6, 16);
} else {
target_addr.atyp = ATYP_V4;
memcpy(target_addr.addr.v4.octet, target_ip.addr.v4.octet, 4);
}
}
PDEBUG("host dns %s\n", dns_name ? dns_name : "<NULL>");
// Allocate a new buffer for the packet data and all the headers
unsigned int headers_size = 0;
udp_relay_node * tmp = chain.head;
int len = 0;
while(tmp->next != NULL){
switch ((tmp->next)->bnd_addr.atyp)
{
case ATYP_V4:
len = 4;
break;
case ATYP_V6:
len = 6;
break;
case ATYP_DOM:
len = (tmp->next)->bnd_addr.addr.dom.len;
break;
default:
break;
}
headers_size += len;
tmp = tmp->next;
}
switch (target_addr.atyp)
{
case ATYP_V4:
len = 4;
break;
case ATYP_V6:
len = 6;
break;
case ATYP_DOM:
len = target_addr.addr.dom.len;
break;
default:
break;
}
headers_size += len;
char * buff = NULL;
if (NULL == (buff = (char*)malloc(headers_size+data_len))){
PDEBUG("error malloc buffer\n");
return -1;
}
// Append each header to the buffer
unsigned int written = 0;
unsigned int offset = 0;
tmp = chain.head;
while (tmp->next != NULL)
{
written = write_udp_header((tmp->next)->bnd_addr, (tmp->next)->bnd_port, 0, buff+offset, headers_size + data_len - offset);
if (written == -1){
PDEBUG("error write_udp_header\n");
goto err;
}
offset += written;
tmp = tmp->next;
}
written = write_udp_header(target_addr, target_port, 0, buff + offset, headers_size + data_len - offset);
if (written == -1){
PDEBUG("error write_udp_header\n");
goto err;
}
offset += written;
// Append data to the buffer
memcpy(buff + offset, data, data_len);
// Send the packet
// FIXME: should write_n_bytes be used here instead ?
if(chain.head->bnd_addr.atyp == ATYP_DOM){
PDEBUG("BND_ADDR of type DOMAINE (0x03) not supported yet\n");
goto err;
}
int v6 = chain.head->bnd_addr.atyp == ATYP_V6;
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_port = chain.head->bnd_port,
.sin_addr.s_addr = (in_addr_t) chain.head->bnd_addr.addr.v4.as_int,
};
struct sockaddr_in6 addr6 = {
.sin6_family = AF_INET6,
.sin6_port = chain.head->bnd_port,
};
if(v6) memcpy(&addr6.sin6_addr.s6_addr, chain.head->bnd_addr.addr.v6, 16);
sendto(sockfd, buff, offset+data_len, 0, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr) );
err:
free(buff);
return -1;
}
@ -474,8 +750,10 @@ static int encapsulate_udp_packet(udp_relay_chain rcd, ip_type target_addr, unsi
#define ST "Strict chain"
#define RT "Random chain"
#define RRT "Round Robin chain"
#define UDPC "UDP_ASSOCIATE tcp socket chain"
static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
PFUNC();
int v6 = pd->ip.is_v6;
*fd = socket(v6?PF_INET6:PF_INET, SOCK_STREAM, 0);
@ -514,6 +792,9 @@ static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
}
static proxy_data *select_proxy(select_type how, proxy_data * pd, unsigned int proxy_count, unsigned int *offset) {
PFUNC();
PDEBUG("offset: %d\n", *offset);
PDEBUG("state: %d\n", pd[0].ps);
unsigned int i = 0, k = 0;
if(*offset >= proxy_count)
return NULL;
@ -780,6 +1061,240 @@ int connect_proxy_chain(int sock, ip_type target_ip,
return -1;
}
// int connect_to_lastnode(int *sock, udp_relay_chain chain){
// udp_relay_node * current_node = chain.head;
// //First connect to the chain head
// if(SUCCESS != start_chain(sock, &(current_node->pd), UDPC)){
// PDEBUG("start_chain failed\n");
// return -1;
// }
// // Connect to the rest of the chain
// while(current_node->next != NULL){
// if(SUCCESS != chain_step(sock, &(current_node->pd), &(current_node->next->pd))){
// PDEBUG("chain step failed\n");
// return -1;
// }
// current_node = current_node->next;
// }
// return SUCCESS;
// }
int add_node_to_chain(proxy_data * pd, udp_relay_chain * chain){
PFUNC();
// Allocate memory for the new node structure
udp_relay_node * new_node = NULL;
if(NULL == (new_node = (udp_relay_node *)malloc(sizeof(udp_relay_node)))){
PDEBUG("error malloc new node\n");
return -1;
}
new_node->next = NULL;
udp_relay_node * tmp = chain->head;
if(tmp == NULL){ // Means new_node is the first node to be created
chain->head = new_node;
new_node->prev = NULL;
} else {
// Moving to the end of the current chain
while(tmp->next != NULL){
tmp = tmp->next;
}
// Adding the new node at the end
tmp->next = new_node;
new_node->prev = tmp;
}
// Initializing the new node
new_node->pd.ip = pd->ip;
new_node->pd.port = pd->port;
new_node->pd.pt = pd->pt;
new_node->pd.ps = pd->ps;
strcpy(new_node->pd.user, pd->user);
strcpy(new_node->pd.pass, pd->pass);
// Connecting the new node tcp_socketfd to the associated proxy through the current chain
//
tmp = chain->head;
// First connect to the chain head
if(SUCCESS != start_chain(&(new_node->tcp_sockfd), &(tmp->pd), UDPC)){
PDEBUG("start_chain failed\n");
new_node->tcp_sockfd = -1;
goto err;
}
// Connect to the rest of the chain
while(tmp->next != NULL){
if(SUCCESS != chain_step(new_node->tcp_sockfd, &(tmp->pd), &(tmp->next->pd))){
PDEBUG("chain step failed\n");
new_node->tcp_sockfd = -1;
goto err;
}
tmp = tmp->next;
}
// Performing UDP_ASSOCIATE handshake in order to fill the new node BND_ADDR and BND_PORT
if(SUCCESS != udp_associate(new_node->tcp_sockfd, NULL, NULL, &(new_node->bnd_addr), &(new_node->bnd_port), new_node->pd.user, new_node->pd.pass)){
PDEBUG("udp_associate failed\n");
goto err;
}
PDEBUG("new node added and open to relay UDP packets\n");
return SUCCESS;
err:
// Ensure new node tcp socket is closed
if(new_node->tcp_sockfd != -1){
close(new_node->tcp_sockfd);
}
// Remove the new node from the chain
if(new_node->prev == NULL){ // means new_node is the only node in chain
chain->head = NULL;
} else{
(new_node->prev)->next = NULL;
}
// Free memory
free(new_node);
return -1;
}
int free_relay_chain_nodes(udp_relay_chain chain){
if(chain.head == NULL){
return SUCCESS;
}
udp_relay_node * current = chain.head;
udp_relay_node * next = NULL;
while(current != NULL){
next = current->next;
close(current->tcp_sockfd);
free(current);
current = next;
}
return SUCCESS;
}
udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, chain_type ct, unsigned int max_chains){
PFUNC();
// Allocate memory for the new relay chain
udp_relay_chain * new_chain = NULL;
if(NULL == (new_chain = (udp_relay_chain *)malloc(sizeof(udp_relay_chain)))){
PDEBUG("error malloc new chain\n");
return NULL;
}
new_chain->head = NULL;
new_chain->sockfd = -1;
unsigned int alive_count = 0;
unsigned int offset = 0;
proxy_data *p1;
switch (ct)
{
case DYNAMIC_TYPE:
PDEBUG("DYNAMIC_TYPE not yet supported for UDP\n");
goto error;
break;
case ROUND_ROBIN_TYPE:
PDEBUG("ROUND_ROBIN_TYPE not yet supported for UDP\n");
goto error;
break;
case STRICT_TYPE:
alive_count = calc_alive(pd, proxy_count);
offset = 0;
PDEBUG("opening STRICT_TYPE relay chain, alive_count=%d, offset=%d\n", alive_count, offset);
while((p1 = select_proxy(FIFOLY, pd, proxy_count, &offset))) {
if(SUCCESS != add_node_to_chain(p1, new_chain)) {
PDEBUG("add_node_to_chain failed\n");
p1->pt = BLOCKED_STATE;
goto error;
}
p1->pt = BUSY_STATE;
}
return new_chain;
break;
case RANDOM_TYPE:
PDEBUG("RANDOM_TYPE not yet supported for UDP\n");
goto error;
break;
default:
break;
}
error:
PDEBUG("error\n");
release_all(pd, proxy_count);
free_relay_chain_nodes(*new_chain);
free(new_chain);
errno = ETIMEDOUT;
return NULL;
}
void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_chain){
new_chain->next = NULL;
if(chains_list->tail == NULL){ // The current list is empty, set head and tail to the new chain
chains_list->head = new_chain;
chains_list->tail = new_chain;
new_chain->prev = NULL;
} else {
// Add the new chain at the end
chains_list->tail->next = new_chain;
new_chain->prev = chains_list->tail;
chains_list->tail = new_chain;
}
}
void del_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* chain){
if(chain == chains_list->head){
if(chain->next == NULL){
free(chain);
chains_list->head = NULL;
chains_list->tail = NULL;
}else{
chains_list->head = chain->next;
free(chain);
}
} else if (chain = chains_list->tail){
chains_list->tail = chain->prev;
free(chain);
} else {
chain->next->prev = chain->prev;
chain->prev->next = chain->next;
free(chain);
}
}
udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd){
udp_relay_chain* tmp = chains_list.head;
while(tmp != NULL){
if(tmp->sockfd == sockfd){
break;
}
tmp = tmp->next;
}
return tmp;
}
static pthread_mutex_t servbyname_lock;
void core_initialize(void) {
MUTEX_INIT(&servbyname_lock);

View File

@ -109,28 +109,38 @@ typedef struct{
unsigned char v6[16];
struct {
char len;
char name[255];
char name[256];
} dom;
} addr ;
} socks5_addr;
/* A structure to hold necessary information about an UDP relay server that has been set up
with a UDP_ASSOCIATE command issued on the tcp_sockfd */
typedef struct {
typedef struct s_udp_relay_node {
int tcp_sockfd; // the tcp socket on which the UDP_ASSOCIATE command has been issued. Closing this fd closes the udp relay.
proxy_data pd; // the associated SOCKS5 server
socks5_addr bnd_addr; // the BND_ADDR returned by the udp relay server in the response to the UDP_ASSOCIATE command.
unsigned short bnd_port; // the BND_PORT returned by the udp relay server in the response to the UDP_ASSOCIATE command.
socks5_addr dst_addr; // ?? the DST_ADDR sent in the UDP_ASSOCIATE command.
unsigned short dst_port; // ?? the DST_PORT sent in the UDP_ASSOCIATE command.
} udp_relay_data;
struct s_udp_relay_node * prev;
struct s_udp_relay_node * next;
} udp_relay_node;
/* A structure to hold the chain of udp relay servers assiociated with a client socket */
typedef struct {
typedef struct s_udp_relay_chain {
int sockfd; // the client socket for which the chain of relays has been set up
udp_relay_data * ud; // an array of relay, ud[0] being the closest to the client and u[len(ud)-1] the closest to the targets
unsigned int relay_count;
udp_relay_node * head; // head of the linked list of udp_relay_node
struct s_udp_relay_chain * prev;
struct s_udp_relay_chain * next;
} udp_relay_chain;
typedef struct {
udp_relay_chain * head;
udp_relay_chain * tail;
} udp_relay_chain_list;
int connect_proxy_chain (int sock, ip_type target_ip, unsigned short target_port,
proxy_data * pd, unsigned int proxy_count, chain_type ct,
unsigned int max_chain );
@ -185,7 +195,12 @@ void proxy_freeaddrinfo(struct addrinfo *res);
void core_initialize(void);
void core_unload(void);
static int udp_associate(int sock, ip_type dst_addr, unsigned short dst_port, ip_type *bnd_addr, unsigned short *bnd_port, char *user, char *pass);
static int udp_associate(int sock, ip_type * dst_addr, unsigned short dst_port, socks5_addr *bnd_addr, unsigned short *bnd_port, char *user, char *pass);
udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd);
void del_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* chain);
void add_relay_chain(udp_relay_chain_list* chains_list, udp_relay_chain* new_chain);
udp_relay_chain * open_relay_chain(proxy_data *pd, unsigned int proxy_count, chain_type ct, unsigned int max_chains);
int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsigned short target_port, char frag, char * data, unsigned int data_len);
#include "debug.h"

View File

@ -84,6 +84,8 @@ dnat_arg dnats[MAX_DNAT];
size_t num_dnats = 0;
unsigned int remote_dns_subnet = 224;
udp_relay_chain_list relay_chains = {NULL, NULL};
pthread_once_t init_once = PTHREAD_ONCE_INIT;
static int init_l = 0;
@ -901,12 +903,112 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
dest_addr = NULL;
addrlen = 0;
flags &= ~MSG_FASTOPEN;
}
//TODO hugoc: case of SOCK_DGRAM with AF_INET or AF_INET6
return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
//TODO hugoc: case of SOCK_DGRAM with AF_INET or AF_INET6
DEBUGDECL(char str[256]);
int socktype = 0, ret = 0;
socklen_t optlen = 0;
optlen = sizeof(socktype);
sa_family_t fam = SOCKFAMILY(*dest_addr);
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
if(!((fam == AF_INET || fam == AF_INET6) && socktype == SOCK_DGRAM)){
return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
ip_type dest_ip;
struct in_addr *p_addr_in;
struct in6_addr *p_addr_in6;
dnat_arg *dnat = NULL;
size_t i;
int remote_dns_connect = 0;
unsigned short port;
int v6 = dest_ip.is_v6 = fam == AF_INET6;
p_addr_in = &((struct sockaddr_in *) dest_addr)->sin_addr;
p_addr_in6 = &((struct sockaddr_in6 *) dest_addr)->sin6_addr;
port = !v6 ? ntohs(((struct sockaddr_in *) dest_addr)->sin_port)
: ntohs(((struct sockaddr_in6 *) dest_addr)->sin6_port);
struct in_addr v4inv6;
if(v6 && is_v4inv6(p_addr_in6)) {
memcpy(&v4inv6.s_addr, &p_addr_in6->s6_addr[12], 4);
v6 = dest_ip.is_v6 = 0;
p_addr_in = &v4inv6;
}
if(!v6 && !memcmp(p_addr_in, "\0\0\0\0", 4)) {
errno = ECONNREFUSED;
return -1;
}
PDEBUG("target: %s\n", inet_ntop(v6 ? AF_INET6 : AF_INET, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, str, sizeof(str)));
PDEBUG("port: %d\n", port);
// check if connect called from proxydns
remote_dns_connect = !v6 && (ntohl(p_addr_in->s_addr) >> 24 == remote_dns_subnet);
// more specific first
if (!v6) for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++)
if(dnats[i].orig_dst.s_addr == p_addr_in->s_addr)
if(dnats[i].orig_port && (dnats[i].orig_port == port))
dnat = &dnats[i];
if (!v6) for(i = 0; i < num_dnats && !remote_dns_connect && !dnat; i++)
if(dnats[i].orig_dst.s_addr == p_addr_in->s_addr)
if(!dnats[i].orig_port)
dnat = &dnats[i];
if (dnat) {
p_addr_in = &dnat->new_dst;
if (dnat->new_port)
port = dnat->new_port;
}
for(i = 0; i < num_localnet_addr && !remote_dns_connect; i++) {
if (localnet_addr[i].port && localnet_addr[i].port != port)
continue;
if (localnet_addr[i].family != (v6 ? AF_INET6 : AF_INET))
continue;
if (v6) {
size_t prefix_bytes = localnet_addr[i].in6_prefix / CHAR_BIT;
size_t prefix_bits = localnet_addr[i].in6_prefix % CHAR_BIT;
if (prefix_bytes && memcmp(p_addr_in6->s6_addr, localnet_addr[i].in6_addr.s6_addr, prefix_bytes) != 0)
continue;
if (prefix_bits && (p_addr_in6->s6_addr[prefix_bytes] ^ localnet_addr[i].in6_addr.s6_addr[prefix_bytes]) >> (CHAR_BIT - prefix_bits))
continue;
} else {
if((p_addr_in->s_addr ^ localnet_addr[i].in_addr.s_addr) & localnet_addr[i].in_mask.s_addr)
continue;
}
PDEBUG("accessing localnet using true_sendto\n");
return true_sendto(sockfd, buf, len, flags, dest_addr, addrlen);
}
// Check if a chain of UDP relay is already opened for this socket
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd);
if(relay_chain == NULL){
// No chain is opened for this socket, open one
PDEBUG("opening new chain of relays for %d\n", sockfd);
if(NULL == (relay_chain = open_relay_chain(proxychains_pd, proxychains_proxy_count, proxychains_ct, proxychains_max_chain))){
PDEBUG("could not open a chain of relay\n");
errno = ECONNREFUSED;
return -1;
}
relay_chain->sockfd = sockfd;
add_relay_chain(&relay_chains, relay_chain);
}
memcpy(dest_ip.addr.v6, v6 ? (void*)p_addr_in6 : (void*)p_addr_in, v6?16:4);
if (SUCCESS != send_udp_packet(sockfd, *relay_chain, dest_ip, htons(port),0, buf, len)){
PDEBUG("could not send udp packet\n");
errno = ECONNREFUSED;
return -1;
}
return SUCCESS;
}
HOOKFUNC(ssize_t, recv, int sockfd, void *buf, size_t len, int flags){
INIT();
PFUNC();