summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUrsula Braun <ubraun@linux.vnet.ibm.com>2016-10-07 15:51:47 +0200
committerDavid S. Miller <davem@davemloft.net>2016-10-12 01:56:04 -0400
commit4e0ad32216910905d00a1228379163c6e5057dc4 (patch)
treeb48d5473773c9ccf469b204816e54e6f0a821e22
parentb07bf5fa32e0991b2634444652de56066fe311f2 (diff)
downloadlinux-4e0ad32216910905d00a1228379163c6e5057dc4.tar.gz
linux-4e0ad32216910905d00a1228379163c6e5057dc4.tar.bz2
linux-4e0ad32216910905d00a1228379163c6e5057dc4.zip
Subject: [PATCH] af_iucv: enable control sends in case of SEND_SHUTDOWN
If a socket program has shut down the socket for sending, it can still receive an undetermined number of packets. The AF_IUCV protocol for HIPER transport requires sending of a WIN flag from time to time from the receiver to the sender, otherwise the peer cannot continue sending. That means sending of control flags must still work, even though the AF_IUCV socket is shutdown for sending data. sock_alloc_send_skb() returns with error EPIPE, if socket sk_shutdown is SEND_SHUTDOWN. Thus this patch temporarily removes the send shutdown attribute from the socket to enable transfer of control flags. Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/iucv/af_iucv.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 02b45a8e8b35..88d0eaa18749 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -453,19 +453,27 @@ static void iucv_sever_path(struct sock *sk, int with_user_data)
}
}
-/* Send FIN through an IUCV socket for HIPER transport */
+/* Send controlling flags through an IUCV socket for HIPER transport */
static int iucv_send_ctrl(struct sock *sk, u8 flags)
{
int err = 0;
int blen;
struct sk_buff *skb;
+ u8 shutdown = 0;
blen = sizeof(struct af_iucv_trans_hdr) + ETH_HLEN;
+ if (sk->sk_shutdown & SEND_SHUTDOWN) {
+ /* controlling flags should be sent anyway */
+ shutdown = sk->sk_shutdown;
+ sk->sk_shutdown &= RCV_SHUTDOWN;
+ }
skb = sock_alloc_send_skb(sk, blen, 1, &err);
if (skb) {
skb_reserve(skb, blen);
err = afiucv_hs_send(NULL, sk, skb, flags);
}
+ if (shutdown)
+ sk->sk_shutdown = shutdown;
return err;
}