summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2015-09-08 17:28:47 +0000
committerbluhm <bluhm@openbsd.org>2015-09-08 17:28:47 +0000
commit3242a7b66cea7c42a90f84918d5798a15678d813 (patch)
treec4fdd4b0b342de6839fe4715a92be5cd1c77feea
parentCorrect strsep() usage to free() correct string. Spotted by and (diff)
downloadwireguard-openbsd-3242a7b66cea7c42a90f84918d5798a15678d813.tar.xz
wireguard-openbsd-3242a7b66cea7c42a90f84918d5798a15678d813.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@
-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);
}