From 57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa Mon Sep 17 00:00:00 2001 From: bluhm <> Date: Tue, 8 Sep 2015 17:28:47 +0000 Subject: 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@ --- src/usr.bin/nc/netcat.c | 21 ++++++--------------- 1 file 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 @@ -/* $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 * @@ -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); } -- cgit v1.2.3-55-g6feb