]> andersk Git - openssh.git/blobdiff - serverloop.c
- beck@cvs.openbsd.org 2001/04/13 22:46:54
[openssh.git] / serverloop.c
index d6b360d9adc499f1177604c15e1adfacf7487f21..5a5b1e37fa0d184a1a57fdb62333846b449858b4 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: serverloop.c,v 1.60 2001/04/05 23:39:20 markus Exp $");
+RCSID("$OpenBSD: serverloop.c,v 1.61 2001/04/13 22:46:54 beck Exp $");
 
 #include "xmalloc.h"
 #include "packet.h"
@@ -91,6 +91,8 @@ static volatile int child_wait_status;        /* Status from wait(). */
 
 void   server_init_dispatch(void);
 
+int client_alive_timeouts = 0;
+
 void
 sigchld_handler(int sig)
 {
@@ -190,6 +192,21 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
 {
        struct timeval tv, *tvp;
        int ret;
+       int client_alive_scheduled = 0;
+
+       /*
+        * if using client_alive, set the max timeout accordingly, 
+        * and indicate that this particular timeout was for client
+        * alive by setting the client_alive_scheduled flag.
+        *
+        * this could be randomized somewhat to make traffic
+        * analysis more difficult, but we're not doing it yet.  
+        */
+       if (max_time_milliseconds == 0 && options.client_alive_interval) {
+               client_alive_scheduled = 1;
+               max_time_milliseconds = options.client_alive_interval * 1000;
+       } else 
+               client_alive_scheduled = 0;
 
        /* When select fails we restart from here. */
 retry_select:
@@ -239,7 +256,7 @@ retry_select:
         * from it, then read as much as is available and exit.
         */
        if (child_terminated && packet_not_very_much_data_to_write())
-               if (max_time_milliseconds == 0)
+               if (max_time_milliseconds == 0 || client_alive_scheduled)
                        max_time_milliseconds = 100;
 
        if (max_time_milliseconds == 0)
@@ -255,12 +272,36 @@ retry_select:
        /* Wait for something to happen, or the timeout to expire. */
        ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp);
 
-       if (ret < 0) {
+       if (ret == -1) {
                if (errno != EINTR)
                        error("select: %.100s", strerror(errno));
                else
                        goto retry_select;
        }
+       if (ret == 0 && client_alive_scheduled) {
+               /* timeout, check to see how many we have had */
+               client_alive_timeouts++;
+
+               if (client_alive_timeouts > options.client_alive_count_max ) {
+                       packet_disconnect(
+                               "Timeout, your session not responding.");
+               } else {
+                       /*
+                        * send a bogus channel request with "wantreply" 
+                        * we should get back a failure
+                        */
+                       int id;
+                       
+                       id = channel_find_open();
+                       if (id != -1) {
+                               channel_request_start(id,
+                                 "keepalive@openssh.com", 1);
+                               packet_send();
+                       } else 
+                               packet_disconnect(
+                                       "No open channels after timeout!");
+               }
+       } 
 }
 
 /*
@@ -700,6 +741,19 @@ server_loop2(void)
        channel_stop_listening();
 }
 
+void
+server_input_channel_failure(int type, int plen, void *ctxt)
+{
+       debug("Got CHANNEL_FAILURE for keepalive");
+       /* 
+         * reset timeout, since we got a sane answer from the client.
+        * even if this was generated by something other than
+        * the bogus CHANNEL_REQUEST we send for keepalives.
+        */
+       client_alive_timeouts = 0; 
+}
+
+
 void
 server_input_stdin_data(int type, int plen, void *ctxt)
 {
@@ -912,7 +966,8 @@ server_init_dispatch_20(void)
        dispatch_set(SSH2_MSG_CHANNEL_REQUEST, &channel_input_channel_request);
        dispatch_set(SSH2_MSG_CHANNEL_WINDOW_ADJUST, &channel_input_window_adjust);
        dispatch_set(SSH2_MSG_GLOBAL_REQUEST, &server_input_global_request);
-
+       /* client_alive */
+       dispatch_set(SSH2_MSG_CHANNEL_FAILURE, &server_input_channel_failure);
        /* rekeying */
        dispatch_set(SSH2_MSG_KEXINIT, &kex_input_kexinit);
 }
@@ -949,3 +1004,4 @@ server_init_dispatch(void)
        else
                server_init_dispatch_15();
 }
+
This page took 0.068014 seconds and 4 git commands to generate.