summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c344
1 files changed, 229 insertions, 115 deletions
diff --git a/channels.c b/channels.c
index 900ab848f..c293eadf1 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.270 2007/06/25 08:20:03 dtucker Exp $ */ 1/* $OpenBSD: channels.c,v 1.286 2008/07/16 11:52:19 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,6 +61,7 @@
61#include <unistd.h> 61#include <unistd.h>
62#include <stdarg.h> 62#include <stdarg.h>
63 63
64#include "openbsd-compat/sys-queue.h"
64#include "xmalloc.h" 65#include "xmalloc.h"
65#include "ssh.h" 66#include "ssh.h"
66#include "ssh1.h" 67#include "ssh1.h"
@@ -164,6 +165,10 @@ static int IPv4or6 = AF_UNSPEC;
164/* helper */ 165/* helper */
165static void port_open_helper(Channel *c, char *rtype); 166static void port_open_helper(Channel *c, char *rtype);
166 167
168/* non-blocking connect helpers */
169static int connect_next(struct channel_connect *);
170static void channel_connect_ctx_free(struct channel_connect *);
171
167/* -- channel core */ 172/* -- channel core */
168 173
169Channel * 174Channel *
@@ -216,7 +221,7 @@ channel_lookup(int id)
216 */ 221 */
217static void 222static void
218channel_register_fds(Channel *c, int rfd, int wfd, int efd, 223channel_register_fds(Channel *c, int rfd, int wfd, int efd,
219 int extusage, int nonblock) 224 int extusage, int nonblock, int is_tty)
220{ 225{
221 /* Update the maximum file descriptor value. */ 226 /* Update the maximum file descriptor value. */
222 channel_max_fd = MAX(channel_max_fd, rfd); 227 channel_max_fd = MAX(channel_max_fd, rfd);
@@ -232,18 +237,9 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
232 c->efd = efd; 237 c->efd = efd;
233 c->extended_usage = extusage; 238 c->extended_usage = extusage;
234 239
235 /* XXX ugly hack: nonblock is only set by the server */ 240 if ((c->isatty = is_tty) != 0)
236 if (nonblock && isatty(c->rfd)) {
237 debug2("channel %d: rfd %d isatty", c->self, c->rfd); 241 debug2("channel %d: rfd %d isatty", c->self, c->rfd);
238 c->isatty = 1; 242 c->wfd_isatty = is_tty || isatty(c->wfd);
239 if (!isatty(c->wfd)) {
240 error("channel %d: wfd %d is not a tty?",
241 c->self, c->wfd);
242 }
243 } else {
244 c->isatty = 0;
245 }
246 c->wfd_isatty = isatty(c->wfd);
247 243
248 /* enable nonblocking mode */ 244 /* enable nonblocking mode */
249 if (nonblock) { 245 if (nonblock) {
@@ -303,7 +299,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
303 c->ostate = CHAN_OUTPUT_OPEN; 299 c->ostate = CHAN_OUTPUT_OPEN;
304 c->istate = CHAN_INPUT_OPEN; 300 c->istate = CHAN_INPUT_OPEN;
305 c->flags = 0; 301 c->flags = 0;
306 channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); 302 channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
307 c->self = found; 303 c->self = found;
308 c->type = type; 304 c->type = type;
309 c->ctype = ctype; 305 c->ctype = ctype;
@@ -319,10 +315,13 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
319 c->single_connection = 0; 315 c->single_connection = 0;
320 c->detach_user = NULL; 316 c->detach_user = NULL;
321 c->detach_close = 0; 317 c->detach_close = 0;
322 c->confirm = NULL; 318 c->open_confirm = NULL;
323 c->confirm_ctx = NULL; 319 c->open_confirm_ctx = NULL;
324 c->input_filter = NULL; 320 c->input_filter = NULL;
325 c->output_filter = NULL; 321 c->output_filter = NULL;
322 c->filter_ctx = NULL;
323 c->filter_cleanup = NULL;
324 TAILQ_INIT(&c->status_confirms);
326 debug("channel %d: new [%s]", found, remote_name); 325 debug("channel %d: new [%s]", found, remote_name);
327 return c; 326 return c;
328} 327}
@@ -379,6 +378,7 @@ channel_free(Channel *c)
379{ 378{
380 char *s; 379 char *s;
381 u_int i, n; 380 u_int i, n;
381 struct channel_confirm *cc;
382 382
383 for (n = 0, i = 0; i < channels_alloc; i++) 383 for (n = 0, i = 0; i < channels_alloc; i++)
384 if (channels[i]) 384 if (channels[i])
@@ -402,6 +402,15 @@ channel_free(Channel *c)
402 xfree(c->remote_name); 402 xfree(c->remote_name);
403 c->remote_name = NULL; 403 c->remote_name = NULL;
404 } 404 }
405 while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
406 if (cc->abandon_cb != NULL)
407 cc->abandon_cb(c, cc->ctx);
408 TAILQ_REMOVE(&c->status_confirms, cc, entry);
409 bzero(cc, sizeof(*cc));
410 xfree(cc);
411 }
412 if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
413 c->filter_cleanup(c->self, c->filter_ctx);
405 channels[c->self] = NULL; 414 channels[c->self] = NULL;
406 xfree(c); 415 xfree(c);
407} 416}
@@ -660,16 +669,33 @@ channel_request_start(int id, char *service, int wantconfirm)
660} 669}
661 670
662void 671void
663channel_register_confirm(int id, channel_callback_fn *fn, void *ctx) 672channel_register_status_confirm(int id, channel_confirm_cb *cb,
673 channel_confirm_abandon_cb *abandon_cb, void *ctx)
674{
675 struct channel_confirm *cc;
676 Channel *c;
677
678 if ((c = channel_lookup(id)) == NULL)
679 fatal("channel_register_expect: %d: bad id", id);
680
681 cc = xmalloc(sizeof(*cc));
682 cc->cb = cb;
683 cc->abandon_cb = abandon_cb;
684 cc->ctx = ctx;
685 TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
686}
687
688void
689channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx)
664{ 690{
665 Channel *c = channel_lookup(id); 691 Channel *c = channel_lookup(id);
666 692
667 if (c == NULL) { 693 if (c == NULL) {
668 logit("channel_register_comfirm: %d: bad id", id); 694 logit("channel_register_open_comfirm: %d: bad id", id);
669 return; 695 return;
670 } 696 }
671 c->confirm = fn; 697 c->open_confirm = fn;
672 c->confirm_ctx = ctx; 698 c->open_confirm_ctx = ctx;
673} 699}
674 700
675void 701void
@@ -700,7 +726,7 @@ channel_cancel_cleanup(int id)
700 726
701void 727void
702channel_register_filter(int id, channel_infilter_fn *ifn, 728channel_register_filter(int id, channel_infilter_fn *ifn,
703 channel_outfilter_fn *ofn) 729 channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
704{ 730{
705 Channel *c = channel_lookup(id); 731 Channel *c = channel_lookup(id);
706 732
@@ -710,17 +736,19 @@ channel_register_filter(int id, channel_infilter_fn *ifn,
710 } 736 }
711 c->input_filter = ifn; 737 c->input_filter = ifn;
712 c->output_filter = ofn; 738 c->output_filter = ofn;
739 c->filter_ctx = ctx;
740 c->filter_cleanup = cfn;
713} 741}
714 742
715void 743void
716channel_set_fds(int id, int rfd, int wfd, int efd, 744channel_set_fds(int id, int rfd, int wfd, int efd,
717 int extusage, int nonblock, u_int window_max) 745 int extusage, int nonblock, int is_tty, u_int window_max)
718{ 746{
719 Channel *c = channel_lookup(id); 747 Channel *c = channel_lookup(id);
720 748
721 if (c == NULL || c->type != SSH_CHANNEL_LARVAL) 749 if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
722 fatal("channel_activate for non-larval channel %d.", id); 750 fatal("channel_activate for non-larval channel %d.", id);
723 channel_register_fds(c, rfd, wfd, efd, extusage, nonblock); 751 channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
724 c->type = SSH_CHANNEL_OPEN; 752 c->type = SSH_CHANNEL_OPEN;
725 c->local_window = c->local_window_max = window_max; 753 c->local_window = c->local_window_max = window_max;
726 packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); 754 packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
@@ -788,7 +816,8 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
788 } 816 }
789 } 817 }
790 /** XXX check close conditions, too */ 818 /** XXX check close conditions, too */
791 if (compat20 && c->efd != -1) { 819 if (compat20 && c->efd != -1 &&
820 !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
792 if (c->extended_usage == CHAN_EXTENDED_WRITE && 821 if (c->extended_usage == CHAN_EXTENDED_WRITE &&
793 buffer_len(&c->extended) > 0) 822 buffer_len(&c->extended) > 0)
794 FD_SET(c->efd, writeset); 823 FD_SET(c->efd, writeset);
@@ -1181,7 +1210,7 @@ static void
1181channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) 1210channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1182{ 1211{
1183 Channel *nc; 1212 Channel *nc;
1184 struct sockaddr addr; 1213 struct sockaddr_storage addr;
1185 int newsock; 1214 int newsock;
1186 socklen_t addrlen; 1215 socklen_t addrlen;
1187 char buf[16384], *remote_ipaddr; 1216 char buf[16384], *remote_ipaddr;
@@ -1190,7 +1219,7 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1190 if (FD_ISSET(c->sock, readset)) { 1219 if (FD_ISSET(c->sock, readset)) {
1191 debug("X11 connection requested."); 1220 debug("X11 connection requested.");
1192 addrlen = sizeof(addr); 1221 addrlen = sizeof(addr);
1193 newsock = accept(c->sock, &addr, &addrlen); 1222 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1194 if (c->single_connection) { 1223 if (c->single_connection) {
1195 debug2("single_connection: closing X11 listener."); 1224 debug2("single_connection: closing X11 listener.");
1196 channel_close_fd(&c->sock); 1225 channel_close_fd(&c->sock);
@@ -1307,7 +1336,7 @@ static void
1307channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) 1336channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1308{ 1337{
1309 Channel *nc; 1338 Channel *nc;
1310 struct sockaddr addr; 1339 struct sockaddr_storage addr;
1311 int newsock, nextstate; 1340 int newsock, nextstate;
1312 socklen_t addrlen; 1341 socklen_t addrlen;
1313 char *rtype; 1342 char *rtype;
@@ -1331,7 +1360,7 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1331 } 1360 }
1332 1361
1333 addrlen = sizeof(addr); 1362 addrlen = sizeof(addr);
1334 newsock = accept(c->sock, &addr, &addrlen); 1363 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1335 if (newsock < 0) { 1364 if (newsock < 0) {
1336 error("accept: %.100s", strerror(errno)); 1365 error("accept: %.100s", strerror(errno));
1337 return; 1366 return;
@@ -1366,12 +1395,12 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
1366{ 1395{
1367 Channel *nc; 1396 Channel *nc;
1368 int newsock; 1397 int newsock;
1369 struct sockaddr addr; 1398 struct sockaddr_storage addr;
1370 socklen_t addrlen; 1399 socklen_t addrlen;
1371 1400
1372 if (FD_ISSET(c->sock, readset)) { 1401 if (FD_ISSET(c->sock, readset)) {
1373 addrlen = sizeof(addr); 1402 addrlen = sizeof(addr);
1374 newsock = accept(c->sock, &addr, &addrlen); 1403 newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1375 if (newsock < 0) { 1404 if (newsock < 0) {
1376 error("accept from auth socket: %.100s", strerror(errno)); 1405 error("accept from auth socket: %.100s", strerror(errno));
1377 return; 1406 return;
@@ -1398,7 +1427,7 @@ channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset)
1398static void 1427static void
1399channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) 1428channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1400{ 1429{
1401 int err = 0; 1430 int err = 0, sock;
1402 socklen_t sz = sizeof(err); 1431 socklen_t sz = sizeof(err);
1403 1432
1404 if (FD_ISSET(c->sock, writeset)) { 1433 if (FD_ISSET(c->sock, writeset)) {
@@ -1407,7 +1436,9 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1407 error("getsockopt SO_ERROR failed"); 1436 error("getsockopt SO_ERROR failed");
1408 } 1437 }
1409 if (err == 0) { 1438 if (err == 0) {
1410 debug("channel %d: connected", c->self); 1439 debug("channel %d: connected to %s port %d",
1440 c->self, c->connect_ctx.host, c->connect_ctx.port);
1441 channel_connect_ctx_free(&c->connect_ctx);
1411 c->type = SSH_CHANNEL_OPEN; 1442 c->type = SSH_CHANNEL_OPEN;
1412 if (compat20) { 1443 if (compat20) {
1413 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); 1444 packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
@@ -1421,8 +1452,19 @@ channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1421 packet_put_int(c->self); 1452 packet_put_int(c->self);
1422 } 1453 }
1423 } else { 1454 } else {
1424 debug("channel %d: not connected: %s", 1455 debug("channel %d: connection failed: %s",
1425 c->self, strerror(err)); 1456 c->self, strerror(err));
1457 /* Try next address, if any */
1458 if ((sock = connect_next(&c->connect_ctx)) > 0) {
1459 close(c->sock);
1460 c->sock = c->rfd = c->wfd = sock;
1461 channel_max_fd = channel_find_maxfd();
1462 return;
1463 }
1464 /* Exhausted all addresses */
1465 error("connect_to %.100s port %d: failed.",
1466 c->connect_ctx.host, c->connect_ctx.port);
1467 channel_connect_ctx_free(&c->connect_ctx);
1426 if (compat20) { 1468 if (compat20) {
1427 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); 1469 packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1428 packet_put_int(c->remote_id); 1470 packet_put_int(c->remote_id);
@@ -1452,7 +1494,8 @@ channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
1452 if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) { 1494 if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
1453 errno = 0; 1495 errno = 0;
1454 len = read(c->rfd, buf, sizeof(buf)); 1496 len = read(c->rfd, buf, sizeof(buf));
1455 if (len < 0 && (errno == EINTR || (errno == EAGAIN && !force))) 1497 if (len < 0 && (errno == EINTR ||
1498 ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
1456 return 1; 1499 return 1;
1457#ifndef PTY_ZEROREAD 1500#ifndef PTY_ZEROREAD
1458 if (len <= 0) { 1501 if (len <= 0) {
@@ -1523,7 +1566,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1523 c->local_consumed += dlen + 4; 1566 c->local_consumed += dlen + 4;
1524 len = write(c->wfd, buf, dlen); 1567 len = write(c->wfd, buf, dlen);
1525 xfree(data); 1568 xfree(data);
1526 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1569 if (len < 0 && (errno == EINTR || errno == EAGAIN ||
1570 errno == EWOULDBLOCK))
1527 return 1; 1571 return 1;
1528 if (len <= 0) { 1572 if (len <= 0) {
1529 if (c->type != SSH_CHANNEL_OPEN) 1573 if (c->type != SSH_CHANNEL_OPEN)
@@ -1541,7 +1585,8 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
1541#endif 1585#endif
1542 1586
1543 len = write(c->wfd, buf, dlen); 1587 len = write(c->wfd, buf, dlen);
1544 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1588 if (len < 0 &&
1589 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1545 return 1; 1590 return 1;
1546 if (len <= 0) { 1591 if (len <= 0) {
1547 if (c->type != SSH_CHANNEL_OPEN) { 1592 if (c->type != SSH_CHANNEL_OPEN) {
@@ -1593,7 +1638,8 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
1593 buffer_len(&c->extended)); 1638 buffer_len(&c->extended));
1594 debug2("channel %d: written %d to efd %d", 1639 debug2("channel %d: written %d to efd %d",
1595 c->self, len, c->efd); 1640 c->self, len, c->efd);
1596 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1641 if (len < 0 && (errno == EINTR || errno == EAGAIN ||
1642 errno == EWOULDBLOCK))
1597 return 1; 1643 return 1;
1598 if (len <= 0) { 1644 if (len <= 0) {
1599 debug2("channel %d: closing write-efd %d", 1645 debug2("channel %d: closing write-efd %d",
@@ -1608,8 +1654,8 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
1608 len = read(c->efd, buf, sizeof(buf)); 1654 len = read(c->efd, buf, sizeof(buf));
1609 debug2("channel %d: read %d from efd %d", 1655 debug2("channel %d: read %d from efd %d",
1610 c->self, len, c->efd); 1656 c->self, len, c->efd);
1611 if (len < 0 && (errno == EINTR || 1657 if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
1612 (errno == EAGAIN && !c->detach_close))) 1658 errno == EWOULDBLOCK) && !c->detach_close)))
1613 return 1; 1659 return 1;
1614 if (len <= 0) { 1660 if (len <= 0) {
1615 debug2("channel %d: closing read-efd %d", 1661 debug2("channel %d: closing read-efd %d",
@@ -1633,7 +1679,8 @@ channel_handle_ctl(Channel *c, fd_set *readset, fd_set *writeset)
1633 /* Monitor control fd to detect if the slave client exits */ 1679 /* Monitor control fd to detect if the slave client exits */
1634 if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) { 1680 if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
1635 len = read(c->ctl_fd, buf, sizeof(buf)); 1681 len = read(c->ctl_fd, buf, sizeof(buf));
1636 if (len < 0 && (errno == EINTR || errno == EAGAIN)) 1682 if (len < 0 &&
1683 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1637 return 1; 1684 return 1;
1638 if (len <= 0) { 1685 if (len <= 0) {
1639 debug2("channel %d: ctl read<=0", c->self); 1686 debug2("channel %d: ctl read<=0", c->self);
@@ -2012,7 +2059,7 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2012 return; 2059 return;
2013 2060
2014 /* Get the data. */ 2061 /* Get the data. */
2015 data = packet_get_string(&data_len); 2062 data = packet_get_string_ptr(&data_len);
2016 2063
2017 /* 2064 /*
2018 * Ignore data for protocol > 1.3 if output end is no longer open. 2065 * Ignore data for protocol > 1.3 if output end is no longer open.
@@ -2026,7 +2073,6 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2026 c->local_window -= data_len; 2073 c->local_window -= data_len;
2027 c->local_consumed += data_len; 2074 c->local_consumed += data_len;
2028 } 2075 }
2029 xfree(data);
2030 return; 2076 return;
2031 } 2077 }
2032 2078
@@ -2038,17 +2084,15 @@ channel_input_data(int type, u_int32_t seq, void *ctxt)
2038 if (data_len > c->local_window) { 2084 if (data_len > c->local_window) {
2039 logit("channel %d: rcvd too much data %d, win %d", 2085 logit("channel %d: rcvd too much data %d, win %d",
2040 c->self, data_len, c->local_window); 2086 c->self, data_len, c->local_window);
2041 xfree(data);
2042 return; 2087 return;
2043 } 2088 }
2044 c->local_window -= data_len; 2089 c->local_window -= data_len;
2045 } 2090 }
2046 packet_check_eom();
2047 if (c->datagram) 2091 if (c->datagram)
2048 buffer_put_string(&c->output, data, data_len); 2092 buffer_put_string(&c->output, data, data_len);
2049 else 2093 else
2050 buffer_append(&c->output, data, data_len); 2094 buffer_append(&c->output, data, data_len);
2051 xfree(data); 2095 packet_check_eom();
2052} 2096}
2053 2097
2054/* ARGSUSED */ 2098/* ARGSUSED */
@@ -2212,9 +2256,9 @@ channel_input_open_confirmation(int type, u_int32_t seq, void *ctxt)
2212 if (compat20) { 2256 if (compat20) {
2213 c->remote_window = packet_get_int(); 2257 c->remote_window = packet_get_int();
2214 c->remote_maxpacket = packet_get_int(); 2258 c->remote_maxpacket = packet_get_int();
2215 if (c->confirm) { 2259 if (c->open_confirm) {
2216 debug2("callback start"); 2260 debug2("callback start");
2217 c->confirm(c->self, c->confirm_ctx); 2261 c->open_confirm(c->self, c->open_confirm_ctx);
2218 debug2("callback done"); 2262 debug2("callback done");
2219 } 2263 }
2220 debug2("channel %d: open confirm rwindow %u rmax %u", c->self, 2264 debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
@@ -2303,7 +2347,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2303 Channel *c = NULL; 2347 Channel *c = NULL;
2304 u_short host_port; 2348 u_short host_port;
2305 char *host, *originator_string; 2349 char *host, *originator_string;
2306 int remote_id, sock = -1; 2350 int remote_id;
2307 2351
2308 remote_id = packet_get_int(); 2352 remote_id = packet_get_int();
2309 host = packet_get_string(NULL); 2353 host = packet_get_string(NULL);
@@ -2315,22 +2359,46 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2315 originator_string = xstrdup("unknown (remote did not supply name)"); 2359 originator_string = xstrdup("unknown (remote did not supply name)");
2316 } 2360 }
2317 packet_check_eom(); 2361 packet_check_eom();
2318 sock = channel_connect_to(host, host_port); 2362 c = channel_connect_to(host, host_port,
2319 if (sock != -1) { 2363 "connected socket", originator_string);
2320 c = channel_new("connected socket",
2321 SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
2322 originator_string, 1);
2323 c->remote_id = remote_id;
2324 }
2325 xfree(originator_string); 2364 xfree(originator_string);
2365 xfree(host);
2326 if (c == NULL) { 2366 if (c == NULL) {
2327 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); 2367 packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
2328 packet_put_int(remote_id); 2368 packet_put_int(remote_id);
2329 packet_send(); 2369 packet_send();
2330 } 2370 } else
2331 xfree(host); 2371 c->remote_id = remote_id;
2332} 2372}
2333 2373
2374/* ARGSUSED */
2375void
2376channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
2377{
2378 Channel *c;
2379 struct channel_confirm *cc;
2380 int remote_id;
2381
2382 /* Reset keepalive timeout */
2383 keep_alive_timeouts = 0;
2384
2385 remote_id = packet_get_int();
2386 packet_check_eom();
2387
2388 debug2("channel_input_confirm: type %d id %d", type, remote_id);
2389
2390 if ((c = channel_lookup(remote_id)) == NULL) {
2391 logit("channel_input_success_failure: %d: unknown", remote_id);
2392 return;
2393 }
2394 ;
2395 if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
2396 return;
2397 cc->cb(type, c, cc->ctx);
2398 TAILQ_REMOVE(&c->status_confirms, cc, entry);
2399 bzero(cc, sizeof(*cc));
2400 xfree(cc);
2401}
2334 2402
2335/* -- tcp forwarding */ 2403/* -- tcp forwarding */
2336 2404
@@ -2385,7 +2453,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2385 wildcard = 1; 2453 wildcard = 1;
2386 } else if (gateway_ports || is_client) { 2454 } else if (gateway_ports || is_client) {
2387 if (((datafellows & SSH_OLD_FORWARD_ADDR) && 2455 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2388 strcmp(listen_addr, "0.0.0.0") == 0) || 2456 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2389 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || 2457 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2390 (!is_client && gateway_ports == 1)) 2458 (!is_client && gateway_ports == 1))
2391 wildcard = 1; 2459 wildcard = 1;
@@ -2409,10 +2477,11 @@ channel_setup_fwd_listener(int type, const char *listen_addr, u_short listen_por
2409 if (addr == NULL) { 2477 if (addr == NULL) {
2410 /* This really shouldn't happen */ 2478 /* This really shouldn't happen */
2411 packet_disconnect("getaddrinfo: fatal error: %s", 2479 packet_disconnect("getaddrinfo: fatal error: %s",
2412 gai_strerror(r)); 2480 ssh_gai_strerror(r));
2413 } else { 2481 } else {
2414 error("channel_setup_fwd_listener: " 2482 error("channel_setup_fwd_listener: "
2415 "getaddrinfo(%.64s): %s", addr, gai_strerror(r)); 2483 "getaddrinfo(%.64s): %s", addr,
2484 ssh_gai_strerror(r));
2416 } 2485 }
2417 return 0; 2486 return 0;
2418 } 2487 }
@@ -2717,35 +2786,37 @@ channel_clear_adm_permitted_opens(void)
2717 num_adm_permitted_opens = 0; 2786 num_adm_permitted_opens = 0;
2718} 2787}
2719 2788
2720/* return socket to remote host, port */ 2789void
2790channel_print_adm_permitted_opens(void)
2791{
2792 int i;
2793
2794 for (i = 0; i < num_adm_permitted_opens; i++)
2795 if (permitted_adm_opens[i].host_to_connect != NULL)
2796 printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
2797 permitted_adm_opens[i].port_to_connect);
2798}
2799
2800/* Try to start non-blocking connect to next host in cctx list */
2721static int 2801static int
2722connect_to(const char *host, u_short port) 2802connect_next(struct channel_connect *cctx)
2723{ 2803{
2724 struct addrinfo hints, *ai, *aitop; 2804 int sock, saved_errno;
2725 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 2805 char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2726 int gaierr;
2727 int sock = -1;
2728 2806
2729 memset(&hints, 0, sizeof(hints)); 2807 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
2730 hints.ai_family = IPv4or6; 2808 if (cctx->ai->ai_family != AF_INET &&
2731 hints.ai_socktype = SOCK_STREAM; 2809 cctx->ai->ai_family != AF_INET6)
2732 snprintf(strport, sizeof strport, "%d", port);
2733 if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
2734 error("connect_to %.100s: unknown host (%s)", host,
2735 gai_strerror(gaierr));
2736 return -1;
2737 }
2738 for (ai = aitop; ai; ai = ai->ai_next) {
2739 if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
2740 continue; 2810 continue;
2741 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 2811 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
2742 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 2812 ntop, sizeof(ntop), strport, sizeof(strport),
2743 error("connect_to: getnameinfo failed"); 2813 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2814 error("connect_next: getnameinfo failed");
2744 continue; 2815 continue;
2745 } 2816 }
2746 sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); 2817 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
2747 if (sock < 0) { 2818 cctx->ai->ai_protocol)) == -1) {
2748 if (ai->ai_next == NULL) 2819 if (cctx->ai->ai_next == NULL)
2749 error("socket: %.100s", strerror(errno)); 2820 error("socket: %.100s", strerror(errno));
2750 else 2821 else
2751 verbose("socket: %.100s", strerror(errno)); 2822 verbose("socket: %.100s", strerror(errno));
@@ -2753,45 +2824,95 @@ connect_to(const char *host, u_short port)
2753 } 2824 }
2754 if (set_nonblock(sock) == -1) 2825 if (set_nonblock(sock) == -1)
2755 fatal("%s: set_nonblock(%d)", __func__, sock); 2826 fatal("%s: set_nonblock(%d)", __func__, sock);
2756 if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && 2827 if (connect(sock, cctx->ai->ai_addr,
2757 errno != EINPROGRESS) { 2828 cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
2758 error("connect_to %.100s port %s: %.100s", ntop, strport, 2829 debug("connect_next: host %.100s ([%.100s]:%s): "
2830 "%.100s", cctx->host, ntop, strport,
2759 strerror(errno)); 2831 strerror(errno));
2832 saved_errno = errno;
2760 close(sock); 2833 close(sock);
2834 errno = saved_errno;
2761 continue; /* fail -- try next */ 2835 continue; /* fail -- try next */
2762 } 2836 }
2763 break; /* success */ 2837 debug("connect_next: host %.100s ([%.100s]:%s) "
2838 "in progress, fd=%d", cctx->host, ntop, strport, sock);
2839 cctx->ai = cctx->ai->ai_next;
2840 set_nodelay(sock);
2841 return sock;
2842 }
2843 return -1;
2844}
2764 2845
2846static void
2847channel_connect_ctx_free(struct channel_connect *cctx)
2848{
2849 xfree(cctx->host);
2850 if (cctx->aitop)
2851 freeaddrinfo(cctx->aitop);
2852 bzero(cctx, sizeof(*cctx));
2853 cctx->host = NULL;
2854 cctx->ai = cctx->aitop = NULL;
2855}
2856
2857/* Return CONNECTING channel to remote host, port */
2858static Channel *
2859connect_to(const char *host, u_short port, char *ctype, char *rname)
2860{
2861 struct addrinfo hints;
2862 int gaierr;
2863 int sock = -1;
2864 char strport[NI_MAXSERV];
2865 struct channel_connect cctx;
2866 Channel *c;
2867
2868 memset(&cctx, 0, sizeof(cctx));
2869 memset(&hints, 0, sizeof(hints));
2870 hints.ai_family = IPv4or6;
2871 hints.ai_socktype = SOCK_STREAM;
2872 snprintf(strport, sizeof strport, "%d", port);
2873 if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
2874 error("connect_to %.100s: unknown host (%s)", host,
2875 ssh_gai_strerror(gaierr));
2876 return NULL;
2765 } 2877 }
2766 freeaddrinfo(aitop); 2878
2767 if (!ai) { 2879 cctx.host = xstrdup(host);
2768 error("connect_to %.100s port %d: failed.", host, port); 2880 cctx.port = port;
2769 return -1; 2881 cctx.ai = cctx.aitop;
2882
2883 if ((sock = connect_next(&cctx)) == -1) {
2884 error("connect to %.100s port %d failed: %s",
2885 host, port, strerror(errno));
2886 channel_connect_ctx_free(&cctx);
2887 return NULL;
2770 } 2888 }
2771 /* success */ 2889 c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
2772 set_nodelay(sock); 2890 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
2773 return sock; 2891 c->connect_ctx = cctx;
2892 return c;
2774} 2893}
2775 2894
2776int 2895Channel *
2777channel_connect_by_listen_address(u_short listen_port) 2896channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
2778{ 2897{
2779 int i; 2898 int i;
2780 2899
2781 for (i = 0; i < num_permitted_opens; i++) 2900 for (i = 0; i < num_permitted_opens; i++) {
2782 if (permitted_opens[i].host_to_connect != NULL && 2901 if (permitted_opens[i].host_to_connect != NULL &&
2783 permitted_opens[i].listen_port == listen_port) 2902 permitted_opens[i].listen_port == listen_port) {
2784 return connect_to( 2903 return connect_to(
2785 permitted_opens[i].host_to_connect, 2904 permitted_opens[i].host_to_connect,
2786 permitted_opens[i].port_to_connect); 2905 permitted_opens[i].port_to_connect, ctype, rname);
2906 }
2907 }
2787 error("WARNING: Server requests forwarding for unknown listen_port %d", 2908 error("WARNING: Server requests forwarding for unknown listen_port %d",
2788 listen_port); 2909 listen_port);
2789 return -1; 2910 return NULL;
2790} 2911}
2791 2912
2792/* Check if connecting to that port is permitted and connect. */ 2913/* Check if connecting to that port is permitted and connect. */
2793int 2914Channel *
2794channel_connect_to(const char *host, u_short port) 2915channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
2795{ 2916{
2796 int i, permit, permit_adm = 1; 2917 int i, permit, permit_adm = 1;
2797 2918
@@ -2817,9 +2938,9 @@ channel_connect_to(const char *host, u_short port)
2817 if (!permit || !permit_adm) { 2938 if (!permit || !permit_adm) {
2818 logit("Received request to connect to host %.100s port %d, " 2939 logit("Received request to connect to host %.100s port %d, "
2819 "but the request was denied.", host, port); 2940 "but the request was denied.", host, port);
2820 return -1; 2941 return NULL;
2821 } 2942 }
2822 return connect_to(host, port); 2943 return connect_to(host, port, ctype, rname);
2823} 2944}
2824 2945
2825void 2946void
@@ -2874,7 +2995,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
2874 hints.ai_socktype = SOCK_STREAM; 2995 hints.ai_socktype = SOCK_STREAM;
2875 snprintf(strport, sizeof strport, "%d", port); 2996 snprintf(strport, sizeof strport, "%d", port);
2876 if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { 2997 if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
2877 error("getaddrinfo: %.100s", gai_strerror(gaierr)); 2998 error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
2878 return -1; 2999 return -1;
2879 } 3000 }
2880 for (ai = aitop; ai; ai = ai->ai_next) { 3001 for (ai = aitop; ai; ai = ai->ai_next) {
@@ -2904,7 +3025,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
2904 error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno)); 3025 error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
2905 } 3026 }
2906#endif 3027#endif
2907 channel_set_reuseaddr(sock); 3028 if (x11_use_localhost)
3029 channel_set_reuseaddr(sock);
2908 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { 3030 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
2909 debug2("bind port %d: %.100s", port, strerror(errno)); 3031 debug2("bind port %d: %.100s", port, strerror(errno));
2910 close(sock); 3032 close(sock);
@@ -2916,17 +3038,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
2916 break; 3038 break;
2917 } 3039 }
2918 socks[num_socks++] = sock; 3040 socks[num_socks++] = sock;
2919#ifndef DONT_TRY_OTHER_AF
2920 if (num_socks == NUM_SOCKS) 3041 if (num_socks == NUM_SOCKS)
2921 break; 3042 break;
2922#else
2923 if (x11_use_localhost) {
2924 if (num_socks == NUM_SOCKS)
2925 break;
2926 } else {
2927 break;
2928 }
2929#endif
2930 } 3043 }
2931 freeaddrinfo(aitop); 3044 freeaddrinfo(aitop);
2932 if (num_socks > 0) 3045 if (num_socks > 0)
@@ -3048,7 +3161,8 @@ x11_connect_display(void)
3048 hints.ai_socktype = SOCK_STREAM; 3161 hints.ai_socktype = SOCK_STREAM;
3049 snprintf(strport, sizeof strport, "%u", 6000 + display_number); 3162 snprintf(strport, sizeof strport, "%u", 6000 + display_number);
3050 if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { 3163 if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
3051 error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr)); 3164 error("%.100s: unknown host. (%s)", buf,
3165 ssh_gai_strerror(gaierr));
3052 return -1; 3166 return -1;
3053 } 3167 }
3054 for (ai = aitop; ai; ai = ai->ai_next) { 3168 for (ai = aitop; ai; ai = ai->ai_next) {