aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2013-11-15 23:35:45 +0000
committerXin LI <delphij@FreeBSD.org>2013-11-15 23:35:45 +0000
commit9c95e4238512453a7367f0fbeb10329675f6a44c (patch)
tree40590e77362a0f37a95d6ce5ce876c478762a162
parenta113ffae60e323fae1068c0f4d3b033d5c4db116 (diff)
downloadsrc-9c95e4238512453a7367f0fbeb10329675f6a44c.tar.gz
src-9c95e4238512453a7367f0fbeb10329675f6a44c.zip
Vendor import OpenBSD nc as of 2013/11/15.
Notes
Notes: svn path=/vendor/netcat/dist/; revision=258198
-rw-r--r--nc.121
-rw-r--r--netcat.c98
2 files changed, 100 insertions, 19 deletions
diff --git a/nc.1 b/nc.1
index 1e0ef0753422..81309e86f809 100644
--- a/nc.1
+++ b/nc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: nc.1,v 1.63 2013/07/16 00:07:52 schwarze Exp $
+.\" $OpenBSD: nc.1,v 1.65 2013/08/20 21:05:20 jmc Exp $
.\"
.\" Copyright (c) 1996 David Sacerdote
.\" All rights reserved.
@@ -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.
.\"
-.Dd $Mdocdate: March 20 2013 $
+.Dd $Mdocdate: August 20 2013 $
.Dt NC 1
.Os
.Sh NAME
@@ -34,7 +34,7 @@
.Sh SYNOPSIS
.Nm nc
.Bk -words
-.Op Fl 46DdhklNnrStUuvz
+.Op Fl 46DdFhklNnrStUuvz
.Op Fl I Ar length
.Op Fl i Ar interval
.Op Fl O Ar length
@@ -102,6 +102,21 @@ to use IPv6 addresses only.
Enable debugging on the socket.
.It Fl d
Do not attempt to read from stdin.
+.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
diff --git a/netcat.c b/netcat.c
index 571de9a76663..2211508c8342 100644
--- a/netcat.c
+++ b/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.112 2013/04/29 00:28:23 okan Exp $ */
+/* $OpenBSD: netcat.c,v 1.117 2013/10/26 21:33:29 sthen Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -34,6 +34,7 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/uio.h>
#include <sys/un.h>
#include <netinet/in.h>
@@ -66,6 +67,7 @@
/* 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 */
@@ -85,7 +87,7 @@ int Iflag; /* TCP receive buffer size */
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;
@@ -97,6 +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));
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,
@@ -130,9 +133,10 @@ main(int argc, char *argv[])
host = NULL;
uport = NULL;
sv = NULL;
+ rtableid = getrtable();
while ((ch = getopt(argc, argv,
- "46DdhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
+ "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
switch (ch) {
case '4':
family = AF_INET;
@@ -156,6 +160,9 @@ main(int argc, char *argv[])
case 'd':
dflag = 1;
break;
+ case 'F':
+ Fflag = 1;
+ break;
case 'h':
help();
break;
@@ -195,7 +202,7 @@ main(int argc, char *argv[])
uflag = 1;
break;
case 'V':
- rtableid = (unsigned int)strtonum(optarg, 0,
+ rtableid = (int)strtonum(optarg, 0,
RT_TABLEID_MAX, &errstr);
if (errstr)
errx(1, "rtable %s: %s", errstr, optarg);
@@ -463,7 +470,9 @@ main(int argc, char *argv[])
uflag ? "udp" : "tcp",
sv ? sv->s_name : "*");
}
- if (!zflag)
+ if (Fflag)
+ fdpass(s);
+ else if (!zflag)
readwrite(s);
}
}
@@ -580,11 +589,9 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
res0->ai_protocol)) < 0)
continue;
- if (rtableid) {
- if (setsockopt(s, SOL_SOCKET, SO_RTABLE, &rtableid,
- sizeof(rtableid)) == -1)
- err(1, "setsockopt SO_RTABLE");
- }
+ if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
/* Bind to a local port or source address if specified. */
if (sflag || pflag) {
@@ -691,11 +698,9 @@ local_listen(char *host, char *port, struct addrinfo hints)
res0->ai_protocol)) < 0)
continue;
- if (rtableid) {
- if (setsockopt(s, IPPROTO_IP, SO_RTABLE, &rtableid,
- sizeof(rtableid)) == -1)
- err(1, "setsockopt SO_RTABLE");
- }
+ if (rtableid >= 0 && (setsockopt(s, IPPROTO_IP, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
if (ret == -1)
@@ -787,6 +792,66 @@ readwrite(int nfd)
}
}
+/*
+ * 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));
+ bzero(&pfd, sizeof(pfd));
+
+ 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;
+ for (;;) {
+ r = sendmsg(STDOUT_FILENO, &mh, 0);
+ if (r == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ pfd.events = POLLOUT;
+ 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)
@@ -1014,6 +1079,7 @@ help(void)
\t-6 Use IPv6\n\
\t-D Enable the debug socket option\n\
\t-d Detach from stdin\n\
+ \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\
@@ -1045,7 +1111,7 @@ void
usage(int ret)
{
fprintf(stderr,
- "usage: nc [-46DdhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
+ "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
"\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
"\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
"\t [-x proxy_address[:port]] [destination] [port]\n");