#include <crypto/aes.h>
 #include "crypto.h"
 
-#define TIPC_TX_PROBE_LIM      msecs_to_jiffies(1000) /* > 1s */
-#define TIPC_TX_LASTING_LIM    msecs_to_jiffies(120000) /* 2 mins */
+#define TIPC_TX_LASTING_TIME   msecs_to_jiffies(10000) /* 10s */
 #define TIPC_RX_ACTIVE_LIM     msecs_to_jiffies(3000) /* 3s */
-#define TIPC_RX_PASSIVE_LIM    msecs_to_jiffies(180000) /* 3 mins */
+#define TIPC_RX_PASSIVE_LIM    msecs_to_jiffies(15000) /* 15s */
+
 #define TIPC_MAX_TFMS_DEF      10
 #define TIPC_MAX_TFMS_LIM      1000
 
        u32 salt;
        u8 authsize;
        u8 mode;
-       char hint[TIPC_AEAD_HINT_LEN + 1];
+       char hint[2 * TIPC_AEAD_HINT_LEN + 1];
        struct rcu_head rcu;
 
        atomic64_t seqno ____cacheline_aligned;
  * @key: the key states
  * @working: the crypto is working or not
  * @stats: the crypto statistics
+ * @name: the crypto name
  * @sndnxt: the per-peer sndnxt (TX)
  * @timer1: general timer 1 (jiffies)
- * @timer2: general timer 1 (jiffies)
+ * @timer2: general timer 2 (jiffies)
  * @lock: tipc_key lock
  */
 struct tipc_crypto {
        struct tipc_key key;
        u8 working:1;
        struct tipc_crypto_stats __percpu *stats;
+       char name[48];
 
        atomic64_t sndnxt ____cacheline_aligned;
        unsigned long timer1;
 static struct tipc_aead *tipc_crypto_key_pick_tx(struct tipc_crypto *tx,
                                                 struct tipc_crypto *rx,
                                                 struct sk_buff *skb);
-static void tipc_crypto_key_synch(struct tipc_crypto *rx, u8 new_rx_active,
-                                 struct tipc_msg *hdr);
+static void tipc_crypto_key_synch(struct tipc_crypto *rx, struct sk_buff *skb);
 static int tipc_crypto_key_revoke(struct net *net, u8 tx_key);
 static void tipc_crypto_rcv_complete(struct net *net, struct tipc_aead *aead,
                                     struct tipc_bearer *b,
                                     struct sk_buff **skb, int err);
 static void tipc_crypto_do_cmd(struct net *net, int cmd);
 static char *tipc_crypto_key_dump(struct tipc_crypto *c, char *buf);
-#ifdef TIPC_CRYPTO_DEBUG
 static char *tipc_key_change_dump(struct tipc_key old, struct tipc_key new,
                                  char *buf);
-#endif
+#define is_tx(crypto) (!(crypto)->node)
+#define is_rx(crypto) (!is_tx(crypto))
 
 #define key_next(cur) ((cur) % KEY_MAX + 1)
 
 /**
  * tipc_aead_key_validate - Validate a AEAD user key
  */
-int tipc_aead_key_validate(struct tipc_aead_key *ukey)
+int tipc_aead_key_validate(struct tipc_aead_key *ukey, struct genl_info *info)
 {
        int keylen;
 
        /* Check if algorithm exists */
        if (unlikely(!crypto_has_alg(ukey->alg_name, 0, 0))) {
-               pr_info("Not found cipher: \"%s\"!\n", ukey->alg_name);
+               GENL_SET_ERR_MSG(info, "unable to load the algorithm (module existed?)");
                return -ENODEV;
        }
 
        /* Currently, we only support the "gcm(aes)" cipher algorithm */
-       if (strcmp(ukey->alg_name, "gcm(aes)"))
+       if (strcmp(ukey->alg_name, "gcm(aes)")) {
+               GENL_SET_ERR_MSG(info, "not supported yet the algorithm");
                return -ENOTSUPP;
+       }
 
        /* Check if key size is correct */
        keylen = ukey->keylen - TIPC_AES_GCM_SALT_SIZE;
        if (unlikely(keylen != TIPC_AES_GCM_KEY_SIZE_128 &&
                     keylen != TIPC_AES_GCM_KEY_SIZE_192 &&
-                    keylen != TIPC_AES_GCM_KEY_SIZE_256))
-               return -EINVAL;
+                    keylen != TIPC_AES_GCM_KEY_SIZE_256)) {
+               GENL_SET_ERR_MSG(info, "incorrect key length (20, 28 or 36 octets?)");
+               return -EKEYREJECTED;
+       }
 
        return 0;
 }
                return err;
        }
 
-       /* Copy some chars from the user key as a hint */
-       memcpy(tmp->hint, ukey->key, TIPC_AEAD_HINT_LEN);
-       tmp->hint[TIPC_AEAD_HINT_LEN] = '\0';
+       /* Form a hex string of some last bytes as the key's hint */
+       bin2hex(tmp->hint, ukey->key + keylen - TIPC_AEAD_HINT_LEN,
+               TIPC_AEAD_HINT_LEN);
 
        /* Initialize the other data */
        tmp->mode = mode;
         * but there is no frag_list, it should be still fine!
         * Otherwise, we must cow it to be a writable buffer with the tailroom.
         */
-#ifdef TIPC_CRYPTO_DEBUG
        SKB_LINEAR_ASSERT(skb);
        if (tailen > skb_tailroom(skb)) {
-               pr_warn("TX: skb tailroom is not enough: %d, requires: %d\n",
-                       skb_tailroom(skb), tailen);
+               pr_debug("TX(): skb tailroom is not enough: %d, requires: %d\n",
+                        skb_tailroom(skb), tailen);
        }
-#endif
 
        if (unlikely(!skb_cloned(skb) && tailen <= skb_tailroom(skb))) {
                nsg = 1;
                                             u8 new_active,
                                             u8 new_pending)
 {
-#ifdef TIPC_CRYPTO_DEBUG
        struct tipc_key old = c->key;
        char buf[32];
-#endif
 
        c->key.keys = ((new_passive & KEY_MASK) << (KEY_BITS * 2)) |
                      ((new_active  & KEY_MASK) << (KEY_BITS)) |
                      ((new_pending & KEY_MASK));
 
-#ifdef TIPC_CRYPTO_DEBUG
-       pr_info("%s(%s): key changing %s ::%pS\n",
-               (c->node) ? "RX" : "TX",
-               (c->node) ? tipc_node_get_id_str(c->node) :
-                           tipc_own_id_string(c->net),
-               tipc_key_change_dump(old, c->key, buf),
-               __builtin_return_address(0));
-#endif
+       pr_debug("%s: key changing %s ::%pS\n", c->name,
+                tipc_key_change_dump(old, c->key, buf),
+                __builtin_return_address(0));
 }
 
 /**
                        tipc_aead_free(&aead->rcu);
        }
 
-       pr_info("%s(%s): key initiating, rc %d!\n",
-               (c->node) ? "RX" : "TX",
-               (c->node) ? tipc_node_get_id_str(c->node) :
-                           tipc_own_id_string(c->net),
-               rc);
-
        return rc;
 }
 
 static int tipc_crypto_key_attach(struct tipc_crypto *c,
                                  struct tipc_aead *aead, u8 pos)
 {
-       u8 new_pending, new_passive, new_key;
        struct tipc_key key;
        int rc = -EBUSY;
+       u8 new_key;
 
        spin_lock_bh(&c->lock);
        key = c->key;
        if (key.active && key.passive)
                goto exit;
-       if (key.passive && !tipc_aead_users(c->aead[key.passive]))
-               goto exit;
        if (key.pending) {
-               if (pos)
-                       goto exit;
                if (tipc_aead_users(c->aead[key.pending]) > 0)
                        goto exit;
+               /* if (pos): ok with replacing, will be aligned when needed */
                /* Replace it */
-               new_pending = key.pending;
-               new_passive = key.passive;
-               new_key = new_pending;
+               new_key = key.pending;
        } else {
                if (pos) {
                        if (key.active && pos != key_next(key.active)) {
-                               new_pending = key.pending;
-                               new_passive = pos;
-                               new_key = new_passive;
+                               key.passive = pos;
+                               new_key = pos;
                                goto attach;
                        } else if (!key.active && !key.passive) {
-                               new_pending = pos;
-                               new_passive = key.passive;
-                               new_key = new_pending;
+                               key.pending = pos;
+                               new_key = pos;
                                goto attach;
                        }
                }
-               new_pending = key_next(key.active ?: key.passive);
-               new_passive = key.passive;
-               new_key = new_pending;
+               key.pending = key_next(key.active ?: key.passive);
+               new_key = key.pending;
        }
 
 attach:
        aead->crypto = c;
-       tipc_crypto_key_set_state(c, new_passive, key.active, new_pending);
        tipc_aead_rcu_replace(c->aead[new_key], aead, &c->lock);
-
+       if (likely(c->key.keys != key.keys))
+               tipc_crypto_key_set_state(c, key.passive, key.active,
+                                         key.pending);
        c->working = 1;
        c->timer1 = jiffies;
        c->timer2 = jiffies;
                rcu_assign_pointer(rx->aead[new_passive], tmp2);
        refcount_set(&tmp1->refcnt, 1);
        aligned = true;
-       pr_info("RX(%s): key is aligned!\n", tipc_node_get_id_str(rx->node));
+       pr_info_ratelimited("%s: key[%d] -> key[%d]\n", rx->name, key.pending,
+                           new_pending);
 
 exit:
        spin_unlock(&rx->lock);
 /**
  * tipc_crypto_key_synch: Synch own key data according to peer key status
  * @rx: RX crypto handle
- * @new_rx_active: latest RX active key from peer
- * @hdr: TIPCv2 message
+ * @skb: TIPCv2 message buffer (incl. the ehdr from peer)
  *
  * This function updates the peer node related data as the peer RX active key
  * has changed, so the number of TX keys' users on this node are increased and
  *
  * The "per-peer" sndnxt is also reset when the peer key has switched.
  */
-static void tipc_crypto_key_synch(struct tipc_crypto *rx, u8 new_rx_active,
-                                 struct tipc_msg *hdr)
+static void tipc_crypto_key_synch(struct tipc_crypto *rx, struct sk_buff *skb)
 {
-       struct net *net = rx->net;
-       struct tipc_crypto *tx = tipc_net(net)->crypto_tx;
-       u8 cur_rx_active;
-
-       /* TX might be even not ready yet */
-       if (unlikely(!tx->key.active && !tx->key.pending))
-               return;
-
-       cur_rx_active = atomic_read(&rx->peer_rx_active);
-       if (likely(cur_rx_active == new_rx_active))
-               return;
+       struct tipc_ehdr *ehdr = (struct tipc_ehdr *)skb_network_header(skb);
+       struct tipc_crypto *tx = tipc_net(rx->net)->crypto_tx;
+       struct tipc_msg *hdr = buf_msg(skb);
+       u32 self = tipc_own_addr(rx->net);
+       u8 cur, new;
 
-       /* Make sure this message destined for this node */
-       if (unlikely(msg_short(hdr) ||
-                    msg_destnode(hdr) != tipc_own_addr(net)))
+       /* Ensure this message is destined to us first */
+       if (!ehdr->destined || msg_short(hdr) || msg_destnode(hdr) != self)
                return;
 
-       /* Peer RX active key has changed, try to update owns' & TX users */
-       if (atomic_cmpxchg(&rx->peer_rx_active,
-                          cur_rx_active,
-                          new_rx_active) == cur_rx_active) {
-               if (new_rx_active)
-                       tipc_aead_users_inc(tx->aead[new_rx_active], INT_MAX);
-               if (cur_rx_active)
-                       tipc_aead_users_dec(tx->aead[cur_rx_active], 0);
+       /* Peer RX active key has changed, let's update own TX users */
+       cur = atomic_read(&rx->peer_rx_active);
+       new = ehdr->rx_key_active;
+       if (tx->key.keys &&
+           cur != new &&
+           atomic_cmpxchg(&rx->peer_rx_active, cur, new) == cur) {
+               if (new)
+                       tipc_aead_users_inc(tx->aead[new], INT_MAX);
+               if (cur)
+                       tipc_aead_users_dec(tx->aead[cur], 0);
 
                atomic64_set(&rx->sndnxt, 0);
                /* Mark the point TX key users changed */
                tx->timer1 = jiffies;
 
-#ifdef TIPC_CRYPTO_DEBUG
-               pr_info("TX(%s): key users changed %d-- %d++, peer RX(%s)\n",
-                       tipc_own_id_string(net), cur_rx_active,
-                       new_rx_active, tipc_node_get_id_str(rx->node));
-#endif
+               pr_debug("%s: key users changed %d-- %d++, peer %s\n",
+                        tx->name, cur, new, rx->name);
        }
 }
 
        tipc_crypto_key_detach(tx->aead[key.active], &tx->lock);
        spin_unlock(&tx->lock);
 
-       pr_warn("TX(%s): key is revoked!\n", tipc_own_id_string(net));
+       pr_warn("%s: key is revoked\n", tx->name);
        return -EKEYREVOKED;
 }
 
        c->timer1 = jiffies;
        c->timer2 = jiffies;
        spin_lock_init(&c->lock);
-       *crypto = c;
+       scnprintf(c->name, 48, "%s(%s)", (is_rx(c)) ? "RX" : "TX",
+                 (is_rx(c)) ? tipc_node_get_id_str(c->node) :
+                              tipc_own_id_string(c->net));
 
+       *crypto = c;
        return 0;
 }
 
 void tipc_crypto_stop(struct tipc_crypto **crypto)
 {
-       struct tipc_crypto *c, *tx, *rx;
-       bool is_rx;
+       struct tipc_crypto *c = *crypto, *tx, *rx;
        u8 k;
 
-       if (!*crypto)
+       if (!c)
                return;
 
        rcu_read_lock();
        /* RX stopping? => decrease TX key users if any */
-       is_rx = !!((*crypto)->node);
-       if (is_rx) {
-               rx = *crypto;
+       if (is_rx(c)) {
+               rx = c;
                tx = tipc_net(rx->net)->crypto_tx;
                k = atomic_read(&rx->peer_rx_active);
                if (k) {
        }
 
        /* Release AEAD keys */
-       c = *crypto;
        for (k = KEY_MIN; k <= KEY_MAX; k++)
                tipc_aead_put(rcu_dereference(c->aead[k]));
        rcu_read_unlock();
-
-       pr_warn("%s(%s) has been purged, node left!\n",
-               (is_rx) ? "RX" : "TX",
-               (is_rx) ? tipc_node_get_id_str((*crypto)->node) :
-                         tipc_own_id_string((*crypto)->net));
+       pr_debug("%s: has been stopped\n", c->name);
 
        /* Free this crypto statistics */
        free_percpu(c->stats);
        struct tipc_net *tn = tipc_net(rx->net);
        struct tipc_crypto *tx = tn->crypto_tx;
        struct tipc_key key;
-       u8 new_pending, new_passive;
        int cmd;
 
-       /* TX key activating:
-        * The pending key (users > 0) -> active
-        * The active key if any (users == 0) -> free
-        */
+       /* TX pending: taking all users & stable -> active */
        spin_lock(&tx->lock);
        key = tx->key;
        if (key.active && tipc_aead_users(tx->aead[key.active]) > 0)
                goto s1;
        if (!key.pending || tipc_aead_users(tx->aead[key.pending]) <= 0)
                goto s1;
-       if (time_before(jiffies, tx->timer1 + TIPC_TX_LASTING_LIM))
+       if (time_before(jiffies, tx->timer1 + TIPC_TX_LASTING_TIME))
                goto s1;
 
        tipc_crypto_key_set_state(tx, key.passive, key.pending, 0);
        if (key.active)
                tipc_crypto_key_detach(tx->aead[key.active], &tx->lock);
        this_cpu_inc(tx->stats->stat[STAT_SWITCHES]);
-       pr_info("TX(%s): key %d is activated!\n", tipc_own_id_string(tx->net),
-               key.pending);
+       pr_info("%s: key[%d] is activated\n", tx->name, key.pending);
 
 s1:
        spin_unlock(&tx->lock);
 
-       /* RX key activating:
-        * The pending key (users > 0) -> active
-        * The active key if any -> passive, freed later
-        */
+       /* RX pending: having user -> active */
        spin_lock(&rx->lock);
        key = rx->key;
        if (!key.pending || tipc_aead_users(rx->aead[key.pending]) <= 0)
                goto s2;
 
-       new_pending = (key.passive &&
-                      !tipc_aead_users(rx->aead[key.passive])) ?
-                                      key.passive : 0;
-       new_passive = (key.active) ?: ((new_pending) ? 0 : key.passive);
-       tipc_crypto_key_set_state(rx, new_passive, key.pending, new_pending);
+       if (key.active)
+               key.passive = key.active;
+       key.active = key.pending;
+       rx->timer2 = jiffies;
+       tipc_crypto_key_set_state(rx, key.passive, key.active, 0);
        this_cpu_inc(rx->stats->stat[STAT_SWITCHES]);
-       pr_info("RX(%s): key %d is activated!\n",
-               tipc_node_get_id_str(rx->node), key.pending);
+       pr_info("%s: key[%d] is activated\n", rx->name, key.pending);
        goto s5;
 
 s2:
-       /* RX key "faulty" switching:
-        * The faulty pending key (users < -30) -> passive
-        * The passive key (users = 0) -> pending
-        * Note: This only happens after RX deactivated - s3!
-        */
-       key = rx->key;
-       if (!key.pending || tipc_aead_users(rx->aead[key.pending]) > -30)
-               goto s3;
-       if (!key.passive || tipc_aead_users(rx->aead[key.passive]) != 0)
+       /* RX pending: not working -> remove */
+       if (!key.pending || tipc_aead_users(rx->aead[key.pending]) > -10)
                goto s3;
 
-       new_pending = key.passive;
-       new_passive = key.pending;
-       tipc_crypto_key_set_state(rx, new_passive, key.active, new_pending);
+       tipc_crypto_key_set_state(rx, key.passive, key.active, 0);
+       tipc_crypto_key_detach(rx->aead[key.pending], &rx->lock);
+       pr_debug("%s: key[%d] is removed\n", rx->name, key.pending);
        goto s5;
 
 s3:
-       /* RX key deactivating:
-        * The passive key if any -> pending
-        * The active key -> passive (users = 0) / pending
-        * The pending key if any -> passive (users = 0)
-        */
-       key = rx->key;
+       /* RX active: timed out or no user -> pending */
        if (!key.active)
                goto s4;
-       if (time_before(jiffies, rx->timer1 + TIPC_RX_ACTIVE_LIM))
+       if (time_before(jiffies, rx->timer1 + TIPC_RX_ACTIVE_LIM) &&
+           tipc_aead_users(rx->aead[key.active]) > 0)
                goto s4;
 
-       new_pending = (key.passive) ?: key.active;
-       new_passive = (key.passive) ? key.active : key.pending;
-       tipc_aead_users_set(rx->aead[new_pending], 0);
-       if (new_passive)
-               tipc_aead_users_set(rx->aead[new_passive], 0);
-       tipc_crypto_key_set_state(rx, new_passive, 0, new_pending);
-       pr_info("RX(%s): key %d is deactivated!\n",
-               tipc_node_get_id_str(rx->node), key.active);
+       if (key.pending)
+               key.passive = key.active;
+       else
+               key.pending = key.active;
+       rx->timer2 = jiffies;
+       tipc_crypto_key_set_state(rx, key.passive, 0, key.pending);
+       tipc_aead_users_set(rx->aead[key.pending], 0);
+       pr_debug("%s: key[%d] is deactivated\n", rx->name, key.active);
        goto s5;
 
 s4:
-       /* RX key passive -> freed: */
-       key = rx->key;
-       if (!key.passive || !tipc_aead_users(rx->aead[key.passive]))
+       /* RX passive: outdated or not working -> free */
+       if (!key.passive)
                goto s5;
-       if (time_before(jiffies, rx->timer2 + TIPC_RX_PASSIVE_LIM))
+       if (time_before(jiffies, rx->timer2 + TIPC_RX_PASSIVE_LIM) &&
+           tipc_aead_users(rx->aead[key.passive]) > -10)
                goto s5;
 
        tipc_crypto_key_set_state(rx, 0, key.active, key.pending);
        tipc_crypto_key_detach(rx->aead[key.passive], &rx->lock);
-       pr_info("RX(%s): key %d is freed!\n", tipc_node_get_id_str(rx->node),
-               key.passive);
+       pr_debug("%s: key[%d] is freed\n", rx->name, key.passive);
 
 s5:
        spin_unlock(&rx->lock);
        struct tipc_crypto *__rx = tipc_node_crypto_rx(__dnode);
        struct tipc_crypto *tx = tipc_net(net)->crypto_tx;
        struct tipc_crypto_stats __percpu *stats = tx->stats;
+       struct tipc_msg *hdr = buf_msg(*skb);
        struct tipc_key key = tx->key;
        struct tipc_aead *aead = NULL;
-       struct sk_buff *probe;
+       struct sk_buff *_skb;
        int rc = -ENOKEY;
+       u32 user = msg_user(hdr);
        u8 tx_key;
 
        /* No encryption? */
                        goto encrypt;
                if (__rx && atomic_read(&__rx->peer_rx_active) == tx_key)
                        goto encrypt;
-               if (TIPC_SKB_CB(*skb)->probe)
+               if (TIPC_SKB_CB(*skb)->probe) {
+                       pr_debug("%s: probing for key[%d]\n", tx->name,
+                                key.pending);
                        goto encrypt;
-               if (!__rx &&
-                   time_after(jiffies, tx->timer2 + TIPC_TX_PROBE_LIM)) {
-                       tx->timer2 = jiffies;
-                       probe = skb_clone(*skb, GFP_ATOMIC);
-                       if (probe) {
-                               TIPC_SKB_CB(probe)->probe = 1;
-                               tipc_crypto_xmit(net, &probe, b, dst, __dnode);
-                               if (probe)
-                                       b->media->send_msg(net, probe, b, dst);
+               }
+               if (user == LINK_CONFIG || user == LINK_PROTOCOL) {
+                       _skb = skb_clone(*skb, GFP_ATOMIC);
+                       if (_skb) {
+                               TIPC_SKB_CB(_skb)->probe = 1;
+                               tipc_crypto_xmit(net, &_skb, b, dst, __dnode);
+                               if (_skb)
+                                       b->media->send_msg(net, _skb, b, dst);
                        }
                }
        }
        if (unlikely(!rx))
                goto pick_tx;
 
-       /* Pick RX key according to TX key, three cases are possible:
-        * 1) The current active key (likely) or;
-        * 2) The pending (new or deactivated) key (if any) or;
-        * 3) The passive or old active key (i.e. users > 0);
-        */
        tx_key = ((struct tipc_ehdr *)(*skb)->data)->tx_key;
+       /* Pick RX key according to TX key if any */
        key = rx->key;
-       if (likely(tx_key == key.active))
-               goto decrypt;
-       if (tx_key == key.pending)
+       if (tx_key == key.active || tx_key == key.pending ||
+           tx_key == key.passive)
                goto decrypt;
-       if (tx_key == key.passive) {
-               rx->timer2 = jiffies;
-               if (tipc_aead_users(rx->aead[key.passive]) > 0)
-                       goto decrypt;
-       }
 
        /* Unknown key, let's try to align RX key(s) */
        if (tipc_crypto_key_try_align(rx, tx_key))
        struct tipc_aead *tmp = NULL;
        struct tipc_ehdr *ehdr;
        struct tipc_node *n;
-       u8 rx_key_active;
-       bool destined;
 
        /* Is this completed by TX? */
-       if (unlikely(!rx->node)) {
+       if (unlikely(is_tx(aead->crypto))) {
                rx = skb_cb->tx_clone_ctx.rx;
-#ifdef TIPC_CRYPTO_DEBUG
-               pr_info("TX->RX(%s): err %d, aead %p, skb->next %p, flags %x\n",
-                       (rx) ? tipc_node_get_id_str(rx->node) : "-", err, aead,
-                       (*skb)->next, skb_cb->flags);
-               pr_info("skb_cb [recurs %d, last %p], tx->aead [%p %p %p]\n",
-                       skb_cb->tx_clone_ctx.recurs, skb_cb->tx_clone_ctx.last,
-                       aead->crypto->aead[1], aead->crypto->aead[2],
-                       aead->crypto->aead[3]);
-#endif
+               pr_debug("TX->RX(%s): err %d, aead %p, skb->next %p, flags %x\n",
+                        (rx) ? tipc_node_get_id_str(rx->node) : "-", err, aead,
+                        (*skb)->next, skb_cb->flags);
+               pr_debug("skb_cb [recurs %d, last %p], tx->aead [%p %p %p]\n",
+                        skb_cb->tx_clone_ctx.recurs, skb_cb->tx_clone_ctx.last,
+                        aead->crypto->aead[1], aead->crypto->aead[2],
+                        aead->crypto->aead[3]);
                if (unlikely(err)) {
                        if (err == -EBADMSG && (*skb)->next)
                                tipc_rcv(net, (*skb)->next, b);
                                goto free_skb;
                }
 
-               /* Skip cloning this time as we had a RX pending key */
-               if (rx->key.pending)
-                       goto rcv;
                if (tipc_aead_clone(&tmp, aead) < 0)
                        goto rcv;
                if (tipc_crypto_key_attach(rx, tmp, ehdr->tx_key) < 0) {
 
        /* Remove ehdr & auth. tag prior to tipc_rcv() */
        ehdr = (struct tipc_ehdr *)(*skb)->data;
-       destined = ehdr->destined;
-       rx_key_active = ehdr->rx_key_active;
+
+       /* Mark this point, RX passive still works */
+       if (rx->key.passive && ehdr->tx_key == rx->key.passive)
+               rx->timer2 = jiffies;
+
+       skb_reset_network_header(*skb);
        skb_pull(*skb, tipc_ehdr_size(ehdr));
        pskb_trim(*skb, (*skb)->len - aead->authsize);
 
                goto free_skb;
        }
 
-       /* Update peer RX active key & TX users */
-       if (destined)
-               tipc_crypto_key_synch(rx, rx_key_active, buf_msg(*skb));
+       /* Ok, everything's fine, try to synch own keys according to peers' */
+       tipc_crypto_key_synch(rx, *skb);
 
        /* Mark skb decrypted */
        skb_cb->decrypted = 1;
        /* Print crypto statistics */
        for (i = 0, j = 0; i < MAX_STATS; i++)
                j += scnprintf(buf + j, 200 - j, "|%11s ", hstats[i]);
-       pr_info("\nCounter     %s", buf);
+       pr_info("Counter     %s", buf);
 
        memset(buf, '-', 115);
        buf[115] = '\0';
                aead = rcu_dereference(c->aead[k]);
                if (aead)
                        i += scnprintf(buf + i, 200 - i,
-                                      "{\"%s...\", \"%s\"}/%d:%d",
+                                      "{\"0x...%s\", \"%s\"}/%d:%d",
                                       aead->hint,
                                       (aead->mode == CLUSTER_KEY) ? "c" : "p",
                                       atomic_read(&aead->users),
                i += scnprintf(buf + i, 200 - i, "\n");
        }
 
-       if (c->node)
+       if (is_rx(c))
                i += scnprintf(buf + i, 200 - i, "\tPeer RX active: %d\n",
                               atomic_read(&c->peer_rx_active));
 
        return buf;
 }
 
-#ifdef TIPC_CRYPTO_DEBUG
 static char *tipc_key_change_dump(struct tipc_key old, struct tipc_key new,
                                  char *buf)
 {
        i += scnprintf(buf + i, 32 - i, "]");
        return buf;
 }
-#endif