xref: /freebsd/tools/regression/netinet/tcpsockclosebeforeaccept/tcpsockclosebeforeaccept.c (revision 4f29da19bd44f0e99f021510460a81bf754c21d2)
14f29da19SRobert Watson /*-
24f29da19SRobert Watson  * Copyright (c) 2006 Robert N. M. Watson
34f29da19SRobert Watson  * All rights reserved.
44f29da19SRobert Watson  *
54f29da19SRobert Watson  * Redistribution and use in source and binary forms, with or without
64f29da19SRobert Watson  * modification, are permitted provided that the following conditions
74f29da19SRobert Watson  * are met:
84f29da19SRobert Watson  * 1. Redistributions of source code must retain the above copyright
94f29da19SRobert Watson  *    notice, this list of conditions and the following disclaimer.
104f29da19SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
114f29da19SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
124f29da19SRobert Watson  *    documentation and/or other materials provided with the distribution.
134f29da19SRobert Watson  *
144f29da19SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
154f29da19SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
164f29da19SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
174f29da19SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
184f29da19SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
194f29da19SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
204f29da19SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
214f29da19SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
224f29da19SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
234f29da19SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
244f29da19SRobert Watson  * SUCH DAMAGE.
254f29da19SRobert Watson  *
264f29da19SRobert Watson  * $FreeBSD$
274f29da19SRobert Watson  */
284f29da19SRobert Watson 
294f29da19SRobert Watson /*
304f29da19SRobert Watson  * TCP regression test which opens a loopback TCP session, and closes it
314f29da19SRobert Watson  * before the remote endpoint (server) can accept it.
324f29da19SRobert Watson  */
334f29da19SRobert Watson 
344f29da19SRobert Watson #include <sys/types.h>
354f29da19SRobert Watson #include <sys/socket.h>
364f29da19SRobert Watson 
374f29da19SRobert Watson #include <netinet/in.h>
384f29da19SRobert Watson 
394f29da19SRobert Watson #include <err.h>
404f29da19SRobert Watson #include <errno.h>
414f29da19SRobert Watson #include <signal.h>
424f29da19SRobert Watson #include <stdio.h>
434f29da19SRobert Watson #include <stdlib.h>
444f29da19SRobert Watson #include <string.h>
454f29da19SRobert Watson #include <unistd.h>
464f29da19SRobert Watson 
474f29da19SRobert Watson #define	TCP_PORT	9001
484f29da19SRobert Watson 
494f29da19SRobert Watson static void
504f29da19SRobert Watson tcp_server(pid_t partner)
514f29da19SRobert Watson {
524f29da19SRobert Watson 	int error, listen_fd, accept_fd;
534f29da19SRobert Watson 	struct sockaddr_in sin;
544f29da19SRobert Watson 
554f29da19SRobert Watson 	listen_fd = socket(PF_INET, SOCK_STREAM, 0);
564f29da19SRobert Watson 	if (listen_fd < 0) {
574f29da19SRobert Watson 		error = errno;
584f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
594f29da19SRobert Watson 		errno = error;
604f29da19SRobert Watson 		err(-1, "tcp_server: socket");
614f29da19SRobert Watson 	}
624f29da19SRobert Watson 
634f29da19SRobert Watson 	bzero(&sin, sizeof(sin));
644f29da19SRobert Watson 	sin.sin_family = AF_INET;
654f29da19SRobert Watson 	sin.sin_len = sizeof(sin);
664f29da19SRobert Watson 	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
674f29da19SRobert Watson 	sin.sin_port = htons(TCP_PORT);
684f29da19SRobert Watson 
694f29da19SRobert Watson 	if (bind(listen_fd, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
704f29da19SRobert Watson 		error = errno;
714f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
724f29da19SRobert Watson 		errno = error;
734f29da19SRobert Watson 		err(-1, "tcp_server: bind");
744f29da19SRobert Watson 	}
754f29da19SRobert Watson 
764f29da19SRobert Watson 	if (listen(listen_fd, -1) < 0) {
774f29da19SRobert Watson 		error = errno;
784f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
794f29da19SRobert Watson 		errno = error;
804f29da19SRobert Watson 		err(-1, "tcp_server: listen");
814f29da19SRobert Watson 	}
824f29da19SRobert Watson 
834f29da19SRobert Watson 	sleep(10);
844f29da19SRobert Watson 
854f29da19SRobert Watson 	accept_fd = accept(listen_fd, NULL, NULL);
864f29da19SRobert Watson 	if (accept_fd < 0) {
874f29da19SRobert Watson 		error = errno;
884f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
894f29da19SRobert Watson 		errno = error;
904f29da19SRobert Watson 		err(-1, "tcp_server: accept");
914f29da19SRobert Watson 	}
924f29da19SRobert Watson 	close(accept_fd);
934f29da19SRobert Watson 	close(listen_fd);
944f29da19SRobert Watson }
954f29da19SRobert Watson 
964f29da19SRobert Watson static void
974f29da19SRobert Watson tcp_client(pid_t partner)
984f29da19SRobert Watson {
994f29da19SRobert Watson 	struct sockaddr_in sin;
1004f29da19SRobert Watson 	int error, sock;
1014f29da19SRobert Watson 
1024f29da19SRobert Watson 	sleep(1);
1034f29da19SRobert Watson 
1044f29da19SRobert Watson 	sock = socket(PF_INET, SOCK_STREAM, 0);
1054f29da19SRobert Watson 	if (sock < 0) {
1064f29da19SRobert Watson 		error = errno;
1074f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
1084f29da19SRobert Watson 		errno = error;
1094f29da19SRobert Watson 		err(-1, "socket");
1104f29da19SRobert Watson 	}
1114f29da19SRobert Watson 
1124f29da19SRobert Watson 	bzero(&sin, sizeof(sin));
1134f29da19SRobert Watson 	sin.sin_family = AF_INET;
1144f29da19SRobert Watson 	sin.sin_len = sizeof(sin);
1154f29da19SRobert Watson 	sin.sin_addr.s_addr = ntohl(INADDR_LOOPBACK);
1164f29da19SRobert Watson 	sin.sin_port = htons(TCP_PORT);
1174f29da19SRobert Watson 
1184f29da19SRobert Watson 	if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
1194f29da19SRobert Watson 		error = errno;
1204f29da19SRobert Watson 		(void)kill(partner, SIGKILL);
1214f29da19SRobert Watson 		errno = error;
1224f29da19SRobert Watson 		err(-1, "connect");
1234f29da19SRobert Watson 	}
1244f29da19SRobert Watson 
1254f29da19SRobert Watson 	close(sock);
1264f29da19SRobert Watson }
1274f29da19SRobert Watson 
1284f29da19SRobert Watson int
1294f29da19SRobert Watson main(int argc, char *argv[])
1304f29da19SRobert Watson {
1314f29da19SRobert Watson 	pid_t child_pid, parent_pid;
1324f29da19SRobert Watson 
1334f29da19SRobert Watson 	if (signal(SIGCHLD, SIG_IGN) == SIG_ERR)
1344f29da19SRobert Watson 		err(-1, "signal");
1354f29da19SRobert Watson 
1364f29da19SRobert Watson 	parent_pid = getpid();
1374f29da19SRobert Watson 	child_pid = fork();
1384f29da19SRobert Watson 	if (child_pid < 0)
1394f29da19SRobert Watson 		err(-1, "fork");
1404f29da19SRobert Watson 	if (child_pid == 0) {
1414f29da19SRobert Watson 		child_pid = getpid();
1424f29da19SRobert Watson 		tcp_server(parent_pid);
1434f29da19SRobert Watson 	} else
1444f29da19SRobert Watson 		tcp_client(child_pid);
1454f29da19SRobert Watson 
1464f29da19SRobert Watson 	return (0);
1474f29da19SRobert Watson }
148