-/* $OpenBSD: channels.c,v 1.266 2006/08/29 10:40:18 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.272 2008/01/19 23:02:40 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
#include "authfd.h"
#include "pathnames.h"
-
/* -- channel core */
/*
u_int32_t tcpwinsz = 0;
socklen_t optsz = sizeof(tcpwinsz);
int ret = -1;
+
+ /* if we aren't on a socket return 128KB*/
if(!packet_connection_is_on_socket())
- return(131072);
+ return(128*1024);
ret = getsockopt(packet_get_connection_in(),
SOL_SOCKET, SO_RCVBUF, &tcpwinsz, &optsz);
+ /* return no more than 64MB */
if ((ret == 0) && tcpwinsz > BUFFER_MAX_LEN_HPN)
tcpwinsz = BUFFER_MAX_LEN_HPN;
debug2("tcpwinsz: %d for connection: %d", tcpwinsz,
u_int limit = compat20 ? c->remote_window : packet_get_maxsize();
/* check buffer limits */
- if (!c->tcpwinsz)
+ if ((!c->tcpwinsz) || (c->dynamic_window > 0))
c->tcpwinsz = channel_tcpwinsz();
- if (c->dynamic_window > 0)
- c->tcpwinsz = channel_tcpwinsz();
limit = MIN(limit, 2 * c->tcpwinsz);
if (have < nmethods + 2)
return 0;
/* look for method: "NO AUTHENTICATION REQUIRED" */
- for (found = 0, i = 2 ; i < nmethods + 2; i++) {
+ for (found = 0, i = 2; i < nmethods + 2; i++) {
if (p[i] == SSH_SOCKS5_NOAUTH) {
found = 1;
break;
channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset)
{
char buf[CHAN_RBUF];
- int len;
+ int len, force;
- if (c->rfd != -1 &&
- FD_ISSET(c->rfd, readset)) {
+ force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;
+ if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
errno = 0;
len = read(c->rfd, buf, sizeof(buf));
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
+ if (len < 0 && (errno == EINTR || (errno == EAGAIN && !force)))
return 1;
#ifndef PTY_ZEROREAD
if (len <= 0) {
c->local_consumed += len;
}
} else if (c->extended_usage == CHAN_EXTENDED_READ &&
- FD_ISSET(c->efd, readset)) {
+ (c->detach_close || FD_ISSET(c->efd, readset))) {
len = read(c->efd, buf, sizeof(buf));
debug2("channel %d: read %d from efd %d",
c->self, len, c->efd);
- if (len < 0 && (errno == EINTR || errno == EAGAIN))
+ if (len < 0 && (errno == EINTR ||
+ (errno == EAGAIN && !c->detach_close)))
return 1;
if (len <= 0) {
debug2("channel %d: closing read-efd %d",
{
if (c->type == SSH_CHANNEL_OPEN &&
!(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
- c->local_window < c->local_window_max/2 &&
+ ((c->local_window_max - c->local_window >
+ c->local_maxpacket*3) ||
+ c->local_window < c->local_window_max/2) &&
c->local_consumed > 0) {
u_int addition = 0;
/* adjust max window size if we are in a dynamic environment */
if (c->dynamic_window && (c->tcpwinsz > c->local_window_max)) {
- addition = c->tcpwinsz - c->local_window_max;
+ /* grow the window somewhat aggressively to maintain pressure */
+ addition = 1.5*(c->tcpwinsz - c->local_window_max);
c->local_window_max += addition;
}
packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
/* If there is data to send to the connection, enqueue some of it now. */
-void
+int
channel_output_poll(void)
{
Channel *c;
u_int i, len;
+ int packet_length = 0;
for (i = 0; i < channels_alloc; i++) {
c = channels[i];
packet_start(SSH2_MSG_CHANNEL_DATA);
packet_put_int(c->remote_id);
packet_put_string(data, dlen);
- packet_send();
+ packet_length = packet_send();
c->remote_window -= dlen + 4;
xfree(data);
}
SSH2_MSG_CHANNEL_DATA : SSH_MSG_CHANNEL_DATA);
packet_put_int(c->remote_id);
packet_put_string(buffer_ptr(&c->input), len);
- packet_send();
+ packet_length = packet_send();
buffer_consume(&c->input, len);
c->remote_window -= len;
}
packet_put_int(c->remote_id);
packet_put_int(SSH2_EXTENDED_DATA_STDERR);
packet_put_string(buffer_ptr(&c->extended), len);
- packet_send();
+ packet_length = packet_send();
buffer_consume(&c->extended, len);
c->remote_window -= len;
debug2("channel %d: sent ext data %d", c->self, len);
}
}
+ return (packet_length);
}
wildcard = 1;
} else if (gateway_ports || is_client) {
if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
- strcmp(listen_addr, "0.0.0.0") == 0) ||
+ strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
*listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
(!is_client && gateway_ports == 1))
wildcard = 1;
if (addr == NULL) {
/* This really shouldn't happen */
packet_disconnect("getaddrinfo: fatal error: %s",
- gai_strerror(r));
+ ssh_gai_strerror(r));
} else {
error("channel_setup_fwd_listener: "
- "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
+ "getaddrinfo(%.64s): %s", addr,
+ ssh_gai_strerror(r));
}
return 0;
}
/* Allocate a channel number for the socket. */
/* explicitly test for hpn disabled option. if true use smaller window size */
if (hpn_disabled)
- c = channel_new("port listener", type, sock, sock, -1,
- CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
- 0, "port listener", 1);
+ c = channel_new("port listener", type, sock, sock, -1,
+ CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
+ 0, "port listener", 1);
else
c = channel_new("port listener", type, sock, sock, -1,
hpn_buffer_size, CHAN_TCP_PACKET_DEFAULT,
/* Send the forward request to the remote side. */
if (compat20) {
const char *address_to_bind;
- if (listen_host == NULL)
- address_to_bind = "localhost";
- else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0)
- address_to_bind = "";
- else
+ if (listen_host == NULL) {
+ if (datafellows & SSH_BUG_RFWD_ADDR)
+ address_to_bind = "127.0.0.1";
+ else
+ address_to_bind = "localhost";
+ } else if (*listen_host == '\0' ||
+ strcmp(listen_host, "*") == 0) {
+ if (datafellows & SSH_BUG_RFWD_ADDR)
+ address_to_bind = "0.0.0.0";
+ else
+ address_to_bind = "";
+ } else
address_to_bind = listen_host;
packet_start(SSH2_MSG_GLOBAL_REQUEST);
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
error("connect_to %.100s: unknown host (%s)", host,
- gai_strerror(gaierr));
+ ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%d", port);
if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
- error("getaddrinfo: %.100s", gai_strerror(gaierr));
+ error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {
*chanids = xcalloc(num_socks + 1, sizeof(**chanids));
for (n = 0; n < num_socks; n++) {
sock = socks[n];
+ /* Is this really necassary? */
if (hpn_disabled)
- nc = channel_new("x11 listener",
- SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
- CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
- 0, "X11 inet listener", 1);
+ nc = channel_new("x11 listener",
+ SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
+ CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT,
+ 0, "X11 inet listener", 1);
else
nc = channel_new("x11 listener",
SSH_CHANNEL_X11_LISTENER, sock, sock, -1,
hints.ai_socktype = SOCK_STREAM;
snprintf(strport, sizeof strport, "%u", 6000 + display_number);
if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
- error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr));
+ error("%.100s: unknown host. (%s)", buf,
+ ssh_gai_strerror(gaierr));
return -1;
}
for (ai = aitop; ai; ai = ai->ai_next) {