FYI, the tcpdump I sent previously was with one of our previously-discussed patches in place:
if (!proxy->client_proxy && net_geterror(proxy->fd_ssl) == EBADF) {
I'm attaching that dump again (as tcpdump_output_witholdpatch_headeronly.txt), as well as a dump without any of the patches (tcpdump_output_withoutpatches_headeronly.txt) in case there is any difference.
On December 4, 2012 6:18:23 AM PST, Ben Morrow <ben@morrow.me.uk> wrote:
At 12PM +0000 on 4/12/12 Ben Morrow wrote:
Well, it looks to me as though xnu/bsd/kern/uipc_socket.c:soreceive will indeed return ENOTCONN for a socket which was once successfully connected but has now been disconnected. This happens when the socket is in the DEFUNCT state, which is a state that doesn't exist in FreeBSD; it's not completely clear but I suspect firewalls may be able to put arbitrary sockets into that state.
Investigating a little further, it should be possible to test for this situation directly. Assuming I'm correct about what's going on here, this should be both cleaner and safer than mucking about looking for ENOTCONN and guessing about what's happening.
Erik, does this make the problem go away? I left out the proxy->client_proxy test, since AFAICT this is just as likely to happen on a client socket.
Ben
#ifdef SO_ISDEFUNCT
if (getsockopt(proxy->fd_ssl, SOL_SOCKET, SO_ISDEFUNCT,
(void *)&err, sizeof(err)) == 0 && err) {
errstr = t_strdup_printf(
"%s: socket is defunct", func_name);
break;
+#endif}
Nope, SO_ISDEFUNCT isn't defined.