summaryrefslogtreecommitdiff
path: root/src/usr.bin/nc/netcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r--src/usr.bin/nc/netcat.c74
1 files changed, 71 insertions, 3 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index 571de9a766..6997b321db 100644
--- a/src/usr.bin/nc/netcat.c
+++ b/src/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: netcat.c,v 1.112 2013/04/29 00:28:23 okan Exp $ */ 1/* $OpenBSD: netcat.c,v 1.113 2013/08/20 16:22:09 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * 4 *
@@ -34,6 +34,7 @@
34#include <sys/types.h> 34#include <sys/types.h>
35#include <sys/socket.h> 35#include <sys/socket.h>
36#include <sys/time.h> 36#include <sys/time.h>
37#include <sys/uio.h>
37#include <sys/un.h> 38#include <sys/un.h>
38 39
39#include <netinet/in.h> 40#include <netinet/in.h>
@@ -66,6 +67,7 @@
66 67
67/* Command Line Options */ 68/* Command Line Options */
68int dflag; /* detached, no stdin */ 69int dflag; /* detached, no stdin */
70int Fflag; /* fdpass sock to stdout */
69unsigned int iflag; /* Interval Flag */ 71unsigned int iflag; /* Interval Flag */
70int kflag; /* More than one connect */ 72int kflag; /* More than one connect */
71int lflag; /* Bind to local port */ 73int lflag; /* Bind to local port */
@@ -97,6 +99,7 @@ void build_ports(char *);
97void help(void); 99void help(void);
98int local_listen(char *, char *, struct addrinfo); 100int local_listen(char *, char *, struct addrinfo);
99void readwrite(int); 101void readwrite(int);
102void fdpass(int nfd) __attribute__((noreturn));
100int remote_connect(const char *, const char *, struct addrinfo); 103int remote_connect(const char *, const char *, struct addrinfo);
101int timeout_connect(int, const struct sockaddr *, socklen_t); 104int timeout_connect(int, const struct sockaddr *, socklen_t);
102int socks_connect(const char *, const char *, struct addrinfo, 105int socks_connect(const char *, const char *, struct addrinfo,
@@ -132,7 +135,7 @@ main(int argc, char *argv[])
132 sv = NULL; 135 sv = NULL;
133 136
134 while ((ch = getopt(argc, argv, 137 while ((ch = getopt(argc, argv,
135 "46DdhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) { 138 "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
136 switch (ch) { 139 switch (ch) {
137 case '4': 140 case '4':
138 family = AF_INET; 141 family = AF_INET;
@@ -156,6 +159,9 @@ main(int argc, char *argv[])
156 case 'd': 159 case 'd':
157 dflag = 1; 160 dflag = 1;
158 break; 161 break;
162 case 'F':
163 Fflag = 1;
164 break;
159 case 'h': 165 case 'h':
160 help(); 166 help();
161 break; 167 break;
@@ -463,7 +469,9 @@ main(int argc, char *argv[])
463 uflag ? "udp" : "tcp", 469 uflag ? "udp" : "tcp",
464 sv ? sv->s_name : "*"); 470 sv ? sv->s_name : "*");
465 } 471 }
466 if (!zflag) 472 if (Fflag)
473 fdpass(s);
474 else if (!zflag)
467 readwrite(s); 475 readwrite(s);
468 } 476 }
469 } 477 }
@@ -787,6 +795,66 @@ readwrite(int nfd)
787 } 795 }
788} 796}
789 797
798/*
799 * fdpass()
800 * Pass the connected file descriptor to stdout and exit.
801 */
802void
803fdpass(int nfd)
804{
805 struct msghdr mh;
806 union {
807 struct cmsghdr hdr;
808 char buf[CMSG_SPACE(sizeof(int))];
809 } cmsgbuf;
810 struct cmsghdr *cmsg;
811 struct iovec iov;
812 char c = '\0';
813 ssize_t r;
814 struct pollfd pfd;
815
816 /* Avoid obvious stupidity */
817 if (isatty(STDOUT_FILENO))
818 errx(1, "Cannot pass file descriptor to tty");
819
820 bzero(&mh, sizeof(mh));
821 bzero(&cmsgbuf, sizeof(cmsgbuf));
822 bzero(&iov, sizeof(iov));
823 bzero(&pfd, sizeof(pfd));
824
825 mh.msg_control = (caddr_t)&cmsgbuf.buf;
826 mh.msg_controllen = sizeof(cmsgbuf.buf);
827 cmsg = CMSG_FIRSTHDR(&mh);
828 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
829 cmsg->cmsg_level = SOL_SOCKET;
830 cmsg->cmsg_type = SCM_RIGHTS;
831 *(int *)CMSG_DATA(cmsg) = nfd;
832
833 iov.iov_base = &c;
834 iov.iov_len = 1;
835 mh.msg_iov = &iov;
836 mh.msg_iovlen = 1;
837
838 bzero(&pfd, sizeof(pfd));
839 pfd.fd = STDOUT_FILENO;
840 for (;;) {
841 r = sendmsg(STDOUT_FILENO, &mh, 0);
842 if (r == -1) {
843 if (errno == EAGAIN || errno == EINTR) {
844 pfd.events = POLLOUT;
845 if (poll(&pfd, 1, -1) == -1)
846 err(1, "poll");
847 continue;
848 }
849 err(1, "sendmsg");
850 } else if (r == -1)
851 errx(1, "sendmsg: unexpected return value %zd", r);
852 else
853 break;
854 }
855 exit(0);
856}
857
790/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */ 858/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
791void 859void
792atelnet(int nfd, unsigned char *buf, unsigned int size) 860atelnet(int nfd, unsigned char *buf, unsigned int size)