diff options
author | bluhm <> | 2015-09-08 17:28:47 +0000 |
---|---|---|
committer | bluhm <> | 2015-09-08 17:28:47 +0000 |
commit | 57ddc6c63a7401c575cb57d4a2d6dfa685bf5ffa (patch) | |
tree | 5611e7a32100893f2356bb503fa3c5443a89b3a7 | |
parent | 7e148f977119e2cb2058b9cf3eeb192afd550b41 (diff) | |
download | openbsd-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@
-rw-r--r-- | src/usr.bin/nc/netcat.c | 21 |
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 | ||