summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c64
1 files changed, 60 insertions, 4 deletions
diff --git a/serverloop.c b/serverloop.c
index d6b360d9a..5a5b1e37f 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: serverloop.c,v 1.60 2001/04/05 23:39:20 markus Exp $"); 38RCSID("$OpenBSD: serverloop.c,v 1.61 2001/04/13 22:46:54 beck Exp $");
39 39
40#include "xmalloc.h" 40#include "xmalloc.h"
41#include "packet.h" 41#include "packet.h"
@@ -91,6 +91,8 @@ static volatile int child_wait_status; /* Status from wait(). */
91 91
92void server_init_dispatch(void); 92void server_init_dispatch(void);
93 93
94int client_alive_timeouts = 0;
95
94void 96void
95sigchld_handler(int sig) 97sigchld_handler(int sig)
96{ 98{
@@ -190,6 +192,21 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
190{ 192{
191 struct timeval tv, *tvp; 193 struct timeval tv, *tvp;
192 int ret; 194 int ret;
195 int client_alive_scheduled = 0;
196
197 /*
198 * if using client_alive, set the max timeout accordingly,
199 * and indicate that this particular timeout was for client
200 * alive by setting the client_alive_scheduled flag.
201 *
202 * this could be randomized somewhat to make traffic
203 * analysis more difficult, but we're not doing it yet.
204 */
205 if (max_time_milliseconds == 0 && options.client_alive_interval) {
206 client_alive_scheduled = 1;
207 max_time_milliseconds = options.client_alive_interval * 1000;
208 } else
209 client_alive_scheduled = 0;
193 210
194 /* When select fails we restart from here. */ 211 /* When select fails we restart from here. */
195retry_select: 212retry_select:
@@ -239,7 +256,7 @@ retry_select:
239 * from it, then read as much as is available and exit. 256 * from it, then read as much as is available and exit.
240 */ 257 */
241 if (child_terminated && packet_not_very_much_data_to_write()) 258 if (child_terminated && packet_not_very_much_data_to_write())
242 if (max_time_milliseconds == 0) 259 if (max_time_milliseconds == 0 || client_alive_scheduled)
243 max_time_milliseconds = 100; 260 max_time_milliseconds = 100;
244 261
245 if (max_time_milliseconds == 0) 262 if (max_time_milliseconds == 0)
@@ -255,12 +272,36 @@ retry_select:
255 /* Wait for something to happen, or the timeout to expire. */ 272 /* Wait for something to happen, or the timeout to expire. */
256 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); 273 ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
257 274
258 if (ret < 0) { 275 if (ret == -1) {
259 if (errno != EINTR) 276 if (errno != EINTR)
260 error("select: %.100s", strerror(errno)); 277 error("select: %.100s", strerror(errno));
261 else 278 else
262 goto retry_select; 279 goto retry_select;
263 } 280 }
281 if (ret == 0 && client_alive_scheduled) {
282 /* timeout, check to see how many we have had */
283 client_alive_timeouts++;
284
285 if (client_alive_timeouts > options.client_alive_count_max ) {
286 packet_disconnect(
287 "Timeout, your session not responding.");
288 } else {
289 /*
290 * send a bogus channel request with "wantreply"
291 * we should get back a failure
292 */
293 int id;
294
295 id = channel_find_open();
296 if (id != -1) {
297 channel_request_start(id,
298 "keepalive@openssh.com", 1);
299 packet_send();
300 } else
301 packet_disconnect(
302 "No open channels after timeout!");
303 }
304 }
264} 305}
265 306
266/* 307/*
@@ -701,6 +742,19 @@ server_loop2(void)
701} 742}
702 743
703void 744void
745server_input_channel_failure(int type, int plen, void *ctxt)
746{
747 debug("Got CHANNEL_FAILURE for keepalive");
748 /*
749 * reset timeout, since we got a sane answer from the client.
750 * even if this was generated by something other than
751 * the bogus CHANNEL_REQUEST we send for keepalives.
752 */
753 client_alive_timeouts = 0;
754}
755
756
757void
704server_input_stdin_data(int type, int plen, void *ctxt) 758server_input_stdin_data(int type, int plen, void *ctxt)
705{ 759{
706 char *data; 760 char *data;
@@ -912,7 +966,8 @@ server_init_dispatch_20(void)
912 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request); 966 dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
913 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust); 967 dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
914 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request); 968 dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
915 969 /* client_alive */
970 dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure);
916 /* rekeying */ 971 /* rekeying */
917 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit); 972 dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
918} 973}
@@ -949,3 +1004,4 @@ server_init_dispatch(void)
949 else 1004 else
950 server_init_dispatch_15(); 1005 server_init_dispatch_15();
951} 1006}
1007