]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - net/mptcp/protocol.c
mptcp: Add MPTCP socket stubs
[mirror_ubuntu-jammy-kernel.git] / net / mptcp / protocol.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Multipath TCP
3 *
4 * Copyright (c) 2017 - 2019, Intel Corporation.
5 */
6
7 #define pr_fmt(fmt) "MPTCP: " fmt
8
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/netdevice.h>
12 #include <net/sock.h>
13 #include <net/inet_common.h>
14 #include <net/inet_hashtables.h>
15 #include <net/protocol.h>
16 #include <net/tcp.h>
17 #include <net/mptcp.h>
18 #include "protocol.h"
19
20 static int mptcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
21 {
22 struct mptcp_sock *msk = mptcp_sk(sk);
23 struct socket *subflow = msk->subflow;
24
25 if (msg->msg_flags & ~(MSG_MORE | MSG_DONTWAIT | MSG_NOSIGNAL))
26 return -EOPNOTSUPP;
27
28 return sock_sendmsg(subflow, msg);
29 }
30
31 static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
32 int nonblock, int flags, int *addr_len)
33 {
34 struct mptcp_sock *msk = mptcp_sk(sk);
35 struct socket *subflow = msk->subflow;
36
37 if (msg->msg_flags & ~(MSG_WAITALL | MSG_DONTWAIT))
38 return -EOPNOTSUPP;
39
40 return sock_recvmsg(subflow, msg, flags);
41 }
42
43 static int mptcp_init_sock(struct sock *sk)
44 {
45 return 0;
46 }
47
48 static void mptcp_close(struct sock *sk, long timeout)
49 {
50 struct mptcp_sock *msk = mptcp_sk(sk);
51
52 inet_sk_state_store(sk, TCP_CLOSE);
53
54 if (msk->subflow) {
55 pr_debug("subflow=%p", msk->subflow->sk);
56 sock_release(msk->subflow);
57 }
58
59 sock_orphan(sk);
60 sock_put(sk);
61 }
62
63 static int mptcp_connect(struct sock *sk, struct sockaddr *saddr, int len)
64 {
65 struct mptcp_sock *msk = mptcp_sk(sk);
66 int err;
67
68 saddr->sa_family = AF_INET;
69
70 pr_debug("msk=%p, subflow=%p", msk, msk->subflow->sk);
71
72 err = kernel_connect(msk->subflow, saddr, len, 0);
73
74 sk->sk_state = TCP_ESTABLISHED;
75
76 return err;
77 }
78
79 static struct proto mptcp_prot = {
80 .name = "MPTCP",
81 .owner = THIS_MODULE,
82 .init = mptcp_init_sock,
83 .close = mptcp_close,
84 .accept = inet_csk_accept,
85 .connect = mptcp_connect,
86 .shutdown = tcp_shutdown,
87 .sendmsg = mptcp_sendmsg,
88 .recvmsg = mptcp_recvmsg,
89 .hash = inet_hash,
90 .unhash = inet_unhash,
91 .get_port = inet_csk_get_port,
92 .obj_size = sizeof(struct mptcp_sock),
93 .no_autobind = true,
94 };
95
96 static struct inet_protosw mptcp_protosw = {
97 .type = SOCK_STREAM,
98 .protocol = IPPROTO_MPTCP,
99 .prot = &mptcp_prot,
100 .ops = &inet_stream_ops,
101 };
102
103 void __init mptcp_init(void)
104 {
105 if (proto_register(&mptcp_prot, 1) != 0)
106 panic("Failed to register MPTCP proto.\n");
107
108 inet_register_protosw(&mptcp_protosw);
109 }
110
111 #if IS_ENABLED(CONFIG_MPTCP_IPV6)
112 static struct proto mptcp_v6_prot;
113
114 static struct inet_protosw mptcp_v6_protosw = {
115 .type = SOCK_STREAM,
116 .protocol = IPPROTO_MPTCP,
117 .prot = &mptcp_v6_prot,
118 .ops = &inet6_stream_ops,
119 .flags = INET_PROTOSW_ICSK,
120 };
121
122 int mptcpv6_init(void)
123 {
124 int err;
125
126 mptcp_v6_prot = mptcp_prot;
127 strcpy(mptcp_v6_prot.name, "MPTCPv6");
128 mptcp_v6_prot.slab = NULL;
129 mptcp_v6_prot.obj_size = sizeof(struct mptcp_sock) +
130 sizeof(struct ipv6_pinfo);
131
132 err = proto_register(&mptcp_v6_prot, 1);
133 if (err)
134 return err;
135
136 err = inet6_register_protosw(&mptcp_v6_protosw);
137 if (err)
138 proto_unregister(&mptcp_v6_prot);
139
140 return err;
141 }
142 #endif