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