Tidy up the SERIOUS NETWORK ERROR fixes
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 30 Oct 2001 20:57:22 +0000 (20:57 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Tue, 30 Oct 2001 20:57:22 +0000 (20:57 +0000)
git-svn-id: svn://svn.tartarus.org/sgt/putty@1345 cda61777-01e9-0310-a592-d414129be87e

network.h
ssh.c

index 4300fb2..28744a6 100644 (file)
--- 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 67ae0d4..119cd4f 100644 (file)
--- 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;