Commit ac0074ee authored by Jon Paul Maloy's avatar Jon Paul Maloy Committed by David S. Miller

tipc: clean up connection protocol reception function

We simplify the code for receiving connection probes, leveraging the
recently introduced tipc_msg_reverse() function. We also stick to
the principle of sending a possible response message directly from
the calling (tipc_sk_rcv or backlog_rcv) functions, hence making
the call chain shallower and easier to follow.

We make one small protocol change here, allowed according to
the spec. If a protocol message arrives from a remote socket that
is not the one we are connected to, we are currently generating a
connection abort message and send it to the source. This behavior
is unnecessary, and might even be a security risk, so instead we
now choose to only ignore the message. The consequnce for the sender
is that he will need longer time to discover his mistake (until the
next timeout), but this is an extreme corner case, and may happen
anyway under other circumstances, so we deem this change acceptable.
Signed-off-by: default avatarJon Maloy <jon.maloy@ericsson.com>
Reviewed-by: default avatarErik Hugne <erik.hugne@ericsson.com>
Reviewed-by: default avatarYing Xue <ying.xue@windriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ec8a2e56
...@@ -348,13 +348,17 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) ...@@ -348,13 +348,17 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err)
struct tipc_msg ohdr; struct tipc_msg ohdr;
uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE); uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE);
if (skb_linearize(buf) || !msg_isdata(msg)) if (skb_linearize(buf))
goto exit;
if (msg_dest_droppable(msg))
goto exit; goto exit;
if (msg_dest_droppable(msg) || msg_errcode(msg)) if (msg_errcode(msg))
goto exit; goto exit;
memcpy(&ohdr, msg, msg_hdr_sz(msg)); memcpy(&ohdr, msg, msg_hdr_sz(msg));
msg_set_importance(msg, min_t(uint, ++imp, TIPC_CRITICAL_IMPORTANCE)); imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE);
if (msg_isdata(msg))
msg_set_importance(msg, imp);
msg_set_errcode(msg, err); msg_set_errcode(msg, err);
msg_set_origport(msg, msg_destport(&ohdr)); msg_set_origport(msg, msg_destport(&ohdr));
msg_set_destport(msg, msg_origport(&ohdr)); msg_set_destport(msg, msg_origport(&ohdr));
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
/* Connection management: */ /* Connection management: */
#define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */
#define CONFIRMED 0
#define PROBING 1
#define MAX_REJECT_SIZE 1024 #define MAX_REJECT_SIZE 1024
...@@ -299,11 +297,11 @@ static void port_timeout(unsigned long ref) ...@@ -299,11 +297,11 @@ static void port_timeout(unsigned long ref)
} }
/* Last probe answered ? */ /* Last probe answered ? */
if (p_ptr->probing_state == PROBING) { if (p_ptr->probing_state == TIPC_CONN_PROBING) {
buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT);
} else { } else {
buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0);
p_ptr->probing_state = PROBING; p_ptr->probing_state = TIPC_CONN_PROBING;
k_start_timer(&p_ptr->timer, p_ptr->probing_interval); k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
} }
tipc_port_unlock(p_ptr); tipc_port_unlock(p_ptr);
...@@ -365,51 +363,6 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er ...@@ -365,51 +363,6 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er
return buf; return buf;
} }
void tipc_port_proto_rcv(struct tipc_port *p_ptr, struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
struct sk_buff *r_buf = NULL;
u32 destport = msg_destport(msg);
int wakeable;
/* Validate connection */
if (!p_ptr || !p_ptr->connected || !tipc_port_peer_msg(p_ptr, msg)) {
r_buf = tipc_buf_acquire(BASIC_H_SIZE);
if (r_buf) {
msg = buf_msg(r_buf);
tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG,
BASIC_H_SIZE, msg_orignode(msg));
msg_set_errcode(msg, TIPC_ERR_NO_PORT);
msg_set_origport(msg, destport);
msg_set_destport(msg, msg_origport(msg));
}
goto exit;
}
/* Process protocol message sent by peer */
switch (msg_type(msg)) {
case CONN_ACK:
wakeable = tipc_port_congested(p_ptr) && p_ptr->congested;
p_ptr->acked += msg_msgcnt(msg);
if (!tipc_port_congested(p_ptr)) {
p_ptr->congested = 0;
if (wakeable)
tipc_port_wakeup(p_ptr);
}
break;
case CONN_PROBE:
r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0);
break;
default:
/* CONN_PROBE_REPLY or unrecognized - no action required */
break;
}
p_ptr->probing_state = CONFIRMED;
exit:
tipc_link_xmit2(r_buf, msg_destnode(msg), msg_link_selector(msg));
kfree_skb(buf);
}
static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id)
{ {
struct publication *publ; struct publication *publ;
...@@ -613,7 +566,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, ...@@ -613,7 +566,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr,
msg_set_hdr_sz(msg, SHORT_H_SIZE); msg_set_hdr_sz(msg, SHORT_H_SIZE);
p_ptr->probing_interval = PROBING_INTERVAL; p_ptr->probing_interval = PROBING_INTERVAL;
p_ptr->probing_state = CONFIRMED; p_ptr->probing_state = TIPC_CONN_OK;
p_ptr->connected = 1; p_ptr->connected = 1;
k_start_timer(&p_ptr->timer, p_ptr->probing_interval); k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
......
...@@ -140,7 +140,6 @@ int tipc_port_mcast_xmit(struct tipc_port *port, ...@@ -140,7 +140,6 @@ int tipc_port_mcast_xmit(struct tipc_port *port,
unsigned int len); unsigned int len);
struct sk_buff *tipc_port_get_ports(void); struct sk_buff *tipc_port_get_ports(void);
void tipc_port_proto_rcv(struct tipc_port *port, struct sk_buff *buf);
void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp); void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp);
void tipc_port_reinit(void); void tipc_port_reinit(void);
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#define SS_READY -2 /* socket is connectionless */ #define SS_READY -2 /* socket is connectionless */
#define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */
#define TIPC_FWD_MSG 1
static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb);
static void tipc_data_ready(struct sock *sk); static void tipc_data_ready(struct sock *sk);
...@@ -533,6 +534,46 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, ...@@ -533,6 +534,46 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
return mask; return mask;
} }
/**
* tipc_sk_proto_rcv - receive a connection mng protocol message
* @tsk: receiving socket
* @dnode: node to send response message to, if any
* @buf: buffer containing protocol message
* Returns 0 (TIPC_OK) if message was consumed, 1 (TIPC_FWD_MSG) if
* (CONN_PROBE_REPLY) message should be forwarded.
*/
int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, struct sk_buff *buf)
{
struct tipc_msg *msg = buf_msg(buf);
struct tipc_port *port = &tsk->port;
int wakeable;
/* Ignore if connection cannot be validated: */
if (!port->connected || !tipc_port_peer_msg(port, msg))
goto exit;
port->probing_state = TIPC_CONN_OK;
if (msg_type(msg) == CONN_ACK) {
wakeable = tipc_port_congested(port) && port->congested;
port->acked += msg_msgcnt(msg);
if (!tipc_port_congested(port)) {
port->congested = 0;
if (wakeable)
tipc_port_wakeup(port);
}
} else if (msg_type(msg) == CONN_PROBE) {
if (!tipc_msg_reverse(buf, dnode, TIPC_OK))
return TIPC_OK;
msg_set_type(msg, CONN_PROBE_REPLY);
return TIPC_FWD_MSG;
}
/* Do nothing if msg_type() == CONN_PROBE_REPLY */
exit:
kfree_skb(buf);
return TIPC_OK;
}
/** /**
* dest_name_check - verify user is permitted to send to specified port name * dest_name_check - verify user is permitted to send to specified port name
* @dest: destination address * @dest: destination address
...@@ -1406,7 +1447,7 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) ...@@ -1406,7 +1447,7 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf)
* Called with socket lock already taken; port lock may also be taken. * Called with socket lock already taken; port lock may also be taken.
* *
* Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message * Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message
* to be rejected. * to be rejected, 1 (TIPC_FWD_MSG) if (CONN_MANAGER) message to be forwarded
*/ */
static int filter_rcv(struct sock *sk, struct sk_buff *buf) static int filter_rcv(struct sock *sk, struct sk_buff *buf)
{ {
...@@ -1414,12 +1455,11 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf) ...@@ -1414,12 +1455,11 @@ static int filter_rcv(struct sock *sk, struct sk_buff *buf)
struct tipc_sock *tsk = tipc_sk(sk); struct tipc_sock *tsk = tipc_sk(sk);
struct tipc_msg *msg = buf_msg(buf); struct tipc_msg *msg = buf_msg(buf);
unsigned int limit = rcvbuf_limit(sk, buf); unsigned int limit = rcvbuf_limit(sk, buf);
u32 onode;
int rc = TIPC_OK; int rc = TIPC_OK;
if (unlikely(msg_user(msg) == CONN_MANAGER)) { if (unlikely(msg_user(msg) == CONN_MANAGER))
tipc_port_proto_rcv(&tsk->port, buf); return tipc_sk_proto_rcv(tsk, &onode, buf);
return TIPC_OK;
}
/* Reject message if it is wrong sort of message for socket */ /* Reject message if it is wrong sort of message for socket */
if (msg_type(msg) > TIPC_DIRECT_MSG) if (msg_type(msg) > TIPC_DIRECT_MSG)
...@@ -1465,10 +1505,16 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf) ...@@ -1465,10 +1505,16 @@ static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf)
rc = filter_rcv(sk, buf); rc = filter_rcv(sk, buf);
if (unlikely(rc && tipc_msg_reverse(buf, &onode, -rc))) if (likely(!rc)) {
tipc_link_xmit2(buf, onode, 0); if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT)
else if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT)
atomic_add(truesize, &tsk->dupl_rcvcnt); atomic_add(truesize, &tsk->dupl_rcvcnt);
return 0;
}
if ((rc < 0) && !tipc_msg_reverse(buf, &onode, -rc))
return 0;
tipc_link_xmit2(buf, onode, 0);
return 0; return 0;
} }
......
...@@ -38,6 +38,9 @@ ...@@ -38,6 +38,9 @@
#include "port.h" #include "port.h"
#include <net/sock.h> #include <net/sock.h>
#define TIPC_CONN_OK 0
#define TIPC_CONN_PROBING 1
/** /**
* struct tipc_sock - TIPC socket structure * struct tipc_sock - TIPC socket structure
* @sk: socket - interacts with 'port' and with user via the socket API * @sk: socket - interacts with 'port' and with user via the socket API
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment