Changeset View
Changeset View
Standalone View
Standalone View
head/sys/kern/uipc_socket.c
Show First 20 Lines • Show All 2,337 Lines • ▼ Show 20 Lines | soreceive(struct socket *so, struct sockaddr **psa, struct uio *uio, | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return (error); | ||||
} | } | ||||
int | int | ||||
soshutdown(struct socket *so, int how) | soshutdown(struct socket *so, int how) | ||||
{ | { | ||||
struct protosw *pr = so->so_proto; | struct protosw *pr = so->so_proto; | ||||
int error; | int error, soerror_enotconn; | ||||
if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) | if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) | ||||
return (EINVAL); | return (EINVAL); | ||||
soerror_enotconn = 0; | |||||
if ((so->so_state & | if ((so->so_state & | ||||
(SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) | (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); | return (ENOTCONN); | ||||
soerror_enotconn = 1; | |||||
} | |||||
CURVNET_SET(so->so_vnet); | CURVNET_SET(so->so_vnet); | ||||
if (pr->pr_usrreqs->pru_flush != NULL) | if (pr->pr_usrreqs->pru_flush != NULL) | ||||
(*pr->pr_usrreqs->pru_flush)(so, how); | (*pr->pr_usrreqs->pru_flush)(so, how); | ||||
if (how != SHUT_WR) | if (how != SHUT_WR) | ||||
sorflush(so); | sorflush(so); | ||||
if (how != SHUT_RD) { | if (how != SHUT_RD) { | ||||
error = (*pr->pr_usrreqs->pru_shutdown)(so); | error = (*pr->pr_usrreqs->pru_shutdown)(so); | ||||
wakeup(&so->so_timeo); | wakeup(&so->so_timeo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (error); | return ((error == 0 && soerror_enotconn) ? ENOTCONN : error); | ||||
} | } | ||||
wakeup(&so->so_timeo); | wakeup(&so->so_timeo); | ||||
CURVNET_RESTORE(); | CURVNET_RESTORE(); | ||||
return (0); | |||||
return (soerror_enotconn ? ENOTCONN : 0); | |||||
} | } | ||||
void | void | ||||
sorflush(struct socket *so) | sorflush(struct socket *so) | ||||
{ | { | ||||
struct sockbuf *sb = &so->so_rcv; | struct sockbuf *sb = &so->so_rcv; | ||||
struct protosw *pr = so->so_proto; | struct protosw *pr = so->so_proto; | ||||
struct socket aso; | struct socket aso; | ||||
▲ Show 20 Lines • Show All 1,392 Lines • Show Last 20 Lines |