xref: /freebsd-src/tools/regression/netinet/tcpconnect/tcpconnect.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
16a671583SRobert Watson /*-
231ae0502SRobert Watson  * Copyright (c) 2004-2005 Robert N. M. Watson
36a671583SRobert Watson  * All rights reserved.
46a671583SRobert Watson  *
56a671583SRobert Watson  * Redistribution and use in source and binary forms, with or without
66a671583SRobert Watson  * modification, are permitted provided that the following conditions
76a671583SRobert Watson  * are met:
86a671583SRobert Watson  * 1. Redistributions of source code must retain the above copyright
96a671583SRobert Watson  *    notice, this list of conditions and the following disclaimer.
106a671583SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
116a671583SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
126a671583SRobert Watson  *    documentation and/or other materials provided with the distribution.
136a671583SRobert Watson  *
146a671583SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
156a671583SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
166a671583SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
176a671583SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
186a671583SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
196a671583SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
206a671583SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
216a671583SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
226a671583SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
236a671583SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
246a671583SRobert Watson  * SUCH DAMAGE.
256a671583SRobert Watson  */
266a671583SRobert Watson 
276a671583SRobert Watson #include <sys/types.h>
286a671583SRobert Watson #include <sys/socket.h>
296a671583SRobert Watson 
306a671583SRobert Watson #include <netinet/in.h>
31551944a2SBjoern A. Zeeb #include <netinet/tcp.h>
326a671583SRobert Watson 
336a671583SRobert Watson #include <arpa/inet.h>
346a671583SRobert Watson 
35*27d36ca1SRobert Watson #include <err.h>
36a09c60ffSRobert Watson #include <errno.h>
37551944a2SBjoern A. Zeeb #include <fcntl.h>
386a671583SRobert Watson #include <stdio.h>
396a671583SRobert Watson #include <stdlib.h>
406a671583SRobert Watson #include <string.h>
416a671583SRobert Watson #include <unistd.h>
426a671583SRobert Watson 
43551944a2SBjoern A. Zeeb 
446a671583SRobert Watson static void
usage(void)4530f4920bSRuslan Ermilov usage(void)
466a671583SRobert Watson {
476a671583SRobert Watson 
486a671583SRobert Watson 	fprintf(stderr, "tcpconnect server port\n");
49551944a2SBjoern A. Zeeb 	fprintf(stderr, "tcpconnect client ip port count [nonblock] [tcpmd5]\n");
506a671583SRobert Watson 	exit(-1);
516a671583SRobert Watson }
526a671583SRobert Watson 
536a671583SRobert Watson static void
tcpconnect_server(int argc,char * argv[])546a671583SRobert Watson tcpconnect_server(int argc, char *argv[])
556a671583SRobert Watson {
566a671583SRobert Watson 	int listen_sock, accept_sock;
576a671583SRobert Watson 	struct sockaddr_in sin;
586a671583SRobert Watson 	char *dummy;
596a671583SRobert Watson 	long port;
606a671583SRobert Watson 
616a671583SRobert Watson 	if (argc != 1)
626a671583SRobert Watson 		usage();
636a671583SRobert Watson 
646a671583SRobert Watson 	bzero(&sin, sizeof(sin));
656a671583SRobert Watson 	sin.sin_len = sizeof(sin);
666a671583SRobert Watson 	sin.sin_family = AF_INET;
676a671583SRobert Watson 	sin.sin_addr.s_addr = htonl(INADDR_ANY);
686a671583SRobert Watson 
696a671583SRobert Watson 	port = strtoul(argv[0], &dummy, 10);
706a671583SRobert Watson 	if (port < 1 || port > 65535 || *dummy != '\0')
716a671583SRobert Watson 		usage();
726a671583SRobert Watson 	sin.sin_port = htons(port);
736a671583SRobert Watson 
746a671583SRobert Watson 	listen_sock = socket(PF_INET, SOCK_STREAM, 0);
75a09c60ffSRobert Watson 	if (listen_sock == -1)
764f744c04SBjoern A. Zeeb 		err(-1, "socket");
776a671583SRobert Watson 
78a09c60ffSRobert Watson 	if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
794f744c04SBjoern A. Zeeb 		err(-1, "bind");
806a671583SRobert Watson 
81a09c60ffSRobert Watson 	if (listen(listen_sock, -1) == -1)
824f744c04SBjoern A. Zeeb 		err(-1, "listen");
836a671583SRobert Watson 
846a671583SRobert Watson 	while (1) {
856a671583SRobert Watson 		accept_sock = accept(listen_sock, NULL, NULL);
866a671583SRobert Watson 		close(accept_sock);
876a671583SRobert Watson 	}
886a671583SRobert Watson }
896a671583SRobert Watson 
906a671583SRobert Watson static void
tcpconnect_client(int argc,char * argv[])916a671583SRobert Watson tcpconnect_client(int argc, char *argv[])
926a671583SRobert Watson {
936a671583SRobert Watson 	struct sockaddr_in sin;
946a671583SRobert Watson 	long count, i, port;
956a671583SRobert Watson 	char *dummy;
966a671583SRobert Watson 	int sock;
97551944a2SBjoern A. Zeeb 	int nonblock = 0, md5enable = 0;
986a671583SRobert Watson 
99551944a2SBjoern A. Zeeb 	if (argc < 3 || argc > 5)
1006a671583SRobert Watson 		usage();
101551944a2SBjoern A. Zeeb 	for (i=3; i < argc; i++) {
102551944a2SBjoern A. Zeeb 		if (strcmp(argv[i], "nonblock") == 0)
103551944a2SBjoern A. Zeeb 			nonblock = 1;
104551944a2SBjoern A. Zeeb 		if (strcmp(argv[i], "tcpmd5") == 0)
105551944a2SBjoern A. Zeeb 			md5enable = 1;
106551944a2SBjoern A. Zeeb 	}
1076a671583SRobert Watson 
1086a671583SRobert Watson 	bzero(&sin, sizeof(sin));
1096a671583SRobert Watson 	sin.sin_len = sizeof(sin);
1106a671583SRobert Watson 	sin.sin_family = AF_INET;
111a09c60ffSRobert Watson 	if (inet_aton(argv[0], &sin.sin_addr) == 0)
1124f744c04SBjoern A. Zeeb 		err(-1, "listen");
1136a671583SRobert Watson 
1146a671583SRobert Watson 	port = strtoul(argv[1], &dummy, 10);
1156a671583SRobert Watson 	if (port < 1 || port > 65535 || *dummy != '\0')
1166a671583SRobert Watson 		usage();
1176a671583SRobert Watson 	sin.sin_port = htons(port);
1186a671583SRobert Watson 
1196a671583SRobert Watson 	count = strtoul(argv[2], &dummy, 10);
1206a671583SRobert Watson 	if (count < 1 || count > 100000 || *dummy != '\0')
1216a671583SRobert Watson 		usage();
1226a671583SRobert Watson 
1236a671583SRobert Watson 	for (i = 0; i < count; i++) {
1246a671583SRobert Watson 		sock = socket(PF_INET, SOCK_STREAM, 0);
125a09c60ffSRobert Watson 		if (sock == -1)
1264f744c04SBjoern A. Zeeb 			err(-1, "socket");
1276a671583SRobert Watson 
128551944a2SBjoern A. Zeeb 		/* No warning in default case on ENOPROTOOPT. */
129551944a2SBjoern A. Zeeb 		if (setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG,
130551944a2SBjoern A. Zeeb 		    &md5enable, sizeof(md5enable)) != 0) {
131551944a2SBjoern A. Zeeb 			if (errno == ENOPROTOOPT && md5enable > 0)
132551944a2SBjoern A. Zeeb 				err(-1, "setsockopt(TCP_MD5SIG)");
133551944a2SBjoern A. Zeeb 			else if (errno != ENOPROTOOPT)
134551944a2SBjoern A. Zeeb 				warn("setsockopt(TCP_MD5SIG)");
135551944a2SBjoern A. Zeeb 		}
136551944a2SBjoern A. Zeeb 
137551944a2SBjoern A. Zeeb 		if (nonblock) {
13831ae0502SRobert Watson 			if (fcntl(sock, F_SETFL, O_NONBLOCK) != 0)
1394f744c04SBjoern A. Zeeb 				err(-1, "fcntl(F_SETFL)");
14031ae0502SRobert Watson 
141551944a2SBjoern A. Zeeb 			if (connect(sock, (struct sockaddr *)&sin,
142551944a2SBjoern A. Zeeb 			    sizeof(sin)) == -1 && errno != EINPROGRESS)
1434f744c04SBjoern A. Zeeb 				err(-1, "connect");
144551944a2SBjoern A. Zeeb 		} else {
145551944a2SBjoern A. Zeeb 			if (connect(sock, (struct sockaddr *)&sin,
146551944a2SBjoern A. Zeeb 			    sizeof(sin)) == -1)
1474f744c04SBjoern A. Zeeb 				err(-1, "connect");
148551944a2SBjoern A. Zeeb 		}
1496a671583SRobert Watson 
1506a671583SRobert Watson 		close(sock);
1516a671583SRobert Watson 	}
1526a671583SRobert Watson }
1536a671583SRobert Watson 
1546a671583SRobert Watson int
main(int argc,char * argv[])1556a671583SRobert Watson main(int argc, char *argv[])
1566a671583SRobert Watson {
1576a671583SRobert Watson 
1586a671583SRobert Watson 	if (argc < 2)
1596a671583SRobert Watson 		usage();
1606a671583SRobert Watson 
1616a671583SRobert Watson 	if (strcmp(argv[1], "server") == 0)
1626a671583SRobert Watson 		tcpconnect_server(argc - 2, argv + 2);
1636a671583SRobert Watson 	else if (strcmp(argv[1], "client") == 0)
1646a671583SRobert Watson 		tcpconnect_client(argc - 2, argv + 2);
1656a671583SRobert Watson 	else
1666a671583SRobert Watson 		usage();
1676a671583SRobert Watson 
1686a671583SRobert Watson 	exit(0);
1696a671583SRobert Watson }
170