View | Details | Raw Unified | Return to bug 343
Collapse All | Expand All

(-)channels.c (-37 / +105 lines)
Lines 161-166 static int IPv4or6 = AF_UNSPEC; Link Here
161
/* helper */
161
/* helper */
162
static void port_open_helper(Channel *c, char *rtype);
162
static void port_open_helper(Channel *c, char *rtype);
163
163
164
static int connect_next(struct addrinfo **, const char *, int);
165
164
/* -- channel core */
166
/* -- channel core */
165
167
166
Channel *
168
Channel *
Lines 1420-1426 channel_post_auth_listener(Channel *c, f Link Here
1420
static void
1422
static void
1421
channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1423
channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1422
{
1424
{
1423
	int err = 0;
1425
	int err = 0, sock;
1424
	socklen_t sz = sizeof(err);
1426
	socklen_t sz = sizeof(err);
1425
1427
1426
	if (FD_ISSET(c->sock, writeset)) {
1428
	if (FD_ISSET(c->sock, writeset)) {
Lines 1429-1435 channel_post_connecting(Channel *c, fd_s Link Here
1429
			error("getsockopt SO_ERROR failed");
1431
			error("getsockopt SO_ERROR failed");
1430
		}
1432
		}
1431
		if (err == 0) {
1433
		if (err == 0) {
1432
			debug("channel %d: connected", c->self);
1434
			debug("channel %d: connected to %s port %d",
1435
			    c->self, c->connect_ctx.host, c->connect_ctx.port);
1436
			xfree(c->connect_ctx.host);
1437
			c->connect_ctx.host = NULL;
1438
			freeaddrinfo(c->connect_ctx.aitop);
1439
			c->connect_ctx.ai = c->connect_ctx.aitop = NULL;
1433
			c->type = SSH_CHANNEL_OPEN;
1440
			c->type = SSH_CHANNEL_OPEN;
1434
			if (compat20) {
1441
			if (compat20) {
1435
				packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1442
				packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
Lines 1443-1450 channel_post_connecting(Channel *c, fd_s Link Here
1443
				packet_put_int(c->self);
1450
				packet_put_int(c->self);
1444
			}
1451
			}
1445
		} else {
1452
		} else {
1446
			debug("channel %d: not connected: %s",
1453
			debug("channel %d: connection failed: %s",
1447
			    c->self, strerror(err));
1454
			    c->self, strerror(err));
1455
			/* Try next address, if any */
1456
			if ((sock = connect_next(&c->connect_ctx.ai,
1457
			    c->connect_ctx.host, c->connect_ctx.port)) > 0) {
1458
				close(c->sock);
1459
				c->sock = c->rfd = c->wfd = sock;
1460
				channel_max_fd = channel_find_maxfd();
1461
				return;
1462
			}
1463
			/* Exhausted all addresses */
1464
			error("connect_to %.100s port %d: failed.",
1465
			    c->connect_ctx.host, c->connect_ctx.port);
1466
			xfree(c->connect_ctx.host);
1467
			c->connect_ctx.host = NULL;
1468
			freeaddrinfo(c->connect_ctx.aitop);
1469
			c->connect_ctx.ai = c->connect_ctx.aitop = NULL;
1448
			if (compat20) {
1470
			if (compat20) {
1449
				packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1471
				packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1450
				packet_put_int(c->remote_id);
1472
				packet_put_int(c->remote_id);
Lines 2311-2316 channel_input_port_open(int type, u_int3 Link Here
2311
	u_short host_port;
2333
	u_short host_port;
2312
	char *host, *originator_string;
2334
	char *host, *originator_string;
2313
	int remote_id, sock = -1;
2335
	int remote_id, sock = -1;
2336
	struct addrinfo *ai, *aitop;
2314
2337
2315
	remote_id = packet_get_int();
2338
	remote_id = packet_get_int();
2316
	host = packet_get_string(NULL);
2339
	host = packet_get_string(NULL);
Lines 2322-2333 channel_input_port_open(int type, u_int3 Link Here
2322
		originator_string = xstrdup("unknown (remote did not supply name)");
2345
		originator_string = xstrdup("unknown (remote did not supply name)");
2323
	}
2346
	}
2324
	packet_check_eom();
2347
	packet_check_eom();
2325
	sock = channel_connect_to(host, host_port);
2348
	sock = channel_connect_to(host, host_port, &ai, &aitop);
2326
	if (sock != -1) {
2349
	if (sock != -1) {
2327
		c = channel_new("connected socket",
2350
		c = channel_new("connected socket",
2328
		    SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
2351
		    SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
2329
		    originator_string, 1);
2352
		    originator_string, 1);
2330
		c->remote_id = remote_id;
2353
		c->remote_id = remote_id;
2354
		c->connect_ctx.host = xstrdup(host);
2355
		c->connect_ctx.port = host_port;
2356
		c->connect_ctx.ai = ai;
2357
		c->connect_ctx.aitop = aitop;
2331
	}
2358
	}
2332
	xfree(originator_string);
2359
	xfree(originator_string);
2333
	if (c == NULL) {
2360
	if (c == NULL) {
Lines 2747-2776 channel_clear_adm_permitted_opens(void) Link Here
2747
	num_adm_permitted_opens = 0;
2774
	num_adm_permitted_opens = 0;
2748
}
2775
}
2749
2776
2750
/* return socket to remote host, port */
2777
/*
2778
 * Attempt non-blocking connect to next host on addrinfo list at *aip.
2779
 * Returns in-progress socket and updates *aip to next host in list,
2780
 * allowing continuation in cases where the connection ends up failing.
2781
 */
2751
static int
2782
static int
2752
connect_to(const char *host, u_short port)
2783
connect_next(struct addrinfo **aip, const char *host, int port)
2753
{
2784
{
2754
	struct addrinfo hints, *ai, *aitop;
2785
	struct addrinfo *ai = *aip;
2786
	int sock, saved_errno;
2755
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2787
	char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2756
	int gaierr;
2757
	int sock = -1;
2758
2788
2759
	memset(&hints, 0, sizeof(hints));
2789
	for (; ai; ai = ai->ai_next) {
2760
	hints.ai_family = IPv4or6;
2761
	hints.ai_socktype = SOCK_STREAM;
2762
	snprintf(strport, sizeof strport, "%d", port);
2763
	if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
2764
		error("connect_to %.100s: unknown host (%s)", host,
2765
		    ssh_gai_strerror(gaierr));
2766
		return -1;
2767
	}
2768
	for (ai = aitop; ai; ai = ai->ai_next) {
2769
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2790
		if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2770
			continue;
2791
			continue;
2771
		if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2792
		if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
2772
		    strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2793
		    ntop, sizeof(ntop),
2773
			error("connect_to: getnameinfo failed");
2794
		    strport, sizeof(strport),
2795
		    NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2796
			error("connect_next: getnameinfo failed");
2774
			continue;
2797
			continue;
2775
		}
2798
		}
2776
		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
2799
		sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
Lines 2785-2819 connect_to(const char *host, u_short por Link Here
2785
			fatal("%s: set_nonblock(%d)", __func__, sock);
2808
			fatal("%s: set_nonblock(%d)", __func__, sock);
2786
		if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
2809
		if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
2787
		    errno != EINPROGRESS) {
2810
		    errno != EINPROGRESS) {
2788
			error("connect_to %.100s port %s: %.100s", ntop, strport,
2811
			debug("connect_next: host %.100s ([%.100s]:%s): "
2789
			    strerror(errno));
2812
			    "%.100s", host, ntop, strport, strerror(errno));
2813
			saved_errno = errno;
2790
			close(sock);
2814
			close(sock);
2815
			errno = saved_errno;
2791
			continue;	/* fail -- try next */
2816
			continue;	/* fail -- try next */
2792
		}
2817
		}
2793
		break; /* success */
2818
		debug("connect_next: host %.100s ([%.100s]:%s) "
2819
		    "in progress, fd=%d", host, ntop, strport, sock);
2820
		*aip = ai->ai_next;
2821
		set_nodelay(sock);
2822
		return sock;
2823
	}
2824
	*aip = NULL;
2825
	return -1;
2826
}
2827
	
2828
/* return socket to remote host, port */
2829
static int
2830
connect_to(const char *host, u_short port, struct addrinfo **aip,
2831
    struct addrinfo **aitopp)
2832
{
2833
	struct addrinfo hints, *ai, *aitop;
2834
	int gaierr;
2835
	int sock = -1;
2836
	char strport[NI_MAXSERV];
2794
2837
2838
	memset(&hints, 0, sizeof(hints));
2839
	hints.ai_family = IPv4or6;
2840
	hints.ai_socktype = SOCK_STREAM;
2841
	snprintf(strport, sizeof strport, "%d", port);
2842
	if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
2843
		error("connect_to %.100s: unknown host (%s)", host,
2844
		    ssh_gai_strerror(gaierr));
2845
		return -1;
2795
	}
2846
	}
2796
	freeaddrinfo(aitop);
2847
2797
	if (!ai) {
2848
	ai = aitop;
2798
		error("connect_to %.100s port %d: failed.", host, port);
2849
	if ((sock = connect_next(&ai, host, port)) == -1) {
2850
		error("connect to %.100s port %d failed: %s",
2851
		    host, port, strerror(errno));
2852
		freeaddrinfo(aitop);
2853
		*aip = NULL;
2854
		*aitopp = NULL;
2799
		return -1;
2855
		return -1;
2800
	}
2856
	}
2857
2801
	/* success */
2858
	/* success */
2802
	set_nodelay(sock);
2859
	*aip = ai;
2860
	*aitopp = aitop;
2803
	return sock;
2861
	return sock;
2804
}
2862
}
2805
2863
2806
int
2864
int
2807
channel_connect_by_listen_address(u_short listen_port)
2865
channel_connect_by_listen_address(u_short listen_port,
2866
     char **dhost, int *dport, struct addrinfo **aip, struct addrinfo **aitopp)
2808
{
2867
{
2809
	int i;
2868
	int i, r;
2810
2869
2811
	for (i = 0; i < num_permitted_opens; i++)
2870
	for (i = 0; i < num_permitted_opens; i++) {
2812
		if (permitted_opens[i].host_to_connect != NULL &&
2871
		if (permitted_opens[i].host_to_connect != NULL &&
2813
		    permitted_opens[i].listen_port == listen_port)
2872
		    permitted_opens[i].listen_port == listen_port) {
2814
			return connect_to(
2873
			if ((r = connect_to(
2815
			    permitted_opens[i].host_to_connect,
2874
			    permitted_opens[i].host_to_connect,
2816
			    permitted_opens[i].port_to_connect);
2875
			    permitted_opens[i].port_to_connect,
2876
			    aip, aitopp)) != -1) {
2877
				*dhost = xstrdup(
2878
				    permitted_opens[i].host_to_connect);
2879
				*dport = permitted_opens[i].port_to_connect;
2880
			}
2881
			return r;
2882
		}
2883
	}
2817
	error("WARNING: Server requests forwarding for unknown listen_port %d",
2884
	error("WARNING: Server requests forwarding for unknown listen_port %d",
2818
	    listen_port);
2885
	    listen_port);
2819
	return -1;
2886
	return -1;
Lines 2821-2827 channel_connect_by_listen_address(u_shor Link Here
2821
2888
2822
/* Check if connecting to that port is permitted and connect. */
2889
/* Check if connecting to that port is permitted and connect. */
2823
int
2890
int
2824
channel_connect_to(const char *host, u_short port)
2891
channel_connect_to(const char *host, u_short port, struct addrinfo **aip,
2892
    struct addrinfo **aitopp)
2825
{
2893
{
2826
	int i, permit, permit_adm = 1;
2894
	int i, permit, permit_adm = 1;
2827
2895
Lines 2849-2855 channel_connect_to(const char *host, u_s Link Here
2849
		    "but the request was denied.", host, port);
2917
		    "but the request was denied.", host, port);
2850
		return -1;
2918
		return -1;
2851
	}
2919
	}
2852
	return connect_to(host, port);
2920
	return connect_to(host, port, aip, aitopp);
2853
}
2921
}
2854
2922
2855
void
2923
void
(-)channels.h (-2 / +11 lines)
Lines 125-130 struct Channel { Link Here
125
	channel_outfilter_fn	*output_filter;
125
	channel_outfilter_fn	*output_filter;
126
126
127
	int     datagram;	/* keep boundaries */
127
	int     datagram;	/* keep boundaries */
128
129
	/* non-blocking connect */
130
	struct {
131
		char *host;
132
		int port;
133
		struct addrinfo *ai, *aitop;
134
	}	connect_ctx;
128
};
135
};
129
136
130
#define CHAN_EXTENDED_IGNORE		0
137
#define CHAN_EXTENDED_IGNORE		0
Lines 224-231 int channel_add_adm_permitted_opens(cha Link Here
224
void	 channel_clear_permitted_opens(void);
231
void	 channel_clear_permitted_opens(void);
225
void	 channel_clear_adm_permitted_opens(void);
232
void	 channel_clear_adm_permitted_opens(void);
226
int      channel_input_port_forward_request(int, int);
233
int      channel_input_port_forward_request(int, int);
227
int	 channel_connect_to(const char *, u_short);
234
int	 channel_connect_to(const char *, u_short, struct addrinfo **,
228
int	 channel_connect_by_listen_address(u_short);
235
    struct addrinfo **);
236
int	 channel_connect_by_listen_address(u_short, char **, int *,
237
    struct addrinfo **, struct addrinfo **);
229
int	 channel_request_remote_forwarding(const char *, u_short,
238
int	 channel_request_remote_forwarding(const char *, u_short,
230
	     const char *, u_short);
239
	     const char *, u_short);
231
int	 channel_setup_local_fwd_listener(const char *, u_short,
240
int	 channel_setup_local_fwd_listener(const char *, u_short,
(-)clientloop.c (-2 / +9 lines)
Lines 1753-1760 client_request_forwarded_tcpip(const cha Link Here
1753
{
1753
{
1754
	Channel *c = NULL;
1754
	Channel *c = NULL;
1755
	char *listen_address, *originator_address;
1755
	char *listen_address, *originator_address;
1756
	int listen_port, originator_port;
1756
	int listen_port, originator_port, dport;
1757
	int sock;
1757
	int sock;
1758
	char *dhost;
1759
	struct addrinfo *ai, *aitop;
1758
1760
1759
	/* Get rest of the packet */
1761
	/* Get rest of the packet */
1760
	listen_address = packet_get_string(NULL);
1762
	listen_address = packet_get_string(NULL);
Lines 1766-1772 client_request_forwarded_tcpip(const cha Link Here
1766
	debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
1768
	debug("client_request_forwarded_tcpip: listen %s port %d, originator %s port %d",
1767
	    listen_address, listen_port, originator_address, originator_port);
1769
	    listen_address, listen_port, originator_address, originator_port);
1768
1770
1769
	sock = channel_connect_by_listen_address(listen_port);
1771
	sock = channel_connect_by_listen_address(listen_port,
1772
	    &dhost, &dport, &ai, &aitop);
1770
	if (sock < 0) {
1773
	if (sock < 0) {
1771
		xfree(originator_address);
1774
		xfree(originator_address);
1772
		xfree(listen_address);
1775
		xfree(listen_address);
Lines 1776-1781 client_request_forwarded_tcpip(const cha Link Here
1776
	    SSH_CHANNEL_CONNECTING, sock, sock, -1,
1779
	    SSH_CHANNEL_CONNECTING, sock, sock, -1,
1777
	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
1780
	    CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0,
1778
	    originator_address, 1);
1781
	    originator_address, 1);
1782
	c->connect_ctx.host = dhost;
1783
	c->connect_ctx.port = dport;
1784
	c->connect_ctx.ai = ai;
1785
	c->connect_ctx.aitop = aitop;
1779
	xfree(originator_address);
1786
	xfree(originator_address);
1780
	xfree(listen_address);
1787
	xfree(listen_address);
1781
	return c;
1788
	return c;
(-)serverloop.c (-5 / +12 lines)
Lines 911-916 server_request_direct_tcpip(void) Link Here
911
	int sock;
911
	int sock;
912
	char *target, *originator;
912
	char *target, *originator;
913
	int target_port, originator_port;
913
	int target_port, originator_port;
914
	struct addrinfo *ai, *aitop;
914
915
915
	target = packet_get_string(NULL);
916
	target = packet_get_string(NULL);
916
	target_port = packet_get_int();
917
	target_port = packet_get_int();
Lines 918-935 server_request_direct_tcpip(void) Link Here
918
	originator_port = packet_get_int();
919
	originator_port = packet_get_int();
919
	packet_check_eom();
920
	packet_check_eom();
920
921
921
	debug("server_request_direct_tcpip: originator %s port %d, target %s port %d",
922
	debug("server_request_direct_tcpip: originator %s port %d, target %s "
922
	    originator, originator_port, target, target_port);
923
	    "port %d", originator, originator_port, target, target_port);
923
924
924
	/* XXX check permission */
925
	/* XXX check permission */
925
	sock = channel_connect_to(target, target_port);
926
	sock = channel_connect_to(target, target_port, &ai, &aitop);
926
	xfree(target);
927
	xfree(originator);
927
	xfree(originator);
928
	if (sock < 0)
928
	if (sock < 0) {
929
		xfree(target);
929
		return NULL;
930
		return NULL;
931
	}
930
	c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
932
	c = channel_new("direct-tcpip", SSH_CHANNEL_CONNECTING,
931
	    sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
933
	    sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT,
932
	    CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
934
	    CHAN_TCP_PACKET_DEFAULT, 0, "direct-tcpip", 1);
935
	c->connect_ctx.host = target;
936
	c->connect_ctx.port = target_port;
937
	c->connect_ctx.ai = ai;
938
	c->connect_ctx.aitop = aitop;
939
933
	return c;
940
	return c;
934
}
941
}
935
942

Return to bug 343