forked from mirrors/linux
		
	mptcp: Add setsockopt()/getsockopt() socket operations
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>
This commit is contained in:
		
							parent
							
								
									214984901a
								
							
						
					
					
						commit
						717e79c867
					
				
					 1 changed files with 58 additions and 0 deletions
				
			
		|  | @ -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, | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Peter Krystad
						Peter Krystad