#include "core.h"
#include "msg.h"
+#include "addr.h"
+#include "name_table.h"
#define MAX_FORWARD_SIZE 1024
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;
+}
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);
/*
* 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.
*
* 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;
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)) {
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;
}
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)