From 5cd6995fb5ab34c3ff2e77f94be1be4135248db3 Mon Sep 17 00:00:00 2001
From: Matt Johnston <matt@ucc.asn.au>
Date: Sun, 2 Nov 2008 12:25:08 +0000
Subject: [PATCH] Report errors if a remote request fails

--HG--
extra : convert_revision : ed1584aacf189b8f8ddee813b98342fa8bb38022
---
 cli-runopts.c |  1 +
 cli-session.c |  4 ++++
 cli-tcpfwd.c  | 38 +++++++++++++++++++++++++++++++++++++-
 tcpfwd.h      |  4 ++++
 4 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/cli-runopts.c b/cli-runopts.c
index be449a3d..13d6b45a 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -609,6 +609,7 @@ static void addforward(const char* origstr, struct TCPFwdList** fwdlist) {
 		goto badport;
 	}
 
+	newfwd->have_reply = 0;
 	newfwd->next = *fwdlist;
 	*fwdlist = newfwd;
 
diff --git a/cli-session.c b/cli-session.c
index d0a73612..c153f4f9 100644
--- a/cli-session.c
+++ b/cli-session.c
@@ -64,6 +64,10 @@ static const packettype cli_packettypes[] = {
 	{SSH_MSG_CHANNEL_OPEN_FAILURE, recv_msg_channel_open_failure},
 	{SSH_MSG_USERAUTH_BANNER, recv_msg_userauth_banner}, /* client */
 	{SSH_MSG_USERAUTH_SPECIFIC_60, recv_msg_userauth_specific_60}, /* client */
+#ifdef  ENABLE_CLI_REMOTETCPFWD
+	{SSH_MSG_REQUEST_SUCCESS, cli_recv_msg_request_success}, /* client */
+	{SSH_MSG_REQUEST_FAILURE, cli_recv_msg_request_failure}, /* client */
+#endif
 	{0, 0} /* End */
 };
 
diff --git a/cli-tcpfwd.c b/cli-tcpfwd.c
index c3bfd4dc..0e60090b 100644
--- a/cli-tcpfwd.c
+++ b/cli-tcpfwd.c
@@ -128,7 +128,7 @@ static void send_msg_global_request_remotetcp(int port) {
 	CHECKCLEARTOWRITE();
 	buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST);
 	buf_putstring(ses.writepayload, "tcpip-forward", 13);
-	buf_putbyte(ses.writepayload, 0);
+	buf_putbyte(ses.writepayload, 1); /* want_reply */
 	if (opts.listen_fwd_all) {
 		listenspec = "";
 	} else {
@@ -143,6 +143,42 @@ static void send_msg_global_request_remotetcp(int port) {
 	TRACE(("leave send_msg_global_request_remotetcp"))
 }
 
+/* The only global success/failure messages are for remotetcp.
+ * Since there isn't any identifier in these messages, we have to rely on them
+ * being in the same order as we sent the requests. This is the ordering
+ * of the cli_opts.remotefwds list */
+void cli_recv_msg_request_success() {
+
+	/* Nothing in the packet. We just mark off that we have received the reply,
+	 * so that we can report failure for later ones. */
+	struct TCPFwdList * iter = NULL;
+
+	iter = cli_opts.remotefwds;
+	while (iter != NULL) {
+		if (!iter->have_reply)
+		{
+			iter->have_reply = 1;
+			return;
+		}
+		iter = iter->next;
+	}
+}
+
+void cli_recv_msg_request_failure() {
+	struct TCPFwdList * iter = NULL;
+
+	iter = cli_opts.remotefwds;
+	while (iter != NULL) {
+		if (!iter->have_reply)
+		{
+			iter->have_reply = 1;
+			dropbear_log(LOG_WARNING, "Remote TCP forward request failed (port %d -> %s:%d)", iter->listenport, iter->connectaddr, iter->connectport);
+			return;
+		}
+		iter = iter->next;
+	}
+}
+
 void setup_remotetcp() {
 
 	struct TCPFwdList * iter = NULL;
diff --git a/tcpfwd.h b/tcpfwd.h
index f50515ce..251612ed 100644
--- a/tcpfwd.h
+++ b/tcpfwd.h
@@ -49,6 +49,8 @@ struct TCPFwdList {
 	const unsigned char* connectaddr;
 	unsigned int connectport;
 	unsigned int listenport;
+	unsigned int have_reply; /* is set to 1 after a reply has been received
+								when setting up the forwarding */
 	struct TCPFwdList * next;
 
 };
@@ -62,6 +64,8 @@ extern const struct ChanType svr_chan_tcpdirect;
 void setup_localtcp();
 void setup_remotetcp();
 extern const struct ChanType cli_chan_tcpremote;
+void cli_recv_msg_request_success();
+void cli_recv_msg_request_failure();
 
 /* Common */
 int listen_tcpfwd(struct TCPListener* tcpinfo);
-- 
GitLab