]> andersk Git - openssh.git/commitdiff
- djm@cvs.openbsd.org 2008/06/12 04:06:00
authordtucker <dtucker>
Thu, 12 Jun 2008 18:50:27 +0000 (18:50 +0000)
committerdtucker <dtucker>
Thu, 12 Jun 2008 18:50:27 +0000 (18:50 +0000)
     [clientloop.h ssh.c clientloop.c]
     maintain an ordered queue of outstanding global requests that we
     expect replies to, similar to the per-channel confirmation queue.
     Use this queue to verify success or failure for remote forward
     establishment in a race free way.
     ok dtucker@

ChangeLog
clientloop.c
clientloop.h
ssh.c

index 15679c64b28b9b5d175ca4e5a5c22a1da389db86..af079a5b434dafae774a48f02718ed7b9b347966 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
      mux client will not be able to connect to a running old ssh
      mux master.
      ok dtucker@
+   - djm@cvs.openbsd.org 2008/06/12 04:06:00
+     [clientloop.h ssh.c clientloop.c]
+     maintain an ordered queue of outstanding global requests that we
+     expect replies to, similar to the per-channel confirmation queue.
+     Use this queue to verify success or failure for remote forward
+     establishment in a race free way.
+     ok dtucker@
 
 20080611
  - (djm) [channels.c configure.ac]
index b45e7298a802ff2e8aefb2bfae549cb214be7a4e..37cecf5a6b05662fa35bb11062c44577861e16b7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.195 2008/06/12 03:40:52 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.196 2008/06/12 04:06:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -174,6 +174,17 @@ struct channel_reply_ctx {
        int id, do_close;
 };
 
+/* Global request success/failure callbacks */
+struct global_confirm {
+       TAILQ_ENTRY(global_confirm) entry;
+       global_confirm_cb *cb;
+       void *ctx;
+       int ref_count;
+};
+TAILQ_HEAD(global_confirms, global_confirm);
+static struct global_confirms global_confirms =
+    TAILQ_HEAD_INITIALIZER(global_confirms);
+
 /*XXX*/
 extern Kex *xxx_kex;
 
@@ -468,8 +479,19 @@ client_check_window_change(void)
 static void
 client_global_request_reply(int type, u_int32_t seq, void *ctxt)
 {
+       struct global_confirm *gc;
+
+       if ((gc = TAILQ_FIRST(&global_confirms)) == NULL)
+               return;
+       if (gc->cb != NULL)
+               gc->cb(type, seq, gc->ctx);
+       if (--gc->ref_count <= 0) {
+               TAILQ_REMOVE(&global_confirms, gc, entry);
+               bzero(gc, sizeof(*gc));
+               xfree(gc);
+       }
+
        keep_alive_timeouts = 0;
-       client_global_request_reply_fwd(type, seq, ctxt);
 }
 
 static void
@@ -483,6 +505,8 @@ server_alive_check(void)
        packet_put_cstring("keepalive@openssh.com");
        packet_put_char(1);     /* boolean: want reply */
        packet_send();
+       /* Insert an empty placeholder to maintain ordering */
+       client_register_global_confirm(NULL, NULL);
 }
 
 /*
@@ -702,6 +726,27 @@ client_expect_confirm(int id, const char *request, int do_close)
            client_abandon_status_confirm, cr);
 }
 
+void
+client_register_global_confirm(global_confirm_cb *cb, void *ctx)
+{
+       struct global_confirm *gc, *first_gc;
+
+       /* Coalesce identical callbacks */
+       first_gc = TAILQ_FIRST(&global_confirms);
+       if (first_gc && first_gc->cb == cb && first_gc->ctx == ctx) {
+               if (++first_gc->ref_count >= INT_MAX)
+                       fatal("%s: first_gc->ref_count = %d",
+                           __func__, first_gc->ref_count);
+               return;
+       }
+
+       gc = xmalloc(sizeof(*gc));
+       gc->cb = cb;
+       gc->ctx = ctx;
+       gc->ref_count = 1;
+       TAILQ_INSERT_TAIL(&global_confirms, gc, entry);
+}
+
 static void
 process_cmdline(void)
 {
index cecbfb1a87893e79ccfaa598c5c29e66c181bc27..3353a9a80d426b3e3857e838060af9e4816ee4bc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.h,v 1.20 2008/06/12 03:40:52 djm Exp $ */
+/* $OpenBSD: clientloop.h,v 1.21 2008/06/12 04:06:00 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -50,6 +50,10 @@ int   client_request_tun_fwd(int, int, int);
 void   *client_new_escape_filter_ctx(int);
 int     client_simple_escape_filter(Channel *, char *, int);
 
+/* Global request confirmation callbacks */
+typedef void global_confirm_cb(int, u_int32_t seq, void *);
+void    client_register_global_confirm(global_confirm_cb *, void *);
+
 /* Multiplexing protocol version */
 #define SSHMUX_VER                     2
 
diff --git a/ssh.c b/ssh.c
index e3737bb9ce65f749577b53f50b8f3dc0185406a8..6c39c85b90f8eab21f5b4856752fe8487d8d5c2b 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.314 2008/06/10 22:15:23 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.315 2008/06/12 04:06:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -164,7 +164,7 @@ Buffer command;
 int subsystem_flag = 0;
 
 /* # of replies received for global requests */
-static int client_global_request_id = 0;
+static int remote_forward_confirms_received = 0;
 
 /* pid of proxycommand child process */
 pid_t proxy_command_pid = 0;
@@ -817,6 +817,28 @@ main(int ac, char **av)
        return exit_status;
 }
 
+/* Callback for remote forward global requests */
+static void
+ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
+{
+       Forward *rfwd = (Forward *)ctxt;
+
+       debug("remote forward %s for: listen %d, connect %s:%d",
+           type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
+           rfwd->listen_port, rfwd->connect_host, rfwd->connect_port);
+       if (type == SSH2_MSG_REQUEST_FAILURE) {
+               if (options.exit_on_forward_failure)
+                       fatal("Error: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+               else
+                       logit("Warning: remote port forwarding failed for "
+                           "listen port %d", rfwd->listen_port);
+       }
+       if (++remote_forward_confirms_received == options.num_remote_forwards)
+               debug("All remote forwarding requests processed");
+               /* XXX fork-after-authentication */
+}
+
 static void
 ssh_init_forwarding(void)
 {
@@ -865,6 +887,8 @@ ssh_init_forwarding(void)
                                logit("Warning: Could not request remote "
                                    "forwarding.");
                }
+               client_register_global_confirm(ssh_confirm_remote_forward,
+                   &options.remote_forwards[i]);
        }
 
        /* Initiate tunnel forwarding. */
@@ -1034,31 +1058,6 @@ ssh_session(void)
            options.escape_char : SSH_ESCAPECHAR_NONE, 0);
 }
 
-void
-client_global_request_reply_fwd(int type, u_int32_t seq, void *ctxt)
-{
-       int i;
-
-       i = client_global_request_id++;
-       if (i >= options.num_remote_forwards)
-               return;
-       debug("remote forward %s for: listen %d, connect %s:%d",
-           type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
-           options.remote_forwards[i].listen_port,
-           options.remote_forwards[i].connect_host,
-           options.remote_forwards[i].connect_port);
-       if (type == SSH2_MSG_REQUEST_FAILURE) {
-               if (options.exit_on_forward_failure)
-                       fatal("Error: remote port forwarding failed for "
-                           "listen port %d",
-                           options.remote_forwards[i].listen_port);
-               else
-                       logit("Warning: remote port forwarding failed for "
-                           "listen port %d",
-                           options.remote_forwards[i].listen_port);
-       }
-}
-
 /* request pty/x11/agent/tcpfwd/shell for channel */
 static void
 ssh_session2_setup(int id, void *arg)
This page took 0.067502 seconds and 5 git commands to generate.