Bugzilla – Attachment 1498 Details for
Bug 343
Only try connect to first address when creating tunnel
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
try subsequent addresses
fwd-try-next-addr.diff (text/plain), 11.79 KB, created by
Damien Miller
on 2008-05-09 01:01:36 AEST
(
hide
)
Description:
try subsequent addresses
Filename:
MIME Type:
Creator:
Damien Miller
Created:
2008-05-09 01:01:36 AEST
Size:
11.79 KB
patch
obsolete
>Index: channels.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/channels.c,v >retrieving revision 1.275 >diff -u -p -r1.275 channels.c >--- channels.c 8 May 2008 12:02:23 -0000 1.275 >+++ channels.c 8 May 2008 14:59:21 -0000 >@@ -161,6 +161,8 @@ static int IPv4or6 = AF_UNSPEC; > /* helper */ > static void port_open_helper(Channel *c, char *rtype); > >+static int connect_next(struct addrinfo **, const char *, int); >+ > /* -- channel core */ > > Channel * >@@ -1420,7 +1422,7 @@ channel_post_auth_listener(Channel *c, f > static void > channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) > { >- int err = 0; >+ int err = 0, sock; > socklen_t sz = sizeof(err); > > if (FD_ISSET(c->sock, writeset)) { >@@ -1429,7 +1431,12 @@ channel_post_connecting(Channel *c, fd_s > error("getsockopt SO_ERROR failed"); > } > if (err == 0) { >- debug("channel %d: connected", c->self); >+ debug("channel %d: connected to %s port %d", >+ c->self, c->connect_ctx.host, c->connect_ctx.port); >+ xfree(c->connect_ctx.host); >+ c->connect_ctx.host = NULL; >+ freeaddrinfo(c->connect_ctx.aitop); >+ c->connect_ctx.ai = c->connect_ctx.aitop = NULL; > c->type = SSH_CHANNEL_OPEN; > if (compat20) { > packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); >@@ -1443,8 +1450,23 @@ channel_post_connecting(Channel *c, fd_s > packet_put_int(c->self); > } > } else { >- debug("channel %d: not connected: %s", >+ debug("channel %d: connection failed: %s", > c->self, strerror(err)); >+ /* Try next address, if any */ >+ if ((sock = connect_next(&c->connect_ctx.ai, >+ c->connect_ctx.host, c->connect_ctx.port)) > 0) { >+ close(c->sock); >+ c->sock = c->rfd = c->wfd = sock; >+ channel_max_fd = channel_find_maxfd(); >+ return; >+ } >+ /* Exhausted all addresses */ >+ error("connect_to %.100s port %d: failed.", >+ c->connect_ctx.host, c->connect_ctx.port); >+ xfree(c->connect_ctx.host); >+ c->connect_ctx.host = NULL; >+ freeaddrinfo(c->connect_ctx.aitop); >+ c->connect_ctx.ai = c->connect_ctx.aitop = NULL; > if (compat20) { > packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); > packet_put_int(c->remote_id); >@@ -2311,6 +2333,7 @@ channel_input_port_open(int type, u_int3 > u_short host_port; > char *host, *originator_string; > int remote_id, sock = -1; >+ struct addrinfo *ai, *aitop; > > remote_id = packet_get_int(); > host = packet_get_string(NULL); >@@ -2322,12 +2345,16 @@ channel_input_port_open(int type, u_int3 > originator_string = xstrdup("unknown (remote did not supply name)"); > } > packet_check_eom(); >- sock = channel_connect_to(host, host_port); >+ sock = channel_connect_to(host, host_port, &ai, &aitop); > if (sock != -1) { > c = channel_new("connected socket", > SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0, > originator_string, 1); > c->remote_id = remote_id; >+ c->connect_ctx.host = xstrdup(host); >+ c->connect_ctx.port = host_port; >+ c->connect_ctx.ai = ai; >+ c->connect_ctx.aitop = aitop; > } > xfree(originator_string); > if (c == NULL) { >@@ -2747,30 +2774,26 @@ channel_clear_adm_permitted_opens(void) > num_adm_permitted_opens = 0; > } > >-/* return socket to remote host, port */ >+/* >+ * Attempt non-blocking connect to next host on addrinfo list at *aip. >+ * Returns in-progress socket and updates *aip to next host in list, >+ * allowing continuation in cases where the connection ends up failing. >+ */ > static int >-connect_to(const char *host, u_short port) >+connect_next(struct addrinfo **aip, const char *host, int port) > { >- struct addrinfo hints, *ai, *aitop; >+ struct addrinfo *ai = *aip; >+ int sock, saved_errno; > char ntop[NI_MAXHOST], strport[NI_MAXSERV]; >- int gaierr; >- int sock = -1; > >- memset(&hints, 0, sizeof(hints)); >- hints.ai_family = IPv4or6; >- hints.ai_socktype = SOCK_STREAM; >- snprintf(strport, sizeof strport, "%d", port); >- if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { >- error("connect_to %.100s: unknown host (%s)", host, >- ssh_gai_strerror(gaierr)); >- return -1; >- } >- for (ai = aitop; ai; ai = ai->ai_next) { >+ for (; ai; ai = ai->ai_next) { > if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) > continue; >- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), >- strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { >- error("connect_to: getnameinfo failed"); >+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, >+ ntop, sizeof(ntop), >+ strport, sizeof(strport), >+ NI_NUMERICHOST|NI_NUMERICSERV) != 0) { >+ error("connect_next: getnameinfo failed"); > continue; > } > sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); >@@ -2785,35 +2808,79 @@ connect_to(const char *host, u_short por > fatal("%s: set_nonblock(%d)", __func__, sock); > if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && > errno != EINPROGRESS) { >- error("connect_to %.100s port %s: %.100s", ntop, strport, >- strerror(errno)); >+ debug("connect_next: host %.100s ([%.100s]:%s): " >+ "%.100s", host, ntop, strport, strerror(errno)); >+ saved_errno = errno; > close(sock); >+ errno = saved_errno; > continue; /* fail -- try next */ > } >- break; /* success */ >+ debug("connect_next: host %.100s ([%.100s]:%s) " >+ "in progress, fd=%d", host, ntop, strport, sock); >+ *aip = ai->ai_next; >+ set_nodelay(sock); >+ return sock; >+ } >+ *aip = NULL; >+ return -1; >+} >+ >+/* return socket to remote host, port */ >+static int >+connect_to(const char *host, u_short port, struct addrinfo **aip, >+ struct addrinfo **aitopp) >+{ >+ struct addrinfo hints, *ai, *aitop; >+ int gaierr; >+ int sock = -1; >+ char strport[NI_MAXSERV]; > >+ memset(&hints, 0, sizeof(hints)); >+ hints.ai_family = IPv4or6; >+ hints.ai_socktype = SOCK_STREAM; >+ snprintf(strport, sizeof strport, "%d", port); >+ if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) { >+ error("connect_to %.100s: unknown host (%s)", host, >+ ssh_gai_strerror(gaierr)); >+ return -1; > } >- freeaddrinfo(aitop); >- if (!ai) { >- error("connect_to %.100s port %d: failed.", host, port); >+ >+ ai = aitop; >+ if ((sock = connect_next(&ai, host, port)) == -1) { >+ error("connect to %.100s port %d failed: %s", >+ host, port, strerror(errno)); >+ freeaddrinfo(aitop); >+ *aip = NULL; >+ *aitopp = NULL; > return -1; > } >+ > /* success */ >- set_nodelay(sock); >+ *aip = ai; >+ *aitopp = aitop; > return sock; > } > > int >-channel_connect_by_listen_address(u_short listen_port) >+channel_connect_by_listen_address(u_short listen_port, >+ char **dhost, int *dport, struct addrinfo **aip, struct addrinfo **aitopp) > { >- int i; >+ int i, r; > >- for (i = 0; i < num_permitted_opens; i++) >+ for (i = 0; i < num_permitted_opens; i++) { > if (permitted_opens[i].host_to_connect != NULL && >- permitted_opens[i].listen_port == listen_port) >- return connect_to( >+ permitted_opens[i].listen_port == listen_port) { >+ if ((r = connect_to( > permitted_opens[i].host_to_connect, >- permitted_opens[i].port_to_connect); >+ permitted_opens[i].port_to_connect, >+ aip, aitopp)) != -1) { >+ *dhost = xstrdup( >+ permitted_opens[i].host_to_connect); >+ *dport = permitted_opens[i].port_to_connect; >+ } >+ return r; >+ } >+ } > error("WARNING: Server requests forwarding for unknown listen_port %d", > listen_port); > return -1; >@@ -2821,7 +2888,8 @@ channel_connect_by_listen_address(u_shor > > /* Check if connecting to that port is permitted and connect. */ > int >-channel_connect_to(const char *host, u_short port) >+channel_connect_to(const char *host, u_short port, struct addrinfo **aip, >+ struct addrinfo **aitopp) > { > int i, permit, permit_adm = 1; > >@@ -2849,7 +2917,7 @@ channel_connect_to(const char *host, u_s > "but the request was denied.", host, port); > return -1; > } >- return connect_to(host, port); >+ return connect_to(host, port, aip, aitopp); > } > > void >Index: channels.h >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/channels.h,v >retrieving revision 1.90 >diff -u -p -r1.90 channels.h >--- channels.h 8 May 2008 12:02:23 -0000 1.90 >+++ channels.h 8 May 2008 14:59:21 -0000 >@@ -125,6 +125,13 @@ struct Channel { > channel_outfilter_fn *output_filter; > > int datagram; /* keep boundaries */ >+ >+ /* non-blocking connect */ >+ struct { >+ char *host; >+ int port; >+ struct addrinfo *ai, *aitop; >+ } connect_ctx; > }; > > #define CHAN_EXTENDED_IGNORE 0 >@@ -224,8 +231,10 @@ int channel_add_adm_permitted_opens(cha > void channel_clear_permitted_opens(void); > void channel_clear_adm_permitted_opens(void); > int channel_input_port_forward_request(int, int); >-int channel_connect_to(const char *, u_short); >-int channel_connect_by_listen_address(u_short); >+int channel_connect_to(const char *, u_short, struct addrinfo **, >+ struct addrinfo **); >+int channel_connect_by_listen_address(u_short, char **, int *, >+ struct addrinfo **, struct addrinfo **); > int channel_request_remote_forwarding(const char *, u_short, > const char *, u_short); > int channel_setup_local_fwd_listener(const char *, u_short, >Index: clientloop.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/clientloop.c,v >retrieving revision 1.190 >diff -u -p -r1.190 clientloop.c >--- clientloop.c 8 May 2008 13:06:10 -0000 1.190 >+++ clientloop.c 8 May 2008 14:59:22 -0000 >@@ -1753,8 +1753,10 @@ client_request_forwarded_tcpip(const cha > { > Channel *c = NULL; > char *listen_address, *originator_address; >- int listen_port, originator_port; >+ int listen_port, originator_port, dport; > int sock; >+ char *dhost; >+ struct addrinfo *ai, *aitop; > > /* Get rest of the packet */ > listen_address = packet_get_string(NULL); >@@ -1766,7 +1768,8 @@ client_request_forwarded_tcpip(const cha > debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d", > listen_address, listen_port, originator_address, originator_port); > >- sock = channel_connect_by_listen_address(listen_port); >+ sock = channel_connect_by_listen_address(listen_port, >+ &dhost, &dport, &ai, &aitop); > if (sock < 0) { > xfree(originator_address); > xfree(listen_address); >@@ -1776,6 +1779,10 @@ client_request_forwarded_tcpip(const cha > SSH_CHANNEL_CONNECTING, sock, sock, -1, > CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, > originator_address, 1); >+ c->connect_ctx.host = dhost; >+ c->connect_ctx.port = dport; >+ c->connect_ctx.ai = ai; >+ c->connect_ctx.aitop = aitop; > xfree(originator_address); > xfree(listen_address); > return c; >Index: serverloop.c >=================================================================== >RCS file: /cvs/src/usr.bin/ssh/serverloop.c,v >retrieving revision 1.149 >diff -u -p -r1.149 serverloop.c >--- serverloop.c 8 May 2008 12:02:23 -0000 1.149 >+++ serverloop.c 8 May 2008 14:59:22 -0000 >@@ -911,6 +911,7 @@ server_request_direct_tcpip(void) > int sock; > char *target, *originator; > int target_port, originator_port; >+ struct addrinfo *ai, *aitop; > > target = packet_get_string(NULL); > target_port = packet_get_int(); >@@ -918,18 +919,24 @@ server_request_direct_tcpip(void) > originator_port = packet_get_int(); > packet_check_eom(); > >- debug("server_request_direct_tcpip: originator %s port %d, target %s port %d", >- originator, originator_port, target, target_port); >+ debug("server_request_direct_tcpip: originator %s port %d, target %s " >+ "port %d", originator, originator_port, target, target_port); > > /* XXX check permission */ >- sock = channel_connect_to(target, target_port); >- xfree(target); >+ sock = channel_connect_to(target, target_port, &ai, &aitop); > xfree(originator); >- if (sock < 0) >+ if (sock < 0) { >+ xfree(target); > return NULL; >+ } > c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING, > sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, > CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1); >+ c->connect_ctx.host = target; >+ c->connect_ctx.port = target_port; >+ c->connect_ctx.ai = ai; >+ c->connect_ctx.aitop = aitop; >+ > return c; > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 343
: 1498