diff options
author | Sabrina Dubroca <sd@queasysnail.net> | 2014-02-08 18:23:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-12 19:26:32 -0500 |
commit | 8815cbd9e38a7a02bfb79854aa7d33f1e1e50305 (patch) | |
tree | db9bb3b7d7cd27ccf767d9a0002948a7f72d77cb /net/ipx | |
parent | 6028323b52e06377638b3509afffb9d86bf4bdf7 (diff) |
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>
Diffstat (limited to 'net/ipx')
-rw-r--r-- | net/ipx/af_ipx.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 00b2a6d1c009..41e4e93cb3aa 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
@@ -1368,6 +1368,7 @@ static int ipx_release(struct socket *sock) | |||
1368 | goto out; | 1368 | goto out; |
1369 | 1369 | ||
1370 | lock_sock(sk); | 1370 | lock_sock(sk); |
1371 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
1371 | if (!sock_flag(sk, SOCK_DEAD)) | 1372 | if (!sock_flag(sk, SOCK_DEAD)) |
1372 | sk->sk_state_change(sk); | 1373 | sk->sk_state_change(sk); |
1373 | 1374 | ||
@@ -1791,8 +1792,11 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1791 | 1792 | ||
1792 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1793 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
1793 | flags & MSG_DONTWAIT, &rc); | 1794 | flags & MSG_DONTWAIT, &rc); |
1794 | if (!skb) | 1795 | if (!skb) { |
1796 | if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
1797 | rc = 0; | ||
1795 | goto out; | 1798 | goto out; |
1799 | } | ||
1796 | 1800 | ||
1797 | ipx = ipx_hdr(skb); | 1801 | ipx = ipx_hdr(skb); |
1798 | copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); | 1802 | 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 | |||
1922 | } | 1926 | } |
1923 | #endif | 1927 | #endif |
1924 | 1928 | ||
1929 | static int ipx_shutdown(struct socket *sock, int mode) | ||
1930 | { | ||
1931 | struct sock *sk = sock->sk; | ||
1932 | |||
1933 | if (mode < SHUT_RD || mode > SHUT_RDWR) | ||
1934 | return -EINVAL; | ||
1935 | /* This maps: | ||
1936 | * SHUT_RD (0) -> RCV_SHUTDOWN (1) | ||
1937 | * SHUT_WR (1) -> SEND_SHUTDOWN (2) | ||
1938 | * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) | ||
1939 | */ | ||
1940 | ++mode; | ||
1941 | |||
1942 | lock_sock(sk); | ||
1943 | sk->sk_shutdown |= mode; | ||
1944 | release_sock(sk); | ||
1945 | sk->sk_state_change(sk); | ||
1946 | |||
1947 | return 0; | ||
1948 | } | ||
1925 | 1949 | ||
1926 | /* | 1950 | /* |
1927 | * Socket family declarations | 1951 | * Socket family declarations |
@@ -1948,7 +1972,7 @@ static const struct proto_ops ipx_dgram_ops = { | |||
1948 | .compat_ioctl = ipx_compat_ioctl, | 1972 | .compat_ioctl = ipx_compat_ioctl, |
1949 | #endif | 1973 | #endif |
1950 | .listen = sock_no_listen, | 1974 | .listen = sock_no_listen, |
1951 | .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ | 1975 | .shutdown = ipx_shutdown, |
1952 | .setsockopt = ipx_setsockopt, | 1976 | .setsockopt = ipx_setsockopt, |
1953 | .getsockopt = ipx_getsockopt, | 1977 | .getsockopt = ipx_getsockopt, |
1954 | .sendmsg = ipx_sendmsg, | 1978 | .sendmsg = ipx_sendmsg, |