]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mptcp: Add setsockopt()/getsockopt() socket operations
authorPeter Krystad <peter.krystad@linux.intel.com>
Wed, 22 Jan 2020 00:56:22 +0000 (16:56 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 24 Jan 2020 12:44:07 +0000 (13:44 +0100)
set/getsockopt behaviour with multiple subflows is undefined.
Therefore, for now, we return -EOPNOTSUPP unless we're in fallback mode.

Co-developed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Peter Krystad <peter.krystad@linux.intel.com>
Signed-off-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/mptcp/protocol.c

index 249b2506a66ab7a079c0c442ffb97dc975751409..875ca48de4b2d94b61ab677cf5696d804f16f7d3 100644 (file)
@@ -330,6 +330,62 @@ static void mptcp_destroy(struct sock *sk)
 {
 }
 
+static int mptcp_setsockopt(struct sock *sk, int level, int optname,
+                           char __user *uoptval, unsigned int optlen)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       char __kernel *optval;
+       int ret = -EOPNOTSUPP;
+       struct socket *ssock;
+
+       /* will be treated as __user in tcp_setsockopt */
+       optval = (char __kernel __force *)uoptval;
+
+       pr_debug("msk=%p", msk);
+
+       /* @@ the meaning of setsockopt() when the socket is connected and
+        * there are multiple subflows is not defined.
+        */
+       lock_sock(sk);
+       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
+       if (!IS_ERR(ssock)) {
+               pr_debug("subflow=%p", ssock->sk);
+               ret = kernel_setsockopt(ssock, level, optname, optval, optlen);
+       }
+       release_sock(sk);
+
+       return ret;
+}
+
+static int mptcp_getsockopt(struct sock *sk, int level, int optname,
+                           char __user *uoptval, int __user *uoption)
+{
+       struct mptcp_sock *msk = mptcp_sk(sk);
+       char __kernel *optval;
+       int ret = -EOPNOTSUPP;
+       int __kernel *option;
+       struct socket *ssock;
+
+       /* will be treated as __user in tcp_getsockopt */
+       optval = (char __kernel __force *)uoptval;
+       option = (int __kernel __force *)uoption;
+
+       pr_debug("msk=%p", msk);
+
+       /* @@ the meaning of getsockopt() when the socket is connected and
+        * there are multiple subflows is not defined.
+        */
+       lock_sock(sk);
+       ssock = __mptcp_socket_create(msk, MPTCP_SAME_STATE);
+       if (!IS_ERR(ssock)) {
+               pr_debug("subflow=%p", ssock->sk);
+               ret = kernel_getsockopt(ssock, level, optname, optval, option);
+       }
+       release_sock(sk);
+
+       return ret;
+}
+
 static int mptcp_get_port(struct sock *sk, unsigned short snum)
 {
        struct mptcp_sock *msk = mptcp_sk(sk);
@@ -380,6 +436,8 @@ static struct proto mptcp_prot = {
        .init           = mptcp_init_sock,
        .close          = mptcp_close,
        .accept         = mptcp_accept,
+       .setsockopt     = mptcp_setsockopt,
+       .getsockopt     = mptcp_getsockopt,
        .shutdown       = tcp_shutdown,
        .destroy        = mptcp_destroy,
        .sendmsg        = mptcp_sendmsg,