*/
#include "includes.h"
-RCSID("$OpenBSD: channels.c,v 1.175 2002/06/10 22:28:41 markus Exp $");
+RCSID("$OpenBSD: channels.c,v 1.187 2003/03/05 22:33:43 markus Exp $");
#include "ssh.h"
#include "ssh1.h"
} else {
c->isatty = 0;
}
+ c->wfd_isatty = isatty(c->wfd);
/* enable nonblocking mode */
if (nonblock) {
Channel *
channel_new(char *ctype, int type, int rfd, int wfd, int efd,
- int window, int maxpack, int extusage, char *remote_name, int nonblock)
+ u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock)
{
int i, found;
Channel *c;
/* There are no free slots. Take last+1 slot and expand the array. */
found = channels_alloc;
channels_alloc += 10;
+ if (channels_alloc > 10000)
+ fatal("channel_new: internal error: channels_alloc %d "
+ "too big.", channels_alloc);
debug2("channel: expanding %d", channels_alloc);
channels = xrealloc(channels, channels_alloc * sizeof(Channel *));
for (i = found; i < channels_alloc; i++)
#if 0
if (!compat20 &&
buffer_len(&c->input) > packet_get_maxsize()) {
- debug("channel %d: big input buffer %d",
+ debug2("channel %d: big input buffer %d",
c->self, buffer_len(&c->input));
return 0;
}
#endif
if (buffer_len(&c->output) > packet_get_maxsize()) {
- debug("channel %d: big output buffer %d > %d",
+ debug2("channel %d: big output buffer %d > %d",
c->self, buffer_len(&c->output),
packet_get_maxsize());
return 0;
channel_send_open(int id)
{
Channel *c = channel_lookup(id);
+
if (c == NULL) {
log("channel_send_open: %d: bad id", id);
return;
}
- debug("send channel open %d", id);
+ debug2("channel %d: send open", id);
packet_start(SSH2_MSG_CHANNEL_OPEN);
packet_put_cstring(c->ctype);
packet_put_int(c->self);
}
void
-channel_request_start(int local_id, char *service, int wantconfirm)
+channel_request_start(int id, char *service, int wantconfirm)
{
- Channel *c = channel_lookup(local_id);
+ Channel *c = channel_lookup(id);
+
if (c == NULL) {
- log("channel_request_start: %d: unknown channel id", local_id);
+ log("channel_request_start: %d: unknown channel id", id);
return;
}
- debug("channel request %d: %s", local_id, service) ;
+ debug("channel %d: request %s", id, service) ;
packet_start(SSH2_MSG_CHANNEL_REQUEST);
packet_put_int(c->remote_id);
packet_put_cstring(service);
channel_register_confirm(int id, channel_callback_fn *fn)
{
Channel *c = channel_lookup(id);
+
if (c == NULL) {
log("channel_register_comfirm: %d: bad id", id);
return;
channel_register_cleanup(int id, channel_callback_fn *fn)
{
Channel *c = channel_lookup(id);
+
if (c == NULL) {
log("channel_register_cleanup: %d: bad id", id);
return;
channel_cancel_cleanup(int id)
{
Channel *c = channel_lookup(id);
+
if (c == NULL) {
log("channel_cancel_cleanup: %d: bad id", id);
return;
channel_register_filter(int id, channel_filter_fn *fn)
{
Channel *c = channel_lookup(id);
+
if (c == NULL) {
log("channel_register_filter: %d: bad id", id);
return;
int extusage, int nonblock, u_int window_max)
{
Channel *c = channel_lookup(id);
+
if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
fatal("channel_activate for non-larval channel %d.", id);
channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
channel_pre_x11_open_13(Channel *c, fd_set * readset, fd_set * writeset)
{
int ret = x11_open_helper(&c->output);
+
if (ret == 1) {
/* Start normal processing for the channel. */
c->type = SSH_CHANNEL_OPEN;
static int
channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
{
- u_char *p, *host;
+ char *p, *host;
int len, have, i, found;
char username[256];
struct {
buffer_len(&c->output) > 0) {
data = buffer_ptr(&c->output);
dlen = buffer_len(&c->output);
+#ifdef _AIX
+ /* XXX: Later AIX versions can't push as much data to tty */
+ if (compat20 && c->wfd_isatty && dlen > 8*1024)
+ dlen = 8*1024;
+#endif
len = write(c->wfd, data, dlen);
if (len < 0 && (errno == EINTR || errno == EAGAIN))
return 1;
channel_post_output_drain_13(Channel *c, fd_set * readset, fd_set * writeset)
{
int len;
+
/* Send buffered output data to the socket. */
if (FD_ISSET(c->sock, writeset) && buffer_len(&c->output) > 0) {
len = write(c->sock, buffer_ptr(&c->output),
channel_handler_init(void)
{
int i;
+
for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) {
channel_pre[i] = NULL;
channel_post[i] = NULL;
void
channel_output_poll(void)
{
- int len, i;
Channel *c;
+ int i;
+ u_int len;
for (i = 0; i < channels_alloc; i++) {
c = channels[i];
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",
+ debug2("channel %d: rwin %u elen %u euse %d",
c->self, c->remote_window, buffer_len(&c->extended),
c->extended_usage);
if (len > c->remote_window)
channel_input_extended_data(int type, u_int32_t seq, void *ctxt)
{
int id;
- int tcode;
char *data;
- u_int data_len;
+ u_int data_len, tcode;
Channel *c;
/* Get the channel number and verify it. */
c->confirm(c->self, NULL);
debug2("callback done");
}
- debug("channel %d: open confirm rwindow %d rmax %d", c->self,
+ debug("channel %d: open confirm rwindow %u rmax %u", c->self,
c->remote_window, c->remote_maxpacket);
}
packet_check_eom();
channel_input_window_adjust(int type, u_int32_t seq, void *ctxt)
{
Channel *c;
- int id, adjust;
+ int id;
+ u_int adjust;
if (!compat20)
return;
}
adjust = packet_get_int();
packet_check_eom();
- debug2("channel %d: rcvd adjust %d", id, adjust);
+ debug2("channel %d: rcvd adjust %u", id, adjust);
c->remote_window += adjust;
}
c->remote_id = remote_id;
}
if (c == NULL) {
+ xfree(originator_string);
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(remote_id);
packet_send();
struct addrinfo hints, *ai, *aitop;
const char *host;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
- struct linger linger;
success = 0;
host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
continue;
}
/*
- * Set socket options. We would like the socket to disappear
- * as soon as it has been closed for whatever reason.
+ * Set socket options.
+ * Allow local port reuse in TIME_WAIT.
*/
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
- linger.l_onoff = 1;
- linger.l_linger = 5;
- setsockopt(sock, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on,
+ sizeof(on)) == -1)
+ error("setsockopt SO_REUSEADDR: %s", strerror(errno));
+
debug("Local forwarding listening on %s port %s.", ntop, strport);
/* Bind the socket to the address. */
}
sock = socket(ai->ai_family, SOCK_STREAM, 0);
if (sock < 0) {
- error("socket: %.100s", strerror(errno));
+ if (ai->ai_next == NULL)
+ error("socket: %.100s", strerror(errno));
+ else
+ verbose("socket: %.100s", strerror(errno));
continue;
}
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0)
/*
* Creates an internet domain socket for listening for X11 connections.
- * Returns a suitable display number for the DISPLAY variable, or -1 if
- * an error occurs.
+ * Returns 0 and a suitable display number for the DISPLAY variable
+ * stored in display_numberp , or -1 if an error occurs.
*/
int
x11_create_display_inet(int x11_display_offset, int x11_use_localhost,
- int single_connection)
+ int single_connection, u_int *display_numberp)
{
Channel *nc = NULL;
int display_number, sock;
}
/* Return the display number for the DISPLAY environment variable. */
- return display_number;
+ *display_numberp = display_number;
+ return (0);
}
static int
/* Send refusal to the remote host. */
packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
packet_put_int(remote_id);
+ xfree(remote_host);
} else {
/* Send a confirmation to the remote host. */
packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION);
deny_input_open(int type, u_int32_t seq, void *ctxt)
{
int rchan = packet_get_int();
+
switch (type) {
case SSH_SMSG_AGENT_OPEN:
error("Warning: ssh server tried agent forwarding.");