diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 101 |
1 files changed, 43 insertions, 58 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 8152a8135422..094cfdc1e2b6 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -1959,91 +1959,76 @@ static void tipc_sk_proto_rcv(struct sock *sk, | |||
1959 | } | 1959 | } |
1960 | 1960 | ||
1961 | /** | 1961 | /** |
1962 | * tipc_filter_connect - Handle incoming message for a connection-based socket | 1962 | * tipc_sk_filter_connect - check incoming message for a connection-based socket |
1963 | * @tsk: TIPC socket | 1963 | * @tsk: TIPC socket |
1964 | * @skb: pointer to message buffer. Set to NULL if buffer is consumed | 1964 | * @skb: pointer to message buffer. |
1965 | * | 1965 | * Returns true if message should be added to receive queue, false otherwise |
1966 | * Returns true if everything ok, false otherwise | ||
1967 | */ | 1966 | */ |
1968 | static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) | 1967 | static bool tipc_sk_filter_connect(struct tipc_sock *tsk, struct sk_buff *skb) |
1969 | { | 1968 | { |
1970 | struct sock *sk = &tsk->sk; | 1969 | struct sock *sk = &tsk->sk; |
1971 | struct net *net = sock_net(sk); | 1970 | struct net *net = sock_net(sk); |
1972 | struct tipc_msg *hdr = buf_msg(skb); | 1971 | struct tipc_msg *hdr = buf_msg(skb); |
1973 | u32 pport = msg_origport(hdr); | 1972 | bool con_msg = msg_connected(hdr); |
1974 | u32 pnode = msg_orignode(hdr); | 1973 | u32 pport = tsk_peer_port(tsk); |
1974 | u32 pnode = tsk_peer_node(tsk); | ||
1975 | u32 oport = msg_origport(hdr); | ||
1976 | u32 onode = msg_orignode(hdr); | ||
1977 | int err = msg_errcode(hdr); | ||
1975 | 1978 | ||
1976 | if (unlikely(msg_mcast(hdr))) | 1979 | if (unlikely(msg_mcast(hdr))) |
1977 | return false; | 1980 | return false; |
1978 | 1981 | ||
1979 | switch (sk->sk_state) { | 1982 | switch (sk->sk_state) { |
1980 | case TIPC_CONNECTING: | 1983 | case TIPC_CONNECTING: |
1981 | /* Accept only ACK or NACK message */ | 1984 | /* Setup ACK */ |
1982 | if (unlikely(!msg_connected(hdr))) { | 1985 | if (likely(con_msg)) { |
1983 | if (pport != tsk_peer_port(tsk) || | 1986 | if (err) |
1984 | pnode != tsk_peer_node(tsk)) | 1987 | break; |
1985 | return false; | 1988 | tipc_sk_finish_conn(tsk, oport, onode); |
1986 | 1989 | msg_set_importance(&tsk->phdr, msg_importance(hdr)); | |
1987 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | 1990 | /* ACK+ message with data is added to receive queue */ |
1988 | sk->sk_err = ECONNREFUSED; | 1991 | if (msg_data_sz(hdr)) |
1989 | sk->sk_state_change(sk); | 1992 | return true; |
1990 | return true; | 1993 | /* Empty ACK-, - wake up sleeping connect() and drop */ |
1991 | } | 1994 | sk->sk_data_ready(sk); |
1992 | 1995 | msg_set_dest_droppable(hdr, 1); | |
1993 | if (unlikely(msg_errcode(hdr))) { | 1996 | return false; |
1994 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | ||
1995 | sk->sk_err = ECONNREFUSED; | ||
1996 | sk->sk_state_change(sk); | ||
1997 | return true; | ||
1998 | } | ||
1999 | |||
2000 | if (unlikely(!msg_isdata(hdr))) { | ||
2001 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | ||
2002 | sk->sk_err = EINVAL; | ||
2003 | sk->sk_state_change(sk); | ||
2004 | return true; | ||
2005 | } | 1997 | } |
1998 | /* Ignore connectionless message if not from listening socket */ | ||
1999 | if (oport != pport || onode != pnode) | ||
2000 | return false; | ||
2006 | 2001 | ||
2007 | tipc_sk_finish_conn(tsk, msg_origport(hdr), msg_orignode(hdr)); | 2002 | /* Rejected SYN - abort */ |
2008 | msg_set_importance(&tsk->phdr, msg_importance(hdr)); | 2003 | break; |
2009 | |||
2010 | /* If 'ACK+' message, add to socket receive queue */ | ||
2011 | if (msg_data_sz(hdr)) | ||
2012 | return true; | ||
2013 | |||
2014 | /* If empty 'ACK-' message, wake up sleeping connect() */ | ||
2015 | sk->sk_data_ready(sk); | ||
2016 | |||
2017 | /* 'ACK-' message is neither accepted nor rejected: */ | ||
2018 | msg_set_dest_droppable(hdr, 1); | ||
2019 | return false; | ||
2020 | |||
2021 | case TIPC_OPEN: | 2004 | case TIPC_OPEN: |
2022 | case TIPC_DISCONNECTING: | 2005 | case TIPC_DISCONNECTING: |
2023 | break; | 2006 | return false; |
2024 | case TIPC_LISTEN: | 2007 | case TIPC_LISTEN: |
2025 | /* Accept only SYN message */ | 2008 | /* Accept only SYN message */ |
2026 | if (!msg_connected(hdr) && !(msg_errcode(hdr))) | 2009 | if (!con_msg && !err) |
2027 | return true; | 2010 | return true; |
2028 | break; | 2011 | return false; |
2029 | case TIPC_ESTABLISHED: | 2012 | case TIPC_ESTABLISHED: |
2030 | /* Accept only connection-based messages sent by peer */ | 2013 | /* Accept only connection-based messages sent by peer */ |
2031 | if (unlikely(!tsk_peer_msg(tsk, hdr))) | 2014 | if (likely(con_msg && !err && pport == oport && pnode == onode)) |
2015 | return true; | ||
2016 | if (!tsk_peer_msg(tsk, hdr)) | ||
2032 | return false; | 2017 | return false; |
2033 | 2018 | if (!err) | |
2034 | if (unlikely(msg_errcode(hdr))) { | 2019 | return true; |
2035 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); | 2020 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
2036 | /* Let timer expire on it's own */ | 2021 | tipc_node_remove_conn(net, pnode, tsk->portid); |
2037 | tipc_node_remove_conn(net, tsk_peer_node(tsk), | 2022 | sk->sk_state_change(sk); |
2038 | tsk->portid); | ||
2039 | sk->sk_state_change(sk); | ||
2040 | } | ||
2041 | return true; | 2023 | return true; |
2042 | default: | 2024 | default: |
2043 | pr_err("Unknown sk_state %u\n", sk->sk_state); | 2025 | pr_err("Unknown sk_state %u\n", sk->sk_state); |
2044 | } | 2026 | } |
2045 | 2027 | /* Abort connection setup attempt */ | |
2046 | return false; | 2028 | tipc_set_sk_state(sk, TIPC_DISCONNECTING); |
2029 | sk->sk_err = ECONNREFUSED; | ||
2030 | sk->sk_state_change(sk); | ||
2031 | return true; | ||
2047 | } | 2032 | } |
2048 | 2033 | ||
2049 | /** | 2034 | /** |