diff options
Diffstat (limited to 'usr.bin/ssh/channels.c')
-rw-r--r-- | usr.bin/ssh/channels.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/usr.bin/ssh/channels.c b/usr.bin/ssh/channels.c index c020390a7ac..1583946e333 100644 --- a/usr.bin/ssh/channels.c +++ b/usr.bin/ssh/channels.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.74 2000/11/30 22:54:31 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.75 2000/12/05 20:34:09 markus Exp $"); #include "ssh.h" #include "packet.h" @@ -346,6 +346,13 @@ channel_pre_listener(Channel *c, fd_set * readset, fd_set * writeset) } void +channel_pre_connecting(Channel *c, fd_set * readset, fd_set * writeset) +{ + debug3("channel %d: waiting for connection", c->self); + FD_SET(c->sock, writeset); +} + +void channel_pre_open_13(Channel *c, fd_set * readset, fd_set * writeset) { if (buffer_len(&c->input) < packet_get_maxsize()) @@ -685,6 +692,28 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) } } +void +channel_post_connecting(Channel *c, fd_set * readset, fd_set * writeset) +{ + if (FD_ISSET(c->sock, writeset)) { + int err = 0; + int sz = sizeof(err); + c->type = SSH_CHANNEL_OPEN; + if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, (char *)&err, &sz) < 0) { + debug("getsockopt SO_ERROR failed"); + } else { + if (err == 0) { + debug("channel %d: connected)", c->self); + } else { + debug("channel %d: not connected: %s", + c->self, strerror(err)); + chan_read_failed(c); + chan_write_failed(c); + } + } + } +} + int channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) { @@ -843,12 +872,14 @@ channel_handler_init_20(void) channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_2; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; + channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; } void @@ -861,12 +892,14 @@ channel_handler_init_13(void) channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; channel_pre[SSH_CHANNEL_INPUT_DRAINING] = &channel_pre_input_draining; channel_pre[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_pre_output_draining; + channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_OUTPUT_DRAINING] = &channel_post_output_drain_13; + channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; } void @@ -877,11 +910,13 @@ channel_handler_init_15(void) channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; + channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; channel_post[SSH_CHANNEL_OPEN] = &channel_post_open_1; + channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; } void @@ -1397,6 +1432,7 @@ channel_still_open() case SSH_CHANNEL_RPORT_LISTENER: case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_AUTH_SOCKET: + case SSH_CHANNEL_CONNECTING: /* XXX ??? */ continue; case SSH_CHANNEL_LARVAL: if (!compat20) @@ -1446,6 +1482,7 @@ channel_open_message() continue; case SSH_CHANNEL_LARVAL: case SSH_CHANNEL_OPENING: + case SSH_CHANNEL_CONNECTING: case SSH_CHANNEL_OPEN: case SSH_CHANNEL_X11_OPEN: case SSH_CHANNEL_INPUT_DRAINING: @@ -1696,8 +1733,11 @@ channel_connect_to(const char *host, u_short host_port) error("socket: %.100s", strerror(errno)); continue; } + if (fcntl(sock, F_SETFL, O_NDELAY) < 0) + fatal("connect_to: F_SETFL: %s", strerror(errno)); /* Connect to the host/port. */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 && + errno != EINPROGRESS) { error("connect %.100s port %s: %.100s", ntop, strport, strerror(errno)); close(sock); @@ -1783,7 +1823,9 @@ channel_input_port_open(int type, int plen, void *ctxt) sock = denied ? -1 : channel_connect_to(host, host_port); if (sock > 0) { /* Allocate a channel for this connection. */ - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string); + newch = channel_allocate(SSH_CHANNEL_CONNECTING, + sock, originator_string); +/*XXX delay answer? */ channels[newch].remote_id = remote_channel; packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); |