]>
git.saurik.com Git - apple/xnu.git/blob - tools/tests/xnu_quick_test/socket_tests.c
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
];
16 /* **************************************************************************************************************
17 * Test accept, bind, connect, listen, socket, recvmsg, sendmsg, recvfrom, sendto, getpeername, getsockname
19 * WARNING - I don't do networking - this should get a good look from a networking stud.
20 * **************************************************************************************************************
22 int socket_tests( void * the_argp
)
24 int my_err
, my_status
, my_len
;
25 pid_t my_pid
, my_wait_pid
;
26 int my_socket_fd
= -1;
27 int my_accepted_socket
= -1;
28 char * my_parent_pathp
= NULL
;
29 char * my_child_pathp
= NULL
;
30 socklen_t my_accept_len
;
31 struct sockaddr
*my_sockaddr
;
33 off_t my_current_offset
;
34 char my_parent_socket_name
[sizeof(struct sockaddr
) + 64];
35 char my_child_socket_name
[sizeof(struct sockaddr
) + 64];
36 char my_accept_buffer
[sizeof(struct sockaddr
) + 64];
39 /* generate 2 names for binding to the sockets (one socket in the parent and one in the child) */
40 my_kr
= vm_allocate((vm_map_t
) mach_task_self(), (vm_address_t
*)&my_parent_pathp
, 128, VM_FLAGS_ANYWHERE
);
41 if(my_kr
!= KERN_SUCCESS
){
42 printf( "vm_allocate failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
43 goto test_failed_exit
;
46 my_kr
= vm_allocate((vm_map_t
) mach_task_self(), (vm_address_t
*)&my_child_pathp
, 128, VM_FLAGS_ANYWHERE
);
47 if(my_kr
!= KERN_SUCCESS
){
48 printf( "vm_allocate failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
49 goto test_failed_exit
;
52 *my_parent_pathp
= 0x00;
53 strcat( my_parent_pathp
, "/tmp/" );
55 /* get a unique name for our testing */
56 my_err
= create_random_name( my_parent_pathp
, 0 );
58 goto test_failed_exit
;
60 strcpy( my_child_pathp
, my_parent_pathp
);
61 strcat( my_parent_pathp
, "p" ); /* append 'p' to mean "parent" */
62 strcat( my_child_pathp
, "c" ); /* append 'c' to mean "child" */
64 memset( &my_parent_socket_name
[0], 0, sizeof(my_parent_socket_name
) );
65 memset( &my_child_socket_name
[0], 0, sizeof(my_child_socket_name
) );
67 /* use unique names we generated in /tmp/ */
68 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
69 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_parent_pathp
);
70 my_sockaddr
->sa_len
= my_len
;
71 my_sockaddr
->sa_family
= AF_UNIX
;
72 strcpy( &my_sockaddr
->sa_data
[0], my_parent_pathp
);
74 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
75 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_child_pathp
);
76 my_sockaddr
->sa_len
= my_len
;
77 my_sockaddr
->sa_family
= AF_UNIX
;
78 strcpy( &my_sockaddr
->sa_data
[0], my_child_pathp
);
80 /* set up socket for parent side */
81 my_socket_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
82 if ( my_socket_fd
== -1 ) {
83 printf( "socket call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
84 goto test_failed_exit
;
86 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
87 my_err
= bind( my_socket_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
89 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
90 goto test_failed_exit
;
93 /* test getsockname */
94 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
95 my_accept_len
= sizeof(my_accept_buffer
);
96 my_err
= getsockname( my_socket_fd
, my_sockaddr
, &my_accept_len
);
98 printf( "getsockname call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
99 goto test_failed_exit
;
101 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
102 printf( "getsockname test failed - did not get correct socket name data \n" );
103 goto test_failed_exit
;
106 /* make sure we can't seek on a socket */
107 my_current_offset
= lseek( my_socket_fd
, 0, SEEK_CUR
);
108 if ( my_current_offset
!= -1 ) {
109 printf( "lseek on socket should fail but did not \n" );
110 goto test_failed_exit
;
114 * spin off a child process that we communicate with via sockets.
117 if ( my_pid
== -1 ) {
118 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
119 goto test_failed_exit
;
123 * child process - open a socket and use it to talk to our parent.
125 int my_child_fd
= -1;
126 struct msghdr my_msghdr
;
127 struct iovec my_iov
[4];
130 my_child_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
131 if ( my_child_fd
== -1 ) {
132 printf( "socket call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
136 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
137 my_err
= bind( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
138 if ( my_err
== -1 ) {
139 close( my_child_fd
);
140 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
145 /* connect to socket in our parent */
146 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
147 my_err
= connect( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
148 if ( my_err
== -1 ) {
149 close( my_child_fd
);
150 printf( "connect call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
154 /* get some data from the child via socket and test socket peer data */
156 socklen_t my_buffer_len
;
157 struct sockaddr
* my_sockaddr
;
158 char my_parent_buffer
[256];
160 my_sockaddr
= (struct sockaddr
*) &my_parent_buffer
[0];
161 my_buffer_len
= sizeof(my_parent_buffer
);
162 my_err
= getpeername( my_child_fd
, my_sockaddr
, &my_buffer_len
);
163 if ( my_err
== -1 ) {
164 printf( "getpeername call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
165 goto test_failed_exit
;
168 /* test results - should be sa_family == SOCK_STREAM and name should match my_child_pathp */
169 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
170 printf( "getpeername test failed - did not get correct peer data \n" );
171 goto test_failed_exit
;
176 my_iov
[0].iov_base
= &my_buffer
[0];
177 my_iov
[0].iov_len
= 1;
179 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
180 my_msghdr
.msg_name
= my_sockaddr
;
181 my_msghdr
.msg_namelen
= my_sockaddr
->sa_len
;
182 my_msghdr
.msg_iov
= &my_iov
[0];
183 my_msghdr
.msg_iovlen
= 1;
184 my_msghdr
.msg_control
= NULL
;
185 my_msghdr
.msg_controllen
= 0;
186 my_msghdr
.msg_flags
= 0;
188 my_result
= sendmsg( my_child_fd
, &my_msghdr
, 0 );
189 if ( my_result
== -1 ) {
190 printf( "sendmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
191 close( my_child_fd
);
196 /* get data from our parent */
197 my_result
= recvfrom( my_child_fd
, &my_buffer
[0], 1,
198 MSG_WAITALL
, NULL
, NULL
);
199 if ( my_result
== -1 ) {
200 printf( "recvfrom failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
201 close( my_child_fd
);
205 /* verify that we got the correct message from our child */
206 if ( my_buffer
[0] != 'e' ) {
207 printf( "test failed - did not get correct data from child \n" );
208 close( my_child_fd
);
213 #if !TARGET_OS_EMBEDDED
214 /* sendfile test. Open libsystem, set up some headers, and send it */
215 struct sf_hdtr my_sf_hdtr
;
219 my_libsys_fd
= open("/usr/lib/libSystem.dylib", O_RDONLY
, 0644);
220 if (my_libsys_fd
< 0) {
221 printf( "test failed - could not open /usr/lib/libSystem.dylib\n" );
222 close ( my_child_fd
);
226 my_libsys_len
= 7+2; /* 2 bytes of header */
228 my_iov
[0].iov_base
= &my_buffer
[0];
229 my_iov
[0].iov_len
= 1;
231 my_iov
[1].iov_base
= &my_buffer
[1];
232 my_iov
[1].iov_len
= 1;
234 my_iov
[2].iov_base
= &my_buffer
[2];
235 my_iov
[2].iov_len
= 1;
237 my_iov
[3].iov_base
= &my_buffer
[3];
238 my_iov
[3].iov_len
= 1;
240 my_sf_hdtr
.headers
= &my_iov
[0];
241 my_sf_hdtr
.hdr_cnt
= 2;
242 my_sf_hdtr
.trailers
= &my_iov
[2];
243 my_sf_hdtr
.trl_cnt
= 2;
245 my_result
= sendfile(my_libsys_fd
, my_child_fd
, 3, &my_libsys_len
, &my_sf_hdtr
, 0);
246 if (my_result
< 0 || my_libsys_len
!= 11) {
247 printf( "sendfile failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
248 close( my_child_fd
);
252 my_result
= close ( my_libsys_fd
);
253 if ( my_libsys_fd
< 0 ) {
254 printf ( "close failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
255 close ( my_child_fd
);
260 /* tell parent we're done */
261 my_result
= write( my_child_fd
, "all done", 8 );
262 if ( my_result
== -1 ) {
263 close( my_child_fd
);
267 close( my_child_fd
);
272 * parent process - listen for connection requests
274 my_err
= listen( my_socket_fd
, 10 );
275 if ( my_err
== -1 ) {
276 printf( "listen call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
277 goto test_failed_exit
;
280 /* accept connection from child */
281 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
282 my_accepted_socket
= accept( my_socket_fd
, my_sockaddr
, &my_accept_len
);
283 if ( my_accepted_socket
== -1 ) {
284 printf( "accept call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
285 goto test_failed_exit
;
288 /* get some data from the child via socket and test socket peer data */
290 //socklen_t my_buffer_len;
291 struct msghdr my_msghdr
;
293 char my_parent_buffer
[128];
295 my_parent_buffer
[0] = 'x';
296 my_iov
.iov_base
= &my_parent_buffer
[0];
299 my_msghdr
.msg_name
= &my_accept_buffer
[0];
300 my_msghdr
.msg_namelen
= my_accept_len
;
301 my_msghdr
.msg_iov
= &my_iov
;
302 my_msghdr
.msg_iovlen
= 1;
303 my_msghdr
.msg_control
= NULL
;
304 my_msghdr
.msg_controllen
= 0;
305 my_msghdr
.msg_flags
= 0;
307 my_result
= recvmsg( my_accepted_socket
, &my_msghdr
, MSG_WAITALL
);
308 if ( my_result
== -1 ) {
309 printf( "recvmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
310 goto test_failed_exit
;
313 /* verify that we got the correct message from our child */
314 if ( my_parent_buffer
[0] != 'j' ) {
315 printf( "test failed - did not get correct data from child \n" );
316 goto test_failed_exit
;
320 /* now send some data to our child */
321 my_parent_buffer
[0] = 'e';
322 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
323 my_result
= sendto( my_accepted_socket
, &my_parent_buffer
[0], 1, 0, my_sockaddr
,
324 my_sockaddr
->sa_len
);
325 if ( my_result
== -1 ) {
326 printf( "sendto failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
327 goto test_failed_exit
;
331 #if !TARGET_OS_EMBEDDED
332 size_t neededBytes
= 11;
334 /* Check for sendfile output */
335 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
336 while (neededBytes
> 0) {
337 my_result
= read( my_accepted_socket
, &my_parent_buffer
[11-neededBytes
], neededBytes
);
338 if ( my_result
== -1 ) {
339 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
340 goto test_failed_exit
;
341 } else if (my_result
== 0) {
344 neededBytes
-= my_result
;
347 if ( neededBytes
> 0 ) {
348 printf( "read call returned %ld bytes instead of 11\n", 11 - neededBytes
);
349 goto test_failed_exit
;
352 if ( ! (my_parent_buffer
[0] == 's' && my_parent_buffer
[1] == 'e' && my_parent_buffer
[9] == 'n' && my_parent_buffer
[10] == 'd') ) {
353 printf( "read wrong sendfile message from child \n" );
354 goto test_failed_exit
;
359 /* see if child is done. bzero so that string is NUL terminated */
360 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
361 my_result
= read( my_accepted_socket
, &my_parent_buffer
[0], sizeof(my_parent_buffer
) );
362 if ( my_result
== -1 ) {
363 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
364 goto test_failed_exit
;
366 if ( strcmp( "all done", &my_parent_buffer
[0] ) != 0 ) {
367 printf( "read wrong message from child \n" );
368 goto test_failed_exit
;
372 /* wait for child to exit */
373 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
374 if ( my_wait_pid
== -1 ) {
375 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
376 goto test_failed_exit
;
379 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
380 goto test_failed_exit
;
384 goto test_passed_exit
;
390 if ( my_socket_fd
!= -1 )
391 close( my_socket_fd
);
392 if ( my_accepted_socket
!= -1 )
393 close( my_accepted_socket
);
394 if ( my_parent_pathp
!= NULL
) {
395 remove( my_parent_pathp
);
396 vm_deallocate(mach_task_self(), (vm_address_t
)my_parent_pathp
, 128);
398 if ( my_child_pathp
!= NULL
) {
399 remove( my_child_pathp
);
400 vm_deallocate(mach_task_self(), (vm_address_t
)my_child_pathp
, 128);
405 /* **************************************************************************************************************
406 * Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
407 * **************************************************************************************************************
409 int socket2_tests( void * the_argp
)
411 int my_err
, my_status
;
412 int my_sockets
[ 2 ] = {-1, -1};
413 pid_t my_pid
, my_wait_pid
;
415 socklen_t my_socklen
;
416 struct timeval
* my_tvp
;
417 struct timeval my_orig_tv
;
418 char my_buffer
[ 32 ];
420 my_err
= socketpair( AF_UNIX
, SOCK_STREAM
, 0, &my_sockets
[0] );
421 if ( my_err
== -1 ) {
422 printf( "socketpair failed with errno %d - %s \n", errno
, strerror( errno
) );
423 goto test_failed_exit
;
426 /* test getsockopt and setsockopt */
427 my_socklen
= sizeof( my_buffer
);
428 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_TYPE
, &my_buffer
[0], &my_socklen
);
429 if ( my_err
== -1 ) {
430 printf( "getsockopt - SO_TYPE - failed with errno %d - %s \n", errno
, strerror( errno
) );
431 goto test_failed_exit
;
433 if ( SOCK_STREAM
!= *((int *)&my_buffer
[0]) ) {
434 printf( "getsockopt returned incorrect socket type \n" );
435 goto test_failed_exit
;
438 /* get and set receive timeout */
439 my_socklen
= sizeof( my_buffer
);
440 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
441 if ( my_err
== -1 ) {
442 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
443 goto test_failed_exit
;
445 my_tvp
= (struct timeval
*) &my_buffer
[0];
446 my_orig_tv
.tv_sec
= my_tvp
->tv_sec
;
447 my_orig_tv
.tv_usec
= my_tvp
->tv_usec
;
449 my_tvp
->tv_sec
+= 60;
450 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], sizeof(struct timeval
) );
451 if ( my_err
== -1 ) {
452 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
453 goto test_failed_exit
;
456 /* verify we set it */
457 my_socklen
= sizeof( my_buffer
);
458 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
459 if ( my_err
== -1 ) {
460 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
461 goto test_failed_exit
;
463 my_tvp
= (struct timeval
*) &my_buffer
[0];
464 if ( my_tvp
->tv_sec
!= (my_orig_tv
.tv_sec
+ 60) || my_tvp
->tv_usec
!= my_orig_tv
.tv_usec
) {
465 printf( "setsockopt - SO_RCVTIMEO - did not set correct timeval \n" );
466 goto test_failed_exit
;
469 /* set back to original receive timeout */
470 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_orig_tv
, sizeof(struct timeval
) );
471 if ( my_err
== -1 ) {
472 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
473 goto test_failed_exit
;
476 /* test fsync - should fail when used with a socket fd */
478 my_err
= fsync( my_sockets
[0] );
479 if ( my_err
== -1 && errno
!= ENOTSUP
) {
480 printf( "fsync failed with errno %d - %s \n", errno
, strerror( errno
) );
481 goto test_failed_exit
;
483 else if ( my_err
!= -1 ) {
484 printf( "fsync should have failed with errno ENOTSUP \n" );
485 goto test_failed_exit
;
489 * spin off a child process that we will talk to via our socketpair.
492 if ( my_pid
== -1 ) {
493 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
494 goto test_failed_exit
;
498 * child process - tell parent we are ready to go.
500 char my_buffer
[ 32 ];
501 struct pollfd my_pollfd
;
503 my_count
= write( my_sockets
[1], "r", 1 );
504 if ( my_count
== -1 ) {
505 printf( "write call failed. got errno %d - %s. \n", errno
, strerror( errno
) );
509 /* test select by using it to wait for message from parent */
512 struct timeval my_timeout
;
514 FD_ZERO( &my_read_set
);
515 FD_SET( my_sockets
[1], &my_read_set
);
516 timerclear( &my_timeout
);
517 my_timeout
.tv_sec
= 1;
519 /* check to see if we are done, if no message is ready after a second
520 * return and try again...
522 my_err
= select( (my_sockets
[1] + 1), &my_read_set
, NULL
, NULL
, &my_timeout
);
523 if ( my_err
== -1 ) {
524 printf( "select call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
527 else if ( my_err
> 0 ) {
534 my_pollfd
.fd
= my_sockets
[1];
535 my_pollfd
.events
= (POLLIN
| POLLPRI
);
536 my_pollfd
.revents
= 0;
537 my_err
= poll( &my_pollfd
, 1, 500 );
538 if ( my_err
== -1 ) {
539 printf( "poll call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
542 /* should be ready for read */
543 if ( (my_pollfd
.revents
& POLLIN
) == 0 ) {
544 printf( "poll should have returned ready for read \n" );
548 my_count
= read( my_sockets
[1], &my_buffer
[0], sizeof(my_buffer
) );
549 if ( my_count
== -1 ) {
550 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
553 if ( my_buffer
[0] != 'd' ) {
554 printf( "read call on socket failed to get \"all done\" message \n" );
562 * parent process - wait for child to spin up
564 my_count
= read( my_sockets
[0], &my_buffer
[0], sizeof(my_buffer
) );
565 if ( my_count
== -1 ) {
566 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
567 goto test_failed_exit
;
569 if ( my_buffer
[0] != 'r' ) {
570 printf( "read call on socket failed to get \"ready to go message\" \n" );
571 goto test_failed_exit
;
574 /* tell child we're done */
575 write( my_sockets
[0], "d", 1 );
577 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
578 if ( my_wait_pid
== -1 ) {
579 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
580 goto test_failed_exit
;
583 /* wait4 should return our child's pid when it exits */
584 if ( my_wait_pid
!= my_pid
) {
585 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid
, my_pid
);
586 goto test_failed_exit
;
589 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
590 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status
);
591 goto test_failed_exit
;
595 goto test_passed_exit
;
601 if ( my_sockets
[0] != -1 )
602 close( my_sockets
[0] );
603 if ( my_sockets
[1] != -1 )
604 close( my_sockets
[1] );