blob: 197edca4e98dfdfc1b26c45a31db0a3d69957595 [file] [log] [blame]
Denis Vlasenkoba2fb712007-04-01 09:39:03 +00001/* Based on ipsvd utilities written by Gerrit Pape <pape@smarden.org>
2 * which are released into public domain by the author.
3 * Homepage: http://smarden.sunsite.dk/ipsvd/
4 *
Denis Vlasenko57a426b2007-04-01 10:59:33 +00005 * Copyright (C) 2007 Denis Vlasenko.
Denis Vlasenkoba2fb712007-04-01 09:39:03 +00006 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options
11 * which are supported by one from ipsvd-0.12.1, but not all are
12 * functional. See help text at the end of this file for details.
13 *
14 * Code inside "#ifdef SSLSVD" is for sslsvd and is currently unused.
15 * Code inside #if 0" is parts of original tcpsvd which are not implemented
16 * for busyboxed version.
Denis Vlasenko57a426b2007-04-01 10:59:33 +000017 *
18 * Output of verbose mode matches original (modulo bugs and
19 * unimplemented stuff). Unnatural splitting of IP and PORT
20 * is retained (personally I prefer one-value "IP:PORT" notation -
21 * it is a natural string representation of struct sockaddr_XX).
22 *
23 * TCPORIGDST{IP,PORT} is busybox-specific addition
Denis Vlasenkoba2fb712007-04-01 09:39:03 +000024 */
Denis Vlasenko2856dab2007-04-01 01:18:20 +000025
Denis Vlasenko57a426b2007-04-01 10:59:33 +000026#include <limits.h>
27#include <linux/netfilter_ipv4.h> /* wants <limits.h> */
Denis Vlasenko2856dab2007-04-01 01:18:20 +000028#include "busybox.h"
29#include "ipsvd_perhost.h"
30
31#ifdef SSLSVD
32#include "matrixSsl.h"
33#include "ssl_io.h"
34#endif
35
36
37static unsigned max_per_host; /* originally in ipsvd_check.c */
38static unsigned cur_per_host;
39static unsigned verbose;
40static unsigned cnum;
41static unsigned cmax = 30;
42
43/* Must match getopt32 in main! */
44enum {
45 OPT_c = (1 << 0),
46 OPT_C = (1 << 1),
47 OPT_i = (1 << 2),
48 OPT_x = (1 << 3),
49 OPT_u = (1 << 4),
50 OPT_l = (1 << 5),
51 OPT_E = (1 << 6),
52 OPT_b = (1 << 7),
53 OPT_h = (1 << 8),
54 OPT_p = (1 << 9),
55 OPT_t = (1 << 10),
56 OPT_v = (1 << 11),
57 OPT_V = (1 << 12),
Denis Vlasenko57a426b2007-04-01 10:59:33 +000058 OPT_U = (1 << 13), /* from here: sslsvd only */
Denis Vlasenko2856dab2007-04-01 01:18:20 +000059 OPT_slash = (1 << 14),
60 OPT_Z = (1 << 15),
61 OPT_K = (1 << 16),
62};
63
64static void connection_status(void)
65{
66 printf("%s: info: status %u/%u\n", applet_name, cnum, cmax);
67}
68
69static void sig_term_handler(int sig)
70{
71 if (verbose)
72 printf("%s: info: sigterm received, exit\n", applet_name);
73 exit(0);
74}
75
76static void sig_child_handler(int sig)
77{
78 int wstat;
79 int pid;
80
81 while ((pid = wait_nohang(&wstat)) > 0) {
82 if (max_per_host)
83 ipsvd_perhost_remove(pid);
84 if (cnum)
85 cnum--;
86 if (verbose) {
87 /* Little bloated, but tries to give accurate info
88 * how child exited. Makes easier to spot segfaulting
89 * children etc... */
90 unsigned e = 0;
91 const char *cause = "?exit";
92 if (WIFEXITED(wstat)) {
93 cause++;
94 e = WEXITSTATUS(wstat);
95 } else if (WIFSIGNALED(wstat)) {
96 cause = "signal";
97 e = WTERMSIG(wstat);
98 }
99 printf("%s: info: end %d %s %d\n",
100 applet_name, pid, cause, e);
101 }
102 }
103 if (verbose)
104 connection_status();
105}
106
107int tcpsvd_main(int argc, char **argv);
108int tcpsvd_main(int argc, char **argv)
109{
110 char *str_c, *str_C, *str_b, *str_t;
111 char *user;
112 struct hcc *hccp;
113 const char *instructs;
114 char *msg_per_host = NULL;
115 unsigned len_per_host = len_per_host; /* gcc */
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000116 int need_hostnames, need_remote_ip;
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000117 int pid;
118 int sock;
119 int conn;
120 unsigned backlog = 20;
121 union {
122 struct sockaddr sa;
123 struct sockaddr_in sin;
124 USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
125 } sock_adr;
126 socklen_t sockadr_size;
127 uint16_t local_port = local_port;
128 uint16_t remote_port;
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000129 char *local_hostname = NULL;
130 char *remote_hostname = (char*)""; /* "" used if no -h */
131 char *local_ip = local_ip;
132 char *remote_ip = NULL;
133 //unsigned iscdb = 0; /* = option_mask32 & OPT_x (TODO) */
134 //unsigned long timeout = 0;
135#ifndef SSLSVD
136 struct bb_uidgid_t ugid;
137#endif
138
139 /* 3+ args, -i at most once, -p implies -h, -v is counter */
140 opt_complementary = "-3:?:i--i:ph:vv";
141#ifdef SSLSVD
142 getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:",
143 &str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
144 &str_b, &str_t, &ssluser, &root, &cert, &key, &verbose
145 );
146#else
147 getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:v",
148 &str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
149 &str_b, &str_t, &verbose
150 );
151#endif
152 if (option_mask32 & OPT_c)
153 cmax = xatou_range(str_c, 1, INT_MAX);
154 if (option_mask32 & OPT_C) { /* -C n[:message] */
155 max_per_host = bb_strtou(str_C, &str_C, 10);
156 if (str_C[0]) {
157 if (str_C[0] != ':')
158 bb_show_usage();
159 msg_per_host = str_C + 1;
160 len_per_host = strlen(msg_per_host);
161 }
162 }
163 if (max_per_host > cmax)
164 max_per_host = cmax;
165 if (option_mask32 & OPT_u) {
166 if (!get_uidgid(&ugid, user, 1))
167 bb_error_msg_and_die("unknown user/group: %s", user);
168 }
169 if (option_mask32 & OPT_b)
170 backlog = xatou(str_b);
171// if (option_mask32 & OPT_t) timeout = xatou(str_t);
172#ifdef SSLSVD
173 if (option_mask32 & OPT_U) ssluser = (char*)optarg; break;
174 if (option_mask32 & OPT_slash) root = (char*)optarg; break;
175 if (option_mask32 & OPT_Z) cert = (char*)optarg; break;
176 if (option_mask32 & OPT_K) key = (char*)optarg; break;
177#endif
178 argv += optind;
179 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
180 argv[0] = (char*)"0.0.0.0";
181
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000182 setlinebuf(stdout);
183 need_hostnames = verbose || !(option_mask32 & OPT_E);
184 need_remote_ip = max_per_host || need_hostnames;
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000185
186#ifdef SSLSVD
187 sslser = user;
188 client = 0;
189 if ((getuid() == 0) && !(option_mask32 & OPT_u)) {
190 xfunc_exitcode = 100;
191 bb_error_msg_and_die("fatal: -U ssluser must be set when running as root");
192 }
193 if (option_mask32 & OPT_u)
194 if (!uidgid_get(&sslugid, ssluser, 1)) {
195 if (errno) {
196 xfunc_exitcode = 100;
197 bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser);
198 }
199 xfunc_exitcode = 111;
200 bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser);
201 }
202 if (!cert) cert = "./cert.pem";
203 if (!key) key = cert;
204 if (matrixSslOpen() < 0)
205 fatal("cannot initialize ssl");
206 if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) {
207 if (client)
208 fatal("cannot read cert, key, or ca file");
209 fatal("cannot read cert or key file");
210 }
211 if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0)
212 fatal("cannot create ssl session");
213#endif
214
215 sig_block(SIGCHLD);
216 signal(SIGCHLD, sig_child_handler);
217 signal(SIGTERM, sig_term_handler);
218 signal(SIGPIPE, SIG_IGN);
219
220 if (max_per_host)
221 ipsvd_perhost_init(cmax);
222
Denis Vlasenko60fadac2007-04-01 19:10:36 +0000223 local_port = bb_lookup_port(argv[1], "tcp", 0);
224 sock = create_and_bind_stream_or_die(argv[0], local_port);
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000225 xlisten(sock, backlog);
226 /* ndelay_off(sock); - it is the default I think? */
227
228#ifndef SSLSVD
229 if (option_mask32 & OPT_u) {
230 /* drop permissions */
231 xsetgid(ugid.gid);
232 xsetuid(ugid.uid);
233 }
234#endif
235 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
236 close(0);
237
238 if (verbose) {
239 /* we do it only for ":port" cosmetics... oh well */
Denis Vlasenko60fadac2007-04-01 19:10:36 +0000240 len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port);
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000241 char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len);
242
243 printf("%s: info: listening on %s", applet_name, addr);
244 free(addr);
245#ifndef SSLSVD
246 if (option_mask32 & OPT_u)
247 printf(", uid %u, gid %u",
Denis Vlasenko60fadac2007-04-01 19:10:36 +0000248 (unsigned)ugid.uid, (unsigned)ugid.gid);
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000249#endif
250 puts(", starting");
251 }
252
253 /* The rest is a main accept() loop */
254
255 again:
256 hccp = NULL;
257
258 while (cnum >= cmax)
259 sig_pause(); /* wait for any signal (expecting SIGCHLD) */
260
261 sockadr_size = sizeof(sock_adr);
262 sig_unblock(SIGCHLD);
263 conn = accept(sock, &sock_adr.sa, &sockadr_size);
264 sig_block(SIGCHLD);
265 if (conn == -1) {
266 if (errno != EINTR)
267 bb_perror_msg("accept");
268 goto again;
269 }
270
271 if (max_per_host) {
272 /* we drop connection immediately if cur_per_host > max_per_host
273 * (minimizing load under SYN flood) */
274 free(remote_ip);
275 remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size);
276 cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp);
277 if (cur_per_host > max_per_host) {
278 /* ipsvd_perhost_add detected that max is exceeded
279 * (and did not store us in connection table) */
280 if (msg_per_host) {
281 ndelay_on(conn);
282 /* don't test for errors */
283 write(conn, msg_per_host, len_per_host);
284 }
285 close(conn);
286 goto again;
287 }
288 }
289
290 cnum++;
291 if (verbose)
292 connection_status();
293
294 pid = fork();
295 if (pid == -1) {
296 bb_perror_msg("fork");
297 close(conn);
298 goto again;
299 }
300 if (pid != 0) {
301 /* parent */
302 close(conn);
303 if (hccp)
304 hccp->pid = pid;
305 goto again;
306 }
307
308 /* Child: prepare env, log, and exec prog */
309
310 close(sock);
311
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000312 if (!max_per_host && need_remote_ip)
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000313 remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sizeof(sock_adr));
314 /* else it is already done */
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000315
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000316 remote_port = get_nport(&sock_adr.sa);
317 remote_port = ntohs(remote_port);
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000318
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000319 if (verbose) {
320 pid = getpid();
321 printf("%s: info: pid %d from %s\n", applet_name, pid, remote_ip);
322 }
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000323
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000324 if (need_hostnames && (option_mask32 & OPT_h)) {
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000325 remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr));
326 if (!remote_hostname) {
327 bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
328 remote_hostname = (char*)"";
329 }
330 }
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000331
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000332 sockadr_size = sizeof(sock_adr);
333 /* Errors ignored (I'm not paranoid enough to imagine kernel
334 * which doesn't know local ip) */
335 getsockname(conn, &sock_adr.sa, &sockadr_size);
336
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000337 if (need_hostnames) {
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000338 local_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size);
339 local_port = get_nport(&sock_adr.sa);
340 local_port = ntohs(local_port);
341 if (!local_hostname) {
342 local_hostname = xmalloc_sockaddr2host_noport(&sock_adr.sa, sockadr_size);
343 if (!local_hostname)
344 bb_error_msg_and_die("cannot look up local hostname for %s", local_ip);
345 }
346 }
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000347
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000348 if (!(option_mask32 & OPT_E)) {
349 /* setup ucspi env */
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000350
351 /* Extract "original" destination addr:port
352 * from Linux firewall. Useful when you redirect
353 * an outbond connection to local handler, and it needs
354 * to know where it originally tried to connect */
355 sockadr_size = sizeof(sock_adr);
356 if (getsockopt(conn, SOL_IP, SO_ORIGINAL_DST, &sock_adr.sa, &sockadr_size) == 0) {
357 char *ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size);
Denis Vlasenko60fadac2007-04-01 19:10:36 +0000358 unsigned port = get_nport(&sock_adr.sa);
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000359 port = ntohs(port);
360 xsetenv("TCPORIGDSTIP", ip);
361 xsetenv("TCPORIGDSTPORT", utoa(port));
362 free(ip);
363 }
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000364 xsetenv("PROTO", "TCP");
365 xsetenv("TCPLOCALIP", local_ip);
366 xsetenv("TCPLOCALPORT", utoa(local_port));
367 xsetenv("TCPLOCALHOST", local_hostname);
368 xsetenv("TCPREMOTEIP", remote_ip);
369 xsetenv("TCPREMOTEPORT", utoa(remote_port));
370 if (option_mask32 & OPT_h) {
371 xsetenv("TCPREMOTEHOST", remote_hostname);
372 }
373 xsetenv("TCPREMOTEINFO", "");
374 /* additional */
375 if (cur_per_host > 0)
376 xsetenv("TCPCONCURRENCY", utoa(cur_per_host));
377 }
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000378
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000379#if 0
380 if (instructs) {
381 ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs,
382 remote_ip, remote_hostname, timeout);
383 if (ac == -1) drop2("cannot check inst", remote_ip);
384 if (ac == IPSVD_ERR) drop2("cannot read", (char*)instructs);
385 } else
386 ac = IPSVD_DEFAULT;
387#endif
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000388
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000389 if (max_per_host && verbose)
390 printf("%s: info: concurrency %u %s %u/%u\n",
391 applet_name, pid, remote_ip, cur_per_host, max_per_host);
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000392
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000393 if (verbose) {
394 printf("%s: info: start %u %s:%s :%s:%s:%u\n",
395 applet_name, pid,
396 local_hostname, local_ip,
397 remote_hostname, remote_ip, (unsigned)remote_port);
398#if 0
399 switch(ac) {
400 case IPSVD_DENY:
401 printf("deny "); break;
402 case IPSVD_DEFAULT:
403 case IPSVD_INSTRUCT:
404 printf("start "); break;
405 case IPSVD_EXEC:
406 printf("exec "); break;
407 }
408 ...
409 if (instructs) {
410 printf(" ");
411 if (iscdb) {
412 printf((char*)instructs);
413 printf("/");
414 }
415 outfix(match.s);
416 if(inst.s && inst.len && (verbose > 1)) {
417 printf(": ");
418 printf(&inst);
419 }
420 }
421 printf("\n");
422#endif
423 }
424
425#if 0
426 if (ac == IPSVD_DENY) {
427 close(conn);
428 _exit(100);
429 }
430 if (ac == IPSVD_EXEC) {
431 args[0] = "/bin/sh";
432 args[1] = "-c";
433 args[2] = inst.s;
434 args[3] = 0;
435 run = args;
436 } else
437 run = argv + 2; /* below: we use argv+2 (was using run) */
438#endif
439
440 xmove_fd(conn, 0);
441 dup2(0, 1);
442 signal(SIGTERM, SIG_DFL);
443 signal(SIGPIPE, SIG_DFL);
444 signal(SIGCHLD, SIG_DFL);
445 sig_unblock(SIGCHLD);
446
447 argv += 2;
448#ifdef SSLSVD
449 strcpy(id, utoa(pid);
450 ssl_io(0, argv);
451#else
452 BB_EXECVP(argv[0], argv);
453#endif
454 bb_perror_msg_and_die("exec '%s'", argv[0]);
455}
456
457/*
Denis Vlasenko57a426b2007-04-01 10:59:33 +0000458tcpsvd [-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name]
459 [-i dir|-x cdb] [ -t sec] host port prog
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000460
461tcpsvd creates a TCP/IP socket, binds it to the address host:port,
462and listens on the socket for incoming connections.
463
464On each incoming connection, tcpsvd conditionally runs a program,
465with standard input reading from the socket, and standard output
466writing to the socket, to handle this connection. tcpsvd keeps
467listening on the socket for new connections, and can handle
468multiple connections simultaneously.
469
470tcpsvd optionally checks for special instructions depending
471on the IP address or hostname of the client that initiated
472the connection, see ipsvd-instruct(5).
473
474host
475 host either is a hostname, or a dotted-decimal IP address,
476 or 0. If host is 0, tcpsvd accepts connections to any local
477 IP address.
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000478 * busybox accepts IPv6 addresses and host:port pairs too
479 In this case second parameter is ignored
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000480port
481 tcpsvd accepts connections to host:port. port may be a name
482 from /etc/services or a number.
483prog
484 prog consists of one or more arguments. For each connection,
485 tcpsvd normally runs prog, with file descriptor 0 reading from
486 the network, and file descriptor 1 writing to the network.
487 By default it also sets up TCP-related environment variables,
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000488 see tcp-environ(5)
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000489-i dir
490 read instructions for handling new connections from the instructions
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000491 directory dir. See ipsvd-instruct(5) for details.
492 * ignored by busyboxed version
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000493-x cdb
494 read instructions for handling new connections from the constant database
495 cdb. The constant database normally is created from an instructions
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000496 directory by running ipsvd-cdb(8).
497 * ignored by busyboxed version
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000498-t sec
499 timeout. This option only takes effect if the -i option is given.
500 While checking the instructions directory, check the time of last access
501 of the file that matches the clients address or hostname if any, discard
502 and remove the file if it wasn't accessed within the last sec seconds;
503 tcpsvd does not discard or remove a file if the user's write permission
504 is not set, for those files the timeout is disabled. Default is 0,
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000505 which means that the timeout is disabled.
506 * ignored by busyboxed version
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000507-l name
508 local hostname. Do not look up the local hostname in DNS, but use name
509 as hostname. This option must be set if tcpsvd listens on port 53
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000510 to avoid loops.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000511-u user[:group]
512 drop permissions. Switch user ID to user's UID, and group ID to user's
513 primary GID after creating and binding to the socket. If user is followed
514 by a colon and a group name, the group ID is switched to the GID of group
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000515 instead. All supplementary groups are removed.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000516-c n
517 concurrency. Handle up to n connections simultaneously. Default is 30.
518 If there are n connections active, tcpsvd defers acceptance of a new
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000519 connection until an active connection is closed.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000520-C n[:msg]
521 per host concurrency. Allow only up to n connections from the same IP
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000522 address simultaneously. If there are n active connections from one IP
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000523 address, new incoming connections from this IP address are closed
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000524 immediately. If n is followed by :msg, the message msg is written
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000525 to the client if possible, before closing the connection. By default
526 msg is empty. See ipsvd-instruct(5) for supported escape sequences in msg.
527
528 For each accepted connection, the current per host concurrency is
529 available through the environment variable TCPCONCURRENCY. n and msg
530 can be overwritten by ipsvd(7) instructions, see ipsvd-instruct(5).
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000531 By default tcpsvd doesn't keep track of connections.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000532-h
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000533 Look up the client's hostname in DNS.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000534-p
535 paranoid. After looking up the client's hostname in DNS, look up the IP
536 addresses in DNS for that hostname, and forget about the hostname
537 if none of the addresses match the client's IP address. You should
538 set this option if you use hostname based instructions. The -p option
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000539 implies the -h option.
540 * ignored by busyboxed version
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000541-b n
542 backlog. Allow a backlog of approximately n TCP SYNs. On some systems n
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000543 is silently limited. Default is 20.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000544-E
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000545 no special environment. Do not set up TCP-related environment variables.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000546-v
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000547 verbose. Print verbose messsages to standard output.
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000548-vv
Denis Vlasenkoba2fb712007-04-01 09:39:03 +0000549 more verbose. Print more verbose messages to standard output.
550 * no difference between -v and -vv in busyboxed version
Denis Vlasenko2856dab2007-04-01 01:18:20 +0000551*/