comparison common-session.c @ 454:7e43f5e473b9

- Add -K keepalive flag for dropbear and dbclient - Try to reduce the frequency of select() timeouts - Add a max receive window size of 1MB
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Aug 2007 15:12:06 +0000
parents 4cab61369879
children e3db1f7a2e43
comparison
equal deleted inserted replaced
453:29953de278ae 454:7e43f5e473b9
32 #include "ssh.h" 32 #include "ssh.h"
33 #include "random.h" 33 #include "random.h"
34 #include "kex.h" 34 #include "kex.h"
35 #include "channel.h" 35 #include "channel.h"
36 #include "atomicio.h" 36 #include "atomicio.h"
37 #include "runopts.h"
37 38
38 static void checktimeouts(); 39 static void checktimeouts();
40 static long select_timeout();
39 static int ident_readln(int fd, char* buf, int count); 41 static int ident_readln(int fd, char* buf, int count);
40 42
41 struct sshsession ses; /* GLOBAL */ 43 struct sshsession ses; /* GLOBAL */
42 44
43 /* need to know if the session struct has been initialised, this way isn't the 45 /* need to know if the session struct has been initialised, this way isn't the
57 ses.remotehost = remotehost; 59 ses.remotehost = remotehost;
58 60
59 ses.sock = sock; 61 ses.sock = sock;
60 ses.maxfd = sock; 62 ses.maxfd = sock;
61 63
62 ses.connecttimeout = 0; 64 ses.connect_time = 0;
65 ses.last_packet_time = 0;
63 66
64 if (pipe(ses.signal_pipe) < 0) { 67 if (pipe(ses.signal_pipe) < 0) {
65 dropbear_exit("signal pipe failed"); 68 dropbear_exit("signal pipe failed");
66 } 69 }
67 setnonblocking(ses.signal_pipe[0]); 70 setnonblocking(ses.signal_pipe[0]);
127 int val; 130 int val;
128 131
129 /* main loop, select()s for all sockets in use */ 132 /* main loop, select()s for all sockets in use */
130 for(;;) { 133 for(;;) {
131 134
132 timeout.tv_sec = SELECT_TIMEOUT; 135 timeout.tv_sec = select_timeout();
133 timeout.tv_usec = 0; 136 timeout.tv_usec = 0;
134 FD_ZERO(&writefd); 137 FD_ZERO(&writefd);
135 FD_ZERO(&readfd); 138 FD_ZERO(&readfd);
136 dropbear_assert(ses.payload == NULL); 139 dropbear_assert(ses.payload == NULL);
137 if (ses.sock != -1) { 140 if (ses.sock != -1) {
357 buf[pos] = '\0'; 360 buf[pos] = '\0';
358 TRACE(("leave ident_readln: return %d", pos+1)) 361 TRACE(("leave ident_readln: return %d", pos+1))
359 return pos+1; 362 return pos+1;
360 } 363 }
361 364
365 void send_msg_ignore() {
366 CHECKCLEARTOWRITE();
367 buf_putbyte(ses.writepayload, SSH_MSG_IGNORE);
368 buf_putstring(ses.writepayload, "", 0);
369 encrypt_packet();
370 }
371
362 /* Check all timeouts which are required. Currently these are the time for 372 /* Check all timeouts which are required. Currently these are the time for
363 * user authentication, and the automatic rekeying. */ 373 * user authentication, and the automatic rekeying. */
364 static void checktimeouts() { 374 static void checktimeouts() {
365 375
366 struct timeval tv; 376 time_t now;
367 long secs; 377
368 378 now = time(NULL);
369 if (gettimeofday(&tv, 0) < 0) { 379
370 dropbear_exit("Error getting time"); 380 if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) {
371 }
372
373 secs = tv.tv_sec;
374
375 if (ses.connecttimeout != 0 && secs > ses.connecttimeout) {
376 dropbear_close("Timeout before auth"); 381 dropbear_close("Timeout before auth");
377 } 382 }
378 383
379 /* we can't rekey if we haven't done remote ident exchange yet */ 384 /* we can't rekey if we haven't done remote ident exchange yet */
380 if (ses.remoteident == NULL) { 385 if (ses.remoteident == NULL) {
381 return; 386 return;
382 } 387 }
383 388
384 if (!ses.kexstate.sentkexinit 389 if (!ses.kexstate.sentkexinit
385 && (secs - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT 390 && (now - ses.kexstate.lastkextime >= KEX_REKEY_TIMEOUT
386 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)){ 391 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) {
387 TRACE(("rekeying after timeout or max data reached")) 392 TRACE(("rekeying after timeout or max data reached"))
388 send_msg_kexinit(); 393 send_msg_kexinit();
389 } 394 }
390 } 395
391 396 if (opts.keepalive_secs > 0
397 && now - ses.last_packet_time >= opts.keepalive_secs) {
398 send_msg_ignore();
399 }
400 }
401
402 static long select_timeout() {
403 /* determine the minimum timeout that might be required, so
404 as to avoid waking when unneccessary */
405 long ret = LONG_MAX;
406 if (KEX_REKEY_TIMEOUT > 0)
407 ret = MIN(KEX_REKEY_TIMEOUT, ret);
408 if (AUTH_TIMEOUT > 0)
409 ret = MIN(AUTH_TIMEOUT, ret);
410 if (opts.keepalive_secs > 0)
411 ret = MIN(opts.keepalive_secs, ret);
412 return ret;
413 }