forked from mirrors/linux
		
	mptcp: fix unblocking connect()
Currently unblocking connect() on MPTCP sockets fails frequently.
If mptcp_stream_connect() is invoked to complete a previously
attempted unblocking connection, it will still try to create
the first subflow via __mptcp_socket_create(). If the 3whs is
completed and the 'can_ack' flag is already set, the latter
will fail with -EINVAL.
This change addresses the issue checking for pending connect and
delegating the completion to the first subflow. Additionally
do msk addresses and sk_state changes only when needed.
Fixes: 2303f994b3 ("mptcp: Associate MPTCP context with TCP socket")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									05aa69e5cb
								
							
						
					
					
						commit
						41be81a8d3
					
				
					 1 changed files with 18 additions and 2 deletions
				
			
		| 
						 | 
					@ -1712,6 +1712,14 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lock_sock(sock->sk);
 | 
						lock_sock(sock->sk);
 | 
				
			||||||
 | 
						if (sock->state != SS_UNCONNECTED && msk->subflow) {
 | 
				
			||||||
 | 
							/* pending connection or invalid state, let existing subflow
 | 
				
			||||||
 | 
							 * cope with that
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							ssock = msk->subflow;
 | 
				
			||||||
 | 
							goto do_connect;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ssock = __mptcp_socket_create(msk, TCP_SYN_SENT);
 | 
						ssock = __mptcp_socket_create(msk, TCP_SYN_SENT);
 | 
				
			||||||
	if (IS_ERR(ssock)) {
 | 
						if (IS_ERR(ssock)) {
 | 
				
			||||||
		err = PTR_ERR(ssock);
 | 
							err = PTR_ERR(ssock);
 | 
				
			||||||
| 
						 | 
					@ -1726,9 +1734,17 @@ static int mptcp_stream_connect(struct socket *sock, struct sockaddr *uaddr,
 | 
				
			||||||
		mptcp_subflow_ctx(ssock->sk)->request_mptcp = 0;
 | 
							mptcp_subflow_ctx(ssock->sk)->request_mptcp = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					do_connect:
 | 
				
			||||||
	err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
 | 
						err = ssock->ops->connect(ssock, uaddr, addr_len, flags);
 | 
				
			||||||
	inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
 | 
						sock->state = ssock->state;
 | 
				
			||||||
	mptcp_copy_inaddrs(sock->sk, ssock->sk);
 | 
					
 | 
				
			||||||
 | 
						/* on successful connect, the msk state will be moved to established by
 | 
				
			||||||
 | 
						 * subflow_finish_connect()
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (!err || err == EINPROGRESS)
 | 
				
			||||||
 | 
							mptcp_copy_inaddrs(sock->sk, ssock->sk);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							inet_sk_state_store(sock->sk, inet_sk_state_load(ssock->sk));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unlock:
 | 
					unlock:
 | 
				
			||||||
	release_sock(sock->sk);
 | 
						release_sock(sock->sk);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue