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:
parent
6028323b52
commit
8815cbd9e3
|
@ -1368,6 +1368,7 @@ static int ipx_release(struct socket *sock)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
lock_sock(sk);
|
lock_sock(sk);
|
||||||
|
sk->sk_shutdown = SHUTDOWN_MASK;
|
||||||
if (!sock_flag(sk, SOCK_DEAD))
|
if (!sock_flag(sk, SOCK_DEAD))
|
||||||
sk->sk_state_change(sk);
|
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,
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
||||||
flags & MSG_DONTWAIT, &rc);
|
flags & MSG_DONTWAIT, &rc);
|
||||||
if (!skb)
|
if (!skb) {
|
||||||
|
if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN))
|
||||||
|
rc = 0;
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
ipx = ipx_hdr(skb);
|
ipx = ipx_hdr(skb);
|
||||||
copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
|
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
|
#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
|
* Socket family declarations
|
||||||
|
@ -1948,7 +1972,7 @@ static const struct proto_ops ipx_dgram_ops = {
|
||||||
.compat_ioctl = ipx_compat_ioctl,
|
.compat_ioctl = ipx_compat_ioctl,
|
||||||
#endif
|
#endif
|
||||||
.listen = sock_no_listen,
|
.listen = sock_no_listen,
|
||||||
.shutdown = sock_no_shutdown, /* FIXME: support shutdown */
|
.shutdown = ipx_shutdown,
|
||||||
.setsockopt = ipx_setsockopt,
|
.setsockopt = ipx_setsockopt,
|
||||||
.getsockopt = ipx_getsockopt,
|
.getsockopt = ipx_getsockopt,
|
||||||
.sendmsg = ipx_sendmsg,
|
.sendmsg = ipx_sendmsg,
|
||||||
|
|
Loading…
Reference in New Issue