mptcp: setsockopt: support SO_LINGER
Similar to PRIORITY/KEEPALIVE: needs to be mirrored to all subflows. Acked-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5d0a6bc82d
commit
268b123874
@ -143,6 +143,47 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
|
||||
return -ENOPROTOOPT;
|
||||
}
|
||||
|
||||
static int mptcp_setsockopt_sol_socket_linger(struct mptcp_sock *msk, sockptr_t optval,
|
||||
unsigned int optlen)
|
||||
{
|
||||
struct mptcp_subflow_context *subflow;
|
||||
struct sock *sk = (struct sock *)msk;
|
||||
struct linger ling;
|
||||
sockptr_t kopt;
|
||||
int ret;
|
||||
|
||||
if (optlen < sizeof(ling))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_sockptr(&ling, optval, sizeof(ling)))
|
||||
return -EFAULT;
|
||||
|
||||
kopt = KERNEL_SOCKPTR(&ling);
|
||||
ret = sock_setsockopt(sk->sk_socket, SOL_SOCKET, SO_LINGER, kopt, sizeof(ling));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lock_sock(sk);
|
||||
sockopt_seq_inc(msk);
|
||||
mptcp_for_each_subflow(msk, subflow) {
|
||||
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
||||
bool slow = lock_sock_fast(ssk);
|
||||
|
||||
if (!ling.l_onoff) {
|
||||
sock_reset_flag(ssk, SOCK_LINGER);
|
||||
} else {
|
||||
ssk->sk_lingertime = sk->sk_lingertime;
|
||||
sock_set_flag(ssk, SOCK_LINGER);
|
||||
}
|
||||
|
||||
subflow->setsockopt_seq = msk->setsockopt_seq;
|
||||
unlock_sock_fast(ssk, slow);
|
||||
}
|
||||
|
||||
release_sock(sk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
|
||||
sockptr_t optval, unsigned int optlen)
|
||||
{
|
||||
@ -182,6 +223,8 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
|
||||
case SO_RCVBUF:
|
||||
case SO_RCVBUFFORCE:
|
||||
return mptcp_setsockopt_sol_socket_int(msk, optname, optval, optlen);
|
||||
case SO_LINGER:
|
||||
return mptcp_setsockopt_sol_socket_linger(msk, optval, optlen);
|
||||
}
|
||||
|
||||
return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, optval, optlen);
|
||||
|
Loading…
Reference in New Issue
Block a user