Commit 268b1238 authored by Florian Westphal's avatar Florian Westphal Committed by David S. Miller

mptcp: setsockopt: support SO_LINGER

Similar to PRIORITY/KEEPALIVE: needs to be mirrored to all subflows.
Acked-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarMat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d0a6bc8
...@@ -143,6 +143,47 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname, ...@@ -143,6 +143,47 @@ static int mptcp_setsockopt_sol_socket_int(struct mptcp_sock *msk, int optname,
return -ENOPROTOOPT; 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, static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
sockptr_t optval, unsigned int optlen) sockptr_t optval, unsigned int optlen)
{ {
...@@ -182,6 +223,8 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname, ...@@ -182,6 +223,8 @@ static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
case SO_RCVBUF: case SO_RCVBUF:
case SO_RCVBUFFORCE: case SO_RCVBUFFORCE:
return mptcp_setsockopt_sol_socket_int(msk, optname, optval, optlen); 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); return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, optval, optlen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment