This allows e.g. a sequence of clients to have 2-way conversations. Prior to this, server standard input was effectively discarded.
-k -l -u -v reports each time a message comes from a different client than that from which the previous message came. Signed-off-by: Duncan Roe <[email protected]> --- usr.bin/nc/netcat.c | 96 +++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c index 528dbeea678..bccce3d3227 100644 --- a/usr.bin/nc/netcat.c +++ b/usr.bin/nc/netcat.c @@ -141,8 +141,11 @@ void save_peer_cert(struct tls *_tls_ctx, FILE *_fp); void report_sock(const char *, const struct sockaddr *, socklen_t, char *); void report_tls(struct tls *tls_ctx, char * host); void usage(int); -ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *); -ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *); +ssize_t drainbuf(int, unsigned char *, size_t *, struct tls *, int); +ssize_t fillbuf(int, unsigned char *, size_t *, struct tls *, int); +static struct sockaddr_storage cliaddr, cliaddr_saved; +static socklen_t clilen, clilen_saved; +static char *host; void tls_setup_client(struct tls *, int, char *); struct tls *tls_setup_server(struct tls *, int, char *); @@ -150,12 +153,11 @@ int main(int argc, char *argv[]) { int ch, s = -1, ret, socksv; - char *host, *uport; + char *uport; char ipaddr[NI_MAXHOST]; struct addrinfo hints; struct servent *sv; socklen_t len; - struct sockaddr_storage cliaddr; char *proxy = NULL, *proxyport = NULL; const char *errstr; struct addrinfo proxyhints; @@ -579,45 +581,44 @@ main(int argc, char *argv[]) } if (s == -1) err(1, NULL); - if (uflag && kflag) { + if (uflag) { if (family == AF_UNIX) { if (pledge("stdio unix", NULL) == -1) err(1, "pledge"); } - /* - * For UDP and -k, don't connect the socket, - * let it receive datagrams from multiple - * socket pairs. - */ - readwrite(s, NULL); - } else if (uflag && !kflag) { - /* - * For UDP and not -k, we will use recvfrom() - * initially to wait for a caller, then use - * the regular functions to talk to the caller. - */ + /* Use recvfrom() initially to wait for a + * caller, whether -k or not */ int rv; char buf[2048]; - struct sockaddr_storage z; - len = sizeof(z); + clilen = sizeof(cliaddr); rv = recvfrom(s, buf, sizeof(buf), MSG_PEEK, - (struct sockaddr *)&z, &len); + (struct sockaddr *)&cliaddr, &clilen); if (rv == -1) err(1, "recvfrom"); - rv = connect(s, (struct sockaddr *)&z, len); - if (rv == -1) - err(1, "connect"); - - if (family == AF_UNIX) { - if (pledge("stdio unix", NULL) == -1) - err(1, "pledge"); - } - if (vflag) + if (vflag) { report_sock("Connection received from", - (struct sockaddr *)&z, len, + (struct sockaddr *)&cliaddr, clilen, family == AF_UNIX ? host : NULL); + if (kflag) { + clilen_saved = clilen; + memcpy(&cliaddr_saved, &cliaddr, + clilen); + } + } + if (!kflag) { + /* + * For UDP and not -k, + * connect the socket and then use + * the regular functions to talk + * to the caller. + */ + rv = connect(s, + (struct sockaddr *)&cliaddr,clilen); + if (rv == -1) + err(1, "connect"); + } readwrite(s, NULL); } else { @@ -1217,7 +1218,7 @@ readwrite(int net_fd, struct tls *tls_ctx) /* try to read from stdin */ if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) { ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf, - &stdinbufpos, NULL); + &stdinbufpos, NULL, 0); if (ret == TLS_WANT_POLLIN) pfd[POLL_STDIN].events = POLLIN; else if (ret == TLS_WANT_POLLOUT) @@ -1234,7 +1235,7 @@ readwrite(int net_fd, struct tls *tls_ctx) /* try to write to network */ if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) { ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf, - &stdinbufpos, tls_ctx); + &stdinbufpos, tls_ctx, 1); if (ret == TLS_WANT_POLLIN) pfd[POLL_NETOUT].events = POLLIN; else if (ret == TLS_WANT_POLLOUT) @@ -1251,7 +1252,7 @@ readwrite(int net_fd, struct tls *tls_ctx) /* try to read from network */ if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) { ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf, - &netinbufpos, tls_ctx); + &netinbufpos, tls_ctx, 1); if (ret == TLS_WANT_POLLIN) pfd[POLL_NETIN].events = POLLIN; else if (ret == TLS_WANT_POLLOUT) @@ -1283,7 +1284,7 @@ readwrite(int net_fd, struct tls *tls_ctx) /* try to write to stdout */ if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) { ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf, - &netinbufpos, NULL); + &netinbufpos, NULL, 0); if (ret == TLS_WANT_POLLIN) pfd[POLL_STDOUT].events = POLLIN; else if (ret == TLS_WANT_POLLOUT) @@ -1312,7 +1313,8 @@ readwrite(int net_fd, struct tls *tls_ctx) } ssize_t -drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) +drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls, + int is_socket) { ssize_t n; ssize_t adjust; @@ -1322,7 +1324,11 @@ drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) if (n == -1) errx(1, "tls write failed (%s)", tls_error(tls)); } else { - n = write(fd, buf, *bufpos); + if (is_socket && uflag && kflag) + n = sendto(fd, buf, *bufpos, 0, + (struct sockaddr *)&cliaddr, clilen); + else + n = write(fd, buf, *bufpos); /* don't treat EAGAIN, EINTR as error */ if (n == -1 && (errno == EAGAIN || errno == EINTR)) n = TLS_WANT_POLLOUT; @@ -1338,7 +1344,8 @@ drainbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) } ssize_t -fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) +fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls, + int is_socket) { size_t num = BUFSIZE - *bufpos; ssize_t n; @@ -1348,7 +1355,20 @@ fillbuf(int fd, unsigned char *buf, size_t *bufpos, struct tls *tls) if (n == -1) errx(1, "tls read failed (%s)", tls_error(tls)); } else { - n = read(fd, buf + *bufpos, num); + if (is_socket && uflag && kflag) { + clilen = sizeof(cliaddr); + n = recvfrom(fd, buf + *bufpos, num, 0, + (struct sockaddr *)&cliaddr, &clilen); + if (vflag && n >= 0 && (clilen != clilen_saved || + memcmp(&cliaddr_saved, &cliaddr, clilen))) { + report_sock("Connection received from", + (struct sockaddr *)&cliaddr, clilen, + family == AF_UNIX ? host : NULL); + clilen_saved = clilen; + memcpy(&cliaddr_saved, &cliaddr, clilen); + } + } else + n = read(fd, buf + *bufpos, num); /* don't treat EAGAIN, EINTR as error */ if (n == -1 && (errno == EAGAIN || errno == EINTR)) n = TLS_WANT_POLLIN; -- 2.17.5
