Restore ability to shutdown DGRAM sockets, still forcing ENOTCONN to be returned

by the shutdown(2) system call. This ability has been lost as part of the svn
revision 285910.

Reviewed by:	ed, rwatson, glebius, hiren
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D10351
This commit is contained in:
Maxim Sobolev 2017-04-14 17:23:28 +00:00
parent a7d94fcc3e
commit 63649db042
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=316874

View File

@ -2343,13 +2343,27 @@ int
soshutdown(struct socket *so, int how)
{
struct protosw *pr = so->so_proto;
int error;
int error, soerror_enotconn;
if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR))
return (EINVAL);
soerror_enotconn = 0;
if ((so->so_state &
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0)
return (ENOTCONN);
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
/*
* POSIX mandates us to return ENOTCONN when shutdown(2) is
* invoked on a datagram sockets, however historically we would
* actually tear socket down. This is known to be leveraged by
* some applications to unblock process waiting in recvXXX(2)
* by other process that it shares that socket with. Try to meet
* both backward-compatibility and POSIX requirements by forcing
* ENOTCONN but still asking protocol to perform pru_shutdown().
*/
if (so->so_type != SOCK_DGRAM)
return (ENOTCONN);
soerror_enotconn = 1;
}
CURVNET_SET(so->so_vnet);
if (pr->pr_usrreqs->pru_flush != NULL)
@ -2360,11 +2374,12 @@ soshutdown(struct socket *so, int how)
error = (*pr->pr_usrreqs->pru_shutdown)(so);
wakeup(&so->so_timeo);
CURVNET_RESTORE();
return (error);
return ((error == 0 && soerror_enotconn) ? ENOTCONN : error);
}
wakeup(&so->so_timeo);
CURVNET_RESTORE();
return (0);
return (soerror_enotconn ? ENOTCONN : 0);
}
void