summaryrefslogtreecommitdiffhomepage
path: root/common-session.c
diff options
context:
space:
mode:
Diffstat (limited to 'common-session.c')
-rw-r--r--common-session.c46
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;
+}