Bugzilla – Attachment 1331 Details for
Bug 1330
ControlPersist: fork and leave ControlMaster behind as a daemon
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Persist and idletimeout combined
openssh-4.6p1-idle+persist.patch.txt (text/plain), 15.26 KB, created by
Wout Mertens
on 2007-07-23 12:52:39 AEST
(
hide
)
Description:
Persist and idletimeout combined
Filename:
MIME Type:
Creator:
Wout Mertens
Created:
2007-07-23 12:52:39 AEST
Size:
15.26 KB
patch
obsolete
>diff -ru openssh-4.6p1-orig/clientloop.c openssh-4.6p1-idletimeout/clientloop.c >--- openssh-4.6p1-orig/clientloop.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/clientloop.c 2007-07-23 03:51:13.000000000 +0200 >@@ -482,7 +482,6 @@ > client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, > int *maxfdp, u_int *nallocp, int rekeying) > { >- struct timeval tv, *tvp; > int ret; > > /* Add any selections by the channel mechanism. */ >@@ -532,14 +531,8 @@ > * event pending. > */ > >- if (options.server_alive_interval == 0 || !compat20) >- tvp = NULL; >- else { >- tv.tv_sec = options.server_alive_interval; >- tv.tv_usec = 0; >- tvp = &tv; >- } >- ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); >+ ret = packet_select((*maxfdp)+1, *readsetp, *writesetp, NULL, >+ compat20 ? options.server_alive_interval : 0); > if (ret < 0) { > char buf[100]; > >@@ -557,8 +550,16 @@ > snprintf(buf, sizeof buf, "select: %s\r\n", strerror(errno)); > buffer_append(&stderr_buffer, buf, strlen(buf)); > quit_pending = 1; >- } else if (ret == 0) >- server_alive_check(); >+ } else if (ret == 0) { >+ if (packet_idle_timedout()) { >+ char buf[100]; >+ snprintf(buf, sizeof buf, "Idle timeout.\r\n"); >+ buffer_append(&stderr_buffer, buf, strlen(buf)); >+ quit_pending = 1; >+ } else { >+ server_alive_check(); >+ } >+ } > } > > static void >@@ -1343,8 +1344,13 @@ > client_channel_closed(int id, void *arg) > { > channel_cancel_cleanup(id); >- session_closed = 1; > leave_raw_mode(); >+ if (options.control_persist && options.control_path != NULL && control_fd != -1) { >+ packet_set_idle_timeout(options.control_timeout); >+ daemon(0,0); >+ return; >+ } >+ session_closed = 1; > } > > /* >diff -ru openssh-4.6p1-orig/packet.c openssh-4.6p1-idletimeout/packet.c >--- openssh-4.6p1-orig/packet.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/packet.c 2007-07-23 04:33:37.000000000 +0200 >@@ -161,6 +161,98 @@ > }; > TAILQ_HEAD(, packet) outgoing; > >+/* Idle timeout variables */ >+static time_t idletime_last=0; >+static int idle_timeout=0; >+ >+ >+void >+packet_set_idle_timeout(int max_idle_seconds) >+{ >+ debug("Setting idle timeout to %d", max_idle_seconds); >+ idle_timeout=max_idle_seconds; >+ if (max_idle_seconds>0) { >+ /* Initialize */ >+ time(&idletime_last); >+ } >+} >+ >+/* Called whenever packets are sent or received. >+ * This function decides which packets mean being idle */ >+void >+idle_timeout_check(int type) >+{ >+ /* No-op, if idle-timeouts are not configured */ >+ if (idle_timeout==0) return; >+ >+ /* The following packets reset the timeout on input or output. >+ * Note that only actual data resets timeout, control packets >+ * do not. */ >+ if (compat20) { >+ switch(type) { >+ case SSH2_MSG_CHANNEL_DATA: >+ case SSH2_MSG_CHANNEL_EXTENDED_DATA: >+ time(&idletime_last); >+ } >+ } else { >+ switch(type) { >+ case SSH_MSG_CHANNEL_DATA: >+ case SSH_CMSG_STDIN_DATA: >+ case SSH_SMSG_STDOUT_DATA: >+ case SSH_SMSG_STDERR_DATA: >+ time(&idletime_last); >+ } >+ } >+} >+ >+/* Check if idle timeout occurred */ >+int >+packet_idle_timedout() >+{ >+ return (idle_timeout == -2); >+} >+ >+/* This function combines the regular select() call with timeout >+ * semantics */ >+int >+packet_select(int maxfds, >+ fd_set *readset, fd_set *writeset, fd_set *exceptset, >+ int max_time_milliseconds) >+{ >+ struct timeval tv, *tvp=NULL; >+ int milliseconds_to_idle=0; >+ int ret; >+ >+ if (idle_timeout>0) { >+ /* Count the time to idle_timeout */ >+ time_t diff=time(NULL)-idletime_last; >+ if (diff>=idle_timeout) >+ milliseconds_to_idle=100; >+ else >+ milliseconds_to_idle=(idle_timeout-diff)*1000; >+ } >+ /* If a timeout value was given and the timeout happens before >+ * idle_timeout, use it */ >+ if (max_time_milliseconds > 0 || milliseconds_to_idle > 0) { >+ if (max_time_milliseconds > 0 && >+ max_time_milliseconds < milliseconds_to_idle) { >+ milliseconds_to_idle = 0; >+ } else { >+ max_time_milliseconds = milliseconds_to_idle; >+ } >+ tv.tv_sec = max_time_milliseconds / 1000; >+ tv.tv_usec = 1000 * (max_time_milliseconds % 1000); >+ tvp = &tv; >+ } >+ >+ ret = select( maxfds, readset, writeset, exceptset, tvp ); >+ >+ /* Disconnect on idle_timeout */ >+ if (milliseconds_to_idle > 0 && ret == 0) { >+ idle_timeout=-2; >+ } >+ return ret; >+} > /* > * Sets the descriptors used for communication. Disables encryption until > * packet_set_encryption_key is called. >@@ -472,6 +564,9 @@ > int len; > > DBG(debug("packet_start[%d]", type)); >+ >+ idle_timeout_check(type); >+ > len = compat20 ? 6 : 9; > memset(buf, 0, len - 1); > buf[len - 1] = type; >@@ -912,21 +1007,27 @@ > /* If we got a packet, return it. */ > if (type != SSH_MSG_NONE) { > xfree(setp); >+ idle_timeout_check(type); > return type; > } > /* > * Otherwise, wait for some data to arrive, add it to the > * buffer, and try again. > */ >- memset(setp, 0, howmany(connection_in + 1, NFDBITS) * >- sizeof(fd_mask)); >- FD_SET(connection_in, setp); >- >- /* Wait for some data to arrive. */ >- while (select(connection_in + 1, setp, NULL, NULL, NULL) == -1 && >- (errno == EAGAIN || errno == EINTR)) >+ do { >+ memset(setp, 0, howmany(connection_in + 1, NFDBITS) * >+ sizeof(fd_mask)); >+ FD_SET(connection_in, setp); >+ >+ /* Wait for some data to arrive. */ >+ } while (packet_select(connection_in + 1, >+ setp, NULL, NULL, 0) == -1 && >+ (errno == EAGAIN || errno == EINTR)) > ; >- >+ if (packet_idle_timedout()) { >+ logit("Idle timeout"); >+ cleanup_exit(255); >+ } > /* Read data from the socket. */ > len = read(connection_in, buf, sizeof(buf)); > if (len == 0) { >@@ -1446,12 +1547,18 @@ > sizeof(fd_mask)); > packet_write_poll(); > while (packet_have_data_to_write()) { >- memset(setp, 0, howmany(connection_out + 1, NFDBITS) * >- sizeof(fd_mask)); >- FD_SET(connection_out, setp); >- while (select(connection_out + 1, NULL, setp, NULL, NULL) == -1 && >- (errno == EAGAIN || errno == EINTR)) >+ do { >+ memset(setp, 0, howmany(connection_out + 1, NFDBITS) * >+ sizeof(fd_mask)); >+ FD_SET(connection_out, setp); >+ } while (packet_select(connection_out + 1, >+ NULL, setp, NULL, 0) == -1 && >+ (errno == EAGAIN || errno == EINTR)) > ; >+ if (packet_idle_timedout()) { >+ logit("Idle timeout"); >+ cleanup_exit(255); >+ } > packet_write_poll(); > } > xfree(setp); >diff -ru openssh-4.6p1-orig/packet.h openssh-4.6p1-idletimeout/packet.h >--- openssh-4.6p1-orig/packet.h 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/packet.h 2007-07-23 03:32:56.000000000 +0200 >@@ -103,4 +103,23 @@ > int packet_need_rekeying(void); > void packet_set_rekey_limit(u_int32_t); > >+/* This sets the maximum idle time before packet_select() automatically >+ * disconnects with packet_disconnect("Idletimeout"). >+ * Never autodisconnects if set to zero. zero is the default */ >+void packet_set_idle_timeout(int max_idle_seconds); >+ >+/* This checks if an idle timeout occurred */ >+int packet_idle_timedout(void); >+ >+/* This is an quite normal select, except that it implements idle_timeouts >+ * set with packet_set_idle_timeout(). >+ * It also returns exits, if select() returns any other error than AGAIN >+ * or EINTR. So if packet_select returns -1, you can safely reinit fd_sets >+ * and call packet_select again, without checking errno. >+ */ >+int packet_select(int maxfds, >+ fd_set *readset, fd_set *writeset, fd_set *exceptset, >+ int max_time_milliseconds); >+ >+ > #endif /* PACKET_H */ >diff -ru openssh-4.6p1-orig/readconf.c openssh-4.6p1-idletimeout/readconf.c >--- openssh-4.6p1-orig/readconf.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/readconf.c 2007-07-20 21:35:15.000000000 +0200 >@@ -128,9 +128,9 @@ > oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, > oAddressFamily, oGssAuthentication, oGssDelegateCreds, > oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, >- oSendEnv, oControlPath, oControlMaster, oHashKnownHosts, >+ oSendEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, > oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand, >- oDeprecated, oUnsupported >+ oControlTimeout, oIdleTimeout, oDeprecated, oUnsupported > } OpCodes; > > /* Textual representations of the tokens. */ >@@ -221,11 +221,14 @@ > { "sendenv", oSendEnv }, > { "controlpath", oControlPath }, > { "controlmaster", oControlMaster }, >+ { "controlpersist", oControlPersist }, >+ { "controltimeout", oControlTimeout }, > { "hashknownhosts", oHashKnownHosts }, > { "tunnel", oTunnel }, > { "tunneldevice", oTunnelDevice }, > { "localcommand", oLocalCommand }, > { "permitlocalcommand", oPermitLocalCommand }, >+ { "idletimeout", oIdleTimeout }, > { NULL, oBadOption } > }; > >@@ -868,6 +871,14 @@ > *intptr = value; > break; > >+ case oControlPersist: >+ intptr = &options->control_persist; >+ goto parse_flag; >+ >+ case oControlTimeout: >+ intptr = &options->control_timeout; >+ goto parse_time; >+ > case oHashKnownHosts: > intptr = &options->hash_known_hosts; > goto parse_flag; >@@ -915,6 +926,10 @@ > intptr = &options->permit_local_command; > goto parse_flag; > >+ case oIdleTimeout: >+ intptr = &options->idle_timeout; >+ goto parse_time; >+ > case oDeprecated: > debug("%s line %d: Deprecated option \"%s\"", > filename, linenum, keyword); >@@ -1059,12 +1074,15 @@ > options->num_send_env = 0; > options->control_path = NULL; > options->control_master = -1; >+ options->control_persist = -1; >+ options->control_timeout = -1; > options->hash_known_hosts = -1; > options->tun_open = -1; > options->tun_local = -1; > options->tun_remote = -1; > options->local_command = NULL; > options->permit_local_command = -1; >+ options->idle_timeout = -1; > } > > /* >@@ -1189,6 +1207,10 @@ > options->server_alive_count_max = 3; > if (options->control_master == -1) > options->control_master = 0; >+ if (options->control_persist == -1) >+ options->control_persist = 0; >+ if (options->control_timeout == -1) >+ options->control_timeout = 0; > if (options->hash_known_hosts == -1) > options->hash_known_hosts = 0; > if (options->tun_open == -1) >@@ -1199,6 +1221,8 @@ > options->tun_remote = SSH_TUNID_ANY; > if (options->permit_local_command == -1) > options->permit_local_command = 0; >+ if (options->idle_timeout == -1) >+ options->idle_timeout = 0; > /* options->local_command should not be set by default */ > /* options->proxy_command should not be set by default */ > /* options->user will be set in the main program if appropriate */ >diff -ru openssh-4.6p1-orig/readconf.h openssh-4.6p1-idletimeout/readconf.h >--- openssh-4.6p1-orig/readconf.h 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/readconf.h 2007-07-20 21:28:54.000000000 +0200 >@@ -111,6 +111,7 @@ > > char *control_path; > int control_master; >+ int control_persist; > > int hash_known_hosts; > >@@ -121,6 +122,12 @@ > char *local_command; > int permit_local_command; > >+ int idle_timeout; /* >+ * If nonzero, the number of seconds >+ * after which idle connections >+ * will be terminated >+ */ >+ int control_timeout; /* Same, for master connections */ > } Options; > > #define SSHCTL_MASTER_NO 0 >diff -ru openssh-4.6p1-orig/servconf.c openssh-4.6p1-idletimeout/servconf.c >--- openssh-4.6p1-orig/servconf.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/servconf.c 2007-07-20 21:30:16.000000000 +0200 >@@ -122,6 +122,7 @@ > options->permit_tun = -1; > options->num_permitted_opens = -1; > options->adm_forced_command = NULL; >+ options->idle_timeout = -1; > } > > void >@@ -262,6 +263,8 @@ > options->compression = 0; > } > #endif >+ if (options->idle_timeout == -1) >+ options->idle_timeout=0; > > } > >@@ -293,7 +296,7 @@ > sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, > sMatch, sPermitOpen, sForceCommand, > sUsePrivilegeSeparation, >- sDeprecated, sUnsupported >+ sIdleTimeout, sDeprecated, sUnsupported > } ServerOpCodes; > > #define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ >@@ -403,6 +406,7 @@ > { "match", sMatch, SSHCFG_ALL }, > { "permitopen", sPermitOpen, SSHCFG_ALL }, > { "forcecommand", sForceCommand, SSHCFG_ALL }, >+ { "idletimeout", sIdleTimeout, SSHCFG_ALL }, > { NULL, sBadOption, 0 } > }; > >@@ -1254,6 +1258,10 @@ > options->adm_forced_command = xstrdup(cp + len); > return 0; > >+ case sIdleTimeout: >+ intptr = &options->idle_timeout; >+ goto parse_time; >+ > case sDeprecated: > logit("%s line %d: Deprecated option %s", > filename, linenum, arg); >diff -ru openssh-4.6p1-orig/servconf.h openssh-4.6p1-idletimeout/servconf.h >--- openssh-4.6p1-orig/servconf.h 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/servconf.h 2007-07-20 21:28:54.000000000 +0200 >@@ -141,6 +141,11 @@ > int permit_tun; > > int num_permitted_opens; >+ int idle_timeout; /* >+ * If nonzero, the number of second >+ * after which idle connections >+ * will be terminated >+ */ > } ServerOptions; > > void initialize_server_options(ServerOptions *); >diff -ru openssh-4.6p1-orig/serverloop.c openssh-4.6p1-idletimeout/serverloop.c >--- openssh-4.6p1-orig/serverloop.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/serverloop.c 2007-07-23 03:31:24.000000000 +0200 >@@ -277,7 +277,6 @@ > wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp, > u_int *nallocp, u_int max_time_milliseconds) > { >- struct timeval tv, *tvp; > int ret; > int client_alive_scheduled = 0; > int program_alive_scheduled = 0; >@@ -348,25 +347,23 @@ > if (max_time_milliseconds == 0 || client_alive_scheduled) > max_time_milliseconds = 100; > >- if (max_time_milliseconds == 0) >- tvp = NULL; >- else { >- tv.tv_sec = max_time_milliseconds / 1000; >- tv.tv_usec = 1000 * (max_time_milliseconds % 1000); >- tvp = &tv; >- } >- >- /* Wait for something to happen, or the timeout to expire. */ >- ret = select((*maxfdp)+1, *readsetp, *writesetp, NULL, tvp); >+ /* Wait for something to happen, or the timeout to expire. >+ * packet select also implements server idle_timeouts for us. */ >+ ret = packet_select((*maxfdp)+1, *readsetp, *writesetp, NULL, >+ max_time_milliseconds); > > if (ret == -1) { > memset(*readsetp, 0, *nallocp); > memset(*writesetp, 0, *nallocp); >- if (errno != EINTR) >- error("select: %.100s", strerror(errno)); > } else { >- if (ret == 0 && client_alive_scheduled) >- client_alive_check(); >+ if (ret == 0) { >+ if (client_alive_scheduled) >+ client_alive_check(); >+ else if (packet_idle_timedout()) { >+ logit("Idle timeout."); >+ cleanup_exit(255); >+ } >+ } > if (!compat20 && program_alive_scheduled && fdin_is_tty) { > if (!fdout_eof) > FD_SET(fdout, *readsetp); >diff -ru openssh-4.6p1-orig/session.c openssh-4.6p1-idletimeout/session.c >--- openssh-4.6p1-orig/session.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/session.c 2007-07-20 21:28:54.000000000 +0200 >@@ -238,6 +238,8 @@ > if (!no_port_forwarding_flag && options.allow_tcp_forwarding) > channel_permit_all_opens(); > >+ packet_set_idle_timeout(options.idle_timeout); >+ > if (compat20) > do_authenticated2(authctxt); > else >diff -ru openssh-4.6p1-orig/sshconnect.c openssh-4.6p1-idletimeout/sshconnect.c >--- openssh-4.6p1-orig/sshconnect.c 2007-07-10 12:48:22.000000000 +0200 >+++ openssh-4.6p1-idletimeout/sshconnect.c 2007-07-20 21:28:54.000000000 +0200 >@@ -973,6 +973,7 @@ > ssh_userauth1(local_user, server_user, host, sensitive); > } > xfree(local_user); >+ packet_set_idle_timeout(options.idle_timeout); > } > > void
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 1330
:
1319
|
1322
|
1331
|
1338
|
1605
|
1858
|
1897