blob: 033481150f6f84fec3acbc423273ed13d90dc6ec [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>
Willy Tarreau5cd60672016-12-16 08:02:21 +010042#include <limits.h>
Willy Tarreau84393aa2016-11-12 11:29:46 +010043#include <netdb.h>
44#include <poll.h>
45#include <signal.h>
46#include <stdarg.h>
47#include <stdio.h>
48#include <stdlib.h>
49#include <string.h>
50#include <time.h>
51#include <unistd.h>
52
53
54struct err_msg {
55 int size;
56 int len;
57 char msg[0];
58};
59
60const int zero = 0;
61const int one = 1;
62const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
63
64#define TRASH_SIZE 65536
65static char trash[TRASH_SIZE];
66
Willy Tarreau95a6b782016-11-12 13:25:53 +010067volatile int nbproc = 0;
Willy Tarreau869c7592016-11-12 17:50:57 +010068static struct timeval start_time;
69static int showtime;
70static int verbose;
71static int pid;
72
Willy Tarreau95a6b782016-11-12 13:25:53 +010073
Willy Tarreau84393aa2016-11-12 11:29:46 +010074/* display the message and exit with the code */
75__attribute__((noreturn)) void die(int code, const char *format, ...)
76{
77 va_list args;
78
Willy Tarreau1973e812016-11-12 18:45:42 +010079 if (format) {
80 va_start(args, format);
81 vfprintf(stderr, format, args);
82 va_end(args);
83 }
Willy Tarreau84393aa2016-11-12 11:29:46 +010084 exit(code);
85}
86
87/* display the usage message and exit with the code */
88__attribute__((noreturn)) void usage(int code, const char *arg0)
89{
Willy Tarreau9557bac2016-11-12 17:53:16 +010090 die(code,
91 "Usage : %s [options]* [<ip>:]port [<action>*]\n"
92 "\n"
93 "options :\n"
94 " -v : verbose\n"
95 " -t|-tt|-ttt : show time (msec / relative / absolute)\n"
96 "actions :\n"
97 " L[<backlog>] : Listens to ip:port and optionally sets backlog\n"
98 " Note: fd=socket,bind(fd),listen(fd)\n"
99 " C : Connects to ip:port\n"
100 " Note: fd=socket,connect(fd)\n"
101 " A[<count>] : Accepts <count> incoming sockets and closes count-1\n"
102 " Note: fd=accept(fd)\n"
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100103 " J : Jump back to oldest post-fork/post-accept action\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100104 " G : disable lingering\n"
105 " T : set TCP_NODELAY\n"
106 " Q : disable TCP Quick-ack\n"
107 " R[<size>] : Read this amount of bytes. 0=infinite. unset=any amount.\n"
108 " S[<size>] : Send this amount of bytes. 0=infinite. unset=any amount.\n"
Willy Tarreau59623e02016-11-12 18:25:45 +0100109 " S:<string> : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100110 " E[<size>] : Echo this amount of bytes. 0=infinite. unset=any amount.\n"
111 " W[<time>] : Wait for any event on the socket, maximum <time> ms\n"
112 " P[<time>] : Pause for <time> ms (100 by default)\n"
113 " I : wait for Input data to be present (POLLIN)\n"
114 " O : wait for Output queue to be empty (POLLOUT + TIOCOUTQ)\n"
115 " F : FIN : shutdown(SHUT_WR)\n"
116 " N<max> : fork New process, limited to <max> concurrent (default 1)\n"
117 "\n"
118 "It's important to note that a single FD is used at once and that Accept\n"
119 "replaces the listening FD with the accepted one. Thus always do it after\n"
120 "a fork if other connections have to be accepted.\n"
121 "\n"
122 "After a fork, we loop back to the beginning and silently skip L/C if the\n"
123 "main socket already exists.\n"
124 "\n"
125 "Example dummy HTTP request drain server :\n"
126 " tcploop 8001 L W N20 A R S10 [ F K ]\n"
127 "\n"
128 "Example large bandwidth HTTP request drain server :\n"
129 " tcploop 8001 L W N20 A R S0 [ F K ]\n"
130 "\n"
131 "Example TCP client with pauses at each step :\n"
132 " tcploop 8001 C T W P100 S10 O P100 R S10 O R G K\n"
133 "", arg0);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100134}
135
Willy Tarreau869c7592016-11-12 17:50:57 +0100136void dolog(const char *format, ...)
137{
138 struct timeval date, tv;
139 int delay;
140 va_list args;
141
142 if (!verbose)
143 return;
144
145 if (showtime) {
146 gettimeofday(&date, NULL);
147 switch (showtime) {
148 case 1: // [msec] relative
149 delay = (date.tv_sec - start_time.tv_sec) * 1000000 + date.tv_usec - start_time.tv_usec;
150 fprintf(stderr, "[%d] ", delay / 1000);
151 break;
152 case 2: // [sec.usec] relative
153 tv.tv_usec = date.tv_usec - start_time.tv_usec;
154 tv.tv_sec = date.tv_sec - start_time.tv_sec;
155 if ((signed)tv.tv_sec > 0) {
156 if ((signed)tv.tv_usec < 0) {
157 tv.tv_usec += 1000000;
158 tv.tv_sec--;
159 }
160 } else if (tv.tv_sec == 0) {
161 if ((signed)tv.tv_usec < 0)
162 tv.tv_usec = 0;
163 } else {
164 tv.tv_sec = 0;
165 tv.tv_usec = 0;
166 }
167 fprintf(stderr, "[%d.%06d] ", tv.tv_sec, tv.tv_usec);
168 break;
169 default: // [sec.usec] absolute
170 fprintf(stderr, "[%d.%06d] ", date.tv_sec, date.tv_usec);
171 break;
172 }
173 }
174
175 fprintf(stderr, "%5d ", pid);
176
177 va_start(args, format);
178 vfprintf(stderr, format, args);
179 va_end(args);
180}
181
Willy Tarreau59623e02016-11-12 18:25:45 +0100182/* convert '\n', '\t', '\r', '\\' to their respective characters */
183int unescape(char *out, int size, const char *in)
184{
185 int len;
186
187 for (len = 0; len < size && *in; in++, out++, len++) {
188 if (*in == '\\') {
189 switch (in[1]) {
190 case 'n' : *out = '\n'; in++; continue;
191 case 't' : *out = '\t'; in++; continue;
192 case 'r' : *out = '\r'; in++; continue;
193 case '\\' : *out = '\\'; in++; continue;
194 default : break;
195 }
196 }
197 *out = *in;
198 }
199 return len;
200}
201
Willy Tarreau84393aa2016-11-12 11:29:46 +0100202struct err_msg *alloc_err_msg(int size)
203{
204 struct err_msg *err;
205
206 err = malloc(sizeof(*err) + size);
207 if (err) {
208 err->len = 0;
209 err->size = size;
210 }
211 return err;
212}
213
Willy Tarreau95a6b782016-11-12 13:25:53 +0100214void sig_handler(int sig)
215{
216 if (sig == SIGCHLD) {
217 while (waitpid(-1, NULL, WNOHANG) > 0)
218 __sync_sub_and_fetch(&nbproc, 1);
219 }
220}
Willy Tarreau84393aa2016-11-12 11:29:46 +0100221
222/* converts str in the form [[<ipv4>|<ipv6>|<hostname>]:]port to struct sockaddr_storage.
223 * Returns < 0 with err set in case of error.
224 */
225int addr_to_ss(char *str, struct sockaddr_storage *ss, struct err_msg *err)
226{
227 char *port_str;
228 int port;
229
230 memset(ss, 0, sizeof(*ss));
231
232 /* look for the addr/port delimiter, it's the last colon. If there's no
233 * colon, it's 0:<port>.
234 */
235 if ((port_str = strrchr(str, ':')) == NULL) {
236 port = atoi(str);
237 if (port <= 0 || port > 65535) {
238 err->len = snprintf(err->msg, err->size, "Missing/invalid port number: '%s'\n", str);
239 return -1;
240 }
241
242 ss->ss_family = AF_INET;
243 ((struct sockaddr_in *)ss)->sin_port = htons(port);
244 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
245 return 0;
246 }
247
248 *port_str++ = 0;
249
250 if (strrchr(str, ':') != NULL) {
251 /* IPv6 address contains ':' */
252 ss->ss_family = AF_INET6;
253 ((struct sockaddr_in6 *)ss)->sin6_port = htons(atoi(port_str));
254
255 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in6 *)ss)->sin6_addr)) {
256 err->len = snprintf(err->msg, err->size, "Invalid server address: '%s'\n", str);
257 return -1;
258 }
259 }
260 else {
261 ss->ss_family = AF_INET;
262 ((struct sockaddr_in *)ss)->sin_port = htons(atoi(port_str));
263
264 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
265 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
266 return 0;
267 }
268
269 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in *)ss)->sin_addr)) {
270 struct hostent *he = gethostbyname(str);
271
272 if (he == NULL) {
273 err->len = snprintf(err->msg, err->size, "Invalid server name: '%s'\n", str);
274 return -1;
275 }
276 ((struct sockaddr_in *)ss)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
277 }
278 }
279
280 return 0;
281}
282
283/* waits up to one second on fd <fd> for events <events> (POLLIN|POLLOUT).
284 * returns poll's status.
285 */
286int wait_on_fd(int fd, int events)
287{
288 struct pollfd pollfd;
289 int ret;
290
291 do {
292 pollfd.fd = fd;
293 pollfd.events = events;
294 ret = poll(&pollfd, 1, 1000);
295 } while (ret == -1 && errno == EINTR);
296
297 return ret;
298}
299
300int tcp_set_nodelay(int sock, const char *arg)
301{
302 return setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
303}
304
305int tcp_set_nolinger(int sock, const char *arg)
306{
307 return setsockopt(sock, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
308}
309
310int tcp_set_noquickack(int sock, const char *arg)
311{
312 /* warning: do not use during connect if nothing is to be sent! */
313 return setsockopt(sock, SOL_TCP, TCP_QUICKACK, &zero, sizeof(zero));
314}
315
316/* Try to listen to address <sa>. Return the fd or -1 in case of error */
317int tcp_listen(const struct sockaddr_storage *sa, const char *arg)
318{
319 int sock;
320 int backlog;
321
322 if (arg[1])
323 backlog = atoi(arg + 1);
324 else
325 backlog = 1000;
326
327 if (backlog < 0 || backlog > 65535) {
328 fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
329 return -1;
330 }
331
332 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
333 if (sock < 0) {
334 perror("socket()");
335 return -1;
336 }
337
338 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
339 perror("setsockopt(SO_REUSEADDR)");
340 goto fail;
341 }
342
343#ifdef SO_REUSEPORT
344 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)) == -1) {
345 perror("setsockopt(SO_REUSEPORT)");
346 goto fail;
347 }
348#endif
349 if (bind(sock, (struct sockaddr *)sa, sa->ss_family == AF_INET6 ?
350 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == -1) {
351 perror("bind");
352 goto fail;
353 }
354
355 if (listen(sock, backlog) == -1) {
356 perror("listen");
357 goto fail;
358 }
359
360 return sock;
361 fail:
362 close(sock);
363 return -1;
364}
365
366/* accepts a socket from listening socket <sock>, and returns it (or -1 in case of error) */
367int tcp_accept(int sock, const char *arg)
368{
369 int count;
370 int newsock;
371
372 if (arg[1])
373 count = atoi(arg + 1);
374 else
375 count = 1;
376
377 if (count <= 0) {
378 fprintf(stderr, "accept count must be > 0 or unset (was %d)\n", count);
379 return -1;
380 }
381
382 do {
383 newsock = accept(sock, NULL, NULL);
384 if (newsock < 0) { // TODO: improve error handling
385 if (errno == EINTR || errno == EAGAIN || errno == ECONNABORTED)
386 continue;
387 perror("accept()");
388 break;
389 }
390
391 if (count > 1)
392 close(newsock);
393 count--;
394 } while (count > 0);
395
396 fcntl(newsock, F_SETFL, O_NONBLOCK);
397 return newsock;
398}
399
400/* Try to establish a new connection to <sa>. Return the fd or -1 in case of error */
401int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
402{
403 int sock;
404
405 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
406 if (sock < 0)
407 return -1;
408
409 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
410 goto fail;
411
412 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
413 goto fail;
414
415 if (connect(sock, (const struct sockaddr *)sa, sizeof(*sa)) < 0) {
416 if (errno != EINPROGRESS)
417 goto fail;
418 }
419
420 return sock;
421 fail:
422 close(sock);
423 return -1;
424}
425
Willy Tarreau1973e812016-11-12 18:45:42 +0100426/* receives N bytes from the socket and returns 0 (or -1 in case of a recv
427 * error, or -2 in case of an argument error). When no arg is passed, receives
428 * anything and stops. Otherwise reads the requested amount of data. 0 means
429 * read as much as possible.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100430 */
431int tcp_recv(int sock, const char *arg)
432{
433 int count = -1; // stop at first read
434 int ret;
435
436 if (arg[1]) {
437 count = atoi(arg + 1);
438 if (count < 0) {
439 fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100440 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100441 }
442 }
443
444 while (1) {
445 ret = recv(sock, NULL, (count > 0) ? count : INT_MAX, MSG_NOSIGNAL | MSG_TRUNC);
446 if (ret < 0) {
447 if (errno == EINTR)
448 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100449 if (errno != EAGAIN) {
450 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100451 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100452 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100453 while (!wait_on_fd(sock, POLLIN));
454 continue;
455 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100456 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100457 if (!ret)
458 break;
459
460 if (!count)
461 continue;
462 else if (count > 0)
463 count -= ret;
464
465 if (count <= 0)
466 break;
467 }
468
469 return 0;
470}
471
Willy Tarreau1973e812016-11-12 18:45:42 +0100472/* Sends N bytes to the socket and returns 0 (or -1 in case of send error, -2
473 * in case of an argument error. If the byte count is not set, sends only one
474 * block. Sending zero means try to send forever. If the argument starts with
475 * ':' then whatever follows is interpreted as the payload to be sent as-is.
476 * Escaped characters '\r', '\n', '\t' and '\\' are detected and converted. In
Willy Tarreau59623e02016-11-12 18:25:45 +0100477 * this case, blocks must be small so that send() doesn't fragment them, as
478 * they will be put into the trash and expected to be sent at once.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100479 */
480int tcp_send(int sock, const char *arg)
481{
482 int count = -1; // stop after first block
483 int ret;
484
Willy Tarreau59623e02016-11-12 18:25:45 +0100485 if (arg[1] == ':') {
486 count = unescape(trash, sizeof(trash), arg + 2);
487 } else if (arg[1]) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100488 count = atoi(arg + 1);
Willy Tarreau869c7592016-11-12 17:50:57 +0100489 if (count < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100490 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100491 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100492 }
493 }
494
495 while (1) {
496 ret = send(sock, trash,
497 (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash),
498 MSG_NOSIGNAL | ((count > sizeof(trash)) ? MSG_MORE : 0));
499 if (ret < 0) {
500 if (errno == EINTR)
501 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100502 if (errno != EAGAIN) {
503 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100504 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100505 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100506 while (!wait_on_fd(sock, POLLOUT));
507 continue;
508 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100509 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100510 if (!count)
511 continue;
512 else if (count > 0)
513 count -= ret;
514
515 if (count <= 0)
516 break;
517 }
518
519 return 0;
520}
521
522/* echoes N bytes to the socket and returns 0 (or -1 in case of error). If not
523 * set, echoes only the first block. Zero means forward forever.
524 */
525int tcp_echo(int sock, const char *arg)
526{
527 int count = -1; // echo forever
528 int ret;
529 int rcvd;
530
531 if (arg[1]) {
532 count = atoi(arg + 1);
533 if (count < 0) {
534 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
535 return -1;
536 }
537 }
538
539 rcvd = 0;
540 while (1) {
541 if (rcvd <= 0) {
542 /* no data pending */
543 rcvd = recv(sock, trash, (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash), MSG_NOSIGNAL);
544 if (rcvd < 0) {
545 if (errno == EINTR)
546 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100547 if (errno != EAGAIN) {
548 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100549 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100550 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100551 while (!wait_on_fd(sock, POLLIN));
552 continue;
553 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100554 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100555 if (!rcvd)
556 break;
557 }
558 else {
559 /* some data still pending */
560 ret = send(sock, trash, rcvd, MSG_NOSIGNAL | ((count > rcvd) ? MSG_MORE : 0));
561 if (ret < 0) {
562 if (errno == EINTR)
563 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100564 if (errno != EAGAIN) {
565 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100566 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100567 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100568 while (!wait_on_fd(sock, POLLOUT));
569 continue;
570 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100571 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100572 rcvd -= ret;
573 if (rcvd)
574 continue;
575
576 if (!count)
577 continue;
578 else if (count > 0)
579 count -= ret;
580
581 if (count <= 0)
582 break;
583 }
584 }
585 return 0;
586}
587
588/* waits for an event on the socket, usually indicates an accept for a
589 * listening socket and a connect for an outgoing socket.
590 */
591int tcp_wait(int sock, const char *arg)
592{
593 struct pollfd pollfd;
594 int delay = -1; // wait forever
595 int ret;
596
597 if (arg[1]) {
598 delay = atoi(arg + 1);
599 if (delay < 0) {
600 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
601 return -1;
602 }
603 }
604
605 /* FIXME: this doesn't take into account delivered signals */
606 do {
607 pollfd.fd = sock;
608 pollfd.events = POLLIN | POLLOUT;
609 ret = poll(&pollfd, 1, delay);
610 } while (ret == -1 && errno == EINTR);
611
Willy Tarreau869c7592016-11-12 17:50:57 +0100612 if (ret > 0 && pollfd.revents & POLLERR)
613 return -1;
614
Willy Tarreau84393aa2016-11-12 11:29:46 +0100615 return 0;
616}
617
618/* waits for the input data to be present */
619int tcp_wait_in(int sock, const char *arg)
620{
621 struct pollfd pollfd;
622 int ret;
623
624 do {
625 pollfd.fd = sock;
626 pollfd.events = POLLIN;
627 ret = poll(&pollfd, 1, 1000);
628 } while (ret == -1 && errno == EINTR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100629
630 if (ret > 0 && pollfd.revents & POLLERR)
631 return -1;
632
Willy Tarreau84393aa2016-11-12 11:29:46 +0100633 return 0;
634}
635
636/* waits for the output queue to be empty */
637int tcp_wait_out(int sock, const char *arg)
638{
639 struct pollfd pollfd;
640 int ret;
641
642 do {
643 pollfd.fd = sock;
644 pollfd.events = POLLOUT;
645 ret = poll(&pollfd, 1, 1000);
646 } while (ret == -1 && errno == EINTR);
647
Willy Tarreau869c7592016-11-12 17:50:57 +0100648 if (ret > 0 && pollfd.revents & POLLERR)
649 return -1;
650
Willy Tarreau84393aa2016-11-12 11:29:46 +0100651 /* Now wait for data to leave the socket */
652 do {
653 if (ioctl(sock, TIOCOUTQ, &ret) < 0)
654 return -1;
655 } while (ret > 0);
656 return 0;
657}
658
659/* delays processing for <time> milliseconds, 100 by default */
660int tcp_pause(int sock, const char *arg)
661{
662 struct pollfd pollfd;
663 int delay = 100;
664 int ret;
665
666 if (arg[1]) {
667 delay = atoi(arg + 1);
668 if (delay < 0) {
669 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
670 return -1;
671 }
672 }
673
674 usleep(delay * 1000);
675 return 0;
676}
677
Willy Tarreau95a6b782016-11-12 13:25:53 +0100678/* forks another process while respecting the limit imposed in argument (1 by
679 * default). Will wait for another process to exit before creating a new one.
680 * Returns the value of the fork() syscall, ie 0 for the child, non-zero for
681 * the parent, -1 for an error.
682 */
683int tcp_fork(int sock, const char *arg)
684{
685 int max = 1;
686 int ret;
687
688 if (arg[1]) {
689 max = atoi(arg + 1);
690 if (max <= 0) {
691 fprintf(stderr, "max process must be > 0 or unset (was %d)\n", max);
692 return -1;
693 }
694 }
695
696 while (nbproc >= max)
697 poll(NULL, 0, 1000);
698
699 ret = fork();
700 if (ret > 0)
701 __sync_add_and_fetch(&nbproc, 1);
702 return ret;
703}
704
Willy Tarreau84393aa2016-11-12 11:29:46 +0100705int main(int argc, char **argv)
706{
707 struct sockaddr_storage ss;
708 struct err_msg err;
709 const char *arg0;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100710 int loop_arg;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100711 int arg;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100712 int ret;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100713 int sock;
714
715 arg0 = argv[0];
Willy Tarreau869c7592016-11-12 17:50:57 +0100716
717 while (argc > 1 && argv[1][0] == '-') {
718 argc--; argv++;
719 if (strcmp(argv[0], "-t") == 0)
720 showtime++;
721 else if (strcmp(argv[0], "-tt") == 0)
722 showtime += 2;
723 else if (strcmp(argv[0], "-ttt") == 0)
724 showtime += 3;
725 else if (strcmp(argv[0], "-v") == 0)
726 verbose ++;
727 else if (strcmp(argv[0], "--") == 0)
728 break;
729 else
730 usage(1, arg0);
731 }
732
Willy Tarreau84393aa2016-11-12 11:29:46 +0100733 if (argc < 2)
734 usage(1, arg0);
735
Willy Tarreau869c7592016-11-12 17:50:57 +0100736 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100737 signal(SIGCHLD, sig_handler);
738
Willy Tarreau84393aa2016-11-12 11:29:46 +0100739 if (addr_to_ss(argv[1], &ss, &err) < 0)
740 die(1, "%s\n", err.msg);
741
Willy Tarreau869c7592016-11-12 17:50:57 +0100742 gettimeofday(&start_time, NULL);
743
Willy Tarreau84393aa2016-11-12 11:29:46 +0100744 sock = -1;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100745 loop_arg = 2;
746 for (arg = loop_arg; arg < argc; arg++) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100747 switch (argv[arg][0]) {
748 case 'L':
749 /* silently ignore existing connections */
750 if (sock == -1)
751 sock = tcp_listen(&ss, argv[arg]);
752 if (sock < 0)
753 die(1, "Fatal: tcp_listen() failed.\n");
754 break;
755
756 case 'C':
757 /* silently ignore existing connections */
758 if (sock == -1)
759 sock = tcp_connect(&ss, argv[arg]);
760 if (sock < 0)
761 die(1, "Fatal: tcp_connect() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100762 dolog("connect\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100763 break;
764
765 case 'A':
766 if (sock < 0)
767 die(1, "Fatal: tcp_accept() on non-socket.\n");
768 sock = tcp_accept(sock, argv[arg]);
769 if (sock < 0)
770 die(1, "Fatal: tcp_accept() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100771 dolog("accept\n");
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100772 loop_arg = arg + 1; // cannot loop before accept()
Willy Tarreau84393aa2016-11-12 11:29:46 +0100773 break;
774
775 case 'T':
776 if (sock < 0)
777 die(1, "Fatal: tcp_set_nodelay() on non-socket.\n");
778 if (tcp_set_nodelay(sock, argv[arg]) < 0)
779 die(1, "Fatal: tcp_set_nodelay() failed.\n");
780 break;
781
782 case 'G':
783 if (sock < 0)
784 die(1, "Fatal: tcp_set_nolinger() on non-socket.\n");
785 if (tcp_set_nolinger(sock, argv[arg]) < 0)
786 die(1, "Fatal: tcp_set_nolinger() failed.\n");
787 break;
788
789 case 'Q':
790 if (sock < 0)
791 die(1, "Fatal: tcp_set_noquickack() on non-socket.\n");
792 if (tcp_set_noquickack(sock, argv[arg]) < 0)
793 die(1, "Fatal: tcp_set_noquickack() failed.\n");
794 break;
795
796 case 'R':
797 if (sock < 0)
798 die(1, "Fatal: tcp_recv() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100799 ret = tcp_recv(sock, argv[arg]);
800 if (ret < 0) {
801 if (ret == -1) // usually ECONNRESET, silently exit
802 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100803 die(1, "Fatal: tcp_recv() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100804 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100805 break;
806
807 case 'S':
808 if (sock < 0)
809 die(1, "Fatal: tcp_send() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100810 ret = tcp_send(sock, argv[arg]);
811 if (ret < 0) {
812 if (ret == -1) // usually a broken pipe, silently exit
813 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100814 die(1, "Fatal: tcp_send() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100815 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100816 break;
817
818 case 'E':
819 if (sock < 0)
820 die(1, "Fatal: tcp_echo() on non-socket.\n");
821 if (tcp_echo(sock, argv[arg]) < 0)
822 die(1, "Fatal: tcp_echo() failed.\n");
823 break;
824
825 case 'P':
826 if (tcp_pause(sock, argv[arg]) < 0)
827 die(1, "Fatal: tcp_pause() failed.\n");
828 break;
829
830 case 'W':
831 if (sock < 0)
832 die(1, "Fatal: tcp_wait() on non-socket.\n");
833 if (tcp_wait(sock, argv[arg]) < 0)
834 die(1, "Fatal: tcp_wait() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100835 dolog("ready_any\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100836 break;
837
838 case 'I':
839 if (sock < 0)
840 die(1, "Fatal: tcp_wait_in() on non-socket.\n");
841 if (tcp_wait_in(sock, argv[arg]) < 0)
842 die(1, "Fatal: tcp_wait_in() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100843 dolog("ready_in\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100844 break;
845
846 case 'O':
847 if (sock < 0)
848 die(1, "Fatal: tcp_wait_out() on non-socket.\n");
849 if (tcp_wait_out(sock, argv[arg]) < 0)
850 die(1, "Fatal: tcp_wait_out() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100851 dolog("ready_out\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100852 break;
853
854 case 'K':
855 if (sock < 0 || close(sock) < 0)
856 die(1, "Fatal: close() on non-socket.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100857 dolog("close\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100858 sock = -1;
859 break;
860
861 case 'F':
862 /* ignore errors on shutdown() as they are common */
863 if (sock >= 0)
864 shutdown(sock, SHUT_WR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100865 dolog("shutdown\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100866 break;
867
Willy Tarreau95a6b782016-11-12 13:25:53 +0100868 case 'N':
869 ret = tcp_fork(sock, argv[arg]);
870 if (ret < 0)
871 die(1, "Fatal: fork() failed.\n");
872 if (ret > 0) {
873 /* loop back to first arg */
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100874 arg = loop_arg - 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100875 continue;
876 }
877 /* OK we're in the child, let's continue */
Willy Tarreau869c7592016-11-12 17:50:57 +0100878 pid = getpid();
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100879 loop_arg = arg + 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100880 break;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100881
882 case 'J': // jump back to oldest post-fork action
883 arg = loop_arg - 1;
884 continue;
885
Willy Tarreau84393aa2016-11-12 11:29:46 +0100886 default:
887 usage(1, arg0);
888 }
889 }
890 return 0;
891}