@ -743,6 +743,29 @@ resolv_cb(struct sockaddr *addr, void *data)
# endif
void convert_ipv4_mapped_ipv6 ( struct sockaddr_storage * addr ) {
if ( addr - > ss_family = = AF_INET ) {
struct sockaddr_in * ipv4_addr = ( struct sockaddr_in * ) addr ;
struct sockaddr_storage mapped_addr ;
memset ( & mapped_addr , 0 , sizeof ( mapped_addr ) ) ;
struct sockaddr_in6 * mapped_ipv6_addr = ( struct sockaddr_in6 * ) & mapped_addr ;
mapped_ipv6_addr - > sin6_family = AF_INET6 ;
mapped_ipv6_addr - > sin6_port = ipv4_addr - > sin_port ;
uint8_t * ipv6_raw_addr = mapped_ipv6_addr - > sin6_addr . s6_addr ;
ipv6_raw_addr [ 10 ] = 0xff ;
ipv6_raw_addr [ 11 ] = 0xff ;
in_addr_t ipv4_raw_addr = ntohl ( ipv4_addr - > sin_addr . s_addr ) ;
ipv6_raw_addr [ 12 ] = ( ipv4_raw_addr > > 24 ) & 0xff ;
ipv6_raw_addr [ 13 ] = ( ipv4_raw_addr > > 16 ) & 0xff ;
ipv6_raw_addr [ 14 ] = ( ipv4_raw_addr > > 8 ) & 0xff ;
ipv6_raw_addr [ 15 ] = ipv4_raw_addr & 0xff ;
memcpy ( addr , & mapped_addr , sizeof ( mapped_addr ) ) ;
}
}
static void
remote_recv_cb ( EV_P_ ev_io * w , int revents )
{
@ -858,21 +881,19 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
}
}
size_t remote_src_addr_len = get_sockaddr_len ( ( struct sockaddr * ) & remote_ctx - > src_addr ) ;
# ifdef MODULE_REDIR
convert_ipv4_mapped_ipv6 ( & dst_addr ) ;
size_t remote_dst_addr_len = get_sockaddr_len ( ( struct sockaddr * ) & dst_addr ) ;
int src_fd = socket ( remote_ctx - > src_addr . ss_family , SOCK_DGRAM , 0 ) ;
int src_fd = socket ( AF_INET6 , SOCK_DGRAM , 0 ) ;
if ( src_fd < 0 ) {
ERROR ( " [udp] remote_recv_socket " ) ;
goto CLEAN_UP ;
}
int opt = 1 ;
int sol = remote_ctx - > src_addr . ss_family = = AF_INET6 ? SOL_IPV6 : SOL_IP ;
int flag = remote_ctx - > src_addr . ss_family = = AF_INET6 ? IPV6_TRANSPARENT : IP_TRANSPARENT ;
if ( setsockopt ( src_fd , sol , flag , & opt , sizeof ( opt ) ) ) {
int opt = 1 ;
if ( setsockopt ( src_fd , SOL_IPV6 , IPV6_TRANSPARENT , & opt , sizeof ( opt ) ) ) {
ERROR ( " [udp] remote_recv_setsockopt " ) ;
close ( src_fd ) ;
goto CLEAN_UP ;
@ -889,7 +910,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
}
# ifdef IP_TOS
/ / Set QoS flag
int tos = 46 < < 2 ;
int tos = 46 < < 2 ;
int rc = setsockopt ( src_fd , IPPROTO_IP , IP_TOS , & tos , sizeof ( tos ) ) ;
if ( rc < 0 & & errno ! = ENOPROTOOPT ) {
LOGE ( " setting ipv4 dscp failed: %d " , errno ) ;
@ -907,8 +928,14 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
goto CLEAN_UP ;
}
struct sockaddr_storage mapped_src_addr ;
memcpy ( & mapped_src_addr , & remote_ctx - > src_addr , sizeof ( remote_ctx - > src_addr ) ) ;
convert_ipv4_mapped_ipv6 ( & mapped_src_addr ) ;
size_t remote_src_addr_len = get_sockaddr_len ( ( struct sockaddr * ) & mapped_src_addr ) ;
int s = sendto ( src_fd , buf - > data , buf - > len , 0 ,
( struct sockaddr * ) & remote_ctx - > src_addr , remote_src_addr_len ) ;
( struct sockaddr * ) & mapped_ src_addr, remote_src_addr_len ) ;
if ( s = = - 1 & & ! ( errno = = EAGAIN | | errno = = EWOULDBLOCK ) ) {
ERROR ( " [udp] remote_recv_sendto " ) ;
close ( src_fd ) ;
@ -917,6 +944,7 @@ remote_recv_cb(EV_P_ ev_io *w, int revents)
close ( src_fd ) ;
# else
size_t remote_src_addr_len = get_sockaddr_len ( ( struct sockaddr * ) & remote_ctx - > src_addr ) ;
int s = sendto ( server_ctx - > fd , buf - > data , buf - > len , 0 ,
( struct sockaddr * ) & remote_ctx - > src_addr , remote_src_addr_len ) ;