diff options
Diffstat (limited to 'src/usr.bin/nc/netcat.c')
-rw-r--r-- | src/usr.bin/nc/netcat.c | 74 |
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 */ |
68 | int dflag; /* detached, no stdin */ | 69 | int dflag; /* detached, no stdin */ |
70 | int Fflag; /* fdpass sock to stdout */ | ||
69 | unsigned int iflag; /* Interval Flag */ | 71 | unsigned int iflag; /* Interval Flag */ |
70 | int kflag; /* More than one connect */ | 72 | int kflag; /* More than one connect */ |
71 | int lflag; /* Bind to local port */ | 73 | int lflag; /* Bind to local port */ |
@@ -97,6 +99,7 @@ void build_ports(char *); | |||
97 | void help(void); | 99 | void help(void); |
98 | int local_listen(char *, char *, struct addrinfo); | 100 | int local_listen(char *, char *, struct addrinfo); |
99 | void readwrite(int); | 101 | void readwrite(int); |
102 | void fdpass(int nfd) __attribute__((noreturn)); | ||
100 | int remote_connect(const char *, const char *, struct addrinfo); | 103 | int remote_connect(const char *, const char *, struct addrinfo); |
101 | int timeout_connect(int, const struct sockaddr *, socklen_t); | 104 | int timeout_connect(int, const struct sockaddr *, socklen_t); |
102 | int socks_connect(const char *, const char *, struct addrinfo, | 105 | int 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 | */ | ||
802 | void | ||
803 | fdpass(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. */ |
791 | void | 859 | void |
792 | atelnet(int nfd, unsigned char *buf, unsigned int size) | 860 | atelnet(int nfd, unsigned char *buf, unsigned int size) |