summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2015-09-08 17:28:48 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2015-09-08 17:28:48 +0000
commita88be22796ad34614555f6c116621b3d8aadda72 (patch)
treec5c7c13bc65b06e9ddf8c7f61ad5d6d040a3c1f2
parent4b8b88b5a7b9df5519e35a784f38a9eadfab03bd (diff)
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@
-rw-r--r--usr.bin/nc/netcat.c21
1 files changed, 6 insertions, 15 deletions
diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
index 2596a6354ec..ce613cd75d8 100644
--- a/usr.bin/nc/netcat.c
+++ b/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.131 2015/09/03 23:06:28 sobrado Exp $ */
+/* $OpenBSD: netcat.c,v 1.132 2015/09/08 17:28:47 bluhm Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -397,8 +397,8 @@ main(int argc, char *argv[])
readwrite(s);
} else {
len = sizeof(cliaddr);
- connfd = accept(s, (struct sockaddr *)&cliaddr,
- &len);
+ connfd = accept4(s, (struct sockaddr *)&cliaddr,
+ &len, SOCK_NONBLOCK);
if (connfd == -1) {
/* For now, all errnos are fatal */
err(1, "accept");
@@ -594,8 +594,8 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
res0 = res;
do {
- if ((s = socket(res0->ai_family, res0->ai_socktype,
- res0->ai_protocol)) < 0)
+ if ((s = socket(res0->ai_family, res0->ai_socktype |
+ SOCK_NONBLOCK, res0->ai_protocol)) < 0)
continue;
if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
@@ -644,15 +644,9 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
{
struct pollfd pfd;
socklen_t optlen;
- int flags, optval;
+ int optval;
int ret;
- if (timeout != -1) {
- flags = fcntl(s, F_GETFL, 0);
- if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
- err(1, "set non-blocking mode");
- }
-
if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
pfd.fd = s;
pfd.events = POLLOUT;
@@ -670,9 +664,6 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
err(1, "poll failed");
}
- if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
- err(1, "restoring flags");
-
return (ret);
}