blob: 8b9a0a0a7070906ff7e85fce6a84f3540b429f0c [file] [log] [blame]
Willy Tarreau9557bac2016-11-12 17:53:16 +01001/*
2 * TCP client and server for bug hunting
3 *
4 * Copyright (C) 2016 Willy Tarreau <w@1wt.eu>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 */
26
Willy Tarreau84393aa2016-11-12 11:29:46 +010027#include <sys/resource.h>
28#include <sys/select.h>
29#include <sys/types.h>
30#include <sys/socket.h>
31#include <sys/stat.h>
32#include <sys/time.h>
33#include <sys/ioctl.h>
Willy Tarreau95a6b782016-11-12 13:25:53 +010034#include <sys/wait.h>
Willy Tarreau84393aa2016-11-12 11:29:46 +010035#include <arpa/inet.h>
36#include <netinet/in.h>
37#include <netinet/tcp.h>
38
39#include <ctype.h>
40#include <errno.h>
41#include <fcntl.h>
42#include <netdb.h>
43#include <poll.h>
44#include <signal.h>
45#include <stdarg.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <time.h>
50#include <unistd.h>
51
52
53struct err_msg {
54 int size;
55 int len;
56 char msg[0];
57};
58
59const int zero = 0;
60const int one = 1;
61const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
62
63#define TRASH_SIZE 65536
64static char trash[TRASH_SIZE];
65
Willy Tarreau95a6b782016-11-12 13:25:53 +010066volatile int nbproc = 0;
Willy Tarreau869c7592016-11-12 17:50:57 +010067static struct timeval start_time;
68static int showtime;
69static int verbose;
70static int pid;
71
Willy Tarreau95a6b782016-11-12 13:25:53 +010072
Willy Tarreau84393aa2016-11-12 11:29:46 +010073/* display the message and exit with the code */
74__attribute__((noreturn)) void die(int code, const char *format, ...)
75{
76 va_list args;
77
78 va_start(args, format);
79 vfprintf(stderr, format, args);
80 va_end(args);
81 exit(code);
82}
83
84/* display the usage message and exit with the code */
85__attribute__((noreturn)) void usage(int code, const char *arg0)
86{
Willy Tarreau9557bac2016-11-12 17:53:16 +010087 die(code,
88 "Usage : %s [options]* [<ip>:]port [<action>*]\n"
89 "\n"
90 "options :\n"
91 " -v : verbose\n"
92 " -t|-tt|-ttt : show time (msec / relative / absolute)\n"
93 "actions :\n"
94 " L[<backlog>] : Listens to ip:port and optionally sets backlog\n"
95 " Note: fd=socket,bind(fd),listen(fd)\n"
96 " C : Connects to ip:port\n"
97 " Note: fd=socket,connect(fd)\n"
98 " A[<count>] : Accepts <count> incoming sockets and closes count-1\n"
99 " Note: fd=accept(fd)\n"
100 " G : disable lingering\n"
101 " T : set TCP_NODELAY\n"
102 " Q : disable TCP Quick-ack\n"
103 " R[<size>] : Read this amount of bytes. 0=infinite. unset=any amount.\n"
104 " S[<size>] : Send this amount of bytes. 0=infinite. unset=any amount.\n"
Willy Tarreau59623e02016-11-12 18:25:45 +0100105 " S:<string> : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100106 " E[<size>] : Echo this amount of bytes. 0=infinite. unset=any amount.\n"
107 " W[<time>] : Wait for any event on the socket, maximum <time> ms\n"
108 " P[<time>] : Pause for <time> ms (100 by default)\n"
109 " I : wait for Input data to be present (POLLIN)\n"
110 " O : wait for Output queue to be empty (POLLOUT + TIOCOUTQ)\n"
111 " F : FIN : shutdown(SHUT_WR)\n"
112 " N<max> : fork New process, limited to <max> concurrent (default 1)\n"
113 "\n"
114 "It's important to note that a single FD is used at once and that Accept\n"
115 "replaces the listening FD with the accepted one. Thus always do it after\n"
116 "a fork if other connections have to be accepted.\n"
117 "\n"
118 "After a fork, we loop back to the beginning and silently skip L/C if the\n"
119 "main socket already exists.\n"
120 "\n"
121 "Example dummy HTTP request drain server :\n"
122 " tcploop 8001 L W N20 A R S10 [ F K ]\n"
123 "\n"
124 "Example large bandwidth HTTP request drain server :\n"
125 " tcploop 8001 L W N20 A R S0 [ F K ]\n"
126 "\n"
127 "Example TCP client with pauses at each step :\n"
128 " tcploop 8001 C T W P100 S10 O P100 R S10 O R G K\n"
129 "", arg0);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100130}
131
Willy Tarreau869c7592016-11-12 17:50:57 +0100132void dolog(const char *format, ...)
133{
134 struct timeval date, tv;
135 int delay;
136 va_list args;
137
138 if (!verbose)
139 return;
140
141 if (showtime) {
142 gettimeofday(&date, NULL);
143 switch (showtime) {
144 case 1: // [msec] relative
145 delay = (date.tv_sec - start_time.tv_sec) * 1000000 + date.tv_usec - start_time.tv_usec;
146 fprintf(stderr, "[%d] ", delay / 1000);
147 break;
148 case 2: // [sec.usec] relative
149 tv.tv_usec = date.tv_usec - start_time.tv_usec;
150 tv.tv_sec = date.tv_sec - start_time.tv_sec;
151 if ((signed)tv.tv_sec > 0) {
152 if ((signed)tv.tv_usec < 0) {
153 tv.tv_usec += 1000000;
154 tv.tv_sec--;
155 }
156 } else if (tv.tv_sec == 0) {
157 if ((signed)tv.tv_usec < 0)
158 tv.tv_usec = 0;
159 } else {
160 tv.tv_sec = 0;
161 tv.tv_usec = 0;
162 }
163 fprintf(stderr, "[%d.%06d] ", tv.tv_sec, tv.tv_usec);
164 break;
165 default: // [sec.usec] absolute
166 fprintf(stderr, "[%d.%06d] ", date.tv_sec, date.tv_usec);
167 break;
168 }
169 }
170
171 fprintf(stderr, "%5d ", pid);
172
173 va_start(args, format);
174 vfprintf(stderr, format, args);
175 va_end(args);
176}
177
Willy Tarreau59623e02016-11-12 18:25:45 +0100178/* convert '\n', '\t', '\r', '\\' to their respective characters */
179int unescape(char *out, int size, const char *in)
180{
181 int len;
182
183 for (len = 0; len < size && *in; in++, out++, len++) {
184 if (*in == '\\') {
185 switch (in[1]) {
186 case 'n' : *out = '\n'; in++; continue;
187 case 't' : *out = '\t'; in++; continue;
188 case 'r' : *out = '\r'; in++; continue;
189 case '\\' : *out = '\\'; in++; continue;
190 default : break;
191 }
192 }
193 *out = *in;
194 }
195 return len;
196}
197
Willy Tarreau84393aa2016-11-12 11:29:46 +0100198struct err_msg *alloc_err_msg(int size)
199{
200 struct err_msg *err;
201
202 err = malloc(sizeof(*err) + size);
203 if (err) {
204 err->len = 0;
205 err->size = size;
206 }
207 return err;
208}
209
Willy Tarreau95a6b782016-11-12 13:25:53 +0100210void sig_handler(int sig)
211{
212 if (sig == SIGCHLD) {
213 while (waitpid(-1, NULL, WNOHANG) > 0)
214 __sync_sub_and_fetch(&nbproc, 1);
215 }
216}
Willy Tarreau84393aa2016-11-12 11:29:46 +0100217
218/* converts str in the form [[<ipv4>|<ipv6>|<hostname>]:]port to struct sockaddr_storage.
219 * Returns < 0 with err set in case of error.
220 */
221int addr_to_ss(char *str, struct sockaddr_storage *ss, struct err_msg *err)
222{
223 char *port_str;
224 int port;
225
226 memset(ss, 0, sizeof(*ss));
227
228 /* look for the addr/port delimiter, it's the last colon. If there's no
229 * colon, it's 0:<port>.
230 */
231 if ((port_str = strrchr(str, ':')) == NULL) {
232 port = atoi(str);
233 if (port <= 0 || port > 65535) {
234 err->len = snprintf(err->msg, err->size, "Missing/invalid port number: '%s'\n", str);
235 return -1;
236 }
237
238 ss->ss_family = AF_INET;
239 ((struct sockaddr_in *)ss)->sin_port = htons(port);
240 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
241 return 0;
242 }
243
244 *port_str++ = 0;
245
246 if (strrchr(str, ':') != NULL) {
247 /* IPv6 address contains ':' */
248 ss->ss_family = AF_INET6;
249 ((struct sockaddr_in6 *)ss)->sin6_port = htons(atoi(port_str));
250
251 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in6 *)ss)->sin6_addr)) {
252 err->len = snprintf(err->msg, err->size, "Invalid server address: '%s'\n", str);
253 return -1;
254 }
255 }
256 else {
257 ss->ss_family = AF_INET;
258 ((struct sockaddr_in *)ss)->sin_port = htons(atoi(port_str));
259
260 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
261 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
262 return 0;
263 }
264
265 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in *)ss)->sin_addr)) {
266 struct hostent *he = gethostbyname(str);
267
268 if (he == NULL) {
269 err->len = snprintf(err->msg, err->size, "Invalid server name: '%s'\n", str);
270 return -1;
271 }
272 ((struct sockaddr_in *)ss)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
273 }
274 }
275
276 return 0;
277}
278
279/* waits up to one second on fd <fd> for events <events> (POLLIN|POLLOUT).
280 * returns poll's status.
281 */
282int wait_on_fd(int fd, int events)
283{
284 struct pollfd pollfd;
285 int ret;
286
287 do {
288 pollfd.fd = fd;
289 pollfd.events = events;
290 ret = poll(&pollfd, 1, 1000);
291 } while (ret == -1 && errno == EINTR);
292
293 return ret;
294}
295
296int tcp_set_nodelay(int sock, const char *arg)
297{
298 return setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
299}
300
301int tcp_set_nolinger(int sock, const char *arg)
302{
303 return setsockopt(sock, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
304}
305
306int tcp_set_noquickack(int sock, const char *arg)
307{
308 /* warning: do not use during connect if nothing is to be sent! */
309 return setsockopt(sock, SOL_TCP, TCP_QUICKACK, &zero, sizeof(zero));
310}
311
312/* Try to listen to address <sa>. Return the fd or -1 in case of error */
313int tcp_listen(const struct sockaddr_storage *sa, const char *arg)
314{
315 int sock;
316 int backlog;
317
318 if (arg[1])
319 backlog = atoi(arg + 1);
320 else
321 backlog = 1000;
322
323 if (backlog < 0 || backlog > 65535) {
324 fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
325 return -1;
326 }
327
328 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
329 if (sock < 0) {
330 perror("socket()");
331 return -1;
332 }
333
334 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
335 perror("setsockopt(SO_REUSEADDR)");
336 goto fail;
337 }
338
339#ifdef SO_REUSEPORT
340 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)) == -1) {
341 perror("setsockopt(SO_REUSEPORT)");
342 goto fail;
343 }
344#endif
345 if (bind(sock, (struct sockaddr *)sa, sa->ss_family == AF_INET6 ?
346 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == -1) {
347 perror("bind");
348 goto fail;
349 }
350
351 if (listen(sock, backlog) == -1) {
352 perror("listen");
353 goto fail;
354 }
355
356 return sock;
357 fail:
358 close(sock);
359 return -1;
360}
361
362/* accepts a socket from listening socket <sock>, and returns it (or -1 in case of error) */
363int tcp_accept(int sock, const char *arg)
364{
365 int count;
366 int newsock;
367
368 if (arg[1])
369 count = atoi(arg + 1);
370 else
371 count = 1;
372
373 if (count <= 0) {
374 fprintf(stderr, "accept count must be > 0 or unset (was %d)\n", count);
375 return -1;
376 }
377
378 do {
379 newsock = accept(sock, NULL, NULL);
380 if (newsock < 0) { // TODO: improve error handling
381 if (errno == EINTR || errno == EAGAIN || errno == ECONNABORTED)
382 continue;
383 perror("accept()");
384 break;
385 }
386
387 if (count > 1)
388 close(newsock);
389 count--;
390 } while (count > 0);
391
392 fcntl(newsock, F_SETFL, O_NONBLOCK);
393 return newsock;
394}
395
396/* Try to establish a new connection to <sa>. Return the fd or -1 in case of error */
397int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
398{
399 int sock;
400
401 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
402 if (sock < 0)
403 return -1;
404
405 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
406 goto fail;
407
408 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
409 goto fail;
410
411 if (connect(sock, (const struct sockaddr *)sa, sizeof(*sa)) < 0) {
412 if (errno != EINPROGRESS)
413 goto fail;
414 }
415
416 return sock;
417 fail:
418 close(sock);
419 return -1;
420}
421
422/* receives N bytes from the socket and returns 0 (or -1 in case of error).
423 * When no arg is passed, receives anything and stops. Otherwise reads the
424 * requested amount of data. 0 means read as much as possible.
425 */
426int tcp_recv(int sock, const char *arg)
427{
428 int count = -1; // stop at first read
429 int ret;
430
431 if (arg[1]) {
432 count = atoi(arg + 1);
433 if (count < 0) {
434 fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
435 return -1;
436 }
437 }
438
439 while (1) {
440 ret = recv(sock, NULL, (count > 0) ? count : INT_MAX, MSG_NOSIGNAL | MSG_TRUNC);
441 if (ret < 0) {
442 if (errno == EINTR)
443 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100444 if (errno != EAGAIN) {
445 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100446 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100447 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100448 while (!wait_on_fd(sock, POLLIN));
449 continue;
450 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100451 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100452 if (!ret)
453 break;
454
455 if (!count)
456 continue;
457 else if (count > 0)
458 count -= ret;
459
460 if (count <= 0)
461 break;
462 }
463
464 return 0;
465}
466
467/* sends N bytes to the socket and returns 0 (or -1 in case of error). If not
Willy Tarreau59623e02016-11-12 18:25:45 +0100468 * set, sends only one block. Sending zero means try to send forever. If the
469 * argument starts with ':' then whatever follows is interpreted as the payload
470 * to be sent as-is. '\r', '\n', '\t' and '\\' are detected and converted. In
471 * this case, blocks must be small so that send() doesn't fragment them, as
472 * they will be put into the trash and expected to be sent at once.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100473 */
474int tcp_send(int sock, const char *arg)
475{
476 int count = -1; // stop after first block
477 int ret;
478
Willy Tarreau59623e02016-11-12 18:25:45 +0100479 if (arg[1] == ':') {
480 count = unescape(trash, sizeof(trash), arg + 2);
481 } else if (arg[1]) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100482 count = atoi(arg + 1);
Willy Tarreau869c7592016-11-12 17:50:57 +0100483 if (count < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100484 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
485 return -1;
486 }
487 }
488
489 while (1) {
490 ret = send(sock, trash,
491 (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash),
492 MSG_NOSIGNAL | ((count > sizeof(trash)) ? MSG_MORE : 0));
493 if (ret < 0) {
494 if (errno == EINTR)
495 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100496 if (errno != EAGAIN) {
497 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100498 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100499 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100500 while (!wait_on_fd(sock, POLLOUT));
501 continue;
502 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100503 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100504 if (!count)
505 continue;
506 else if (count > 0)
507 count -= ret;
508
509 if (count <= 0)
510 break;
511 }
512
513 return 0;
514}
515
516/* echoes N bytes to the socket and returns 0 (or -1 in case of error). If not
517 * set, echoes only the first block. Zero means forward forever.
518 */
519int tcp_echo(int sock, const char *arg)
520{
521 int count = -1; // echo forever
522 int ret;
523 int rcvd;
524
525 if (arg[1]) {
526 count = atoi(arg + 1);
527 if (count < 0) {
528 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
529 return -1;
530 }
531 }
532
533 rcvd = 0;
534 while (1) {
535 if (rcvd <= 0) {
536 /* no data pending */
537 rcvd = recv(sock, trash, (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash), MSG_NOSIGNAL);
538 if (rcvd < 0) {
539 if (errno == EINTR)
540 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100541 if (errno != EAGAIN) {
542 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100543 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100544 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100545 while (!wait_on_fd(sock, POLLIN));
546 continue;
547 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100548 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100549 if (!rcvd)
550 break;
551 }
552 else {
553 /* some data still pending */
554 ret = send(sock, trash, rcvd, MSG_NOSIGNAL | ((count > rcvd) ? MSG_MORE : 0));
555 if (ret < 0) {
556 if (errno == EINTR)
557 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100558 if (errno != EAGAIN) {
559 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100560 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100561 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100562 while (!wait_on_fd(sock, POLLOUT));
563 continue;
564 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100565 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100566 rcvd -= ret;
567 if (rcvd)
568 continue;
569
570 if (!count)
571 continue;
572 else if (count > 0)
573 count -= ret;
574
575 if (count <= 0)
576 break;
577 }
578 }
579 return 0;
580}
581
582/* waits for an event on the socket, usually indicates an accept for a
583 * listening socket and a connect for an outgoing socket.
584 */
585int tcp_wait(int sock, const char *arg)
586{
587 struct pollfd pollfd;
588 int delay = -1; // wait forever
589 int ret;
590
591 if (arg[1]) {
592 delay = atoi(arg + 1);
593 if (delay < 0) {
594 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
595 return -1;
596 }
597 }
598
599 /* FIXME: this doesn't take into account delivered signals */
600 do {
601 pollfd.fd = sock;
602 pollfd.events = POLLIN | POLLOUT;
603 ret = poll(&pollfd, 1, delay);
604 } while (ret == -1 && errno == EINTR);
605
Willy Tarreau869c7592016-11-12 17:50:57 +0100606 if (ret > 0 && pollfd.revents & POLLERR)
607 return -1;
608
Willy Tarreau84393aa2016-11-12 11:29:46 +0100609 return 0;
610}
611
612/* waits for the input data to be present */
613int tcp_wait_in(int sock, const char *arg)
614{
615 struct pollfd pollfd;
616 int ret;
617
618 do {
619 pollfd.fd = sock;
620 pollfd.events = POLLIN;
621 ret = poll(&pollfd, 1, 1000);
622 } while (ret == -1 && errno == EINTR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100623
624 if (ret > 0 && pollfd.revents & POLLERR)
625 return -1;
626
Willy Tarreau84393aa2016-11-12 11:29:46 +0100627 return 0;
628}
629
630/* waits for the output queue to be empty */
631int tcp_wait_out(int sock, const char *arg)
632{
633 struct pollfd pollfd;
634 int ret;
635
636 do {
637 pollfd.fd = sock;
638 pollfd.events = POLLOUT;
639 ret = poll(&pollfd, 1, 1000);
640 } while (ret == -1 && errno == EINTR);
641
Willy Tarreau869c7592016-11-12 17:50:57 +0100642 if (ret > 0 && pollfd.revents & POLLERR)
643 return -1;
644
Willy Tarreau84393aa2016-11-12 11:29:46 +0100645 /* Now wait for data to leave the socket */
646 do {
647 if (ioctl(sock, TIOCOUTQ, &ret) < 0)
648 return -1;
649 } while (ret > 0);
650 return 0;
651}
652
653/* delays processing for <time> milliseconds, 100 by default */
654int tcp_pause(int sock, const char *arg)
655{
656 struct pollfd pollfd;
657 int delay = 100;
658 int ret;
659
660 if (arg[1]) {
661 delay = atoi(arg + 1);
662 if (delay < 0) {
663 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
664 return -1;
665 }
666 }
667
668 usleep(delay * 1000);
669 return 0;
670}
671
Willy Tarreau95a6b782016-11-12 13:25:53 +0100672/* forks another process while respecting the limit imposed in argument (1 by
673 * default). Will wait for another process to exit before creating a new one.
674 * Returns the value of the fork() syscall, ie 0 for the child, non-zero for
675 * the parent, -1 for an error.
676 */
677int tcp_fork(int sock, const char *arg)
678{
679 int max = 1;
680 int ret;
681
682 if (arg[1]) {
683 max = atoi(arg + 1);
684 if (max <= 0) {
685 fprintf(stderr, "max process must be > 0 or unset (was %d)\n", max);
686 return -1;
687 }
688 }
689
690 while (nbproc >= max)
691 poll(NULL, 0, 1000);
692
693 ret = fork();
694 if (ret > 0)
695 __sync_add_and_fetch(&nbproc, 1);
696 return ret;
697}
698
Willy Tarreau84393aa2016-11-12 11:29:46 +0100699int main(int argc, char **argv)
700{
701 struct sockaddr_storage ss;
702 struct err_msg err;
703 const char *arg0;
704 int arg;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100705 int ret;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100706 int sock;
707
708 arg0 = argv[0];
Willy Tarreau869c7592016-11-12 17:50:57 +0100709
710 while (argc > 1 && argv[1][0] == '-') {
711 argc--; argv++;
712 if (strcmp(argv[0], "-t") == 0)
713 showtime++;
714 else if (strcmp(argv[0], "-tt") == 0)
715 showtime += 2;
716 else if (strcmp(argv[0], "-ttt") == 0)
717 showtime += 3;
718 else if (strcmp(argv[0], "-v") == 0)
719 verbose ++;
720 else if (strcmp(argv[0], "--") == 0)
721 break;
722 else
723 usage(1, arg0);
724 }
725
Willy Tarreau84393aa2016-11-12 11:29:46 +0100726 if (argc < 2)
727 usage(1, arg0);
728
Willy Tarreau869c7592016-11-12 17:50:57 +0100729 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100730 signal(SIGCHLD, sig_handler);
731
Willy Tarreau84393aa2016-11-12 11:29:46 +0100732 if (addr_to_ss(argv[1], &ss, &err) < 0)
733 die(1, "%s\n", err.msg);
734
Willy Tarreau869c7592016-11-12 17:50:57 +0100735 gettimeofday(&start_time, NULL);
736
Willy Tarreau84393aa2016-11-12 11:29:46 +0100737 sock = -1;
738 for (arg = 2; arg < argc; arg++) {
739 switch (argv[arg][0]) {
740 case 'L':
741 /* silently ignore existing connections */
742 if (sock == -1)
743 sock = tcp_listen(&ss, argv[arg]);
744 if (sock < 0)
745 die(1, "Fatal: tcp_listen() failed.\n");
746 break;
747
748 case 'C':
749 /* silently ignore existing connections */
750 if (sock == -1)
751 sock = tcp_connect(&ss, argv[arg]);
752 if (sock < 0)
753 die(1, "Fatal: tcp_connect() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100754 dolog("connect\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100755 break;
756
757 case 'A':
758 if (sock < 0)
759 die(1, "Fatal: tcp_accept() on non-socket.\n");
760 sock = tcp_accept(sock, argv[arg]);
761 if (sock < 0)
762 die(1, "Fatal: tcp_accept() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100763 dolog("accept\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100764 break;
765
766 case 'T':
767 if (sock < 0)
768 die(1, "Fatal: tcp_set_nodelay() on non-socket.\n");
769 if (tcp_set_nodelay(sock, argv[arg]) < 0)
770 die(1, "Fatal: tcp_set_nodelay() failed.\n");
771 break;
772
773 case 'G':
774 if (sock < 0)
775 die(1, "Fatal: tcp_set_nolinger() on non-socket.\n");
776 if (tcp_set_nolinger(sock, argv[arg]) < 0)
777 die(1, "Fatal: tcp_set_nolinger() failed.\n");
778 break;
779
780 case 'Q':
781 if (sock < 0)
782 die(1, "Fatal: tcp_set_noquickack() on non-socket.\n");
783 if (tcp_set_noquickack(sock, argv[arg]) < 0)
784 die(1, "Fatal: tcp_set_noquickack() failed.\n");
785 break;
786
787 case 'R':
788 if (sock < 0)
789 die(1, "Fatal: tcp_recv() on non-socket.\n");
790 if (tcp_recv(sock, argv[arg]) < 0)
791 die(1, "Fatal: tcp_recv() failed.\n");
792 break;
793
794 case 'S':
795 if (sock < 0)
796 die(1, "Fatal: tcp_send() on non-socket.\n");
797 if (tcp_send(sock, argv[arg]) < 0)
798 die(1, "Fatal: tcp_send() failed.\n");
799 break;
800
801 case 'E':
802 if (sock < 0)
803 die(1, "Fatal: tcp_echo() on non-socket.\n");
804 if (tcp_echo(sock, argv[arg]) < 0)
805 die(1, "Fatal: tcp_echo() failed.\n");
806 break;
807
808 case 'P':
809 if (tcp_pause(sock, argv[arg]) < 0)
810 die(1, "Fatal: tcp_pause() failed.\n");
811 break;
812
813 case 'W':
814 if (sock < 0)
815 die(1, "Fatal: tcp_wait() on non-socket.\n");
816 if (tcp_wait(sock, argv[arg]) < 0)
817 die(1, "Fatal: tcp_wait() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100818 dolog("ready_any\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100819 break;
820
821 case 'I':
822 if (sock < 0)
823 die(1, "Fatal: tcp_wait_in() on non-socket.\n");
824 if (tcp_wait_in(sock, argv[arg]) < 0)
825 die(1, "Fatal: tcp_wait_in() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100826 dolog("ready_in\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100827 break;
828
829 case 'O':
830 if (sock < 0)
831 die(1, "Fatal: tcp_wait_out() on non-socket.\n");
832 if (tcp_wait_out(sock, argv[arg]) < 0)
833 die(1, "Fatal: tcp_wait_out() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100834 dolog("ready_out\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100835 break;
836
837 case 'K':
838 if (sock < 0 || close(sock) < 0)
839 die(1, "Fatal: close() on non-socket.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100840 dolog("close\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100841 sock = -1;
842 break;
843
844 case 'F':
845 /* ignore errors on shutdown() as they are common */
846 if (sock >= 0)
847 shutdown(sock, SHUT_WR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100848 dolog("shutdown\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100849 break;
850
Willy Tarreau95a6b782016-11-12 13:25:53 +0100851 case 'N':
852 ret = tcp_fork(sock, argv[arg]);
853 if (ret < 0)
854 die(1, "Fatal: fork() failed.\n");
855 if (ret > 0) {
856 /* loop back to first arg */
857 arg = 1;
858 continue;
859 }
860 /* OK we're in the child, let's continue */
Willy Tarreau869c7592016-11-12 17:50:57 +0100861 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100862 break;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100863 default:
864 usage(1, arg0);
865 }
866 }
867 return 0;
868}