ipx: implement shutdown()

IPX doesn't implement shutdown, which poses a problem to some users:

https://bugzilla.kernel.org/show_bug.cgi?id=67841

This patch is heavily based on the shutdown implementation for unix
sockets.

Reported-by: Bruno Jesus <00cpxxx@gmail.com>
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Sabrina Dubroca 2014-02-09 00:23:38 +01:00 committed by David S. Miller
parent 6028323b52
commit 8815cbd9e3
1 changed files with 26 additions and 2 deletions

View File

@ -1368,6 +1368,7 @@ static int ipx_release(struct socket *sock)
goto out;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);
@ -1791,8 +1792,11 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &rc);
if (!skb)
if (!skb) {
if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
rc = 0;
goto out;
}
ipx = ipx_hdr(skb);
copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
@ -1922,6 +1926,26 @@ static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long
}
#endif
static int ipx_shutdown(struct socket *sock, int mode)
{
struct sock *sk = sock->sk;
if (mode < SHUT_RD || mode > SHUT_RDWR)
return -EINVAL;
/* This maps:
* SHUT_RD (0) -> RCV_SHUTDOWN (1)
* SHUT_WR (1) -> SEND_SHUTDOWN (2)
* SHUT_RDWR (2) -> SHUTDOWN_MASK (3)
*/
++mode;
lock_sock(sk);
sk->sk_shutdown |= mode;
release_sock(sk);
sk->sk_state_change(sk);
return 0;
}
/*
* Socket family declarations
@ -1948,7 +1972,7 @@ static const struct proto_ops ipx_dgram_ops = {
.compat_ioctl = ipx_compat_ioctl,
#endif
.listen = sock_no_listen,
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */
.shutdown = ipx_shutdown,
.setsockopt = ipx_setsockopt,
.getsockopt = ipx_getsockopt,
.sendmsg = ipx_sendmsg,