{
        struct tipc_node *n_ptr;
        struct tipc_link *link;
-       struct tipc_media_addr media_addr, *addr;
+       struct tipc_media_addr media_addr;
        struct sk_buff *rbuf;
        struct tipc_msg *msg = buf_msg(buf);
        u32 dest = msg_dest_domain(msg);
        u32 net_id = msg_bc_netid(msg);
        u32 type = msg_type(msg);
        u32 signature = msg_node_sig(msg);
+       int addr_mismatch;
        int link_fully_up;
 
        media_addr.broadcast = 1;
        b_ptr->media->msg2addr(&media_addr, msg_media_addr(msg));
        buf_discard(buf);
 
-       /* Validate discovery message from requesting node */
+       /* Ensure message from node is valid and communication is permitted */
        if (net_id != tipc_net_id)
                return;
        if (media_addr.broadcast)
        }
        tipc_node_lock(n_ptr);
 
+       /* Prepare to validate requesting node's signature and media address */
        link = n_ptr->links[b_ptr->identity];
+       addr_mismatch = (link != NULL) &&
+               memcmp(&link->media_addr, &media_addr, sizeof(media_addr));
 
-       /* Create a link endpoint for this bearer, if necessary */
-       if (!link) {
-               link = tipc_link_create(n_ptr, b_ptr, &media_addr);
-               if (!link) {
+       /*
+        * Ensure discovery message's signature is correct
+        *
+        * If signature is incorrect and there is no working link to the node,
+        * accept the new signature but invalidate all existing links to the
+        * node so they won't re-activate without a new discovery message.
+        *
+        * If signature is incorrect and the requested link to the node is
+        * working, accept the new signature. (This is an instance of delayed
+        * rediscovery, where a link endpoint was able to re-establish contact
+        * with its peer endpoint on a node that rebooted before receiving a
+        * discovery message from that node.)
+        *
+        * If signature is incorrect and there is a working link to the node
+        * that is not the requested link, reject the request (must be from
+        * a duplicate node).
+        */
+       if (signature != n_ptr->signature) {
+               if (n_ptr->working_links == 0) {
+                       struct tipc_link *curr_link;
+                       int i;
+
+                       for (i = 0; i < MAX_BEARERS; i++) {
+                               curr_link = n_ptr->links[i];
+                               if (curr_link) {
+                                       memset(&curr_link->media_addr, 0,
+                                              sizeof(media_addr));
+                                       tipc_link_reset(curr_link);
+                               }
+                       }
+                       addr_mismatch = (link != NULL);
+               } else if (tipc_link_is_up(link) && !addr_mismatch) {
+                       /* delayed rediscovery */
+               } else {
+                       disc_dupl_alert(b_ptr, orig, &media_addr);
                        tipc_node_unlock(n_ptr);
                        return;
                }
+               n_ptr->signature = signature;
        }
 
        /*
         * 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)) {
+
+       if (addr_mismatch) {
+               if (tipc_link_is_up(link)) {
                        disc_dupl_alert(b_ptr, orig, &media_addr);
                        tipc_node_unlock(n_ptr);
                        return;
+               } else {
+                       memcpy(&link->media_addr, &media_addr,
+                              sizeof(media_addr));
+                       tipc_link_reset(link);
+               }
+       }
+
+       /* Create a link endpoint for this bearer, if necessary */
+       if (!link) {
+               link = tipc_link_create(n_ptr, b_ptr, &media_addr);
+               if (!link) {
+                       tipc_node_unlock(n_ptr);
+                       return;
                }
-               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 */
-       n_ptr->signature = signature;
        link_fully_up = link_working_working(link);
 
        if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {