@@ -46,9 +46,11 @@ static const char test_str_all_tx_bufs[] =
46
46
;
47
47
48
48
#define MY_IPV4_ADDR "127.0.0.1"
49
+ #define MY_IPV4_MAPPED_ADDR "::ffff:127.0.0.1"
49
50
#define MY_IPV6_ADDR "::1"
50
51
#define MY_MCAST_IPV4_ADDR "224.0.0.1"
51
52
#define MY_MCAST_IPV6_ADDR "ff01::1"
53
+ #define ANY_IPV6_ADDR "::"
52
54
53
55
#define ANY_PORT 0
54
56
#define SERVER_PORT 4242
@@ -3586,6 +3588,133 @@ ZTEST_USER(net_socket_udp, test_45_udp_shutdown_recv)
3586
3588
zassert_equal (rv , 0 , "close failed" );
3587
3589
}
3588
3590
3591
+ enum ipv4_mapped_to_ipv6_send_mode {
3592
+ IPV4_MAPPED_TO_IPV6_SENDTO ,
3593
+ IPV4_MAPPED_TO_IPV6_SENDMSG ,
3594
+ };
3595
+
3596
+ void test_ipv4_mapped_to_ipv6_send_common (enum ipv4_mapped_to_ipv6_send_mode test_mode )
3597
+ {
3598
+ int off = 0 ;
3599
+ int ret ;
3600
+ int sock_s , sock_c ;
3601
+ socklen_t addrlen ;
3602
+ struct sockaddr_in addr_c4 = { 0 };
3603
+ struct sockaddr_in addr_s4 = { 0 };
3604
+ struct sockaddr_in6 addr_s6 = { 0 };
3605
+ struct sockaddr_in6 addr_recv = { 0 };
3606
+ struct in6_addr mapped_address = { 0 };
3607
+
3608
+ /* Create IPv4 client socket */
3609
+ prepare_sock_udp_v4 (MY_IPV4_ADDR , CLIENT_PORT , & sock_c , & addr_c4 );
3610
+ /* Create IPv6 server socket */
3611
+ prepare_sock_udp_v6 (ANY_IPV6_ADDR , SERVER_PORT , & sock_s , & addr_s6 );
3612
+
3613
+ /* Prepare server's IPv4 address and expected mapped address */
3614
+ addr_s4 .sin_family = AF_INET ;
3615
+ addr_s4 .sin_port = htons (SERVER_PORT );
3616
+ ret = zsock_inet_pton (AF_INET , MY_IPV4_ADDR , & addr_s4 .sin_addr );
3617
+ zassert_equal (ret , 1 , "inet_pton failed" );
3618
+
3619
+ ret = zsock_inet_pton (AF_INET6 , MY_IPV4_MAPPED_ADDR , & mapped_address );
3620
+ zassert_equal (ret , 1 , "inet_pton failed" );
3621
+
3622
+ /* Bind the client socket to ensure we check the correct address */
3623
+ ret = zsock_bind (sock_c , (struct sockaddr * )& addr_c4 , sizeof (addr_c4 ));
3624
+ zassert_ok (ret , "bind failed, %d" , errno );
3625
+
3626
+ /* Turn off IPV6_V6ONLY on the server socket, so the socket becomes
3627
+ * dual-stack.
3628
+ */
3629
+ ret = zsock_setsockopt (sock_s , IPPROTO_IPV6 , IPV6_V6ONLY , & off , sizeof (off ));
3630
+ zassert_ok (ret , "setsockopt failed, %d" , errno );
3631
+
3632
+ /* And bind it to ANY address */
3633
+ ret = zsock_bind (sock_s , (struct sockaddr * )& addr_s6 , sizeof (addr_s6 ));
3634
+ zassert_ok (ret , "bind failed, %d" , errno );
3635
+
3636
+ /* Send datagram from IPv4 client socket to dual-stack server */
3637
+ ret = zsock_sendto (sock_c , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 , 0 ,
3638
+ (struct sockaddr * )& addr_s4 , sizeof (addr_s4 ));
3639
+ zexpect_equal (ret , sizeof (TEST_STR_SMALL ) - 1 ,
3640
+ "invalid send len (was %d expected %d) (%d)" ,
3641
+ ret , sizeof (TEST_STR_SMALL ) - 1 , errno );
3642
+
3643
+ /* Give the packet a chance to go through the net stack */
3644
+ k_msleep (10 );
3645
+
3646
+ /* Server should get the datagram, with IPv4-to-IPv6 mapped address */
3647
+ addrlen = sizeof (addr_recv );
3648
+ clear_buf (rx_buf );
3649
+ ret = zsock_recvfrom (sock_s , rx_buf , sizeof (rx_buf ), ZSOCK_MSG_DONTWAIT ,
3650
+ (struct sockaddr * )& addr_recv , & addrlen );
3651
+ zassert_true (ret >= 0 , "recvfrom fail (%d)" , errno );
3652
+ zassert_equal (ret , sizeof (TEST_STR_SMALL ) - 1 , "unexpected received bytes" );
3653
+ zassert_mem_equal (rx_buf , BUF_AND_SIZE (TEST_STR_SMALL ), "wrong data" );
3654
+ zassert_equal (addrlen , sizeof (struct sockaddr_in6 ), "unexpected addrlen" );
3655
+ zassert_equal (addr_recv .sin6_family , AF_INET6 ,
3656
+ "IPv4-to-IPv6 mapped address should be AF_INET6" );
3657
+ zassert_equal (addr_recv .sin6_port , htons (CLIENT_PORT ), "invalid port" );
3658
+ zassert_mem_equal (& addr_recv .sin6_addr , & mapped_address ,
3659
+ sizeof (mapped_address ), "invalid mapped address" );
3660
+
3661
+ /* Echo data back */
3662
+ if (test_mode == IPV4_MAPPED_TO_IPV6_SENDTO ) {
3663
+ ret = zsock_sendto (sock_s , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 , 0 ,
3664
+ (struct sockaddr * )& addr_recv , addrlen );
3665
+ zexpect_equal (ret , sizeof (TEST_STR_SMALL ) - 1 ,
3666
+ "invalid send len (was %d expected %d) (%d)" ,
3667
+ ret , sizeof (TEST_STR_SMALL ) - 1 , errno );
3668
+ } else if (test_mode == IPV4_MAPPED_TO_IPV6_SENDMSG ) {
3669
+ struct msghdr msg = { 0 };
3670
+ struct iovec io_vector [1 ] = { 0 };
3671
+
3672
+ io_vector [0 ].iov_base = TEST_STR_SMALL ;
3673
+ io_vector [0 ].iov_len = strlen (TEST_STR_SMALL );
3674
+
3675
+ msg .msg_iov = io_vector ;
3676
+ msg .msg_iovlen = 1 ;
3677
+ msg .msg_name = & addr_recv ;
3678
+ msg .msg_namelen = addrlen ;
3679
+
3680
+ ret = zsock_sendmsg (sock_s , & msg , 0 );
3681
+ zexpect_equal (ret , sizeof (TEST_STR_SMALL ) - 1 ,
3682
+ "invalid send len (was %d expected %d) (%d)" ,
3683
+ ret , sizeof (TEST_STR_SMALL ) - 1 , errno );
3684
+ } else {
3685
+ zassert_unreachable ("invalid test mode" );
3686
+ }
3687
+
3688
+ /* Give the packet a chance to go through the net stack */
3689
+ k_msleep (10 );
3690
+
3691
+ /* Client should get the echoed datagram */
3692
+ clear_buf (rx_buf );
3693
+ ret = zsock_recv (sock_c , rx_buf , sizeof (rx_buf ), ZSOCK_MSG_DONTWAIT );
3694
+ zassert_true (ret >= 0 , "recvfrom fail (%d)" , errno );
3695
+ zassert_equal (ret , sizeof (TEST_STR_SMALL ) - 1 , "unexpected received bytes" );
3696
+ zassert_mem_equal (rx_buf , BUF_AND_SIZE (TEST_STR_SMALL ), "wrong data" );
3697
+
3698
+ ret = zsock_close (sock_c );
3699
+ zassert_ok (ret , "close failed, %d" , errno );
3700
+ ret = zsock_close (sock_s );
3701
+ zassert_ok (ret , "close failed, %d" , errno );
3702
+ }
3703
+
3704
+ ZTEST (net_socket_udp , test_46_ipv4_mapped_to_ipv6_sendto )
3705
+ {
3706
+ Z_TEST_SKIP_IFNDEF (CONFIG_NET_IPV4_MAPPING_TO_IPV6 );
3707
+
3708
+ test_ipv4_mapped_to_ipv6_send_common (IPV4_MAPPED_TO_IPV6_SENDTO );
3709
+ }
3710
+
3711
+ ZTEST (net_socket_udp , test_47_ipv4_mapped_to_ipv6_sendmsg )
3712
+ {
3713
+ Z_TEST_SKIP_IFNDEF (CONFIG_NET_IPV4_MAPPING_TO_IPV6 );
3714
+
3715
+ test_ipv4_mapped_to_ipv6_send_common (IPV4_MAPPED_TO_IPV6_SENDMSG );
3716
+ }
3717
+
3589
3718
static void after (void * arg )
3590
3719
{
3591
3720
ARG_UNUSED (arg );
0 commit comments