summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c279
1 files changed, 214 insertions, 65 deletions
diff --git a/channels.c b/channels.c
index e8b8aa07e..d8c53a4a8 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.296 2009/05/25 06:48:00 andreas Exp $ */ 1/* $OpenBSD: channels.c,v 1.303 2010/01/30 21:12:08 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
@@ -53,6 +53,7 @@
53#include <arpa/inet.h> 53#include <arpa/inet.h>
54 54
55#include <errno.h> 55#include <errno.h>
56#include <fcntl.h>
56#include <netdb.h> 57#include <netdb.h>
57#include <stdio.h> 58#include <stdio.h>
58#include <stdlib.h> 59#include <stdlib.h>
@@ -228,12 +229,16 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
228 channel_max_fd = MAX(channel_max_fd, wfd); 229 channel_max_fd = MAX(channel_max_fd, wfd);
229 channel_max_fd = MAX(channel_max_fd, efd); 230 channel_max_fd = MAX(channel_max_fd, efd);
230 231
231 /* XXX set close-on-exec -markus */ 232 if (rfd != -1)
233 fcntl(rfd, F_SETFD, FD_CLOEXEC);
234 if (wfd != -1 && wfd != rfd)
235 fcntl(wfd, F_SETFD, FD_CLOEXEC);
236 if (efd != -1 && efd != rfd && efd != wfd)
237 fcntl(efd, F_SETFD, FD_CLOEXEC);
232 238
233 c->rfd = rfd; 239 c->rfd = rfd;
234 c->wfd = wfd; 240 c->wfd = wfd;
235 c->sock = (rfd == wfd) ? rfd : -1; 241 c->sock = (rfd == wfd) ? rfd : -1;
236 c->ctl_fd = -1; /* XXX: set elsewhere */
237 c->efd = efd; 242 c->efd = efd;
238 c->extended_usage = extusage; 243 c->extended_usage = extusage;
239 244
@@ -322,6 +327,10 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
322 c->output_filter = NULL; 327 c->output_filter = NULL;
323 c->filter_ctx = NULL; 328 c->filter_ctx = NULL;
324 c->filter_cleanup = NULL; 329 c->filter_cleanup = NULL;
330 c->ctl_chan = -1;
331 c->mux_rcb = NULL;
332 c->mux_ctx = NULL;
333 c->delayed = 1; /* prevent call to channel_post handler */
325 TAILQ_INIT(&c->status_confirms); 334 TAILQ_INIT(&c->status_confirms);
326 debug("channel %d: new [%s]", found, remote_name); 335 debug("channel %d: new [%s]", found, remote_name);
327 return c; 336 return c;
@@ -363,11 +372,10 @@ channel_close_fd(int *fdp)
363static void 372static void
364channel_close_fds(Channel *c) 373channel_close_fds(Channel *c)
365{ 374{
366 debug3("channel %d: close_fds r %d w %d e %d c %d", 375 debug3("channel %d: close_fds r %d w %d e %d",
367 c->self, c->rfd, c->wfd, c->efd, c->ctl_fd); 376 c->self, c->rfd, c->wfd, c->efd);
368 377
369 channel_close_fd(&c->sock); 378 channel_close_fd(&c->sock);
370 channel_close_fd(&c->ctl_fd);
371 channel_close_fd(&c->rfd); 379 channel_close_fd(&c->rfd);
372 channel_close_fd(&c->wfd); 380 channel_close_fd(&c->wfd);
373 channel_close_fd(&c->efd); 381 channel_close_fd(&c->efd);
@@ -393,8 +401,6 @@ channel_free(Channel *c)
393 401
394 if (c->sock != -1) 402 if (c->sock != -1)
395 shutdown(c->sock, SHUT_RDWR); 403 shutdown(c->sock, SHUT_RDWR);
396 if (c->ctl_fd != -1)
397 shutdown(c->ctl_fd, SHUT_RDWR);
398 channel_close_fds(c); 404 channel_close_fds(c);
399 buffer_free(&c->input); 405 buffer_free(&c->input);
400 buffer_free(&c->output); 406 buffer_free(&c->output);
@@ -516,6 +522,7 @@ channel_still_open(void)
516 case SSH_CHANNEL_X11_LISTENER: 522 case SSH_CHANNEL_X11_LISTENER:
517 case SSH_CHANNEL_PORT_LISTENER: 523 case SSH_CHANNEL_PORT_LISTENER:
518 case SSH_CHANNEL_RPORT_LISTENER: 524 case SSH_CHANNEL_RPORT_LISTENER:
525 case SSH_CHANNEL_MUX_LISTENER:
519 case SSH_CHANNEL_CLOSED: 526 case SSH_CHANNEL_CLOSED:
520 case SSH_CHANNEL_AUTH_SOCKET: 527 case SSH_CHANNEL_AUTH_SOCKET:
521 case SSH_CHANNEL_DYNAMIC: 528 case SSH_CHANNEL_DYNAMIC:
@@ -529,6 +536,7 @@ channel_still_open(void)
529 case SSH_CHANNEL_OPENING: 536 case SSH_CHANNEL_OPENING:
530 case SSH_CHANNEL_OPEN: 537 case SSH_CHANNEL_OPEN:
531 case SSH_CHANNEL_X11_OPEN: 538 case SSH_CHANNEL_X11_OPEN:
539 case SSH_CHANNEL_MUX_CLIENT:
532 return 1; 540 return 1;
533 case SSH_CHANNEL_INPUT_DRAINING: 541 case SSH_CHANNEL_INPUT_DRAINING:
534 case SSH_CHANNEL_OUTPUT_DRAINING: 542 case SSH_CHANNEL_OUTPUT_DRAINING:
@@ -560,6 +568,8 @@ channel_find_open(void)
560 case SSH_CHANNEL_X11_LISTENER: 568 case SSH_CHANNEL_X11_LISTENER:
561 case SSH_CHANNEL_PORT_LISTENER: 569 case SSH_CHANNEL_PORT_LISTENER:
562 case SSH_CHANNEL_RPORT_LISTENER: 570 case SSH_CHANNEL_RPORT_LISTENER:
571 case SSH_CHANNEL_MUX_LISTENER:
572 case SSH_CHANNEL_MUX_CLIENT:
563 case SSH_CHANNEL_OPENING: 573 case SSH_CHANNEL_OPENING:
564 case SSH_CHANNEL_CONNECTING: 574 case SSH_CHANNEL_CONNECTING:
565 case SSH_CHANNEL_ZOMBIE: 575 case SSH_CHANNEL_ZOMBIE:
@@ -610,6 +620,8 @@ channel_open_message(void)
610 case SSH_CHANNEL_CLOSED: 620 case SSH_CHANNEL_CLOSED:
611 case SSH_CHANNEL_AUTH_SOCKET: 621 case SSH_CHANNEL_AUTH_SOCKET:
612 case SSH_CHANNEL_ZOMBIE: 622 case SSH_CHANNEL_ZOMBIE:
623 case SSH_CHANNEL_MUX_CLIENT:
624 case SSH_CHANNEL_MUX_LISTENER:
613 continue; 625 continue;
614 case SSH_CHANNEL_LARVAL: 626 case SSH_CHANNEL_LARVAL:
615 case SSH_CHANNEL_OPENING: 627 case SSH_CHANNEL_OPENING:
@@ -620,12 +632,12 @@ channel_open_message(void)
620 case SSH_CHANNEL_INPUT_DRAINING: 632 case SSH_CHANNEL_INPUT_DRAINING:
621 case SSH_CHANNEL_OUTPUT_DRAINING: 633 case SSH_CHANNEL_OUTPUT_DRAINING:
622 snprintf(buf, sizeof buf, 634 snprintf(buf, sizeof buf,
623 " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cfd %d)\r\n", 635 " #%d %.300s (t%d r%d i%d/%d o%d/%d fd %d/%d cc %d)\r\n",
624 c->self, c->remote_name, 636 c->self, c->remote_name,
625 c->type, c->remote_id, 637 c->type, c->remote_id,
626 c->istate, buffer_len(&c->input), 638 c->istate, buffer_len(&c->input),
627 c->ostate, buffer_len(&c->output), 639 c->ostate, buffer_len(&c->output),
628 c->rfd, c->wfd, c->ctl_fd); 640 c->rfd, c->wfd, c->ctl_chan);
629 buffer_append(&buffer, buf, strlen(buf)); 641 buffer_append(&buffer, buf, strlen(buf));
630 continue; 642 continue;
631 default: 643 default:
@@ -832,9 +844,6 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset)
832 FD_SET(c->efd, readset); 844 FD_SET(c->efd, readset);
833 } 845 }
834 /* XXX: What about efd? races? */ 846 /* XXX: What about efd? races? */
835 if (compat20 && c->ctl_fd != -1 &&
836 c->istate == CHAN_INPUT_OPEN && c->ostate == CHAN_OUTPUT_OPEN)
837 FD_SET(c->ctl_fd, readset);
838} 847}
839 848
840/* ARGSUSED */ 849/* ARGSUSED */
@@ -979,6 +988,28 @@ channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset)
979 } 988 }
980} 989}
981 990
991static void
992channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
993{
994 if (c->istate == CHAN_INPUT_OPEN &&
995 buffer_check_alloc(&c->input, CHAN_RBUF))
996 FD_SET(c->rfd, readset);
997 if (c->istate == CHAN_INPUT_WAIT_DRAIN) {
998 /* clear buffer immediately (discard any partial packet) */
999 buffer_clear(&c->input);
1000 chan_ibuf_empty(c);
1001 /* Start output drain. XXX just kill chan? */
1002 chan_rcvd_oclose(c);
1003 }
1004 if (c->ostate == CHAN_OUTPUT_OPEN ||
1005 c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {
1006 if (buffer_len(&c->output) > 0)
1007 FD_SET(c->wfd, writeset);
1008 else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)
1009 chan_obuf_empty(c);
1010 }
1011}
1012
982/* try to decode a socks4 header */ 1013/* try to decode a socks4 header */
983/* ARGSUSED */ 1014/* ARGSUSED */
984static int 1015static int
@@ -1210,6 +1241,30 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset)
1210 return 1; 1241 return 1;
1211} 1242}
1212 1243
1244Channel *
1245channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect,
1246 int in, int out)
1247{
1248 Channel *c;
1249
1250 debug("channel_connect_stdio_fwd %s:%d", host_to_connect,
1251 port_to_connect);
1252
1253 c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out,
1254 -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
1255 0, "stdio-forward", /*nonblock*/0);
1256
1257 c->path = xstrdup(host_to_connect);
1258 c->host_port = port_to_connect;
1259 c->listening_port = 0;
1260 c->force_drain = 1;
1261
1262 channel_register_fds(c, in, out, -1, 0, 1, 0);
1263 port_open_helper(c, "direct-tcpip");
1264
1265 return c;
1266}
1267
1213/* dynamic port forwarding */ 1268/* dynamic port forwarding */
1214static void 1269static void
1215channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) 1270channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
@@ -1219,7 +1274,6 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
1219 int ret; 1274 int ret;
1220 1275
1221 have = buffer_len(&c->input); 1276 have = buffer_len(&c->input);
1222 c->delayed = 0;
1223 debug2("channel %d: pre_dynamic: have %d", c->self, have); 1277 debug2("channel %d: pre_dynamic: have %d", c->self, have);
1224 /* buffer_dump(&c->input); */ 1278 /* buffer_dump(&c->input); */
1225 /* check if the fixed size part of the packet is in buffer. */ 1279 /* check if the fixed size part of the packet is in buffer. */
@@ -1322,6 +1376,13 @@ port_open_helper(Channel *c, char *rtype)
1322 char *remote_ipaddr = get_peer_ipaddr(c->sock); 1376 char *remote_ipaddr = get_peer_ipaddr(c->sock);
1323 int remote_port = get_peer_port(c->sock); 1377 int remote_port = get_peer_port(c->sock);
1324 1378
1379 if (remote_port == -1) {
1380 /* Fake addr/port to appease peers that validate it (Tectia) */
1381 xfree(remote_ipaddr);
1382 remote_ipaddr = xstrdup("127.0.0.1");
1383 remote_port = 65535;
1384 }
1385
1325 direct = (strcmp(rtype, "direct-tcpip") == 0); 1386 direct = (strcmp(rtype, "direct-tcpip") == 0);
1326 1387
1327 snprintf(buf, sizeof buf, 1388 snprintf(buf, sizeof buf,
@@ -1423,16 +1484,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1423 if (c->path != NULL) 1484 if (c->path != NULL)
1424 nc->path = xstrdup(c->path); 1485 nc->path = xstrdup(c->path);
1425 1486
1426 if (nextstate == SSH_CHANNEL_DYNAMIC) { 1487 if (nextstate != SSH_CHANNEL_DYNAMIC)
1427 /*
1428 * do not call the channel_post handler until
1429 * this flag has been reset by a pre-handler.
1430 * otherwise the FD_ISSET calls might overflow
1431 */
1432 nc->delayed = 1;
1433 } else {
1434 port_open_helper(nc, rtype); 1488 port_open_helper(nc, rtype);
1435 }
1436 } 1489 }
1437} 1490}
1438 1491
@@ -1722,36 +1775,6 @@ channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset)
1722 return 1; 1775 return 1;
1723} 1776}
1724 1777
1725/* ARGSUSED */
1726static int
1727channel_handle_ctl(Channel *c, fd_set *readset, fd_set *writeset)
1728{
1729 char buf[16];
1730 int len;
1731
1732 /* Monitor control fd to detect if the slave client exits */
1733 if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
1734 len = read(c->ctl_fd, buf, sizeof(buf));
1735 if (len < 0 &&
1736 (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1737 return 1;
1738 if (len <= 0) {
1739 debug2("channel %d: ctl read<=0", c->self);
1740 if (c->type != SSH_CHANNEL_OPEN) {
1741 debug2("channel %d: not open", c->self);
1742 chan_mark_dead(c);
1743 return -1;
1744 } else {
1745 chan_read_failed(c);
1746 chan_write_failed(c);
1747 }
1748 return -1;
1749 } else
1750 fatal("%s: unexpected data on ctl fd", __func__);
1751 }
1752 return 1;
1753}
1754
1755static int 1778static int
1756channel_check_window(Channel *c) 1779channel_check_window(Channel *c)
1757{ 1780{
@@ -1777,17 +1800,136 @@ channel_check_window(Channel *c)
1777static void 1800static void
1778channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) 1801channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
1779{ 1802{
1780 if (c->delayed)
1781 return;
1782 channel_handle_rfd(c, readset, writeset); 1803 channel_handle_rfd(c, readset, writeset);
1783 channel_handle_wfd(c, readset, writeset); 1804 channel_handle_wfd(c, readset, writeset);
1784 if (!compat20) 1805 if (!compat20)
1785 return; 1806 return;
1786 channel_handle_efd(c, readset, writeset); 1807 channel_handle_efd(c, readset, writeset);
1787 channel_handle_ctl(c, readset, writeset);
1788 channel_check_window(c); 1808 channel_check_window(c);
1789} 1809}
1790 1810
1811static u_int
1812read_mux(Channel *c, u_int need)
1813{
1814 char buf[CHAN_RBUF];
1815 int len;
1816 u_int rlen;
1817
1818 if (buffer_len(&c->input) < need) {
1819 rlen = need - buffer_len(&c->input);
1820 len = read(c->rfd, buf, MIN(rlen, CHAN_RBUF));
1821 if (len <= 0) {
1822 if (errno != EINTR && errno != EAGAIN) {
1823 debug2("channel %d: ctl read<=0 rfd %d len %d",
1824 c->self, c->rfd, len);
1825 chan_read_failed(c);
1826 return 0;
1827 }
1828 } else
1829 buffer_append(&c->input, buf, len);
1830 }
1831 return buffer_len(&c->input);
1832}
1833
1834static void
1835channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset)
1836{
1837 u_int need;
1838 ssize_t len;
1839
1840 if (!compat20)
1841 fatal("%s: entered with !compat20", __func__);
1842
1843 if (c->rfd != -1 && FD_ISSET(c->rfd, readset) &&
1844 (c->istate == CHAN_INPUT_OPEN ||
1845 c->istate == CHAN_INPUT_WAIT_DRAIN)) {
1846 /*
1847 * Don't not read past the precise end of packets to
1848 * avoid disrupting fd passing.
1849 */
1850 if (read_mux(c, 4) < 4) /* read header */
1851 return;
1852 need = get_u32(buffer_ptr(&c->input));
1853#define CHANNEL_MUX_MAX_PACKET (256 * 1024)
1854 if (need > CHANNEL_MUX_MAX_PACKET) {
1855 debug2("channel %d: packet too big %u > %u",
1856 c->self, CHANNEL_MUX_MAX_PACKET, need);
1857 chan_rcvd_oclose(c);
1858 return;
1859 }
1860 if (read_mux(c, need + 4) < need + 4) /* read body */
1861 return;
1862 if (c->mux_rcb(c) != 0) {
1863 debug("channel %d: mux_rcb failed", c->self);
1864 chan_mark_dead(c);
1865 return;
1866 }
1867 }
1868
1869 if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) &&
1870 buffer_len(&c->output) > 0) {
1871 len = write(c->wfd, buffer_ptr(&c->output),
1872 buffer_len(&c->output));
1873 if (len < 0 && (errno == EINTR || errno == EAGAIN))
1874 return;
1875 if (len <= 0) {
1876 chan_mark_dead(c);
1877 return;
1878 }
1879 buffer_consume(&c->output, len);
1880 }
1881}
1882
1883static void
1884channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset)
1885{
1886 Channel *nc;
1887 struct sockaddr_storage addr;
1888 socklen_t addrlen;
1889 int newsock;
1890 uid_t euid;
1891 gid_t egid;
1892
1893 if (!FD_ISSET(c->sock, readset))
1894 return;
1895
1896 debug("multiplexing control connection");
1897
1898 /*
1899 * Accept connection on control socket
1900 */
1901 memset(&addr, 0, sizeof(addr));
1902 addrlen = sizeof(addr);
1903 if ((newsock = accept(c->sock, (struct sockaddr*)&addr,
1904 &addrlen)) == -1) {
1905 error("%s accept: %s", __func__, strerror(errno));
1906 return;
1907 }
1908
1909 if (getpeereid(newsock, &euid, &egid) < 0) {
1910 error("%s getpeereid failed: %s", __func__,
1911 strerror(errno));
1912 close(newsock);
1913 return;
1914 }
1915 if ((euid != 0) && (getuid() != euid)) {
1916 error("multiplex uid mismatch: peer euid %u != uid %u",
1917 (u_int)euid, (u_int)getuid());
1918 close(newsock);
1919 return;
1920 }
1921 nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT,
1922 newsock, newsock, -1, c->local_window_max,
1923 c->local_maxpacket, 0, "mux-control", 1);
1924 nc->mux_rcb = c->mux_rcb;
1925 debug3("%s: new mux channel %d fd %d", __func__,
1926 nc->self, nc->sock);
1927 /* establish state */
1928 nc->mux_rcb(nc);
1929 /* mux state transitions must not elicit protocol messages */
1930 nc->flags |= CHAN_LOCAL;
1931}
1932
1791/* ARGSUSED */ 1933/* ARGSUSED */
1792static void 1934static void
1793channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset) 1935channel_post_output_drain_13(Channel *c, fd_set *readset, fd_set *writeset)
@@ -1816,6 +1958,8 @@ channel_handler_init_20(void)
1816 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 1958 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
1817 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 1959 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
1818 channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; 1960 channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic;
1961 channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener;
1962 channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client;
1819 1963
1820 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; 1964 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
1821 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 1965 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
@@ -1824,6 +1968,8 @@ channel_handler_init_20(void)
1824 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 1968 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
1825 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 1969 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
1826 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; 1970 channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open;
1971 channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener;
1972 channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client;
1827} 1973}
1828 1974
1829static void 1975static void
@@ -1910,17 +2056,23 @@ static void
1910channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset) 2056channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
1911{ 2057{
1912 static int did_init = 0; 2058 static int did_init = 0;
1913 u_int i; 2059 u_int i, oalloc;
1914 Channel *c; 2060 Channel *c;
1915 2061
1916 if (!did_init) { 2062 if (!did_init) {
1917 channel_handler_init(); 2063 channel_handler_init();
1918 did_init = 1; 2064 did_init = 1;
1919 } 2065 }
1920 for (i = 0; i < channels_alloc; i++) { 2066 for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
1921 c = channels[i]; 2067 c = channels[i];
1922 if (c == NULL) 2068 if (c == NULL)
1923 continue; 2069 continue;
2070 if (c->delayed) {
2071 if (ftab == channel_pre)
2072 c->delayed = 0;
2073 else
2074 continue;
2075 }
1924 if (ftab[c->type] != NULL) 2076 if (ftab[c->type] != NULL)
1925 (*ftab[c->type])(c, readset, writeset); 2077 (*ftab[c->type])(c, readset, writeset);
1926 channel_garbage_collect(c); 2078 channel_garbage_collect(c);
@@ -2577,6 +2729,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2577 } 2729 }
2578 2730
2579 channel_set_reuseaddr(sock); 2731 channel_set_reuseaddr(sock);
2732 if (ai->ai_family == AF_INET6)
2733 sock_set_v6only(sock);
2580 2734
2581 debug("Local forwarding listening on %s port %s.", 2735 debug("Local forwarding listening on %s port %s.",
2582 ntop, strport); 2736 ntop, strport);
@@ -3108,13 +3262,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
3108 continue; 3262 continue;
3109 } 3263 }
3110 } 3264 }
3111#ifdef IPV6_V6ONLY 3265 if (ai->ai_family == AF_INET6)
3112 if (ai->ai_family == AF_INET6) { 3266 sock_set_v6only(sock);
3113 int on = 1;
3114 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
3115 error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
3116 }
3117#endif
3118 if (x11_use_localhost) 3267 if (x11_use_localhost)
3119 channel_set_reuseaddr(sock); 3268 channel_set_reuseaddr(sock);
3120 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { 3269 if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {