]>
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 /* sendfile test. Open libsystem, set up some headers, and send it */
214 struct sf_hdtr my_sf_hdtr
;
218 my_libsys_fd
= open("/usr/lib/libSystem.dylib", O_RDONLY
, 0644);
219 if (my_libsys_fd
< 0) {
220 printf( "test failed - could not open /usr/lib/libSystem.dylib\n" );
221 close ( my_child_fd
);
225 my_libsys_len
= 7+2; /* 2 bytes of header */
227 my_iov
[0].iov_base
= &my_buffer
[0];
228 my_iov
[0].iov_len
= 1;
230 my_iov
[1].iov_base
= &my_buffer
[1];
231 my_iov
[1].iov_len
= 1;
233 my_iov
[2].iov_base
= &my_buffer
[2];
234 my_iov
[2].iov_len
= 1;
236 my_iov
[3].iov_base
= &my_buffer
[3];
237 my_iov
[3].iov_len
= 1;
239 my_sf_hdtr
.headers
= &my_iov
[0];
240 my_sf_hdtr
.hdr_cnt
= 2;
241 my_sf_hdtr
.trailers
= &my_iov
[2];
242 my_sf_hdtr
.trl_cnt
= 2;
244 my_result
= sendfile(my_libsys_fd
, my_child_fd
, 3, &my_libsys_len
, &my_sf_hdtr
, 0);
245 if (my_result
< 0 || my_libsys_len
!= 11) {
246 printf( "sendfile failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
247 close( my_child_fd
);
251 my_result
= close ( my_libsys_fd
);
252 if ( my_libsys_fd
< 0 ) {
253 printf ( "close failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
254 close ( my_child_fd
);
258 /* tell parent we're done */
259 my_result
= write( my_child_fd
, "all done", 8 );
260 if ( my_result
== -1 ) {
261 close( my_child_fd
);
265 close( my_child_fd
);
270 * parent process - listen for connection requests
272 my_err
= listen( my_socket_fd
, 10 );
273 if ( my_err
== -1 ) {
274 printf( "listen call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
275 goto test_failed_exit
;
278 /* accept connection from child */
279 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
280 my_accepted_socket
= accept( my_socket_fd
, my_sockaddr
, &my_accept_len
);
281 if ( my_accepted_socket
== -1 ) {
282 printf( "accept call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
283 goto test_failed_exit
;
286 /* get some data from the child via socket and test socket peer data */
288 //socklen_t my_buffer_len;
289 struct msghdr my_msghdr
;
291 char my_parent_buffer
[128];
293 my_parent_buffer
[0] = 'x';
294 my_iov
.iov_base
= &my_parent_buffer
[0];
297 my_msghdr
.msg_name
= &my_accept_buffer
[0];
298 my_msghdr
.msg_namelen
= my_accept_len
;
299 my_msghdr
.msg_iov
= &my_iov
;
300 my_msghdr
.msg_iovlen
= 1;
301 my_msghdr
.msg_control
= NULL
;
302 my_msghdr
.msg_controllen
= 0;
303 my_msghdr
.msg_flags
= 0;
305 my_result
= recvmsg( my_accepted_socket
, &my_msghdr
, MSG_WAITALL
);
306 if ( my_result
== -1 ) {
307 printf( "recvmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
308 goto test_failed_exit
;
311 /* verify that we got the correct message from our child */
312 if ( my_parent_buffer
[0] != 'j' ) {
313 printf( "test failed - did not get correct data from child \n" );
314 goto test_failed_exit
;
318 /* now send some data to our child */
319 my_parent_buffer
[0] = 'e';
320 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
321 my_result
= sendto( my_accepted_socket
, &my_parent_buffer
[0], 1, 0, my_sockaddr
,
322 my_sockaddr
->sa_len
);
323 if ( my_result
== -1 ) {
324 printf( "sendto failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
325 goto test_failed_exit
;
329 size_t neededBytes
= 11;
331 /* Check for sendfile output */
332 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
333 while (neededBytes
> 0) {
334 my_result
= read( my_accepted_socket
, &my_parent_buffer
[11-neededBytes
], neededBytes
);
335 if ( my_result
== -1 ) {
336 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
337 goto test_failed_exit
;
338 } else if (my_result
== 0) {
341 neededBytes
-= my_result
;
344 if ( neededBytes
> 0 ) {
345 printf( "read call returned %ld bytes instead of 11\n", 11 - neededBytes
);
346 goto test_failed_exit
;
349 if ( ! (my_parent_buffer
[0] == 's' && my_parent_buffer
[1] == 'e' && my_parent_buffer
[9] == 'n' && my_parent_buffer
[10] == 'd') ) {
350 printf( "read wrong sendfile message from child \n" );
351 goto test_failed_exit
;
355 /* see if child is done. bzero so that string is NUL terminated */
356 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
357 my_result
= read( my_accepted_socket
, &my_parent_buffer
[0], sizeof(my_parent_buffer
) );
358 if ( my_result
== -1 ) {
359 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
360 goto test_failed_exit
;
362 if ( strcmp( "all done", &my_parent_buffer
[0] ) != 0 ) {
363 printf( "read wrong message from child \n" );
364 goto test_failed_exit
;
368 /* wait for child to exit */
369 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
370 if ( my_wait_pid
== -1 ) {
371 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
372 goto test_failed_exit
;
375 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
376 goto test_failed_exit
;
380 goto test_passed_exit
;
386 if ( my_socket_fd
!= -1 )
387 close( my_socket_fd
);
388 if ( my_accepted_socket
!= -1 )
389 close( my_accepted_socket
);
390 if ( my_parent_pathp
!= NULL
) {
391 remove( my_parent_pathp
);
392 vm_deallocate(mach_task_self(), (vm_address_t
)my_parent_pathp
, 128);
394 if ( my_child_pathp
!= NULL
) {
395 remove( my_child_pathp
);
396 vm_deallocate(mach_task_self(), (vm_address_t
)my_child_pathp
, 128);
401 /* **************************************************************************************************************
402 * Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
403 * **************************************************************************************************************
405 int socket2_tests( void * the_argp
)
407 int my_err
, my_status
;
408 int my_sockets
[ 2 ] = {-1, -1};
409 pid_t my_pid
, my_wait_pid
;
411 socklen_t my_socklen
;
412 struct timeval
* my_tvp
;
413 struct timeval my_orig_tv
;
414 char my_buffer
[ 32 ];
416 my_err
= socketpair( AF_UNIX
, SOCK_STREAM
, 0, &my_sockets
[0] );
417 if ( my_err
== -1 ) {
418 printf( "socketpair failed with errno %d - %s \n", errno
, strerror( errno
) );
419 goto test_failed_exit
;
422 /* test getsockopt and setsockopt */
423 my_socklen
= sizeof( my_buffer
);
424 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_TYPE
, &my_buffer
[0], &my_socklen
);
425 if ( my_err
== -1 ) {
426 printf( "getsockopt - SO_TYPE - failed with errno %d - %s \n", errno
, strerror( errno
) );
427 goto test_failed_exit
;
429 if ( SOCK_STREAM
!= *((int *)&my_buffer
[0]) ) {
430 printf( "getsockopt returned incorrect socket type \n" );
431 goto test_failed_exit
;
434 /* get and set receive timeout */
435 my_socklen
= sizeof( my_buffer
);
436 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
437 if ( my_err
== -1 ) {
438 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
439 goto test_failed_exit
;
441 my_tvp
= (struct timeval
*) &my_buffer
[0];
442 my_orig_tv
.tv_sec
= my_tvp
->tv_sec
;
443 my_orig_tv
.tv_usec
= my_tvp
->tv_usec
;
445 my_tvp
->tv_sec
+= 60;
446 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], sizeof(struct timeval
) );
447 if ( my_err
== -1 ) {
448 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
449 goto test_failed_exit
;
452 /* verify we set it */
453 my_socklen
= sizeof( my_buffer
);
454 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
455 if ( my_err
== -1 ) {
456 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
457 goto test_failed_exit
;
459 my_tvp
= (struct timeval
*) &my_buffer
[0];
460 if ( my_tvp
->tv_sec
!= (my_orig_tv
.tv_sec
+ 60) || my_tvp
->tv_usec
!= my_orig_tv
.tv_usec
) {
461 printf( "setsockopt - SO_RCVTIMEO - did not set correct timeval \n" );
462 goto test_failed_exit
;
465 /* set back to original receive timeout */
466 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_orig_tv
, sizeof(struct timeval
) );
467 if ( my_err
== -1 ) {
468 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
469 goto test_failed_exit
;
472 /* test fsync - should fail when used with a socket fd */
474 my_err
= fsync( my_sockets
[0] );
475 if ( my_err
== -1 && errno
!= ENOTSUP
) {
476 printf( "fsync failed with errno %d - %s \n", errno
, strerror( errno
) );
477 goto test_failed_exit
;
479 else if ( my_err
!= -1 ) {
480 printf( "fsync should have failed with errno ENOTSUP \n" );
481 goto test_failed_exit
;
485 * spin off a child process that we will talk to via our socketpair.
488 if ( my_pid
== -1 ) {
489 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
490 goto test_failed_exit
;
494 * child process - tell parent we are ready to go.
496 char my_buffer
[ 32 ];
497 struct pollfd my_pollfd
;
499 my_count
= write( my_sockets
[1], "r", 1 );
500 if ( my_count
== -1 ) {
501 printf( "write call failed. got errno %d - %s. \n", errno
, strerror( errno
) );
505 /* test select by using it to wait for message from parent */
508 struct timeval my_timeout
;
510 FD_ZERO( &my_read_set
);
511 FD_SET( my_sockets
[1], &my_read_set
);
512 timerclear( &my_timeout
);
513 my_timeout
.tv_sec
= 1;
515 /* check to see if we are done, if no message is ready after a second
516 * return and try again...
518 my_err
= select( (my_sockets
[1] + 1), &my_read_set
, NULL
, NULL
, &my_timeout
);
519 if ( my_err
== -1 ) {
520 printf( "select call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
523 else if ( my_err
> 0 ) {
530 my_pollfd
.fd
= my_sockets
[1];
531 my_pollfd
.events
= (POLLIN
| POLLPRI
);
532 my_pollfd
.revents
= 0;
533 my_err
= poll( &my_pollfd
, 1, 500 );
534 if ( my_err
== -1 ) {
535 printf( "poll call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
538 /* should be ready for read */
539 if ( (my_pollfd
.revents
& POLLIN
) == 0 ) {
540 printf( "poll should have returned ready for read \n" );
544 my_count
= read( my_sockets
[1], &my_buffer
[0], sizeof(my_buffer
) );
545 if ( my_count
== -1 ) {
546 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
549 if ( my_buffer
[0] != 'd' ) {
550 printf( "read call on socket failed to get \"all done\" message \n" );
558 * parent process - wait for child to spin up
560 my_count
= read( my_sockets
[0], &my_buffer
[0], sizeof(my_buffer
) );
561 if ( my_count
== -1 ) {
562 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
563 goto test_failed_exit
;
565 if ( my_buffer
[0] != 'r' ) {
566 printf( "read call on socket failed to get \"ready to go message\" \n" );
567 goto test_failed_exit
;
570 /* tell child we're done */
571 write( my_sockets
[0], "d", 1 );
573 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
574 if ( my_wait_pid
== -1 ) {
575 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
576 goto test_failed_exit
;
579 /* wait4 should return our child's pid when it exits */
580 if ( my_wait_pid
!= my_pid
) {
581 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid
, my_pid
);
582 goto test_failed_exit
;
585 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
586 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status
);
587 goto test_failed_exit
;
591 goto test_passed_exit
;
597 if ( my_sockets
[0] != -1 )
598 close( my_sockets
[0] );
599 if ( my_sockets
[1] != -1 )
600 close( my_sockets
[1] );