/* * TCP client and server for bug hunting * * Copyright (C) 2016 Willy Tarreau * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include struct err_msg { int size; int len; char msg[0]; }; const int zero = 0; const int one = 1; const struct linger nolinger = { .l_onoff = 1, .l_linger = 0 }; #define TRASH_SIZE 65536 static char trash[TRASH_SIZE]; volatile int nbproc = 0; static struct timeval start_time; static int showtime; static int verbose; static int pid; /* display the message and exit with the code */ __attribute__((noreturn)) void die(int code, const char *format, ...) { va_list args; if (format) { va_start(args, format); vfprintf(stderr, format, args); va_end(args); } exit(code); } /* display the usage message and exit with the code */ __attribute__((noreturn)) void usage(int code, const char *arg0) { die(code, "Usage : %s [options]* [:]port [*]\n" "\n" "options :\n" " -v : verbose\n" " -t|-tt|-ttt : show time (msec / relative / absolute)\n" "actions :\n" " L[] : Listens to ip:port and optionally sets backlog\n" " Note: fd=socket,bind(fd),listen(fd)\n" " C : Connects to ip:port\n" " Note: fd=socket,connect(fd)\n" " A[] : Accepts incoming sockets and closes count-1\n" " Note: fd=accept(fd)\n" " J : Jump back to oldest post-fork/post-accept action\n" " G : disable lingering\n" " T : set TCP_NODELAY\n" " Q : disable TCP Quick-ack\n" " R[] : Read this amount of bytes. 0=infinite. unset=any amount.\n" " S[] : Send this amount of bytes. 0=infinite. unset=any amount.\n" " S: : Send this exact string. \\r, \\n, \\t, \\\\ supported.\n" " E[] : Echo this amount of bytes. 0=infinite. unset=any amount.\n" " W[