[Midnightbsd-cvs] src [11173] trunk/contrib/netcat: sync up fron openbsd

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Jun 30 13:27:53 EDT 2018


Revision: 11173
          http://svnweb.midnightbsd.org/src/?rev=11173
Author:   laffer1
Date:     2018-06-30 13:27:52 -0400 (Sat, 30 Jun 2018)
Log Message:
-----------
sync up fron openbsd

Modified Paths:
--------------
    trunk/contrib/netcat/atomicio.c
    trunk/contrib/netcat/nc.1
    trunk/contrib/netcat/netcat.c
    trunk/contrib/netcat/socks.c

Modified: trunk/contrib/netcat/atomicio.c
===================================================================
--- trunk/contrib/netcat/atomicio.c	2018-06-30 17:25:53 UTC (rev 11172)
+++ trunk/contrib/netcat/atomicio.c	2018-06-30 17:27:52 UTC (rev 11173)
@@ -1,4 +1,4 @@
-/* $OpenBSD: atomicio.c,v 1.10 2011/01/08 00:47:19 jeremy Exp $ */
+/* $OpenBSD: atomicio.c,v 1.11 2012/12/04 02:24:47 deraadt Exp $ */
 /*
  * Copyright (c) 2006 Damien Miller. All rights reserved.
  * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
@@ -26,8 +26,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <sys/param.h>
-
 #include <errno.h>
 #include <poll.h>
 #include <unistd.h>

Modified: trunk/contrib/netcat/nc.1
===================================================================
--- trunk/contrib/netcat/nc.1	2018-06-30 17:25:53 UTC (rev 11172)
+++ trunk/contrib/netcat/nc.1	2018-06-30 17:27:52 UTC (rev 11173)
@@ -1,4 +1,4 @@
-.\"     $OpenBSD: nc.1,v 1.61 2012/07/07 15:33:02 haesbaert Exp $
+.\"     $OpenBSD: nc.1,v 1.68 2015/03/26 10:35:04 tobias Exp $
 .\"
 .\" Copyright (c) 1996 David Sacerdote
 .\" All rights reserved.
@@ -25,9 +25,9 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $FreeBSD$
+.\" $FreeBSD: stable/10/contrib/netcat/nc.1 294288 2016-01-18 19:42:05Z delphij $
 .\"
-.Dd February 7, 2012
+.Dd September 26, 2015
 .Dt NC 1
 .Os
 .Sh NAME
@@ -36,7 +36,7 @@
 .Sh SYNOPSIS
 .Nm nc
 .Bk -words
-.Op Fl 46DdEhklnrStUuvz
+.Op Fl 46DdEFhklNnrStUuvz
 .Op Fl e Ar IPsec_policy
 .Op Fl I Ar length
 .Op Fl i Ar interval
@@ -120,6 +120,21 @@
 .Xr ipsec_set_policy 3 .
 This flag can be specified up to two times, as typically one policy for
 each direction is needed.
+.It Fl F
+Pass the first connected socket using
+.Xr sendmsg 2
+to stdout and exit.
+This is useful in conjunction with
+.Fl X
+to have
+.Nm
+perform connection setup with a proxy but then leave the rest of the
+connection to another program (e.g.\&
+.Xr ssh 1
+using the
+.Xr ssh_config 5
+.Cm ProxyUseFdpass
+option).
 .It Fl h
 Prints out
 .Nm
@@ -155,6 +170,10 @@
 Additionally, any timeouts specified with the
 .Fl w
 option are ignored.
+.It Fl N
+.Xr shutdown 2
+the network socket after EOF on the input.
+Some servers require this to finish their work.
 .It Fl n
 Do not do any DNS or service lookups on any specified addresses,
 hostnames or ports.
@@ -232,7 +251,6 @@
 Set the routing table
 .Pq Dq FIB
 to be used.
-The default is 0.
 .It Fl v
 Have
 .Nm
@@ -361,7 +379,7 @@
 .Nm
 process, feeding it the file which is to be transferred:
 .Pp
-.Dl $ nc host.example.com 1234 \*(Lt filename.in
+.Dl $ nc -N host.example.com 1234 \*(Lt filename.in
 .Pp
 After the file has been transferred, the connection will close automatically.
 .Sh TALKING TO SERVERS
@@ -486,10 +504,10 @@
 .Xr tcp 4
 .Sh AUTHORS
 Original implementation by *Hobbit*
-.Aq hobbit at avian.org .
+.Aq Mt hobbit at avian.org .
 .br
 Rewritten with IPv6 support by
-.An Eric Jackson Aq ericj at monkey.org .
+.An Eric Jackson Aq Mt ericj at monkey.org .
 .Sh CAVEATS
 UDP port scans using the
 .Fl uz

Modified: trunk/contrib/netcat/netcat.c
===================================================================
--- trunk/contrib/netcat/netcat.c	2018-06-30 17:25:53 UTC (rev 11172)
+++ trunk/contrib/netcat/netcat.c	2018-06-30 17:27:52 UTC (rev 11173)
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.109 2012/07/07 15:33:02 haesbaert Exp $ */
+/* $OpenBSD: netcat.c,v 1.130 2015/07/26 19:12:28 chl Exp $ */
 /*
  * Copyright (c) 2001 Eric Jackson <ericj at monkey.org>
  *
@@ -25,7 +25,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $FreeBSD$
+ * $FreeBSD: stable/10/contrib/netcat/netcat.c 294288 2016-01-18 19:42:05Z delphij $
  */
 
 /*
@@ -38,10 +38,10 @@
 #include <sys/socket.h>
 #include <sys/sysctl.h>
 #include <sys/time.h>
+#include <sys/uio.h>
 #include <sys/un.h>
 
 #include <netinet/in.h>
-#include <netinet/in_systm.h>
 #ifdef IPSEC
 #include <netipsec/ipsec.h>
 #endif
@@ -52,15 +52,16 @@
 #include <err.h>
 #include <errno.h>
 #include <getopt.h>
+#include <fcntl.h>
+#include <limits.h>
 #include <netdb.h>
 #include <poll.h>
+#include <signal.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
-#include <fcntl.h>
-#include <limits.h>
 #include "atomicio.h"
 
 #ifndef SUN_LEN
@@ -72,11 +73,19 @@
 #define PORT_MAX_LEN	6
 #define UNIX_DG_TMP_SOCKET_SIZE	19
 
+#define POLL_STDIN 0
+#define POLL_NETOUT 1
+#define POLL_NETIN 2
+#define POLL_STDOUT 3
+#define BUFSIZE 16384
+
 /* Command Line Options */
 int	dflag;					/* detached, no stdin */
+int	Fflag;					/* fdpass sock to stdout */
 unsigned int iflag;				/* Interval Flag */
 int	kflag;					/* More than one connect */
 int	lflag;					/* Bind to local port */
+int	Nflag;					/* shutdown() network socket */
 int	nflag;					/* Don't do name look up */
 int	FreeBSD_Oflag;				/* Do not use TCP options */
 char   *Pflag;					/* Proxy username */
@@ -93,7 +102,7 @@
 int	Oflag;					/* TCP send buffer size */
 int	Sflag;					/* TCP MD5 signature option */
 int	Tflag = -1;				/* IP Type of Service */
-u_int	rtableid;
+int	rtableid = -1;
 
 int timeout = -1;
 int family = AF_UNSPEC;
@@ -105,6 +114,7 @@
 void	help(void);
 int	local_listen(char *, char *, struct addrinfo);
 void	readwrite(int);
+void	fdpass(int nfd) __attribute__((noreturn));
 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,
@@ -113,10 +123,12 @@
 int	unix_bind(char *);
 int	unix_connect(char *);
 int	unix_listen(char *);
-void	set_common_sockopts(int);
+void	set_common_sockopts(int, int);
 int	map_tos(char *, int *);
 void	report_connect(const struct sockaddr *, socklen_t);
 void	usage(int);
+ssize_t drainbuf(int, unsigned char *, size_t *);
+ssize_t fillbuf(int, unsigned char *, size_t *);
 
 #ifdef IPSEC
 void	add_ipsec_policy(int, char *);
@@ -152,8 +164,10 @@
 	uport = NULL;
 	sv = NULL;
 
+	signal(SIGPIPE, SIG_IGN);
+
 	while ((ch = getopt_long(argc, argv,
-	    "46DdEe:hI:i:klnoO:P:p:rSs:tT:UuV:vw:X:x:z",
+	    "46DdEe:FhI:i:klNnoO:P:p:rSs:tT:UuV:vw:X:x:z",
 	    longopts, NULL)) != -1) {
 		switch (ch) {
 		case '4':
@@ -193,6 +207,9 @@
 			errx(1, "IPsec support unavailable.");
 #endif
 			break;
+		case 'F':
+			Fflag = 1;
+			break;
 		case 'h':
 			help();
 			break;
@@ -207,6 +224,9 @@
 		case 'l':
 			lflag = 1;
 			break;
+		case 'N':
+			Nflag = 1;
+			break;
 		case 'n':
 			nflag = 1;
 			break;
@@ -234,7 +254,7 @@
 		case 'V':
 			if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
 				errx(1, "Multiple FIBS not supported");
-			rtableid = (unsigned int)strtonum(optarg, 0,
+			rtableid = (int)strtonum(optarg, 0,
 			    numfibs - 1, &errstr);
 			if (errstr)
 				errx(1, "rtable %s: %s", errstr, optarg);
@@ -424,9 +444,10 @@
 				len = sizeof(cliaddr);
 				connfd = accept(s, (struct sockaddr *)&cliaddr,
 				    &len);
-				if (connfd == -1)
+				if (connfd == -1) {
+					/* For now, all errnos are fatal */
 					err(1, "accept");
-
+				}
 				if (vflag)
 					report_connect((struct sockaddr *)&cliaddr, len);
 
@@ -503,7 +524,9 @@
 				    uflag ? "udp" : "tcp",
 				    sv ? sv->s_name : "*");
 			}
-			if (!zflag)
+			if (Fflag)
+				fdpass(s);
+			else if (!zflag)
 				readwrite(s);
 		}
 	}
@@ -563,7 +586,7 @@
 		if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
 			return (-1);
 	}
-	(void)fcntl(s, F_SETFD, 1);
+	(void)fcntl(s, F_SETFD, FD_CLOEXEC);
 
 	memset(&sun, 0, sizeof(struct sockaddr_un));
 	sun.sun_family = AF_UNIX;
@@ -626,12 +649,9 @@
 			add_ipsec_policy(s, ipsec_policy[1]);
 #endif
 
-		if (rtableid) {
-			if (setsockopt(s, SOL_SOCKET, SO_SETFIB, &rtableid,
-			    sizeof(rtableid)) == -1)
-				err(1, "setsockopt(.., SO_SETFIB, %u, ..)",
-				    rtableid);
-		}
+		if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_SETFIB,
+		    &rtableid, sizeof(rtableid)) == -1))
+			err(1, "setsockopt SO_SETFIB");
 
 		/* Bind to a local port or source address if specified. */
 		if (sflag || pflag) {
@@ -649,11 +669,11 @@
 
 			if (bind(s, (struct sockaddr *)ares->ai_addr,
 			    ares->ai_addrlen) < 0)
-				errx(1, "bind failed: %s", strerror(errno));
+				err(1, "bind failed");
 			freeaddrinfo(ares);
 		}
 
-		set_common_sockopts(s);
+		set_common_sockopts(s, res0->ai_family);
 
 		if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
 			break;
@@ -738,13 +758,9 @@
 		    res0->ai_protocol)) < 0)
 			continue;
 
-		if (rtableid) {
-			ret = setsockopt(s, SOL_SOCKET, SO_SETFIB, &rtableid,
-			    sizeof(rtableid));
-			if (ret == -1)
-				err(1, "setsockopt(.., SO_SETFIB, %u, ..)",
-				    rtableid);
-		}
+		if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_SETFIB,
+		    &rtableid, sizeof(rtableid)) == -1))
+			err(1, "setsockopt SO_SETFIB");
 
 		ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
 		if (ret == -1)
@@ -761,6 +777,8 @@
 				err(1, "disable TCP options");
 		}
 
+		set_common_sockopts(s, res0->ai_family);
+
 		if (bind(s, (struct sockaddr *)res0->ai_addr,
 		    res0->ai_addrlen) == 0)
 			break;
@@ -784,66 +802,283 @@
  * Loop that polls on the network file descriptor and stdin.
  */
 void
-readwrite(int nfd)
+readwrite(int net_fd)
 {
-	struct pollfd pfd[2];
-	unsigned char buf[16384];
-	int n, wfd = fileno(stdin);
-	int lfd = fileno(stdout);
-	int plen;
+	struct pollfd pfd[4];
+	int stdin_fd = STDIN_FILENO;
+	int stdout_fd = STDOUT_FILENO;
+	unsigned char netinbuf[BUFSIZE];
+	size_t netinbufpos = 0;
+	unsigned char stdinbuf[BUFSIZE];
+	size_t stdinbufpos = 0;
+	int n, num_fds;
+	ssize_t ret;
 
-	plen = 2048;
+	/* don't read from stdin if requested */
+	if (dflag)
+		stdin_fd = -1;
 
-	/* Setup Network FD */
-	pfd[0].fd = nfd;
-	pfd[0].events = POLLIN;
+	/* stdin */
+	pfd[POLL_STDIN].fd = stdin_fd;
+	pfd[POLL_STDIN].events = POLLIN;
 
-	/* Set up STDIN FD. */
-	pfd[1].fd = wfd;
-	pfd[1].events = POLLIN;
+	/* network out */
+	pfd[POLL_NETOUT].fd = net_fd;
+	pfd[POLL_NETOUT].events = 0;
 
-	while (pfd[0].fd != -1) {
+	/* network in */
+	pfd[POLL_NETIN].fd = net_fd;
+	pfd[POLL_NETIN].events = POLLIN;
+
+	/* stdout */
+	pfd[POLL_STDOUT].fd = stdout_fd;
+	pfd[POLL_STDOUT].events = 0;
+
+	while (1) {
+		/* both inputs are gone, buffers are empty, we are done */
+		if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
+		    && stdinbufpos == 0 && netinbufpos == 0) {
+			close(net_fd);
+			return;
+		}
+		/* both outputs are gone, we can't continue */
+		if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
+			close(net_fd);
+			return;
+		}
+		/* listen and net in gone, queues empty, done */
+		if (lflag && pfd[POLL_NETIN].fd == -1
+		    && stdinbufpos == 0 && netinbufpos == 0) {
+			close(net_fd);
+			return;
+		}
+
+		/* help says -i is for "wait between lines sent". We read and
+		 * write arbitrary amounts of data, and we don't want to start
+		 * scanning for newlines, so this is as good as it gets */
 		if (iflag)
 			sleep(iflag);
 
-		if ((n = poll(pfd, 2 - dflag, timeout)) < 0) {
-			close(nfd);
-			err(1, "Polling Error");
+		/* poll */
+		num_fds = poll(pfd, 4, timeout);
+
+		/* treat poll errors */
+		if (num_fds == -1) {
+			close(net_fd);
+			err(1, "polling error");
 		}
 
-		if (n == 0)
+		/* timeout happened */
+		if (num_fds == 0)
 			return;
 
-		if (pfd[0].revents & POLLIN) {
-			if ((n = read(nfd, buf, plen)) < 0)
-				return;
-			else if (n == 0) {
-				shutdown(nfd, SHUT_RD);
-				pfd[0].fd = -1;
-				pfd[0].events = 0;
-			} else {
-				if (tflag)
-					atelnet(nfd, buf, n);
-				if (atomicio(vwrite, lfd, buf, n) != n)
-					return;
+		/* treat socket error conditions */
+		for (n = 0; n < 4; n++) {
+			if (pfd[n].revents & (POLLERR|POLLNVAL)) {
+				pfd[n].fd = -1;
 			}
 		}
+		/* reading is possible after HUP */
+		if (pfd[POLL_STDIN].events & POLLIN &&
+		    pfd[POLL_STDIN].revents & POLLHUP &&
+		    ! (pfd[POLL_STDIN].revents & POLLIN))
+				pfd[POLL_STDIN].fd = -1;
 
-		if (!dflag && pfd[1].revents & POLLIN) {
-			if ((n = read(wfd, buf, plen)) < 0)
-				return;
-			else if (n == 0) {
-				shutdown(nfd, SHUT_WR);
-				pfd[1].fd = -1;
-				pfd[1].events = 0;
-			} else {
-				if (atomicio(vwrite, nfd, buf, n) != n)
-					return;
+		if (pfd[POLL_NETIN].events & POLLIN &&
+		    pfd[POLL_NETIN].revents & POLLHUP &&
+		    ! (pfd[POLL_NETIN].revents & POLLIN))
+				pfd[POLL_NETIN].fd = -1;
+
+		if (pfd[POLL_NETOUT].revents & POLLHUP) {
+			if (Nflag)
+				shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+			pfd[POLL_NETOUT].fd = -1;
+		}
+		/* if HUP, stop watching stdout */
+		if (pfd[POLL_STDOUT].revents & POLLHUP)
+			pfd[POLL_STDOUT].fd = -1;
+		/* if no net out, stop watching stdin */
+		if (pfd[POLL_NETOUT].fd == -1)
+			pfd[POLL_STDIN].fd = -1;
+		/* if no stdout, stop watching net in */
+		if (pfd[POLL_STDOUT].fd == -1) {
+			if (pfd[POLL_NETIN].fd != -1)
+				shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+			pfd[POLL_NETIN].fd = -1;
+		}
+
+		/* try to read from stdin */
+		if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
+			ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
+			    &stdinbufpos);
+			/* error or eof on stdin - remove from pfd */
+			if (ret == 0 || ret == -1)
+				pfd[POLL_STDIN].fd = -1;
+			/* read something - poll net out */
+			if (stdinbufpos > 0)
+				pfd[POLL_NETOUT].events = POLLOUT;
+			/* filled buffer - remove self from polling */
+			if (stdinbufpos == BUFSIZE)
+				pfd[POLL_STDIN].events = 0;
+		}
+		/* try to write to network */
+		if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
+			ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
+			    &stdinbufpos);
+			if (ret == -1)
+				pfd[POLL_NETOUT].fd = -1;
+			/* buffer empty - remove self from polling */
+			if (stdinbufpos == 0)
+				pfd[POLL_NETOUT].events = 0;
+			/* buffer no longer full - poll stdin again */
+			if (stdinbufpos < BUFSIZE)
+				pfd[POLL_STDIN].events = POLLIN;
+		}
+		/* try to read from network */
+		if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
+			ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
+			    &netinbufpos);
+			if (ret == -1)
+				pfd[POLL_NETIN].fd = -1;
+			/* eof on net in - remove from pfd */
+			if (ret == 0) {
+				shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+				pfd[POLL_NETIN].fd = -1;
 			}
+			/* read something - poll stdout */
+			if (netinbufpos > 0)
+				pfd[POLL_STDOUT].events = POLLOUT;
+			/* filled buffer - remove self from polling */
+			if (netinbufpos == BUFSIZE)
+				pfd[POLL_NETIN].events = 0;
+			/* handle telnet */
+			if (tflag)
+				atelnet(pfd[POLL_NETIN].fd, netinbuf,
+				    netinbufpos);
 		}
+		/* try to write to stdout */
+		if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
+			ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
+			    &netinbufpos);
+			if (ret == -1)
+				pfd[POLL_STDOUT].fd = -1;
+			/* buffer empty - remove self from polling */
+			if (netinbufpos == 0)
+				pfd[POLL_STDOUT].events = 0;
+			/* buffer no longer full - poll net in again */
+			if (netinbufpos < BUFSIZE)
+				pfd[POLL_NETIN].events = POLLIN;
+		}
+
+		/* stdin gone and queue empty? */
+		if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
+			if (pfd[POLL_NETOUT].fd != -1 && Nflag)
+				shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+			pfd[POLL_NETOUT].fd = -1;
+		}
+		/* net in gone and queue empty? */
+		if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
+			pfd[POLL_STDOUT].fd = -1;
+		}
 	}
 }
 
+ssize_t
+drainbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+	ssize_t n;
+	ssize_t adjust;
+
+	n = write(fd, buf, *bufpos);
+	/* don't treat EAGAIN, EINTR as error */
+	if (n == -1 && (errno == EAGAIN || errno == EINTR))
+		n = -2;
+	if (n <= 0)
+		return n;
+	/* adjust buffer */
+	adjust = *bufpos - n;
+	if (adjust > 0)
+		memmove(buf, buf + n, adjust);
+	*bufpos -= n;
+	return n;
+}
+
+
+ssize_t
+fillbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+	size_t num = BUFSIZE - *bufpos;
+	ssize_t n;
+
+	n = read(fd, buf + *bufpos, num);
+	/* don't treat EAGAIN, EINTR as error */
+	if (n == -1 && (errno == EAGAIN || errno == EINTR))
+		n = -2;
+	if (n <= 0)
+		return n;
+	*bufpos += n;
+	return n;
+}
+
+/*
+ * fdpass()
+ * Pass the connected file descriptor to stdout and exit.
+ */
+void
+fdpass(int nfd)
+{
+	struct msghdr mh;
+	union {
+		struct cmsghdr hdr;
+		char buf[CMSG_SPACE(sizeof(int))];
+	} cmsgbuf;
+	struct cmsghdr *cmsg;
+	struct iovec iov;
+	char c = '\0';
+	ssize_t r;
+	struct pollfd pfd;
+
+	/* Avoid obvious stupidity */
+	if (isatty(STDOUT_FILENO))
+		errx(1, "Cannot pass file descriptor to tty");
+
+	bzero(&mh, sizeof(mh));
+	bzero(&cmsgbuf, sizeof(cmsgbuf));
+	bzero(&iov, sizeof(iov));
+
+	mh.msg_control = (caddr_t)&cmsgbuf.buf;
+	mh.msg_controllen = sizeof(cmsgbuf.buf);
+	cmsg = CMSG_FIRSTHDR(&mh);
+	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	*(int *)CMSG_DATA(cmsg) = nfd;
+
+	iov.iov_base = &c;
+	iov.iov_len = 1;
+	mh.msg_iov = &iov;
+	mh.msg_iovlen = 1;
+
+	bzero(&pfd, sizeof(pfd));
+	pfd.fd = STDOUT_FILENO;
+	pfd.events = POLLOUT;
+	for (;;) {
+		r = sendmsg(STDOUT_FILENO, &mh, 0);
+		if (r == -1) {
+			if (errno == EAGAIN || errno == EINTR) {
+				if (poll(&pfd, 1, -1) == -1)
+					err(1, "poll");
+				continue;
+			}
+			err(1, "sendmsg");
+		} else if (r != 1)
+			errx(1, "sendmsg: unexpected return value %zd", r);
+		else
+			break;
+	}
+	exit(0);
+}
+
 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
 void
 atelnet(int nfd, unsigned char *buf, unsigned int size)
@@ -957,7 +1192,7 @@
 }
 
 void
-set_common_sockopts(int s)
+set_common_sockopts(int s, int af)
 {
 	int x = 1;
 
@@ -972,8 +1207,17 @@
 			err(1, NULL);
 	}
 	if (Tflag != -1) {
-		if (setsockopt(s, IPPROTO_IP, IP_TOS,
-		    &Tflag, sizeof(Tflag)) == -1)
+		int proto, option;
+
+		if (af == AF_INET6) {
+			proto = IPPROTO_IPV6;
+			option = IPV6_TCLASS;
+		} else {
+			proto = IPPROTO_IP;
+			option = IP_TOS;
+		}
+
+		if (setsockopt(s, proto, option, &Tflag, sizeof(Tflag)) == -1)
 			err(1, "set IP ToS");
 	}
 	if (Iflag) {
@@ -1082,11 +1326,13 @@
 	\t-e policy	Use specified IPsec policy\n");
 #endif
 	fprintf(stderr, "\
+	\t-F		Pass socket fd\n\
 	\t-h		This help text\n\
 	\t-I length	TCP receive buffer length\n\
 	\t-i secs\t	Delay interval for lines sent, ports scanned\n\
 	\t-k		Keep inbound sockets open for multiple connects\n\
 	\t-l		Listen mode, for inbound connects\n\
+	\t-N		Shutdown the network socket after EOF on stdin\n\
 	\t-n		Suppress name/port resolutions\n\
 	\t--no-tcpopt	Disable TCP options\n\
 	\t-O length	TCP send buffer length\n\
@@ -1139,9 +1385,9 @@
 {
 	fprintf(stderr,
 #ifdef IPSEC
-	    "usage: nc [-46DdEhklnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
+	    "usage: nc [-46DdEFhklNnrStUuvz] [-e policy] [-I length] [-i interval] [-O length]\n"
 #else
-	    "usage: nc [-46DdhklnrStUuvz] [-I length] [-i interval] [-O length]\n"
+	    "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
 #endif
 	    "\t  [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
 	    "\t  [-V rtable] [-w timeout] [-X proxy_protocol]\n"

Modified: trunk/contrib/netcat/socks.c
===================================================================
--- trunk/contrib/netcat/socks.c	2018-06-30 17:25:53 UTC (rev 11172)
+++ trunk/contrib/netcat/socks.c	2018-06-30 17:27:52 UTC (rev 11173)
@@ -1,4 +1,4 @@
-/*	$OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $	*/
+/*	$OpenBSD: socks.c,v 1.21 2015/03/26 21:19:51 tobias Exp $	*/
 
 /*
  * Copyright (c) 1999 Niklas Hallqvist.  All rights reserved.
@@ -308,8 +308,8 @@
 		}
 
 		/* Terminate headers */
-		if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
-			err(1, "write failed (2/%d)", r);
+		if ((cnt = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
+			err(1, "write failed (%zu/2)", cnt);
 
 		/* Read status reply */
 		proxy_read_line(proxyfd, buf, sizeof(buf));



More information about the Midnightbsd-cvs mailing list