blob: 543e346f40d04e36cd27170a7b41bb0666a46bc7 [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
Willy Tarreau0c0c0a62017-03-14 14:36:26 +010053#ifndef SOL_TCP
54#define SOL_TCP IPPROTO_TCP
55#endif
56
57#ifndef MSG_MORE
58#define MSG_MORE 0
59#endif
Willy Tarreau84393aa2016-11-12 11:29:46 +010060
61struct err_msg {
62 int size;
63 int len;
64 char msg[0];
65};
66
67const int zero = 0;
68const int one = 1;
69const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
70
71#define TRASH_SIZE 65536
72static char trash[TRASH_SIZE];
73
Willy Tarreau95a6b782016-11-12 13:25:53 +010074volatile int nbproc = 0;
Willy Tarreau869c7592016-11-12 17:50:57 +010075static struct timeval start_time;
76static int showtime;
77static int verbose;
78static int pid;
79
Willy Tarreau95a6b782016-11-12 13:25:53 +010080
Willy Tarreau84393aa2016-11-12 11:29:46 +010081/* display the message and exit with the code */
82__attribute__((noreturn)) void die(int code, const char *format, ...)
83{
84 va_list args;
85
Willy Tarreau1973e812016-11-12 18:45:42 +010086 if (format) {
87 va_start(args, format);
88 vfprintf(stderr, format, args);
89 va_end(args);
90 }
Willy Tarreau84393aa2016-11-12 11:29:46 +010091 exit(code);
92}
93
94/* display the usage message and exit with the code */
95__attribute__((noreturn)) void usage(int code, const char *arg0)
96{
Willy Tarreau9557bac2016-11-12 17:53:16 +010097 die(code,
98 "Usage : %s [options]* [<ip>:]port [<action>*]\n"
99 "\n"
100 "options :\n"
101 " -v : verbose\n"
102 " -t|-tt|-ttt : show time (msec / relative / absolute)\n"
103 "actions :\n"
104 " L[<backlog>] : Listens to ip:port and optionally sets backlog\n"
105 " Note: fd=socket,bind(fd),listen(fd)\n"
106 " C : Connects to ip:port\n"
107 " Note: fd=socket,connect(fd)\n"
108 " A[<count>] : Accepts <count> incoming sockets and closes count-1\n"
109 " Note: fd=accept(fd)\n"
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100110 " J : Jump back to oldest post-fork/post-accept action\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100111 " G : disable lingering\n"
112 " T : set TCP_NODELAY\n"
113 " Q : disable TCP Quick-ack\n"
114 " R[<size>] : Read this amount of bytes. 0=infinite. unset=any amount.\n"
115 " S[<size>] : Send this amount of bytes. 0=infinite. unset=any amount.\n"
Willy Tarreau59623e02016-11-12 18:25:45 +0100116 " S:<string> : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100117 " E[<size>] : Echo this amount of bytes. 0=infinite. unset=any amount.\n"
118 " W[<time>] : Wait for any event on the socket, maximum <time> ms\n"
119 " P[<time>] : Pause for <time> ms (100 by default)\n"
120 " I : wait for Input data to be present (POLLIN)\n"
121 " O : wait for Output queue to be empty (POLLOUT + TIOCOUTQ)\n"
122 " F : FIN : shutdown(SHUT_WR)\n"
123 " N<max> : fork New process, limited to <max> concurrent (default 1)\n"
124 "\n"
125 "It's important to note that a single FD is used at once and that Accept\n"
126 "replaces the listening FD with the accepted one. Thus always do it after\n"
127 "a fork if other connections have to be accepted.\n"
128 "\n"
129 "After a fork, we loop back to the beginning and silently skip L/C if the\n"
130 "main socket already exists.\n"
131 "\n"
132 "Example dummy HTTP request drain server :\n"
133 " tcploop 8001 L W N20 A R S10 [ F K ]\n"
134 "\n"
135 "Example large bandwidth HTTP request drain server :\n"
136 " tcploop 8001 L W N20 A R S0 [ F K ]\n"
137 "\n"
138 "Example TCP client with pauses at each step :\n"
139 " tcploop 8001 C T W P100 S10 O P100 R S10 O R G K\n"
140 "", arg0);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100141}
142
Willy Tarreau869c7592016-11-12 17:50:57 +0100143void dolog(const char *format, ...)
144{
145 struct timeval date, tv;
146 int delay;
147 va_list args;
148
149 if (!verbose)
150 return;
151
152 if (showtime) {
153 gettimeofday(&date, NULL);
154 switch (showtime) {
155 case 1: // [msec] relative
156 delay = (date.tv_sec - start_time.tv_sec) * 1000000 + date.tv_usec - start_time.tv_usec;
157 fprintf(stderr, "[%d] ", delay / 1000);
158 break;
159 case 2: // [sec.usec] relative
160 tv.tv_usec = date.tv_usec - start_time.tv_usec;
161 tv.tv_sec = date.tv_sec - start_time.tv_sec;
162 if ((signed)tv.tv_sec > 0) {
163 if ((signed)tv.tv_usec < 0) {
164 tv.tv_usec += 1000000;
165 tv.tv_sec--;
166 }
167 } else if (tv.tv_sec == 0) {
168 if ((signed)tv.tv_usec < 0)
169 tv.tv_usec = 0;
170 } else {
171 tv.tv_sec = 0;
172 tv.tv_usec = 0;
173 }
Willy Tarreau752cc492017-03-14 14:37:13 +0100174 fprintf(stderr, "[%d.%06d] ", (int)tv.tv_sec, (int)tv.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100175 break;
176 default: // [sec.usec] absolute
Willy Tarreau752cc492017-03-14 14:37:13 +0100177 fprintf(stderr, "[%d.%06d] ", (int)date.tv_sec, (int)date.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100178 break;
179 }
180 }
181
182 fprintf(stderr, "%5d ", pid);
183
184 va_start(args, format);
185 vfprintf(stderr, format, args);
186 va_end(args);
187}
188
Willy Tarreau59623e02016-11-12 18:25:45 +0100189/* convert '\n', '\t', '\r', '\\' to their respective characters */
190int unescape(char *out, int size, const char *in)
191{
192 int len;
193
194 for (len = 0; len < size && *in; in++, out++, len++) {
195 if (*in == '\\') {
196 switch (in[1]) {
197 case 'n' : *out = '\n'; in++; continue;
198 case 't' : *out = '\t'; in++; continue;
199 case 'r' : *out = '\r'; in++; continue;
200 case '\\' : *out = '\\'; in++; continue;
201 default : break;
202 }
203 }
204 *out = *in;
205 }
206 return len;
207}
208
Willy Tarreau84393aa2016-11-12 11:29:46 +0100209struct err_msg *alloc_err_msg(int size)
210{
211 struct err_msg *err;
212
213 err = malloc(sizeof(*err) + size);
214 if (err) {
215 err->len = 0;
216 err->size = size;
217 }
218 return err;
219}
220
Willy Tarreau95a6b782016-11-12 13:25:53 +0100221void sig_handler(int sig)
222{
223 if (sig == SIGCHLD) {
224 while (waitpid(-1, NULL, WNOHANG) > 0)
225 __sync_sub_and_fetch(&nbproc, 1);
226 }
227}
Willy Tarreau84393aa2016-11-12 11:29:46 +0100228
229/* converts str in the form [[<ipv4>|<ipv6>|<hostname>]:]port to struct sockaddr_storage.
230 * Returns < 0 with err set in case of error.
231 */
232int addr_to_ss(char *str, struct sockaddr_storage *ss, struct err_msg *err)
233{
234 char *port_str;
235 int port;
236
237 memset(ss, 0, sizeof(*ss));
238
239 /* look for the addr/port delimiter, it's the last colon. If there's no
240 * colon, it's 0:<port>.
241 */
242 if ((port_str = strrchr(str, ':')) == NULL) {
243 port = atoi(str);
244 if (port <= 0 || port > 65535) {
245 err->len = snprintf(err->msg, err->size, "Missing/invalid port number: '%s'\n", str);
246 return -1;
247 }
248
249 ss->ss_family = AF_INET;
250 ((struct sockaddr_in *)ss)->sin_port = htons(port);
251 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
252 return 0;
253 }
254
255 *port_str++ = 0;
256
257 if (strrchr(str, ':') != NULL) {
258 /* IPv6 address contains ':' */
259 ss->ss_family = AF_INET6;
260 ((struct sockaddr_in6 *)ss)->sin6_port = htons(atoi(port_str));
261
262 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in6 *)ss)->sin6_addr)) {
263 err->len = snprintf(err->msg, err->size, "Invalid server address: '%s'\n", str);
264 return -1;
265 }
266 }
267 else {
268 ss->ss_family = AF_INET;
269 ((struct sockaddr_in *)ss)->sin_port = htons(atoi(port_str));
270
271 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
272 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
273 return 0;
274 }
275
276 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in *)ss)->sin_addr)) {
277 struct hostent *he = gethostbyname(str);
278
279 if (he == NULL) {
280 err->len = snprintf(err->msg, err->size, "Invalid server name: '%s'\n", str);
281 return -1;
282 }
283 ((struct sockaddr_in *)ss)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
284 }
285 }
286
287 return 0;
288}
289
290/* waits up to one second on fd <fd> for events <events> (POLLIN|POLLOUT).
291 * returns poll's status.
292 */
293int wait_on_fd(int fd, int events)
294{
295 struct pollfd pollfd;
296 int ret;
297
298 do {
299 pollfd.fd = fd;
300 pollfd.events = events;
301 ret = poll(&pollfd, 1, 1000);
302 } while (ret == -1 && errno == EINTR);
303
304 return ret;
305}
306
307int tcp_set_nodelay(int sock, const char *arg)
308{
309 return setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
310}
311
312int tcp_set_nolinger(int sock, const char *arg)
313{
314 return setsockopt(sock, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
315}
316
317int tcp_set_noquickack(int sock, const char *arg)
318{
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100319#ifdef TCP_QUICKACK
Willy Tarreau84393aa2016-11-12 11:29:46 +0100320 /* warning: do not use during connect if nothing is to be sent! */
321 return setsockopt(sock, SOL_TCP, TCP_QUICKACK, &zero, sizeof(zero));
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100322#else
323 return 0;
324#endif
Willy Tarreau84393aa2016-11-12 11:29:46 +0100325}
326
327/* Try to listen to address <sa>. Return the fd or -1 in case of error */
328int tcp_listen(const struct sockaddr_storage *sa, const char *arg)
329{
330 int sock;
331 int backlog;
332
333 if (arg[1])
334 backlog = atoi(arg + 1);
335 else
336 backlog = 1000;
337
338 if (backlog < 0 || backlog > 65535) {
339 fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
340 return -1;
341 }
342
343 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
344 if (sock < 0) {
345 perror("socket()");
346 return -1;
347 }
348
349 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
350 perror("setsockopt(SO_REUSEADDR)");
351 goto fail;
352 }
353
354#ifdef SO_REUSEPORT
355 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)) == -1) {
356 perror("setsockopt(SO_REUSEPORT)");
357 goto fail;
358 }
359#endif
360 if (bind(sock, (struct sockaddr *)sa, sa->ss_family == AF_INET6 ?
361 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == -1) {
362 perror("bind");
363 goto fail;
364 }
365
366 if (listen(sock, backlog) == -1) {
367 perror("listen");
368 goto fail;
369 }
370
371 return sock;
372 fail:
373 close(sock);
374 return -1;
375}
376
377/* accepts a socket from listening socket <sock>, and returns it (or -1 in case of error) */
378int tcp_accept(int sock, const char *arg)
379{
380 int count;
381 int newsock;
382
383 if (arg[1])
384 count = atoi(arg + 1);
385 else
386 count = 1;
387
388 if (count <= 0) {
389 fprintf(stderr, "accept count must be > 0 or unset (was %d)\n", count);
390 return -1;
391 }
392
393 do {
394 newsock = accept(sock, NULL, NULL);
395 if (newsock < 0) { // TODO: improve error handling
396 if (errno == EINTR || errno == EAGAIN || errno == ECONNABORTED)
397 continue;
398 perror("accept()");
399 break;
400 }
401
402 if (count > 1)
403 close(newsock);
404 count--;
405 } while (count > 0);
406
407 fcntl(newsock, F_SETFL, O_NONBLOCK);
408 return newsock;
409}
410
411/* Try to establish a new connection to <sa>. Return the fd or -1 in case of error */
412int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
413{
414 int sock;
415
416 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
417 if (sock < 0)
418 return -1;
419
420 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
421 goto fail;
422
423 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
424 goto fail;
425
426 if (connect(sock, (const struct sockaddr *)sa, sizeof(*sa)) < 0) {
427 if (errno != EINPROGRESS)
428 goto fail;
429 }
430
431 return sock;
432 fail:
433 close(sock);
434 return -1;
435}
436
Willy Tarreau1973e812016-11-12 18:45:42 +0100437/* receives N bytes from the socket and returns 0 (or -1 in case of a recv
438 * error, or -2 in case of an argument error). When no arg is passed, receives
439 * anything and stops. Otherwise reads the requested amount of data. 0 means
440 * read as much as possible.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100441 */
442int tcp_recv(int sock, const char *arg)
443{
444 int count = -1; // stop at first read
445 int ret;
446
447 if (arg[1]) {
448 count = atoi(arg + 1);
449 if (count < 0) {
450 fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100451 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100452 }
453 }
454
455 while (1) {
456 ret = recv(sock, NULL, (count > 0) ? count : INT_MAX, MSG_NOSIGNAL | MSG_TRUNC);
457 if (ret < 0) {
458 if (errno == EINTR)
459 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100460 if (errno != EAGAIN) {
461 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100462 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100463 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100464 while (!wait_on_fd(sock, POLLIN));
465 continue;
466 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100467 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100468 if (!ret)
469 break;
470
471 if (!count)
472 continue;
473 else if (count > 0)
474 count -= ret;
475
476 if (count <= 0)
477 break;
478 }
479
480 return 0;
481}
482
Willy Tarreau1973e812016-11-12 18:45:42 +0100483/* Sends N bytes to the socket and returns 0 (or -1 in case of send error, -2
484 * in case of an argument error. If the byte count is not set, sends only one
485 * block. Sending zero means try to send forever. If the argument starts with
486 * ':' then whatever follows is interpreted as the payload to be sent as-is.
487 * Escaped characters '\r', '\n', '\t' and '\\' are detected and converted. In
Willy Tarreau59623e02016-11-12 18:25:45 +0100488 * this case, blocks must be small so that send() doesn't fragment them, as
489 * they will be put into the trash and expected to be sent at once.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100490 */
491int tcp_send(int sock, const char *arg)
492{
493 int count = -1; // stop after first block
494 int ret;
495
Willy Tarreau59623e02016-11-12 18:25:45 +0100496 if (arg[1] == ':') {
497 count = unescape(trash, sizeof(trash), arg + 2);
498 } else if (arg[1]) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100499 count = atoi(arg + 1);
Willy Tarreau869c7592016-11-12 17:50:57 +0100500 if (count < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100501 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100502 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100503 }
504 }
505
506 while (1) {
507 ret = send(sock, trash,
508 (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash),
509 MSG_NOSIGNAL | ((count > sizeof(trash)) ? MSG_MORE : 0));
510 if (ret < 0) {
511 if (errno == EINTR)
512 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100513 if (errno != EAGAIN) {
514 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100515 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100516 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100517 while (!wait_on_fd(sock, POLLOUT));
518 continue;
519 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100520 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100521 if (!count)
522 continue;
523 else if (count > 0)
524 count -= ret;
525
526 if (count <= 0)
527 break;
528 }
529
530 return 0;
531}
532
533/* echoes N bytes to the socket and returns 0 (or -1 in case of error). If not
534 * set, echoes only the first block. Zero means forward forever.
535 */
536int tcp_echo(int sock, const char *arg)
537{
538 int count = -1; // echo forever
539 int ret;
540 int rcvd;
541
542 if (arg[1]) {
543 count = atoi(arg + 1);
544 if (count < 0) {
545 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
546 return -1;
547 }
548 }
549
550 rcvd = 0;
551 while (1) {
552 if (rcvd <= 0) {
553 /* no data pending */
554 rcvd = recv(sock, trash, (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash), MSG_NOSIGNAL);
555 if (rcvd < 0) {
556 if (errno == EINTR)
557 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100558 if (errno != EAGAIN) {
559 dolog("recv %d\n", rcvd);
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, POLLIN));
563 continue;
564 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100565 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100566 if (!rcvd)
567 break;
568 }
569 else {
570 /* some data still pending */
571 ret = send(sock, trash, rcvd, MSG_NOSIGNAL | ((count > rcvd) ? MSG_MORE : 0));
572 if (ret < 0) {
573 if (errno == EINTR)
574 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100575 if (errno != EAGAIN) {
576 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100577 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100578 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100579 while (!wait_on_fd(sock, POLLOUT));
580 continue;
581 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100582 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100583 rcvd -= ret;
584 if (rcvd)
585 continue;
586
587 if (!count)
588 continue;
589 else if (count > 0)
590 count -= ret;
591
592 if (count <= 0)
593 break;
594 }
595 }
596 return 0;
597}
598
599/* waits for an event on the socket, usually indicates an accept for a
600 * listening socket and a connect for an outgoing socket.
601 */
602int tcp_wait(int sock, const char *arg)
603{
604 struct pollfd pollfd;
605 int delay = -1; // wait forever
606 int ret;
607
608 if (arg[1]) {
609 delay = atoi(arg + 1);
610 if (delay < 0) {
611 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
612 return -1;
613 }
614 }
615
616 /* FIXME: this doesn't take into account delivered signals */
617 do {
618 pollfd.fd = sock;
619 pollfd.events = POLLIN | POLLOUT;
620 ret = poll(&pollfd, 1, delay);
621 } while (ret == -1 && errno == EINTR);
622
Willy Tarreau869c7592016-11-12 17:50:57 +0100623 if (ret > 0 && pollfd.revents & POLLERR)
624 return -1;
625
Willy Tarreau84393aa2016-11-12 11:29:46 +0100626 return 0;
627}
628
629/* waits for the input data to be present */
630int tcp_wait_in(int sock, const char *arg)
631{
632 struct pollfd pollfd;
633 int ret;
634
635 do {
636 pollfd.fd = sock;
637 pollfd.events = POLLIN;
638 ret = poll(&pollfd, 1, 1000);
639 } while (ret == -1 && errno == EINTR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100640
641 if (ret > 0 && pollfd.revents & POLLERR)
642 return -1;
643
Willy Tarreau84393aa2016-11-12 11:29:46 +0100644 return 0;
645}
646
647/* waits for the output queue to be empty */
648int tcp_wait_out(int sock, const char *arg)
649{
650 struct pollfd pollfd;
651 int ret;
652
653 do {
654 pollfd.fd = sock;
655 pollfd.events = POLLOUT;
656 ret = poll(&pollfd, 1, 1000);
657 } while (ret == -1 && errno == EINTR);
658
Willy Tarreau869c7592016-11-12 17:50:57 +0100659 if (ret > 0 && pollfd.revents & POLLERR)
660 return -1;
661
Willy Tarreau84393aa2016-11-12 11:29:46 +0100662 /* Now wait for data to leave the socket */
663 do {
664 if (ioctl(sock, TIOCOUTQ, &ret) < 0)
665 return -1;
666 } while (ret > 0);
667 return 0;
668}
669
670/* delays processing for <time> milliseconds, 100 by default */
671int tcp_pause(int sock, const char *arg)
672{
673 struct pollfd pollfd;
674 int delay = 100;
675 int ret;
676
677 if (arg[1]) {
678 delay = atoi(arg + 1);
679 if (delay < 0) {
680 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
681 return -1;
682 }
683 }
684
685 usleep(delay * 1000);
686 return 0;
687}
688
Willy Tarreau95a6b782016-11-12 13:25:53 +0100689/* forks another process while respecting the limit imposed in argument (1 by
690 * default). Will wait for another process to exit before creating a new one.
691 * Returns the value of the fork() syscall, ie 0 for the child, non-zero for
692 * the parent, -1 for an error.
693 */
694int tcp_fork(int sock, const char *arg)
695{
696 int max = 1;
697 int ret;
698
699 if (arg[1]) {
700 max = atoi(arg + 1);
701 if (max <= 0) {
702 fprintf(stderr, "max process must be > 0 or unset (was %d)\n", max);
703 return -1;
704 }
705 }
706
707 while (nbproc >= max)
708 poll(NULL, 0, 1000);
709
710 ret = fork();
711 if (ret > 0)
712 __sync_add_and_fetch(&nbproc, 1);
713 return ret;
714}
715
Willy Tarreau84393aa2016-11-12 11:29:46 +0100716int main(int argc, char **argv)
717{
718 struct sockaddr_storage ss;
719 struct err_msg err;
720 const char *arg0;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100721 int loop_arg;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100722 int arg;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100723 int ret;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100724 int sock;
725
726 arg0 = argv[0];
Willy Tarreau869c7592016-11-12 17:50:57 +0100727
728 while (argc > 1 && argv[1][0] == '-') {
729 argc--; argv++;
730 if (strcmp(argv[0], "-t") == 0)
731 showtime++;
732 else if (strcmp(argv[0], "-tt") == 0)
733 showtime += 2;
734 else if (strcmp(argv[0], "-ttt") == 0)
735 showtime += 3;
736 else if (strcmp(argv[0], "-v") == 0)
737 verbose ++;
738 else if (strcmp(argv[0], "--") == 0)
739 break;
740 else
741 usage(1, arg0);
742 }
743
Willy Tarreau84393aa2016-11-12 11:29:46 +0100744 if (argc < 2)
745 usage(1, arg0);
746
Willy Tarreau869c7592016-11-12 17:50:57 +0100747 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100748 signal(SIGCHLD, sig_handler);
749
Willy Tarreau84393aa2016-11-12 11:29:46 +0100750 if (addr_to_ss(argv[1], &ss, &err) < 0)
751 die(1, "%s\n", err.msg);
752
Willy Tarreau869c7592016-11-12 17:50:57 +0100753 gettimeofday(&start_time, NULL);
754
Willy Tarreau84393aa2016-11-12 11:29:46 +0100755 sock = -1;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100756 loop_arg = 2;
757 for (arg = loop_arg; arg < argc; arg++) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100758 switch (argv[arg][0]) {
759 case 'L':
760 /* silently ignore existing connections */
761 if (sock == -1)
762 sock = tcp_listen(&ss, argv[arg]);
763 if (sock < 0)
764 die(1, "Fatal: tcp_listen() failed.\n");
765 break;
766
767 case 'C':
768 /* silently ignore existing connections */
769 if (sock == -1)
770 sock = tcp_connect(&ss, argv[arg]);
771 if (sock < 0)
772 die(1, "Fatal: tcp_connect() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100773 dolog("connect\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100774 break;
775
776 case 'A':
777 if (sock < 0)
778 die(1, "Fatal: tcp_accept() on non-socket.\n");
779 sock = tcp_accept(sock, argv[arg]);
780 if (sock < 0)
781 die(1, "Fatal: tcp_accept() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100782 dolog("accept\n");
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100783 loop_arg = arg + 1; // cannot loop before accept()
Willy Tarreau84393aa2016-11-12 11:29:46 +0100784 break;
785
786 case 'T':
787 if (sock < 0)
788 die(1, "Fatal: tcp_set_nodelay() on non-socket.\n");
789 if (tcp_set_nodelay(sock, argv[arg]) < 0)
790 die(1, "Fatal: tcp_set_nodelay() failed.\n");
791 break;
792
793 case 'G':
794 if (sock < 0)
795 die(1, "Fatal: tcp_set_nolinger() on non-socket.\n");
796 if (tcp_set_nolinger(sock, argv[arg]) < 0)
797 die(1, "Fatal: tcp_set_nolinger() failed.\n");
798 break;
799
800 case 'Q':
801 if (sock < 0)
802 die(1, "Fatal: tcp_set_noquickack() on non-socket.\n");
803 if (tcp_set_noquickack(sock, argv[arg]) < 0)
804 die(1, "Fatal: tcp_set_noquickack() failed.\n");
805 break;
806
807 case 'R':
808 if (sock < 0)
809 die(1, "Fatal: tcp_recv() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100810 ret = tcp_recv(sock, argv[arg]);
811 if (ret < 0) {
812 if (ret == -1) // usually ECONNRESET, silently exit
813 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100814 die(1, "Fatal: tcp_recv() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100815 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100816 break;
817
818 case 'S':
819 if (sock < 0)
820 die(1, "Fatal: tcp_send() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100821 ret = tcp_send(sock, argv[arg]);
822 if (ret < 0) {
823 if (ret == -1) // usually a broken pipe, silently exit
824 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100825 die(1, "Fatal: tcp_send() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100826 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100827 break;
828
829 case 'E':
830 if (sock < 0)
831 die(1, "Fatal: tcp_echo() on non-socket.\n");
832 if (tcp_echo(sock, argv[arg]) < 0)
833 die(1, "Fatal: tcp_echo() failed.\n");
834 break;
835
836 case 'P':
837 if (tcp_pause(sock, argv[arg]) < 0)
838 die(1, "Fatal: tcp_pause() failed.\n");
839 break;
840
841 case 'W':
842 if (sock < 0)
843 die(1, "Fatal: tcp_wait() on non-socket.\n");
844 if (tcp_wait(sock, argv[arg]) < 0)
845 die(1, "Fatal: tcp_wait() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100846 dolog("ready_any\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100847 break;
848
849 case 'I':
850 if (sock < 0)
851 die(1, "Fatal: tcp_wait_in() on non-socket.\n");
852 if (tcp_wait_in(sock, argv[arg]) < 0)
853 die(1, "Fatal: tcp_wait_in() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100854 dolog("ready_in\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100855 break;
856
857 case 'O':
858 if (sock < 0)
859 die(1, "Fatal: tcp_wait_out() on non-socket.\n");
860 if (tcp_wait_out(sock, argv[arg]) < 0)
861 die(1, "Fatal: tcp_wait_out() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100862 dolog("ready_out\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100863 break;
864
865 case 'K':
866 if (sock < 0 || close(sock) < 0)
867 die(1, "Fatal: close() on non-socket.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100868 dolog("close\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100869 sock = -1;
870 break;
871
872 case 'F':
873 /* ignore errors on shutdown() as they are common */
874 if (sock >= 0)
875 shutdown(sock, SHUT_WR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100876 dolog("shutdown\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100877 break;
878
Willy Tarreau95a6b782016-11-12 13:25:53 +0100879 case 'N':
880 ret = tcp_fork(sock, argv[arg]);
881 if (ret < 0)
882 die(1, "Fatal: fork() failed.\n");
883 if (ret > 0) {
884 /* loop back to first arg */
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100885 arg = loop_arg - 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100886 continue;
887 }
888 /* OK we're in the child, let's continue */
Willy Tarreau869c7592016-11-12 17:50:57 +0100889 pid = getpid();
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100890 loop_arg = arg + 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100891 break;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100892
893 case 'J': // jump back to oldest post-fork action
894 arg = loop_arg - 1;
895 continue;
896
Willy Tarreau84393aa2016-11-12 11:29:46 +0100897 default:
898 usage(1, arg0);
899 }
900 }
901 return 0;
902}