diff options
Diffstat (limited to '')
| -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) |
