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