return true;
 exit:
        kfree_skb(buf);
+       *dnode = 0;
        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
- *
+ * tipc_msg_lookup_dest(): try to find new destination for named message
+ * @skb: the buffer containing the message.
+ * @dnode: return value: next-hop node, if destination found
+ * @err: return value: 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
+ * Returns true if a destination is found, false otherwise
  */
-int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode)
+bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb,
+                         u32 *dnode, int *err)
 {
-       struct tipc_msg *msg = buf_msg(buf);
+       struct tipc_msg *msg = buf_msg(skb);
        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_isdata(msg))
+               return false;
+       if (!msg_named(msg))
+               return false;
+       *err = -TIPC_ERR_NO_NAME;
+       if (skb_linearize(skb))
+               return false;
        if (msg_reroute_cnt(msg) > 0)
-               return -TIPC_ERR_NO_NAME;
-
+               return false;
        *dnode = addr_domain(net, msg_lookup_scope(msg));
        dport = tipc_nametbl_translate(net, msg_nametype(msg),
-                                      msg_nameinst(msg),
-                                      dnode);
+                                      msg_nameinst(msg), dnode);
        if (!dport)
-               return -TIPC_ERR_NO_NAME;
+               return false;
        msg_incr_reroute_cnt(msg);
        msg_set_destnode(msg, *dnode);
        msg_set_destport(msg, dport);
-       return TIPC_OK;
+       *err = TIPC_OK;
+       return true;
 }
 
 /* tipc_msg_reassemble() - clone a buffer chain of fragments and
 
 struct sk_buff *tipc_buf_acquire(u32 size);
 bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode,
                      int err);
-int tipc_msg_eval(struct net *net, struct sk_buff *buf, u32 *dnode);
 void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,
                   u32 hsize, u32 destnode);
-struct sk_buff *tipc_msg_create(uint user, uint type,
-                               uint hdr_sz, uint data_sz, u32 dnode,
-                               u32 onode, u32 dport, u32 oport, int errcode);
+struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz,
+                               uint data_sz, u32 dnode, u32 onode,
+                               u32 dport, u32 oport, int errcode);
 int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf);
 bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu);
 bool tipc_msg_make_bundle(struct sk_buff_head *list,
                          struct sk_buff *skb, u32 mtu, u32 dnode);
 int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m,
                   int offset, int dsz, int mtu, struct sk_buff_head *list);
+bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, u32 *dnode,
+                         int *err);
 struct sk_buff *tipc_msg_reassemble(struct sk_buff_head *list);
 
 #endif
 
  * @sk: socket
  * @skb: message
  *
- * Caller must hold socket lock, but not port lock.
+ * Caller must hold socket lock
  *
  * Returns 0
  */
        struct tipc_net *tn;
        struct sock *sk;
        u32 dport = msg_destport(buf_msg(skb));
-       int err;
+       int err = -TIPC_ERR_NO_PORT;
        u32 dnode;
 
-       /* Validate destination and message */
+       /* Find destination */
        tsk = tipc_sk_lookup(net, dport);
-       if (unlikely(!tsk)) {
-               err = tipc_msg_eval(net, skb, &dnode);
-               goto exit;
-       }
-       sk = &tsk->sk;
-
-       spin_lock_bh(&sk->sk_lock.slock);
-       err = tipc_sk_enqueue_skb(sk, &skb);
-       spin_unlock_bh(&sk->sk_lock.slock);
-       sock_put(sk);
-exit:
-       if (unlikely(skb)) {
-               tn = net_generic(net, tipc_net_id);
-               if (!err || tipc_msg_reverse(tn->own_addr, skb, &dnode, -err))
-                       tipc_link_xmit_skb(net, skb, dnode, 0);
+       if (likely(tsk)) {
+               sk = &tsk->sk;
+               spin_lock_bh(&sk->sk_lock.slock);
+               err = tipc_sk_enqueue_skb(sk, &skb);
+               spin_unlock_bh(&sk->sk_lock.slock);
+               sock_put(sk);
        }
+       if (likely(!skb))
+               return 0;
+       if (tipc_msg_lookup_dest(net, skb, &dnode, &err))
+               goto xmit;
+       if (!err) {
+               dnode = msg_destnode(buf_msg(skb));
+               goto xmit;
+       }
+       tn = net_generic(net, tipc_net_id);
+       if (!tipc_msg_reverse(tn->own_addr, skb, &dnode, -err))
+               return -EHOSTUNREACH;
+xmit:
+       tipc_link_xmit_skb(net, skb, dnode, dport);
        return err ? -EHOSTUNREACH : 0;
 }