diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 3f03ddd0e35b..8152a8135422 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -2545,43 +2545,57 @@ static int tipc_shutdown(struct socket *sock, int how) | |||
2545 | return res; | 2545 | return res; |
2546 | } | 2546 | } |
2547 | 2547 | ||
2548 | static void tipc_sk_check_probing_state(struct sock *sk, | ||
2549 | struct sk_buff_head *list) | ||
2550 | { | ||
2551 | struct tipc_sock *tsk = tipc_sk(sk); | ||
2552 | u32 pnode = tsk_peer_node(tsk); | ||
2553 | u32 pport = tsk_peer_port(tsk); | ||
2554 | u32 self = tsk_own_node(tsk); | ||
2555 | u32 oport = tsk->portid; | ||
2556 | struct sk_buff *skb; | ||
2557 | |||
2558 | if (tsk->probe_unacked) { | ||
2559 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | ||
2560 | sk->sk_err = ECONNABORTED; | ||
2561 | tipc_node_remove_conn(sock_net(sk), pnode, pport); | ||
2562 | sk->sk_state_change(sk); | ||
2563 | return; | ||
2564 | } | ||
2565 | /* Prepare new probe */ | ||
2566 | skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 0, | ||
2567 | pnode, self, pport, oport, TIPC_OK); | ||
2568 | if (skb) | ||
2569 | __skb_queue_tail(list, skb); | ||
2570 | tsk->probe_unacked = true; | ||
2571 | sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); | ||
2572 | } | ||
2573 | |||
2548 | static void tipc_sk_timeout(struct timer_list *t) | 2574 | static void tipc_sk_timeout(struct timer_list *t) |
2549 | { | 2575 | { |
2550 | struct sock *sk = from_timer(sk, t, sk_timer); | 2576 | struct sock *sk = from_timer(sk, t, sk_timer); |
2551 | struct tipc_sock *tsk = tipc_sk(sk); | 2577 | struct tipc_sock *tsk = tipc_sk(sk); |
2552 | u32 peer_port = tsk_peer_port(tsk); | 2578 | u32 pnode = tsk_peer_node(tsk); |
2553 | u32 peer_node = tsk_peer_node(tsk); | 2579 | struct sk_buff_head list; |
2554 | u32 own_node = tsk_own_node(tsk); | ||
2555 | u32 own_port = tsk->portid; | ||
2556 | struct net *net = sock_net(sk); | ||
2557 | struct sk_buff *skb = NULL; | ||
2558 | 2580 | ||
2581 | skb_queue_head_init(&list); | ||
2559 | bh_lock_sock(sk); | 2582 | bh_lock_sock(sk); |
2560 | if (!tipc_sk_connected(sk)) | ||
2561 | goto exit; | ||
2562 | 2583 | ||
2563 | /* Try again later if socket is busy */ | 2584 | /* Try again later if socket is busy */ |
2564 | if (sock_owned_by_user(sk)) { | 2585 | if (sock_owned_by_user(sk)) { |
2565 | sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 20); | 2586 | sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 20); |
2566 | goto exit; | 2587 | bh_unlock_sock(sk); |
2588 | return; | ||
2567 | } | 2589 | } |
2568 | 2590 | ||
2569 | if (tsk->probe_unacked) { | 2591 | if (sk->sk_state == TIPC_ESTABLISHED) |
2570 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | 2592 | tipc_sk_check_probing_state(sk, &list); |
2571 | tipc_node_remove_conn(net, peer_node, peer_port); | 2593 | |
2572 | sk->sk_state_change(sk); | ||
2573 | goto exit; | ||
2574 | } | ||
2575 | /* Send new probe */ | ||
2576 | skb = tipc_msg_create(CONN_MANAGER, CONN_PROBE, INT_H_SIZE, 0, | ||
2577 | peer_node, own_node, peer_port, own_port, | ||
2578 | TIPC_OK); | ||
2579 | tsk->probe_unacked = true; | ||
2580 | sk_reset_timer(sk, &sk->sk_timer, jiffies + CONN_PROBING_INTV); | ||
2581 | exit: | ||
2582 | bh_unlock_sock(sk); | 2594 | bh_unlock_sock(sk); |
2583 | if (skb) | 2595 | |
2584 | tipc_node_xmit_skb(net, skb, peer_node, own_port); | 2596 | if (!skb_queue_empty(&list)) |
2597 | tipc_node_xmit(sock_net(sk), &list, pnode, tsk->portid); | ||
2598 | |||
2585 | sock_put(sk); | 2599 | sock_put(sk); |
2586 | } | 2600 | } |
2587 | 2601 | ||