tcp-socket-accept 1 user commands nosh
tcp-socket-accept accept incoming TCP connections and spawn a program per connection
`tcp-socket-accept` --verbose --no-keepalives --no-kill-IP-options --no-delay --connection-limit number --localname hostname next-prog

## Description

`tcp-socket-accept` expects to inherit 1 or more sockets that have been set up to listen for incoming TCP connections, as done by tcp-socket-listen 1. It loops forever, accepting TCP connections and (for each such connection) spawning next-prog, closing the listening socket(s) in the child process and setting the connected socket as the child process' standard input and standard output.

next-prog may contain its own command line options, which `tcp-socket-accept` will ignore.

If the --verbose option is used, `tcp-socket-accept` logs information about processes spawned and the current and maximum number of connections. The latter is set with the --connection-limit option, which defaults to 40. If it is reached, `tcp-socket-accept` stops accepting new connections until one or more child processes exit. `tcp-socket-accept` always limits the number of connections, and has no notion of an "unlimited" number of connections. (Whilst it is not accepting connections, the kernel will build up a backlog of unaccepted connections until the listening socket's backlog limit, specified by whatever opened the socket for `tcp-socket-accept`, is reached.)

The --no-keepalives, --no-kill-IP-options, and --no-delay command line options set options on the accepted sockets. The first disables the use of TCP keepalive probes (which are used by default to ensure that dead connections are noticed and eliminated); the second permits IP options (which are removed by default) so that clients can set source routes; and the third disables the "Nagle" delay algorithm used for slow clients.

### Listening socket conventions

There are no UCSPI conventions for listening sockets before a connection has been accepted. `tcp-socket-accept` follows the systemd convention, falling back on a daemontools-like default.

If the `LISTEN_PID` environment variable is set, if its value is parseable as a (decimal) number, if that number is the process ID of the `tcp-socket-accept` process, if the `LISTEN_FDS` environment variable is set, and if its value is parseable as a (positive decimal) number n: then the listening sockets are taken to be file descriptors 3 up to but not including 3+n. (It is an error for there to be zero listening file descriptors.) Otherwise file descriptor 3 is taken unconditionally to be the single listening open file descriptor.

`tcp-socket-accept` unconditionally unsets the `LISTEN_PID`, `LISTEN_FDS`, and `LISTEN_FDNAMES` environment variables after it has determined what the open file descriptors to use are.

### UCSPI (specifically UCSPI-TCP) conventions

next-prog is expected to follow the UCSPI conventions: its standard input and output are the connected socket, which it should treat as generic I/O streams and not expect to be a socket, and information about the local and remote ends of the connected socket is in environment variables.

In the child process, `tcp-socket-accept` closes all of the listening sockets. It obtains information about the local socket connection, using the `getpeername` 2 and `getsockname` 2 library functions, and sets up the conventional UCSPI-TCP environment variables as follows:

`PROTO`

  This always has the value `TCP`, indicating the prefix to the names of the remaining environment variables.

`TCPLOCALIP`

  The local (server) IP address of the accepted socket, in human-readable form.

`TCPLOCALPORT`

  The local (server) port number of the accepted socket.

`TCPLOCALHOST`

  The value of hostname set by the --localname option; guaranteed unset if that option is not used.

`TCPREMOTEIP`

  The remote (client) IP address of the accepted socket, in human-readable form.

`TCPREMOTEPORT`

  The remote (client) port number of the accepted socket.

`TCPREMOTEINFO`

  Guaranteed unset.

`TCPREMOTEHOST`

  Guaranteed unset.

In the 21st century Internet, remote user account information and even host name information are attacker-supplied data and must not be expected by a UCSPI-TCP server, let alone relied upon. Even attempting to find out such information can involve contacting potentially malicious servers. `tcp-socket-accept` performs no lookups for such information.

## USAGE

`tcp-socket-accept` can be used

- as a "socket-activated" dæmon monitored by systemd 1 (with the systemd-recommended `Accept=false`),

- as a dæmon started by inetd 1 (with `wait` and as long as it is chained via `fdmove 0 3`), and

- as a simple dæmon chained from tcp-socket-listen 1 and monitored by service-manager 1.

Together, `tcp-socket-accept` and tcp-socket-listen 1 replace tcpserver 1 from ucspi-tcp.

To change the process' UID and GID after a successful call to accept 2, simply chain to setuidgid 1 or setuidgid-fromenv 1. This is, however, not usually necessary because unprivileged processes can accept any connections. It is preferable to chain `tcp-socket-accept` from setuidgid 1 or setuidgid-fromenv 1.

## Author

Jonathan de Boyne Pollard