@@ -949,6 +949,7 @@ static struct in6_addr my_addr3 = { { { 0x20, 0x01, 0x0d, 0xb8, 1, 0, 0, 0,
949949 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x3 } } };
950950static struct in6_addr my_mcast_addr1 = { { { 0xff , 0x01 , 0 , 0 , 0 , 0 , 0 , 0 ,
951951 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x1 } } };
952+ static struct in_addr my_mcast_addr2 = { { { 224 , 0 , 0 , 2 } } };
952953static uint8_t server_lladdr [] = { 0x01 , 0x02 , 0x03 , 0xff , 0xfe ,
953954 0x04 , 0x05 , 0x06 };
954955static struct net_linkaddr server_link_addr = {
@@ -2671,6 +2672,259 @@ ZTEST(net_socket_udp, test_38_ipv6_multicast_ifindex)
26712672 loopback_enable_address_swap (true);
26722673}
26732674
2675+ ZTEST (net_socket_udp , test_39_ipv4_multicast_ifindex )
2676+ {
2677+ struct sockaddr_in saddr4 = {
2678+ .sin_family = AF_INET ,
2679+ .sin_port = htons (SERVER_PORT ),
2680+ .sin_addr = my_mcast_addr2 ,
2681+ };
2682+ struct sockaddr_in dst_addr = {
2683+ .sin_family = AF_INET ,
2684+ .sin_port = htons (SERVER_PORT ),
2685+ .sin_addr = my_mcast_addr2 ,
2686+ };
2687+ struct net_if_mcast_addr * ifmaddr ;
2688+ struct net_if_addr * ifaddr ;
2689+ struct in_addr addr = { 0 };
2690+ struct ip_mreqn mreqn ;
2691+ struct ip_mreq mreq ;
2692+ struct net_if * iface ;
2693+ int server_sock ;
2694+ size_t addrlen ;
2695+ size_t optlen ;
2696+ int ifindex ;
2697+ int sock ;
2698+ int ret ;
2699+ int err ;
2700+
2701+ net_if_foreach (iface_cb , & eth_iface );
2702+ zassert_not_null (eth_iface , "No ethernet interface found" );
2703+
2704+ ifmaddr = net_if_ipv4_maddr_add (eth_iface , & my_mcast_addr2 );
2705+ if (!ifmaddr ) {
2706+ DBG ("Cannot add IPv4 multicast address %s\n" ,
2707+ net_sprint_ipv4_addr (& my_mcast_addr2 ));
2708+ zassert_not_null (ifmaddr , "mcast_addr2" );
2709+ }
2710+
2711+ ifaddr = net_if_ipv4_addr_add (eth_iface , & my_addr2 ,
2712+ NET_ADDR_MANUAL , 0 );
2713+ if (!ifaddr ) {
2714+ DBG ("Cannot add IPv4 address %s\n" ,
2715+ net_sprint_ipv4_addr (& my_addr2 ));
2716+ zassert_not_null (ifaddr , "addr2" );
2717+ }
2718+
2719+ net_if_up (eth_iface );
2720+
2721+ /* Check that we get the default interface */
2722+ sock = zsock_socket (AF_INET , SOCK_DGRAM , IPPROTO_UDP );
2723+ zassert_true (sock >= 0 , "Cannot create socket (%d)" , - errno );
2724+
2725+ optlen = sizeof (addr );
2726+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2727+ & addr , & optlen );
2728+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , errno );
2729+ zexpect_equal (optlen , sizeof (addr ), "invalid optlen %d vs %d" ,
2730+ optlen , sizeof (addr ));
2731+ ifindex = net_if_get_by_iface (net_if_get_default ());
2732+ ret = net_if_ipv4_addr_lookup_by_index (& addr );
2733+ zexpect_equal (ret , ifindex ,
2734+ "getsockopt multicast ifindex (expected %d got %d)" ,
2735+ ifindex , ret );
2736+
2737+ ret = zsock_close (sock );
2738+ zassert_equal (sock , 0 , "Cannot close socket (%d)" , - errno );
2739+
2740+ /* Check failure for IPv6 socket */
2741+ sock = zsock_socket (AF_INET6 , SOCK_DGRAM , IPPROTO_UDP );
2742+ zassert_true (sock >= 0 , "Cannot create socket (%d)" , - errno );
2743+
2744+ optlen = 0U ;
2745+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2746+ & addr , & optlen );
2747+ err = - errno ;
2748+ zexpect_equal (ret , -1 , "setsockopt failed (%d)" , errno );
2749+ zexpect_equal (err , - EAFNOSUPPORT , "setsockopt failed (%d)" , errno );
2750+ zexpect_equal (optlen , 0U , "setsockopt optlen (%d)" , optlen );
2751+
2752+ ret = zsock_close (sock );
2753+ zassert_equal (sock , 0 , "Cannot close socket (%d)" , - errno );
2754+
2755+ /* Check that we can set the interface */
2756+ sock = zsock_socket (AF_INET , SOCK_DGRAM , IPPROTO_UDP );
2757+ zassert_true (sock >= 0 , "Cannot create socket (%d)" , - errno );
2758+
2759+ /* Clear any existing interface value by setting it to 0 */
2760+ optlen = sizeof (mreqn );
2761+ mreqn .imr_ifindex = 0 ;
2762+ mreqn .imr_address .s_addr = 0 ;
2763+
2764+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2765+ & mreqn , optlen );
2766+ err = - errno ;
2767+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2768+
2769+ /* Verify that we get the empty value */
2770+ optlen = sizeof (addr );
2771+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2772+ & addr , & optlen );
2773+ err = - errno ;
2774+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2775+ zexpect_equal (optlen , sizeof (addr ), "setsockopt optlen (%d)" , optlen );
2776+
2777+ /* Set the output multicast packet interface to the default interface */
2778+ optlen = sizeof (mreqn );
2779+ mreqn .imr_ifindex = net_if_get_by_iface (net_if_get_default ());
2780+ mreqn .imr_address .s_addr = 0 ;
2781+
2782+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2783+ & mreqn , optlen );
2784+ err = - errno ;
2785+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2786+
2787+ /* Verify that we get the default interface */
2788+ optlen = sizeof (addr );
2789+ memset (& addr , 0 , sizeof (addr ));
2790+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2791+ & addr , & optlen );
2792+ err = - errno ;
2793+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2794+ zexpect_equal (optlen , sizeof (addr ), "setsockopt optlen (%d)" , optlen );
2795+
2796+ ifaddr = net_if_ipv4_addr_lookup (& addr , & iface );
2797+ zexpect_not_null (ifaddr , "Address %s not found" ,
2798+ net_sprint_ipv4_addr (& addr ));
2799+ zexpect_equal (net_if_get_by_iface (iface ),
2800+ net_if_get_by_iface (net_if_get_default ()),
2801+ "Invalid interface %d vs %d" ,
2802+ net_if_get_by_iface (iface ),
2803+ net_if_get_by_iface (net_if_get_default ()));
2804+
2805+ /* Now send a packet and verify that it is sent via the default
2806+ * interface instead of the Ethernet interface.
2807+ */
2808+ server_sock = prepare_listen_sock_udp_v4 (& saddr4 );
2809+ zassert_not_equal (server_sock , -1 , "Cannot create server socket (%d)" , - errno );
2810+
2811+ test_started = true;
2812+ loopback_enable_address_swap (false);
2813+
2814+ ret = zsock_sendto (sock , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 , 0 ,
2815+ (struct sockaddr * )& dst_addr , sizeof (dst_addr ));
2816+ zexpect_equal (ret , STRLEN (TEST_STR_SMALL ),
2817+ "invalid send len (was %d expected %d) (%d)" ,
2818+ ret , STRLEN (TEST_STR_SMALL ), - errno );
2819+
2820+ /* Test that the sent data is received from Ethernet interface. */
2821+ addrlen = sizeof (saddr4 );
2822+ ret = zsock_recvfrom (server_sock , rx_buf , sizeof (rx_buf ),
2823+ 0 , (struct sockaddr * )& saddr4 , & addrlen );
2824+ zexpect_true (ret >= 0 , "recvfrom fail" );
2825+ zexpect_equal (ret , strlen (TEST_STR_SMALL ),
2826+ "unexpected received bytes" );
2827+ zexpect_mem_equal (rx_buf , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 ,
2828+ "wrong data" );
2829+
2830+ /* Clear the old interface value by setting it to 0 */
2831+ optlen = sizeof (mreqn );
2832+ mreqn .imr_ifindex = 0 ;
2833+ mreqn .imr_address .s_addr = 0 ;
2834+
2835+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2836+ & mreqn , optlen );
2837+ err = - errno ;
2838+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2839+
2840+ /* Then do it the other way around, set the address but leave the
2841+ * interface number unassigned.
2842+ */
2843+ optlen = sizeof (mreqn );
2844+ mreqn .imr_ifindex = 0 ;
2845+
2846+ /* Get the address of default interface and set it as a target
2847+ * interface.
2848+ */
2849+ ifaddr = net_if_ipv4_addr_get_first_by_index (net_if_get_by_iface (net_if_get_default ()));
2850+ zexpect_not_null (ifaddr , "No address found for interface %d" ,
2851+ net_if_get_by_iface (net_if_get_default ()));
2852+ mreqn .imr_address .s_addr = ifaddr -> address .in_addr .s_addr ;
2853+
2854+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2855+ & mreqn , optlen );
2856+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , errno );
2857+
2858+ /* Verify that we get the default interface address */
2859+ optlen = sizeof (struct in_addr );
2860+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2861+ & addr , & optlen );
2862+ err = - errno ;
2863+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2864+ zexpect_equal (optlen , sizeof (struct in_addr ), "setsockopt optlen (%d)" , optlen );
2865+ ret = net_if_ipv4_addr_lookup_by_index (& addr );
2866+ zexpect_equal (ret , net_if_get_by_iface (net_if_get_default ()),
2867+ "getsockopt multicast ifindex (expected %d got %d)" ,
2868+ net_if_get_by_iface (net_if_get_default ()), ret );
2869+ zexpect_equal (ifaddr -> address .in_addr .s_addr ,
2870+ addr .s_addr ,
2871+ "getsockopt iface address mismatch (expected %s got %s)" ,
2872+ net_sprint_ipv4_addr (& ifaddr -> address .in_addr ),
2873+ net_sprint_ipv4_addr (& addr ));
2874+
2875+ ret = zsock_sendto (sock , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 , 0 ,
2876+ (struct sockaddr * )& dst_addr , sizeof (dst_addr ));
2877+ zexpect_equal (ret , STRLEN (TEST_STR_SMALL ),
2878+ "invalid send len (was %d expected %d) (%d)" ,
2879+ ret , STRLEN (TEST_STR_SMALL ), - errno );
2880+
2881+ /* Test that the sent data is received from default interface. */
2882+ addrlen = sizeof (saddr4 );
2883+ ret = zsock_recvfrom (server_sock , rx_buf , sizeof (rx_buf ),
2884+ 0 , (struct sockaddr * )& saddr4 , & addrlen );
2885+ zexpect_true (ret >= 0 , "recvfrom fail" );
2886+ zexpect_equal (ret , strlen (TEST_STR_SMALL ),
2887+ "unexpected received bytes" );
2888+ zexpect_mem_equal (rx_buf , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 ,
2889+ "wrong data" );
2890+
2891+ /* Then use mreq structure to set the interface */
2892+ optlen = sizeof (mreq );
2893+ ifaddr = net_if_ipv4_addr_get_first_by_index (net_if_get_by_iface (net_if_get_default ()));
2894+ zexpect_not_null (ifaddr , "No address found for interface %d" ,
2895+ net_if_get_by_iface (net_if_get_default ()));
2896+ mreq .imr_interface .s_addr = ifaddr -> address .in_addr .s_addr ;
2897+
2898+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_MULTICAST_IF ,
2899+ & mreq , optlen );
2900+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , errno );
2901+
2902+ ret = zsock_sendto (sock , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 , 0 ,
2903+ (struct sockaddr * )& dst_addr , sizeof (dst_addr ));
2904+ zexpect_equal (ret , STRLEN (TEST_STR_SMALL ),
2905+ "invalid send len (was %d expected %d) (%d)" ,
2906+ ret , STRLEN (TEST_STR_SMALL ), - errno );
2907+
2908+ /* Test that the sent data is received from default interface. */
2909+ addrlen = sizeof (saddr4 );
2910+ ret = zsock_recvfrom (server_sock , rx_buf , sizeof (rx_buf ),
2911+ 0 , (struct sockaddr * )& saddr4 , & addrlen );
2912+ zexpect_true (ret >= 0 , "recvfrom fail" );
2913+ zexpect_equal (ret , strlen (TEST_STR_SMALL ),
2914+ "unexpected received bytes" );
2915+ zexpect_mem_equal (rx_buf , TEST_STR_SMALL , sizeof (TEST_STR_SMALL ) - 1 ,
2916+ "wrong data" );
2917+
2918+ ret = zsock_close (sock );
2919+ zassert_equal (ret , 0 , "Cannot close socket (%d)" , - errno );
2920+
2921+ ret = zsock_close (server_sock );
2922+ zassert_equal (ret , 0 , "Cannot close socket (%d)" , - errno );
2923+
2924+ test_started = false;
2925+ loopback_enable_address_swap (true);
2926+ }
2927+
26742928static void after (void * arg )
26752929{
26762930 ARG_UNUSED (arg );
0 commit comments