summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/tipc/msg.c38
-rw-r--r--net/tipc/msg.h2
-rw-r--r--net/tipc/net.c33
-rw-r--r--net/tipc/socket.c16
4 files changed, 51 insertions, 38 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 6070dd0ec634..7bfc4422bf2c 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -36,6 +36,8 @@
#include "core.h"
#include "msg.h"
+#include "addr.h"
+#include "name_table.h"
#define MAX_FORWARD_SIZE 1024
@@ -370,3 +372,39 @@ exit:
kfree_skb(buf);
return false;
}
+
+/**
+ * tipc_msg_eval: determine fate of message that found no destination
+ * @buf: the buffer containing the message.
+ * @dnode: return value: next-hop node, if message to be forwarded
+ * @err: error code to use, if message to be rejected
+ *
+ * Does not consume buffer
+ * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error
+ * code if message to be rejected
+ */
+int tipc_msg_eval(struct sk_buff *buf, u32 *dnode)
+{
+ struct tipc_msg *msg = buf_msg(buf);
+ u32 dport;
+
+ if (msg_type(msg) != TIPC_NAMED_MSG)
+ return -TIPC_ERR_NO_PORT;
+ if (skb_linearize(buf))
+ return -TIPC_ERR_NO_NAME;
+ if (msg_data_sz(msg) > MAX_FORWARD_SIZE)
+ return -TIPC_ERR_NO_NAME;
+ if (msg_reroute_cnt(msg) > 0)
+ return -TIPC_ERR_NO_NAME;
+
+ *dnode = addr_domain(msg_lookup_scope(msg));
+ dport = tipc_nametbl_translate(msg_nametype(msg),
+ msg_nameinst(msg),
+ dnode);
+ if (!dport)
+ return -TIPC_ERR_NO_NAME;
+ msg_incr_reroute_cnt(msg);
+ msg_set_destnode(msg, *dnode);
+ msg_set_destport(msg, dport);
+ return TIPC_OK;
+}
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 38050941a504..7d574346e75e 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -727,6 +727,8 @@ static inline u32 msg_tot_origport(struct tipc_msg *m)
bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err);
+int tipc_msg_eval(struct sk_buff *buf, u32 *dnode);
+
void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize,
u32 destnode);
diff --git a/net/tipc/net.c b/net/tipc/net.c
index f64375e7f99f..5f7d6ffb5465 100644
--- a/net/tipc/net.c
+++ b/net/tipc/net.c
@@ -1,7 +1,7 @@
/*
* net/tipc/net.c: TIPC network routing code
*
- * Copyright (c) 1995-2006, Ericsson AB
+ * Copyright (c) 1995-2006, 2014, Ericsson AB
* Copyright (c) 2005, 2010-2011, Wind River Systems
* All rights reserved.
*
@@ -103,29 +103,6 @@
* This is always used within the scope of a tipc_nametbl_lock(read).
* - A local spin_lock protecting the queue of subscriber events.
*/
-
-static void net_route_named_msg(struct sk_buff *buf)
-{
- struct tipc_msg *msg = buf_msg(buf);
- u32 dnode;
- u32 dport;
-
- if (!msg_named(msg)) {
- kfree_skb(buf);
- return;
- }
-
- dnode = addr_domain(msg_lookup_scope(msg));
- dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode);
- if (dport) {
- msg_set_destnode(msg, dnode);
- msg_set_destport(msg, dport);
- tipc_net_route_msg(buf);
- return;
- }
- tipc_reject_msg(buf, TIPC_ERR_NO_NAME);
-}
-
void tipc_net_route_msg(struct sk_buff *buf)
{
struct tipc_msg *msg;
@@ -141,10 +118,12 @@ void tipc_net_route_msg(struct sk_buff *buf)
if (msg_isdata(msg)) {
if (msg_mcast(msg))
tipc_port_mcast_rcv(buf, NULL);
- else if (msg_destport(msg))
+ else if (msg_destport(msg)) {
tipc_sk_rcv(buf);
- else
- net_route_named_msg(buf);
+ } else {
+ pr_warn("Cannot route msg; no destination\n");
+ kfree_skb(buf);
+ }
return;
}
switch (msg_user(msg)) {
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 5961a6335f49..e642ed5b3602 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -1466,16 +1466,10 @@ int tipc_sk_rcv(struct sk_buff *buf)
uint limit;
u32 dnode;
- /* Forward unresolved named message */
- if (unlikely(!dport)) {
- tipc_net_route_msg(buf);
- return 0;
- }
-
- /* Validate destination */
+ /* Validate destination and message */
port = tipc_port_lock(dport);
if (unlikely(!port)) {
- rc = -TIPC_ERR_NO_PORT;
+ rc = tipc_msg_eval(buf, &dnode);
goto exit;
}
@@ -1494,17 +1488,17 @@ int tipc_sk_rcv(struct sk_buff *buf)
if (sk_add_backlog(sk, buf, limit))
rc = -TIPC_ERR_OVERLOAD;
}
-
bh_unlock_sock(sk);
tipc_port_unlock(port);
if (likely(!rc))
return 0;
exit:
- if (!tipc_msg_reverse(buf, &dnode, -rc))
+ if ((rc < 0) && !tipc_msg_reverse(buf, &dnode, -rc))
return -EHOSTUNREACH;
+
tipc_link_xmit2(buf, dnode, 0);
- return -EHOSTUNREACH;
+ return (rc < 0) ? -EHOSTUNREACH : 0;
}
static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)