X-Git-Url: http://andersk.mit.edu/gitweb/openssh.git/blobdiff_plain/4e1082aabd94cc3fb7dbb1c2d41daefec6807ca9..1f4dfa1815e0c2ac9e3cee45793dda64f2da1c06:/channels.c diff --git a/channels.c b/channels.c index 22e7f628..e8589d8c 100644 --- a/channels.c +++ b/channels.c @@ -1,4 +1,4 @@ -/* $OpenBSD: channels.c,v 1.296 2009/05/25 06:48:00 andreas Exp $ */ +/* $OpenBSD: channels.c,v 1.301 2010/01/11 01:39:46 dtucker Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland @@ -53,6 +53,7 @@ #include #include +#include #include #include #include @@ -228,7 +229,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 +328,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; @@ -1210,6 +1217,35 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) return 1; } +Channel * +channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect) +{ + Channel *c; + int in, out; + + debug("channel_connect_stdio_fwd %s:%d", host_to_connect, + port_to_connect); + + in = dup(STDIN_FILENO); + out = dup(STDOUT_FILENO); + if (in < 0 || out < 0) + fatal("channel_connect_stdio_fwd: dup() in/out failed"); + + c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out, + -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, + 0, "stdio-forward", /*nonblock*/0); + + c->path = xstrdup(host_to_connect); + c->host_port = port_to_connect; + c->listening_port = 0; + c->force_drain = 1; + + channel_register_fds(c, in, out, -1, 0, 1, 0); + port_open_helper(c, "direct-tcpip"); + + return c; +} + /* dynamic port forwarding */ static void channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) @@ -1219,7 +1255,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 +1458,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); - } } } @@ -1777,8 +1804,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) @@ -1910,17 +1935,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);