summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2011-10-04 08:34:35 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2011-10-04 08:34:35 +0000
commit2cec946c0ba6f35dcb74e2da92353821e8b12132 (patch)
tree5db0fd32177c0b961a363df09750ba5d0a65b98b
parent22d59143b24c68530a21ef23cc3558ea72dab438 (diff)
change -w to apply to the connection as well. manpage bit from jmc@
nicm@ ok.
-rw-r--r--usr.bin/nc/nc.18
-rw-r--r--usr.bin/nc/netcat.c42
2 files changed, 44 insertions, 6 deletions
diff --git a/usr.bin/nc/nc.1 b/usr.bin/nc/nc.1
index 6a1538cb456..d249aa18b11 100644
--- a/usr.bin/nc/nc.1
+++ b/usr.bin/nc/nc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: nc.1,v 1.58 2011/09/17 14:10:05 haesbaert Exp $
+.\" $OpenBSD: nc.1,v 1.59 2011/10/04 08:34:34 fgsch Exp $
.\"
.\" Copyright (c) 1996 David Sacerdote
.\" All rights reserved.
@@ -25,7 +25,7 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: September 17 2011 $
+.Dd $Mdocdate: October 4 2011 $
.Dt NC 1
.Os
.Sh NAME
@@ -210,9 +210,9 @@ Have
.Nm
give more verbose output.
.It Fl w Ar timeout
-If a connection and stdin are idle for more than
+Connections which cannot be established or are idle timeout after
.Ar timeout
-seconds, then the connection is silently closed.
+seconds.
The
.Fl w
flag has no effect on the
diff --git a/usr.bin/nc/netcat.c b/usr.bin/nc/netcat.c
index 952bfb7dda0..7880c7f452a 100644
--- a/usr.bin/nc/netcat.c
+++ b/usr.bin/nc/netcat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: netcat.c,v 1.102 2011/09/17 14:10:05 haesbaert Exp $ */
+/* $OpenBSD: netcat.c,v 1.103 2011/10/04 08:34:34 fgsch Exp $ */
/*
* Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
*
@@ -98,6 +98,7 @@ void help(void);
int local_listen(char *, char *, struct addrinfo);
void readwrite(int);
int remote_connect(const char *, const char *, struct addrinfo);
+int timeout_connect(int, const struct sockaddr *, socklen_t);
int socks_connect(const char *, const char *, struct addrinfo,
const char *, const char *, struct addrinfo, int, const char *);
int udptest(int);
@@ -590,7 +591,7 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
set_common_sockopts(s);
- if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+ if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
break;
else if (vflag)
warn("connect to %s port %s (%s) failed", host, port,
@@ -605,6 +606,43 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
return (s);
}
+int
+timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct pollfd pfd;
+ socklen_t optlen;
+ int flags, 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;
+ if ((ret = poll(&pfd, 1, timeout)) == 1) {
+ optlen = sizeof(optval);
+ if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
+ &optval, &optlen)) == 0) {
+ errno = optval;
+ ret = optval == 0 ? 0 : -1;
+ }
+ } else if (ret == 0) {
+ errno = ETIMEDOUT;
+ ret = -1;
+ } else
+ err(1, "poll failed");
+ }
+
+ if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
+ err(1, "restoring flags");
+
+ return (ret);
+}
+
/*
* local_listen()
* Returns a socket listening on a local port, binds to specified source