Mercurial > dropbear
comparison 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 |
comparison
equal
deleted
inserted
replaced
938:c88dce72f6d2 | 939:a0819ecfee0b |
---|---|
49 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ | 49 /* this is set when we get SIGINT or SIGTERM, the handler is in main.c */ |
50 int exitflag = 0; /* GLOBAL */ | 50 int exitflag = 0; /* GLOBAL */ |
51 | 51 |
52 /* called only at the start of a session, set up initial state */ | 52 /* called only at the start of a session, set up initial state */ |
53 void common_session_init(int sock_in, int sock_out) { | 53 void common_session_init(int sock_in, int sock_out) { |
54 time_t now; | |
54 | 55 |
55 TRACE(("enter session_init")) | 56 TRACE(("enter session_init")) |
56 | 57 |
57 ses.sock_in = sock_in; | 58 ses.sock_in = sock_in; |
58 ses.sock_out = sock_out; | 59 ses.sock_out = sock_out; |
59 ses.maxfd = MAX(sock_in, sock_out); | 60 ses.maxfd = MAX(sock_in, sock_out); |
60 | 61 |
61 ses.connect_time = 0; | 62 now = monotonic_now(); |
62 ses.last_trx_packet_time = 0; | 63 ses.connect_time = now; |
63 ses.last_packet_time = 0; | 64 ses.last_packet_time_keepalive_recv = now; |
65 ses.last_packet_time_idle = now; | |
66 ses.last_packet_time_any_sent = 0; | |
67 ses.last_packet_time_keepalive_sent = 0; | |
64 | 68 |
65 if (pipe(ses.signal_pipe) < 0) { | 69 if (pipe(ses.signal_pipe) < 0) { |
66 dropbear_exit("Signal pipe failed"); | 70 dropbear_exit("Signal pipe failed"); |
67 } | 71 } |
68 setnonblocking(ses.signal_pipe[0]); | 72 setnonblocking(ses.signal_pipe[0]); |
385 buf[pos] = '\0'; | 389 buf[pos] = '\0'; |
386 TRACE(("leave ident_readln: return %d", pos+1)) | 390 TRACE(("leave ident_readln: return %d", pos+1)) |
387 return pos+1; | 391 return pos+1; |
388 } | 392 } |
389 | 393 |
390 void send_msg_ignore() { | 394 static void send_msg_keepalive() { |
391 CHECKCLEARTOWRITE(); | 395 CHECKCLEARTOWRITE(); |
392 buf_putbyte(ses.writepayload, SSH_MSG_IGNORE); | 396 time_t old_time_idle = ses.last_packet_time_idle; |
393 buf_putstring(ses.writepayload, "", 0); | 397 /* Try to force a response from the other end. Some peers will |
398 reply with SSH_MSG_REQUEST_FAILURE, some will reply with SSH_MSG_UNIMPLEMENTED */ | |
399 buf_putbyte(ses.writepayload, SSH_MSG_GLOBAL_REQUEST); | |
400 /* A short string */ | |
401 buf_putstring(ses.writepayload, "[email protected]", 0); | |
402 buf_putbyte(ses.writepayload, 1); /* want_reply */ | |
394 encrypt_packet(); | 403 encrypt_packet(); |
404 | |
405 ses.last_packet_time_keepalive_sent = monotonic_now(); | |
406 | |
407 /* keepalives shouldn't update idle timeout, reset it back */ | |
408 ses.last_packet_time_idle = old_time_idle; | |
395 } | 409 } |
396 | 410 |
397 /* Check all timeouts which are required. Currently these are the time for | 411 /* Check all timeouts which are required. Currently these are the time for |
398 * user authentication, and the automatic rekeying. */ | 412 * user authentication, and the automatic rekeying. */ |
399 static void checktimeouts() { | 413 static void checktimeouts() { |
400 | 414 |
401 time_t now; | 415 time_t now; |
402 now = monotonic_now(); | 416 now = monotonic_now(); |
403 | 417 |
404 if (ses.connect_time != 0 && now - ses.connect_time >= AUTH_TIMEOUT) { | 418 if (now - ses.connect_time >= AUTH_TIMEOUT) { |
405 dropbear_close("Timeout before auth"); | 419 dropbear_close("Timeout before auth"); |
406 } | 420 } |
407 | 421 |
408 /* we can't rekey if we haven't done remote ident exchange yet */ | 422 /* we can't rekey if we haven't done remote ident exchange yet */ |
409 if (ses.remoteident == NULL) { | 423 if (ses.remoteident == NULL) { |
415 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) { | 429 || ses.kexstate.datarecv+ses.kexstate.datatrans >= KEX_REKEY_DATA)) { |
416 TRACE(("rekeying after timeout or max data reached")) | 430 TRACE(("rekeying after timeout or max data reached")) |
417 send_msg_kexinit(); | 431 send_msg_kexinit(); |
418 } | 432 } |
419 | 433 |
420 if (opts.keepalive_secs > 0 | 434 if (opts.keepalive_secs > 0) { |
421 && now - ses.last_trx_packet_time >= opts.keepalive_secs) { | 435 /* Send keepalives if we've been idle */ |
422 send_msg_ignore(); | 436 if (now - ses.last_packet_time_any_sent >= opts.keepalive_secs) { |
423 } | 437 send_msg_keepalive(); |
424 | 438 } |
425 if (opts.idle_timeout_secs > 0 && ses.last_packet_time > 0 | 439 |
426 && now - ses.last_packet_time >= opts.idle_timeout_secs) { | 440 /* Also send an explicit keepalive message to trigger a response |
441 if the remote end hasn't sent us anything */ | |
442 if (now - ses.last_packet_time_keepalive_recv >= opts.keepalive_secs | |
443 && now - ses.last_packet_time_keepalive_sent >= opts.keepalive_secs) { | |
444 send_msg_keepalive(); | |
445 } | |
446 | |
447 if (now - ses.last_packet_time_keepalive_recv | |
448 >= opts.keepalive_secs * DEFAULT_KEEPALIVE_LIMIT) { | |
449 dropbear_exit("Keepalive timeout"); | |
450 } | |
451 } | |
452 | |
453 if (opts.idle_timeout_secs > 0 | |
454 && now - ses.last_packet_time_idle >= opts.idle_timeout_secs) { | |
427 dropbear_close("Idle timeout"); | 455 dropbear_close("Idle timeout"); |
428 } | 456 } |
429 } | 457 } |
430 | 458 |
431 static long select_timeout() { | 459 static long select_timeout() { |