For me this patch (against 1.2.26) fixes the problem of lingering forwarded agent connections which prevents ssh from terminating. A simple example of the problem: $ ssh SOME_HOSTNAME_HERE ssh-add -l SOME_KEY_OUTPUT_HERE Waiting for forwarded connections to terminate... The following connections are open: Forwarded agent connection The reason for this problem has to do with how ssh tries to gracefully close a forwarded connection by shutting down the two directions individually. On some systems a shutdown() on a unix-domain socket will not be detected at the other end. An example of a system where shutdown() is not detected is HP-UX 10.20. Linux is an example of a system where it is detected. It only matters what system you run ssh on, not what system you are connecting to. A forwarded agent connection won't terminate if the agent never receives the EOF indication on its input which the shutdown() should have caused. To work around this we tear down the entire connection on unix-domain sockets rather than just shutting-down half of the socket. This replaces the is_x_connection check and fixes both that problem and the lingering authentication sockets problem (they are the same problem if I understand correctly). Currently we assume all systems fail to detect shutdown()s on AF_UNIX sockets. Eventually the configure script should decide if this is needed on a given system. Paul H. Hargrove [EMAIL PROTECTED] --- ssh-1.2.26/ssh.h.orig Wed Jul 8 09:40:38 1998 +++ ssh-1.2.26/ssh.h Fri Apr 9 18:39:04 1999 @@ -656,7 +656,7 @@ /* Allocate a new channel object and set its type and socket. Remote_name must have been allocated with xmalloc; this will free it when the channel is freed. */ -int channel_allocate(int type, int sock, char *remote_name); +int channel_allocate(int type, int sock, char *remote_name, int family); /* Free the channel and close its socket. */ void channel_free(int channel); --- ssh-1.2.26/newchannels.c.orig Thu Apr 8 17:58:50 1999 +++ ssh-1.2.26/newchannels.c Fri Apr 9 18:35:41 1999 @@ -325,7 +325,7 @@ int listening_port; /* port being listened for forwards */ char *remote_name; - int is_x_connection; + int family; } Channel; /* Pointer to an array containing all allocated channels. The array is @@ -436,7 +436,7 @@ /* Allocate a new channel object and set its type and socket. This will cause remote_name to be freed. */ -int channel_allocate(int type, int sock, char *remote_name) +int channel_allocate(int type, int sock, char *remote_name, int family) { int i; @@ -487,9 +487,10 @@ channels[i].remote_name = remote_name; channels[i].status_flags = 0; channels[i].local_id = i; - channels[i].is_x_connection = 0; + channels[i].family = family; channels_used++; debug("Allocated channel %d of type %d.", i, type); + debug("Channel %d linked to socket of addr family %d.", i, family); return i; } i++; @@ -657,11 +658,14 @@ debug("Channel %d receives input eof.", ch->local_id); ch->status_flags |= STATUS_EOF_RECEIVED; - if (ch->is_x_connection) +#ifndef SHUTDOWN_WORKS_ON_AF_UNIX_SOCKETS + if (ch->family == AF_UNIX) { - debug("X problem fix: close the other direction."); + debug("Channel %d forcing close of input on AF_UNIX socket.", + ch->local_id); channel_close_input(ch); } +#endif if (ch->type != SSH_CHANNEL_OPEN) channel_close_output(ch); channel_check_termination(ch); @@ -945,8 +949,7 @@ } #endif /* LIBWRAP */ newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, - xstrdup(buf)); - channels[newch].is_x_connection = 1; + xstrdup(buf), ch->family); packet_start(SSH_SMSG_X11_OPEN); packet_put_int(newch); if (have_hostname_in_open) @@ -1011,7 +1014,7 @@ } #endif /* LIBWRAP */ newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, - xstrdup(buf)); + xstrdup(buf), ch->family); packet_start(SSH_MSG_PORT_OPEN); packet_put_int(newch); packet_put_string(ch->path, strlen(ch->path)); @@ -1037,7 +1040,7 @@ } sprintf(buf, "Forwarded agent connection"); newch = channel_allocate(SSH_CHANNEL_OPENING, newsock, - xstrdup(buf)); + xstrdup(buf), ch->family); packet_start(SSH_SMSG_AGENT_OPEN); packet_put_int(newch); packet_send(); @@ -1429,7 +1432,7 @@ /* Allocate a channel number for the socket. */ ch = channel_allocate(SSH_CHANNEL_PORT_LISTENER, sock, - xstrdup("port listener")); + xstrdup("port listener"), AF_INET); strcpy(channels[ch].path, host); /* note: host name stored here */ channels[ch].host_port = host_port; /* port on host to connect to */ channels[ch].listening_port = port; /* port being listened */ @@ -1755,7 +1758,8 @@ #endif /* O_NONBLOCK && !O_NONBLOCK_BROKEN */ /* Allocate a channel for this connection. */ - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, originator_string); + newch = channel_allocate(SSH_CHANNEL_OPEN, sock, + originator_string, sin.sin_family); channels[newch].remote_id = remote_channel; /* Send a confirmation to the remote host. */ @@ -1883,7 +1887,7 @@ /* Allocate a channel for the socket. */ (void)channel_allocate(SSH_CHANNEL_X11_LISTENER, sock, - xstrdup("X11 inet listener")); + xstrdup("X11 inet listener"), AF_INET); /* Return a suitable value for the DISPLAY environment variable. */ return xstrdup(buf); @@ -1895,7 +1899,7 @@ void x11_input_open(void) { - int remote_channel, display_number, sock, newch; + int remote_channel, display_number, sock, newch, family; const char *display; struct sockaddr_un ssun; struct sockaddr_in sin; @@ -1945,6 +1949,7 @@ goto fail; } /* Create a socket. */ + family = AF_UNIX; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { @@ -2072,6 +2077,7 @@ sin.sin_port = htons(6000 + display_number); /* Create a socket. */ + family = sin.sin_family; sock = socket(sin.sin_family, SOCK_STREAM, 0); if (sock < 0) { @@ -2098,10 +2104,9 @@ /* Allocate a channel for this connection. */ if (x11_saved_proto == NULL) - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host); + newch = channel_allocate(SSH_CHANNEL_OPEN, sock, remote_host, family); else - newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host); - channels[newch].is_x_connection = 1; + newch = channel_allocate(SSH_CHANNEL_X11_OPEN, sock, remote_host, family); channels[newch].remote_id = remote_channel; debug("Sending open confirmation to the remote host."); @@ -2409,7 +2414,7 @@ /* Allocate a channel for the authentication agent socket. */ newch = channel_allocate(SSH_CHANNEL_AUTH_LISTENER, sock, - xstrdup("auth socket")); + xstrdup("auth socket"), AF_UNIX); strcpy(channels[newch].path, channel_forwarded_auth_socket_name); return 1; } @@ -2454,7 +2459,7 @@ dummyname = xstrdup("authentication agent connection"); /* Allocate a channel for this connection. */ - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname); + newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname, AF_UNIX); channels[newch].remote_id = remote_channel; /* Send a confirmation to the remote host. */ -- Paul H. Hargrove All material not otherwise attributed [EMAIL PROTECTED] is the opinion of the author or a typo.