Skip to content

Commit

Permalink
tipc: fix implicit-connect for SYN+
Browse files Browse the repository at this point in the history
[ Upstream commit f8dd60d ]

For implicit-connect, when it's either SYN- or SYN+, an ACK should
be sent back to the client immediately. It's not appropriate for
the client to enter established state only after receiving data
from the server.

On client side, after the SYN is sent out, tipc_wait_for_connect()
should be called to wait for the ACK if timeout is set.

This patch also restricts __tipc_sendstream() to call __sendmsg()
only when it's in TIPC_OPEN state, so that the client can program
in a single loop doing both connecting and data sending like:

  for (...)
      sendmsg(dest, buf);

This makes the implicit-connect more implicit.

Fixes: b97bf3f ("[TIPC] Initial merge")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
lxin authored and gregkh committed Aug 4, 2021
1 parent bb60616 commit 10f5857
Showing 1 changed file with 13 additions and 8 deletions.
21 changes: 13 additions & 8 deletions net/tipc/socket.c
Expand Up @@ -148,6 +148,7 @@ static void tipc_sk_remove(struct tipc_sock *tsk);
static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dsz);
static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dsz);
static void tipc_sk_push_backlog(struct tipc_sock *tsk, bool nagle_ack);
static int tipc_wait_for_connect(struct socket *sock, long *timeo_p);

static const struct proto_ops packet_ops;
static const struct proto_ops stream_ops;
Expand Down Expand Up @@ -1508,8 +1509,13 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
rc = 0;
}

if (unlikely(syn && !rc))
if (unlikely(syn && !rc)) {
tipc_set_sk_state(sk, TIPC_CONNECTING);
if (timeout) {
timeout = msecs_to_jiffies(timeout);
tipc_wait_for_connect(sock, &timeout);
}
}

return rc ? rc : dlen;
}
Expand Down Expand Up @@ -1557,7 +1563,7 @@ static int __tipc_sendstream(struct socket *sock, struct msghdr *m, size_t dlen)
return -EMSGSIZE;

/* Handle implicit connection setup */
if (unlikely(dest)) {
if (unlikely(dest && sk->sk_state == TIPC_OPEN)) {
rc = __tipc_sendmsg(sock, m, dlen);
if (dlen && dlen == rc) {
tsk->peer_caps = tipc_node_get_capabilities(net, dnode);
Expand Down Expand Up @@ -2686,9 +2692,10 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
bool kern)
{
struct sock *new_sk, *sk = sock->sk;
struct sk_buff *buf;
struct tipc_sock *new_tsock;
struct msghdr m = {NULL,};
struct tipc_msg *msg;
struct sk_buff *buf;
long timeo;
int res;

Expand Down Expand Up @@ -2733,19 +2740,17 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
}

/*
* Respond to 'SYN-' by discarding it & returning 'ACK'-.
* Respond to 'SYN+' by queuing it on new socket.
* Respond to 'SYN-' by discarding it & returning 'ACK'.
* Respond to 'SYN+' by queuing it on new socket & returning 'ACK'.
*/
if (!msg_data_sz(msg)) {
struct msghdr m = {NULL,};

tsk_advance_rx_queue(sk);
__tipc_sendstream(new_sock, &m, 0);
} else {
__skb_dequeue(&sk->sk_receive_queue);
__skb_queue_head(&new_sk->sk_receive_queue, buf);
skb_set_owner_r(buf, new_sk);
}
__tipc_sendstream(new_sock, &m, 0);
release_sock(new_sk);
exit:
release_sock(sk);
Expand Down

0 comments on commit 10f5857

Please sign in to comment.