mirror of
https://github.com/rofl0r/proxychains-ng
synced 2025-02-02 18:12:54 +08:00
implements udp reception and fixes
This commit is contained in:
parent
48422d4c07
commit
4c75e059d9
227
src/core.c
227
src/core.c
@ -426,7 +426,7 @@ 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.
|
/* 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) */
|
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){
|
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){
|
||||||
//TODO hugoc
|
//TODO hugoc
|
||||||
|
|
||||||
PFUNC();
|
PFUNC();
|
||||||
@ -524,27 +524,27 @@ either of them. */
|
|||||||
if(buff[0] != 5 || buff[1] != 0)
|
if(buff[0] != 5 || buff[1] != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
bnd_addr->atyp = buff[3];
|
|
||||||
|
|
||||||
switch (buff[3]) {
|
switch (buff[3]) {
|
||||||
case 1:
|
case ATYP_V4:
|
||||||
len = 4;
|
bnd_addr->is_v6 = 0;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case ATYP_V6:
|
||||||
len = 16;
|
bnd_addr->is_v6 = 1;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case ATYP_DOM:
|
||||||
PDEBUG("BND_ADDR in UDP_ASSOCIATE response should not be a domain name!\n");
|
PDEBUG("BND_ADDR in UDP_ASSOCIATE response should not be a domain name!\n");
|
||||||
goto err;
|
goto err;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
len = bnd_addr->is_v6?16:4;
|
||||||
|
|
||||||
if(len != read_n_bytes(sock, (char *) buff, len))
|
if(len != read_n_bytes(sock, (char *) buff, len))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
memcpy(bnd_addr->addr.v6, buff,(len==16)?16:4);
|
memcpy(bnd_addr->addr.v6, buff,len);
|
||||||
|
|
||||||
if(2 != read_n_bytes(sock, (char *) buff, 2))
|
if(2 != read_n_bytes(sock, (char *) buff, 2))
|
||||||
goto err;
|
goto err;
|
||||||
@ -603,6 +603,8 @@ static int write_udp_header(socks5_addr dst_addr, unsigned short dst_port , char
|
|||||||
|
|
||||||
int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned short* src_port, char* frag) {
|
int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned short* src_port, char* frag) {
|
||||||
|
|
||||||
|
PFUNC();
|
||||||
|
PDEBUG("buflen : %d\n", buflen);
|
||||||
if (buflen < 5){
|
if (buflen < 5){
|
||||||
PDEBUG("buffer too short to contain a UDP header\n");
|
PDEBUG("buffer too short to contain a UDP header\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -612,12 +614,14 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
|||||||
buf_iter += 2; // first 2 bytes are reserved;
|
buf_iter += 2; // first 2 bytes are reserved;
|
||||||
*frag = buf[buf_iter++];
|
*frag = buf[buf_iter++];
|
||||||
src_addr->atyp = buf[buf_iter++];
|
src_addr->atyp = buf[buf_iter++];
|
||||||
|
int v6;
|
||||||
|
|
||||||
switch (src_addr->atyp)
|
switch (src_addr->atyp)
|
||||||
{
|
{
|
||||||
case ATYP_DOM:
|
case ATYP_DOM:
|
||||||
|
PDEBUG("UDP header with ATYP_DOM addr type\n");
|
||||||
src_addr->addr.dom.len = buf[buf_iter++];
|
src_addr->addr.dom.len = buf[buf_iter++];
|
||||||
if(buflen < 5 + 2 + src_addr->addr.dom.len ) {
|
if(buflen < (5 + 2 + src_addr->addr.dom.len) ) {
|
||||||
PDEBUG("buffer too short to read the UDP header\n");
|
PDEBUG("buffer too short to read the UDP header\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -627,8 +631,10 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
|||||||
|
|
||||||
case ATYP_V4:
|
case ATYP_V4:
|
||||||
case ATYP_V6:
|
case ATYP_V6:
|
||||||
int v6 = src_addr->atyp == ATYP_V6;
|
PDEBUG("UDP header with ATYP_V4/6 addr type\n");
|
||||||
if(buflen < 4 + 2 + v6?16:4 ){
|
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");
|
PDEBUG("buffer too short to read the UDP header\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -645,6 +651,151 @@ int read_udp_header(char * buf, size_t buflen, socks5_addr* src_addr, unsigned s
|
|||||||
return buf_iter;
|
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 ){
|
||||||
|
//receives data on sockfd, decapsulates the header for each relay in chain and check they match, returns UDP data and source address/port
|
||||||
|
|
||||||
|
PFUNC();
|
||||||
|
|
||||||
|
char buffer[65535]; //buffer to receive and decapsulate a UDP relay packet. UDP maxsize is 65535
|
||||||
|
int bytes_received;
|
||||||
|
struct sockaddr from;
|
||||||
|
socklen_t addrlen = sizeof(from);
|
||||||
|
PDEBUG("test\n");
|
||||||
|
|
||||||
|
bytes_received = true_recvfrom(sockfd, buffer,sizeof(buffer), 0, &from, &addrlen);
|
||||||
|
if(-1 == bytes_received){
|
||||||
|
PDEBUG("true_receive returned -1\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)){
|
||||||
|
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;
|
||||||
|
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");
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int min = ((bytes_received-read)>data_len)?data_len:(bytes_received-read);
|
||||||
|
memcpy(data,buffer+read, min);
|
||||||
|
|
||||||
|
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
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 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 ){
|
if (chain.head == NULL ){
|
||||||
@ -663,10 +814,11 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
|||||||
if(!target_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && target_ip.addr.v4.octet[0] == remote_dns_subnet) {
|
if(!target_ip.is_v6 && proxychains_resolver >= DNSLF_RDNS_START && target_ip.addr.v4.octet[0] == remote_dns_subnet) {
|
||||||
target_addr.atyp = ATYP_DOM;
|
target_addr.atyp = ATYP_DOM;
|
||||||
dns_len = rdns_get_host_for_ip(target_ip.addr.v4, target_addr.addr.dom.name);
|
dns_len = rdns_get_host_for_ip(target_ip.addr.v4, target_addr.addr.dom.name);
|
||||||
|
PDEBUG("dnslen: %d\n", dns_len);
|
||||||
if(!dns_len) goto err;
|
if(!dns_len) goto err;
|
||||||
else dns_name = target_addr.addr.dom.name;
|
else dns_name = target_addr.addr.dom.name;
|
||||||
target_addr.addr.dom.len = dns_len && 0xFF;
|
target_addr.addr.dom.len = dns_len & 0xFF;
|
||||||
|
PDEBUG("dnslen in struct: %d\n", target_addr.addr.dom.len);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if(target_ip.is_v6){
|
if(target_ip.is_v6){
|
||||||
@ -689,20 +841,22 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
while(tmp->next != NULL){
|
while(tmp->next != NULL){
|
||||||
|
|
||||||
switch ((tmp->next)->bnd_addr.atyp)
|
// switch ((tmp->next)->bnd_addr.atyp)
|
||||||
{
|
// {
|
||||||
case ATYP_V4:
|
// case ATYP_V4:
|
||||||
len = 4;
|
// len = 4;
|
||||||
break;
|
// break;
|
||||||
case ATYP_V6:
|
// case ATYP_V6:
|
||||||
len = 6;
|
// len = 6;
|
||||||
break;
|
// break;
|
||||||
case ATYP_DOM:
|
// case ATYP_DOM:
|
||||||
len = (tmp->next)->bnd_addr.addr.dom.len + 1;
|
// len = (tmp->next)->bnd_addr.addr.dom.len + 1;
|
||||||
break;
|
// break;
|
||||||
default:
|
// default:
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
len = (tmp->next)->bnd_addr.is_v6?16:4;
|
||||||
|
|
||||||
headers_size += len + 6;
|
headers_size += len + 6;
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@ -740,7 +894,12 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
|||||||
tmp = chain.head;
|
tmp = chain.head;
|
||||||
while (tmp->next != NULL)
|
while (tmp->next != NULL)
|
||||||
{
|
{
|
||||||
written = write_udp_header((tmp->next)->bnd_addr, (tmp->next)->bnd_port, 0, buff+offset, headers_size + data_len - offset);
|
|
||||||
|
socks5_addr tmpaddr;
|
||||||
|
tmpaddr.atyp = (tmp->next)->bnd_addr.is_v6?ATYP_V6:ATYP_V4;
|
||||||
|
memcpy(tmpaddr.addr.v6, (tmp->next)->bnd_addr.addr.v6, (tmp->next)->bnd_addr.is_v6?16:4);
|
||||||
|
|
||||||
|
written = write_udp_header(tmpaddr, (tmp->next)->bnd_port, 0, buff+offset, headers_size + data_len - offset);
|
||||||
if (written == -1){
|
if (written == -1){
|
||||||
PDEBUG("error write_udp_header\n");
|
PDEBUG("error write_udp_header\n");
|
||||||
goto err;
|
goto err;
|
||||||
@ -763,11 +922,11 @@ int send_udp_packet(int sockfd, udp_relay_chain chain, ip_type target_ip, unsign
|
|||||||
// Send the packet
|
// Send the packet
|
||||||
// FIXME: should write_n_bytes be used here instead ?
|
// FIXME: should write_n_bytes be used here instead ?
|
||||||
|
|
||||||
if(chain.head->bnd_addr.atyp == ATYP_DOM){
|
// if(chain.head->bnd_addr.atyp == ATYP_DOM){
|
||||||
PDEBUG("BND_ADDR of type DOMAINE (0x03) not supported yet\n");
|
// PDEBUG("BND_ADDR of type DOMAINE (0x03) not supported yet\n");
|
||||||
goto err;
|
// goto err;
|
||||||
}
|
// }
|
||||||
int v6 = chain.head->bnd_addr.atyp == ATYP_V6;
|
int v6 = chain.head->bnd_addr.is_v6 == ATYP_V6;
|
||||||
|
|
||||||
struct sockaddr_in addr = {
|
struct sockaddr_in addr = {
|
||||||
.sin_family = AF_INET,
|
.sin_family = AF_INET,
|
||||||
|
13
src/core.h
13
src/core.h
@ -109,7 +109,7 @@ typedef struct{
|
|||||||
unsigned char v6[16];
|
unsigned char v6[16];
|
||||||
struct {
|
struct {
|
||||||
char len;
|
char len;
|
||||||
char name[256];
|
char name[255];
|
||||||
} dom;
|
} dom;
|
||||||
} addr ;
|
} addr ;
|
||||||
} socks5_addr;
|
} socks5_addr;
|
||||||
@ -119,9 +119,9 @@ with a UDP_ASSOCIATE command issued on the tcp_sockfd */
|
|||||||
typedef struct s_udp_relay_node {
|
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.
|
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
|
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.
|
ip_type 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.
|
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.
|
ip_type dst_addr; // ?? the DST_ADDR sent in the UDP_ASSOCIATE command.
|
||||||
unsigned short dst_port; // ?? the DST_PORT sent in the UDP_ASSOCIATE command.
|
unsigned short dst_port; // ?? the DST_PORT sent in the UDP_ASSOCIATE command.
|
||||||
struct s_udp_relay_node * prev;
|
struct s_udp_relay_node * prev;
|
||||||
struct s_udp_relay_node * next;
|
struct s_udp_relay_node * next;
|
||||||
@ -178,6 +178,9 @@ extern freeaddrinfo_t true_freeaddrinfo;
|
|||||||
extern getnameinfo_t true_getnameinfo;
|
extern getnameinfo_t true_getnameinfo;
|
||||||
extern gethostbyaddr_t true_gethostbyaddr;
|
extern gethostbyaddr_t true_gethostbyaddr;
|
||||||
extern sendto_t true_sendto;
|
extern sendto_t true_sendto;
|
||||||
|
extern recvfrom_t true_recvfrom;
|
||||||
|
extern recv_t true_recv;
|
||||||
|
extern send_t true_send;
|
||||||
|
|
||||||
struct gethostbyname_data {
|
struct gethostbyname_data {
|
||||||
struct hostent hostent_space;
|
struct hostent hostent_space;
|
||||||
@ -196,13 +199,13 @@ void proxy_freeaddrinfo(struct addrinfo *res);
|
|||||||
void core_initialize(void);
|
void core_initialize(void);
|
||||||
void core_unload(void);
|
void core_unload(void);
|
||||||
|
|
||||||
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);
|
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);
|
||||||
udp_relay_chain* get_relay_chain(udp_relay_chain_list chains_list, int sockfd);
|
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 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);
|
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);
|
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 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 );
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1015,7 +1015,7 @@ HOOKFUNC(ssize_t, recv, int sockfd, void *buf, size_t len, int flags){
|
|||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
//TODO hugoc
|
//TODO hugoc
|
||||||
return true_recv(sockfd, buf, len, flags);
|
return recvfrom(sockfd, buf, len, flags, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags,
|
HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags,
|
||||||
@ -1023,7 +1023,102 @@ HOOKFUNC(ssize_t, recvfrom, int sockfd, void *buf, size_t len, int flags,
|
|||||||
INIT();
|
INIT();
|
||||||
PFUNC();
|
PFUNC();
|
||||||
//TODO hugoc
|
//TODO hugoc
|
||||||
return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
DEBUGDECL(char str[256]);
|
||||||
|
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_recvfrom\n", sockfd);
|
||||||
|
return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
||||||
|
}
|
||||||
|
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_recvfrom()\n", errno);
|
||||||
|
return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
||||||
|
}
|
||||||
|
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_recvfrom\n", sockfd);
|
||||||
|
return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_recvfrom\n", sockfd);
|
||||||
|
return true_recvfrom(sockfd, buf, len, flags, src_addr, addrlen);
|
||||||
|
}
|
||||||
|
PDEBUG("sockfd %d is associated with udp_relay_chain %x\n", sockfd, relay_chain);
|
||||||
|
|
||||||
|
// On lance un receive_udp_packet()
|
||||||
|
|
||||||
|
char tmp_buffer[65535]; //maximum theoretical size of a UDP packet.
|
||||||
|
int bytes_received;
|
||||||
|
ip_type from_addr;
|
||||||
|
unsigned short from_port;
|
||||||
|
bytes_received = receive_udp_packet(sockfd, *relay_chain, &from_addr, &from_port, tmp_buffer, 65535);
|
||||||
|
|
||||||
|
if(-1 == bytes_received){
|
||||||
|
PDEBUG("true_recvfrom returned -1\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PDEBUG("received %d bytes through receive_udp_packet()\n", bytes_received);
|
||||||
|
PDEBUG("data: ");
|
||||||
|
DUMP_BUFFER(tmp_buffer, bytes_received);
|
||||||
|
PDEBUG("from_addr: ");
|
||||||
|
DUMP_BUFFER(from_addr.addr.v6, from_addr.is_v6?16:4);
|
||||||
|
PDEBUG("from_addr: %s\n", inet_ntop(from_addr.is_v6 ? AF_INET6 : AF_INET, from_addr.is_v6 ? (void*)from_addr.addr.v6 : (void*)from_addr.addr.v4.octet, str, sizeof(str)));
|
||||||
|
PDEBUG("from_port: %hu\n", ntohs(from_port));
|
||||||
|
|
||||||
|
// 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 ?
|
||||||
|
|
||||||
|
int min = (bytes_received > len)?len:bytes_received;
|
||||||
|
memcpy(buf, tmp_buffer, min);
|
||||||
|
|
||||||
|
if (src_addr == NULL){ // No need to fill src_addr in this case
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
//
|
||||||
|
|
||||||
|
if(from_addr.is_v6){
|
||||||
|
if(addrlen < sizeof(struct sockaddr_in6)){
|
||||||
|
PDEBUG("addrlen too short for ipv6\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
src_addr_v6 = (struct sockaddr_in6*)src_addr;
|
||||||
|
src_addr_v6->sin6_family = AF_INET6;
|
||||||
|
src_addr_v6->sin6_port = from_port;
|
||||||
|
memcpy(src_addr_v6->sin6_addr.s6_addr, from_addr.addr.v6, 16);
|
||||||
|
*addrlen = sizeof(src_addr_v6);
|
||||||
|
}else {
|
||||||
|
if(addrlen < sizeof(struct sockaddr_in)){
|
||||||
|
PDEBUG("addrlen too short for ipv4\n");
|
||||||
|
}
|
||||||
|
src_addr_v4 = (struct sockaddr_in*)src_addr;
|
||||||
|
src_addr_v4->sin_family = AF_INET;
|
||||||
|
src_addr_v4->sin_port = from_port;
|
||||||
|
src_addr_v4->sin_addr.s_addr = (in_addr_t) from_addr.addr.v4.as_int;
|
||||||
|
*addrlen = sizeof(src_addr_v4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return min;
|
||||||
}
|
}
|
||||||
|
|
||||||
HOOKFUNC(ssize_t, send, int sockfd, const void *buf, size_t len, int flags){
|
HOOKFUNC(ssize_t, send, int sockfd, const void *buf, size_t len, int flags){
|
||||||
|
Loading…
Reference in New Issue
Block a user