|
11 | 11 | #include <linux/netdevice.h> |
12 | 12 | #include <linux/sched/signal.h> |
13 | 13 | #include <linux/atomic.h> |
| 14 | +#include <linux/igmp.h> |
14 | 15 | #include <net/sock.h> |
15 | 16 | #include <net/inet_common.h> |
16 | 17 | #include <net/inet_hashtables.h> |
|
19 | 20 | #include <net/tcp_states.h> |
20 | 21 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
21 | 22 | #include <net/transp_v6.h> |
| 23 | +#include <net/addrconf.h> |
22 | 24 | #endif |
23 | 25 | #include <net/mptcp.h> |
24 | 26 | #include <net/xfrm.h> |
@@ -2264,13 +2266,12 @@ static void mptcp_worker(struct work_struct *work) |
2264 | 2266 | __mptcp_check_send_data_fin(sk); |
2265 | 2267 | mptcp_check_data_fin(sk); |
2266 | 2268 |
|
2267 | | - /* if the msk data is completely acked, or the socket timedout, |
2268 | | - * there is no point in keeping around an orphaned sk |
| 2269 | + /* There is no point in keeping around an orphaned sk timedout or |
| 2270 | + * closed, but we need the msk around to reply to incoming DATA_FIN, |
| 2271 | + * even if it is orphaned and in FIN_WAIT2 state |
2269 | 2272 | */ |
2270 | 2273 | if (sock_flag(sk, SOCK_DEAD) && |
2271 | | - (mptcp_check_close_timeout(sk) || |
2272 | | - (state != sk->sk_state && |
2273 | | - ((1 << inet_sk_state_load(sk)) & (TCPF_CLOSE | TCPF_FIN_WAIT2))))) { |
| 2274 | + (mptcp_check_close_timeout(sk) || sk->sk_state == TCP_CLOSE)) { |
2274 | 2275 | inet_sk_state_store(sk, TCP_CLOSE); |
2275 | 2276 | __mptcp_destroy_sock(sk); |
2276 | 2277 | goto unlock; |
@@ -3375,10 +3376,34 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, |
3375 | 3376 | return mask; |
3376 | 3377 | } |
3377 | 3378 |
|
| 3379 | +static int mptcp_release(struct socket *sock) |
| 3380 | +{ |
| 3381 | + struct mptcp_subflow_context *subflow; |
| 3382 | + struct sock *sk = sock->sk; |
| 3383 | + struct mptcp_sock *msk; |
| 3384 | + |
| 3385 | + if (!sk) |
| 3386 | + return 0; |
| 3387 | + |
| 3388 | + lock_sock(sk); |
| 3389 | + |
| 3390 | + msk = mptcp_sk(sk); |
| 3391 | + |
| 3392 | + mptcp_for_each_subflow(msk, subflow) { |
| 3393 | + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3394 | + |
| 3395 | + ip_mc_drop_socket(ssk); |
| 3396 | + } |
| 3397 | + |
| 3398 | + release_sock(sk); |
| 3399 | + |
| 3400 | + return inet_release(sock); |
| 3401 | +} |
| 3402 | + |
3378 | 3403 | static const struct proto_ops mptcp_stream_ops = { |
3379 | 3404 | .family = PF_INET, |
3380 | 3405 | .owner = THIS_MODULE, |
3381 | | - .release = inet_release, |
| 3406 | + .release = mptcp_release, |
3382 | 3407 | .bind = mptcp_bind, |
3383 | 3408 | .connect = mptcp_stream_connect, |
3384 | 3409 | .socketpair = sock_no_socketpair, |
@@ -3470,10 +3495,35 @@ void __init mptcp_proto_init(void) |
3470 | 3495 | } |
3471 | 3496 |
|
3472 | 3497 | #if IS_ENABLED(CONFIG_MPTCP_IPV6) |
| 3498 | +static int mptcp6_release(struct socket *sock) |
| 3499 | +{ |
| 3500 | + struct mptcp_subflow_context *subflow; |
| 3501 | + struct mptcp_sock *msk; |
| 3502 | + struct sock *sk = sock->sk; |
| 3503 | + |
| 3504 | + if (!sk) |
| 3505 | + return 0; |
| 3506 | + |
| 3507 | + lock_sock(sk); |
| 3508 | + |
| 3509 | + msk = mptcp_sk(sk); |
| 3510 | + |
| 3511 | + mptcp_for_each_subflow(msk, subflow) { |
| 3512 | + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); |
| 3513 | + |
| 3514 | + ip_mc_drop_socket(ssk); |
| 3515 | + ipv6_sock_mc_close(ssk); |
| 3516 | + ipv6_sock_ac_close(ssk); |
| 3517 | + } |
| 3518 | + |
| 3519 | + release_sock(sk); |
| 3520 | + return inet6_release(sock); |
| 3521 | +} |
| 3522 | + |
3473 | 3523 | static const struct proto_ops mptcp_v6_stream_ops = { |
3474 | 3524 | .family = PF_INET6, |
3475 | 3525 | .owner = THIS_MODULE, |
3476 | | - .release = inet6_release, |
| 3526 | + .release = mptcp6_release, |
3477 | 3527 | .bind = mptcp_bind, |
3478 | 3528 | .connect = mptcp_stream_connect, |
3479 | 3529 | .socketpair = sock_no_socketpair, |
|
0 commit comments