*/
#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.92 2001/02/16 13:38:18 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.98 2001/03/04 17:42:28 millert Exp $");
#include <openssl/rsa.h>
#include <openssl/dsa.h>
/* XXX ugly hack: nonblock is only set by the server */
if (nonblock && isatty(c->rfd)) {
- debug("channel: %d: rfd %d isatty", c->self, c->rfd);
+ debug("channel %d: rfd %d isatty", c->self, c->rfd);
c->isatty = 1;
if (!isatty(c->wfd)) {
- error("channel: %d: wfd %d is not a tty?",
+ error("channel %d: wfd %d is not a tty?",
c->self, c->wfd);
}
} else {
* We have received an X11 connection that has bad
* authentication information.
*/
- log("X11 connection rejected because of wrong authentication.\r\n");
+ log("X11 connection rejected because of wrong authentication.");
buffer_clear(&c->input);
buffer_clear(&c->output);
close(c->sock);
int
channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset)
{
+ struct termios tio;
int len;
/* Send buffered output data to the socket. */
return -1;
}
if (compat20 && c->isatty) {
- struct termios tio;
if (tcgetattr(c->wfd, &tio) == 0 &&
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {
/*
* Simulate echo to reduce the impact of
- * traffic analysis.
+ * traffic analysis. We need to match the
+ * size of a SSH2_MSG_CHANNEL_DATA message
+ * (4 byte channel id + data)
*/
- packet_start(SSH2_MSG_IGNORE);
- memset(buffer_ptr(&c->output), 0, len);
- packet_put_string(buffer_ptr(&c->output), len);
+ packet_send_ignore(4 + len);
packet_send();
}
}
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;
}
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 &&
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
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);
+ }
}
}
} 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))) {
- debug("channel: %d: no data after CLOSE", c->self);
+ /* XXX is this true? */
+ debug2("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)
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)
packet_send();
buffer_consume(&c->extended, len);
c->remote_window -= len;
+ debug2("channel %d: sent ext data %d", c->self, len);
}
}
}
debug2("callback done");
} else {
char *service = packet_get_string(NULL);
- debug("channel: %d rcvd request for %s", c->self, service);
+ debug("channel %d: rcvd request for %s", c->self, service);
debug("cb_fn %p cb_event %d", c->cb_fn , c->cb_event);
xfree(service);
}