]>
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.
13 extern char g_target_path
[ PATH_MAX
];
15 /* **************************************************************************************************************
16 * Test accept, bind, connect, listen, socket, recvmsg, sendmsg, recvfrom, sendto, getpeername, getsockname
18 * WARNING - I don't do networking - this should get a good look from a networking stud.
19 * **************************************************************************************************************
21 int socket_tests( void * the_argp
)
23 int my_err
, my_status
, my_len
;
24 pid_t my_pid
, my_wait_pid
;
25 int my_socket_fd
= -1;
26 int my_accepted_socket
= -1;
27 char * my_parent_pathp
= NULL
;
28 char * my_child_pathp
= NULL
;
29 socklen_t my_accept_len
;
30 struct sockaddr
*my_sockaddr
;
32 off_t my_current_offset
;
33 char my_parent_socket_name
[sizeof(struct sockaddr
) + 64];
34 char my_child_socket_name
[sizeof(struct sockaddr
) + 64];
35 char my_accept_buffer
[sizeof(struct sockaddr
) + 64];
37 /* generate 2 names for binding to the sockets (one socket in the parent and one in the child) */
38 my_parent_pathp
= (char *) malloc( 128 );
39 if ( my_parent_pathp
== NULL
) {
40 printf( "malloc failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
41 goto test_failed_exit
;
43 my_child_pathp
= (char *) malloc( 128 );
44 if ( my_child_pathp
== NULL
) {
45 printf( "malloc failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
46 goto test_failed_exit
;
49 *my_parent_pathp
= 0x00;
50 strcat( my_parent_pathp
, "/tmp/" );
52 /* get a unique name for our testing */
53 my_err
= create_random_name( my_parent_pathp
, 0 );
55 goto test_failed_exit
;
57 strcpy( my_child_pathp
, my_parent_pathp
);
58 strcat( my_parent_pathp
, "p" ); /* append 'p' to mean "parent" */
59 strcat( my_child_pathp
, "c" ); /* append 'c' to mean "child" */
61 memset( &my_parent_socket_name
[0], 0, sizeof(my_parent_socket_name
) );
62 memset( &my_child_socket_name
[0], 0, sizeof(my_child_socket_name
) );
64 /* use unique names we generated in /tmp/ */
65 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
66 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_parent_pathp
);
67 my_sockaddr
->sa_len
= my_len
;
68 my_sockaddr
->sa_family
= AF_UNIX
;
69 strcpy( &my_sockaddr
->sa_data
[0], my_parent_pathp
);
71 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
72 my_len
= sizeof(*my_sockaddr
) - sizeof(my_sockaddr
->sa_data
) + strlen(my_child_pathp
);
73 my_sockaddr
->sa_len
= my_len
;
74 my_sockaddr
->sa_family
= AF_UNIX
;
75 strcpy( &my_sockaddr
->sa_data
[0], my_child_pathp
);
77 /* set up socket for parent side */
78 my_socket_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
79 if ( my_socket_fd
== -1 ) {
80 printf( "socket call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
81 goto test_failed_exit
;
83 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
84 my_err
= bind( my_socket_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
86 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
87 goto test_failed_exit
;
90 /* test getsockname */
91 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
92 my_accept_len
= sizeof(my_accept_buffer
);
93 my_err
= getsockname( my_socket_fd
, my_sockaddr
, &my_accept_len
);
95 printf( "getsockname call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
96 goto test_failed_exit
;
98 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
99 printf( "getsockname test failed - did not get correct socket name data \n" );
100 goto test_failed_exit
;
103 /* make sure we can't seek on a socket */
104 my_current_offset
= lseek( my_socket_fd
, 0, SEEK_CUR
);
105 if ( my_current_offset
!= -1 ) {
106 printf( "lseek on socket should fail but did not \n" );
107 goto test_failed_exit
;
111 * spin off a child process that we communicate with via sockets.
114 if ( my_pid
== -1 ) {
115 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
116 goto test_failed_exit
;
120 * child process - open a socket and use it to talk to our parent.
122 int my_child_fd
= -1;
123 struct msghdr my_msghdr
;
127 my_child_fd
= socket( AF_UNIX
, SOCK_STREAM
, 0 );
128 if ( my_child_fd
== -1 ) {
129 printf( "socket call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
133 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
134 my_err
= bind( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
135 if ( my_err
== -1 ) {
136 close( my_child_fd
);
137 printf( "bind call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
142 /* connect to socket in our parent */
143 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
144 my_err
= connect( my_child_fd
, my_sockaddr
, my_sockaddr
->sa_len
);
145 if ( my_err
== -1 ) {
146 close( my_child_fd
);
147 printf( "connect call in child failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
151 /* get some data from the child via socket and test socket peer data */
153 socklen_t my_buffer_len
;
154 struct sockaddr
* my_sockaddr
;
155 char my_parent_buffer
[256];
157 my_sockaddr
= (struct sockaddr
*) &my_parent_buffer
[0];
158 my_buffer_len
= sizeof(my_parent_buffer
);
159 my_err
= getpeername( my_child_fd
, my_sockaddr
, &my_buffer_len
);
160 if ( my_err
== -1 ) {
161 printf( "getpeername call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
162 goto test_failed_exit
;
165 /* test results - should be sa_family == SOCK_STREAM and name should match my_child_pathp */
166 if ( my_sockaddr
->sa_family
!= SOCK_STREAM
) {
167 printf( "getpeername test failed - did not get correct peer data \n" );
168 goto test_failed_exit
;
173 my_iov
.iov_base
= &my_buffer
[0];
176 my_sockaddr
= (struct sockaddr
*) &my_parent_socket_name
[0];
177 my_msghdr
.msg_name
= my_sockaddr
;
178 my_msghdr
.msg_namelen
= my_sockaddr
->sa_len
;
179 my_msghdr
.msg_iov
= &my_iov
;
180 my_msghdr
.msg_iovlen
= 1;
181 my_msghdr
.msg_control
= NULL
;
182 my_msghdr
.msg_controllen
= 0;
183 my_msghdr
.msg_flags
= 0;
185 my_result
= sendmsg( my_child_fd
, &my_msghdr
, 0 );
186 if ( my_result
== -1 ) {
187 printf( "sendmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
188 close( my_child_fd
);
193 /* get data from our parent */
194 my_result
= recvfrom( my_child_fd
, &my_buffer
[0], 1,
195 MSG_WAITALL
, NULL
, NULL
);
196 if ( my_result
== -1 ) {
197 printf( "recvfrom failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
198 close( my_child_fd
);
202 /* verify that we got the correct message from our child */
203 if ( my_buffer
[0] != 'e' ) {
204 printf( "test failed - did not get correct data from child \n" );
205 close( my_child_fd
);
210 /* tell parent we're done */
211 my_result
= write( my_child_fd
, "all done", 8 );
212 if ( my_result
== -1 ) {
213 close( my_child_fd
);
217 close( my_child_fd
);
222 * parent process - listen for connection requests
224 my_err
= listen( my_socket_fd
, 10 );
225 if ( my_err
== -1 ) {
226 printf( "listen call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
227 goto test_failed_exit
;
230 /* accept connection from child */
231 my_sockaddr
= (struct sockaddr
*) &my_accept_buffer
[0];
232 my_accepted_socket
= accept( my_socket_fd
, my_sockaddr
, &my_accept_len
);
233 if ( my_accepted_socket
== -1 ) {
234 printf( "accept call in parent failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
235 goto test_failed_exit
;
238 /* get some data from the child via socket and test socket peer data */
240 //socklen_t my_buffer_len;
241 struct msghdr my_msghdr
;
243 char my_parent_buffer
[128];
245 my_parent_buffer
[0] = 'x';
246 my_iov
.iov_base
= &my_parent_buffer
[0];
249 my_msghdr
.msg_name
= &my_accept_buffer
[0];
250 my_msghdr
.msg_namelen
= my_accept_len
;
251 my_msghdr
.msg_iov
= &my_iov
;
252 my_msghdr
.msg_iovlen
= 1;
253 my_msghdr
.msg_control
= NULL
;
254 my_msghdr
.msg_controllen
= 0;
255 my_msghdr
.msg_flags
= 0;
257 my_result
= recvmsg( my_accepted_socket
, &my_msghdr
, MSG_WAITALL
);
258 if ( my_result
== -1 ) {
259 printf( "recvmsg failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
260 goto test_failed_exit
;
263 /* verify that we got the correct message from our child */
264 if ( my_parent_buffer
[0] != 'j' ) {
265 printf( "test failed - did not get correct data from child \n" );
266 goto test_failed_exit
;
270 /* now send some data to our child */
271 my_parent_buffer
[0] = 'e';
272 my_sockaddr
= (struct sockaddr
*) &my_child_socket_name
[0];
273 my_result
= sendto( my_accepted_socket
, &my_parent_buffer
[0], 1, 0, my_sockaddr
,
274 my_sockaddr
->sa_len
);
275 if ( my_result
== -1 ) {
276 printf( "sendto failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
277 goto test_failed_exit
;
281 /* see if child is done */
282 bzero( (void *)&my_parent_buffer
[0], sizeof(my_parent_buffer
) );
283 my_result
= read( my_accepted_socket
, &my_parent_buffer
[0], sizeof(my_parent_buffer
) );
284 if ( my_result
== -1 ) {
285 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
286 goto test_failed_exit
;
288 if ( strcmp( "all done", &my_parent_buffer
[0] ) != 0 ) {
289 printf( "read wrong message from child \n" );
290 goto test_failed_exit
;
294 /* wait for child to exit */
295 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
296 if ( my_wait_pid
== -1 ) {
297 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
298 goto test_failed_exit
;
301 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
302 goto test_failed_exit
;
306 goto test_passed_exit
;
312 if ( my_socket_fd
!= -1 )
313 close( my_socket_fd
);
314 if ( my_accepted_socket
!= -1 )
315 close( my_accepted_socket
);
316 if ( my_parent_pathp
!= NULL
) {
317 remove( my_parent_pathp
);
318 free( my_parent_pathp
);
320 if ( my_child_pathp
!= NULL
) {
321 remove( my_child_pathp
);
322 free( my_child_pathp
);
327 /* **************************************************************************************************************
328 * Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
329 * **************************************************************************************************************
331 int socket2_tests( void * the_argp
)
333 int my_err
, my_status
;
334 int my_sockets
[ 2 ] = {-1, -1};
335 pid_t my_pid
, my_wait_pid
;
337 socklen_t my_socklen
;
338 struct timeval
* my_tvp
;
339 struct timeval my_orig_tv
;
340 char my_buffer
[ 32 ];
342 my_err
= socketpair( AF_UNIX
, SOCK_STREAM
, 0, &my_sockets
[0] );
343 if ( my_err
== -1 ) {
344 printf( "socketpair failed with errno %d - %s \n", errno
, strerror( errno
) );
345 goto test_failed_exit
;
348 /* test getsockopt and setsockopt */
349 my_socklen
= sizeof( my_buffer
);
350 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_TYPE
, &my_buffer
[0], &my_socklen
);
351 if ( my_err
== -1 ) {
352 printf( "getsockopt - SO_TYPE - failed with errno %d - %s \n", errno
, strerror( errno
) );
353 goto test_failed_exit
;
355 if ( SOCK_STREAM
!= *((int *)&my_buffer
[0]) ) {
356 printf( "getsockopt returned incorrect socket type \n" );
357 goto test_failed_exit
;
360 /* get and set receive timeout */
361 my_socklen
= sizeof( my_buffer
);
362 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
363 if ( my_err
== -1 ) {
364 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
365 goto test_failed_exit
;
367 my_tvp
= (struct timeval
*) &my_buffer
[0];
368 my_orig_tv
.tv_sec
= my_tvp
->tv_sec
;
369 my_orig_tv
.tv_usec
= my_tvp
->tv_usec
;
371 my_tvp
->tv_sec
+= 60;
372 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], sizeof(struct timeval
) );
373 if ( my_err
== -1 ) {
374 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
375 goto test_failed_exit
;
378 /* verify we set it */
379 my_socklen
= sizeof( my_buffer
);
380 my_err
= getsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_buffer
[0], &my_socklen
);
381 if ( my_err
== -1 ) {
382 printf( "getsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
383 goto test_failed_exit
;
385 my_tvp
= (struct timeval
*) &my_buffer
[0];
386 if ( my_tvp
->tv_sec
!= (my_orig_tv
.tv_sec
+ 60) || my_tvp
->tv_usec
!= my_orig_tv
.tv_usec
) {
387 printf( "setsockopt - SO_RCVTIMEO - did not set correct timeval \n" );
388 goto test_failed_exit
;
391 /* set back to original receive timeout */
392 my_err
= setsockopt( my_sockets
[0], SOL_SOCKET
, SO_RCVTIMEO
, &my_orig_tv
, sizeof(struct timeval
) );
393 if ( my_err
== -1 ) {
394 printf( "setsockopt - SO_RCVTIMEO - failed with errno %d - %s \n", errno
, strerror( errno
) );
395 goto test_failed_exit
;
398 /* test fsync - should fail when used with a socket fd */
400 my_err
= fsync( my_sockets
[0] );
401 if ( my_err
== -1 && errno
!= ENOTSUP
) {
402 printf( "fsync failed with errno %d - %s \n", errno
, strerror( errno
) );
403 goto test_failed_exit
;
405 else if ( my_err
!= -1 ) {
406 printf( "fsync should have failed with errno ENOTSUP \n" );
407 goto test_failed_exit
;
411 * spin off a child process that we will talk to via our socketpair.
414 if ( my_pid
== -1 ) {
415 printf( "fork failed with errno %d - %s \n", errno
, strerror( errno
) );
416 goto test_failed_exit
;
420 * child process - tell parent we are ready to go.
422 char my_buffer
[ 32 ];
423 struct pollfd my_pollfd
;
425 my_count
= write( my_sockets
[1], "r", 1 );
426 if ( my_count
== -1 ) {
427 printf( "write call failed. got errno %d - %s. \n", errno
, strerror( errno
) );
431 /* test select by using it to wait for message from parent */
434 struct timeval my_timeout
;
436 FD_ZERO( &my_read_set
);
437 FD_SET( my_sockets
[1], &my_read_set
);
438 timerclear( &my_timeout
);
439 my_timeout
.tv_sec
= 1;
441 /* check to see if we are done, if no message is ready after a second
442 * return and try again...
444 my_err
= select( (my_sockets
[1] + 1), &my_read_set
, NULL
, NULL
, &my_timeout
);
445 if ( my_err
== -1 ) {
446 printf( "select call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
449 else if ( my_err
> 0 ) {
456 my_pollfd
.fd
= my_sockets
[1];
457 my_pollfd
.events
= (POLLIN
| POLLPRI
);
458 my_pollfd
.revents
= 0;
459 my_err
= poll( &my_pollfd
, 1, 500 );
460 if ( my_err
== -1 ) {
461 printf( "poll call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
464 /* should be ready for read */
465 if ( (my_pollfd
.revents
& POLLIN
) == 0 ) {
466 printf( "poll should have returned ready for read \n" );
470 my_count
= read( my_sockets
[1], &my_buffer
[0], sizeof(my_buffer
) );
471 if ( my_count
== -1 ) {
472 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
475 if ( my_buffer
[0] != 'd' ) {
476 printf( "read call on socket failed to get \"all done\" message \n" );
484 * parent process - wait for child to spin up
486 my_count
= read( my_sockets
[0], &my_buffer
[0], sizeof(my_buffer
) );
487 if ( my_count
== -1 ) {
488 printf( "read call failed with error %d - \"%s\" \n", errno
, strerror( errno
) );
489 goto test_failed_exit
;
491 if ( my_buffer
[0] != 'r' ) {
492 printf( "read call on socket failed to get \"ready to go message\" \n" );
493 goto test_failed_exit
;
496 /* tell child we're done */
497 write( my_sockets
[0], "d", 1 );
499 my_wait_pid
= wait4( my_pid
, &my_status
, 0, NULL
);
500 if ( my_wait_pid
== -1 ) {
501 printf( "wait4 failed with errno %d - %s \n", errno
, strerror( errno
) );
502 goto test_failed_exit
;
505 /* wait4 should return our child's pid when it exits */
506 if ( my_wait_pid
!= my_pid
) {
507 printf( "wait4 did not return child pid - returned %d should be %d \n", my_wait_pid
, my_pid
);
508 goto test_failed_exit
;
511 if ( WIFEXITED( my_status
) && WEXITSTATUS( my_status
) != 0 ) {
512 printf( "wait4 returned wrong exit status - 0x%02X \n", my_status
);
513 goto test_failed_exit
;
517 goto test_passed_exit
;
523 if ( my_sockets
[0] != -1 )
524 close( my_sockets
[0] );
525 if ( my_sockets
[1] != -1 )
526 close( my_sockets
[1] );