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