1/*
2 *  socket_tests.c
3 *  xnu_quick_test
4 *
5 *  Created by Jerry Cottingham on 4/12/05.
6 *  Copyright 2005 Apple Computer Inc. All rights reserved.
7 *
8 */
9
10#include "tests.h"
11#include <poll.h>
12#include <mach/mach.h>
13
14extern char  g_target_path[ PATH_MAX ];
15
16/*  **************************************************************************************************************
17 *	Test accept, bind, connect, listen, socket, recvmsg, sendmsg, recvfrom, sendto, getpeername, getsockname
18 *  system calls.
19 *  WARNING - I don't do networking - this should get a good look from a networking stud.
20 *  **************************************************************************************************************
21 */
22int socket_tests( void * the_argp )
23{
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;
32	ssize_t			my_result;
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];
37	kern_return_t           my_kr;
38
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;
44        }
45
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;
50	}
51
52	*my_parent_pathp = 0x00;
53	strcat( my_parent_pathp, "/tmp/" );
54
55	/* get a unique name for our testing */
56	my_err = create_random_name( my_parent_pathp, 0 );
57	if ( my_err != 0 ) {
58		goto test_failed_exit;
59	}
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" */
63
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) );
66
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 );
73
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 );
79
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;
85	}
86	my_sockaddr = (struct sockaddr *) &my_parent_socket_name[0];
87	my_err = bind( my_socket_fd, my_sockaddr, my_sockaddr->sa_len );
88	if ( my_err == -1 ) {
89		printf( "bind call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
90		goto test_failed_exit;
91	}
92
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 );
97	if ( my_err == -1 ) {
98		printf( "getsockname call in child failed with error %d - \"%s\" \n", errno, strerror( errno) );
99		goto test_failed_exit;
100	}
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;
104	}
105
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;
111	}
112
113	/*
114	 * spin off a child process that we communicate with via sockets.
115	 */
116	my_pid = fork( );
117	if ( my_pid == -1 ) {
118		printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
119		goto test_failed_exit;
120	}
121	if ( my_pid == 0 ) {
122		/*
123		 * child process - open a socket and use it to talk to our parent.
124		 */
125		int					my_child_fd = -1;
126		struct msghdr		my_msghdr;
127		struct iovec		my_iov[4];
128		char				my_buffer[128];
129
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) );
133			exit( -1 );
134		}
135
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) );
141			exit( -1 );
142		}
143		sleep(2);
144
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) );
151			exit( -1 );
152		}
153
154	/* get some data from the child via socket and test socket peer data */
155	{
156		socklen_t			my_buffer_len;
157		struct sockaddr *	my_sockaddr;
158		char				my_parent_buffer[256];
159
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;
166		}
167
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;
172		}
173	}
174
175		my_buffer[0] = 'j';
176		my_iov[0].iov_base = &my_buffer[0];
177		my_iov[0].iov_len = 1;
178
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;
187
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 );
192			exit( -1 );
193		}
194
195#if 1
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 );
202			exit( -1 );
203		}
204
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 );
209			exit( -1 );
210		}
211#endif
212
213		/* sendfile test. Open libsystem, set up some headers, and send it */
214		struct sf_hdtr		my_sf_hdtr;
215		int					my_libsys_fd;
216		off_t				my_libsys_len;
217
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 );
222			exit ( -1 );
223		}
224
225		my_libsys_len = 7+2; /* 2 bytes of header */
226		my_buffer[0] = 's';
227		my_iov[0].iov_base = &my_buffer[0];
228		my_iov[0].iov_len = 1;
229		my_buffer[1] = 'e';
230		my_iov[1].iov_base = &my_buffer[1];
231		my_iov[1].iov_len = 1;
232		my_buffer[2] = 'n';
233		my_iov[2].iov_base = &my_buffer[2];
234		my_iov[2].iov_len = 1;
235		my_buffer[3] = 'd';
236		my_iov[3].iov_base = &my_buffer[3];
237		my_iov[3].iov_len = 1;
238
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;
243
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 );
248			exit( -1 );
249		}
250
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 );
255			exit ( -1 );
256		}
257
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 );
262			exit( -1 );
263		}
264
265		close( my_child_fd );
266		exit(0);
267	}
268
269	/*
270	 * parent process - listen for connection requests
271	 */
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;
276	}
277
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;
284	}
285
286	/* get some data from the child via socket and test socket peer data */
287	{
288		//socklen_t			my_buffer_len;
289		struct msghdr		my_msghdr;
290		struct iovec		my_iov;
291		char				my_parent_buffer[128];
292
293		my_parent_buffer[0] = 'x';
294		my_iov.iov_base = &my_parent_buffer[0];
295		my_iov.iov_len = 1;
296
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;
304
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;
309		}
310
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;
315		}
316
317#if 1
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;
326		}
327#endif
328
329		size_t neededBytes = 11;
330
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) {
339				break;
340			}
341			neededBytes -= my_result;
342		}
343
344		if ( neededBytes > 0 ) {
345			printf( "read call returned %ld bytes instead of 11\n", 11 - neededBytes );
346			goto test_failed_exit;
347		}
348
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;
352		}
353
354
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;
361		}
362		if ( strcmp( "all done", &my_parent_buffer[0] ) != 0 ) {
363			printf( "read wrong message from child \n" );
364			goto test_failed_exit;
365		}
366	}
367
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;
373	}
374
375	if ( WIFEXITED( my_status ) && WEXITSTATUS( my_status ) != 0 ) {
376		goto test_failed_exit;
377	}
378
379	my_err = 0;
380	goto test_passed_exit;
381
382test_failed_exit:
383	my_err = -1;
384
385test_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);
393	 }
394	if ( my_child_pathp != NULL ) {
395		remove( my_child_pathp );
396		vm_deallocate(mach_task_self(), (vm_address_t)my_child_pathp, 128);
397	 }
398	return( my_err );
399}
400
401/*  **************************************************************************************************************
402 *	Test fsync, getsockopt, poll, select, setsockopt, socketpair system calls.
403 *  **************************************************************************************************************
404 */
405int socket2_tests( void * the_argp )
406{
407	int					my_err, my_status;
408	int					my_sockets[ 2 ] = {-1, -1};
409	pid_t				my_pid, my_wait_pid;
410	ssize_t				my_count;
411	socklen_t			my_socklen;
412	struct timeval *	my_tvp;
413	struct timeval		my_orig_tv;
414	char				my_buffer[ 32 ];
415
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;
420	}
421
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;
428	}
429	if ( SOCK_STREAM != *((int *)&my_buffer[0]) ) {
430		printf( "getsockopt returned incorrect socket type \n" );
431		goto test_failed_exit;
432	}
433
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;
440	}
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;
444
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;
450	}
451
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;
458	}
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;
463	}
464
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;
470	}
471
472	/* test fsync - should fail when used with a socket fd */
473	errno = 0;
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;
478	}
479	else if ( my_err != -1 ) {
480		printf( "fsync should have failed with errno ENOTSUP \n" );
481		goto test_failed_exit;
482	}
483
484	/*
485	 * spin off a child process that we will talk to via our socketpair.
486	 */
487	my_pid = fork( );
488	if ( my_pid == -1 ) {
489		printf( "fork failed with errno %d - %s \n", errno, strerror( errno ) );
490		goto test_failed_exit;
491	}
492	if ( my_pid == 0 ) {
493		/*
494		 * child process - tell parent we are ready to go.
495		 */
496		char			my_buffer[ 32 ];
497		struct pollfd	my_pollfd;
498
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 ) );
502			exit( -1 );
503		}
504
505		/* test select by using it to wait for message from parent */
506		for ( ;; ) {
507			fd_set			my_read_set;
508			struct timeval	my_timeout;
509
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;
514
515			/* check to see if we are done, if no message is ready after a second
516			 * return and try again...
517			 */
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) );
521				exit( -1 );
522			}
523			else if ( my_err > 0 ) {
524				/* we're done */
525				break;
526			}
527		}
528
529		/* test poll too */
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) );
536			exit( -1 );
537		}
538		/* should be ready for read */
539		if ( (my_pollfd.revents & POLLIN) == 0 ) {
540			printf( "poll should have returned ready for read \n" );
541			exit( -1 );
542		}
543
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) );
547			exit( -1 );
548		}
549		if ( my_buffer[0] != 'd' ) {
550			printf( "read call on socket failed to get \"all done\" message \n" );
551			exit( -1 );
552		}
553
554		exit(0);
555	}
556
557	/*
558	 * parent process - wait for child to spin up
559	 */
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;
564	}
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;
568	}
569
570	/* tell child we're done */
571	write( my_sockets[0], "d", 1 );
572
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;
577	}
578
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;
583	}
584
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;
588	}
589
590	my_err = 0;
591	goto test_passed_exit;
592
593test_failed_exit:
594	my_err = -1;
595
596test_passed_exit:
597	if ( my_sockets[0] != -1 )
598		close( my_sockets[0] );
599	if ( my_sockets[1] != -1 )
600		close( my_sockets[1] );
601	return( my_err );
602}
603
604