diff --git a/lib/libc/sys/shutdown.2 b/lib/libc/sys/shutdown.2 index e8a434b23955..35c464e9fe2e 100644 --- a/lib/libc/sys/shutdown.2 +++ b/lib/libc/sys/shutdown.2 @@ -29,7 +29,7 @@ .\" @(#)shutdown.2 8.1 (Berkeley) 6/4/93 .\" $FreeBSD$ .\" -.Dd March 5, 2007 +.Dd July 27, 2015 .Dt SHUTDOWN 2 .Os .Sh NAME @@ -79,40 +79,26 @@ The following protocol specific actions apply to the use of based on the properties of the socket associated with the file descriptor .Fa s . .Bl -column ".Dv PF_INET6" ".Dv SOCK_STREAM" ".Dv IPPROTO_SCTP" -.It Sy Domain Ta Sy Type Ta Sy Protocol Ta Sy Return value and action +.It Sy Domain Ta Sy Type Ta Sy Protocol Ta Sy Action .It Dv PF_INET Ta Dv SOCK_DGRAM Ta Dv IPPROTO_SCTP Ta -Return \-1. -The global variable -.Va errno -will be set to -.Er EOPNOTSUPP . +Failure, +as socket is not connected. .It Dv PF_INET Ta Dv SOCK_DGRAM Ta Dv IPPROTO_UDP Ta -Return 0. -ICMP messages will -.Em not -be generated. +Failure, +as socket is not connected. .It Dv PF_INET Ta Dv SOCK_STREAM Ta Dv IPPROTO_SCTP Ta -Return 0. Send queued data and tear down association. .It Dv PF_INET Ta Dv SOCK_STREAM Ta Dv IPPROTO_TCP Ta -Return 0. Send queued data, wait for ACK, then send FIN. .It Dv PF_INET6 Ta Dv SOCK_DGRAM Ta Dv IPPROTO_SCTP Ta -Return \-1. -The global variable -.Va errno -will be set to -.Er EOPNOTSUPP . +Failure, +as socket is not connected. .It Dv PF_INET6 Ta Dv SOCK_DGRAM Ta Dv IPPROTO_UDP Ta -Return 0. -ICMP messages will -.Em not -be generated. +Failure, +as socket is not connected. .It Dv PF_INET6 Ta Dv SOCK_STREAM Ta Dv IPPROTO_SCTP Ta -Return 0. Send queued data and tear down association. .It Dv PF_INET6 Ta Dv SOCK_STREAM Ta Dv IPPROTO_TCP Ta -Return 0. Send queued data, wait for ACK, then send FIN. .El .\" @@ -131,16 +117,10 @@ argument is not a valid file descriptor. The .Fa how argument is invalid. -.It Bq Er EOPNOTSUPP -The socket associated with the file descriptor -.Fa s -does not support this operation. .It Bq Er ENOTCONN The .Fa s -argument specifies a -.Dv SOCK_STREAM -socket which is not connected. +argument specifies a socket which is not connected. .It Bq Er ENOTSOCK The .Fa s diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 58a38f2b827f..350ca3cdd0b0 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -2334,6 +2334,9 @@ soshutdown(struct socket *so, int how) if (!(how == SHUT_RD || how == SHUT_WR || how == SHUT_RDWR)) return (EINVAL); + if ((so->so_state & + (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) + return (ENOTCONN); CURVNET_SET(so->so_vnet); if (pr->pr_usrreqs->pru_flush != NULL) diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index e3557ba72604..54c13024c611 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1383,6 +1383,15 @@ sys_shutdown(td, uap) if (error == 0) { so = fp->f_data; error = soshutdown(so, uap->how); + /* + * Previous versions did not return ENOTCONN, but 0 in + * case the socket was not connected. Some important + * programs like syslogd up to r279016, 2015-02-19, + * still depend on this behavior. + */ + if (error == ENOTCONN && + td->td_proc->p_osrel < P_OSREL_SHUTDOWN_ENOTCONN) + error = 0; fdrop(fp, td); } return (error); diff --git a/sys/sys/param.h b/sys/sys/param.h index a146da86a42f..5f6665668145 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -77,12 +77,13 @@ #define __FreeBSD_kernel__ #ifdef _KERNEL -#define P_OSREL_SIGWAIT 700000 -#define P_OSREL_SIGSEGV 700004 -#define P_OSREL_MAP_ANON 800104 -#define P_OSREL_MAP_FSTRICT 1100036 +#define P_OSREL_SIGWAIT 700000 +#define P_OSREL_SIGSEGV 700004 +#define P_OSREL_MAP_ANON 800104 +#define P_OSREL_MAP_FSTRICT 1100036 +#define P_OSREL_SHUTDOWN_ENOTCONN 1100077 -#define P_OSREL_MAJOR(x) ((x) / 100000) +#define P_OSREL_MAJOR(x) ((x) / 100000) #endif #ifndef LOCORE