changeset 941:5daedffd0769

Set tcp priority as follows: if (connecting || ptys || x11) tos = LOWDELAY; else if (tcp_forwards) tos = 0; else tos = BULK; TCP forwards could be either lowdelay or bulk, hence the default priority.
author Matt Johnston <matt@ucc.asn.au>
date Wed, 16 Jul 2014 22:53:32 +0800
parents e9dfb6d15193
children 8664fea5072f
files channel.h cli-chansession.c cli-main.c cli-tcpfwd.c common-channel.c common-session.c dbutil.h session.h svr-chansession.c svr-tcpfwd.c svr-x11fwd.c tcp-accept.c tcpfwd.h
diffstat 13 files changed, 120 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/channel.h	Wed Jul 09 22:02:22 2014 +0800
+++ b/channel.h	Wed Jul 16 22:53:32 2014 +0800
@@ -29,14 +29,6 @@
 #include "buffer.h"
 #include "circbuffer.h"
 
-/* channel->type values */
-#define CHANNEL_ID_NONE 0
-#define CHANNEL_ID_SESSION 1
-#define CHANNEL_ID_X11 2
-#define CHANNEL_ID_AGENT 3
-#define CHANNEL_ID_TCPDIRECT 4
-#define CHANNEL_ID_TCPFORWARDED 5
-
 #define SSH_OPEN_ADMINISTRATIVELY_PROHIBITED    1
 #define SSH_OPEN_CONNECT_FAILED                 2
 #define SSH_OPEN_UNKNOWN_CHANNEL_TYPE           3
@@ -49,6 +41,13 @@
 
 struct ChanType;
 
+enum dropbear_channel_prio {
+	DROPBEAR_CHANNEL_PRIO_INTERACTIVE, /* pty shell, x11 */
+	DROPBEAR_CHANNEL_PRIO_UNKNOWABLE, /* tcp - can't know what's being forwarded */
+	DROPBEAR_CHANNEL_PRIO_BULK, /* the rest - probably scp or something */
+	DROPBEAR_CHANNEL_PRIO_EARLY, /* channel is still being set up */
+};
+
 struct Channel {
 
 	unsigned int index; /* the local channel index */
@@ -87,6 +86,8 @@
 	void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
 
 	const struct ChanType* type;
+
+	enum dropbear_channel_prio prio;
 };
 
 struct ChanType {
@@ -97,7 +98,6 @@
 	int (*check_close)(struct Channel*);
 	void (*reqhandler)(struct Channel*);
 	void (*closehandler)(struct Channel*);
-
 };
 
 void chaninitialise(const struct ChanType *chantypes[]);
--- a/cli-chansession.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/cli-chansession.c	Wed Jul 16 22:53:32 2014 +0800
@@ -41,7 +41,7 @@
 static void send_chansess_pty_req(struct Channel *channel);
 static void send_chansess_shell_req(struct Channel *channel);
 static void cli_escape_handler(struct Channel *channel, unsigned char* buf, int *len);
-
+static int cli_init_netcat(struct Channel *channel);
 
 static void cli_tty_setup();
 
@@ -357,6 +357,11 @@
 	return 0;
 }
 
+static int cli_init_netcat(struct Channel *channel) {
+	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
+	return cli_init_stdpipe_sess(channel);
+}
+
 static int cli_initchansess(struct Channel *channel) {
 
 	cli_init_stdpipe_sess(channel);
@@ -369,8 +374,9 @@
 
 	if (cli_opts.wantpty) {
 		send_chansess_pty_req(channel);
+		channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
 	} else {
-		set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
+		channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
 	}
 
 	send_chansess_shell_req(channel);
@@ -389,7 +395,7 @@
 static const struct ChanType cli_chan_netcat = {
 	0, /* sepfds */
 	"direct-tcpip",
-	cli_init_stdpipe_sess, /* inithandler */
+	cli_init_netcat, /* inithandler */
 	NULL,
 	NULL,
 	cli_closechansess
--- a/cli-main.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/cli-main.c	Wed Jul 16 22:53:32 2014 +0800
@@ -75,9 +75,6 @@
 		int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport, 
 				0, &error);
 		sock_in = sock_out = sock;
-	 	if (cli_opts.wantpty) {
-			set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY);
-	 	}
 	}
 
 	if (sock_in < 0) {
--- a/cli-tcpfwd.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/cli-tcpfwd.c	Wed Jul 16 22:53:32 2014 +0800
@@ -52,7 +52,7 @@
 static const struct ChanType cli_chan_tcplocal = {
 	1, /* sepfds */
 	"direct-tcpip",
-	NULL,
+	tcp_prio_inithandler,
 	NULL,
 	NULL,
 	NULL
@@ -267,6 +267,8 @@
 	 * progress succeeds */
 	channel->writefd = sock;
 	channel->initconn = 1;
+
+	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
 	
 	err = SSH_OPEN_IN_PROGRESS;
 
--- a/common-channel.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/common-channel.c	Wed Jul 16 22:53:32 2014 +0800
@@ -174,6 +174,8 @@
 	newchan->recvdonelen = 0;
 	newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
 
+	newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */
+
 	ses.channels[i] = newchan;
 	ses.chancount++;
 
@@ -595,6 +597,8 @@
 	m_free(channel);
 	ses.chancount--;
 
+	update_channel_prio();
+
 	TRACE(("leave remove_channel"))
 }
 
@@ -885,6 +889,10 @@
 		}
 	}
 
+	if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
+		channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
+	}
+
 	chan_initwritebuf(channel);
 
 	/* success */
@@ -898,6 +906,8 @@
 
 cleanup:
 	m_free(type);
+	
+	update_channel_prio();
 
 	TRACE(("leave recv_msg_channel_open"))
 }
@@ -1013,7 +1023,7 @@
  * for X11, agent, tcp forwarding, and should be filled with channel-specific
  * options, with the calling function calling encrypt_packet() after
  * completion. It is mandatory for the caller to encrypt_packet() if
- * DROPBEAR_SUCCESS is returned */
+ * a channel is returned. NULL is returned on failure. */
 int send_msg_channel_open_init(int fd, const struct ChanType *type) {
 
 	struct Channel* chan;
@@ -1082,6 +1092,10 @@
 		}
 	}
 
+	if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
+		channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
+	}
+	update_channel_prio();
 	
 	TRACE(("leave recv_msg_channel_open_confirmation"))
 }
@@ -1113,4 +1127,3 @@
 	buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
 	encrypt_packet();
 }
-
--- a/common-session.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/common-session.c	Wed Jul 16 22:53:32 2014 +0800
@@ -59,6 +59,10 @@
 	ses.sock_out = sock_out;
 	ses.maxfd = MAX(sock_in, sock_out);
 
+	ses.socket_prio = DROPBEAR_PRIO_DEFAULT;
+	/* Sets it to lowdelay */
+	update_channel_prio();
+
 	now = monotonic_now();
 	ses.last_packet_time_keepalive_recv = now;
 	ses.last_packet_time_idle = now;
@@ -512,3 +516,47 @@
 	}
 }
 
+/* Called when channels are modified */
+void update_channel_prio() {
+	enum dropbear_prio new_prio;
+	int any = 0;
+	unsigned int i;
+
+	TRACE(("update_channel_prio"))
+
+	new_prio = DROPBEAR_PRIO_BULK;
+	for (i = 0; i < ses.chansize; i++) {
+		struct Channel *channel = ses.channels[i];
+		if (!channel || channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
+			if (channel && channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
+				TRACE(("update_channel_prio: early %d", channel->index))
+			}
+			continue;
+		}
+		any = 1;
+		if (channel->prio == DROPBEAR_CHANNEL_PRIO_INTERACTIVE)
+		{
+			TRACE(("update_channel_prio: lowdelay %d", channel->index))
+			new_prio = DROPBEAR_PRIO_LOWDELAY;
+			break;
+		} else if (channel->prio == DROPBEAR_CHANNEL_PRIO_UNKNOWABLE
+			&& new_prio == DROPBEAR_PRIO_BULK)
+		{
+			TRACE(("update_channel_prio: unknowable %d", channel->index))
+			new_prio = DROPBEAR_PRIO_DEFAULT;
+		}
+	}
+
+	if (any == 0) {
+		/* lowdelay during setup */
+		TRACE(("update_channel_prio: not any"))
+		new_prio = DROPBEAR_PRIO_LOWDELAY;
+	}
+
+	if (new_prio != ses.socket_prio) {
+		TRACE(("Dropbear priority transitioning %4.4s -> %4.4s", (char*)&ses.socket_prio, (char*)&new_prio))
+		set_sock_priority(ses.sock_out, new_prio);
+		ses.socket_prio = new_prio;
+	}
+}
+
--- a/dbutil.h	Wed Jul 09 22:02:22 2014 +0800
+++ b/dbutil.h	Wed Jul 16 22:53:32 2014 +0800
@@ -62,9 +62,9 @@
 #endif
 
 enum dropbear_prio {
-	DROPBEAR_PRIO_DEFAULT,
-	DROPBEAR_PRIO_LOWDELAY,
-	DROPBEAR_PRIO_BULK,
+	DROPBEAR_PRIO_DEFAULT = 'dffd',
+	DROPBEAR_PRIO_LOWDELAY = 'lddl',
+	DROPBEAR_PRIO_BULK = 'bllb',
 };
 
 char * stripcontrol(const char * text);
--- a/session.h	Wed Jul 09 22:02:22 2014 +0800
+++ b/session.h	Wed Jul 16 22:53:32 2014 +0800
@@ -48,6 +48,8 @@
 void send_session_identification();
 void send_msg_ignore();
 
+void update_channel_prio();
+
 const char* get_user_shell();
 void fill_passwd(const char* username);
 
@@ -186,7 +188,9 @@
 	unsigned int chancount; /* the number of Channel*s in use */
 	const struct ChanType **chantypes; /* The valid channel types */
 
-	
+	/* TCP priority level for the main "port 22" tcp socket */
+	enum dropbear_prio socket_prio;
+
 	/* TCP forwarding - where manage listeners */
 	struct Listener ** listeners;
 	unsigned int listensize;
--- a/svr-chansession.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/svr-chansession.c	Wed Jul 16 22:53:32 2014 +0800
@@ -253,6 +253,8 @@
 	chansess->agentdir = NULL;
 #endif
 
+	channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
+
 	return 0;
 
 }
@@ -668,8 +670,11 @@
 
 	if (chansess->term == NULL) {
 		/* no pty */
-		set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
 		ret = noptycommand(channel, chansess);
+		if (ret == DROPBEAR_SUCCESS) {
+			channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
+			update_channel_prio();
+		}
 	} else {
 		/* want pty */
 		ret = ptycommand(channel, chansess);
--- a/svr-tcpfwd.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/svr-tcpfwd.c	Wed Jul 16 22:53:32 2014 +0800
@@ -53,7 +53,7 @@
 static const struct ChanType svr_chan_tcpremote = {
 	1, /* sepfds */
 	"forwarded-tcpip",
-	NULL,
+	tcp_prio_inithandler,
 	NULL,
 	NULL,
 	NULL
@@ -240,6 +240,8 @@
 	int len;
 	int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
 
+	TRACE(("newtcpdirect channel %d", channel->index))
+
 	if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {
 		TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
 		goto out;
@@ -281,6 +283,8 @@
 	 * progress succeeds */
 	channel->writefd = sock;
 	channel->initconn = 1;
+
+	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
 	
 	err = SSH_OPEN_IN_PROGRESS;
 
--- a/svr-x11fwd.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/svr-x11fwd.c	Wed Jul 16 22:53:32 2014 +0800
@@ -182,10 +182,15 @@
 	}
 }
 
+static int x11_inithandler(struct Channel *channel) {
+	channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
+	return 0;
+}
+
 static const struct ChanType chan_x11 = {
 	0, /* sepfds */
 	"x11",
-	NULL, /* inithandler */
+	x11_inithandler, /* inithandler */
 	NULL, /* checkclose */
 	NULL, /* reqhandler */
 	NULL /* closehandler */
--- a/tcp-accept.c	Wed Jul 09 22:02:22 2014 +0800
+++ b/tcp-accept.c	Wed Jul 16 22:53:32 2014 +0800
@@ -30,6 +30,7 @@
 #include "buffer.h"
 #include "packet.h"
 #include "listener.h"
+#include "listener.h"
 #include "runopts.h"
 
 #ifdef DROPBEAR_TCP_ACCEPT
@@ -44,6 +45,13 @@
 	m_free(tcpinfo);
 }
 
+int tcp_prio_inithandler(struct Channel* channel)
+{
+	TRACE(("tcp_prio_inithandler channel %d", channel->index))
+	channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
+	return 0;
+}
+
 static void tcp_acceptor(struct Listener *listener, int sock) {
 
 	int fd;
--- a/tcpfwd.h	Wed Jul 09 22:02:22 2014 +0800
+++ b/tcpfwd.h	Wed Jul 16 22:53:32 2014 +0800
@@ -70,5 +70,8 @@
 
 /* Common */
 int listen_tcpfwd(struct TCPListener* tcpinfo);
+int tcp_prio_inithandler(struct Channel* chan);
+
+#define CHANNEL_ID_TCPFORWARDED 'tcpf'
 
 #endif