mirror of
https://github.com/rofl0r/proxychains-ng
synced 2025-01-23 01:12:59 +08:00
separate functions, add utils, hook recvmsg
This commit is contained in:
parent
45aed8644f
commit
8ed4b52140
336
src/core.c
336
src/core.c
@ -633,13 +633,13 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
||||
case ATYP_V6:
|
||||
PDEBUG("UDP header with ATYP_V4/6 addr type\n");
|
||||
v6 = src_addr->atyp == ATYP_V6;
|
||||
PDEBUG("buflen : %d\n", buflen);
|
||||
if(buflen < (4 + 2 + v6?16:4) ){
|
||||
PDEBUG("buffer too short to read the UDP header\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(src_addr->addr.v6, buf + buf_iter, v6?16:4);
|
||||
buf_iter += v6?16:4;
|
||||
cast_socks5addr_v4inv6_to_v4(src_addr);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -651,7 +651,186 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
||||
return buf_iter;
|
||||
}
|
||||
|
||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len ){
|
||||
size_t get_iov_total_len(struct iovec* iov, size_t iov_len){
|
||||
size_t n = 0;
|
||||
for(int i=0; i<iov_len; i++){
|
||||
n += iov[i].iov_len;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t write_buf_to_iov(void* buff, size_t buff_len, struct iovec* iov, size_t iov_len){
|
||||
size_t written = 0;
|
||||
int i = 0;
|
||||
size_t min = 0;
|
||||
//size_t iov_total_len = get_iov_total_len(iov, iov_len);
|
||||
|
||||
while( (written < buff_len) && (i < iov_len)){
|
||||
min = ((buff_len-written)<iov[i].iov_len)?(buff_len-written):iov[i].iov_len;
|
||||
memcpy(iov[i].iov_base, buff+written, min);
|
||||
written += min;
|
||||
i += 1;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
void cast_socks5addr_v4inv6_to_v4(socks5_addr* addr){
|
||||
if( (addr->atyp == ATYP_V6) && !memcmp(addr->addr.v6, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12)){
|
||||
PDEBUG("casting v4inv6 address to v4 address\n");
|
||||
addr->atyp=ATYP_V4;
|
||||
memcpy(addr->addr.v4.octet, addr->addr.v6+12, 4);
|
||||
}
|
||||
}
|
||||
|
||||
int compare_iptype_sockaddr(ip_type addr1, struct sockaddr addr2){
|
||||
if(addr1.is_v6 && (((struct sockaddr_in6 *) &(addr2))->sin6_family == AF_INET6)){
|
||||
//Both are IPv6
|
||||
return !memcmp(((struct sockaddr_in6 *)&addr2)->sin6_addr.s6_addr, addr1.addr.v6, 16);
|
||||
} else if(!addr1.is_v6 && (((struct sockaddr_in *) &(addr2))->sin_family == AF_INET)){
|
||||
//Both are IPv4
|
||||
return ((uint32_t)(((struct sockaddr_in *)&addr2)->sin_addr.s_addr) == addr1.addr.v4.as_int);
|
||||
} else {
|
||||
// Not the same address type
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int compare_socks5_addr_iptype(socks5_addr addr1, ip_type addr2){
|
||||
PFUNC();
|
||||
if(addr1.atyp == ATYP_DOM){
|
||||
//addr1 is a domain name
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((addr1.atyp == ATYP_V6) && addr2.is_v6){
|
||||
//Both are IPv6
|
||||
return !memcmp(addr1.addr.v6, addr2.addr.v6, 16);
|
||||
} else if((addr1.atyp == ATYP_V4) && !addr2.is_v6){
|
||||
//Both are IPv4
|
||||
return (addr1.addr.v4.as_int == addr2.addr.v4.as_int);
|
||||
} else {
|
||||
// Not the same address type
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr){
|
||||
|
||||
if(compare_iptype_sockaddr(chain.head->bnd_addr, src_addr)){
|
||||
return (chain.head->bnd_port == ((struct sockaddr_in*)&src_addr)->sin_port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int decapsulate_check_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, socks5_addr* src_addr, unsigned short* src_port, void* udp_data, size_t* udp_data_len){
|
||||
|
||||
PFUNC();
|
||||
// Go through the whole proxy chain, decapsulate each header and check that the addresses match
|
||||
|
||||
udp_relay_node * tmp = chain.head;
|
||||
int read = 0;
|
||||
int rc = 0;
|
||||
socks5_addr header_addr;
|
||||
unsigned short header_port;
|
||||
char header_frag;
|
||||
while (tmp->next != NULL)
|
||||
{
|
||||
rc = read_udp_header(in_buffer+read, in_buffer_len-read, &header_addr, &header_port, &header_frag );
|
||||
if(-1 == rc){
|
||||
PDEBUG("error reading UDP header\n");
|
||||
return -1;
|
||||
}
|
||||
read += rc;
|
||||
|
||||
if(header_frag != 0x00){
|
||||
printf("WARNING: received UDP packet with frag != 0 while fragmentation is unsupported.\n");
|
||||
}
|
||||
|
||||
if(!compare_socks5_addr_iptype(header_addr, tmp->next->bnd_addr)){
|
||||
PDEBUG("UDP header addr is not equal to proxy node addr, dropping packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(tmp->next->bnd_port != header_port){
|
||||
PDEBUG("UDP header port is not equal to proxy node port, dropping packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PDEBUG("UDP header's addr and port correspond to proxy node's addr and port\n");
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
PDEBUG("all UDP headers validated\n");
|
||||
|
||||
|
||||
// Decapsulate the last header. No checks needed here, just pass the source addr and port as return values
|
||||
rc = read_udp_header(in_buffer+read, in_buffer_len-read, src_addr, src_port, &header_frag);
|
||||
if(-1 == rc){
|
||||
PDEBUG("error reading UDP header\n");
|
||||
return -1;
|
||||
}
|
||||
read += rc;
|
||||
|
||||
if(header_frag != 0x00){
|
||||
printf("WARNING: received UDP packet with frag != 0 while fragmentation is unsupported.\n");
|
||||
}
|
||||
|
||||
|
||||
// Copy the UDP data to the provided buffer. If the provided buffer is too small, data is truncated
|
||||
int min = ((in_buffer_len-read)>*udp_data_len)?*udp_data_len:(in_buffer_len-read);
|
||||
memcpy(udp_data,in_buffer+read, min);
|
||||
|
||||
// Write back the length of written UDP data in the input/output parameter udp_data_len
|
||||
*udp_data_len = min;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unsocks_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, void* udp_data, size_t* udp_data_len){
|
||||
PFUNC();
|
||||
// Decapsulate all the UDP headers and check that the packet came from the right proxy nodes
|
||||
int rc;
|
||||
socks5_addr src_addr;
|
||||
rc = decapsulate_check_udp_packet(in_buffer, in_buffer_len, chain, &src_addr, src_port, udp_data, udp_data_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error decapsulating the packet\n");
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("all UDP headers decapsulated and validated\n");
|
||||
|
||||
// If the innermost UDP header (containing the address of the final target) is of type ATYP_DOM, perform a
|
||||
// reverse mapping to hand the 224.X.X.X IP to the client application
|
||||
|
||||
if(src_addr.atyp == ATYP_DOM){
|
||||
PDEBUG("Fetching matching IP for hostname\n");
|
||||
DUMP_BUFFER(src_addr.addr.dom.name,src_addr.addr.dom.len);
|
||||
ip_type4 tmp_ip = IPT4_INVALID;
|
||||
char host_string[256];
|
||||
memcpy(host_string, src_addr.addr.dom.name, src_addr.addr.dom.len);
|
||||
host_string[src_addr.addr.dom.len] = 0x00;
|
||||
|
||||
tmp_ip = rdns_get_ip_for_host(host_string, src_addr.addr.dom.len);
|
||||
if(tmp_ip.as_int == -1){
|
||||
PDEBUG("error getting ip for host\n");
|
||||
return -1;
|
||||
}
|
||||
src_addr.atyp = ATYP_V4;
|
||||
src_addr.addr.v4.as_int = tmp_ip.as_int;
|
||||
|
||||
}
|
||||
|
||||
src_ip->is_v6 = (src_addr.atyp == ATYP_V6);
|
||||
if(src_ip->is_v6){
|
||||
memcpy(src_ip->addr.v6, src_addr.addr.v6, 16);
|
||||
} else{
|
||||
src_ip->addr.v4.as_int = src_addr.addr.v4.as_int;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, char* data, unsigned int data_len ){
|
||||
//receives data on sockfd, decapsulates the header for each relay in chain and check they match, returns UDP data and source address/port
|
||||
|
||||
PFUNC();
|
||||
@ -671,129 +850,68 @@ int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, uns
|
||||
PDEBUG("successful recvfrom(), %d bytes received\n", bytes_received);
|
||||
//Check that the packet was received from the first relay of the chain
|
||||
// i.e. does from == chain.head.bnd_addr ?
|
||||
int from_isv6 = ((struct sockaddr_in *) &(from))->sin_family == AF_INET6;
|
||||
int same_address = 0;
|
||||
int same_port = 0;
|
||||
|
||||
if(chain.head->bnd_addr.is_v6){
|
||||
if(from_isv6){
|
||||
same_address = memcmp(((struct sockaddr_in6 *)&from)->sin6_addr.s6_addr, chain.head->bnd_addr.addr.v6, 16);
|
||||
}
|
||||
}
|
||||
else{
|
||||
uint32_t from_v4_asint;
|
||||
if(from_isv6){
|
||||
// Maybe from is a ipv4-mapped ipv6 ? // TODO: use the existing is_v4inv6 as in connect and sendto
|
||||
memcpy(from_v4_asint, ((struct sockaddr_in6 *)&from)->sin6_addr.s6_addr + 11, 4);
|
||||
}
|
||||
else{
|
||||
from_v4_asint = (uint32_t)(((struct sockaddr_in *)&from)->sin_addr.s_addr);
|
||||
}
|
||||
|
||||
same_address = from_v4_asint == chain.head->bnd_addr.addr.v4.as_int;
|
||||
}
|
||||
|
||||
same_port = chain.head->bnd_port == from_isv6?((struct sockaddr_in6 *)&from)->sin6_port:((struct sockaddr_in *)&from)->sin_port;
|
||||
|
||||
if(!(same_address && same_port)){
|
||||
if(!is_from_chain_head(chain, from)){
|
||||
PDEBUG("UDP packet not received from the proxy chain's head, transfering it as is\n");
|
||||
int min = (bytes_received <= data_len)?bytes_received:data_len;
|
||||
//TODO : il faut aussi transmettre les adresses et ports qu ón a recu a l'appli qui a fait le call !!!!!
|
||||
memcpy(data, buffer, min);
|
||||
return min;
|
||||
}
|
||||
|
||||
PDEBUG("packet received from the proxy chain's head\n");
|
||||
// Go through the whole proxy chain, decapsulate each header and check that the addresses match
|
||||
|
||||
udp_relay_node * tmp = chain.head;
|
||||
int read = 0;
|
||||
int rc = 0;
|
||||
socks5_addr header_addr;
|
||||
unsigned short header_port;
|
||||
char header_frag;
|
||||
while (tmp->next != NULL)
|
||||
{
|
||||
same_address = 0;
|
||||
|
||||
|
||||
|
||||
rc = read_udp_header(buffer+read, bytes_received-read, &header_addr, &header_port, &header_frag );
|
||||
if(-1 == rc){
|
||||
PDEBUG("error reading UDP header\n");
|
||||
return -1;
|
||||
}
|
||||
read += rc;
|
||||
|
||||
int header_v6 = header_addr.atyp == ATYP_V6;
|
||||
|
||||
if(tmp->next->bnd_port != header_port){
|
||||
PDEBUG("UDP header port is not equal to proxy node port, dropping packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(tmp->next->bnd_addr.is_v6){
|
||||
if(header_v6){
|
||||
same_address = memcmp(tmp->next->bnd_addr.addr.v6, header_addr.addr.v6, 16);
|
||||
}
|
||||
}
|
||||
else{
|
||||
same_address = memcmp(&(tmp->next->bnd_addr.addr.v4), header_v6?(&(header_addr.addr.v6)+11):&(header_addr.addr.v4), 4);
|
||||
}
|
||||
|
||||
|
||||
if(!same_address){
|
||||
PDEBUG("UDP header addr is not equal to proxy node addr, dropping packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PDEBUG("UDP header's addr and port correspond to proxy node's addr and port\n");
|
||||
tmp = tmp->next;
|
||||
|
||||
}
|
||||
|
||||
PDEBUG("all UDP headers validated\n");
|
||||
|
||||
|
||||
// Decapsulate the last header. No checks needed here, just pass the source addr and port as return values
|
||||
char frag;
|
||||
rc = read_udp_header(buffer+read, bytes_received-read, &header_addr, src_port, &frag);
|
||||
if(-1 == rc){
|
||||
PDEBUG("error reading UDP header\n");
|
||||
int rc;
|
||||
size_t udp_data_len = data_len;
|
||||
rc = unsocks_udp_packet(buffer, bytes_received, chain, src_ip, src_port, data, &udp_data_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error unSOCKSing the UDP packet\n");
|
||||
return -1;
|
||||
}
|
||||
read += rc;
|
||||
|
||||
if(header_addr.atyp == ATYP_DOM){ // do the reverse mapping
|
||||
PDEBUG("Fetching matching IP for hostname\n");
|
||||
DUMP_BUFFER(header_addr.addr.dom.name,header_addr.addr.dom.len);
|
||||
ip_type4 tmp_ip = IPT4_INVALID;
|
||||
char host_string[256];
|
||||
memcpy(host_string, header_addr.addr.dom.name, header_addr.addr.dom.len);
|
||||
host_string[header_addr.addr.dom.len] = 0x00;
|
||||
|
||||
tmp_ip = rdns_get_ip_for_host(host_string, header_addr.addr.dom.len);
|
||||
if(tmp_ip.as_int == -1){
|
||||
PDEBUG("No matching IP found for hostname\n");
|
||||
return -1;
|
||||
}
|
||||
header_addr.atyp = ATYP_V4;
|
||||
header_addr.addr.v4.as_int = tmp_ip.as_int;
|
||||
PDEBUG("UDP packet successfully unSOCKified\n");
|
||||
|
||||
}
|
||||
|
||||
src_addr->is_v6 = (header_addr.atyp == ATYP_V6);
|
||||
if(src_addr->is_v6){
|
||||
memcpy(src_addr->addr.v6, header_addr.addr.v6, 16);
|
||||
} else{
|
||||
src_addr->addr.v4.as_int = header_addr.addr.v4.as_int;
|
||||
}
|
||||
return udp_data_len;
|
||||
|
||||
// // Decapsulate all the UDP headers and check that the packet came from the right proxy nodes
|
||||
// int rc;
|
||||
// socks5_addr src_addr;
|
||||
// size_t udp_data_len = data_len;
|
||||
// rc = decapsulate_check_udp_packet(buffer, bytes_received, chain, &src_addr, src_port, data, &udp_data_len);
|
||||
// if(rc != SUCCESS){
|
||||
// PDEBUG("error decapsulating the packet\n");
|
||||
// return -1;
|
||||
// }
|
||||
// PDEBUG("all UDP headers decapsulated and validated\n");
|
||||
|
||||
int min = ((bytes_received-read)>data_len)?data_len:(bytes_received-read);
|
||||
memcpy(data,buffer+read, min);
|
||||
// // If the innermost UDP header (containing the address of the final target) is of type ATYP_DOM, perform a
|
||||
// // reverse mapping to hand the 224.X.X.X IP to the client application
|
||||
|
||||
// if(src_addr.atyp == ATYP_DOM){
|
||||
// PDEBUG("Fetching matching IP for hostname\n");
|
||||
// DUMP_BUFFER(src_addr.addr.dom.name,src_addr.addr.dom.len);
|
||||
// ip_type4 tmp_ip = IPT4_INVALID;
|
||||
// char host_string[256];
|
||||
// memcpy(host_string, src_addr.addr.dom.name, src_addr.addr.dom.len);
|
||||
// host_string[src_addr.addr.dom.len] = 0x00;
|
||||
|
||||
// tmp_ip = rdns_get_ip_for_host(host_string, src_addr.addr.dom.len);
|
||||
// if(tmp_ip.as_int == -1){
|
||||
// PDEBUG("error getting ip for host\n");
|
||||
// return -1;
|
||||
// }
|
||||
// src_addr.atyp = ATYP_V4;
|
||||
// src_addr.addr.v4.as_int = tmp_ip.as_int;
|
||||
|
||||
return min;
|
||||
// }
|
||||
|
||||
// src_ip->is_v6 = (src_addr.atyp == ATYP_V6);
|
||||
// if(src_ip->is_v6){
|
||||
// memcpy(src_ip->addr.v6, src_addr.addr.v6, 16);
|
||||
// } else{
|
||||
// src_ip->addr.v4.as_int = src_addr.addr.v4.as_int;
|
||||
// }
|
||||
|
||||
// return udp_data_len;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
11
src/core.h
11
src/core.h
@ -103,7 +103,6 @@ typedef enum {
|
||||
} ATYP;
|
||||
|
||||
typedef struct{
|
||||
ATYP atyp;
|
||||
union {
|
||||
ip_type4 v4;
|
||||
unsigned char v6[16];
|
||||
@ -112,6 +111,7 @@ typedef struct{
|
||||
char name[255];
|
||||
} dom;
|
||||
} addr ;
|
||||
ATYP atyp;
|
||||
} socks5_addr;
|
||||
|
||||
/* A structure to hold necessary information about an UDP relay server that has been set up
|
||||
@ -170,6 +170,9 @@ typedef ssize_t (*recv_t) (int sockfd, void *buf, size_t len, int flags);
|
||||
typedef ssize_t (*recvfrom_t) (int sockfd, void *buf, size_t len, int flags,
|
||||
struct sockaddr *src_addr, socklen_t *addrlen);
|
||||
|
||||
typedef ssize_t (*sendmsg_t) (int sockfd, const struct msghdr *msg, int flags);
|
||||
typedef ssize_t (*recvmsg_t) (int sockfd, struct msghdr *msg, int flags);
|
||||
|
||||
|
||||
extern connect_t true_connect;
|
||||
extern gethostbyname_t true_gethostbyname;
|
||||
@ -181,6 +184,8 @@ extern sendto_t true_sendto;
|
||||
extern recvfrom_t true_recvfrom;
|
||||
extern recv_t true_recv;
|
||||
extern send_t true_send;
|
||||
extern sendmsg_t true_sendmsg;
|
||||
extern recvmsg_t true_recvmsg;
|
||||
|
||||
struct gethostbyname_data {
|
||||
struct hostent hostent_space;
|
||||
@ -207,6 +212,10 @@ int free_relay_chain_nodes(udp_relay_chain 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);
|
||||
int receive_udp_packet(int sockfd, udp_relay_chain chain, ip_type* src_addr, unsigned short* src_port, char* data, unsigned int data_len );
|
||||
size_t get_msg_iov_total_len(struct iovec* iov, size_t iov_len);
|
||||
size_t write_buf_to_iov(void* buff, size_t buff_len, struct iovec* iov, size_t iov_len);
|
||||
int is_from_chain_head(udp_relay_chain chain, struct sockaddr src_addr);
|
||||
int unsocks_udp_packet(void* in_buffer, size_t in_buffer_len, udp_relay_chain chain, ip_type* src_ip, unsigned short* src_port, void* udp_data, size_t* udp_data_len);
|
||||
#include "debug.h"
|
||||
|
||||
#endif
|
||||
|
@ -67,6 +67,8 @@ sendto_t true_sendto;
|
||||
send_t true_send;
|
||||
recv_t true_recv;
|
||||
recvfrom_t true_recvfrom;
|
||||
sendmsg_t true_sendmsg;
|
||||
recvmsg_t true_recvmsg;
|
||||
|
||||
int tcp_read_time_out;
|
||||
int tcp_connect_time_out;
|
||||
@ -810,10 +812,13 @@ HOOKFUNC(int, getaddrinfo, const char *node, const char *service, const struct a
|
||||
INIT();
|
||||
PDEBUG("getaddrinfo: %s %s\n", node ? node : "null", service ? service : "null");
|
||||
|
||||
if(proxychains_resolver != DNSLF_LIBC)
|
||||
if(proxychains_resolver != DNSLF_LIBC){
|
||||
PDEBUG("using proxy_getaddrinfo()\n");
|
||||
return proxy_getaddrinfo(node, service, hints, res);
|
||||
else
|
||||
}
|
||||
else{
|
||||
return true_getaddrinfo(node, service, hints, res);
|
||||
}
|
||||
}
|
||||
|
||||
HOOKFUNC(void, freeaddrinfo, struct addrinfo *res) {
|
||||
@ -1026,6 +1031,185 @@ HOOKFUNC(ssize_t, sendto, int sockfd, const void *buf, size_t len, int flags,
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
// HOOKFUNC(ssize_t, sendmsg, int sockfd, const struct msghdr *msg, int flags){
|
||||
// //TODO hugoc
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
HOOKFUNC(ssize_t, recvmsg, int sockfd, struct msghdr *msg, int flags){
|
||||
|
||||
|
||||
INIT();
|
||||
PFUNC();
|
||||
|
||||
int socktype = 0;
|
||||
socklen_t optlen = 0;
|
||||
optlen = sizeof(socktype);
|
||||
getsockopt(sockfd, SOL_SOCKET, SO_TYPE, &socktype, &optlen);
|
||||
if( socktype != SOCK_DGRAM){
|
||||
PDEBUG("sockfd %d is not a SOCK_DGRAM socket, returning to true_recvmsg\n", sockfd);
|
||||
return true_recvmsg(sockfd, msg, flags);
|
||||
}
|
||||
PDEBUG("sockfd %d is a SOCK_DGRAM socket\n", sockfd);
|
||||
|
||||
struct sockaddr addr;
|
||||
socklen_t addr_len = sizeof(addr);
|
||||
if(SUCCESS != getsockname(sockfd, &addr, &addr_len )){
|
||||
PDEBUG("error getsockname, errno=%d. Returning to true_recvmsg()\n", errno);
|
||||
return true_recvmsg(sockfd,msg, flags);
|
||||
}
|
||||
sa_family_t fam = SOCKFAMILY(addr);
|
||||
if(!(fam == AF_INET || fam == AF_INET6)){
|
||||
PDEBUG("sockfd %d address familiy is not a AF_INET or AF_INET6, returning to true_recvmsg\n", sockfd);
|
||||
return true_recvmsg(sockfd,msg, flags);
|
||||
}
|
||||
|
||||
PDEBUG("sockfd %d's address family is AF_INET or AF_INET6\n", sockfd);
|
||||
|
||||
udp_relay_chain* relay_chain = get_relay_chain(relay_chains, sockfd);
|
||||
if(relay_chain == NULL){
|
||||
// No chain is opened for this socket
|
||||
PDEBUG("sockfd %d does not corresponds to any opened relay chain, returning to true_recvmsg\n", sockfd);
|
||||
return true_recvmsg(sockfd,msg, flags);
|
||||
}
|
||||
PDEBUG("sockfd %d is associated with udp_relay_chain %x\n", sockfd, relay_chain);
|
||||
|
||||
|
||||
char buffer[65535]; //buffer to receive and decapsulate a UDP relay packet. UDP maxsize is 65535
|
||||
size_t bytes_received;
|
||||
|
||||
struct sockaddr from;
|
||||
|
||||
|
||||
|
||||
struct iovec iov[1];
|
||||
iov[0].iov_base = buffer;
|
||||
iov[0].iov_len = sizeof(buffer);
|
||||
|
||||
|
||||
struct msghdr tmp_msg;
|
||||
|
||||
tmp_msg.msg_name = &from;
|
||||
tmp_msg.msg_namelen = sizeof(from);
|
||||
tmp_msg.msg_iov = iov;
|
||||
tmp_msg.msg_iovlen = 1;
|
||||
tmp_msg.msg_control = msg->msg_control; // Pass directly
|
||||
tmp_msg.msg_controllen = msg->msg_controllen; // Pass directly
|
||||
tmp_msg.msg_flags = msg->msg_flags;
|
||||
|
||||
PDEBUG("exec true_recvmsg\n");
|
||||
bytes_received = true_recvmsg(sockfd, &tmp_msg, flags);
|
||||
if(-1 == bytes_received){
|
||||
PDEBUG("true_recvmsg returned -1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Transfer the fields we do not manage
|
||||
|
||||
msg->msg_controllen = tmp_msg.msg_controllen;
|
||||
msg->msg_control = tmp_msg.msg_control; //Not sure this one is necessary
|
||||
msg->msg_flags = tmp_msg.msg_flags;
|
||||
|
||||
PDEBUG("successful recvmsg(), %d bytes received\n", bytes_received);
|
||||
//Check that the packet was received from the first relay of the chain
|
||||
|
||||
if(!is_from_chain_head(*relay_chain, *(struct sockaddr *)(msg->msg_name))){
|
||||
PDEBUG("UDP packet not received from the proxy chain's head, transfering it as is\n");
|
||||
// Write the data we received in tmp_msg to msg
|
||||
int written = write_buf_to_iov(buffer, bytes_received, msg->msg_iov, msg->msg_iovlen);
|
||||
|
||||
// Write the addr we received in tmp_msg to msg
|
||||
if(msg->msg_name != NULL){
|
||||
socklen_t min = (msg->msg_namelen>tmp_msg.msg_namelen)?tmp_msg.msg_namelen:msg->msg_namelen;
|
||||
memcpy(msg->msg_name, tmp_msg.msg_name, min);
|
||||
msg->msg_namelen = min;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
PDEBUG("packet received from the proxy chain's head\n");
|
||||
|
||||
|
||||
int rc;
|
||||
ip_type src_ip;
|
||||
unsigned short src_port;
|
||||
char udp_data[65535];
|
||||
size_t udp_data_len = sizeof(udp_data);
|
||||
|
||||
rc = unsocks_udp_packet(buffer, bytes_received, *relay_chain, &src_ip, &src_port, udp_data, &udp_data_len);
|
||||
if(rc != SUCCESS){
|
||||
PDEBUG("error unSOCKSing the UDP packet\n");
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("UDP packet successfully unSOCKified\n");
|
||||
|
||||
|
||||
/*debug*/
|
||||
DEBUGDECL(char str[256]);
|
||||
PDEBUG("received %d bytes through receive_udp_packet()\n", udp_data_len);
|
||||
PDEBUG("data: ");
|
||||
DUMP_BUFFER(udp_data, udp_data_len);
|
||||
PDEBUG("src_ip: ");
|
||||
DUMP_BUFFER(src_ip.addr.v6, src_ip.is_v6?16:4);
|
||||
PDEBUG("src_ip: %s\n", inet_ntop(src_ip.is_v6 ? AF_INET6 : AF_INET, src_ip.is_v6 ? (void*)src_ip.addr.v6 : (void*)src_ip.addr.v4.octet, str, sizeof(str)));
|
||||
PDEBUG("from_port: %hu\n", ntohs(src_port));
|
||||
/*end debug*/
|
||||
|
||||
|
||||
// Write the udp data we received in tmp_msg and unsocksified to msg
|
||||
int written = write_buf_to_iov(udp_data, udp_data_len, msg->msg_iov, msg->msg_iovlen);
|
||||
|
||||
// Overwrite the addresse in msg with the src_addr retrieved from unsocks_udp_packet();
|
||||
|
||||
if(msg->msg_name != NULL){
|
||||
struct sockaddr_in* src_addr_v4;
|
||||
struct sockaddr_in6* src_addr_v6;
|
||||
|
||||
//TODO bien gérer le controle de la taille de la src_addr fournie et le retour dans addrlen
|
||||
// TODO faire une fonction cast_iptype_to_sockaddr()
|
||||
|
||||
if(src_ip.is_v6 && is_v4inv6((struct in6_addr*)src_ip.addr.v6)){
|
||||
PDEBUG("src_ip is v4 in v6 ip\n");
|
||||
if(msg->msg_namelen < sizeof(struct sockaddr_in)){
|
||||
PDEBUG("msg_namelen too short for ipv4\n");
|
||||
}
|
||||
src_addr_v4 = (struct sockaddr_in*)(msg->msg_name);
|
||||
src_addr_v4->sin_family = AF_INET;
|
||||
src_addr_v4->sin_port = src_port;
|
||||
memcpy(&(src_addr_v4->sin_addr.s_addr), src_ip.addr.v6+12, 4);
|
||||
msg->msg_namelen = sizeof(src_addr_v4);
|
||||
}
|
||||
else if(src_ip.is_v6){
|
||||
PDEBUG("src_ip is true v6\n");
|
||||
if(msg->msg_namelen < sizeof(struct sockaddr_in6)){
|
||||
PDEBUG("addrlen too short for ipv6\n");
|
||||
return -1;
|
||||
}
|
||||
src_addr_v6 = (struct sockaddr_in6*)(msg->msg_name);
|
||||
src_addr_v6->sin6_family = AF_INET6;
|
||||
src_addr_v6->sin6_port = src_port;
|
||||
memcpy(src_addr_v6->sin6_addr.s6_addr, src_ip.addr.v6, 16);
|
||||
msg->msg_namelen = sizeof(src_addr_v6);
|
||||
}else {
|
||||
if(msg->msg_namelen < sizeof(struct sockaddr_in)){
|
||||
PDEBUG("addrlen too short for ipv4\n");
|
||||
}
|
||||
src_addr_v4 = (struct sockaddr_in*)(msg->msg_name);
|
||||
src_addr_v4->sin_family = AF_INET;
|
||||
src_addr_v4->sin_port = src_port;
|
||||
src_addr_v4->sin_addr.s_addr = (in_addr_t) src_ip.addr.v4.as_int;
|
||||
msg->msg_namelen = sizeof(src_addr_v4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return udp_data_len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
HOOKFUNC(ssize_t, recv, int sockfd, void *buf, size_t len, int flags){
|
||||
INIT();
|
||||
PFUNC();
|
||||
@ -1095,7 +1279,7 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags,
|
||||
|
||||
// WARNING : Est ce que si le client avait envoyé des packets UDP avec resolution DNS dans le socks,
|
||||
// on doit lui filer comme address source pour les packets recu l'addresse de mapping DNS ? Si oui comment
|
||||
// la retrouver ?
|
||||
// la retrouver ? -> done in receive_udp_packet()
|
||||
|
||||
int min = (bytes_received > len)?len:bytes_received;
|
||||
memcpy(buf, tmp_buffer, min);
|
||||
@ -1197,6 +1381,8 @@ static void setup_hooks(void) {
|
||||
SETUP_SYM(send);
|
||||
SETUP_SYM(sendto);
|
||||
SETUP_SYM(recvfrom);
|
||||
SETUP_SYM(recvmsg);
|
||||
//SETUP_SYM(sendmsg);
|
||||
SETUP_SYM(recv);
|
||||
SETUP_SYM(gethostbyname);
|
||||
SETUP_SYM(getaddrinfo);
|
||||
|
Loading…
Reference in New Issue
Block a user