diff options
Diffstat (limited to 'common-session.c')
-rw-r--r-- | common-session.c | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/common-session.c b/common-session.c index 9b248cf..79313f2 100644 --- a/common-session.c +++ b/common-session.c @@ -34,8 +34,10 @@ #include "kex.h" #include "channel.h" #include "atomicio.h" +#include "runopts.h" static void checktimeouts(); +static long select_timeout(); static int ident_readln(int fd, char* buf, int count); struct sshsession ses; /* GLOBAL */ @@ -59,7 +61,8 @@ void common_session_init(int sock, char* remotehost) { ses.sock = sock; ses.maxfd = sock; - ses.connecttimeout = 0; + ses.connect_time = 0; + ses.last_packet_time = 0; if (pipe(ses.signal_pipe) < 0) { dropbear_exit("signal pipe failed"); @@ -129,7 +132,7 @@ void session_loop(void(*loophandler)()) { /* main loop, select()s for all sockets in use */ for(;;) { - timeout.tv_sec = SELECT_TIMEOUT; + timeout.tv_sec = select_timeout(); timeout.tv_usec = 0; FD_ZERO(&writefd); FD_ZERO(&readfd); @@ -359,20 +362,22 @@ static int ident_readln(int fd, char* buf, int count) { return pos+1; } +void send_msg_ignore() { + CHECKCLEARTOWRITE(); + buf_putbyte(ses.writepayload, SSH_MSG_IGNORE); + buf_putstring(ses.writepayload, "", 0); + encrypt_packet(); +} + /* Check all timeouts which are required. Currently these are the time for * user authentication, and the automatic rekeying. */ static void checktimeouts() { - struct timeval tv; - long secs; - - if (gettimeofday(&tv, 0) < 0) { - dropbear_exit("Error getting time"); - } + time_t now; - secs = tv.tv_sec; + now = time(NULL); - if (ses.connecttimeout != 0 && secs > ses.connecttimeout) { + if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) { dropbear_close("Timeout before auth"); } @@ -382,10 +387,27 @@ static void checktimeouts() { } if (!ses.kexstate.sentkexinit - && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT - || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){ + && (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT + || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) { TRACE(("rekeying after timeout or max data reached")) send_msg_kexinit(); } + + if (opts.keepalive_secs > 0 + && now - ses.last_packet_time >= opts.keepalive_secs) { + send_msg_ignore(); + } } +static long select_timeout() { + /* determine the minimum timeout that might be required, so + as to avoid waking when unneccessary */ + long ret = LONG_MAX; + if (KEX_REKEY_TIMEOUT > 0) + ret = MIN(KEX_REKEY_TIMEOUT, ret); + if (AUTH_TIMEOUT > 0) + ret = MIN(AUTH_TIMEOUT, ret); + if (opts.keepalive_secs > 0) + ret = MIN(opts.keepalive_secs, ret); + return ret; +} |