From 7fbd455c780e96065dc2bd8d96d21f0c017c0f99 Mon Sep 17 00:00:00 2001 From: Ben Lindstrom Date: Mon, 5 Mar 2001 06:16:11 +0000 Subject: [PATCH] - markus@cvs.openbsd.org 2001/02/28 08:54:55 [channels.c nchan.c nchan.h] make sure remote stderr does not get truncated. remove closed fd's from the select mask. --- ChangeLog | 6 +++++- channels.c | 57 +++++++++++++++++++++++++++++++++++++++++------------- nchan.c | 57 +++++++++++++++++++++++++++++------------------------- nchan.h | 4 ++-- 4 files changed, 82 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 36ab623ad..a30623c4a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -68,6 +68,10 @@ - markus@cvs.openbsd.org 2001/02/28 08:45:39 [clientloop.c] fix byte counts for ssh protocol v1 + - markus@cvs.openbsd.org 2001/02/28 08:54:55 + [channels.c nchan.c nchan.h] + make sure remote stderr does not get truncated. + remove closed fd's from the select mask. 20010304 - (bal) Remove make-ssh-known-hosts.1 since it's no longer valid. @@ -4260,4 +4264,4 @@ - Wrote replacements for strlcpy and mkdtemp - Released 1.0pre1 -$Id: ChangeLog,v 1.871 2001/03/05 06:14:02 mouring Exp $ +$Id: ChangeLog,v 1.872 2001/03/05 06:16:11 mouring Exp $ diff --git a/channels.c b/channels.c index 71a345109..f10427c17 100644 --- a/channels.c +++ b/channels.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.92 2001/02/16 13:38:18 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.93 2001/02/28 08:54:55 markus Exp $"); #include #include @@ -824,7 +824,14 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) buffer_len(&c->extended)); debug2("channel %d: written %d to efd %d", c->self, len, c->efd); - if (len > 0) { + if (len < 0 && (errno == EINTR || errno == EAGAIN)) + return 1; + if (len <= 0) { + debug2("channel %d: closing write-efd %d", + c->self, c->efd); + close(c->efd); + c->efd = -1; + } else { buffer_consume(&c->extended, len); c->local_consumed += len; } @@ -833,19 +840,22 @@ channel_handle_efd(Channel *c, fd_set * readset, fd_set * writeset) len = read(c->efd, buf, sizeof(buf)); debug2("channel %d: read %d from efd %d", c->self, len, c->efd); - if (len == 0) { - debug("channel %d: closing efd %d", + if (len < 0 && (errno == EINTR || errno == EAGAIN)) + return 1; + if (len <= 0) { + debug2("channel %d: closing read-efd %d", c->self, c->efd); close(c->efd); c->efd = -1; - } else if (len > 0) + } else { buffer_append(&c->extended, buf, len); + } } } return 1; } int -channel_check_window(Channel *c, fd_set * readset, fd_set * writeset) +channel_check_window(Channel *c) { if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && c->local_window < c->local_window_max/2 && @@ -876,7 +886,8 @@ channel_post_open_2(Channel *c, fd_set * readset, fd_set * writeset) channel_handle_rfd(c, readset, writeset); channel_handle_wfd(c, readset, writeset); channel_handle_efd(c, readset, writeset); - channel_check_window(c, readset, writeset); + + channel_check_window(c); } void @@ -984,7 +995,24 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) if (ftab[c->type] == NULL) continue; (*ftab[c->type])(c, readset, writeset); - chan_delete_if_full_closed(c); + if (chan_is_dead(c)) { + /* + * we have to remove the fd's from the select mask + * before the channels are free'd and the fd's are + * closed + */ + if (c->wfd != -1) + FD_CLR(c->wfd, writeset); + if (c->rfd != -1) + FD_CLR(c->rfd, readset); + if (c->efd != -1) { + if (c->extended_usage == CHAN_EXTENDED_READ) + FD_CLR(c->efd, readset); + if (c->extended_usage == CHAN_EXTENDED_WRITE) + FD_CLR(c->efd, writeset); + } + channel_free(c->self); + } } } @@ -1037,19 +1065,18 @@ channel_output_poll() } else { if (c->type != SSH_CHANNEL_OPEN) continue; - if (c->istate != CHAN_INPUT_OPEN && - c->istate != CHAN_INPUT_WAIT_DRAIN) - continue; } if (compat20 && (c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { + /* XXX is this true? */ debug("channel: %d: no data after CLOSE", c->self); continue; } /* Get the amount of buffered data for this channel. */ - len = buffer_len(&c->input); - if (len > 0) { + if ((c->istate == CHAN_INPUT_OPEN || + c->istate == CHAN_INPUT_WAIT_DRAIN) && + (len = buffer_len(&c->input)) > 0) { /* Send some data for the other side over the secure connection. */ if (compat20) { if (len > c->remote_window) @@ -1089,6 +1116,9 @@ channel_output_poll() c->remote_window > 0 && (len = buffer_len(&c->extended)) > 0 && c->extended_usage == CHAN_EXTENDED_READ) { + debug2("channel %d: rwin %d elen %d euse %d", + c->self, c->remote_window, buffer_len(&c->extended), + c->extended_usage); if (len > c->remote_window) len = c->remote_window; if (len > c->remote_maxpacket) @@ -1100,6 +1130,7 @@ channel_output_poll() packet_send(); buffer_consume(&c->extended, len); c->remote_window -= len; + debug2("channel %d: sent ext data %d", c->self, len); } } } diff --git a/nchan.c b/nchan.c index 6c347203d..d91217e54 100644 --- a/nchan.c +++ b/nchan.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.22 2001/01/21 19:05:52 markus Exp $"); +RCSID("$OpenBSD: nchan.c,v 1.23 2001/02/28 08:54:55 markus Exp $"); #include "ssh1.h" #include "ssh2.h" @@ -54,9 +54,6 @@ static void chan_send_oclose1(Channel *c); static void chan_send_close2(Channel *c); static void chan_send_eof2(Channel *c); -/* channel cleanup */ -chan_event_fn *chan_delete_if_full_closed = NULL; - /* helper */ static void chan_shutdown_write(Channel *c); static void chan_shutdown_read(Channel *c); @@ -249,16 +246,6 @@ chan_send_oclose1(Channel *c) break; } } -static void -chan_delete_if_full_closed1(Channel *c) -{ - debug3("channel %d: chan_delete_if_full_closed1: istate %d ostate %d", - c->self, c->istate, c->ostate); - if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { - debug("channel %d: full closed", c->self); - channel_free(c->self); - } -} /* * the same for SSH2 @@ -401,24 +388,46 @@ chan_send_close2(Channel *c) c->flags |= CHAN_CLOSE_SENT; } } -static void -chan_delete_if_full_closed2(Channel *c) + +/* shared */ + +int +chan_is_dead(Channel *c) { - debug3("channel %d: chan_delete_if_full_closed2: istate %d ostate %d", - c->self, c->istate, c->ostate); - if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) { + if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) + return 0; + if (!compat20) { + debug("channel %d: is dead", c->self); + return 1; + } + /* + * we have to delay the close message if the efd (for stderr) is + * still active + */ + if (((c->extended_usage != CHAN_EXTENDED_IGNORE) && + buffer_len(&c->extended) > 0) +#if 0 + || ((c->extended_usage == CHAN_EXTENDED_READ) && + c->efd != -1) +#endif + ) { + debug2("channel %d: active efd: %d len %d type %s", + c->self, c->efd, buffer_len(&c->extended), + c->extended_usage==CHAN_EXTENDED_READ ? + "read": "write"); + } else { if (!(c->flags & CHAN_CLOSE_SENT)) { chan_send_close2(c); } if ((c->flags & CHAN_CLOSE_SENT) && (c->flags & CHAN_CLOSE_RCVD)) { - debug("channel %d: full closed2", c->self); - channel_free(c->self); + debug("channel %d: is dead", c->self); + return 1; } } + return 0; } -/* shared */ void chan_init_iostates(Channel *c) { @@ -439,8 +448,6 @@ chan_init(void) chan_rcvd_ieof = chan_rcvd_ieof2; chan_write_failed = chan_write_failed2; chan_obuf_empty = chan_obuf_empty2; - - chan_delete_if_full_closed = chan_delete_if_full_closed2; } else { chan_rcvd_oclose = chan_rcvd_oclose1; chan_read_failed = chan_read_failed_12; @@ -449,8 +456,6 @@ chan_init(void) chan_rcvd_ieof = chan_rcvd_ieof1; chan_write_failed = chan_write_failed1; chan_obuf_empty = chan_obuf_empty1; - - chan_delete_if_full_closed = chan_delete_if_full_closed1; } } diff --git a/nchan.h b/nchan.h index 366b894ae..623ecccc3 100644 --- a/nchan.h +++ b/nchan.h @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: nchan.h,v 1.9 2000/09/07 20:27:52 deraadt Exp $"); */ +/* RCSID("$OpenBSD: nchan.h,v 1.10 2001/02/28 08:54:55 markus Exp $"); */ #ifndef NCHAN_H #define NCHAN_H @@ -84,7 +84,7 @@ extern chan_event_fn *chan_rcvd_ieof; extern chan_event_fn *chan_write_failed; extern chan_event_fn *chan_obuf_empty; -extern chan_event_fn *chan_delete_if_full_closed; +int chan_is_dead(Channel * c); void chan_init_iostates(Channel * c); void chan_init(void);