]> andersk Git - openssh.git/blobdiff - channels.c
- (dtucker) Wrap use of IPPROTO_IPV6 in an ifdef for platforms that don't
[openssh.git] / channels.c
index dea60ba24e7740d8ecac95ab6f6db89c8574155c..94939239022df3867337d554afc3d14a39c28af0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.295 2009/02/12 03:00:56 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.299 2009/11/11 21:37:03 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -53,6 +53,7 @@
 #include <arpa/inet.h>
 
 #include <errno.h>
+#include <fcntl.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -162,6 +163,9 @@ static u_int x11_fake_data_len;
 /* AF_UNSPEC or AF_INET or AF_INET6 */
 static int IPv4or6 = AF_UNSPEC;
 
+/* Set the routing domain a.k.a. VRF */
+static int channel_rdomain = -1;
+
 /* helper */
 static void port_open_helper(Channel *c, char *rtype);
 
@@ -228,7 +232,12 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd,
        channel_max_fd = MAX(channel_max_fd, wfd);
        channel_max_fd = MAX(channel_max_fd, efd);
 
-       /* XXX set close-on-exec -markus */
+       if (rfd != -1)
+               fcntl(rfd, F_SETFD, FD_CLOEXEC);
+       if (wfd != -1 && wfd != rfd)
+               fcntl(wfd, F_SETFD, FD_CLOEXEC);
+       if (efd != -1 && efd != rfd && efd != wfd)
+               fcntl(efd, F_SETFD, FD_CLOEXEC);
 
        c->rfd = rfd;
        c->wfd = wfd;
@@ -322,6 +331,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd,
        c->output_filter = NULL;
        c->filter_ctx = NULL;
        c->filter_cleanup = NULL;
+       c->delayed = 1;         /* prevent call to channel_post handler */
        TAILQ_INIT(&c->status_confirms);
        debug("channel %d: new [%s]", found, remote_name);
        return c;
@@ -1219,7 +1229,6 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset)
        int ret;
 
        have = buffer_len(&c->input);
-       c->delayed = 0;
        debug2("channel %d: pre_dynamic: have %d", c->self, have);
        /* buffer_dump(&c->input); */
        /* check if the fixed size part of the packet is in buffer. */
@@ -1423,16 +1432,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
                if (c->path != NULL)
                        nc->path = xstrdup(c->path);
 
-               if (nextstate == SSH_CHANNEL_DYNAMIC) {
-                       /*
-                        * do not call the channel_post handler until
-                        * this flag has been reset by a pre-handler.
-                        * otherwise the FD_ISSET calls might overflow
-                        */
-                       nc->delayed = 1;
-               } else {
+               if (nextstate != SSH_CHANNEL_DYNAMIC)
                        port_open_helper(nc, rtype);
-               }
        }
 }
 
@@ -1653,6 +1654,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
                        }
                        return -1;
                }
+#ifndef BROKEN_TCGETATTR_ICANON
                if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') {
                        if (tcgetattr(c->wfd, &tio) == 0 &&
                            !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
@@ -1666,6 +1668,7 @@ channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset)
                                packet_send();
                        }
                }
+#endif
                buffer_consume(&c->output, len);
                if (compat20 && len > 0) {
                        c->local_consumed += len;
@@ -1775,8 +1778,6 @@ channel_check_window(Channel *c)
 static void
 channel_post_open(Channel *c, fd_set *readset, fd_set *writeset)
 {
-       if (c->delayed)
-               return;
        channel_handle_rfd(c, readset, writeset);
        channel_handle_wfd(c, readset, writeset);
        if (!compat20)
@@ -1908,17 +1909,23 @@ static void
 channel_handler(chan_fn *ftab[], fd_set *readset, fd_set *writeset)
 {
        static int did_init = 0;
-       u_int i;
+       u_int i, oalloc;
        Channel *c;
 
        if (!did_init) {
                channel_handler_init();
                did_init = 1;
        }
-       for (i = 0; i < channels_alloc; i++) {
+       for (i = 0, oalloc = channels_alloc; i < oalloc; i++) {
                c = channels[i];
                if (c == NULL)
                        continue;
+               if (c->delayed) {
+                       if (ftab == channel_pre)
+                               c->delayed = 0;
+                       else
+                               continue;
+               }
                if (ftab[c->type] != NULL)
                        (*ftab[c->type])(c, readset, writeset);
                channel_garbage_collect(c);
@@ -2431,7 +2438,7 @@ channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
        int id;
 
        /* Reset keepalive timeout */
-       keep_alive_timeouts = 0;
+       packet_set_alive_timeouts(0);
 
        id = packet_get_int();
        packet_check_eom();
@@ -2459,6 +2466,12 @@ channel_set_af(int af)
        IPv4or6 = af;
 }
 
+void
+channel_set_rdomain(int rdomain)
+{
+       channel_rdomain = rdomain;
+}
+
 static int
 channel_setup_fwd_listener(int type, const char *listen_addr,
     u_short listen_port, int *allocated_listen_port,
@@ -2567,7 +2580,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
                        continue;
                }
                /* Create a port to listen for the host. */
-               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+               sock = socket_rdomain(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol, channel_rdomain);
                if (sock < 0) {
                        /* this is no error since kernel may not support ipv6 */
                        verbose("socket: %.100s", strerror(errno));
@@ -2575,6 +2589,8 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
                }
 
                channel_set_reuseaddr(sock);
+               if (ai->ai_family == AF_INET6)
+                       sock_set_v6only(sock);
 
                debug("Local forwarding listening on %s port %s.",
                    ntop, strport);
@@ -2906,8 +2922,9 @@ connect_next(struct channel_connect *cctx)
                        error("connect_next: getnameinfo failed");
                        continue;
                }
-               if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
-                   cctx->ai->ai_protocol)) == -1) {
+               if ((sock = socket_rdomain(cctx->ai->ai_family,
+                   cctx->ai->ai_socktype, cctx->ai->ai_protocol,
+                   channel_rdomain)) == -1) {
                        if (cctx->ai->ai_next == NULL)
                                error("socket: %.100s", strerror(errno));
                        else
@@ -3093,8 +3110,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
                for (ai = aitop; ai; ai = ai->ai_next) {
                        if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                                continue;
-                       sock = socket(ai->ai_family, ai->ai_socktype,
-                           ai->ai_protocol);
+                       sock = socket_rdomain(ai->ai_family, ai->ai_socktype,
+                           ai->ai_protocol, channel_rdomain);
                        if (sock < 0) {
                                if ((errno != EINVAL) && (errno != EAFNOSUPPORT)) {
                                        error("socket: %.100s", strerror(errno));
@@ -3106,13 +3123,8 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
                                        continue;
                                }
                        }
-#ifdef IPV6_V6ONLY
-                       if (ai->ai_family == AF_INET6) {
-                               int on = 1;
-                               if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0)
-                                       error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
-                       }
-#endif
+                       if (ai->ai_family == AF_INET6)
+                               sock_set_v6only(sock);
                        if (x11_use_localhost)
                                channel_set_reuseaddr(sock);
                        if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
@@ -3274,7 +3286,8 @@ x11_connect_display(void)
        }
        for (ai = aitop; ai; ai = ai->ai_next) {
                /* Create a socket. */
-               sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+               sock = socket_rdomain(ai->ai_family, ai->ai_socktype,
+                   ai->ai_protocol, channel_rdomain);
                if (sock < 0) {
                        debug2("socket: %.100s", strerror(errno));
                        continue;
This page took 0.042496 seconds and 4 git commands to generate.