struct tipc_msg ohdr;
        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;
-       if (msg_dest_droppable(msg) || msg_errcode(msg))
+       if (msg_errcode(msg))
                goto exit;
 
        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_origport(msg, msg_destport(&ohdr));
        msg_set_destport(msg, msg_origport(&ohdr));
 
 
 /* Connection management: */
 #define PROBING_INTERVAL 3600000       /* [ms] => 1 h */
-#define CONFIRMED 0
-#define PROBING 1
 
 #define MAX_REJECT_SIZE 1024
 
        }
 
        /* 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);
        } else {
                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);
        }
        tipc_port_unlock(p_ptr);
        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)
 {
        struct publication *publ;
        msg_set_hdr_sz(msg, SHORT_H_SIZE);
 
        p_ptr->probing_interval = PROBING_INTERVAL;
-       p_ptr->probing_state = CONFIRMED;
+       p_ptr->probing_state = TIPC_CONN_OK;
        p_ptr->connected = 1;
        k_start_timer(&p_ptr->timer, p_ptr->probing_interval);
 
 
                         unsigned int len);
 
 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_reinit(void);
 
 
 #define SS_READY       -2      /* socket is connectionless */
 
 #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 void tipc_data_ready(struct sock *sk);
        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: destination address
  * 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
- * 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)
 {
        struct tipc_sock *tsk = tipc_sk(sk);
        struct tipc_msg *msg = buf_msg(buf);
        unsigned int limit = rcvbuf_limit(sk, buf);
+       u32 onode;
        int rc = TIPC_OK;
 
-       if (unlikely(msg_user(msg) == CONN_MANAGER)) {
-               tipc_port_proto_rcv(&tsk->port, buf);
-               return TIPC_OK;
-       }
+       if (unlikely(msg_user(msg) == CONN_MANAGER))
+               return tipc_sk_proto_rcv(tsk, &onode, buf);
 
        /* Reject message if it is wrong sort of message for socket */
        if (msg_type(msg) > TIPC_DIRECT_MSG)
 
        rc = filter_rcv(sk, buf);
 
-       if (unlikely(rc && tipc_msg_reverse(buf, &onode, -rc)))
-               tipc_link_xmit2(buf, onode, 0);
-       else if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT)
-               atomic_add(truesize, &tsk->dupl_rcvcnt);
+       if (likely(!rc)) {
+               if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT)
+                       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;
 }
 
 #include "port.h"
 #include <net/sock.h>
 
+#define TIPC_CONN_OK      0
+#define TIPC_CONN_PROBING 1
+
 /**
  * struct tipc_sock - TIPC socket structure
  * @sk: socket - interacts with 'port' and with user via the socket API