dale at accentre.com
2001-Jan-12 20:22 UTC
Socket options not properly set for ssh and sshd.
I mentioned this problem in a previous post (in November). This time I'm including a patch. Version: OpenSSH_2.3.0p1 Keywords: setsockopt keepalive hang masquerade interactive Symptom: For protocol 2, socket options (especially keepalive) are not being properly set for OpenSSH_2.3.0p1, even when request in the config files. Furthermore (for either protocol), keepalive is only set for "interactive" connections -- it should be set (when requested) for any sort of connection. ----------------------- As an aside (as information for anyone else with the same problem), I need keepalives to keep my connections from hanging after thirty minutes due to an ISP (Cox at work) router that is masquerading IP addresses for my local network. This router apparently drops the masquerade table entries after 30 minutes of inactivity. (Then, in response to any further activity from the client it just sends TCP resets, which generally leaves the connected incarnation of sshd hung until killed). My solution to that problem is to change the default keepalive time on my Linux system from 120 minutes to 20 minutes (1200 seconds) via echo 1200 > /proc/sys/net/ipv4/tcp_keepalive_time and then depend on sshd keepalives to avoid inactivity. --- sv0/packet.c Fri Oct 13 22:23:12 2000 +++ packet.c Tue Jan 2 16:40:45 2001 @@ -1225,7 +1225,7 @@ /* Informs that the current session is interactive. Sets IP flags for that. */ void -packet_set_interactive(int interactive, int keepalives) +packet_set_interactive(int interactive) { int on = 1; @@ -1235,12 +1235,7 @@ /* Only set socket options if using a socket. */ if (!packet_connection_is_on_socket()) return; - if (keepalives) { - /* Set keepalives if requested. */ - if (setsockopt(connection_in, SOL_SOCKET, SO_KEEPALIVE, (void *) &on, - sizeof(on)) < 0) - error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); - } + /* * IPTOS_LOWDELAY, TCP_NODELAY and IPTOS_THROUGHPUT are IPv4 only */ --- sv0/packet.h Fri Sep 15 19:29:09 2000 +++ packet.h Tue Jan 2 16:40:45 2001 @@ -65,7 +65,7 @@ * Informs that the current session is interactive. Sets IP flags for * optimal performance in interactive use. */ -void packet_set_interactive(int interactive, int keepalives); +void packet_set_interactive(int interactive); /* Returns true if the current connection is interactive. */ int packet_is_interactive(void); --- sv0/session.c Fri Oct 27 20:19:58 2000 +++ session.c Tue Jan 2 16:40:45 2001 @@ -405,8 +405,7 @@ case SSH_CMSG_EXEC_SHELL: case SSH_CMSG_EXEC_CMD: /* Set interactive/non-interactive mode. */ - packet_set_interactive(have_pty || s->display != NULL, - options.keepalives); + packet_set_interactive(have_pty || s->display != NULL); if (type == SSH_CMSG_EXEC_CMD) { command = packet_get_string(&dlen); --- sv0/ssh.c Fri Oct 27 20:19:58 2000 +++ ssh.c Tue Jan 2 16:42:51 2001 @@ -843,7 +843,7 @@ } } /* Tell the packet module whether this is an interactive session. */ - packet_set_interactive(interactive, options.keepalives); + packet_set_interactive(interactive); /* Clear agent forwarding if we don\'t have an agent. */ authfd = ssh_get_authentication_socket(); --- sv0/sshconnect.c Fri Sep 22 23:15:57 2000 +++ sshconnect.c Tue Jan 2 16:40:45 2001 @@ -304,6 +304,15 @@ linger.l_linger = 5; setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); + if (options.keepalives) { + static const int on = 1; + + /* Set keepalives if requested. */ + if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *) &on, + sizeof(on)) < 0) + error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); + } + /* Set the connection. */ packet_set_connection(sock, sock); --- sv0/sshd.c Fri Oct 13 22:23:13 2000 +++ sshd.c Tue Jan 2 16:42:57 2001 @@ -1014,6 +1014,13 @@ linger.l_linger = 5; setsockopt(sock_in, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger)); + if (options.keepalives) { + /* Set keepalives if requested. */ + if (setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, (void *) &on, + sizeof(on)) < 0) + error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); + } + /* * Register our connection. This turns encryption off because we do * not have a key.