diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1464,7 +1464,8 @@ INP_WLOCK_ASSERT(inp); if (__predict_false((so->so_state & - (SS_ISCONNECTING | SS_ISCONNECTED)) != 0)) + (SS_ISCONNECTING | SS_ISCONNECTED | SS_ISDISCONNECTING | + SS_ISDISCONNECTED)) != 0)) return (EISCONN); INP_HASH_WLOCK(&V_tcbinfo); diff --git a/tests/sys/netinet/socket_afinet.c b/tests/sys/netinet/socket_afinet.c --- a/tests/sys/netinet/socket_afinet.c +++ b/tests/sys/netinet/socket_afinet.c @@ -28,9 +28,9 @@ #include __FBSDID("$FreeBSD$"); -#include #include #include +#include #include #include @@ -228,14 +228,57 @@ close(ss); } -ATF_TP_ADD_TCS(tp) +ATF_TC_WITHOUT_HEAD(socket_afinet_stream_reconnect); +ATF_TC_BODY(socket_afinet_stream_reconnect, tc) { + struct sockaddr_in sin; + int ss, cs, rc; + + /* + * Make sure that an attempt to connect(2) a connected or disconnected + * stream socket fails with EISCONN. + */ + /* Server setup. */ + ss = socket(PF_INET, SOCK_STREAM, 0); + ATF_CHECK(ss >= 0); + bzero(&sin, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_len = sizeof(sin); + sin.sin_port = htons(6666); + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + rc = bind(ss, (struct sockaddr *)&sin, sizeof(sin)); + ATF_CHECK_EQ(0, rc); + rc = listen(ss, 1); + ATF_CHECK_EQ(0, rc); + + /* Client connects, shuts down. */ + cs = socket(PF_INET, SOCK_STREAM, 0); + ATF_CHECK(cs >= 0); + rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); + ATF_CHECK_EQ(0, rc); + rc = shutdown(cs, SHUT_RDWR); + ATF_CHECK_EQ(0, rc); + + /* A subsequent connect(2) fails with EISCONN. */ + rc = connect(cs, (struct sockaddr *)&sin, sizeof(sin)); + ATF_CHECK_EQ(-1, rc); + ATF_CHECK_EQ(errno, EISCONN); + + rc = close(cs); + ATF_CHECK_EQ(0, rc); + rc = close(ss); + ATF_CHECK_EQ(0, rc); +} + +ATF_TP_ADD_TCS(tp) +{ ATF_TP_ADD_TC(tp, socket_afinet); ATF_TP_ADD_TC(tp, socket_afinet_bind_zero); ATF_TP_ADD_TC(tp, socket_afinet_bind_ok); ATF_TP_ADD_TC(tp, socket_afinet_poll_no_rdhup); ATF_TP_ADD_TC(tp, socket_afinet_poll_rdhup); + ATF_TP_ADD_TC(tp, socket_afinet_stream_reconnect); return atf_no_error(); }