diff options
author | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-09-08 17:28:48 +0000 |
---|---|---|
committer | Alexander Bluhm <bluhm@cvs.openbsd.org> | 2015-09-08 17:28:48 +0000 |
commit | a88be22796ad34614555f6c116621b3d8aadda72 (patch) | |
tree | c5c7c13bc65b06e9ddf8c7f61ad5d6d040a3c1f2 | |
parent | 4b8b88b5a7b9df5519e35a784f38a9eadfab03bd (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.c | 21 |
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); } |