mirror of
https://github.com/clearml/dropbear
synced 2025-06-16 19:28:49 +00:00
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.
This commit is contained in:
parent
f1826ea389
commit
da57dd13c5
18
channel.h
18
channel.h
@ -29,14 +29,6 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "circbuffer.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_ADMINISTRATIVELY_PROHIBITED 1
|
||||||
#define SSH_OPEN_CONNECT_FAILED 2
|
#define SSH_OPEN_CONNECT_FAILED 2
|
||||||
#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
|
#define SSH_OPEN_UNKNOWN_CHANNEL_TYPE 3
|
||||||
@ -49,6 +41,13 @@
|
|||||||
|
|
||||||
struct ChanType;
|
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 {
|
struct Channel {
|
||||||
|
|
||||||
unsigned int index; /* the local channel index */
|
unsigned int index; /* the local channel index */
|
||||||
@ -87,6 +86,8 @@ struct Channel {
|
|||||||
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
|
void (*read_mangler)(struct Channel*, unsigned char* bytes, int *len);
|
||||||
|
|
||||||
const struct ChanType* type;
|
const struct ChanType* type;
|
||||||
|
|
||||||
|
enum dropbear_channel_prio prio;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ChanType {
|
struct ChanType {
|
||||||
@ -97,7 +98,6 @@ struct ChanType {
|
|||||||
int (*check_close)(struct Channel*);
|
int (*check_close)(struct Channel*);
|
||||||
void (*reqhandler)(struct Channel*);
|
void (*reqhandler)(struct Channel*);
|
||||||
void (*closehandler)(struct Channel*);
|
void (*closehandler)(struct Channel*);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void chaninitialise(const struct ChanType *chantypes[]);
|
void chaninitialise(const struct ChanType *chantypes[]);
|
||||||
|
@ -41,7 +41,7 @@ static void cli_chansessreq(struct Channel *channel);
|
|||||||
static void send_chansess_pty_req(struct Channel *channel);
|
static void send_chansess_pty_req(struct Channel *channel);
|
||||||
static void send_chansess_shell_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 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();
|
static void cli_tty_setup();
|
||||||
|
|
||||||
@ -357,6 +357,11 @@ static int cli_init_stdpipe_sess(struct Channel *channel) {
|
|||||||
return 0;
|
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) {
|
static int cli_initchansess(struct Channel *channel) {
|
||||||
|
|
||||||
cli_init_stdpipe_sess(channel);
|
cli_init_stdpipe_sess(channel);
|
||||||
@ -369,8 +374,9 @@ static int cli_initchansess(struct Channel *channel) {
|
|||||||
|
|
||||||
if (cli_opts.wantpty) {
|
if (cli_opts.wantpty) {
|
||||||
send_chansess_pty_req(channel);
|
send_chansess_pty_req(channel);
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||||
} else {
|
} else {
|
||||||
set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
|
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_chansess_shell_req(channel);
|
send_chansess_shell_req(channel);
|
||||||
@ -389,7 +395,7 @@ static int cli_initchansess(struct Channel *channel) {
|
|||||||
static const struct ChanType cli_chan_netcat = {
|
static const struct ChanType cli_chan_netcat = {
|
||||||
0, /* sepfds */
|
0, /* sepfds */
|
||||||
"direct-tcpip",
|
"direct-tcpip",
|
||||||
cli_init_stdpipe_sess, /* inithandler */
|
cli_init_netcat, /* inithandler */
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
cli_closechansess
|
cli_closechansess
|
||||||
|
@ -75,9 +75,6 @@ int main(int argc, char ** argv) {
|
|||||||
int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
int sock = connect_remote(cli_opts.remotehost, cli_opts.remoteport,
|
||||||
0, &error);
|
0, &error);
|
||||||
sock_in = sock_out = sock;
|
sock_in = sock_out = sock;
|
||||||
if (cli_opts.wantpty) {
|
|
||||||
set_sock_priority(sock, DROPBEAR_PRIO_LOWDELAY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sock_in < 0) {
|
if (sock_in < 0) {
|
||||||
|
@ -52,7 +52,7 @@ static int cli_localtcp(const char* listenaddr,
|
|||||||
static const struct ChanType cli_chan_tcplocal = {
|
static const struct ChanType cli_chan_tcplocal = {
|
||||||
1, /* sepfds */
|
1, /* sepfds */
|
||||||
"direct-tcpip",
|
"direct-tcpip",
|
||||||
NULL,
|
tcp_prio_inithandler,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
@ -267,6 +267,8 @@ static int newtcpforwarded(struct Channel * channel) {
|
|||||||
* progress succeeds */
|
* progress succeeds */
|
||||||
channel->writefd = sock;
|
channel->writefd = sock;
|
||||||
channel->initconn = 1;
|
channel->initconn = 1;
|
||||||
|
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||||
|
|
||||||
err = SSH_OPEN_IN_PROGRESS;
|
err = SSH_OPEN_IN_PROGRESS;
|
||||||
|
|
||||||
|
@ -174,6 +174,8 @@ static struct Channel* newchannel(unsigned int remotechan,
|
|||||||
newchan->recvdonelen = 0;
|
newchan->recvdonelen = 0;
|
||||||
newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
|
newchan->recvmaxpacket = RECV_MAX_CHANNEL_DATA_LEN;
|
||||||
|
|
||||||
|
newchan->prio = DROPBEAR_CHANNEL_PRIO_EARLY; /* inithandler sets it */
|
||||||
|
|
||||||
ses.channels[i] = newchan;
|
ses.channels[i] = newchan;
|
||||||
ses.chancount++;
|
ses.chancount++;
|
||||||
|
|
||||||
@ -595,6 +597,8 @@ static void remove_channel(struct Channel * channel) {
|
|||||||
m_free(channel);
|
m_free(channel);
|
||||||
ses.chancount--;
|
ses.chancount--;
|
||||||
|
|
||||||
|
update_channel_prio();
|
||||||
|
|
||||||
TRACE(("leave remove_channel"))
|
TRACE(("leave remove_channel"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,6 +889,10 @@ void recv_msg_channel_open() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||||
|
}
|
||||||
|
|
||||||
chan_initwritebuf(channel);
|
chan_initwritebuf(channel);
|
||||||
|
|
||||||
/* success */
|
/* success */
|
||||||
@ -898,6 +906,8 @@ failure:
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
m_free(type);
|
m_free(type);
|
||||||
|
|
||||||
|
update_channel_prio();
|
||||||
|
|
||||||
TRACE(("leave recv_msg_channel_open"))
|
TRACE(("leave recv_msg_channel_open"))
|
||||||
}
|
}
|
||||||
@ -1013,7 +1023,7 @@ static void close_chan_fd(struct Channel *channel, int fd, int how) {
|
|||||||
* for X11, agent, tcp forwarding, and should be filled with channel-specific
|
* for X11, agent, tcp forwarding, and should be filled with channel-specific
|
||||||
* options, with the calling function calling encrypt_packet() after
|
* options, with the calling function calling encrypt_packet() after
|
||||||
* completion. It is mandatory for the caller to encrypt_packet() if
|
* 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) {
|
int send_msg_channel_open_init(int fd, const struct ChanType *type) {
|
||||||
|
|
||||||
struct Channel* chan;
|
struct Channel* chan;
|
||||||
@ -1082,6 +1092,10 @@ void recv_msg_channel_open_confirmation() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel->prio == DROPBEAR_CHANNEL_PRIO_EARLY) {
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||||
|
}
|
||||||
|
update_channel_prio();
|
||||||
|
|
||||||
TRACE(("leave recv_msg_channel_open_confirmation"))
|
TRACE(("leave recv_msg_channel_open_confirmation"))
|
||||||
}
|
}
|
||||||
@ -1113,4 +1127,3 @@ void send_msg_request_failure() {
|
|||||||
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
|
buf_putbyte(ses.writepayload, SSH_MSG_REQUEST_FAILURE);
|
||||||
encrypt_packet();
|
encrypt_packet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,10 @@ void common_session_init(int sock_in, int sock_out) {
|
|||||||
ses.sock_out = sock_out;
|
ses.sock_out = sock_out;
|
||||||
ses.maxfd = MAX(sock_in, 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();
|
now = monotonic_now();
|
||||||
ses.last_packet_time_keepalive_recv = now;
|
ses.last_packet_time_keepalive_recv = now;
|
||||||
ses.last_packet_time_idle = now;
|
ses.last_packet_time_idle = now;
|
||||||
@ -512,3 +516,47 @@ void fill_passwd(const char* username) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
6
dbutil.h
6
dbutil.h
@ -62,9 +62,9 @@ extern int debug_trace;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
enum dropbear_prio {
|
enum dropbear_prio {
|
||||||
DROPBEAR_PRIO_DEFAULT,
|
DROPBEAR_PRIO_DEFAULT = 'dffd',
|
||||||
DROPBEAR_PRIO_LOWDELAY,
|
DROPBEAR_PRIO_LOWDELAY = 'lddl',
|
||||||
DROPBEAR_PRIO_BULK,
|
DROPBEAR_PRIO_BULK = 'bllb',
|
||||||
};
|
};
|
||||||
|
|
||||||
char * stripcontrol(const char * text);
|
char * stripcontrol(const char * text);
|
||||||
|
@ -48,6 +48,8 @@ void session_cleanup();
|
|||||||
void send_session_identification();
|
void send_session_identification();
|
||||||
void send_msg_ignore();
|
void send_msg_ignore();
|
||||||
|
|
||||||
|
void update_channel_prio();
|
||||||
|
|
||||||
const char* get_user_shell();
|
const char* get_user_shell();
|
||||||
void fill_passwd(const char* username);
|
void fill_passwd(const char* username);
|
||||||
|
|
||||||
@ -186,7 +188,9 @@ struct sshsession {
|
|||||||
unsigned int chancount; /* the number of Channel*s in use */
|
unsigned int chancount; /* the number of Channel*s in use */
|
||||||
const struct ChanType **chantypes; /* The valid channel types */
|
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 */
|
/* TCP forwarding - where manage listeners */
|
||||||
struct Listener ** listeners;
|
struct Listener ** listeners;
|
||||||
unsigned int listensize;
|
unsigned int listensize;
|
||||||
|
@ -253,6 +253,8 @@ static int newchansess(struct Channel *channel) {
|
|||||||
chansess->agentdir = NULL;
|
chansess->agentdir = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -668,8 +670,11 @@ static int sessioncommand(struct Channel *channel, struct ChanSess *chansess,
|
|||||||
|
|
||||||
if (chansess->term == NULL) {
|
if (chansess->term == NULL) {
|
||||||
/* no pty */
|
/* no pty */
|
||||||
set_sock_priority(ses.sock_out, DROPBEAR_PRIO_BULK);
|
|
||||||
ret = noptycommand(channel, chansess);
|
ret = noptycommand(channel, chansess);
|
||||||
|
if (ret == DROPBEAR_SUCCESS) {
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_BULK;
|
||||||
|
update_channel_prio();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* want pty */
|
/* want pty */
|
||||||
ret = ptycommand(channel, chansess);
|
ret = ptycommand(channel, chansess);
|
||||||
|
@ -53,7 +53,7 @@ static int newtcpdirect(struct Channel * channel);
|
|||||||
static const struct ChanType svr_chan_tcpremote = {
|
static const struct ChanType svr_chan_tcpremote = {
|
||||||
1, /* sepfds */
|
1, /* sepfds */
|
||||||
"forwarded-tcpip",
|
"forwarded-tcpip",
|
||||||
NULL,
|
tcp_prio_inithandler,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
@ -240,6 +240,8 @@ static int newtcpdirect(struct Channel * channel) {
|
|||||||
int len;
|
int len;
|
||||||
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
int err = SSH_OPEN_ADMINISTRATIVELY_PROHIBITED;
|
||||||
|
|
||||||
|
TRACE(("newtcpdirect channel %d", channel->index))
|
||||||
|
|
||||||
if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {
|
if (svr_opts.nolocaltcp || !svr_pubkey_allows_tcpfwd()) {
|
||||||
TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
|
TRACE(("leave newtcpdirect: local tcp forwarding disabled"))
|
||||||
goto out;
|
goto out;
|
||||||
@ -281,6 +283,8 @@ static int newtcpdirect(struct Channel * channel) {
|
|||||||
* progress succeeds */
|
* progress succeeds */
|
||||||
channel->writefd = sock;
|
channel->writefd = sock;
|
||||||
channel->initconn = 1;
|
channel->initconn = 1;
|
||||||
|
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_UNKNOWABLE;
|
||||||
|
|
||||||
err = SSH_OPEN_IN_PROGRESS;
|
err = SSH_OPEN_IN_PROGRESS;
|
||||||
|
|
||||||
|
@ -182,10 +182,15 @@ void x11cleanup(struct ChanSess *chansess) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int x11_inithandler(struct Channel *channel) {
|
||||||
|
channel->prio = DROPBEAR_CHANNEL_PRIO_INTERACTIVE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct ChanType chan_x11 = {
|
static const struct ChanType chan_x11 = {
|
||||||
0, /* sepfds */
|
0, /* sepfds */
|
||||||
"x11",
|
"x11",
|
||||||
NULL, /* inithandler */
|
x11_inithandler, /* inithandler */
|
||||||
NULL, /* checkclose */
|
NULL, /* checkclose */
|
||||||
NULL, /* reqhandler */
|
NULL, /* reqhandler */
|
||||||
NULL /* closehandler */
|
NULL /* closehandler */
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "listener.h"
|
#include "listener.h"
|
||||||
|
#include "listener.h"
|
||||||
#include "runopts.h"
|
#include "runopts.h"
|
||||||
|
|
||||||
#ifdef DROPBEAR_TCP_ACCEPT
|
#ifdef DROPBEAR_TCP_ACCEPT
|
||||||
@ -44,6 +45,13 @@ static void cleanup_tcp(struct Listener *listener) {
|
|||||||
m_free(tcpinfo);
|
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) {
|
static void tcp_acceptor(struct Listener *listener, int sock) {
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
|
Loading…
Reference in New Issue
Block a user