@@ -196,6 +196,29 @@ static int mptcp_init_sock(struct sock *sk)
196
196
return 0 ;
197
197
}
198
198
199
+ static void mptcp_subflow_shutdown (struct sock * ssk , int how )
200
+ {
201
+ lock_sock (ssk );
202
+
203
+ switch (ssk -> sk_state ) {
204
+ case TCP_LISTEN :
205
+ if (!(how & RCV_SHUTDOWN ))
206
+ break ;
207
+ /* fall through */
208
+ case TCP_SYN_SENT :
209
+ tcp_disconnect (ssk , O_NONBLOCK );
210
+ break ;
211
+ default :
212
+ ssk -> sk_shutdown |= how ;
213
+ tcp_shutdown (ssk , how );
214
+ break ;
215
+ }
216
+
217
+ /* Wake up anyone sleeping in poll. */
218
+ ssk -> sk_state_change (ssk );
219
+ release_sock (ssk );
220
+ }
221
+
199
222
static void mptcp_close (struct sock * sk , long timeout )
200
223
{
201
224
struct mptcp_subflow_context * subflow , * tmp ;
@@ -273,6 +296,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
273
296
* err = - ENOBUFS ;
274
297
local_bh_enable ();
275
298
release_sock (sk );
299
+ mptcp_subflow_shutdown (newsk , SHUT_RDWR + 1 );
276
300
tcp_close (newsk , 0 );
277
301
return NULL ;
278
302
}
@@ -544,6 +568,46 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock,
544
568
return mask ;
545
569
}
546
570
571
+ static int mptcp_shutdown (struct socket * sock , int how )
572
+ {
573
+ struct mptcp_sock * msk = mptcp_sk (sock -> sk );
574
+ struct mptcp_subflow_context * subflow ;
575
+ int ret = 0 ;
576
+
577
+ pr_debug ("sk=%p, how=%d" , msk , how );
578
+
579
+ lock_sock (sock -> sk );
580
+
581
+ if (how == SHUT_WR || how == SHUT_RDWR )
582
+ inet_sk_state_store (sock -> sk , TCP_FIN_WAIT1 );
583
+
584
+ how ++ ;
585
+
586
+ if ((how & ~SHUTDOWN_MASK ) || !how ) {
587
+ ret = - EINVAL ;
588
+ goto out_unlock ;
589
+ }
590
+
591
+ if (sock -> state == SS_CONNECTING ) {
592
+ if ((1 << sock -> sk -> sk_state ) &
593
+ (TCPF_SYN_SENT | TCPF_SYN_RECV | TCPF_CLOSE ))
594
+ sock -> state = SS_DISCONNECTING ;
595
+ else
596
+ sock -> state = SS_CONNECTED ;
597
+ }
598
+
599
+ mptcp_for_each_subflow (msk , subflow ) {
600
+ struct sock * tcp_sk = mptcp_subflow_tcp_sock (subflow );
601
+
602
+ mptcp_subflow_shutdown (tcp_sk , how );
603
+ }
604
+
605
+ out_unlock :
606
+ release_sock (sock -> sk );
607
+
608
+ return ret ;
609
+ }
610
+
547
611
static struct proto_ops mptcp_stream_ops ;
548
612
549
613
static struct inet_protosw mptcp_protosw = {
@@ -564,6 +628,7 @@ void __init mptcp_init(void)
564
628
mptcp_stream_ops .accept = mptcp_stream_accept ;
565
629
mptcp_stream_ops .getname = mptcp_v4_getname ;
566
630
mptcp_stream_ops .listen = mptcp_listen ;
631
+ mptcp_stream_ops .shutdown = mptcp_shutdown ;
567
632
568
633
mptcp_subflow_init ();
569
634
@@ -613,6 +678,7 @@ int mptcpv6_init(void)
613
678
mptcp_v6_stream_ops .accept = mptcp_stream_accept ;
614
679
mptcp_v6_stream_ops .getname = mptcp_v6_getname ;
615
680
mptcp_v6_stream_ops .listen = mptcp_listen ;
681
+ mptcp_v6_stream_ops .shutdown = mptcp_shutdown ;
616
682
617
683
err = inet6_register_protosw (& mptcp_v6_protosw );
618
684
if (err )
0 commit comments