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]
-/* $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
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;
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
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);
}
/*
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)
{
-/* $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>
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
-/* $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
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;
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)
{
logit("Warning: Could not request remote "
"forwarding.");
}
+ client_register_global_confirm(ssh_confirm_remote_forward,
+ &options.remote_forwards[i]);
}
/* Initiate tunnel forwarding. */
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)