]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/socket_tests.c
c80172e19efc39608ecd217ec3c7fe0e92e804ce
5 * Created by Jerry Cottingham on 4/12/05.
6 * Copyright 2005 Apple Computer Inc. All rights reserved.
12 #include <mach/mach.h>
14 extern char g_target_path
[ PATH_MAX
];
15 extern int g_is_under_rosetta
;
17 /* **************************************************************************************************************
18 * Test accept, bind, connect, listen, socket, recvmsg, sendmsg, recvfrom, sendto, getpeername, getsockname
20 * WARNING - I don't do networking - this should get a good look from a networking stud.
21 * **************************************************************************************************************
23 int socket_tests( void * the_argp
)
25 int my_err
, my_status
, my_len
;
26 pid_t my_pid
, my_wait_pid
;
27 int my_socket_fd
= -1;
28 int my_accepted_socket
= -1;
29 char * my_parent_pathp
= NULL
;
30 char * my_child_pathp
= NULL
;
31 socklen_t my_accept_len
;
32 struct sockaddr
*my_sockaddr
;
34 off_t my_current_offset
;
35 char my_parent_socket_name
[sizeof(struct sockaddr
) + 64];
36 char my_child_socket_name
[sizeof(struct sockaddr
) + 64];
37 char my_accept_buffer
[sizeof(struct sockaddr
) + 64];
40 /* generate 2 names for binding to the sockets (one socket in the parent and one in the child) */
41 my_kr
= vm_allocate((vm_map_t
) mach_task_self(), (vm_address_t
*)&my_parent_pathp
, 128, VM_FLAGS_ANYWHERE
);
42 if(my_kr
!= KERN_SUCCESS
){
43 printf( "vm_allocate failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
44 goto test_failed_exit
;
47 my_kr
= vm_allocate((vm_map_t
) mach_task_self(), (vm_address_t
*)&my_child_pathp
, 128, VM_FLAGS_ANYWHERE
);
48 if(my_kr
!= KERN_SUCCESS
){
49 printf( "vm_allocate failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
50 goto test_failed_exit
;
53 *my_parent_pathp
= 0x00;
54 strcat( my_parent_pathp
, "/tmp/" );
56 /* get a unique name for our testing */
57 my_err
= create_random_name( my_parent_pathp
, 0 );
59 goto test_failed_exit
;
61 strcpy( my_child_pathp
, my_parent_pathp
);
62 strcat( my_parent_pathp
, "p" ); /* append 'p' to mean "parent" */
63 strcat( my_child_pathp
, "c" ); /* append 'c' to mean "child" */
65 memset( &my_parent_socket_name
[0], 0, sizeof(my_parent_socket_name
) );
66 memset( &my_child_socket_name
[0], 0, sizeof(my_child_socket_name
) );
68 /* use unique names we generated in /tmp/ */
69 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
70 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_parent_pathp
);
71 my_sockaddr
->sa_len
= my_len
;
72 my_sockaddr
->sa_family
= AF_UNIX
;
73 strcpy( &my_sockaddr
->sa_data
[0], my_parent_pathp
);
75 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
76 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_child_pathp
);
77 my_sockaddr
->sa_len
= my_len
;
78 my_sockaddr
->sa_family
= AF_UNIX
;
79 strcpy( &my_sockaddr
->sa_data
[0], my_child_pathp
);
81 /* set up socket for parent side */
82 my_socket_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
83 if ( my_socket_fd
== -1 ) {
84 printf( "socket call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
85 goto test_failed_exit
;
87 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
88 my_err
= bind( my_socket_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
90 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
91 goto test_failed_exit
;
94 /* test getsockname */
95 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
96 my_accept_len
= sizeof(my_accept_buffer
);
97 my_err
= getsockname( my_socket_fd
, my_sockaddr
, &my_accept_len
);
99 printf( "getsockname call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
100 goto test_failed_exit
;
102 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
103 printf( "getsockname test failed - did not get correct socket name data \n" );
104 goto test_failed_exit
;
107 /* make sure we can't seek on a socket */
108 my_current_offset
= lseek( my_socket_fd
, 0, SEEK_CUR
);
109 if ( my_current_offset
!= -1 ) {
110 printf( "lseek on socket should fail but did not \n" );
111 goto test_failed_exit
;
115 * spin off a child process that we communicate with via sockets.
118 if ( my_pid
== -1 ) {
119 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
120 goto test_failed_exit
;
124 * child process - open a socket and use it to talk to our parent.
126 int my_child_fd
= -1;
127 struct msghdr my_msghdr
;
128 struct iovec my_iov
[4];
131 my_child_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
132 if ( my_child_fd
== -1 ) {
133 printf( "socket call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
137 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
138 my_err
= bind( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
139 if ( my_err
== -1 ) {
140 close( my_child_fd
);
141 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
146 /* connect to socket in our parent */
147 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
148 my_err
= connect( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
149 if ( my_err
== -1 ) {
150 close( my_child_fd
);
151 printf( "connect call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
155 /* get some data from the child via socket and test socket peer data */
157 socklen_t my_buffer_len
;
158 struct sockaddr
* my_sockaddr
;
159 char my_parent_buffer
[256];
161 my_sockaddr
= (struct sockaddr
*) &my_parent_buffer
[0];
162 my_buffer_len
= sizeof(my_parent_buffer
);
163 my_err
= getpeername( my_child_fd
, my_sockaddr
, &my_buffer_len
);
164 if ( my_err
== -1 ) {
165 printf( "getpeername call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
166 goto test_failed_exit
;
169 /* test results - should be sa_family == SOCK_STREAM and name should match my_child_pathp */
170 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
171 printf( "getpeername test failed - did not get correct peer data \n" );
172 goto test_failed_exit
;
177 my_iov
[0].iov_base
= &my_buffer
[0];
178 my_iov
[0].iov_len
= 1;
180 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
181 my_msghdr
.msg_name
= my_sockaddr
;
182 my_msghdr
.msg_namelen
= my_sockaddr
->sa_len
;
183 my_msghdr
.msg_iov
= &my_iov
[0];
184 my_msghdr
.msg_iovlen
= 1;
185 my_msghdr
.msg_control
= NULL
;
186 my_msghdr
.msg_controllen
= 0;
187 my_msghdr
.msg_flags
= 0;
189 my_result
= sendmsg( my_child_fd
, &my_msghdr
, 0 );
190 if ( my_result
== -1 ) {
191 printf( "sendmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
192 close( my_child_fd
);
197 /* get data from our parent */
198 my_result
= recvfrom( my_child_fd
, &my_buffer
[0], 1,
199 MSG_WAITALL
, NULL
, NULL
);
200 if ( my_result
== -1 ) {
201 printf( "recvfrom failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
202 close( my_child_fd
);
206 /* verify that we got the correct message from our child */
207 if ( my_buffer
[0] != 'e' ) {
208 printf( "test failed - did not get correct data from child \n" );
209 close( my_child_fd
);
215 /* sendfile test. Open libsystem, set up some headers, and send it */
216 if (!g_is_under_rosetta
) {
217 struct sf_hdtr my_sf_hdtr
;
221 my_libsys_fd
= open("/usr/lib/libSystem.dylib", O_RDONLY
, 0644);
222 if (my_libsys_fd
< 0) {
223 printf( "test failed - could not open /usr/lib/libSystem.dylib\n" );
224 close ( my_child_fd
);
228 my_libsys_len
= 7+2; /* 2 bytes of header */
230 my_iov
[0].iov_base
= &my_buffer
[0];
231 my_iov
[0].iov_len
= 1;
233 my_iov
[1].iov_base
= &my_buffer
[1];
234 my_iov
[1].iov_len
= 1;
236 my_iov
[2].iov_base
= &my_buffer
[2];
237 my_iov
[2].iov_len
= 1;
239 my_iov
[3].iov_base
= &my_buffer
[3];
240 my_iov
[3].iov_len
= 1;
242 my_sf_hdtr
.headers
= &my_iov
[0];
243 my_sf_hdtr
.hdr_cnt
= 2;
244 my_sf_hdtr
.trailers
= &my_iov
[2];
245 my_sf_hdtr
.trl_cnt
= 2;
247 my_result
= sendfile(my_libsys_fd
, my_child_fd
, 3, &my_libsys_len
, &my_sf_hdtr
, 0);
248 if (my_result
< 0 || my_libsys_len
!= 11) {
249 printf( "sendfile failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
250 close( my_child_fd
);
254 my_result
= close ( my_libsys_fd
);
255 if ( my_libsys_fd
< 0 ) {
256 printf ( "close failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
257 close ( my_child_fd
);
263 /* tell parent we're done */
264 my_result
= write( my_child_fd
, "all done", 8 );
265 if ( my_result
== -1 ) {
266 close( my_child_fd
);
270 close( my_child_fd
);
275 * parent process - listen for connection requests
277 my_err
= listen( my_socket_fd
, 10 );
278 if ( my_err
== -1 ) {
279 printf( "listen call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
280 goto test_failed_exit
;
283 /* accept connection from child */
284 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
285 my_accepted_socket
= accept( my_socket_fd
, my_sockaddr
, &my_accept_len
);
286 if ( my_accepted_socket
== -1 ) {
287 printf( "accept call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
288 goto test_failed_exit
;
291 /* get some data from the child via socket and test socket peer data */
293 //socklen_t my_buffer_len;
294 struct msghdr my_msghdr
;
296 char my_parent_buffer
[128];
298 my_parent_buffer
[0] = 'x';
299 my_iov
.iov_base
= &my_parent_buffer
[0];
302 my_msghdr
.msg_name
= &my_accept_buffer
[0];
303 my_msghdr
.msg_namelen
= my_accept_len
;
304 my_msghdr
.msg_iov
= &my_iov
;
305 my_msghdr
.msg_iovlen
= 1;
306 my_msghdr
.msg_control
= NULL
;
307 my_msghdr
.msg_controllen
= 0;
308 my_msghdr
.msg_flags
= 0;
310 my_result
= recvmsg( my_accepted_socket
, &my_msghdr
, MSG_WAITALL
);
311 if ( my_result
== -1 ) {
312 printf( "recvmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
313 goto test_failed_exit
;
316 /* verify that we got the correct message from our child */
317 if ( my_parent_buffer
[0] != 'j' ) {
318 printf( "test failed - did not get correct data from child \n" );
319 goto test_failed_exit
;
323 /* now send some data to our child */
324 my_parent_buffer
[0] = 'e';
325 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
326 my_result
= sendto( my_accepted_socket
, &my_parent_buffer
[0], 1, 0, my_sockaddr
,
327 my_sockaddr
->sa_len
);
328 if ( my_result
== -1 ) {
329 printf( "sendto failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
330 goto test_failed_exit
;
335 if (!g_is_under_rosetta
) {
336 size_t neededBytes
= 11;
338 /* Check for sendfile output */
339 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
340 while (neededBytes
> 0) {
341 my_result
= read( my_accepted_socket
, &my_parent_buffer
[11-neededBytes
], neededBytes
);
342 if ( my_result
== -1 ) {
343 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
344 goto test_failed_exit
;
345 } else if (my_result
== 0) {
348 neededBytes
-= my_result
;
351 if ( neededBytes
> 0 ) {
352 printf( "read call returned %ld bytes instead of 11\n", 11 - neededBytes
);
353 goto test_failed_exit
;
356 if ( ! (my_parent_buffer
[0] == 's' && my_parent_buffer
[1] == 'e' && my_parent_buffer
[9] == 'n' && my_parent_buffer
[10] == 'd') ) {
357 printf( "read wrong sendfile message from child \n" );
358 goto test_failed_exit
;
364 /* see if child is done. bzero so that string is NUL terminated */
365 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
366 my_result
= read( my_accepted_socket
, &my_parent_buffer
[0], sizeof(my_parent_buffer
) );
367 if ( my_result
== -1 ) {
368 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
369 goto test_failed_exit
;
371 if ( strcmp( "all done", &my_parent_buffer
[0] ) != 0 ) {
372 printf( "read wrong message from child \n" );
373 goto test_failed_exit
;
377 /* wait for child to exit */
378 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
379 if ( my_wait_pid
== -1 ) {
380 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
381 goto test_failed_exit
;
384 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
385 goto test_failed_exit
;
389 goto test_passed_exit
;
395 if ( my_socket_fd
!= -1 )
396 close( my_socket_fd
);
397 if ( my_accepted_socket
!= -1 )
398 close( my_accepted_socket
);
399 if ( my_parent_pathp
!= NULL
) {
400 remove( my_parent_pathp
);
401 vm_deallocate(mach_task_self(), (vm_address_t
)my_parent_pathp
, 128);
403 if ( my_child_pathp
!= NULL
) {
404 remove( my_child_pathp
);
405 vm_deallocate(mach_task_self(), (vm_address_t
)my_child_pathp
, 128);
410 /* **************************************************************************************************************
411 * Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
412 * **************************************************************************************************************
414 int socket2_tests( void * the_argp
)
416 int my_err
, my_status
;
417 int my_sockets
[ 2 ] = {-1, -1};
418 pid_t my_pid
, my_wait_pid
;
420 socklen_t my_socklen
;
421 struct timeval
* my_tvp
;
422 struct timeval my_orig_tv
;
423 char my_buffer
[ 32 ];
425 my_err
= socketpair( AF_UNIX
, SOCK_STREAM
, 0, &my_sockets
[0] );
426 if ( my_err
== -1 ) {
427 printf( "socketpair failed with errno %d - %s \n", errno
, strerror( errno
) );
428 goto test_failed_exit
;
431 /* test getsockopt and setsockopt */
432 my_socklen
= sizeof( my_buffer
);
433 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_TYPE
, &my_buffer
[0], &my_socklen
);
434 if ( my_err
== -1 ) {
435 printf( "getsockopt - SO_TYPE - failed with errno %d - %s \n", errno
, strerror( errno
) );
436 goto test_failed_exit
;
438 if ( SOCK_STREAM
!= *((int *)&my_buffer
[0]) ) {
439 printf( "getsockopt returned incorrect socket type \n" );
440 goto test_failed_exit
;
443 /* get and set receive timeout */
444 my_socklen
= sizeof( my_buffer
);
445 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
446 if ( my_err
== -1 ) {
447 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
448 goto test_failed_exit
;
450 my_tvp
= (struct timeval
*) &my_buffer
[0];
451 my_orig_tv
.tv_sec
= my_tvp
->tv_sec
;
452 my_orig_tv
.tv_usec
= my_tvp
->tv_usec
;
454 my_tvp
->tv_sec
+= 60;
455 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], sizeof(struct timeval
) );
456 if ( my_err
== -1 ) {
457 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
458 goto test_failed_exit
;
461 /* verify we set it */
462 my_socklen
= sizeof( my_buffer
);
463 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
464 if ( my_err
== -1 ) {
465 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
466 goto test_failed_exit
;
468 my_tvp
= (struct timeval
*) &my_buffer
[0];
469 if ( my_tvp
->tv_sec
!= (my_orig_tv
.tv_sec
+ 60) || my_tvp
->tv_usec
!= my_orig_tv
.tv_usec
) {
470 printf( "setsockopt - SO_RCVTIMEO - did not set correct timeval \n" );
471 goto test_failed_exit
;
474 /* set back to original receive timeout */
475 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_orig_tv
, sizeof(struct timeval
) );
476 if ( my_err
== -1 ) {
477 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
478 goto test_failed_exit
;
481 /* test fsync - should fail when used with a socket fd */
483 my_err
= fsync( my_sockets
[0] );
484 if ( my_err
== -1 && errno
!= ENOTSUP
) {
485 printf( "fsync failed with errno %d - %s \n", errno
, strerror( errno
) );
486 goto test_failed_exit
;
488 else if ( my_err
!= -1 ) {
489 printf( "fsync should have failed with errno ENOTSUP \n" );
490 goto test_failed_exit
;
494 * spin off a child process that we will talk to via our socketpair.
497 if ( my_pid
== -1 ) {
498 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
499 goto test_failed_exit
;
503 * child process - tell parent we are ready to go.
505 char my_buffer
[ 32 ];
506 struct pollfd my_pollfd
;
508 my_count
= write( my_sockets
[1], "r", 1 );
509 if ( my_count
== -1 ) {
510 printf( "write call failed. got errno %d - %s. \n", errno
, strerror( errno
) );
514 /* test select by using it to wait for message from parent */
517 struct timeval my_timeout
;
519 FD_ZERO( &my_read_set
);
520 FD_SET( my_sockets
[1], &my_read_set
);
521 timerclear( &my_timeout
);
522 my_timeout
.tv_sec
= 1;
524 /* check to see if we are done, if no message is ready after a second
525 * return and try again...
527 my_err
= select( (my_sockets
[1] + 1), &my_read_set
, NULL
, NULL
, &my_timeout
);
528 if ( my_err
== -1 ) {
529 printf( "select call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
532 else if ( my_err
> 0 ) {
539 my_pollfd
.fd
= my_sockets
[1];
540 my_pollfd
.events
= (POLLIN
| POLLPRI
);
541 my_pollfd
.revents
= 0;
542 my_err
= poll( &my_pollfd
, 1, 500 );
543 if ( my_err
== -1 ) {
544 printf( "poll call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
547 /* should be ready for read */
548 if ( (my_pollfd
.revents
& POLLIN
) == 0 ) {
549 printf( "poll should have returned ready for read \n" );
553 my_count
= read( my_sockets
[1], &my_buffer
[0], sizeof(my_buffer
) );
554 if ( my_count
== -1 ) {
555 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
558 if ( my_buffer
[0] != 'd' ) {
559 printf( "read call on socket failed to get \"all done\" message \n" );
567 * parent process - wait for child to spin up
569 my_count
= read( my_sockets
[0], &my_buffer
[0], sizeof(my_buffer
) );
570 if ( my_count
== -1 ) {
571 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
572 goto test_failed_exit
;
574 if ( my_buffer
[0] != 'r' ) {
575 printf( "read call on socket failed to get \"ready to go message\" \n" );
576 goto test_failed_exit
;
579 /* tell child we're done */
580 write( my_sockets
[0], "d", 1 );
582 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
583 if ( my_wait_pid
== -1 ) {
584 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
585 goto test_failed_exit
;
588 /* wait4 should return our child's pid when it exits */
589 if ( my_wait_pid
!= my_pid
) {
590 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid
, my_pid
);
591 goto test_failed_exit
;
594 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
595 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status
);
596 goto test_failed_exit
;
600 goto test_passed_exit
;
606 if ( my_sockets
[0] != -1 )
607 close( my_sockets
[0] );
608 if ( my_sockets
[1] != -1 )
609 close( my_sockets
[1] );