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