blob: d8e9f0f4b20d6ef4a18d80cb721a5350d925e124 [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 Tarreaue5f72b82022-11-25 16:15:20 +010027#define _GNU_SOURCE // for POLLRDHUP
Willy Tarreau84393aa2016-11-12 11:29:46 +010028#include <sys/resource.h>
29#include <sys/select.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/ioctl.h>
Willy Tarreau95a6b782016-11-12 13:25:53 +010035#include <sys/wait.h>
Willy Tarreaud8a6a322022-11-25 17:05:05 +010036
37#ifdef __linux__
38#include <sys/epoll.h>
39#endif
40
Willy Tarreau84393aa2016-11-12 11:29:46 +010041#include <arpa/inet.h>
42#include <netinet/in.h>
43#include <netinet/tcp.h>
44
45#include <ctype.h>
46#include <errno.h>
47#include <fcntl.h>
Willy Tarreau5cd60672016-12-16 08:02:21 +010048#include <limits.h>
Willy Tarreau84393aa2016-11-12 11:29:46 +010049#include <netdb.h>
50#include <poll.h>
51#include <signal.h>
52#include <stdarg.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <time.h>
57#include <unistd.h>
58
Willy Tarreaue5f72b82022-11-25 16:15:20 +010059/* for OSes which don't have it */
60#ifndef POLLRDHUP
61#define POLLRDHUP 0
62#endif
63
Willy Tarreau0c0c0a62017-03-14 14:36:26 +010064#ifndef MSG_MORE
65#define MSG_MORE 0
66#endif
Willy Tarreau84393aa2016-11-12 11:29:46 +010067
68struct err_msg {
69 int size;
70 int len;
71 char msg[0];
72};
73
74const int zero = 0;
75const int one = 1;
76const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 };
77
78#define TRASH_SIZE 65536
79static char trash[TRASH_SIZE];
80
Willy Tarreau95a6b782016-11-12 13:25:53 +010081volatile int nbproc = 0;
Willy Tarreau869c7592016-11-12 17:50:57 +010082static struct timeval start_time;
83static int showtime;
84static int verbose;
Willy Tarreaud8a6a322022-11-25 17:05:05 +010085static int use_epoll;
Willy Tarreau869c7592016-11-12 17:50:57 +010086static int pid;
Willy Tarreau2d7cd3e2022-06-07 12:09:55 +020087static int sock_type = SOCK_STREAM;
88static int sock_proto = IPPROTO_TCP;
Willy Tarreau869c7592016-11-12 17:50:57 +010089
Willy Tarreau95a6b782016-11-12 13:25:53 +010090
Willy Tarreau84393aa2016-11-12 11:29:46 +010091/* display the message and exit with the code */
92__attribute__((noreturn)) void die(int code, const char *format, ...)
93{
94 va_list args;
95
Willy Tarreau1973e812016-11-12 18:45:42 +010096 if (format) {
97 va_start(args, format);
98 vfprintf(stderr, format, args);
99 va_end(args);
100 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100101 exit(code);
102}
103
104/* display the usage message and exit with the code */
105__attribute__((noreturn)) void usage(int code, const char *arg0)
106{
Willy Tarreau9557bac2016-11-12 17:53:16 +0100107 die(code,
108 "Usage : %s [options]* [<ip>:]port [<action>*]\n"
109 "\n"
110 "options :\n"
111 " -v : verbose\n"
Willy Tarreau2d7cd3e2022-06-07 12:09:55 +0200112 " -u : use UDP instead of TCP (limited)\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100113 " -t|-tt|-ttt : show time (msec / relative / absolute)\n"
Willy Tarreaud8a6a322022-11-25 17:05:05 +0100114 " -e : use epoll instead of poll on Linux\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100115 "actions :\n"
Willy Tarreau98028c82022-06-07 11:29:16 +0200116 " A[<count>] : Accepts <count> incoming sockets and closes count-1\n"
117 " Note: fd=accept(fd)\n"
Willy Tarreaud4933312022-06-07 12:03:48 +0200118 " B[[ip]:port] : Bind a new socket to ip:port or default one if unspecified.\n"
119 " Note: fd=socket,bind(fd)\n"
Willy Tarreau542bf0a2022-06-07 11:46:57 +0200120 " C[[ip]:port] : Connects to ip:port or default ones if unspecified.\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100121 " Note: fd=socket,connect(fd)\n"
Willy Tarreau2e065cb2020-10-14 08:09:48 +0200122 " D : Disconnect (connect to AF_UNSPEC)\n"
Willy Tarreau98028c82022-06-07 11:29:16 +0200123 " E[<size>] : Echo this amount of bytes. 0=infinite. unset=any amount.\n"
124 " F : FIN : shutdown(SHUT_WR)\n"
125 " G : disable lingering\n"
126 " I : wait for Input data to be present (POLLIN)\n"
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100127 " J : Jump back to oldest post-fork/post-accept action\n"
Willy Tarreaubcd817e2017-03-14 14:44:06 +0100128 " K : kill the connection and go on with next operation\n"
Willy Tarreau98028c82022-06-07 11:29:16 +0200129 " L[<backlog>] : Listens to ip:port and optionally sets backlog\n"
130 " Note: fd=socket,bind(fd),listen(fd)\n"
131 " N<max> : fork New process, limited to <max> concurrent (default 1)\n"
132 " O : wait for Output queue to be empty (POLLOUT + TIOCOUTQ)\n"
133 " P[<time>] : Pause for <time> ms (100 by default)\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100134 " Q : disable TCP Quick-ack\n"
135 " R[<size>] : Read this amount of bytes. 0=infinite. unset=any amount.\n"
136 " S[<size>] : Send this amount of bytes. 0=infinite. unset=any amount.\n"
Willy Tarreau59623e02016-11-12 18:25:45 +0100137 " S:<string> : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n"
Willy Tarreau98028c82022-06-07 11:29:16 +0200138 " T : set TCP_NODELAY\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100139 " W[<time>] : Wait for any event on the socket, maximum <time> ms\n"
Willy Tarreaub7a6d0d2017-05-02 22:14:59 +0200140 " X[i|o|e]* ** : execvp() next args passing socket as stdin/stdout/stderr.\n"
141 " If i/o/e present, only stdin/out/err are mapped to socket.\n"
Willy Tarreau98028c82022-06-07 11:29:16 +0200142 " r : shutr : shutdown(SHUT_RD) (pauses a listener or ends recv)\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100143 "\n"
144 "It's important to note that a single FD is used at once and that Accept\n"
145 "replaces the listening FD with the accepted one. Thus always do it after\n"
146 "a fork if other connections have to be accepted.\n"
147 "\n"
148 "After a fork, we loop back to the beginning and silently skip L/C if the\n"
149 "main socket already exists.\n"
150 "\n"
151 "Example dummy HTTP request drain server :\n"
152 " tcploop 8001 L W N20 A R S10 [ F K ]\n"
153 "\n"
154 "Example large bandwidth HTTP request drain server :\n"
155 " tcploop 8001 L W N20 A R S0 [ F K ]\n"
156 "\n"
157 "Example TCP client with pauses at each step :\n"
158 " tcploop 8001 C T W P100 S10 O P100 R S10 O R G K\n"
Willy Tarreaub7a6d0d2017-05-02 22:14:59 +0200159 "\n"
160 "Simple chargen server :\n"
161 " tcploop 8001 L A Xo cat /dev/zero\n"
162 "\n"
163 "Simple telnet server :\n"
164 " tcploop 8001 L W N A X /usr/sbin/in.telnetd\n"
Willy Tarreau9557bac2016-11-12 17:53:16 +0100165 "", arg0);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100166}
167
Willy Tarreau869c7592016-11-12 17:50:57 +0100168void dolog(const char *format, ...)
169{
170 struct timeval date, tv;
171 int delay;
172 va_list args;
173
174 if (!verbose)
175 return;
176
177 if (showtime) {
178 gettimeofday(&date, NULL);
179 switch (showtime) {
180 case 1: // [msec] relative
181 delay = (date.tv_sec - start_time.tv_sec) * 1000000 + date.tv_usec - start_time.tv_usec;
182 fprintf(stderr, "[%d] ", delay / 1000);
183 break;
184 case 2: // [sec.usec] relative
185 tv.tv_usec = date.tv_usec - start_time.tv_usec;
186 tv.tv_sec = date.tv_sec - start_time.tv_sec;
187 if ((signed)tv.tv_sec > 0) {
188 if ((signed)tv.tv_usec < 0) {
189 tv.tv_usec += 1000000;
190 tv.tv_sec--;
191 }
192 } else if (tv.tv_sec == 0) {
193 if ((signed)tv.tv_usec < 0)
194 tv.tv_usec = 0;
195 } else {
196 tv.tv_sec = 0;
197 tv.tv_usec = 0;
198 }
Willy Tarreau752cc492017-03-14 14:37:13 +0100199 fprintf(stderr, "[%d.%06d] ", (int)tv.tv_sec, (int)tv.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100200 break;
201 default: // [sec.usec] absolute
Willy Tarreau752cc492017-03-14 14:37:13 +0100202 fprintf(stderr, "[%d.%06d] ", (int)date.tv_sec, (int)date.tv_usec);
Willy Tarreau869c7592016-11-12 17:50:57 +0100203 break;
204 }
205 }
206
207 fprintf(stderr, "%5d ", pid);
208
209 va_start(args, format);
210 vfprintf(stderr, format, args);
211 va_end(args);
212}
213
Willy Tarreau59623e02016-11-12 18:25:45 +0100214/* convert '\n', '\t', '\r', '\\' to their respective characters */
215int unescape(char *out, int size, const char *in)
216{
217 int len;
218
219 for (len = 0; len < size && *in; in++, out++, len++) {
220 if (*in == '\\') {
221 switch (in[1]) {
222 case 'n' : *out = '\n'; in++; continue;
223 case 't' : *out = '\t'; in++; continue;
224 case 'r' : *out = '\r'; in++; continue;
225 case '\\' : *out = '\\'; in++; continue;
226 default : break;
227 }
228 }
229 *out = *in;
230 }
231 return len;
232}
233
Willy Tarreau84393aa2016-11-12 11:29:46 +0100234struct err_msg *alloc_err_msg(int size)
235{
236 struct err_msg *err;
237
238 err = malloc(sizeof(*err) + size);
239 if (err) {
240 err->len = 0;
241 err->size = size;
242 }
243 return err;
244}
245
Willy Tarreau95a6b782016-11-12 13:25:53 +0100246void sig_handler(int sig)
247{
248 if (sig == SIGCHLD) {
249 while (waitpid(-1, NULL, WNOHANG) > 0)
250 __sync_sub_and_fetch(&nbproc, 1);
251 }
252}
Willy Tarreau84393aa2016-11-12 11:29:46 +0100253
254/* converts str in the form [[<ipv4>|<ipv6>|<hostname>]:]port to struct sockaddr_storage.
255 * Returns < 0 with err set in case of error.
256 */
Willy Tarreau542bf0a2022-06-07 11:46:57 +0200257int addr_to_ss(const char *str, struct sockaddr_storage *ss, struct err_msg *err)
Willy Tarreau84393aa2016-11-12 11:29:46 +0100258{
259 char *port_str;
260 int port;
261
262 memset(ss, 0, sizeof(*ss));
263
264 /* look for the addr/port delimiter, it's the last colon. If there's no
265 * colon, it's 0:<port>.
266 */
267 if ((port_str = strrchr(str, ':')) == NULL) {
268 port = atoi(str);
Willy Tarreaucb284c72022-06-07 12:06:04 +0200269 if (port < 0 || port > 65535) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100270 err->len = snprintf(err->msg, err->size, "Missing/invalid port number: '%s'\n", str);
271 return -1;
272 }
273
274 ss->ss_family = AF_INET;
275 ((struct sockaddr_in *)ss)->sin_port = htons(port);
276 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
277 return 0;
278 }
279
280 *port_str++ = 0;
281
282 if (strrchr(str, ':') != NULL) {
283 /* IPv6 address contains ':' */
284 ss->ss_family = AF_INET6;
285 ((struct sockaddr_in6 *)ss)->sin6_port = htons(atoi(port_str));
286
287 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in6 *)ss)->sin6_addr)) {
288 err->len = snprintf(err->msg, err->size, "Invalid server address: '%s'\n", str);
289 return -1;
290 }
291 }
292 else {
293 ss->ss_family = AF_INET;
294 ((struct sockaddr_in *)ss)->sin_port = htons(atoi(port_str));
295
296 if (*str == '*' || *str == '\0') { /* INADDR_ANY */
297 ((struct sockaddr_in *)ss)->sin_addr.s_addr = INADDR_ANY;
298 return 0;
299 }
300
301 if (!inet_pton(ss->ss_family, str, &((struct sockaddr_in *)ss)->sin_addr)) {
302 struct hostent *he = gethostbyname(str);
303
304 if (he == NULL) {
305 err->len = snprintf(err->msg, err->size, "Invalid server name: '%s'\n", str);
306 return -1;
307 }
308 ((struct sockaddr_in *)ss)->sin_addr = *(struct in_addr *) *(he->h_addr_list);
309 }
310 }
311
312 return 0;
313}
314
Willy Tarreaue5f72b82022-11-25 16:15:20 +0100315/* waits up to <ms> milliseconds on fd <fd> for events <events> (POLLIN|POLLRDHUP|POLLOUT).
Willy Tarreaufd0974c2022-11-25 17:04:05 +0100316 * returns poll's status.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100317 */
Willy Tarreau45c27792022-11-25 16:05:46 +0100318int wait_on_fd(int fd, int events, int ms)
Willy Tarreau84393aa2016-11-12 11:29:46 +0100319{
320 struct pollfd pollfd;
321 int ret;
322
Willy Tarreaud8a6a322022-11-25 17:05:05 +0100323#ifdef __linux__
324 while (use_epoll) {
325 struct epoll_event evt;
326 static int epoll_fd = -1;
327
328 if (epoll_fd == -1)
329 epoll_fd = epoll_create(1024);
330 if (epoll_fd == -1)
331 break;
332 evt.events = ((events & POLLIN) ? EPOLLIN : 0) |
333 ((events & POLLOUT) ? EPOLLOUT : 0) |
334 ((events & POLLRDHUP) ? EPOLLRDHUP : 0);
335 evt.data.fd = fd;
336 epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &evt);
337
338 do {
339 ret = epoll_wait(epoll_fd, &evt, 1, ms);
340 } while (ret == -1 && errno == EINTR);
341
342 evt.data.fd = fd;
343 epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &evt);
344 return ret;
345 }
346#endif
347
Willy Tarreau84393aa2016-11-12 11:29:46 +0100348 do {
349 pollfd.fd = fd;
350 pollfd.events = events;
Willy Tarreau45c27792022-11-25 16:05:46 +0100351 ret = poll(&pollfd, 1, ms);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100352 } while (ret == -1 && errno == EINTR);
353
354 return ret;
355}
356
357int tcp_set_nodelay(int sock, const char *arg)
358{
Willy Tarreau4bfc6632021-03-31 08:45:47 +0200359 return setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one));
Willy Tarreau84393aa2016-11-12 11:29:46 +0100360}
361
362int tcp_set_nolinger(int sock, const char *arg)
363{
364 return setsockopt(sock, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger));
365}
366
367int tcp_set_noquickack(int sock, const char *arg)
368{
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100369#ifdef TCP_QUICKACK
Willy Tarreau84393aa2016-11-12 11:29:46 +0100370 /* warning: do not use during connect if nothing is to be sent! */
Willy Tarreau4bfc6632021-03-31 08:45:47 +0200371 return setsockopt(sock, IPPROTO_TCP, TCP_QUICKACK, &zero, sizeof(zero));
Willy Tarreau0c0c0a62017-03-14 14:36:26 +0100372#else
373 return 0;
374#endif
Willy Tarreau84393aa2016-11-12 11:29:46 +0100375}
376
Willy Tarreauff13dad2022-06-07 11:55:45 +0200377/* Create a new TCP socket for either listening or connecting */
378int tcp_socket()
Willy Tarreau84393aa2016-11-12 11:29:46 +0100379{
380 int sock;
Willy Tarreauff13dad2022-06-07 11:55:45 +0200381
Willy Tarreau2d7cd3e2022-06-07 12:09:55 +0200382 sock = socket(AF_INET, sock_type, sock_proto);
Willy Tarreauff13dad2022-06-07 11:55:45 +0200383 if (sock < 0) {
384 perror("socket()");
385 return -1;
386 }
387
388 return sock;
389}
390
Willy Tarreaud4933312022-06-07 12:03:48 +0200391/* Try to bind to local address <sa>. Return the fd or -1 in case of error.
392 * Supports being passed NULL for arg if none has to be passed.
393 */
394int tcp_bind(int sock, const struct sockaddr_storage *sa, const char *arg)
Willy Tarreauff13dad2022-06-07 11:55:45 +0200395{
Willy Tarreaud4933312022-06-07 12:03:48 +0200396 struct sockaddr_storage conn_addr;
397
398 if (arg && arg[1]) {
399 struct err_msg err;
400
401 if (addr_to_ss(arg + 1, &conn_addr, &err) < 0)
402 die(1, "%s\n", err.msg);
403 sa = &conn_addr;
404 }
405
Willy Tarreau84393aa2016-11-12 11:29:46 +0100406
Willy Tarreauff13dad2022-06-07 11:55:45 +0200407 if (sock < 0) {
408 sock = tcp_socket();
409 if (sock < 0)
410 return sock;
411 }
412
Willy Tarreau84393aa2016-11-12 11:29:46 +0100413 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
414 perror("setsockopt(SO_REUSEADDR)");
415 goto fail;
416 }
417
418#ifdef SO_REUSEPORT
419 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (char *) &one, sizeof(one)) == -1) {
420 perror("setsockopt(SO_REUSEPORT)");
421 goto fail;
422 }
423#endif
424 if (bind(sock, (struct sockaddr *)sa, sa->ss_family == AF_INET6 ?
425 sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) == -1) {
426 perror("bind");
427 goto fail;
428 }
429
Willy Tarreaud4933312022-06-07 12:03:48 +0200430 return sock;
431 fail:
432 close(sock);
433 return -1;
434}
435
436/* Try to listen to address <sa>. Return the fd or -1 in case of error */
437int tcp_listen(int sock, const struct sockaddr_storage *sa, const char *arg)
438{
439 int backlog;
440
441 if (sock < 0) {
442 sock = tcp_bind(sock, sa, NULL);
443 if (sock < 0)
444 return sock;
445 }
446
447 if (arg[1])
448 backlog = atoi(arg + 1);
449 else
450 backlog = 1000;
451
452 if (backlog < 0 || backlog > 65535) {
453 fprintf(stderr, "backlog must be between 0 and 65535 inclusive (was %d)\n", backlog);
454 goto fail;
455 }
456
Willy Tarreau84393aa2016-11-12 11:29:46 +0100457 if (listen(sock, backlog) == -1) {
458 perror("listen");
459 goto fail;
460 }
461
462 return sock;
463 fail:
464 close(sock);
465 return -1;
466}
467
468/* accepts a socket from listening socket <sock>, and returns it (or -1 in case of error) */
469int tcp_accept(int sock, const char *arg)
470{
471 int count;
472 int newsock;
473
474 if (arg[1])
475 count = atoi(arg + 1);
476 else
477 count = 1;
478
479 if (count <= 0) {
480 fprintf(stderr, "accept count must be > 0 or unset (was %d)\n", count);
481 return -1;
482 }
483
484 do {
485 newsock = accept(sock, NULL, NULL);
486 if (newsock < 0) { // TODO: improve error handling
487 if (errno == EINTR || errno == EAGAIN || errno == ECONNABORTED)
488 continue;
489 perror("accept()");
490 break;
491 }
492
493 if (count > 1)
494 close(newsock);
495 count--;
496 } while (count > 0);
497
498 fcntl(newsock, F_SETFL, O_NONBLOCK);
499 return newsock;
500}
501
502/* Try to establish a new connection to <sa>. Return the fd or -1 in case of error */
Willy Tarreauff13dad2022-06-07 11:55:45 +0200503int tcp_connect(int sock, const struct sockaddr_storage *sa, const char *arg)
Willy Tarreau84393aa2016-11-12 11:29:46 +0100504{
Willy Tarreau542bf0a2022-06-07 11:46:57 +0200505 struct sockaddr_storage conn_addr;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100506
Willy Tarreau542bf0a2022-06-07 11:46:57 +0200507 if (arg[1]) {
508 struct err_msg err;
509
510 if (addr_to_ss(arg + 1, &conn_addr, &err) < 0)
511 die(1, "%s\n", err.msg);
512 sa = &conn_addr;
513 }
514
Willy Tarreauff13dad2022-06-07 11:55:45 +0200515 if (sock < 0) {
516 sock = tcp_socket();
517 if (sock < 0)
518 return sock;
519 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100520
521 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
522 goto fail;
523
524 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1)
525 goto fail;
526
Willy Tarreau24d41b92017-03-14 14:50:05 +0100527 if (connect(sock, (const struct sockaddr *)sa, sizeof(struct sockaddr_in)) < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100528 if (errno != EINPROGRESS)
529 goto fail;
530 }
531
532 return sock;
533 fail:
534 close(sock);
535 return -1;
536}
537
Willy Tarreau2e065cb2020-10-14 08:09:48 +0200538/* Try to disconnect by connecting to AF_UNSPEC. Return >=0 on success, -1 in case of error */
539int tcp_disconnect(int sock)
540{
541 const struct sockaddr sa = { .sa_family = AF_UNSPEC };
542
543 return connect(sock, &sa, sizeof(sa));
544}
545
Willy Tarreau1973e812016-11-12 18:45:42 +0100546/* receives N bytes from the socket and returns 0 (or -1 in case of a recv
547 * error, or -2 in case of an argument error). When no arg is passed, receives
548 * anything and stops. Otherwise reads the requested amount of data. 0 means
549 * read as much as possible.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100550 */
551int tcp_recv(int sock, const char *arg)
552{
553 int count = -1; // stop at first read
554 int ret;
Willy Tarreaua84a2db2017-03-14 14:50:52 +0100555 int max;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100556
557 if (arg[1]) {
558 count = atoi(arg + 1);
559 if (count < 0) {
560 fprintf(stderr, "recv count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100561 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100562 }
563 }
564
565 while (1) {
Willy Tarreaua84a2db2017-03-14 14:50:52 +0100566 max = (count > 0) ? count : INT_MAX;
567 if (max > sizeof(trash))
568 max = sizeof(trash);
569 ret = recv(sock, trash, max, MSG_NOSIGNAL | MSG_TRUNC);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100570 if (ret < 0) {
571 if (errno == EINTR)
572 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100573 if (errno != EAGAIN) {
574 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100575 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100576 }
Willy Tarreaue5f72b82022-11-25 16:15:20 +0100577 while (!wait_on_fd(sock, POLLIN | POLLRDHUP, 1000));
Willy Tarreau84393aa2016-11-12 11:29:46 +0100578 continue;
579 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100580 dolog("recv %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100581 if (!ret)
582 break;
583
584 if (!count)
585 continue;
586 else if (count > 0)
587 count -= ret;
588
589 if (count <= 0)
590 break;
591 }
592
593 return 0;
594}
595
Willy Tarreau1973e812016-11-12 18:45:42 +0100596/* Sends N bytes to the socket and returns 0 (or -1 in case of send error, -2
597 * in case of an argument error. If the byte count is not set, sends only one
598 * block. Sending zero means try to send forever. If the argument starts with
599 * ':' then whatever follows is interpreted as the payload to be sent as-is.
600 * Escaped characters '\r', '\n', '\t' and '\\' are detected and converted. In
Willy Tarreau59623e02016-11-12 18:25:45 +0100601 * this case, blocks must be small so that send() doesn't fragment them, as
602 * they will be put into the trash and expected to be sent at once.
Willy Tarreau84393aa2016-11-12 11:29:46 +0100603 */
604int tcp_send(int sock, const char *arg)
605{
606 int count = -1; // stop after first block
607 int ret;
608
Willy Tarreau59623e02016-11-12 18:25:45 +0100609 if (arg[1] == ':') {
610 count = unescape(trash, sizeof(trash), arg + 2);
611 } else if (arg[1]) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100612 count = atoi(arg + 1);
Willy Tarreau869c7592016-11-12 17:50:57 +0100613 if (count < 0) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100614 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
Willy Tarreau1973e812016-11-12 18:45:42 +0100615 return -2;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100616 }
617 }
618
619 while (1) {
620 ret = send(sock, trash,
621 (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash),
622 MSG_NOSIGNAL | ((count > sizeof(trash)) ? MSG_MORE : 0));
623 if (ret < 0) {
624 if (errno == EINTR)
625 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100626 if (errno != EAGAIN) {
627 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100628 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100629 }
Willy Tarreau45c27792022-11-25 16:05:46 +0100630 while (!wait_on_fd(sock, POLLOUT, 1000));
Willy Tarreau84393aa2016-11-12 11:29:46 +0100631 continue;
632 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100633 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100634 if (!count)
635 continue;
636 else if (count > 0)
637 count -= ret;
638
639 if (count <= 0)
640 break;
641 }
642
643 return 0;
644}
645
646/* echoes N bytes to the socket and returns 0 (or -1 in case of error). If not
647 * set, echoes only the first block. Zero means forward forever.
648 */
649int tcp_echo(int sock, const char *arg)
650{
651 int count = -1; // echo forever
652 int ret;
653 int rcvd;
654
655 if (arg[1]) {
656 count = atoi(arg + 1);
657 if (count < 0) {
658 fprintf(stderr, "send count must be >= 0 or unset (was %d)\n", count);
659 return -1;
660 }
661 }
662
663 rcvd = 0;
664 while (1) {
665 if (rcvd <= 0) {
666 /* no data pending */
667 rcvd = recv(sock, trash, (count > 0) && (count < sizeof(trash)) ? count : sizeof(trash), MSG_NOSIGNAL);
668 if (rcvd < 0) {
669 if (errno == EINTR)
670 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100671 if (errno != EAGAIN) {
672 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100673 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100674 }
Willy Tarreaue5f72b82022-11-25 16:15:20 +0100675 while (!wait_on_fd(sock, POLLIN | POLLRDHUP, 1000));
Willy Tarreau84393aa2016-11-12 11:29:46 +0100676 continue;
677 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100678 dolog("recv %d\n", rcvd);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100679 if (!rcvd)
680 break;
681 }
682 else {
683 /* some data still pending */
684 ret = send(sock, trash, rcvd, MSG_NOSIGNAL | ((count > rcvd) ? MSG_MORE : 0));
685 if (ret < 0) {
686 if (errno == EINTR)
687 continue;
Willy Tarreau869c7592016-11-12 17:50:57 +0100688 if (errno != EAGAIN) {
689 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100690 return -1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100691 }
Willy Tarreau45c27792022-11-25 16:05:46 +0100692 while (!wait_on_fd(sock, POLLOUT, 1000));
Willy Tarreau84393aa2016-11-12 11:29:46 +0100693 continue;
694 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100695 dolog("send %d\n", ret);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100696 rcvd -= ret;
697 if (rcvd)
698 continue;
699
700 if (!count)
701 continue;
702 else if (count > 0)
703 count -= ret;
704
705 if (count <= 0)
706 break;
707 }
708 }
709 return 0;
710}
711
712/* waits for an event on the socket, usually indicates an accept for a
713 * listening socket and a connect for an outgoing socket.
714 */
715int tcp_wait(int sock, const char *arg)
716{
Willy Tarreau84393aa2016-11-12 11:29:46 +0100717 int delay = -1; // wait forever
718 int ret;
719
720 if (arg[1]) {
721 delay = atoi(arg + 1);
722 if (delay < 0) {
723 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
724 return -1;
725 }
726 }
727
728 /* FIXME: this doesn't take into account delivered signals */
Willy Tarreaue5f72b82022-11-25 16:15:20 +0100729 ret = wait_on_fd(sock, POLLIN | POLLRDHUP | POLLOUT, delay);
Willy Tarreau45c27792022-11-25 16:05:46 +0100730 if (ret < 0)
731 return ret;
Willy Tarreau869c7592016-11-12 17:50:57 +0100732
Willy Tarreau84393aa2016-11-12 11:29:46 +0100733 return 0;
734}
735
736/* waits for the input data to be present */
737int tcp_wait_in(int sock, const char *arg)
738{
Willy Tarreau84393aa2016-11-12 11:29:46 +0100739 int ret;
740
Willy Tarreaue5f72b82022-11-25 16:15:20 +0100741 ret = wait_on_fd(sock, POLLIN | POLLRDHUP, 1000);
Willy Tarreau45c27792022-11-25 16:05:46 +0100742 if (ret < 0)
743 return ret;
Willy Tarreau869c7592016-11-12 17:50:57 +0100744
Willy Tarreau84393aa2016-11-12 11:29:46 +0100745 return 0;
746}
747
748/* waits for the output queue to be empty */
749int tcp_wait_out(int sock, const char *arg)
750{
Willy Tarreau84393aa2016-11-12 11:29:46 +0100751 int ret;
752
Willy Tarreau45c27792022-11-25 16:05:46 +0100753 ret = wait_on_fd(sock, POLLOUT, 1000);
754 if (ret < 0)
755 return ret;
Willy Tarreau869c7592016-11-12 17:50:57 +0100756
Willy Tarreau84393aa2016-11-12 11:29:46 +0100757 /* Now wait for data to leave the socket */
758 do {
759 if (ioctl(sock, TIOCOUTQ, &ret) < 0)
760 return -1;
761 } while (ret > 0);
762 return 0;
763}
764
765/* delays processing for <time> milliseconds, 100 by default */
766int tcp_pause(int sock, const char *arg)
767{
Willy Tarreau84393aa2016-11-12 11:29:46 +0100768 int delay = 100;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100769
770 if (arg[1]) {
771 delay = atoi(arg + 1);
772 if (delay < 0) {
773 fprintf(stderr, "wait time must be >= 0 or unset (was %d)\n", delay);
774 return -1;
775 }
776 }
777
778 usleep(delay * 1000);
779 return 0;
780}
781
Willy Tarreau95a6b782016-11-12 13:25:53 +0100782/* forks another process while respecting the limit imposed in argument (1 by
783 * default). Will wait for another process to exit before creating a new one.
784 * Returns the value of the fork() syscall, ie 0 for the child, non-zero for
785 * the parent, -1 for an error.
786 */
787int tcp_fork(int sock, const char *arg)
788{
789 int max = 1;
790 int ret;
791
792 if (arg[1]) {
793 max = atoi(arg + 1);
794 if (max <= 0) {
795 fprintf(stderr, "max process must be > 0 or unset (was %d)\n", max);
796 return -1;
797 }
798 }
799
800 while (nbproc >= max)
801 poll(NULL, 0, 1000);
802
803 ret = fork();
804 if (ret > 0)
805 __sync_add_and_fetch(&nbproc, 1);
806 return ret;
807}
808
Willy Tarreau84393aa2016-11-12 11:29:46 +0100809int main(int argc, char **argv)
810{
Willy Tarreau7184ca22022-06-07 11:36:20 +0200811 struct sockaddr_storage default_addr;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100812 struct err_msg err;
813 const char *arg0;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100814 int loop_arg;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100815 int arg;
Willy Tarreau95a6b782016-11-12 13:25:53 +0100816 int ret;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100817 int sock;
Willy Tarreaub7a6d0d2017-05-02 22:14:59 +0200818 int errfd;
Willy Tarreau84393aa2016-11-12 11:29:46 +0100819
820 arg0 = argv[0];
Willy Tarreau869c7592016-11-12 17:50:57 +0100821
822 while (argc > 1 && argv[1][0] == '-') {
823 argc--; argv++;
824 if (strcmp(argv[0], "-t") == 0)
825 showtime++;
826 else if (strcmp(argv[0], "-tt") == 0)
827 showtime += 2;
828 else if (strcmp(argv[0], "-ttt") == 0)
829 showtime += 3;
Willy Tarreaud8a6a322022-11-25 17:05:05 +0100830 else if (strcmp(argv[0], "-e") == 0)
831 use_epoll = 1;
Willy Tarreau869c7592016-11-12 17:50:57 +0100832 else if (strcmp(argv[0], "-v") == 0)
833 verbose ++;
Willy Tarreau2d7cd3e2022-06-07 12:09:55 +0200834 else if (strcmp(argv[0], "-u") == 0) {
835 sock_type = SOCK_DGRAM;
836 sock_proto = IPPROTO_UDP;
837 }
Willy Tarreau869c7592016-11-12 17:50:57 +0100838 else if (strcmp(argv[0], "--") == 0)
839 break;
840 else
841 usage(1, arg0);
842 }
843
Willy Tarreau84393aa2016-11-12 11:29:46 +0100844 if (argc < 2)
845 usage(1, arg0);
846
Willy Tarreau869c7592016-11-12 17:50:57 +0100847 pid = getpid();
Willy Tarreau95a6b782016-11-12 13:25:53 +0100848 signal(SIGCHLD, sig_handler);
849
Willy Tarreau7184ca22022-06-07 11:36:20 +0200850 if (addr_to_ss(argv[1], &default_addr, &err) < 0)
Willy Tarreau84393aa2016-11-12 11:29:46 +0100851 die(1, "%s\n", err.msg);
852
Willy Tarreau869c7592016-11-12 17:50:57 +0100853 gettimeofday(&start_time, NULL);
854
Willy Tarreau84393aa2016-11-12 11:29:46 +0100855 sock = -1;
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100856 loop_arg = 2;
857 for (arg = loop_arg; arg < argc; arg++) {
Willy Tarreau84393aa2016-11-12 11:29:46 +0100858 switch (argv[arg][0]) {
859 case 'L':
Willy Tarreaud4933312022-06-07 12:03:48 +0200860 sock = tcp_listen(sock, &default_addr, argv[arg]);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100861 if (sock < 0)
862 die(1, "Fatal: tcp_listen() failed.\n");
863 break;
864
Willy Tarreaud4933312022-06-07 12:03:48 +0200865 case 'B':
Willy Tarreau84393aa2016-11-12 11:29:46 +0100866 /* silently ignore existing connections */
Willy Tarreaud4933312022-06-07 12:03:48 +0200867 sock = tcp_bind(sock, &default_addr, argv[arg]);
868 if (sock < 0)
869 die(1, "Fatal: tcp_connect() failed.\n");
870 dolog("connect\n");
871 break;
872
873 case 'C':
874 sock = tcp_connect(sock, &default_addr, argv[arg]);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100875 if (sock < 0)
876 die(1, "Fatal: tcp_connect() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100877 dolog("connect\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100878 break;
879
Willy Tarreau2e065cb2020-10-14 08:09:48 +0200880 case 'D':
881 /* silently ignore non-existing connections */
882 if (sock >= 0 && tcp_disconnect(sock) < 0)
883 die(1, "Fatal: tcp_connect() failed.\n");
884 dolog("disconnect\n");
885 break;
886
Willy Tarreau84393aa2016-11-12 11:29:46 +0100887 case 'A':
888 if (sock < 0)
889 die(1, "Fatal: tcp_accept() on non-socket.\n");
890 sock = tcp_accept(sock, argv[arg]);
891 if (sock < 0)
892 die(1, "Fatal: tcp_accept() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100893 dolog("accept\n");
Willy Tarreau29cc11c2016-11-12 18:54:20 +0100894 loop_arg = arg + 1; // cannot loop before accept()
Willy Tarreau84393aa2016-11-12 11:29:46 +0100895 break;
896
897 case 'T':
898 if (sock < 0)
899 die(1, "Fatal: tcp_set_nodelay() on non-socket.\n");
900 if (tcp_set_nodelay(sock, argv[arg]) < 0)
901 die(1, "Fatal: tcp_set_nodelay() failed.\n");
902 break;
903
904 case 'G':
905 if (sock < 0)
906 die(1, "Fatal: tcp_set_nolinger() on non-socket.\n");
907 if (tcp_set_nolinger(sock, argv[arg]) < 0)
908 die(1, "Fatal: tcp_set_nolinger() failed.\n");
909 break;
910
911 case 'Q':
912 if (sock < 0)
913 die(1, "Fatal: tcp_set_noquickack() on non-socket.\n");
914 if (tcp_set_noquickack(sock, argv[arg]) < 0)
915 die(1, "Fatal: tcp_set_noquickack() failed.\n");
916 break;
917
918 case 'R':
919 if (sock < 0)
920 die(1, "Fatal: tcp_recv() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100921 ret = tcp_recv(sock, argv[arg]);
922 if (ret < 0) {
923 if (ret == -1) // usually ECONNRESET, silently exit
924 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100925 die(1, "Fatal: tcp_recv() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100926 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100927 break;
928
929 case 'S':
930 if (sock < 0)
931 die(1, "Fatal: tcp_send() on non-socket.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100932 ret = tcp_send(sock, argv[arg]);
933 if (ret < 0) {
934 if (ret == -1) // usually a broken pipe, silently exit
935 die(0, NULL);
Willy Tarreau84393aa2016-11-12 11:29:46 +0100936 die(1, "Fatal: tcp_send() failed.\n");
Willy Tarreau1973e812016-11-12 18:45:42 +0100937 }
Willy Tarreau84393aa2016-11-12 11:29:46 +0100938 break;
939
940 case 'E':
941 if (sock < 0)
942 die(1, "Fatal: tcp_echo() on non-socket.\n");
943 if (tcp_echo(sock, argv[arg]) < 0)
944 die(1, "Fatal: tcp_echo() failed.\n");
945 break;
946
947 case 'P':
948 if (tcp_pause(sock, argv[arg]) < 0)
949 die(1, "Fatal: tcp_pause() failed.\n");
950 break;
951
952 case 'W':
953 if (sock < 0)
954 die(1, "Fatal: tcp_wait() on non-socket.\n");
955 if (tcp_wait(sock, argv[arg]) < 0)
956 die(1, "Fatal: tcp_wait() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100957 dolog("ready_any\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100958 break;
959
960 case 'I':
961 if (sock < 0)
962 die(1, "Fatal: tcp_wait_in() on non-socket.\n");
963 if (tcp_wait_in(sock, argv[arg]) < 0)
964 die(1, "Fatal: tcp_wait_in() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100965 dolog("ready_in\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100966 break;
967
968 case 'O':
969 if (sock < 0)
970 die(1, "Fatal: tcp_wait_out() on non-socket.\n");
971 if (tcp_wait_out(sock, argv[arg]) < 0)
972 die(1, "Fatal: tcp_wait_out() failed.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100973 dolog("ready_out\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100974 break;
975
976 case 'K':
977 if (sock < 0 || close(sock) < 0)
978 die(1, "Fatal: close() on non-socket.\n");
Willy Tarreau869c7592016-11-12 17:50:57 +0100979 dolog("close\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100980 sock = -1;
981 break;
982
983 case 'F':
984 /* ignore errors on shutdown() as they are common */
985 if (sock >= 0)
986 shutdown(sock, SHUT_WR);
Willy Tarreauc3890e52017-10-05 06:31:10 +0200987 dolog("shutdown(w)\n");
988 break;
989
990 case 'r':
991 /* ignore errors on shutdown() as they are common */
992 if (sock >= 0)
993 shutdown(sock, SHUT_RD);
994 dolog("shutdown(r)\n");
Willy Tarreau84393aa2016-11-12 11:29:46 +0100995 break;
996
Willy Tarreau95a6b782016-11-12 13:25:53 +0100997 case 'N':
998 ret = tcp_fork(sock, argv[arg]);
999 if (ret < 0)
1000 die(1, "Fatal: fork() failed.\n");
1001 if (ret > 0) {
1002 /* loop back to first arg */
Willy Tarreau29cc11c2016-11-12 18:54:20 +01001003 arg = loop_arg - 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +01001004 continue;
1005 }
1006 /* OK we're in the child, let's continue */
Willy Tarreau869c7592016-11-12 17:50:57 +01001007 pid = getpid();
Willy Tarreau29cc11c2016-11-12 18:54:20 +01001008 loop_arg = arg + 1;
Willy Tarreau95a6b782016-11-12 13:25:53 +01001009 break;
Willy Tarreau29cc11c2016-11-12 18:54:20 +01001010
1011 case 'J': // jump back to oldest post-fork action
1012 arg = loop_arg - 1;
1013 continue;
1014
Willy Tarreaub7a6d0d2017-05-02 22:14:59 +02001015 case 'X': // execute command. Optionally supports redirecting only i/o/e
1016 if (arg + 1 >= argc)
1017 die(1, "Fatal: missing argument after %s\n", argv[arg]);
1018
1019 errfd = dup(2);
1020 fcntl(errfd, F_SETFD, fcntl(errfd, F_GETFD, FD_CLOEXEC) | FD_CLOEXEC);
1021 fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, O_NONBLOCK) & ~O_NONBLOCK);
1022 if (!argv[arg][1] || strchr(argv[arg], 'i'))
1023 dup2(sock, 0);
1024 if (!argv[arg][1] || strchr(argv[arg], 'o'))
1025 dup2(sock, 1);
1026 if (!argv[arg][1] || strchr(argv[arg], 'e'))
1027 dup2(sock, 2);
1028 argv += arg + 1;
1029 if (execvp(argv[0], argv) == -1) {
1030 int e = errno;
1031
1032 dup2(errfd, 2); // restore original stderr
1033 close(errfd);
1034 die(1, "Fatal: execvp(%s) failed : %s\n", argv[0], strerror(e));
1035 }
1036 break;
Willy Tarreau84393aa2016-11-12 11:29:46 +01001037 default:
1038 usage(1, arg0);
1039 }
1040 }
1041 return 0;
1042}