blob: cb9e5f124643d1a9285eecf64e29fd872e855970 [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 Tarreaubcd817e2017-03-14 14:44:06 +0100111 " K : kill the connection and go on with next operation\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100112 " G : disable lingering\n"
113 " T : set TCP_NODELAY\n"
114 " Q : disable TCP Quick-ack\n"
115 " R[<size>] : Read this amount of bytes. 0=infinite. unset=any amount.\n"
116 " S[<size>] : Send this amount of bytes. 0=infinite. unset=any amount.\n"
Willy Tarreau59623e02016-11-12 18:25:45 +0100117 " S:<string> : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100118 " E[<size>] : Echo this amount of bytes. 0=infinite. unset=any amount.\n"
119 " W[<time>] : Wait for any event on the socket, maximum <time> ms\n"
120 " P[<time>] : Pause for <time> ms (100 by default)\n"
121 " I : wait for Input data to be present (POLLIN)\n"
122 " O : wait for Output queue to be empty (POLLOUT + TIOCOUTQ)\n"
123 " F : FIN : shutdown(SHUT_WR)\n"
124 " N<max> : fork New process, limited to <max> concurrent (default 1)\n"
125 "\n"
126 "It's important to note that a single FD is used at once and that Accept\n"
127 "replaces the listening FD with the accepted one. Thus always do it after\n"
128 "a fork if other connections have to be accepted.\n"
129 "\n"
130 "After a fork, we loop back to the beginning and silently skip L/C if the\n"
131 "main socket already exists.\n"
132 "\n"
133 "Example dummy HTTP request drain server :\n"
134 " tcploop 8001 L W N20 A R S10 [ F K ]\n"
135 "\n"
136 "Example large bandwidth HTTP request drain server :\n"
137 " tcploop 8001 L W N20 A R S0 [ F K ]\n"
138 "\n"
139 "Example TCP client with pauses at each step :\n"
140 " tcploop 8001 C T W P100 S10 O P100 R S10 O R G K\n"
141 "", arg0);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100142}
143
Willy Tarreau869c7592016-11-12 17:50:57 +0100144void dolog(const char *format, ...)
145{
146 struct timeval date, tv;
147 int delay;
148 va_list args;
149
150 if (!verbose)
151 return;
152
153 if (showtime) {
154 gettimeofday(&date, NULL);
155 switch (showtime) {
156 case 1: // [msec] relative
157 delay = (date.tv_sec - start_time.tv_sec) * 1000000 + date.tv_usec - start_time.tv_usec;
158 fprintf(stderr, "[%d] ", delay / 1000);
159 break;
160 case 2: // [sec.usec] relative
161 tv.tv_usec = date.tv_usec - start_time.tv_usec;
162 tv.tv_sec = date.tv_sec - start_time.tv_sec;
163 if ((signed)tv.tv_sec > 0) {
164 if ((signed)tv.tv_usec < 0) {
165 tv.tv_usec += 1000000;
166 tv.tv_sec--;
167 }
168 } else if (tv.tv_sec == 0) {
169 if ((signed)tv.tv_usec < 0)
170 tv.tv_usec = 0;
171 } else {
172 tv.tv_sec = 0;
173 tv.tv_usec = 0;
174 }
Willy Tarreau752cc492017-03-14 14:37:13 +0100175 fprintf(stderr, "[%d.%06d] ", (int)tv.tv_sec, (int)tv.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100176 break;
177 default: // [sec.usec] absolute
Willy Tarreau752cc492017-03-14 14:37:13 +0100178 fprintf(stderr, "[%d.%06d] ", (int)date.tv_sec, (int)date.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100179 break;
180 }
181 }
182
183 fprintf(stderr, "%5d ", pid);
184
185 va_start(args, format);
186 vfprintf(stderr, format, args);
187 va_end(args);
188}
189
Willy Tarreau59623e02016-11-12 18:25:45 +0100190/* convert '\n', '\t', '\r', '\\' to their respective characters */
191int unescape(char *out, int size, const char *in)
192{
193 int len;
194
195 for (len = 0; len < size && *in; in++, out++, len++) {
196 if (*in == '\\') {
197 switch (in[1]) {
198 case 'n' : *out = '\n'; in++; continue;
199 case 't' : *out = '\t'; in++; continue;
200 case 'r' : *out = '\r'; in++; continue;
201 case '\\' : *out = '\\'; in++; continue;
202 default : break;
203 }
204 }
205 *out = *in;
206 }
207 return len;
208}
209
Willy Tarreau84393aa2016-11-12 11:29:46 +0100210struct err_msg *alloc_err_msg(int size)
211{
212 struct err_msg *err;
213
214 err = malloc(sizeof(*err) + size);
215 if (err) {
216 err->len = 0;
217 err->size = size;
218 }
219 return err;
220}
221
Willy Tarreau95a6b782016-11-12 13:25:53 +0100222void sig_handler(int sig)
223{
224 if (sig == SIGCHLD) {
225 while (waitpid(-1, NULL, WNOHANG) > 0)
226 __sync_sub_and_fetch(&nbproc, 1);
227 }
228}
Willy Tarreau84393aa2016-11-12 11:29:46 +0100229
230/* converts str in the form [[<ipv4>|<ipv6>|<hostname>]:]port to struct sockaddr_storage.
231 * Returns < 0 with err set in case of error.
232 */
233int addr_to_ss(char *str, struct sockaddr_storage *ss, struct err_msg *err)
234{
235 char *port_str;
236 int port;
237
238 memset(ss, 0, sizeof(*ss));
239
240 /* look for the addr/port delimiter, it's the last colon. If there's no
241 * colon, it's 0:<port>.
242 */
243 if ((port_str = strrchr(str, ':')) == NULL) {
244 port = atoi(str);
245 if (port <= 0 || port > 65535) {
246 err->len = snprintf(err->msg, err->size, "Missing/invalid port number: '%s'\n", str);
247 return -1;
248 }
249
250 ss->ss_family = AF_INET;
251 ((struct sockaddr_in *)ss)->sin_port = htons(port);
252 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
253 return 0;
254 }
255
256 *port_str++ = 0;
257
258 if (strrchr(str, ':') != NULL) {
259 /* IPv6 address contains ':' */
260 ss->ss_family = AF_INET6;
261 ((struct sockaddr_in6 *)ss)->sin6_port = htons(atoi(port_str));
262
263 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in6 *)ss)->sin6_addr)) {
264 err->len = snprintf(err->msg, err->size, "Invalid server address: '%s'\n", str);
265 return -1;
266 }
267 }
268 else {
269 ss->ss_family = AF_INET;
270 ((struct sockaddr_in *)ss)->sin_port = htons(atoi(port_str));
271
272 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
273 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
274 return 0;
275 }
276
277 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in *)ss)->sin_addr)) {
278 struct hostent *he = gethostbyname(str);
279
280 if (he == NULL) {
281 err->len = snprintf(err->msg, err->size, "Invalid server name: '%s'\n", str);
282 return -1;
283 }
284 ((struct sockaddr_in *)ss)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
285 }
286 }
287
288 return 0;
289}
290
291/* waits up to one second on fd <fd> for events <events> (POLLIN|POLLOUT).
292 * returns poll's status.
293 */
294int wait_on_fd(int fd, int events)
295{
296 struct pollfd pollfd;
297 int ret;
298
299 do {
300 pollfd.fd = fd;
301 pollfd.events = events;
302 ret = poll(&pollfd, 1, 1000);
303 } while (ret == -1 && errno == EINTR);
304
305 return ret;
306}
307
308int tcp_set_nodelay(int sock, const char *arg)
309{
310 return setsockopt(sock, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
311}
312
313int tcp_set_nolinger(int sock, const char *arg)
314{
315 return setsockopt(sock, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
316}
317
318int tcp_set_noquickack(int sock, const char *arg)
319{
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100320#ifdef TCP_QUICKACK
Willy Tarreau84393aa2016-11-12 11:29:46 +0100321 /* warning: do not use during connect if nothing is to be sent! */
322 return setsockopt(sock, SOL_TCP, TCP_QUICKACK, &zero, sizeof(zero));
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100323#else
324 return 0;
325#endif
Willy Tarreau84393aa2016-11-12 11:29:46 +0100326}
327
328/* Try to listen to address <sa>. Return the fd or -1 in case of error */
329int tcp_listen(const struct sockaddr_storage *sa, const char *arg)
330{
331 int sock;
332 int backlog;
333
334 if (arg[1])
335 backlog = atoi(arg + 1);
336 else
337 backlog = 1000;
338
339 if (backlog < 0 || backlog > 65535) {
340 fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
341 return -1;
342 }
343
344 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
345 if (sock < 0) {
346 perror("socket()");
347 return -1;
348 }
349
350 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
351 perror("setsockopt(SO_REUSEADDR)");
352 goto fail;
353 }
354
355#ifdef SO_REUSEPORT
356 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)) == -1) {
357 perror("setsockopt(SO_REUSEPORT)");
358 goto fail;
359 }
360#endif
361 if (bind(sock, (struct sockaddr *)sa, sa->ss_family == AF_INET6 ?
362 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == -1) {
363 perror("bind");
364 goto fail;
365 }
366
367 if (listen(sock, backlog) == -1) {
368 perror("listen");
369 goto fail;
370 }
371
372 return sock;
373 fail:
374 close(sock);
375 return -1;
376}
377
378/* accepts a socket from listening socket <sock>, and returns it (or -1 in case of error) */
379int tcp_accept(int sock, const char *arg)
380{
381 int count;
382 int newsock;
383
384 if (arg[1])
385 count = atoi(arg + 1);
386 else
387 count = 1;
388
389 if (count <= 0) {
390 fprintf(stderr, "accept count must be > 0 or unset (was %d)\n", count);
391 return -1;
392 }
393
394 do {
395 newsock = accept(sock, NULL, NULL);
396 if (newsock < 0) { // TODO: improve error handling
397 if (errno == EINTR || errno == EAGAIN || errno == ECONNABORTED)
398 continue;
399 perror("accept()");
400 break;
401 }
402
403 if (count > 1)
404 close(newsock);
405 count--;
406 } while (count > 0);
407
408 fcntl(newsock, F_SETFL, O_NONBLOCK);
409 return newsock;
410}
411
412/* Try to establish a new connection to <sa>. Return the fd or -1 in case of error */
413int tcp_connect(const struct sockaddr_storage *sa, const char *arg)
414{
415 int sock;
416
417 sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
418 if (sock < 0)
419 return -1;
420
421 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
422 goto fail;
423
424 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
425 goto fail;
426
Willy Tarreau24d41b92017-03-14 14:50:05 +0100427 if (connect(sock, (const struct sockaddr *)sa, sizeof(struct sockaddr_in)) < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100428 if (errno != EINPROGRESS)
429 goto fail;
430 }
431
432 return sock;
433 fail:
434 close(sock);
435 return -1;
436}
437
Willy Tarreau1973e812016-11-12 18:45:42 +0100438/* receives N bytes from the socket and returns 0 (or -1 in case of a recv
439 * error, or -2 in case of an argument error). When no arg is passed, receives
440 * anything and stops. Otherwise reads the requested amount of data. 0 means
441 * read as much as possible.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100442 */
443int tcp_recv(int sock, const char *arg)
444{
445 int count = -1; // stop at first read
446 int ret;
Willy Tarreaua84a2db2017-03-14 14:50:52 +0100447 int max;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100448
449 if (arg[1]) {
450 count = atoi(arg + 1);
451 if (count < 0) {
452 fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100453 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100454 }
455 }
456
457 while (1) {
Willy Tarreaua84a2db2017-03-14 14:50:52 +0100458 max = (count > 0) ? count : INT_MAX;
459 if (max > sizeof(trash))
460 max = sizeof(trash);
461 ret = recv(sock, trash, max, MSG_NOSIGNAL | MSG_TRUNC);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100462 if (ret < 0) {
463 if (errno == EINTR)
464 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100465 if (errno != EAGAIN) {
466 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100467 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100468 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100469 while (!wait_on_fd(sock, POLLIN));
470 continue;
471 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100472 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100473 if (!ret)
474 break;
475
476 if (!count)
477 continue;
478 else if (count > 0)
479 count -= ret;
480
481 if (count <= 0)
482 break;
483 }
484
485 return 0;
486}
487
Willy Tarreau1973e812016-11-12 18:45:42 +0100488/* Sends N bytes to the socket and returns 0 (or -1 in case of send error, -2
489 * in case of an argument error. If the byte count is not set, sends only one
490 * block. Sending zero means try to send forever. If the argument starts with
491 * ':' then whatever follows is interpreted as the payload to be sent as-is.
492 * Escaped characters '\r', '\n', '\t' and '\\' are detected and converted. In
Willy Tarreau59623e02016-11-12 18:25:45 +0100493 * this case, blocks must be small so that send() doesn't fragment them, as
494 * they will be put into the trash and expected to be sent at once.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100495 */
496int tcp_send(int sock, const char *arg)
497{
498 int count = -1; // stop after first block
499 int ret;
500
Willy Tarreau59623e02016-11-12 18:25:45 +0100501 if (arg[1] == ':') {
502 count = unescape(trash, sizeof(trash), arg + 2);
503 } else if (arg[1]) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100504 count = atoi(arg + 1);
Willy Tarreau869c7592016-11-12 17:50:57 +0100505 if (count < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100506 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100507 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100508 }
509 }
510
511 while (1) {
512 ret = send(sock, trash,
513 (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash),
514 MSG_NOSIGNAL | ((count > sizeof(trash)) ? MSG_MORE : 0));
515 if (ret < 0) {
516 if (errno == EINTR)
517 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100518 if (errno != EAGAIN) {
519 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100520 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100521 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100522 while (!wait_on_fd(sock, POLLOUT));
523 continue;
524 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100525 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100526 if (!count)
527 continue;
528 else if (count > 0)
529 count -= ret;
530
531 if (count <= 0)
532 break;
533 }
534
535 return 0;
536}
537
538/* echoes N bytes to the socket and returns 0 (or -1 in case of error). If not
539 * set, echoes only the first block. Zero means forward forever.
540 */
541int tcp_echo(int sock, const char *arg)
542{
543 int count = -1; // echo forever
544 int ret;
545 int rcvd;
546
547 if (arg[1]) {
548 count = atoi(arg + 1);
549 if (count < 0) {
550 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
551 return -1;
552 }
553 }
554
555 rcvd = 0;
556 while (1) {
557 if (rcvd <= 0) {
558 /* no data pending */
559 rcvd = recv(sock, trash, (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash), MSG_NOSIGNAL);
560 if (rcvd < 0) {
561 if (errno == EINTR)
562 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100563 if (errno != EAGAIN) {
564 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100565 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100566 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100567 while (!wait_on_fd(sock, POLLIN));
568 continue;
569 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100570 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100571 if (!rcvd)
572 break;
573 }
574 else {
575 /* some data still pending */
576 ret = send(sock, trash, rcvd, MSG_NOSIGNAL | ((count > rcvd) ? MSG_MORE : 0));
577 if (ret < 0) {
578 if (errno == EINTR)
579 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100580 if (errno != EAGAIN) {
581 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100582 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100583 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100584 while (!wait_on_fd(sock, POLLOUT));
585 continue;
586 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100587 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100588 rcvd -= ret;
589 if (rcvd)
590 continue;
591
592 if (!count)
593 continue;
594 else if (count > 0)
595 count -= ret;
596
597 if (count <= 0)
598 break;
599 }
600 }
601 return 0;
602}
603
604/* waits for an event on the socket, usually indicates an accept for a
605 * listening socket and a connect for an outgoing socket.
606 */
607int tcp_wait(int sock, const char *arg)
608{
609 struct pollfd pollfd;
610 int delay = -1; // wait forever
611 int ret;
612
613 if (arg[1]) {
614 delay = atoi(arg + 1);
615 if (delay < 0) {
616 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
617 return -1;
618 }
619 }
620
621 /* FIXME: this doesn't take into account delivered signals */
622 do {
623 pollfd.fd = sock;
624 pollfd.events = POLLIN | POLLOUT;
625 ret = poll(&pollfd, 1, delay);
626 } while (ret == -1 && errno == EINTR);
627
Willy Tarreau869c7592016-11-12 17:50:57 +0100628 if (ret > 0 && pollfd.revents & POLLERR)
629 return -1;
630
Willy Tarreau84393aa2016-11-12 11:29:46 +0100631 return 0;
632}
633
634/* waits for the input data to be present */
635int tcp_wait_in(int sock, const char *arg)
636{
637 struct pollfd pollfd;
638 int ret;
639
640 do {
641 pollfd.fd = sock;
642 pollfd.events = POLLIN;
643 ret = poll(&pollfd, 1, 1000);
644 } while (ret == -1 && errno == EINTR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100645
646 if (ret > 0 && pollfd.revents & POLLERR)
647 return -1;
648
Willy Tarreau84393aa2016-11-12 11:29:46 +0100649 return 0;
650}
651
652/* waits for the output queue to be empty */
653int tcp_wait_out(int sock, const char *arg)
654{
655 struct pollfd pollfd;
656 int ret;
657
658 do {
659 pollfd.fd = sock;
660 pollfd.events = POLLOUT;
661 ret = poll(&pollfd, 1, 1000);
662 } while (ret == -1 && errno == EINTR);
663
Willy Tarreau869c7592016-11-12 17:50:57 +0100664 if (ret > 0 && pollfd.revents & POLLERR)
665 return -1;
666
Willy Tarreau84393aa2016-11-12 11:29:46 +0100667 /* Now wait for data to leave the socket */
668 do {
669 if (ioctl(sock, TIOCOUTQ, &ret) < 0)
670 return -1;
671 } while (ret > 0);
672 return 0;
673}
674
675/* delays processing for <time> milliseconds, 100 by default */
676int tcp_pause(int sock, const char *arg)
677{
678 struct pollfd pollfd;
679 int delay = 100;
680 int ret;
681
682 if (arg[1]) {
683 delay = atoi(arg + 1);
684 if (delay < 0) {
685 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
686 return -1;
687 }
688 }
689
690 usleep(delay * 1000);
691 return 0;
692}
693
Willy Tarreau95a6b782016-11-12 13:25:53 +0100694/* forks another process while respecting the limit imposed in argument (1 by
695 * default). Will wait for another process to exit before creating a new one.
696 * Returns the value of the fork() syscall, ie 0 for the child, non-zero for
697 * the parent, -1 for an error.
698 */
699int tcp_fork(int sock, const char *arg)
700{
701 int max = 1;
702 int ret;
703
704 if (arg[1]) {
705 max = atoi(arg + 1);
706 if (max <= 0) {
707 fprintf(stderr, "max process must be > 0 or unset (was %d)\n", max);
708 return -1;
709 }
710 }
711
712 while (nbproc >= max)
713 poll(NULL, 0, 1000);
714
715 ret = fork();
716 if (ret > 0)
717 __sync_add_and_fetch(&nbproc, 1);
718 return ret;
719}
720
Willy Tarreau84393aa2016-11-12 11:29:46 +0100721int main(int argc, char **argv)
722{
723 struct sockaddr_storage ss;
724 struct err_msg err;
725 const char *arg0;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100726 int loop_arg;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100727 int arg;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100728 int ret;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100729 int sock;
730
731 arg0 = argv[0];
Willy Tarreau869c7592016-11-12 17:50:57 +0100732
733 while (argc > 1 && argv[1][0] == '-') {
734 argc--; argv++;
735 if (strcmp(argv[0], "-t") == 0)
736 showtime++;
737 else if (strcmp(argv[0], "-tt") == 0)
738 showtime += 2;
739 else if (strcmp(argv[0], "-ttt") == 0)
740 showtime += 3;
741 else if (strcmp(argv[0], "-v") == 0)
742 verbose ++;
743 else if (strcmp(argv[0], "--") == 0)
744 break;
745 else
746 usage(1, arg0);
747 }
748
Willy Tarreau84393aa2016-11-12 11:29:46 +0100749 if (argc < 2)
750 usage(1, arg0);
751
Willy Tarreau869c7592016-11-12 17:50:57 +0100752 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100753 signal(SIGCHLD, sig_handler);
754
Willy Tarreau84393aa2016-11-12 11:29:46 +0100755 if (addr_to_ss(argv[1], &ss, &err) < 0)
756 die(1, "%s\n", err.msg);
757
Willy Tarreau869c7592016-11-12 17:50:57 +0100758 gettimeofday(&start_time, NULL);
759
Willy Tarreau84393aa2016-11-12 11:29:46 +0100760 sock = -1;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100761 loop_arg = 2;
762 for (arg = loop_arg; arg < argc; arg++) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100763 switch (argv[arg][0]) {
764 case 'L':
765 /* silently ignore existing connections */
766 if (sock == -1)
767 sock = tcp_listen(&ss, argv[arg]);
768 if (sock < 0)
769 die(1, "Fatal: tcp_listen() failed.\n");
770 break;
771
772 case 'C':
773 /* silently ignore existing connections */
774 if (sock == -1)
775 sock = tcp_connect(&ss, argv[arg]);
776 if (sock < 0)
777 die(1, "Fatal: tcp_connect() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100778 dolog("connect\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100779 break;
780
781 case 'A':
782 if (sock < 0)
783 die(1, "Fatal: tcp_accept() on non-socket.\n");
784 sock = tcp_accept(sock, argv[arg]);
785 if (sock < 0)
786 die(1, "Fatal: tcp_accept() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100787 dolog("accept\n");
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100788 loop_arg = arg + 1; // cannot loop before accept()
Willy Tarreau84393aa2016-11-12 11:29:46 +0100789 break;
790
791 case 'T':
792 if (sock < 0)
793 die(1, "Fatal: tcp_set_nodelay() on non-socket.\n");
794 if (tcp_set_nodelay(sock, argv[arg]) < 0)
795 die(1, "Fatal: tcp_set_nodelay() failed.\n");
796 break;
797
798 case 'G':
799 if (sock < 0)
800 die(1, "Fatal: tcp_set_nolinger() on non-socket.\n");
801 if (tcp_set_nolinger(sock, argv[arg]) < 0)
802 die(1, "Fatal: tcp_set_nolinger() failed.\n");
803 break;
804
805 case 'Q':
806 if (sock < 0)
807 die(1, "Fatal: tcp_set_noquickack() on non-socket.\n");
808 if (tcp_set_noquickack(sock, argv[arg]) < 0)
809 die(1, "Fatal: tcp_set_noquickack() failed.\n");
810 break;
811
812 case 'R':
813 if (sock < 0)
814 die(1, "Fatal: tcp_recv() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100815 ret = tcp_recv(sock, argv[arg]);
816 if (ret < 0) {
817 if (ret == -1) // usually ECONNRESET, silently exit
818 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100819 die(1, "Fatal: tcp_recv() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100820 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100821 break;
822
823 case 'S':
824 if (sock < 0)
825 die(1, "Fatal: tcp_send() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100826 ret = tcp_send(sock, argv[arg]);
827 if (ret < 0) {
828 if (ret == -1) // usually a broken pipe, silently exit
829 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100830 die(1, "Fatal: tcp_send() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100831 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100832 break;
833
834 case 'E':
835 if (sock < 0)
836 die(1, "Fatal: tcp_echo() on non-socket.\n");
837 if (tcp_echo(sock, argv[arg]) < 0)
838 die(1, "Fatal: tcp_echo() failed.\n");
839 break;
840
841 case 'P':
842 if (tcp_pause(sock, argv[arg]) < 0)
843 die(1, "Fatal: tcp_pause() failed.\n");
844 break;
845
846 case 'W':
847 if (sock < 0)
848 die(1, "Fatal: tcp_wait() on non-socket.\n");
849 if (tcp_wait(sock, argv[arg]) < 0)
850 die(1, "Fatal: tcp_wait() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100851 dolog("ready_any\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100852 break;
853
854 case 'I':
855 if (sock < 0)
856 die(1, "Fatal: tcp_wait_in() on non-socket.\n");
857 if (tcp_wait_in(sock, argv[arg]) < 0)
858 die(1, "Fatal: tcp_wait_in() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100859 dolog("ready_in\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100860 break;
861
862 case 'O':
863 if (sock < 0)
864 die(1, "Fatal: tcp_wait_out() on non-socket.\n");
865 if (tcp_wait_out(sock, argv[arg]) < 0)
866 die(1, "Fatal: tcp_wait_out() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100867 dolog("ready_out\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100868 break;
869
870 case 'K':
871 if (sock < 0 || close(sock) < 0)
872 die(1, "Fatal: close() on non-socket.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100873 dolog("close\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100874 sock = -1;
875 break;
876
877 case 'F':
878 /* ignore errors on shutdown() as they are common */
879 if (sock >= 0)
880 shutdown(sock, SHUT_WR);
Willy Tarreau869c7592016-11-12 17:50:57 +0100881 dolog("shutdown\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100882 break;
883
Willy Tarreau95a6b782016-11-12 13:25:53 +0100884 case 'N':
885 ret = tcp_fork(sock, argv[arg]);
886 if (ret < 0)
887 die(1, "Fatal: fork() failed.\n");
888 if (ret > 0) {
889 /* loop back to first arg */
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100890 arg = loop_arg - 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100891 continue;
892 }
893 /* OK we're in the child, let's continue */
Willy Tarreau869c7592016-11-12 17:50:57 +0100894 pid = getpid();
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100895 loop_arg = arg + 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100896 break;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100897
898 case 'J': // jump back to oldest post-fork action
899 arg = loop_arg - 1;
900 continue;
901
Willy Tarreau84393aa2016-11-12 11:29:46 +0100902 default:
903 usage(1, arg0);
904 }
905 }
906 return 0;
907}