void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
 {
+       struct tipc_node *n_ptr;
        struct link *link;
-       struct tipc_media_addr media_addr;
+       struct tipc_media_addr media_addr, *addr;
+       struct sk_buff *rbuf;
        struct tipc_msg *msg = buf_msg(buf);
        u32 dest = msg_dest_domain(msg);
        u32 orig = msg_prevnode(msg);
        u32 net_id = msg_bc_netid(msg);
        u32 type = msg_type(msg);
+       int link_fully_up;
 
        msg_get_media_addr(msg, &media_addr);
        buf_discard(buf);
 
+       /* Validate discovery message from requesting node */
        if (net_id != tipc_net_id)
                return;
        if (!tipc_addr_domain_valid(dest))
        }
        if (!tipc_in_scope(dest, tipc_own_addr))
                return;
-       if (in_own_cluster(orig)) {
-               /* Always accept link here */
-               struct sk_buff *rbuf;
-               struct tipc_media_addr *addr;
-               struct tipc_node *n_ptr = tipc_node_find(orig);
-               int link_fully_up;
-
-               if (n_ptr == NULL) {
-                       n_ptr = tipc_node_create(orig);
-                       if (!n_ptr)
-                               return;
-               }
-               spin_lock_bh(&n_ptr->lock);
-
-               /* Don't talk to neighbor during cleanup after last session */
+       if (!in_own_cluster(orig))
+               return;
 
-               if (n_ptr->cleanup_required) {
-                       spin_unlock_bh(&n_ptr->lock);
+       /* Locate structure corresponding to requesting node */
+       n_ptr = tipc_node_find(orig);
+       if (!n_ptr) {
+               n_ptr = tipc_node_create(orig);
+               if (!n_ptr)
                        return;
-               }
+       }
+       tipc_node_lock(n_ptr);
+
+       /* Don't talk to neighbor during cleanup after last session */
+       if (n_ptr->cleanup_required) {
+               tipc_node_unlock(n_ptr);
+               return;
+       }
 
-               link = n_ptr->links[b_ptr->identity];
+       link = n_ptr->links[b_ptr->identity];
+
+       /* Create a link endpoint for this bearer, if necessary */
+       if (!link) {
+               link = tipc_link_create(b_ptr, orig, &media_addr);
                if (!link) {
-                       link = tipc_link_create(b_ptr, orig, &media_addr);
-                       if (!link) {
-                               spin_unlock_bh(&n_ptr->lock);
-                               return;
-                       }
-               }
-               addr = &link->media_addr;
-               if (memcmp(addr, &media_addr, sizeof(*addr))) {
-                       if (tipc_link_is_up(link) || (!link->started)) {
-                               disc_dupl_alert(b_ptr, orig, &media_addr);
-                               spin_unlock_bh(&n_ptr->lock);
-                               return;
-                       }
-                       warn("Resetting link <%s>, peer interface address changed\n",
-                            link->name);
-                       memcpy(addr, &media_addr, sizeof(*addr));
-                       tipc_link_reset(link);
+                       tipc_node_unlock(n_ptr);
+                       return;
                }
-               link_fully_up = link_working_working(link);
-               spin_unlock_bh(&n_ptr->lock);
-               if ((type == DSC_RESP_MSG) || link_fully_up)
+       }
+
+       /*
+        * Ensure requesting node's media address is correct
+        *
+        * If media address doesn't match and the link is working, reject the
+        * request (must be from a duplicate node).
+        *
+        * If media address doesn't match and the link is not working, accept
+        * the new media address and reset the link to ensure it starts up
+        * cleanly.
+        */
+       addr = &link->media_addr;
+       if (memcmp(addr, &media_addr, sizeof(*addr))) {
+               if (tipc_link_is_up(link) || (!link->started)) {
+                       disc_dupl_alert(b_ptr, orig, &media_addr);
+                       tipc_node_unlock(n_ptr);
                        return;
-               rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
-               if (rbuf != NULL) {
-                       b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
-                       buf_discard(rbuf);
                }
+               warn("Resetting link <%s>, peer interface address changed\n",
+                    link->name);
+               memcpy(addr, &media_addr, sizeof(*addr));
+               tipc_link_reset(link);
+       }
+
+       /* Accept discovery message & send response, if necessary */
+       link_fully_up = link_working_working(link);
+       tipc_node_unlock(n_ptr);
+       if ((type == DSC_RESP_MSG) || link_fully_up)
+               return;
+       rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
+       if (rbuf != NULL) {
+               b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
+               buf_discard(rbuf);
        }
 }