@@ -2925,6 +2925,173 @@ ZTEST(net_socket_udp, test_39_ipv4_multicast_ifindex)
29252925 loopback_enable_address_swap (true);
29262926}
29272927
2928+ #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE )
2929+
2930+ #define PORT_RANGE (lower , upper ) \
2931+ (uint32_t)(((uint16_t)(upper) << 16) | (uint16_t)(lower))
2932+
2933+ static void check_port_range (struct sockaddr * my_addr ,
2934+ size_t my_addr_len ,
2935+ struct sockaddr * local_addr ,
2936+ size_t local_addr_len )
2937+ {
2938+ sa_family_t family = AF_UNSPEC ;
2939+ uint32_t optval ;
2940+ size_t addr_len ;
2941+ size_t optlen ;
2942+ int sock ;
2943+ int ret , err ;
2944+
2945+ addr_len = local_addr_len ;
2946+
2947+ if (my_addr -> sa_family == AF_INET ) {
2948+ family = AF_INET ;
2949+ } else if (my_addr -> sa_family == AF_INET6 ) {
2950+ family = AF_INET6 ;
2951+ } else {
2952+ zassert_true (false, "Invalid address family %d" ,
2953+ my_addr -> sa_family );
2954+ }
2955+
2956+ sock = zsock_socket (family , SOCK_DGRAM , IPPROTO_UDP );
2957+ zassert_true (sock >= 0 , "Cannot create socket (%d)" , - errno );
2958+
2959+ optval = PORT_RANGE (1024 , 1500 );
2960+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2961+ & optval , sizeof (optval ));
2962+ err = - errno ;
2963+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2964+
2965+ optval = 0 ; optlen = 0U ;
2966+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2967+ & optval , optlen );
2968+ err = - errno ;
2969+ zexpect_equal (ret , -1 , "setsockopt failed (%d)" , err );
2970+
2971+ optval = 0 ; optlen = sizeof (uint64_t );
2972+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2973+ & optval , optlen );
2974+ err = - errno ;
2975+ zexpect_equal (ret , -1 , "setsockopt failed (%d)" , err );
2976+
2977+ optval = PORT_RANGE (0 , 0 );
2978+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2979+ & optval , sizeof (optval ));
2980+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2981+
2982+ /* Linux allows setting the invalid port range but that is not
2983+ * then taken into use when we bind the socket.
2984+ */
2985+ optval = PORT_RANGE (1024 , 0 );
2986+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2987+ & optval , sizeof (optval ));
2988+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2989+
2990+ optval = PORT_RANGE (0 , 1024 );
2991+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2992+ & optval , sizeof (optval ));
2993+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
2994+
2995+ /* Then set a valid range and verify that bound socket is using it */
2996+ optval = PORT_RANGE (10000 , 10010 );
2997+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
2998+ & optval , sizeof (optval ));
2999+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
3000+
3001+ optval = 0 ; optlen = sizeof (optval );
3002+ ret = zsock_getsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
3003+ & optval , & optlen );
3004+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
3005+ zexpect_equal (optval , PORT_RANGE (10000 , 10010 ), "Invalid port range" );
3006+
3007+ ret = zsock_bind (sock , my_addr , my_addr_len );
3008+ err = - errno ;
3009+ zexpect_equal (ret , 0 , "bind failed (%d)" , err );
3010+
3011+ ret = zsock_getsockname (sock , local_addr , & addr_len );
3012+ err = - errno ;
3013+ zexpect_equal (ret , 0 , "getsockname failed (%d)" , err );
3014+
3015+ /* The port should be in the range */
3016+ zexpect_true (ntohs (net_sin (local_addr )-> sin_port ) >= 10000 &&
3017+ ntohs (net_sin (local_addr )-> sin_port ) <= 10010 ,
3018+ "Invalid port %d" , ntohs (net_sin (local_addr )-> sin_port ));
3019+
3020+ (void )zsock_close (sock );
3021+
3022+ /* Try setting invalid range and verify that we do not net a port from that
3023+ * range.
3024+ */
3025+ sock = zsock_socket (family , SOCK_DGRAM , IPPROTO_UDP );
3026+ zassert_true (sock >= 0 , "Cannot create socket (%d)" , - errno );
3027+
3028+ optval = PORT_RANGE (1001 , 1000 );
3029+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
3030+ & optval , sizeof (optval ));
3031+ err = - errno ;
3032+ zexpect_equal (ret , -1 , "setsockopt failed (%d)" , err );
3033+ zexpect_equal (err , - EINVAL , "Invalid errno (%d)" , - err );
3034+
3035+ /* Port range cannot be just one port */
3036+ optval = PORT_RANGE (1001 , 1001 );
3037+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
3038+ & optval , sizeof (optval ));
3039+ err = - errno ;
3040+ zexpect_equal (ret , -1 , "setsockopt failed (%d)" , err );
3041+ zexpect_equal (err , - EINVAL , "Invalid errno (%d)" , - err );
3042+
3043+ optval = PORT_RANGE (0 , 1000 );
3044+ ret = zsock_setsockopt (sock , IPPROTO_IP , IP_LOCAL_PORT_RANGE ,
3045+ & optval , sizeof (optval ));
3046+ err = - errno ;
3047+ zexpect_equal (ret , 0 , "setsockopt failed (%d)" , err );
3048+
3049+ ret = zsock_bind (sock , my_addr , my_addr_len );
3050+ err = - errno ;
3051+ zexpect_equal (ret , 0 , "bind failed (%d)" , err );
3052+
3053+ addr_len = local_addr_len ;
3054+ ret = zsock_getsockname (sock , local_addr , & addr_len );
3055+ err = - errno ;
3056+ zexpect_equal (ret , 0 , "getsockname failed (%d)" , err );
3057+
3058+ /* The port should not be in the range */
3059+ zexpect_false (ntohs (net_sin (local_addr )-> sin_port ) >= 1000 &&
3060+ ntohs (net_sin (local_addr )-> sin_port ) <= 1001 ,
3061+ "Invalid port %d" , ntohs (net_sin (local_addr )-> sin_port ));
3062+
3063+ (void )zsock_close (sock );
3064+ }
3065+ #endif
3066+
3067+ ZTEST (net_socket_udp , test_40_clamp_udp_tcp_port_range )
3068+ {
3069+ #if defined(CONFIG_NET_CONTEXT_CLAMP_PORT_RANGE )
3070+ struct sockaddr_in my_addr4 = {
3071+ .sin_family = AF_INET ,
3072+ .sin_port = 0 ,
3073+ .sin_addr = { { { 192 , 0 , 2 , 2 } } },
3074+ };
3075+ struct sockaddr_in6 my_addr6 = {
3076+ .sin6_family = AF_INET6 ,
3077+ .sin6_port = 0 ,
3078+ .sin6_addr = in6addr_loopback ,
3079+ };
3080+ struct sockaddr_in local_addr4 ;
3081+ struct sockaddr_in6 local_addr6 ;
3082+
3083+ /* First try with a IPv4 socket */
3084+ check_port_range ((struct sockaddr * )& my_addr4 , sizeof (my_addr4 ),
3085+ (struct sockaddr * )& local_addr4 , sizeof (local_addr4 ));
3086+
3087+ /* Finally try with a IPv6 socket */
3088+ check_port_range ((struct sockaddr * )& my_addr6 , sizeof (my_addr6 ),
3089+ (struct sockaddr * )& local_addr6 , sizeof (local_addr6 ));
3090+ #else
3091+ ztest_test_skip ();
3092+ #endif
3093+ }
3094+
29283095static void after (void * arg )
29293096{
29303097 ARG_UNUSED (arg );
0 commit comments