A recently added -F option to the nc (netcat) command to pass a connected file descriptor to stdout only works for the listen mode when it passes the accepted descriptor.
The patch below makes -F universal. When given it makes nc to always pass the socket to stdout rather than performing the copy loop. This works both in the client and the server modes including -l -k when nc continuesly passes to stdout all sockets it accepted when listening to the connection. The patch aslo updates nc.1 to show how to use nc -F together with ProxyUseFdPass. Index: nc.1 =================================================================== RCS file: /cvs/src/usr.bin/nc/nc.1,v retrieving revision 1.67 diff -U3 -p -r1.67 nc.1 --- nc.1 26 Feb 2014 20:56:11 -0000 1.67 +++ nc.1 2 May 2014 18:18:10 -0000 @@ -103,9 +103,9 @@ Enable debugging on the socket. .It Fl d Do not attempt to read from stdin. .It Fl F -Pass the first connected socket using +Pass the connected socket using .Xr sendmsg 2 -to stdout and exit. +to stdout and close own copy. This is useful in conjunction with .Fl X to have @@ -116,7 +116,14 @@ connection to another program (e.g.\& using the .Xr ssh_config 5 .Cm ProxyUseFdPass -option). +directive). When this option is specified together with +.Fl l, +.Nm +sends a socket representing the connection it accepted from a client. If the +.Fl k +is also given, +.Nm +will continue to send all incomming connections indefinitely. .It Fl h Prints out .Nm @@ -445,16 +452,18 @@ stream socket: .Dl $ nc -lU /var/tmp/dsocket .Pp Connect to port 42 of host.example.com via an HTTP proxy at 10.2.3.4, -port 8080. +port 8080, pass the connected socket to stdout and exit. This example could also be used by .Xr ssh 1 ; see the .Cm ProxyCommand -directive in +and +.Cm ProxyUseFdPass +directives in .Xr ssh_config 5 for more information. .Pp -.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42 +.Dl $ nc -F -x10.2.3.4:8080 -Xconnect host.example.com 42 .Pp The same example again, this time enabling proxy authentication with username .Dq ruser Index: netcat.c =================================================================== RCS file: /cvs/src/usr.bin/nc/netcat.c,v retrieving revision 1.118 diff -U3 -p -r1.118 netcat.c --- netcat.c 12 Mar 2014 10:19:40 -0000 1.118 +++ netcat.c 2 May 2014 18:18:10 -0000 @@ -99,7 +99,7 @@ void build_ports(char *); void help(void); int local_listen(char *, char *, struct addrinfo); void readwrite(int); -void fdpass(int nfd) __attribute__((noreturn)); +void fdpass(int nfd); int remote_connect(const char *, const char *, struct addrinfo); int timeout_connect(int, const struct sockaddr *, socklen_t); int socks_connect(const char *, const char *, struct addrinfo, @@ -286,6 +286,15 @@ main(int argc, char *argv[]) if (!lflag && kflag) errx(1, "must use -l with -k"); + if (Fflag && zflag) { + warnx(1, "ignoring -z flag as -F is given"); + zflag = 0; + } + if (FFlag && uflag && kflag) { + warnx(1, "ignoring -k flag as -F is given together with -u"); + kflag = 0; + } + /* Get name of temporary socket for unix datagram client */ if ((family == AF_UNIX) && uflag && !lflag) { if (sflag) { @@ -469,9 +478,7 @@ main(int argc, char *argv[]) uflag ? "udp" : "tcp", sv ? sv->s_name : "*"); } - if (Fflag) - fdpass(s); - else if (!zflag) + if (!zflag) readwrite(s); } } @@ -727,17 +734,25 @@ local_listen(char *host, char *port, str /* * readwrite() - * Loop that polls on the network file descriptor and stdin. + * Loop that polls on the network file descriptor and stdin, or, when the + * FFlag is given, pass the descriptor to stdout. */ void readwrite(int nfd) { struct pollfd pfd[2]; unsigned char buf[16384]; - int n, wfd = fileno(stdin); - int lfd = fileno(stdout); + int n, wfd; + int lfd; int plen; + if (Fflag) { + fdpass(nfd); + return; + } + + lfd = fileno(stdout); + wfd = fileno(stdin); plen = 2048; /* Setup Network FD */ @@ -793,7 +808,7 @@ readwrite(int nfd) /* * fdpass() - * Pass the connected file descriptor to stdout and exit. + * Pass the connected file descriptor to stdout. */ void fdpass(int nfd) @@ -848,7 +863,6 @@ fdpass(int nfd) else break; } - exit(0); } /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */