1/*-
2 * Copyright (c) 2008-2009 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD$
27 */
28
29#include <sys/types.h>
30#include <sys/socket.h>
31
32#include <netinet/in.h>
33
34#include <arpa/inet.h>
35
36#include <err.h>
37#include <getopt.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <sysexits.h>
42#include <unistd.h>
43
44#include "tcpp.h"
45
46#define	BYTES_DEFAULT	10*1024*1024	/* Data per connection. */
47#define	MAXTCPS_DEFAULT	32		/* Number of TCPs at a time per proc. */
48#define	PROCS_DEFAULT	1		/* Processes used in run. */
49#define	TCPS_DEFAULT	1		/* Number of connections per process. */
50#define	BASEPORT_DEFAULT	10000
51
52struct sockaddr_in remoteip; 		/* Base target address. */
53struct sockaddr_in localipbase;		/* Base local address, if -l. */
54int cflag, hflag, lflag, mflag, pflag, sflag, tflag, Mflag, Pflag;
55uint64_t bflag;
56u_short rflag;
57
58static void
59usage(void)
60{
61
62	fprintf(stderr, "client: tcpp"
63	    " -c remoteIP"
64	    " [-h]"
65	    " [-P]"
66	    " [-M localIPcount]"
67	    " [-l localIPbase]"
68	    "\n\t"
69	    " [-b bytespertcp]"
70	    " [-m maxtcpsatonce]"
71	    " [-p procs]"
72	    " [-t tcpsperproc]"
73	    "\n"
74	    "\t"
75	    " [-r baseport]"
76	    "\n");
77
78	fprintf(stderr, "server: tcpp"
79	    " -s"
80	    " [-P]"
81	    " [-l localIPbase]"
82	    " [-m maxtcpsatonce]"
83	    " [-p procs]"
84	    "\n"
85	    "\t"
86	    " [-r baseport]"
87	    "\n");
88	exit(EX_USAGE);
89}
90
91int
92main(int argc, char *argv[])
93{
94	long long ll;
95	char *dummy;
96	int ch;
97
98	bzero(&localipbase, sizeof(localipbase));
99	localipbase.sin_len = sizeof(localipbase);
100	localipbase.sin_family = AF_INET;
101	localipbase.sin_addr.s_addr = htonl(INADDR_ANY);	/* Default. */
102	localipbase.sin_port = htons(0);				/* Default. */
103
104	bzero(&remoteip, sizeof(remoteip));
105	remoteip.sin_len = sizeof(remoteip);
106	remoteip.sin_family = AF_INET;
107	remoteip.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* Default. */
108	remoteip.sin_port = htons(0);				/* Default. */
109
110	bflag = BYTES_DEFAULT;
111	mflag = MAXTCPS_DEFAULT;
112	pflag = PROCS_DEFAULT;
113	rflag = BASEPORT_DEFAULT;
114	tflag = TCPS_DEFAULT;
115	Mflag = 1;
116	while ((ch = getopt(argc, argv, "b:c:hl:m:p:r:st:CM:PT")) != -1) {
117		switch (ch) {
118		case 'b':
119			ll = strtoll(optarg, &dummy, 10);
120			if (*dummy != '\0' || ll <= 0)
121				usage();
122			bflag = ll;
123			break;
124
125		case 'c':
126			cflag++;
127			if (inet_aton(optarg, &remoteip.sin_addr) != 1)
128				err(-1, "inet_aton: %s", optarg);
129			break;
130
131		case 'h':
132			hflag++;
133			break;
134
135		case 'l':
136			lflag++;
137			if (inet_aton(optarg, &localipbase.sin_addr) != 1)
138				err(-1, "inet_aton: %s", optarg);
139			break;
140
141		case 'm':
142			ll = strtoll(optarg, &dummy, 10);
143			if (*dummy != '\0' || ll <= 0)
144				usage();
145			mflag = ll;
146			break;
147
148		case 'p':
149			ll = strtoll(optarg, &dummy, 10);
150			if (*dummy != '\0' || ll <= 0)
151				usage();
152			pflag = ll;
153			break;
154
155		case 'r':
156			ll = strtol(optarg, &dummy, 10);
157			if (*dummy != '\0' || ll < 1 || ll > 65535)
158				usage();
159			rflag = ll;
160			break;
161
162		case 's':
163			sflag++;
164			break;
165
166		case 't':
167			ll = strtoll(optarg, &dummy, 10);
168			if (*dummy != '\0' || ll <= 0)
169				usage();
170			tflag = ll;
171			break;
172
173		case 'M':
174			ll = strtoll(optarg, &dummy, 10);
175			if (*dummy != '\0' || ll <= 1)
176				usage();
177			Mflag = ll;
178			break;
179
180		case 'P':
181#if defined(CPU_SETSIZE) && 0
182			Pflag++;
183			break;
184#else
185			errx(EX_USAGE, "-P current unsupported");
186#endif
187
188		default:
189			usage();
190		}
191	}
192
193	/* Exactly one of client and server. */
194	if (cflag > 1 || sflag > 1)
195		usage();
196	if ((cflag && sflag) || (!cflag && !sflag))
197		usage();
198
199	/* If Mflag is specified, we must have the lflag for a local IP. */
200	if (Mflag > 1 && !lflag)
201		usage();
202
203	/* Several flags are valid only on the client, disallow if server. */
204	if (sflag && (hflag || Mflag > 1))
205		usage();
206
207	if (cflag)
208		tcpp_client();
209	else
210		tcpp_server();
211	exit(0);
212}
213