1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2021, Red Hat.
7 #define pr_fmt(fmt) "MPTCP: " fmt
9 #include <linux/kernel.h>
10 #include <linux/module.h>
12 #include <net/protocol.h>
14 #include <net/mptcp.h>
17 static struct sock *__mptcp_tcp_fallback(struct mptcp_sock *msk)
19 sock_owned_by_me((const struct sock *)msk);
21 if (likely(!__mptcp_check_fallback(msk)))
27 static int mptcp_setsockopt_sol_socket(struct mptcp_sock *msk, int optname,
28 sockptr_t optval, unsigned int optlen)
30 struct sock *sk = (struct sock *)msk;
38 ssock = __mptcp_nmpc_socket(msk);
44 ret = sock_setsockopt(ssock, SOL_SOCKET, optname, optval, optlen);
46 if (optname == SO_REUSEPORT)
47 sk->sk_reuseport = ssock->sk->sk_reuseport;
48 else if (optname == SO_REUSEADDR)
49 sk->sk_reuse = ssock->sk->sk_reuse;
55 return sock_setsockopt(sk->sk_socket, SOL_SOCKET, optname, optval, optlen);
58 static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname,
59 sockptr_t optval, unsigned int optlen)
61 struct sock *sk = (struct sock *)msk;
62 int ret = -EOPNOTSUPP;
68 ssock = __mptcp_nmpc_socket(msk);
74 ret = tcp_setsockopt(ssock->sk, SOL_IPV6, optname, optval, optlen);
76 sk->sk_ipv6only = ssock->sk->sk_ipv6only;
85 int mptcp_setsockopt(struct sock *sk, int level, int optname,
86 sockptr_t optval, unsigned int optlen)
88 struct mptcp_sock *msk = mptcp_sk(sk);
91 pr_debug("msk=%p", msk);
93 if (level == SOL_SOCKET)
94 return mptcp_setsockopt_sol_socket(msk, optname, optval, optlen);
96 /* @@ the meaning of setsockopt() when the socket is connected and
97 * there are multiple subflows is not yet defined. It is up to the
98 * MPTCP-level socket to configure the subflows until the subflow
99 * is in TCP fallback, when TCP socket options are passed through
100 * to the one remaining subflow.
103 ssk = __mptcp_tcp_fallback(msk);
106 return tcp_setsockopt(ssk, level, optname, optval, optlen);
108 if (level == SOL_IPV6)
109 return mptcp_setsockopt_v6(msk, optname, optval, optlen);
114 int mptcp_getsockopt(struct sock *sk, int level, int optname,
115 char __user *optval, int __user *option)
117 struct mptcp_sock *msk = mptcp_sk(sk);
120 pr_debug("msk=%p", msk);
122 /* @@ the meaning of setsockopt() when the socket is connected and
123 * there are multiple subflows is not yet defined. It is up to the
124 * MPTCP-level socket to configure the subflows until the subflow
125 * is in TCP fallback, when socket options are passed through
126 * to the one remaining subflow.
129 ssk = __mptcp_tcp_fallback(msk);
132 return tcp_getsockopt(ssk, level, optname, optval, option);