|
@@ -55,6 +55,7 @@ enum {
|
|
TIPC_ESTABLISHED = TCP_ESTABLISHED,
|
|
TIPC_ESTABLISHED = TCP_ESTABLISHED,
|
|
TIPC_OPEN = TCP_CLOSE,
|
|
TIPC_OPEN = TCP_CLOSE,
|
|
TIPC_DISCONNECTING = TCP_CLOSE_WAIT,
|
|
TIPC_DISCONNECTING = TCP_CLOSE_WAIT,
|
|
|
|
+ TIPC_CONNECTING = TCP_SYN_SENT,
|
|
};
|
|
};
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -349,7 +350,6 @@ static bool tsk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
|
|
*/
|
|
*/
|
|
static int tipc_set_sk_state(struct sock *sk, int state)
|
|
static int tipc_set_sk_state(struct sock *sk, int state)
|
|
{
|
|
{
|
|
- int oldstate = sk->sk_socket->state;
|
|
|
|
int oldsk_state = sk->sk_state;
|
|
int oldsk_state = sk->sk_state;
|
|
int res = -EINVAL;
|
|
int res = -EINVAL;
|
|
|
|
|
|
@@ -358,16 +358,17 @@ static int tipc_set_sk_state(struct sock *sk, int state)
|
|
res = 0;
|
|
res = 0;
|
|
break;
|
|
break;
|
|
case TIPC_LISTEN:
|
|
case TIPC_LISTEN:
|
|
|
|
+ case TIPC_CONNECTING:
|
|
if (oldsk_state == TIPC_OPEN)
|
|
if (oldsk_state == TIPC_OPEN)
|
|
res = 0;
|
|
res = 0;
|
|
break;
|
|
break;
|
|
case TIPC_ESTABLISHED:
|
|
case TIPC_ESTABLISHED:
|
|
- if (oldstate == SS_CONNECTING ||
|
|
|
|
|
|
+ if (oldsk_state == TIPC_CONNECTING ||
|
|
oldsk_state == TIPC_OPEN)
|
|
oldsk_state == TIPC_OPEN)
|
|
res = 0;
|
|
res = 0;
|
|
break;
|
|
break;
|
|
case TIPC_DISCONNECTING:
|
|
case TIPC_DISCONNECTING:
|
|
- if (oldstate == SS_CONNECTING ||
|
|
|
|
|
|
+ if (oldsk_state == TIPC_CONNECTING ||
|
|
oldsk_state == TIPC_ESTABLISHED)
|
|
oldsk_state == TIPC_ESTABLISHED)
|
|
res = 0;
|
|
res = 0;
|
|
break;
|
|
break;
|
|
@@ -689,16 +690,12 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
|
|
if (sk->sk_shutdown == SHUTDOWN_MASK)
|
|
if (sk->sk_shutdown == SHUTDOWN_MASK)
|
|
mask |= POLLHUP;
|
|
mask |= POLLHUP;
|
|
|
|
|
|
- switch ((int)sock->state) {
|
|
|
|
- case SS_CONNECTED:
|
|
|
|
|
|
+ if ((int)sock->state == SS_CONNECTED) {
|
|
if (!tsk->link_cong && !tsk_conn_cong(tsk))
|
|
if (!tsk->link_cong && !tsk_conn_cong(tsk))
|
|
mask |= POLLOUT;
|
|
mask |= POLLOUT;
|
|
- /* fall thru' */
|
|
|
|
- case SS_CONNECTING:
|
|
|
|
if (!skb_queue_empty(&sk->sk_receive_queue))
|
|
if (!skb_queue_empty(&sk->sk_receive_queue))
|
|
mask |= (POLLIN | POLLRDNORM);
|
|
mask |= (POLLIN | POLLRDNORM);
|
|
- break;
|
|
|
|
- default:
|
|
|
|
|
|
+ } else {
|
|
switch (sk->sk_state) {
|
|
switch (sk->sk_state) {
|
|
case TIPC_OPEN:
|
|
case TIPC_OPEN:
|
|
if (!tsk->link_cong)
|
|
if (!tsk->link_cong)
|
|
@@ -711,6 +708,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
|
|
mask = (POLLIN | POLLRDNORM | POLLHUP);
|
|
mask = (POLLIN | POLLRDNORM | POLLHUP);
|
|
break;
|
|
break;
|
|
case TIPC_LISTEN:
|
|
case TIPC_LISTEN:
|
|
|
|
+ case TIPC_CONNECTING:
|
|
if (!skb_queue_empty(&sk->sk_receive_queue))
|
|
if (!skb_queue_empty(&sk->sk_receive_queue))
|
|
mask |= (POLLIN | POLLRDNORM);
|
|
mask |= (POLLIN | POLLRDNORM);
|
|
break;
|
|
break;
|
|
@@ -1014,7 +1012,7 @@ new_mtu:
|
|
rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
|
|
rc = tipc_node_xmit(net, &pktchain, dnode, tsk->portid);
|
|
if (likely(!rc)) {
|
|
if (likely(!rc)) {
|
|
if (!is_connectionless)
|
|
if (!is_connectionless)
|
|
- sock->state = SS_CONNECTING;
|
|
|
|
|
|
+ tipc_set_sk_state(sk, TIPC_CONNECTING);
|
|
return dsz;
|
|
return dsz;
|
|
}
|
|
}
|
|
if (rc == -ELINKCONG) {
|
|
if (rc == -ELINKCONG) {
|
|
@@ -1650,9 +1648,10 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
|
|
sk->sk_state_change(sk);
|
|
sk->sk_state_change(sk);
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
|
|
+ }
|
|
|
|
|
|
- case SS_CONNECTING:
|
|
|
|
-
|
|
|
|
|
|
+ switch (sk->sk_state) {
|
|
|
|
+ case TIPC_CONNECTING:
|
|
/* Accept only ACK or NACK message */
|
|
/* Accept only ACK or NACK message */
|
|
if (unlikely(!msg_connected(hdr)))
|
|
if (unlikely(!msg_connected(hdr)))
|
|
return false;
|
|
return false;
|
|
@@ -1684,9 +1683,7 @@ static bool filter_connect(struct tipc_sock *tsk, struct sk_buff *skb)
|
|
/* 'ACK-' message is neither accepted nor rejected: */
|
|
/* 'ACK-' message is neither accepted nor rejected: */
|
|
msg_set_dest_droppable(hdr, 1);
|
|
msg_set_dest_droppable(hdr, 1);
|
|
return false;
|
|
return false;
|
|
- }
|
|
|
|
|
|
|
|
- switch (sk->sk_state) {
|
|
|
|
case TIPC_OPEN:
|
|
case TIPC_OPEN:
|
|
case TIPC_DISCONNECTING:
|
|
case TIPC_DISCONNECTING:
|
|
break;
|
|
break;
|
|
@@ -1955,7 +1952,8 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
|
|
return sock_intr_errno(*timeo_p);
|
|
return sock_intr_errno(*timeo_p);
|
|
|
|
|
|
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
|
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
|
|
- done = sk_wait_event(sk, timeo_p, sock->state != SS_CONNECTING);
|
|
|
|
|
|
+ done = sk_wait_event(sk, timeo_p,
|
|
|
|
+ sk->sk_state != TIPC_CONNECTING);
|
|
finish_wait(sk_sleep(sk), &wait);
|
|
finish_wait(sk_sleep(sk), &wait);
|
|
} while (!done);
|
|
} while (!done);
|
|
return 0;
|
|
return 0;
|
|
@@ -1978,7 +1976,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
|
|
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
|
|
struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
|
|
struct msghdr m = {NULL,};
|
|
struct msghdr m = {NULL,};
|
|
long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
|
|
long timeout = (flags & O_NONBLOCK) ? 0 : tsk->conn_timeout;
|
|
- socket_state previous;
|
|
|
|
|
|
+ int previous;
|
|
int res = 0;
|
|
int res = 0;
|
|
|
|
|
|
lock_sock(sk);
|
|
lock_sock(sk);
|
|
@@ -2006,7 +2004,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
|
|
goto exit;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
- previous = sock->state;
|
|
|
|
|
|
+ previous = sk->sk_state;
|
|
|
|
|
|
switch (sk->sk_state) {
|
|
switch (sk->sk_state) {
|
|
case TIPC_OPEN:
|
|
case TIPC_OPEN:
|
|
@@ -2024,31 +2022,29 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
|
|
if ((res < 0) && (res != -EWOULDBLOCK))
|
|
if ((res < 0) && (res != -EWOULDBLOCK))
|
|
goto exit;
|
|
goto exit;
|
|
|
|
|
|
- /* Just entered SS_CONNECTING state; the only
|
|
|
|
|
|
+ /* Just entered TIPC_CONNECTING state; the only
|
|
* difference is that return value in non-blocking
|
|
* difference is that return value in non-blocking
|
|
* case is EINPROGRESS, rather than EALREADY.
|
|
* case is EINPROGRESS, rather than EALREADY.
|
|
*/
|
|
*/
|
|
res = -EINPROGRESS;
|
|
res = -EINPROGRESS;
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- switch (sock->state) {
|
|
|
|
- case SS_CONNECTING:
|
|
|
|
- if (previous == SS_CONNECTING)
|
|
|
|
- res = -EALREADY;
|
|
|
|
- if (!timeout)
|
|
|
|
|
|
+ /* fall thru' */
|
|
|
|
+ case TIPC_CONNECTING:
|
|
|
|
+ if (!timeout) {
|
|
|
|
+ if (previous == TIPC_CONNECTING)
|
|
|
|
+ res = -EALREADY;
|
|
goto exit;
|
|
goto exit;
|
|
|
|
+ }
|
|
timeout = msecs_to_jiffies(timeout);
|
|
timeout = msecs_to_jiffies(timeout);
|
|
/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
|
|
/* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
|
|
res = tipc_wait_for_connect(sock, &timeout);
|
|
res = tipc_wait_for_connect(sock, &timeout);
|
|
- break;
|
|
|
|
- case SS_CONNECTED:
|
|
|
|
|
|
+ goto exit;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (sock->state == SS_CONNECTED)
|
|
res = -EISCONN;
|
|
res = -EISCONN;
|
|
- break;
|
|
|
|
- default:
|
|
|
|
|
|
+ else
|
|
res = -EINVAL;
|
|
res = -EINVAL;
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
exit:
|
|
exit:
|
|
release_sock(sk);
|
|
release_sock(sk);
|
|
return res;
|
|
return res;
|