From 4ed34d251770cb8dd7f13217976d1dec9452b5e6 Mon Sep 17 00:00:00 2001 From: simon Date: Tue, 30 Oct 2001 20:57:22 +0000 Subject: [PATCH] Tidy up the SERIOUS NETWORK ERROR fixes git-svn-id: svn://svn.tartarus.org/sgt/putty@1345 cda61777-01e9-0310-a592-d414129be87e --- network.h | 6 ++++++ ssh.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/network.h b/network.h index 4300fb2e..28744a6f 100644 --- a/network.h +++ b/network.h @@ -124,6 +124,12 @@ char *sk_addr_error(SockAddr addr); */ void sk_set_frozen(Socket sock, int is_frozen); +/* + * Call this after an operation that might have tried to send on a + * socket, to clean up any pending network errors. + */ +void net_pending_errors(void); + /********** SSL stuff **********/ /* diff --git a/ssh.c b/ssh.c index 67ae0d42..119cd4fe 100644 --- a/ssh.c +++ b/ssh.c @@ -2523,19 +2523,29 @@ static int do_ssh1_login(unsigned char *in, int inlen, int ispkt) void sshfwd_close(struct ssh_channel *c) { if (c && !c->closes) { - if (ssh_version == 1) { - send_packet(SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid, - PKT_END); - } else { - ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); - ssh2_pkt_adduint32(c->remoteid); - ssh2_pkt_send(); + /* + * If the channel's remoteid is -1, we have sent + * CHANNEL_OPEN for this channel, but it hasn't even been + * acknowledged by the server. So we must set a close flag + * on it now, and then when the server acks the channel + * open, we can close it then. + */ + if (c->remoteid != -1) { + if (ssh_version == 1) { + send_packet(SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid, + PKT_END); + } else { + ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); + ssh2_pkt_adduint32(c->remoteid); + ssh2_pkt_send(); + } } c->closes = 1; if (c->type == CHAN_X11) { c->u.x11.s = NULL; logevent("Forwarded X11 connection terminated"); - } else if (c->type == CHAN_SOCKDATA) { + } else if (c->type == CHAN_SOCKDATA || + c->type == CHAN_SOCKDATA_DORMANT) { c->u.pfd.s = NULL; logevent("Forwarded port closed"); } @@ -2905,6 +2915,17 @@ static void ssh1_protocol(unsigned char *in, int inlen, int ispkt) pfd_confirm(c->u.pfd.s); } + if (c && c->closes) { + /* + * We have a pending close on this channel, + * which we decided on before the server acked + * the channel open. So now we know the + * remoteid, we can close it again. + */ + send_packet(SSH1_MSG_CHANNEL_CLOSE, PKT_INT, c->remoteid, + PKT_END); + } + } else if (pktin.type == SSH1_MSG_CHANNEL_OPEN_FAILURE) { unsigned int remoteid = GET_32BIT(pktin.body); unsigned int localid = GET_32BIT(pktin.body+4); @@ -4864,11 +4885,22 @@ static void do_ssh2_authconn(unsigned char *in, int inlen, int ispkt) continue; /* dunno why they're confirming this */ c->remoteid = ssh2_pkt_getuint32(); c->type = CHAN_SOCKDATA; - c->closes = 0; c->v.v2.remwindow = ssh2_pkt_getuint32(); c->v.v2.remmaxpkt = ssh2_pkt_getuint32(); bufchain_init(&c->v.v2.outbuffer); - pfd_confirm(c->u.pfd.s); + if (c->u.pfd.s) + pfd_confirm(c->u.pfd.s); + if (c->closes) { + /* + * We have a pending close on this channel, + * which we decided on before the server acked + * the channel open. So now we know the + * remoteid, we can close it again. + */ + ssh2_pkt_init(SSH2_MSG_CHANNEL_CLOSE); + ssh2_pkt_adduint32(c->remoteid); + ssh2_pkt_send(); + } } else if (pktin.type == SSH2_MSG_CHANNEL_OPEN_FAILURE) { unsigned i = ssh2_pkt_getuint32(); struct ssh_channel *c; -- 2.11.0