1189623Srwatson/*-
2189623Srwatson * Copyright (c) 2008-2009 Robert N. M. Watson
3189623Srwatson * All rights reserved.
4189623Srwatson *
5189623Srwatson * Redistribution and use in source and binary forms, with or without
6189623Srwatson * modification, are permitted provided that the following conditions
7189623Srwatson * are met:
8189623Srwatson * 1. Redistributions of source code must retain the above copyright
9189623Srwatson *    notice, this list of conditions and the following disclaimer.
10189623Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11189623Srwatson *    notice, this list of conditions and the following disclaimer in the
12189623Srwatson *    documentation and/or other materials provided with the distribution.
13189623Srwatson *
14189623Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15189623Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16189623Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17189623Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18189623Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19189623Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20189623Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21189623Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22189623Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23189623Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24189623Srwatson * SUCH DAMAGE.
25189623Srwatson *
26189623Srwatson * $FreeBSD$
27189623Srwatson */
28189623Srwatson
29189623Srwatson#include <sys/types.h>
30189623Srwatson#include <sys/socket.h>
31189623Srwatson
32189623Srwatson#include <netinet/in.h>
33189623Srwatson
34189623Srwatson#include <arpa/inet.h>
35189623Srwatson
36189623Srwatson#include <err.h>
37189623Srwatson#include <getopt.h>
38189623Srwatson#include <stdio.h>
39189623Srwatson#include <stdlib.h>
40189623Srwatson#include <string.h>
41189623Srwatson#include <sysexits.h>
42189623Srwatson#include <unistd.h>
43189623Srwatson
44189623Srwatson#include "tcpp.h"
45189623Srwatson
46189623Srwatson#define	BYTES_DEFAULT	10*1024*1024	/* Data per connection. */
47189623Srwatson#define	MAXTCPS_DEFAULT	32		/* Number of TCPs at a time per proc. */
48189623Srwatson#define	PROCS_DEFAULT	1		/* Processes used in run. */
49189623Srwatson#define	TCPS_DEFAULT	1		/* Number of connections per process. */
50189623Srwatson#define	BASEPORT_DEFAULT	10000
51189623Srwatson
52189623Srwatsonstruct sockaddr_in remoteip; 		/* Base target address. */
53189623Srwatsonstruct sockaddr_in localipbase;		/* Base local address, if -l. */
54208873Srwatsonint cflag, hflag, lflag, mflag, pflag, sflag, tflag, Mflag, Pflag;
55189623Srwatsonuint64_t bflag;
56189623Srwatsonu_short rflag;
57189623Srwatson
58189623Srwatsonstatic void
59189623Srwatsonusage(void)
60189623Srwatson{
61189623Srwatson
62189623Srwatson	fprintf(stderr, "client: tcpp"
63189623Srwatson	    " -c remoteIP"
64208873Srwatson	    " [-h]"
65208873Srwatson	    " [-P]"
66189623Srwatson	    " [-M localIPcount]"
67189623Srwatson	    " [-l localIPbase]"
68208859Srwatson	    "\n\t"
69189623Srwatson	    " [-b bytespertcp]"
70189623Srwatson	    " [-m maxtcpsatonce]"
71208859Srwatson	    " [-p procs]"
72208859Srwatson	    " [-t tcpsperproc]"
73189623Srwatson	    "\n"
74189623Srwatson	    "\t"
75189623Srwatson	    " [-r baseport]"
76189623Srwatson	    "\n");
77189623Srwatson
78189623Srwatson	fprintf(stderr, "server: tcpp"
79189623Srwatson	    " -s"
80208873Srwatson	    " [-P]"
81189623Srwatson	    " [-l localIPbase]"
82189623Srwatson	    " [-m maxtcpsatonce]"
83189623Srwatson	    " [-p procs]"
84208859Srwatson	    "\n"
85208859Srwatson	    "\t"
86189623Srwatson	    " [-r baseport]"
87189623Srwatson	    "\n");
88189623Srwatson	exit(EX_USAGE);
89189623Srwatson}
90189623Srwatson
91189623Srwatsonint
92189623Srwatsonmain(int argc, char *argv[])
93189623Srwatson{
94189623Srwatson	long long ll;
95189623Srwatson	char *dummy;
96189623Srwatson	int ch;
97189623Srwatson
98189623Srwatson	bzero(&localipbase, sizeof(localipbase));
99189623Srwatson	localipbase.sin_len = sizeof(localipbase);
100189623Srwatson	localipbase.sin_family = AF_INET;
101189623Srwatson	localipbase.sin_addr.s_addr = htonl(INADDR_ANY);	/* Default. */
102189623Srwatson	localipbase.sin_port = htons(0);				/* Default. */
103189623Srwatson
104189623Srwatson	bzero(&remoteip, sizeof(remoteip));
105189623Srwatson	remoteip.sin_len = sizeof(remoteip);
106189623Srwatson	remoteip.sin_family = AF_INET;
107189623Srwatson	remoteip.sin_addr.s_addr = htonl(INADDR_LOOPBACK); /* Default. */
108189623Srwatson	remoteip.sin_port = htons(0);				/* Default. */
109189623Srwatson
110189623Srwatson	bflag = BYTES_DEFAULT;
111189623Srwatson	mflag = MAXTCPS_DEFAULT;
112189623Srwatson	pflag = PROCS_DEFAULT;
113189623Srwatson	rflag = BASEPORT_DEFAULT;
114189623Srwatson	tflag = TCPS_DEFAULT;
115189623Srwatson	Mflag = 1;
116208873Srwatson	while ((ch = getopt(argc, argv, "b:c:hl:m:p:r:st:CM:PT")) != -1) {
117189623Srwatson		switch (ch) {
118189623Srwatson		case 'b':
119189623Srwatson			ll = strtoll(optarg, &dummy, 10);
120189623Srwatson			if (*dummy != '\0' || ll <= 0)
121189623Srwatson				usage();
122189623Srwatson			bflag = ll;
123189623Srwatson			break;
124189623Srwatson
125189623Srwatson		case 'c':
126189623Srwatson			cflag++;
127189623Srwatson			if (inet_aton(optarg, &remoteip.sin_addr) != 1)
128189623Srwatson				err(-1, "inet_aton: %s", optarg);
129189623Srwatson			break;
130189623Srwatson
131208873Srwatson		case 'h':
132208873Srwatson			hflag++;
133208873Srwatson			break;
134208873Srwatson
135189623Srwatson		case 'l':
136189623Srwatson			lflag++;
137189623Srwatson			if (inet_aton(optarg, &localipbase.sin_addr) != 1)
138189623Srwatson				err(-1, "inet_aton: %s", optarg);
139189623Srwatson			break;
140189623Srwatson
141189623Srwatson		case 'm':
142189623Srwatson			ll = strtoll(optarg, &dummy, 10);
143189623Srwatson			if (*dummy != '\0' || ll <= 0)
144189623Srwatson				usage();
145189623Srwatson			mflag = ll;
146189623Srwatson			break;
147189623Srwatson
148189623Srwatson		case 'p':
149189623Srwatson			ll = strtoll(optarg, &dummy, 10);
150189623Srwatson			if (*dummy != '\0' || ll <= 0)
151189623Srwatson				usage();
152189623Srwatson			pflag = ll;
153189623Srwatson			break;
154189623Srwatson
155189623Srwatson		case 'r':
156189623Srwatson			ll = strtol(optarg, &dummy, 10);
157189623Srwatson			if (*dummy != '\0' || ll < 1 || ll > 65535)
158189623Srwatson				usage();
159189623Srwatson			rflag = ll;
160189623Srwatson			break;
161189623Srwatson
162189623Srwatson		case 's':
163189623Srwatson			sflag++;
164189623Srwatson			break;
165189623Srwatson
166189623Srwatson		case 't':
167189623Srwatson			ll = strtoll(optarg, &dummy, 10);
168189623Srwatson			if (*dummy != '\0' || ll <= 0)
169189623Srwatson				usage();
170189623Srwatson			tflag = ll;
171189623Srwatson			break;
172189623Srwatson
173189623Srwatson		case 'M':
174189623Srwatson			ll = strtoll(optarg, &dummy, 10);
175189623Srwatson			if (*dummy != '\0' || ll <= 1)
176189623Srwatson				usage();
177189623Srwatson			Mflag = ll;
178189623Srwatson			break;
179189623Srwatson
180208859Srwatson		case 'P':
181208859Srwatson#if defined(CPU_SETSIZE) && 0
182208859Srwatson			Pflag++;
183208859Srwatson			break;
184208859Srwatson#else
185208859Srwatson			errx(EX_USAGE, "-P current unsupported");
186208859Srwatson#endif
187208859Srwatson
188189623Srwatson		default:
189189623Srwatson			usage();
190189623Srwatson		}
191189623Srwatson	}
192189623Srwatson
193189623Srwatson	/* Exactly one of client and server. */
194189623Srwatson	if (cflag > 1 || sflag > 1)
195189623Srwatson		usage();
196189623Srwatson	if ((cflag && sflag) || (!cflag && !sflag))
197189623Srwatson		usage();
198189623Srwatson
199189623Srwatson	/* If Mflag is specified, we must have the lflag for a local IP. */
200189623Srwatson	if (Mflag > 1 && !lflag)
201189623Srwatson		usage();
202189623Srwatson
203189623Srwatson	/* Several flags are valid only on the client, disallow if server. */
204208873Srwatson	if (sflag && (hflag || Mflag > 1))
205189623Srwatson		usage();
206189623Srwatson
207189623Srwatson	if (cflag)
208189623Srwatson		tcpp_client();
209189623Srwatson	else
210189623Srwatson		tcpp_server();
211189623Srwatson	exit(0);
212189623Srwatson}
213