diff --git a/src/core.c b/src/core.c index cac8142..39d3362 100644 --- a/src/core.c +++ b/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; iatyp == 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) { diff --git a/src/core.h b/src/core.h index 57e5d64..1c1bc14 100644 --- a/src/core.h +++ b/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 diff --git a/src/libproxychains.c b/src/libproxychains.c index 2f628e9..1cf39b4 100644 --- a/src/libproxychains.c +++ b/src/libproxychains.c @@ -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);