source: npl/overig/netcat_openbsd/patches/0002-connect-timeout.patch @ c5c522c

gcc484ntopperl-5.22
Last change on this file since c5c522c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 3.4 KB
RevLine 
[c5c522c]1From: Aron Xu <aron@debian.org>
2Date: Mon, 13 Feb 2012 14:43:56 +0800
3Subject: connect timeout
4
5---
6 netcat.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
7 1 file changed, 75 insertions(+), 2 deletions(-)
8
9diff --git a/netcat.c b/netcat.c
10index 9b2def2..f3cc8c1 100644
11--- a/netcat.c
12+++ b/netcat.c
13@@ -106,6 +106,10 @@
14 #define PORT_MAX_LEN   6
15 #define UNIX_DG_TMP_SOCKET_SIZE        19
16 
17+#define CONNECTION_SUCCESS 0
18+#define CONNECTION_FAILED 1
19+#define CONNECTION_TIMEOUT 2
20+
21 /* Command Line Options */
22 int    dflag;                                  /* detached, no stdin */
23 unsigned int iflag;                            /* Interval Flag */
24@@ -151,6 +155,9 @@ void        set_common_sockopts(int);
25 int    map_tos(char *, int *);
26 void   usage(int);
27 
28+static int connect_with_timeout(int fd, const struct sockaddr *sa,
29+        socklen_t salen, int ctimeout);
30+
31 int
32 main(int argc, char *argv[])
33 {
34@@ -651,11 +658,14 @@ remote_connect(const char *host, const char *port, struct addrinfo hints)
35 
36                set_common_sockopts(s);
37 
38-               if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
39+                if ((error = connect_with_timeout(s, res0->ai_addr, res0->ai_addrlen, timeout))== CONNECTION_SUCCESS)
40                        break;
41-               else if (vflag)
42+               else if (vflag && error == CONNECTION_FAILED)
43                        warn("connect to %s port %s (%s) failed", host, port,
44                            uflag ? "udp" : "tcp");
45+                else if (vflag && error == CONNECTION_TIMEOUT)
46+                    warn("connect to %s port %s (%s) timed out", host, port,
47+                            uflag ? "udp" : "tcp");
48 
49                close(s);
50                s = -1;
51@@ -703,6 +713,69 @@ timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
52        return (ret);
53 }
54 
55+static int connect_with_timeout(int fd, const struct sockaddr *sa,
56+                               socklen_t salen, int ctimeout)
57+{
58+       int err;
59+       struct timeval tv, *tvp = NULL;
60+       fd_set connect_fdset;
61+       socklen_t len;
62+       int orig_flags;
63+
64+       orig_flags = fcntl(fd, F_GETFL, 0);
65+       if (fcntl(fd, F_SETFL, orig_flags | O_NONBLOCK) < 0 ) {
66+               warn("can't set O_NONBLOCK - timeout not available");
67+               if (connect(fd, sa, salen) == 0)
68+                       return CONNECTION_SUCCESS;
69+               else
70+                       return CONNECTION_FAILED;
71+       }
72+
73+       /* set connect timeout */
74+       if (ctimeout > 0) {
75+               tv.tv_sec = (time_t)ctimeout/1000;
76+               tv.tv_usec = 0;
77+               tvp = &tv;
78+       }
79+
80+       /* attempt the connection */
81+       err = connect(fd, sa, salen);
82+       if (err != 0 && errno == EINPROGRESS) {
83+               /* connection is proceeding
84+                * it is complete (or failed) when select returns */
85+
86+               /* initialize connect_fdset */
87+               FD_ZERO(&connect_fdset);
88+               FD_SET(fd, &connect_fdset);
89+
90+               /* call select */
91+               do {
92+                       err = select(fd + 1, NULL, &connect_fdset,
93+                                    NULL, tvp);
94+               } while (err < 0 && errno == EINTR);
95+
96+               /* select error */
97+               if (err < 0)
98+                       errx(1,"select error: %s", strerror(errno));
99+               /* we have reached a timeout */
100+               if (err == 0)
101+                       return CONNECTION_TIMEOUT;
102+               /* select returned successfully, but we must test socket
103+                * error for result */
104+               len = sizeof(err);
105+               if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
106+                       errx(1, "getsockopt error: %s", strerror(errno));
107+               /* setup errno according to the result returned by
108+                * getsockopt */
109+               if (err != 0)
110+                       errno = err;
111+       }
112+
113+       /* return aborted if an error occured, and valid otherwise */
114+       fcntl(fd, F_SETFL, orig_flags);
115+       return (err != 0)? CONNECTION_FAILED : CONNECTION_SUCCESS;
116+}
117+
118 /*
119  * local_listen()
120  * Returns a socket listening on a local port, binds to specified source
121--
Note: See TracBrowser for help on using the repository browser.