summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbluhm <>2015-09-08 17:28:47 +0000
committerbluhm <>2015-09-08 17:28:47 +0000
commit57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa (patch)
tree5611e7a32100893f2356bb503fa3c5443a89b3a7 /src
parent7e148f977119e2cb2058b9cf3eeb192afd550b41 (diff)
downloadopenbsd-57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa.tar.gz
openbsd-57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa.tar.bz2
openbsd-57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa.zip
Netcat could hang during write(2) although poll(2) reports that the
socket is writeable. This happens because netcat tries to write more than the low water mark of the socket write buffer. With a non-blocking socket you may get a short write, otherwise it blocks. The latter could cause a total hang of the netcat process depending on the upper protocol. So make the network connection non-blocking. OK claudio@ millert@
Diffstat (limited to 'src')
-rw-r--r--src/usr.bin/nc/netcat.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c
index 2596a6354e..ce613cd75d 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.131 2015/09/03 23:06:28 sobrado Exp $ */ 1/* $OpenBSD: netcat.c,v 1.132 2015/09/08 17:28:47 bluhm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * 4 *
@@ -397,8 +397,8 @@ main(int argc, char *argv[])
397 readwrite(s); 397 readwrite(s);
398 } else { 398 } else {
399 len = sizeof(cliaddr); 399 len = sizeof(cliaddr);
400 connfd = accept(s, (struct sockaddr *)&cliaddr, 400 connfd = accept4(s, (struct sockaddr *)&cliaddr,
401 &len); 401 &len, SOCK_NONBLOCK);
402 if (connfd == -1) { 402 if (connfd == -1) {
403 /* For now, all errnos are fatal */ 403 /* For now, all errnos are fatal */
404 err(1, "accept"); 404 err(1, "accept");
@@ -594,8 +594,8 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
594 594
595 res0 = res; 595 res0 = res;
596 do { 596 do {
597 if ((s = socket(res0->ai_family, res0->ai_socktype, 597 if ((s = socket(res0->ai_family, res0->ai_socktype |
598 res0->ai_protocol)) < 0) 598 SOCK_NONBLOCK, res0->ai_protocol)) < 0)
599 continue; 599 continue;
600 600
601 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE, 601 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
@@ -644,15 +644,9 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
644{ 644{
645 struct pollfd pfd; 645 struct pollfd pfd;
646 socklen_t optlen; 646 socklen_t optlen;
647 int flags, optval; 647 int optval;
648 int ret; 648 int ret;
649 649
650 if (timeout != -1) {
651 flags = fcntl(s, F_GETFL, 0);
652 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
653 err(1, "set non-blocking mode");
654 }
655
656 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) { 650 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
657 pfd.fd = s; 651 pfd.fd = s;
658 pfd.events = POLLOUT; 652 pfd.events = POLLOUT;
@@ -670,9 +664,6 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
670 err(1, "poll failed"); 664 err(1, "poll failed");
671 } 665 }
672 666
673 if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
674 err(1, "restoring flags");
675
676 return (ret); 667 return (ret);
677} 668}
678 669