1/* 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 * 5 * Copyright (C) 2007 Denys Vlasenko. 6 * 7 * Licensed under GPLv2, see file LICENSE in this source tree. 8 */ 9 10/* Based on 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 * 16 * Busybox version exports TCPLOCALADDR instead of 17 * TCPLOCALIP + TCPLOCALPORT pair. ADDR more closely matches reality 18 * (which is "struct sockaddr_XXX". Port is not a separate entity, 19 * it's just a part of (AF_INET[6]) sockaddr!). 20 * 21 * TCPORIGDSTADDR is Busybox-specific addition. 22 * 23 * udp server is hacked up by reusing TCP code. It has the following 24 * limitation inherent in Unix DGRAM sockets implementation: 25 * - local IP address is retrieved (using recvmsg voodoo) but 26 * child's socket is not bound to it (bind cannot be called on 27 * already bound socket). Thus it still can emit outgoing packets 28 * with wrong source IP... 29 * - don't know how to retrieve ORIGDST for udp. 30 */ 31//config:config TCPSVD 32//config: bool "tcpsvd (13 kb)" 33//config: default y 34//config: help 35//config: tcpsvd listens on a TCP port and runs a program for each new 36//config: connection. 37//config: 38//config:config UDPSVD 39//config: bool "udpsvd (13 kb)" 40//config: default y 41//config: help 42//config: udpsvd listens on an UDP port and runs a program for each new 43//config: connection. 44 45//applet:IF_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, tcpsvd)) 46//applet:IF_UDPSVD(APPLET_ODDNAME(udpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, udpsvd)) 47 48//kbuild:lib-$(CONFIG_TCPSVD) += tcpudp.o tcpudp_perhost.o 49//kbuild:lib-$(CONFIG_UDPSVD) += tcpudp.o tcpudp_perhost.o 50 51//usage:#define tcpsvd_trivial_usage 52//usage: "[-hEv] [-c N] [-C N[:MSG]] [-b N] [-u USER] [-l NAME] IP PORT PROG" 53/* with not-implemented options: */ 54/* //usage: "[-hpEvv] [-c N] [-C N[:MSG]] [-b N] [-u USER] [-l NAME] [-i DIR|-x CDB] [-t SEC] IP PORT PROG" */ 55//usage:#define tcpsvd_full_usage "\n\n" 56//usage: "Create TCP socket, bind to IP:PORT and listen for incoming connections.\n" 57//usage: "Run PROG for each connection.\n" 58//usage: "\n IP PORT IP:PORT to listen on" 59//usage: "\n PROG ARGS Program to run" 60//usage: "\n -u USER[:GRP] Change to user/group after bind" 61//usage: "\n -c N Up to N connections simultaneously (default 30)" 62//usage: "\n -b N Allow backlog of approximately N TCP SYNs (default 20)" 63//usage: "\n -C N[:MSG] Allow only up to N connections from the same IP:" 64//usage: "\n new connections from this IP address are closed" 65//usage: "\n immediately, MSG is written to the peer before close" 66//usage: "\n -E Don't set up environment" 67//usage: "\n -h Look up peer's hostname" 68//usage: "\n -l NAME Local hostname (else look up local hostname in DNS)" 69//usage: "\n -v Verbose" 70//usage: "\n" 71//usage: "\nEnvironment if no -E:" 72//usage: "\nPROTO='TCP'" 73//usage: "\nTCPREMOTEADDR='ip:port'" IF_FEATURE_IPV6(" ('[ip]:port' for IPv6)") 74//usage: "\nTCPLOCALADDR='ip:port'" 75//usage: "\nTCPORIGDSTADDR='ip:port' of destination before firewall" 76//usage: "\n Useful for REDIRECTed-to-local connections:" 77//usage: "\n iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080" 78//usage: "\nTCPCONCURRENCY=num_of_connects_from_this_ip" 79//usage: "\nIf -h:" 80//usage: "\nTCPLOCALHOST='hostname' (-l NAME is used if specified)" 81//usage: "\nTCPREMOTEHOST='hostname'" 82 83//usage: 84//usage:#define udpsvd_trivial_usage 85//usage: "[-hEv] [-c N] [-u USER] [-l NAME] IP PORT PROG" 86//usage:#define udpsvd_full_usage "\n\n" 87//usage: "Create UDP socket, bind to IP:PORT and wait for incoming packets.\n" 88//usage: "Run PROG for each packet, redirecting all further packets with same\n" 89//usage: "peer ip:port to it.\n" 90//usage: "\n IP PORT IP:PORT to listen on" 91//usage: "\n PROG ARGS Program to run" 92//usage: "\n -u USER[:GRP] Change to user/group after bind" 93//usage: "\n -c N Up to N connections simultaneously (default 30)" 94//usage: "\n -E Don't set up environment" 95//usage: "\n -h Look up peer's hostname" 96//usage: "\n -l NAME Local hostname (else look up local hostname in DNS)" 97//usage: "\n -v Verbose" 98//usage: "\n" 99//usage: "\nEnvironment if no -E:" 100//usage: "\nPROTO='UDP'" 101//usage: "\nUDPREMOTEADDR='ip:port'" IF_FEATURE_IPV6(" ('[ip]:port' for IPv6)") 102//usage: "\nUDPLOCALADDR='ip:port'" 103//usage: "\nIf -h:" 104//usage: "\nUDPLOCALHOST='hostname' (-l NAME is used if specified)" 105//usage: "\nUDPREMOTEHOST='hostname'" 106 107#include "libbb.h" 108#include "common_bufsiz.h" 109 110#ifdef __linux__ 111/* from linux/netfilter_ipv4.h: */ 112# undef SO_ORIGINAL_DST 113# define SO_ORIGINAL_DST 80 114#endif 115 116// TODO: move into this file: 117#include "tcpudp_perhost.h" 118 119#ifdef SSLSVD 120#include "matrixSsl.h" 121#include "ssl_io.h" 122#endif 123 124struct globals { 125 unsigned verbose; 126 unsigned max_per_host; 127 unsigned cur_per_host; 128 unsigned cnum; 129 unsigned cmax; 130 struct hcc *cc; 131 char **env_cur; 132 char *env_var[1]; /* actually bigger */ 133} FIX_ALIASING; 134#define G (*(struct globals*)bb_common_bufsiz1) 135#define verbose (G.verbose ) 136#define max_per_host (G.max_per_host) 137#define cur_per_host (G.cur_per_host) 138#define cnum (G.cnum ) 139#define cmax (G.cmax ) 140#define env_cur (G.env_cur ) 141#define env_var (G.env_var ) 142#define INIT_G() do { \ 143 setup_common_bufsiz(); \ 144 cmax = 30; \ 145 env_cur = &env_var[0]; \ 146} while (0) 147 148 149/* We have to be careful about leaking memory in repeated setenv's */ 150static void xsetenv_plain(const char *n, const char *v) 151{ 152 char *var = xasprintf("%s=%s", n, v); 153 *env_cur++ = var; 154 putenv(var); 155} 156 157static void xsetenv_proto(const char *proto, const char *n, const char *v) 158{ 159 char *var = xasprintf("%s%s=%s", proto, n, v); 160 *env_cur++ = var; 161 putenv(var); 162} 163 164static void undo_xsetenv(void) 165{ 166 char **pp = env_cur = &env_var[0]; 167 while (*pp) { 168 char *var = *pp; 169 bb_unsetenv_and_free(var); 170 *pp++ = NULL; 171 } 172} 173 174static void sig_term_handler(int sig) 175{ 176 if (verbose) 177 bb_error_msg("got signal %u, exit", sig); 178 kill_myself_with_sig(sig); 179} 180 181/* Little bloated, but tries to give accurate info how child exited. 182 * Makes easier to spot segfaulting children etc... */ 183static void print_waitstat(unsigned pid, int wstat) 184{ 185 unsigned e = 0; 186 const char *cause = "?exit"; 187 188 if (WIFEXITED(wstat)) { 189 cause++; 190 e = WEXITSTATUS(wstat); 191 } else if (WIFSIGNALED(wstat)) { 192 cause = "signal"; 193 e = WTERMSIG(wstat); 194 } 195 bb_error_msg("end %d %s %d", pid, cause, e); 196} 197 198/* Must match getopt32 in main! */ 199enum { 200 OPT_c = (1 << 0), 201 OPT_C = (1 << 1), 202 OPT_i = (1 << 2), 203 OPT_x = (1 << 3), 204 OPT_u = (1 << 4), 205 OPT_l = (1 << 5), 206 OPT_E = (1 << 6), 207 OPT_b = (1 << 7), 208 OPT_h = (1 << 8), 209 OPT_p = (1 << 9), 210 OPT_t = (1 << 10), 211 OPT_v = (1 << 11), 212 OPT_V = (1 << 12), 213 OPT_U = (1 << 13), /* from here: sslsvd only */ 214 OPT_slash = (1 << 14), 215 OPT_Z = (1 << 15), 216 OPT_K = (1 << 16), 217}; 218 219static void connection_status(void) 220{ 221 /* "only 1 client max" desn't need this */ 222 if (cmax > 1) 223 bb_error_msg("status %u/%u", cnum, cmax); 224} 225 226static void sig_child_handler(int sig UNUSED_PARAM) 227{ 228 int wstat; 229 pid_t pid; 230 231 while ((pid = wait_any_nohang(&wstat)) > 0) { 232 if (max_per_host) 233 ipsvd_perhost_remove(G.cc, pid); 234 if (cnum) 235 cnum--; 236 if (verbose) 237 print_waitstat(pid, wstat); 238 } 239 if (verbose) 240 connection_status(); 241} 242 243int tcpudpsvd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 244int tcpudpsvd_main(int argc UNUSED_PARAM, char **argv) 245{ 246 char *str_C, *str_t; 247 char *user; 248 struct hcc *hccp; 249 const char *instructs; 250 char *msg_per_host = NULL; 251 unsigned len_per_host = len_per_host; /* gcc */ 252#ifndef SSLSVD 253 struct bb_uidgid_t ugid; 254#endif 255 bool tcp; 256 uint16_t local_port; 257 char *preset_local_hostname = NULL; 258 char *remote_hostname = remote_hostname; /* for compiler */ 259 char *remote_addr = remote_addr; /* for compiler */ 260 len_and_sockaddr *lsa; 261 len_and_sockaddr local, remote; 262 socklen_t sa_len; 263 int pid; 264 int sock; 265 int conn; 266 unsigned backlog = 20; 267 unsigned opts; 268 269 INIT_G(); 270 271 tcp = (applet_name[0] == 't'); 272 273 /* "+": stop on first non-option */ 274#ifdef SSLSVD 275 opts = getopt32(argv, "^+" 276 "c:+C:i:x:u:l:Eb:+hpt:vU:/:Z:K:" /* -c NUM, -b NUM */ 277 "\0" 278 /* 3+ args, -i at most once, -p implies -h, -v is a counter */ 279 "-3:i--i:ph:vv", 280 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, 281 &backlog, &str_t, &ssluser, &root, &cert, &key, &verbose 282 ); 283#else 284 opts = getopt32(argv, "^+" 285 "c:+C:i:x:u:l:Eb:+hpt:v" /* -c NUM, -b NUM */ 286 "\0" 287 /* 3+ args, -i at most once, -p implies -h, -v is a counter */ 288 "-3:i--i:ph:vv", 289 &cmax, &str_C, &instructs, &instructs, &user, &preset_local_hostname, 290 &backlog, &str_t, &verbose 291 ); 292#endif 293 if (opts & OPT_C) { /* -C n[:message] */ 294 max_per_host = bb_strtou(str_C, &str_C, 10); 295 if (str_C[0]) { 296 if (str_C[0] != ':') 297 bb_show_usage(); 298 msg_per_host = str_C + 1; 299 len_per_host = strlen(msg_per_host); 300 } 301 } 302 if (max_per_host > cmax) 303 max_per_host = cmax; 304 if (opts & OPT_u) { 305 xget_uidgid(&ugid, user); 306 } 307#ifdef SSLSVD 308 if (opts & OPT_U) ssluser = optarg; 309 if (opts & OPT_slash) root = optarg; 310 if (opts & OPT_Z) cert = optarg; 311 if (opts & OPT_K) key = optarg; 312#endif 313 argv += optind; 314 if (!argv[0][0] || LONE_CHAR(argv[0], '0')) 315 argv[0] = (char*)"0.0.0.0"; 316 317 /* Per-IP flood protection is not thought-out for UDP */ 318 if (!tcp) 319 max_per_host = 0; 320 321 bb_sanitize_stdio(); /* fd# 0,1,2 must be opened */ 322 323#ifdef SSLSVD 324 sslser = user; 325 client = 0; 326 if ((getuid() == 0) && !(opts & OPT_u)) { 327 xfunc_error_retval = 100; 328 bb_error_msg_and_die(bb_msg_you_must_be_root); 329 } 330 if (opts & OPT_u) 331 if (!uidgid_get(&sslugid, ssluser, 1)) { 332 if (errno) { 333 bb_perror_msg_and_die("can't get user/group: %s", ssluser); 334 } 335 bb_error_msg_and_die("unknown user/group %s", ssluser); 336 } 337 if (!cert) cert = "./cert.pem"; 338 if (!key) key = cert; 339 if (matrixSslOpen() < 0) 340 fatal("can't initialize ssl"); 341 if (matrixSslReadKeys(&keys, cert, key, 0, ca) < 0) { 342 if (client) 343 fatal("can't read cert, key, or ca file"); 344 fatal("can't read cert or key file"); 345 } 346 if (matrixSslNewSession(&ssl, keys, 0, SSL_FLAGS_SERVER) < 0) 347 fatal("can't create ssl session"); 348#endif 349 350 sig_block(SIGCHLD); 351 signal(SIGCHLD, sig_child_handler); 352 bb_signals(BB_FATAL_SIGS, sig_term_handler); 353 signal(SIGPIPE, SIG_IGN); 354 355 if (max_per_host) 356 G.cc = ipsvd_perhost_init(cmax); 357 358 local_port = bb_lookup_port(argv[1], tcp ? "tcp" : "udp", 0); 359 lsa = xhost2sockaddr(argv[0], local_port); 360 argv += 2; 361 362 sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); 363 setsockopt_reuseaddr(sock); 364 sa_len = lsa->len; /* I presume sockaddr len stays the same */ 365 xbind(sock, &lsa->u.sa, sa_len); 366 if (tcp) { 367 xlisten(sock, backlog); 368 close_on_exec_on(sock); 369 } else { /* udp: needed for recv_from_to to work: */ 370 socket_want_pktinfo(sock); 371 } 372 /* ndelay_off(sock); - it is the default I think? */ 373 374#ifndef SSLSVD 375 if (opts & OPT_u) { 376 /* drop permissions */ 377 xsetgid(ugid.gid); 378 xsetuid(ugid.uid); 379 } 380#endif 381 382 if (verbose) { 383 char *addr = xmalloc_sockaddr2dotted(&lsa->u.sa); 384 if (opts & OPT_u) 385 bb_error_msg("listening on %s, starting, uid %u, gid %u", addr, 386 (unsigned)ugid.uid, (unsigned)ugid.gid); 387 else 388 bb_error_msg("listening on %s, starting", addr); 389 free(addr); 390 } 391 392 /* Main accept() loop */ 393 394 again: 395 hccp = NULL; 396 397 again1: 398 close(0); 399 /* It's important to close(0) _before_ wait loop: 400 * fd#0 can be a shared connection fd. 401 * If kept open by us, peer can't detect PROG closing it. 402 */ 403 while (cnum >= cmax) 404 wait_for_any_sig(); /* expecting SIGCHLD */ 405 406 again2: 407 sig_unblock(SIGCHLD); 408 local.len = remote.len = sa_len; 409 if (tcp) { 410 /* Accept a connection to fd #0 */ 411 conn = accept(sock, &remote.u.sa, &remote.len); 412 } else { 413 /* In case recv_from_to won't be able to recover local addr. 414 * Also sets port - recv_from_to is unable to do it. */ 415 local = *lsa; 416 conn = recv_from_to(sock, NULL, 0, MSG_PEEK, 417 &remote.u.sa, &local.u.sa, sa_len); 418 } 419 sig_block(SIGCHLD); 420 if (conn < 0) { 421 if (errno != EINTR) 422 bb_perror_msg(tcp ? "accept" : "recv"); 423 goto again2; 424 } 425 xmove_fd(tcp ? conn : sock, 0); 426 427 if (max_per_host) { 428 /* Drop connection immediately if cur_per_host > max_per_host 429 * (minimizing load under SYN flood) */ 430 remote_addr = xmalloc_sockaddr2dotted_noport(&remote.u.sa); 431 cur_per_host = ipsvd_perhost_add(G.cc, remote_addr, max_per_host, &hccp); 432 if (cur_per_host > max_per_host) { 433 /* ipsvd_perhost_add detected that max is exceeded 434 * (and did not store ip in connection table) */ 435 free(remote_addr); 436 if (msg_per_host) { 437 /* don't block or test for errors */ 438 send(0, msg_per_host, len_per_host, MSG_DONTWAIT); 439 } 440 goto again1; 441 } 442 /* NB: remote_addr is not leaked, it is stored in conn table */ 443 } 444 445 if (!tcp) { 446 /* Voodoo magic: making udp sockets each receive its own 447 * packets is not trivial, and I still not sure 448 * I do it 100% right. 449 * 1) we have to do it before fork() 450 * 2) order is important - is it right now? */ 451 452 /* Open new non-connected UDP socket for further clients... */ 453 sock = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0); 454 setsockopt_reuseaddr(sock); 455 /* Make plain write/send work for old socket by supplying default 456 * destination address. This also restricts incoming packets 457 * to ones coming from this remote IP. */ 458 xconnect(0, &remote.u.sa, sa_len); 459 /* hole? at this point we have no wildcard udp socket... 460 * can this cause clients to get "port unreachable" icmp? 461 * Yup, time window is very small, but it exists (is it?) */ 462 /* ..."open new socket", continued */ 463 xbind(sock, &lsa->u.sa, sa_len); 464 socket_want_pktinfo(sock); 465 466 /* Doesn't work: 467 * we cannot replace fd #0 - we will lose pending packet 468 * which is already buffered for us! And we cannot use fd #1 469 * instead - it will "intercept" all following packets, but child 470 * does not expect data coming *from fd #1*! */ 471#if 0 472 /* Make it so that local addr is fixed to localp->u.sa 473 * and we don't accidentally accept packets to other local IPs. */ 474 /* NB: we possibly bind to the _very_ same_ address & port as the one 475 * already bound in parent! This seems to work in Linux. 476 * (otherwise we can move socket to fd #0 only if bind succeeds) */ 477 close(0); 478 set_nport(&localp->u.sa, htons(local_port)); 479 xmove_fd(xsocket(localp->u.sa.sa_family, SOCK_DGRAM, 0), 0); 480 setsockopt_reuseaddr(0); /* crucial */ 481 xbind(0, &localp->u.sa, localp->len); 482#endif 483 } 484 485 pid = vfork(); 486 if (pid == -1) { 487 bb_perror_msg("vfork"); 488 goto again; 489 } 490 491 if (pid != 0) { 492 /* Parent */ 493 cnum++; 494 if (verbose) 495 connection_status(); 496 if (hccp) 497 hccp->pid = pid; 498 /* clean up changes done by vforked child */ 499 undo_xsetenv(); 500 goto again; 501 } 502 503 /* Child: prepare env, log, and exec prog */ 504 505 { /* vfork alert! every xmalloc in this block should be freed! */ 506 char *local_hostname = local_hostname; /* for compiler */ 507 char *local_addr = NULL; 508 char *free_me0 = NULL; 509 char *free_me1 = NULL; 510 char *free_me2 = NULL; 511 512 if (verbose || !(opts & OPT_E)) { 513 if (!max_per_host) /* remote_addr is not yet known */ 514 free_me0 = remote_addr = xmalloc_sockaddr2dotted(&remote.u.sa); 515 if (opts & OPT_h) { 516 free_me1 = remote_hostname = xmalloc_sockaddr2host_noport(&remote.u.sa); 517 if (!remote_hostname) { 518 bb_error_msg("can't look up hostname for %s", remote_addr); 519 remote_hostname = remote_addr; 520 } 521 } 522 /* Find out local IP peer connected to. 523 * Errors ignored (I'm not paranoid enough to imagine kernel 524 * which doesn't know local IP). */ 525 if (tcp) 526 getsockname(0, &local.u.sa, &local.len); 527 /* else: for UDP it is done earlier by parent */ 528 local_addr = xmalloc_sockaddr2dotted(&local.u.sa); 529 if (opts & OPT_h) { 530 local_hostname = preset_local_hostname; 531 if (!local_hostname) { 532 free_me2 = local_hostname = xmalloc_sockaddr2host_noport(&local.u.sa); 533 if (!local_hostname) 534 bb_error_msg_and_die("can't look up hostname for %s", local_addr); 535 } 536 /* else: local_hostname is not NULL, but is NOT malloced! */ 537 } 538 } 539 if (verbose) { 540 pid = getpid(); 541 if (max_per_host) { 542 bb_error_msg("concurrency %s %u/%u", 543 remote_addr, 544 cur_per_host, max_per_host); 545 } 546 bb_error_msg((opts & OPT_h) 547 ? "start %u %s-%s (%s-%s)" 548 : "start %u %s-%s", 549 pid, 550 local_addr, remote_addr, 551 local_hostname, remote_hostname); 552 } 553 554 if (!(opts & OPT_E)) { 555 /* setup ucspi env */ 556 const char *proto = tcp ? "TCP" : "UDP"; 557 558#ifdef SO_ORIGINAL_DST 559 /* Extract "original" destination addr:port 560 * from Linux firewall. Useful when you redirect 561 * an outbond connection to local handler, and it needs 562 * to know where it originally tried to connect */ 563 if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &local.u.sa, &local.len) == 0) { 564 char *addr = xmalloc_sockaddr2dotted(&local.u.sa); 565 xsetenv_plain("TCPORIGDSTADDR", addr); 566 free(addr); 567 } 568#endif 569 xsetenv_plain("PROTO", proto); 570 xsetenv_proto(proto, "LOCALADDR", local_addr); 571 xsetenv_proto(proto, "REMOTEADDR", remote_addr); 572 if (opts & OPT_h) { 573 xsetenv_proto(proto, "LOCALHOST", local_hostname); 574 xsetenv_proto(proto, "REMOTEHOST", remote_hostname); 575 } 576 //compat? xsetenv_proto(proto, "REMOTEINFO", ""); 577 /* additional */ 578 if (cur_per_host > 0) /* can not be true for udp */ 579 xsetenv_plain("TCPCONCURRENCY", utoa(cur_per_host)); 580 } 581 free(local_addr); 582 free(free_me0); 583 free(free_me1); 584 free(free_me2); 585 } 586 587 xdup2(0, 1); 588 589 signal(SIGPIPE, SIG_DFL); /* this one was SIG_IGNed */ 590 /* Non-ignored signals revert to SIG_DFL on exec anyway */ 591 /*signal(SIGCHLD, SIG_DFL);*/ 592 sig_unblock(SIGCHLD); 593 594#ifdef SSLSVD 595 strcpy(id, utoa(pid)); 596 ssl_io(0, argv); 597 bb_perror_msg_and_die("can't execute '%s'", argv[0]); 598#else 599 BB_EXECVP_or_die(argv); 600#endif 601} 602 603/* 604tcpsvd [-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] 605 [-i dir|-x cdb] [ -t sec] host port prog 606 607tcpsvd creates a TCP/IP socket, binds it to the address host:port, 608and listens on the socket for incoming connections. 609 610On each incoming connection, tcpsvd conditionally runs a program, 611with standard input reading from the socket, and standard output 612writing to the socket, to handle this connection. tcpsvd keeps 613listening on the socket for new connections, and can handle 614multiple connections simultaneously. 615 616tcpsvd optionally checks for special instructions depending 617on the IP address or hostname of the client that initiated 618the connection, see ipsvd-instruct(5). 619 620host 621 host either is a hostname, or a dotted-decimal IP address, 622 or 0. If host is 0, tcpsvd accepts connections to any local 623 IP address. 624 * busybox accepts IPv6 addresses and host:port pairs too 625 In this case second parameter is ignored 626port 627 tcpsvd accepts connections to host:port. port may be a name 628 from /etc/services or a number. 629prog 630 prog consists of one or more arguments. For each connection, 631 tcpsvd normally runs prog, with file descriptor 0 reading from 632 the network, and file descriptor 1 writing to the network. 633 By default it also sets up TCP-related environment variables, 634 see tcp-environ(5) 635-i dir 636 read instructions for handling new connections from the instructions 637 directory dir. See ipsvd-instruct(5) for details. 638 * ignored by busyboxed version 639-x cdb 640 read instructions for handling new connections from the constant database 641 cdb. The constant database normally is created from an instructions 642 directory by running ipsvd-cdb(8). 643 * ignored by busyboxed version 644-t sec 645 timeout. This option only takes effect if the -i option is given. 646 While checking the instructions directory, check the time of last access 647 of the file that matches the clients address or hostname if any, discard 648 and remove the file if it wasn't accessed within the last sec seconds; 649 tcpsvd does not discard or remove a file if the user's write permission 650 is not set, for those files the timeout is disabled. Default is 0, 651 which means that the timeout is disabled. 652 * ignored by busyboxed version 653-l name 654 local hostname. Do not look up the local hostname in DNS, but use name 655 as hostname. This option must be set if tcpsvd listens on port 53 656 to avoid loops. 657-u user[:group] 658 drop permissions. Switch user ID to user's UID, and group ID to user's 659 primary GID after creating and binding to the socket. If user is followed 660 by a colon and a group name, the group ID is switched to the GID of group 661 instead. All supplementary groups are removed. 662-c n 663 concurrency. Handle up to n connections simultaneously. Default is 30. 664 If there are n connections active, tcpsvd defers acceptance of a new 665 connection until an active connection is closed. 666-C n[:msg] 667 per host concurrency. Allow only up to n connections from the same IP 668 address simultaneously. If there are n active connections from one IP 669 address, new incoming connections from this IP address are closed 670 immediately. If n is followed by :msg, the message msg is written 671 to the client if possible, before closing the connection. By default 672 msg is empty. See ipsvd-instruct(5) for supported escape sequences in msg. 673 674 For each accepted connection, the current per host concurrency is 675 available through the environment variable TCPCONCURRENCY. n and msg 676 can be overwritten by ipsvd(7) instructions, see ipsvd-instruct(5). 677 By default tcpsvd doesn't keep track of connections. 678-h 679 Look up the client's hostname in DNS. 680-p 681 paranoid. After looking up the client's hostname in DNS, look up the IP 682 addresses in DNS for that hostname, and forget about the hostname 683 if none of the addresses match the client's IP address. You should 684 set this option if you use hostname based instructions. The -p option 685 implies the -h option. 686 * ignored by busyboxed version 687-b n 688 backlog. Allow a backlog of approximately n TCP SYNs. On some systems n 689 is silently limited. Default is 20. 690-E 691 no special environment. Do not set up TCP-related environment variables. 692-v 693 verbose. Print verbose messages to standard output. 694-vv 695 more verbose. Print more verbose messages to standard output. 696 * no difference between -v and -vv in busyboxed version 697*/ 698