Added silc_server_remove_servers_by_server to remove servers
[silc.git] / apps / silcd / packet_receive.c
index f5b28e6100a44ab2ce7eaa220b5ce0808ea72892..4e07b0ce40502355bbca0bb2b7f7580e33ee4c71 100644 (file)
@@ -94,13 +94,12 @@ void silc_server_notify(SilcServer server,
       if (!channel_id)
        goto out;
 
-      if (!server->standalone)
-       silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server), 
-                                    packet->type, packet->flags | 
-                                    SILC_PACKET_FLAG_BROADCAST, 
-                                    channel_id, SILC_ID_CHANNEL,
-                                    packet->buffer->data, 
-                                    packet->buffer->len, FALSE);
+      silc_server_packet_send_dest(server, SILC_PRIMARY_ROUTE(server), 
+                                  packet->type, packet->flags | 
+                                  SILC_PACKET_FLAG_BROADCAST, 
+                                  channel_id, SILC_ID_CHANNEL,
+                                  packet->buffer->data, 
+                                  packet->buffer->len, FALSE);
       silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data, 
                                   packet->type, packet->flags,
                                   channel_id, SILC_ID_CHANNEL,
@@ -108,12 +107,11 @@ void silc_server_notify(SilcServer server,
                                   FALSE, TRUE);
     } else {
       /* Packet is destined to client or server */
-      if (!server->standalone)
-       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server), 
-                               packet->type,
-                               packet->flags | SILC_PACKET_FLAG_BROADCAST, 
-                               packet->buffer->data, packet->buffer->len, 
-                               FALSE);
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server), 
+                             packet->type,
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST, 
+                             packet->buffer->data, packet->buffer->len, 
+                             FALSE);
       silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
                              packet->type, packet->flags,
                              packet->buffer->data, packet->buffer->len, 
@@ -148,6 +146,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -219,10 +218,17 @@ void silc_server_notify(SilcServer server,
     chl->client = client;
     chl->channel = channel;
 
-    /* If this is the first one on the channel then it is the founder of
-       the channel. */
-    if (!silc_hash_table_count(channel->user_list))
-      chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+    if (server->server_type != SILC_ROUTER ||
+       sock->type == SILC_SOCKET_TYPE_ROUTER) {
+      /* If this is the first one on the channel then it is the founder of
+        the channel. This is done on normal server and on router if this
+        notify is coming from router */
+      if (!silc_hash_table_count(channel->user_list)) {
+       SILC_LOG_DEBUG(("Client %s is founder on channel",
+                       silc_id_render(chl->client->id, SILC_ID_CLIENT)));
+       chl->mode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
+      }
+    }
 
     silc_hash_table_add(channel->user_list, client, chl);
     silc_hash_table_add(client->channels, channel, chl);
@@ -259,6 +265,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -409,13 +416,16 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
     }
 
-    if (channel->topic && !strcmp(channel->topic, tmp))
+    if (channel->topic && !strcmp(channel->topic, tmp)) {
+      SILC_LOG_DEBUG(("Topic is already set and same"));
       goto out;
+    }
 
     if (client) {
       /* Get user's channel entry and check that topic set is allowed. */
@@ -434,7 +444,7 @@ void silc_server_notify(SilcServer server,
     channel->topic = strdup(tmp);
 
     /* Send the same notify to the channel */
-    silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
+    silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
                                       FALSE, packet->buffer->data, 
                                       packet->buffer->len, FALSE);
     silc_free(channel_id);
@@ -504,9 +514,9 @@ void silc_server_notify(SilcServer server,
     /* 
      * Distribute the notify to local clients on the channel
      */
-    
+
     SILC_LOG_DEBUG(("CMODE CHANGE notify"));
-      
+
     /* Get client ID */
     tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
     if (!tmp)
@@ -544,6 +554,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -559,6 +570,38 @@ void silc_server_notify(SilcServer server,
     /* Check if mode changed */
     if (channel->mode == mode) {
       SILC_LOG_DEBUG(("Mode is changed already"));
+
+      /* If this mode change has founder mode then we'll enforce the
+        change so that the server gets the real founder public key */
+      if (server->server_type != SILC_SERVER &&
+         sock != SILC_PRIMARY_ROUTE(server) &&
+         mode & SILC_CHANNEL_MODE_FOUNDER_AUTH && channel->founder_key) {
+       SILC_LOG_DEBUG(("Sending founder public key to server"));
+       silc_server_send_notify_cmode(server, sock, FALSE, channel,
+                                     channel->mode, server->id,
+                                     SILC_ID_SERVER, channel->cipher,
+                                     channel->hmac_name,
+                                     channel->passphrase,
+                                     channel->founder_key);
+      }
+
+      /* If we received same mode from our primary check whether founder
+        mode and key in the notify is set.  We update the founder key
+        here since we may have wrong one */
+      if (server->server_type == SILC_SERVER &&
+         sock == SILC_PRIMARY_ROUTE(server) &&
+         mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+       SILC_LOG_DEBUG(("Founder public key received from primary router"));
+       tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
+       if (!tmp)
+         break;
+
+       if (channel->founder_key)
+         silc_pkcs_public_key_free(channel->founder_key);
+       channel->founder_key = NULL;
+       silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
+      }
+
       break;
     }
 
@@ -568,22 +611,51 @@ void silc_server_notify(SilcServer server,
        goto out;
       if (!silc_server_check_cmode_rights(server, channel, chl, mode)) {
        SILC_LOG_DEBUG(("CMODE change is not allowed"));
+       silc_server_send_notify_cmode(server, sock, FALSE, channel,
+                                     channel->mode, server->id,
+                                     SILC_ID_SERVER, channel->cipher,
+                                     channel->hmac_name,
+                                     channel->passphrase,
+                                     channel->founder_key);
        goto out;
       }
     } else {
+      /* Assure that server is not removing founder mode from us */
       if (server->server_type == SILC_ROUTER &&
+         sock != SILC_PRIMARY_ROUTE(server) &&
          channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH &&
          !(mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
        SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
        silc_server_send_notify_cmode(server, sock, FALSE, channel,
                                      channel->mode, server->id,
-                                     SILC_ID_SERVER,
-                                     channel->cipher,
+                                     SILC_ID_SERVER, channel->cipher,
                                      channel->hmac_name,
                                      channel->passphrase,
                                      channel->founder_key);
        goto out;
       }
+
+      /* If server is adding founder mode, check whether there is founder
+        on channel already and is not from this server */
+      if (server->server_type == SILC_ROUTER &&
+         sock != SILC_PRIMARY_ROUTE(server) &&
+         mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
+       silc_hash_table_list(channel->user_list, &htl);
+       while (silc_hash_table_get(&htl, NULL, (void *)&chl))
+         if (chl->mode & SILC_CHANNEL_UMODE_CHANFO &&
+             chl->client->router != sock->user_data) {
+           SILC_LOG_DEBUG(("Enforcing sender to change channel mode"));
+           silc_server_send_notify_cmode(server, sock, FALSE, channel,
+                                         channel->mode, server->id,
+                                         SILC_ID_SERVER, channel->cipher,
+                                         channel->hmac_name,
+                                         channel->passphrase,
+                                         channel->founder_key);
+           silc_hash_table_list_reset(&htl);
+           goto out;
+         }
+       silc_hash_table_list_reset(&htl);
+      }
     }
 
     /* If the channel had private keys set and the mode was removed then
@@ -694,9 +766,9 @@ void silc_server_notify(SilcServer server,
        */
       SilcChannelClientEntry chl2 = NULL;
       bool notify_sent = FALSE;
-      
+
       SILC_LOG_DEBUG(("CUMODE CHANGE notify"));
-      
+
       /* Get client ID */
       tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
       if (!tmp)
@@ -734,6 +806,7 @@ void silc_server_notify(SilcServer server,
        channel = silc_idlist_find_channel_by_id(server->local_list, 
                                                 channel_id, NULL);
        if (!channel) {
+         SILC_LOG_DEBUG(("Notify for unknown channel"));
          silc_free(channel_id);
          goto out;
        }
@@ -797,10 +870,15 @@ void silc_server_notify(SilcServer server,
       if (!silc_server_client_on_channel(client2, channel, &chl))
        goto out;
 
+      if (server->server_type == SILC_SERVER && chl->mode == mode) {
+       SILC_LOG_DEBUG(("Mode is changed already"));
+       break;
+      }
+
       if (mode & SILC_CHANNEL_UMODE_CHANFO &&
          !(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
          server->server_type == SILC_ROUTER &&
-         sock->user_data != server->router) {
+         sock != SILC_PRIMARY_ROUTE(server)) {
        SilcPublicKey founder_key = NULL;
 
        /* If channel doesn't have founder auth mode then it's impossible
@@ -809,7 +887,7 @@ void silc_server_notify(SilcServer server,
           founder at all on the channel. */
        if (client && !(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
          /* Force the mode to not have founder mode */
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+         chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
          silc_server_force_cumode_change(server, sock, channel, chl, mode);
          notify_sent = TRUE;
          break;
@@ -829,7 +907,7 @@ void silc_server_notify(SilcServer server,
                 silc_pkcs_public_key_compare(
                                        channel->founder_key,
                                        chl2->client->data.public_key))) {
-             mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+             chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
              silc_server_force_cumode_change(server, sock, channel,
                                              chl, mode);
              notify_sent = TRUE;
@@ -844,30 +922,30 @@ void silc_server_notify(SilcServer server,
           is set on the channel now check whether this is the client that
           originally set the mode. */
 
-       /* Get public key that must be present in notify */
-       tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
-       if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
-                                                &founder_key)) {
-         mode &= ~SILC_CHANNEL_UMODE_CHANFO;
-         silc_server_force_cumode_change(server, sock, channel, chl, mode);
-         notify_sent = TRUE;
-         break;
-       }
-
        if (channel->founder_key) {
+         /* Get public key that must be present in notify */
+         tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
+         if (!tmp || !silc_pkcs_public_key_decode(tmp, tmp_len,
+                                                  &founder_key)) {
+           chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           silc_server_force_cumode_change(server, sock, channel, chl, mode);
+           notify_sent = TRUE;
+           break;
+         }
+
          /* Now match the public key we have cached and public key sent.
             They must match. */
          if (client && client->data.public_key && 
              !silc_pkcs_public_key_compare(channel->founder_key,
                                            client->data.public_key)) {
-           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
            break;
          }
          if (!silc_pkcs_public_key_compare(channel->founder_key,
                                            founder_key)) {
-           mode &= ~SILC_CHANNEL_UMODE_CHANFO;
+           chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
            silc_server_force_cumode_change(server, sock, channel, chl, mode);
            notify_sent = TRUE;
            break;
@@ -890,12 +968,14 @@ void silc_server_notify(SilcServer server,
          silc_pkcs_public_key_free(founder_key);
       }
 
-      if (chl->mode == mode) {
+      if (server->server_type != SILC_SERVER && chl->mode == mode) {
        SILC_LOG_DEBUG(("Mode is changed already"));
        break;
       }
 
-      SILC_LOG_DEBUG(("Changing the channel user mode"));
+      SILC_LOG_DEBUG(("Changing %s channel user mode",
+                     chl->client->nickname ? chl->client->nickname :
+                     (unsigned char *)""));
 
       /* Change the mode */
       chl->mode = mode;
@@ -933,6 +1013,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -1040,6 +1121,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->global_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -1085,6 +1167,13 @@ void silc_server_notify(SilcServer server,
       /* Re-announce our clients on the channel as the ID has changed now */
       silc_server_announce_get_channel_users(server, channel, &modes, &users,
                                             &users_modes);
+      if (users) {
+       silc_buffer_push(users, users->data - users->head);
+       silc_server_packet_send(server, sock,
+                               SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                               users->data, users->len, FALSE);
+       silc_buffer_free(users);
+      }
       if (modes) {
        silc_buffer_push(modes, modes->data - modes->head);
        silc_server_packet_send_dest(server, sock,
@@ -1093,13 +1182,6 @@ void silc_server_notify(SilcServer server,
                                     modes->data, modes->len, FALSE);
        silc_buffer_free(modes);
       }
-      if (users) {
-       silc_buffer_push(users, users->data - users->head);
-       silc_server_packet_send(server, sock,
-                               SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
-                               users->data, users->len, FALSE);
-       silc_buffer_free(users);
-      }
       if (users_modes) {
        silc_buffer_push(users_modes, users_modes->data - users_modes->head);
        silc_server_packet_send_dest(server, sock,
@@ -1212,9 +1294,19 @@ void silc_server_notify(SilcServer server,
     }
     silc_free(server_id);
 
-    /* Free all client entries that this server owns as they will
-       become invalid now as well. */
-    silc_server_remove_clients_by_server(server, server_entry, TRUE);
+    /* Sending SERVER_SIGNOFF is not right way to signoff local connection */
+    if (SILC_IS_LOCAL(server_entry))
+      break;
+
+    /* Remove all servers that are originated from this server, and
+       remove the clients of those servers too. */
+    silc_server_remove_servers_by_server(server, server_entry, TRUE);
+
+    /* Remove the clients that this server owns as they will become
+       invalid now too. */
+    silc_server_remove_clients_by_server(server, server_entry,
+                                        server_entry, TRUE);
+    silc_server_backup_del(server, server_entry);
 
     /* Remove the server entry */
     silc_idlist_del_server(local ? server->local_list :
@@ -1247,6 +1339,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -1340,10 +1433,10 @@ void silc_server_notify(SilcServer server,
 
       /* If the the client is not in local list we check global list */
       client = silc_idlist_find_client_by_id(server->global_list, 
-                                            client_id, TRUE, NULL);
+                                            client_id, TRUE, &cache);
       if (!client) {
        client = silc_idlist_find_client_by_id(server->local_list, 
-                                              client_id, TRUE, NULL);
+                                              client_id, TRUE, &cache);
        if (!client) {
          silc_free(client_id);
          goto out;
@@ -1387,7 +1480,8 @@ void silc_server_notify(SilcServer server,
          silc_free(client_id);
 
          /* Killer must be router operator */
-         if (!(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+         if (server->server_type != SILC_SERVER &&
+             !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
            SILC_LOG_DEBUG(("Killing is not allowed"));
            goto out;
          }
@@ -1406,10 +1500,25 @@ void silc_server_notify(SilcServer server,
                                       FALSE);
 
       /* Check if anyone is watching this nickname */
-      if (server->server_type == SILC_ROUTER)
-       silc_server_check_watcher_list(server, client, NULL,
-                                      SILC_NOTIFY_TYPE_KILLED);
+      silc_server_check_watcher_list(server, client, NULL,
+                                    SILC_NOTIFY_TYPE_KILLED);
+
+      /* Update statistics */
+      server->stat.clients--;
+      if (server->stat.cell_clients)
+       server->stat.cell_clients--;
+      SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
+      SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
 
+      if (SILC_IS_LOCAL(client)) {
+       server->stat.my_clients--;
+       silc_schedule_task_del_by_context(server->schedule, client);
+       silc_idlist_del_data(client);
+       client->mode = 0;
+      }
+
+      client->data.status &= ~SILC_IDLIST_STATUS_REGISTERED;
+      cache->expire = SILC_ID_CACHE_EXPIRE_DEF;
       break;
     }
 
@@ -1447,12 +1556,6 @@ void silc_server_notify(SilcServer server,
       goto out;
     SILC_GET32_MSB(mode, tmp);
 
-    /* Check that mode changing is allowed. */
-    if (!silc_server_check_umode_rights(server, client, mode)) {
-      SILC_LOG_DEBUG(("UMODE change is not allowed"));
-      goto out;
-    }
-
     /* Remove internal resumed flag if client is marked detached now */
     if (mode & SILC_UMODE_DETACHED)
       client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
@@ -1507,6 +1610,7 @@ void silc_server_notify(SilcServer server,
       channel = silc_idlist_find_channel_by_id(server->local_list, 
                                               channel_id, NULL);
       if (!channel) {
+       SILC_LOG_DEBUG(("Notify for unknown channel"));
        silc_free(channel_id);
        goto out;
       }
@@ -2391,6 +2495,12 @@ SilcServerEntry silc_server_new_server(SilcServer server,
       silc_server_announce_clients(server, 0, sock);
       silc_server_announce_channels(server, 0, sock);
     }
+
+    /* By default the servers connected to backup router are disabled
+       until backup router has become the primary */
+    if (server->server_type == SILC_BACKUP_ROUTER &&
+       sock->type == SILC_SOCKET_TYPE_SERVER)
+      idata->status |= SILC_IDLIST_STATUS_DISABLED;
   }
 
   return new_server;
@@ -2693,8 +2803,6 @@ void silc_server_new_channel(SilcServer server,
   SilcServerEntry server_entry;
   SilcChannelEntry channel;
 
-  SILC_LOG_DEBUG(("Processing New Channel"));
-
   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
       packet->src_id_type != SILC_ID_SERVER ||
       server->server_type == SILC_SERVER)
@@ -2766,6 +2874,8 @@ void silc_server_new_channel(SilcServer server,
     /* If the channel does not exist, then create it. This creates a new
        key to the channel as well that we will send to the server. */
     if (!channel) {
+      SILC_LOG_DEBUG(("Channel is new to us"));
+
       /* The protocol says that the Channel ID's IP address must be based
         on the router's IP address.  Check whether the ID is based in our
         IP and if it is not then create a new ID and enforce the server
@@ -2793,6 +2903,7 @@ void silc_server_new_channel(SilcServer server,
        return;
       }
       channel->disabled = TRUE;
+      channel->mode = silc_channel_get_mode(payload);
 
       /* Send the new channel key to the server */
       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
@@ -2812,6 +2923,8 @@ void silc_server_new_channel(SilcServer server,
         We also create a new key for the channel. */
       SilcBuffer modes = NULL, users = NULL, users_modes = NULL;
 
+      SILC_LOG_DEBUG(("Channel already exists"));
+
       if (!SILC_ID_CHANNEL_COMPARE(channel_id, channel->id)) {
        /* They don't match, send CHANNEL_CHANGE notify to the server to
           force the ID change. */
@@ -2823,8 +2936,8 @@ void silc_server_new_channel(SilcServer server,
        return;
       }
 
-#if 0 /* Lets expect that server send CMODE_CHANGE notify anyway to
-        (attempt) force mode change, and may very well get it. */
+#if 0 /* We will announce our CMODE anyway for this channel, so no need
+        to check it (implicit enforce). */
 
       /* If the mode is different from what we have then enforce the
         mode change. */
@@ -2876,6 +2989,13 @@ void silc_server_new_channel(SilcServer server,
         users on the channel "joining" the channel. */
       silc_server_announce_get_channel_users(server, channel, &modes, &users,
                                             &users_modes);
+      if (users) {
+       silc_buffer_push(users, users->data - users->head);
+       silc_server_packet_send(server, sock,
+                               SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
+                               users->data, users->len, FALSE);
+       silc_buffer_free(users);
+      }
       if (modes) {
        silc_buffer_push(modes, modes->data - modes->head);
        silc_server_packet_send_dest(server, sock,
@@ -2884,13 +3004,6 @@ void silc_server_new_channel(SilcServer server,
                                     modes->data, modes->len, FALSE);
        silc_buffer_free(modes);
       }
-      if (users) {
-       silc_buffer_push(users, users->data - users->head);
-       silc_server_packet_send(server, sock,
-                               SILC_PACKET_NOTIFY, SILC_PACKET_FLAG_LIST,
-                               users->data, users->len, FALSE);
-       silc_buffer_free(users);
-      }
       if (users_modes) {
        silc_buffer_push(users_modes, users_modes->data - users_modes->head);
        silc_server_packet_send_dest(server, sock,
@@ -3673,6 +3786,7 @@ void silc_server_resume_client(SilcServer server,
                     server->global_list->clients, 
                     detached_client->nickname,
                     detached_client->id, detached_client, FALSE, NULL);
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
 
     /* Change the owner of the client if needed */
     if (detached_client->router != server_entry)