Mercurial > dropbear
diff common-session.c @ 939:a0819ecfee0b
Make -K keepalive behave like OpenSSH's ServerAliveInterval
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 09 Jul 2014 00:15:20 +0800 |
parents | 9d40ed1da686 |
children | e9dfb6d15193 |
line wrap: on
line diff
--- a/common-session.c Wed Jul 09 00:13:17 2014 +0800 +++ b/common-session.c Wed Jul 09 00:15:20 2014 +0800 @@ -51,6 +51,7 @@ /* called only at the start of a session, set up initial state */ void common_session_init(int sock_in, int sock_out) { + time_t now; TRACE(("enter session_init")) @@ -58,9 +59,12 @@ ses.sock_out = sock_out; ses.maxfd = MAX(sock_in, sock_out); - ses.connect_time = 0; - ses.last_trx_packet_time = 0; - ses.last_packet_time = 0; + now = monotonic_now(); + ses.connect_time = now; + ses.last_packet_time_keepalive_recv = now; + ses.last_packet_time_idle = now; + ses.last_packet_time_any_sent = 0; + ses.last_packet_time_keepalive_sent = 0; if (pipe(ses.signal_pipe) < 0) { dropbear_exit("Signal pipe failed"); @@ -387,11 +391,21 @@ return pos+1; } -void send_msg_ignore() { +static void send_msg_keepalive() { CHECKCLEARTOWRITE(); - buf_putbyte(ses.writepayload, SSH_MSG_IGNORE); - buf_putstring(ses.writepayload, "", 0); + time_t old_time_idle = ses.last_packet_time_idle; + /* Try to force a response from the other end. Some peers will + reply with SSH_MSG_REQUEST_FAILURE, some will reply with SSH_MSG_UNIMPLEMENTED */ + buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); + /* A short string */ + buf_putstring(ses.writepayload, "[email protected]", 0); + buf_putbyte(ses.writepayload, 1); /* want_reply */ encrypt_packet(); + + ses.last_packet_time_keepalive_sent = monotonic_now(); + + /* keepalives shouldn't update idle timeout, reset it back */ + ses.last_packet_time_idle = old_time_idle; } /* Check all timeouts which are required. Currently these are the time for @@ -401,7 +415,7 @@ time_t now; now = monotonic_now(); - if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) { + if (now - ses.connect_time >= AUTH_TIMEOUT) { dropbear_close("Timeout before auth"); } @@ -417,13 +431,27 @@ send_msg_kexinit(); } - if (opts.keepalive_secs > 0 - && now - ses.last_trx_packet_time >= opts.keepalive_secs) { - send_msg_ignore(); + if (opts.keepalive_secs > 0) { + /* Send keepalives if we've been idle */ + if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) { + send_msg_keepalive(); + } + + /* Also send an explicit keepalive message to trigger a response + if the remote end hasn't sent us anything */ + if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs + && now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) { + send_msg_keepalive(); + } + + if (now - ses.last_packet_time_keepalive_recv + >= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) { + dropbear_exit("Keepalive timeout"); + } } - if (opts.idle_timeout_secs > 0 && ses.last_packet_time > 0 - && now - ses.last_packet_time >= opts.idle_timeout_secs) { + if (opts.idle_timeout_secs > 0 + && now - ses.last_packet_time_idle >= opts.idle_timeout_secs) { dropbear_close("Idle timeout"); } }