# HG changeset patch # User Matt Johnston # Date 1405522412 -28800 # Node ID 5daedffd0769a8311970d57d5e7fd881fe0b06a0 # Parent e9dfb6d15193cee96bcf6635e748de262987b63b 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. diff -r e9dfb6d15193 -r 5daedffd0769 channel.h --- 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[]); diff -r e9dfb6d15193 -r 5daedffd0769 cli-chansession.c --- 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 diff -r e9dfb6d15193 -r 5daedffd0769 cli-main.c --- 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) { diff -r e9dfb6d15193 -r 5daedffd0769 cli-tcpfwd.c --- 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; diff -r e9dfb6d15193 -r 5daedffd0769 common-channel.c --- 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(); } - diff -r e9dfb6d15193 -r 5daedffd0769 common-session.c --- 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; + } +} + diff -r e9dfb6d15193 -r 5daedffd0769 dbutil.h --- 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); diff -r e9dfb6d15193 -r 5daedffd0769 session.h --- 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; diff -r e9dfb6d15193 -r 5daedffd0769 svr-chansession.c --- 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); diff -r e9dfb6d15193 -r 5daedffd0769 svr-tcpfwd.c --- 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; diff -r e9dfb6d15193 -r 5daedffd0769 svr-x11fwd.c --- 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 */ diff -r e9dfb6d15193 -r 5daedffd0769 tcp-accept.c --- 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; diff -r e9dfb6d15193 -r 5daedffd0769 tcpfwd.h --- 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