2525
2626#define NETSOCK_TEST_PEEK_COUNT 8
2727
28+ struct netsock_thread_params {
29+ int sock_type ;
30+ boolean ipv6 ;
31+ struct sockaddr * addr ;
32+ };
33+
2834static inline void timespec_sub (struct timespec * a , struct timespec * b , struct timespec * r )
2935{
3036 r -> tv_sec = a -> tv_sec - b -> tv_sec ;
@@ -35,6 +41,28 @@ static inline void timespec_sub(struct timespec *a, struct timespec *b, struct t
3541 }
3642}
3743
44+ /* Finds an available port to bind to, starting from 1024. */
45+ static void netsock_bind (int fd , boolean ipv6 , struct sockaddr * addr )
46+ {
47+ int port = 1024 ;
48+
49+ while (1 ) {
50+ int ret ;
51+
52+ if (ipv6 ) {
53+ ((struct sockaddr_in6 * )addr )-> sin6_port = htons (port );
54+ ret = bind (fd , addr , sizeof (struct sockaddr_in6 ));
55+ } else {
56+ ((struct sockaddr_in * )addr )-> sin_port = htons (port );
57+ ret = bind (fd , addr , sizeof (struct sockaddr_in ));
58+ }
59+ if (ret == 0 )
60+ break ;
61+ test_assert ((ret == -1 ) && (errno == EADDRINUSE ));
62+ port ++ ;
63+ }
64+ }
65+
3866static void * netsock_test_basic_thread (void * arg )
3967{
4068 int sock_type = (long )arg ;
@@ -947,6 +975,90 @@ static void netsock_test_timeout(void)
947975 close (listen_fd );
948976}
949977
978+ static void * netsock_test_txrx_thread (void * arg )
979+ {
980+ struct netsock_thread_params * params = arg ;
981+ int fd ;
982+ socklen_t addrlen = params -> ipv6 ? sizeof (struct sockaddr_in6 ) : sizeof (struct sockaddr_in );
983+ uint8_t buf [KB ];
984+
985+ fd = socket (params -> ipv6 ? AF_INET6 : AF_INET , params -> sock_type , 0 );
986+ test_assert (fd > 0 );
987+ if (params -> sock_type == SOCK_STREAM ) {
988+ test_assert (connect (fd , params -> addr , addrlen ) == 0 );
989+ test_assert (send (fd , buf , sizeof (buf ), 0 ) > 0 );
990+ test_assert (recv (fd , buf , sizeof (buf ), 0 ) > 0 );
991+ } else {
992+ test_assert (sendto (fd , buf , sizeof (buf ), 0 , params -> addr , addrlen ) > 0 );
993+ test_assert (recvfrom (fd , buf , sizeof (buf ), 0 , params -> addr , & addrlen ) > 0 );
994+ }
995+ close (fd );
996+ return NULL ;
997+ }
998+
999+ /* Tests connection to the "any" address (0.0.0.0 for IPv4, [::] for IPv6), which should be remapped
1000+ * to the loopback address. */
1001+ static void netsock_test_addr_any (int sock_type , boolean ipv6 )
1002+ {
1003+ int fd ;
1004+ struct sockaddr_in addr4 ;
1005+ struct sockaddr_in6 addr6 ;
1006+ struct sockaddr * addr ;
1007+ struct netsock_thread_params params ;
1008+ pthread_t thread ;
1009+ uint8_t buf [KB ];
1010+ int ret ;
1011+
1012+ fd = socket (ipv6 ? AF_INET6 : AF_INET , sock_type , 0 );
1013+ test_assert (fd > 0 );
1014+ if (ipv6 ) {
1015+ memset (& addr6 , 0 , sizeof (addr6 ));
1016+ addr6 .sin6_family = AF_INET6 ;
1017+ addr6 .sin6_addr = in6addr_any ;
1018+ addr = (struct sockaddr * )& addr6 ;
1019+ } else {
1020+ addr4 .sin_family = AF_INET ;
1021+ addr4 .sin_addr .s_addr = htonl (INADDR_ANY );
1022+ addr = (struct sockaddr * )& addr4 ;
1023+ }
1024+ netsock_bind (fd , ipv6 , addr );
1025+ params .sock_type = sock_type ;
1026+ params .ipv6 = ipv6 ;
1027+ params .addr = addr ;
1028+ if (sock_type == SOCK_STREAM ) {
1029+ int conn_fd ;
1030+
1031+ test_assert (listen (fd , 1 ) == 0 );
1032+ ret = pthread_create (& thread , NULL , netsock_test_txrx_thread , & params );
1033+ test_assert (ret == 0 );
1034+ conn_fd = accept (fd , NULL , NULL );
1035+ test_assert (conn_fd > 0 );
1036+ test_assert (recv (conn_fd , buf , sizeof (buf ), 0 ) > 0 );
1037+ test_assert (send (conn_fd , buf , sizeof (buf ), 0 ) > 0 );
1038+ close (conn_fd );
1039+ } else {
1040+ struct sockaddr_in peer_addr4 ;
1041+ struct sockaddr_in6 peer_addr6 ;
1042+ socklen_t addrlen ;
1043+
1044+ ret = pthread_create (& thread , NULL , netsock_test_txrx_thread , & params );
1045+ test_assert (ret == 0 );
1046+ if (ipv6 ) {
1047+ addr = (struct sockaddr * )& peer_addr6 ;
1048+ addrlen = sizeof (peer_addr6 );
1049+ } else {
1050+ addr = (struct sockaddr * )& peer_addr4 ;
1051+ addrlen = sizeof (peer_addr4 );
1052+ }
1053+ ret = recvfrom (fd , buf , sizeof (buf ), 0 , addr , & addrlen );
1054+ test_assert (ret > 0 );
1055+ ret = sendto (fd , buf , sizeof (buf ), 0 , addr , addrlen );
1056+ test_assert (ret > 0 );
1057+ }
1058+ test_assert (pthread_join (thread , NULL ) == 0 );
1059+ close (fd );
1060+ }
1061+
9501062int main (int argc , char * * argv )
9511063{
9521064 netsock_test_basic (SOCK_STREAM );
@@ -962,6 +1074,10 @@ int main(int argc, char **argv)
9621074 netsock_test_msg (SOCK_DGRAM );
9631075 netsock_test_fault ();
9641076 netsock_test_timeout ();
1077+ netsock_test_addr_any (SOCK_STREAM , false);
1078+ netsock_test_addr_any (SOCK_STREAM , true);
1079+ netsock_test_addr_any (SOCK_DGRAM , false);
1080+ netsock_test_addr_any (SOCK_DGRAM , true);
9651081 printf ("Network socket tests OK\n" );
9661082 return EXIT_SUCCESS ;
9671083}
0 commit comments