Merged from silc_1_0_branch.
[silc.git] / apps / silcd / packet_receive.c
index 95486d8f61832a0ccc7b447806fa789847729785..e49fafb59e7fb9a6d34595eff5748831a191b5a3 100644 (file)
@@ -43,7 +43,7 @@ void silc_server_notify(SilcServer server,
   SilcClientEntry client = NULL, client2 = NULL;
   SilcServerEntry server_entry = NULL;
   SilcChannelClientEntry chl;
-  SilcIDCacheEntry cache;
+  SilcIDCacheEntry cache = NULL;
   SilcHashTableList htl;
   SilcUInt32 mode;
   unsigned char *tmp;
@@ -100,7 +100,7 @@ void silc_server_notify(SilcServer server,
                                   channel_id, SILC_ID_CHANNEL,
                                   packet->buffer->data, 
                                   packet->buffer->len, FALSE);
-      silc_server_backup_send_dest(server, (SilcServerEntry)sock->user_data, 
+      silc_server_backup_send_dest(server, sock->user_data, 
                                   packet->type, packet->flags,
                                   channel_id, SILC_ID_CHANNEL,
                                   packet->buffer->data, packet->buffer->len, 
@@ -112,7 +112,7 @@ void silc_server_notify(SilcServer server,
                              packet->flags | SILC_PACKET_FLAG_BROADCAST, 
                              packet->buffer->data, packet->buffer->len, 
                              FALSE);
-      silc_server_backup_send(server, (SilcServerEntry)sock->user_data,
+      silc_server_backup_send(server, sock->user_data,
                              packet->type, packet->flags,
                              packet->buffer->data, packet->buffer->len, 
                              FALSE, TRUE);
@@ -131,6 +131,9 @@ void silc_server_notify(SilcServer server,
      */
     SILC_LOG_DEBUG(("JOIN notify"));
 
+    if (channel_id)
+      silc_free(channel_id);
+
     /* Get Channel ID */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
     if (!tmp)
@@ -166,15 +169,17 @@ void silc_server_notify(SilcServer server,
        entry for the client. */
     client = silc_idlist_find_client_by_id(server->global_list, 
                                           client_id, server->server_type, 
-                                          NULL);
+                                          &cache);
     if (!client) {
       client = silc_idlist_find_client_by_id(server->local_list, 
                                             client_id, server->server_type,
-                                            NULL);
+                                            &cache);
       if (!client) {
        /* If router did not find the client the it is bogus */
-       if (server->server_type != SILC_SERVER)
+       if (server->server_type != SILC_SERVER) {
+         silc_free(client_id);
          goto out;
+       }
 
        client = 
          silc_idlist_add_client(server->global_list, NULL, NULL, NULL,
@@ -189,6 +194,7 @@ void silc_server_notify(SilcServer server,
        client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
       }
     }
+    silc_free(client_id);
 
     /* Do not process the notify if the client is not registered */
     if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED))
@@ -196,7 +202,8 @@ void silc_server_notify(SilcServer server,
 
     /* Do not add client to channel if it is there already */
     if (silc_server_client_on_channel(client, channel, NULL)) {
-      SILC_LOG_DEBUG(("Client already on channel"));
+      SILC_LOG_DEBUG(("Client already on channel %s",
+                     channel->channel_name));
       break;
     }
 
@@ -218,17 +225,27 @@ 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);
-    silc_free(client_id);
     channel->user_count++;
     channel->disabled = FALSE;
 
+    /* Make sure we don't expire clients that are on channel */
+    if (cache)
+      cache->expire = 0;
+
     /* Update statistics */
     if (server->server_type == SILC_ROUTER) {
       if (sock->type != SILC_SOCKET_TYPE_ROUTER)
@@ -289,6 +306,7 @@ void silc_server_notify(SilcServer server,
       }
     }
     silc_free(client_id);
+    silc_free(channel_id);
 
     /* Check if on channel */
     if (!silc_server_client_on_channel(client, channel, NULL))
@@ -344,7 +362,8 @@ void silc_server_notify(SilcServer server,
     silc_schedule_task_del_by_context(server->schedule, client);
 
     /* Remove the client from all channels. */
-    silc_server_remove_from_channels(server, NULL, client, TRUE, tmp, FALSE);
+    silc_server_remove_from_channels(server, NULL, client, TRUE,
+                                    tmp, FALSE, FALSE);
 
     /* Check if anyone is watching this nickname */
     if (server->server_type == SILC_ROUTER)
@@ -414,6 +433,7 @@ void silc_server_notify(SilcServer server,
        goto out;
       }
     }
+    silc_free(channel_id);
 
     if (channel->topic && !strcmp(channel->topic, tmp)) {
       SILC_LOG_DEBUG(("Topic is already set and same"));
@@ -440,7 +460,6 @@ void silc_server_notify(SilcServer server,
     silc_server_packet_send_to_channel(server, NULL, channel, packet->type, 
                                       FALSE, packet->buffer->data, 
                                       packet->buffer->len, FALSE);
-    silc_free(channel_id);
     break;
 
   case SILC_NOTIFY_TYPE_NICK_CHANGE:
@@ -467,8 +486,10 @@ void silc_server_notify(SilcServer server,
       if (!id2)
        goto out;
       client_id2 = silc_id_payload_parse_id(id2, tmp_len, NULL);
-      if (!client_id2)
+      if (!client_id2) {
+       silc_free(client_id);
        goto out;
+      }
       
       SILC_LOG_DEBUG(("Old Client ID id(%s)", 
                      silc_id_render(client_id, SILC_ID_CLIENT)));
@@ -530,8 +551,8 @@ void silc_server_notify(SilcServer server,
          goto out;
        }
       }
-      silc_free(client_id);
     }
+    silc_free(client_id);
 
     if (!channel_id) {
       channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
@@ -584,7 +605,7 @@ void silc_server_notify(SilcServer server,
       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"));
+       SILC_LOG_DEBUG(("Founder public key received from router"));
        tmp = silc_argument_get_arg_type(args, 6, &tmp_len);
        if (!tmp)
          break;
@@ -592,7 +613,8 @@ void silc_server_notify(SilcServer server,
        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);
+       silc_pkcs_public_key_payload_decode(tmp, tmp_len,
+                                           &channel->founder_key);
       }
 
       break;
@@ -698,7 +720,7 @@ void silc_server_notify(SilcServer server,
       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);
+      silc_pkcs_public_key_payload_decode(tmp, tmp_len, &channel->founder_key);
 
       if (!channel->founder_key || 
          (client && client->data.public_key && 
@@ -782,8 +804,8 @@ void silc_server_notify(SilcServer server,
            goto out;
          }
        }
-       silc_free(client_id);
       }
+      silc_free(client_id);
 
       if (!channel_id) {
        channel_id = silc_id_str2id(packet->dst_id, packet->dst_id_len,
@@ -915,19 +937,20 @@ 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)) {
-         chl->mode = 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_payload_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 0 /* The key may be other than the client's in 1.2 */
          if (client && client->data.public_key && 
              !silc_pkcs_public_key_compare(channel->founder_key,
                                            client->data.public_key)) {
@@ -936,6 +959,7 @@ void silc_server_notify(SilcServer server,
            notify_sent = TRUE;
            break;
          }
+#endif
          if (!silc_pkcs_public_key_compare(channel->founder_key,
                                            founder_key)) {
            chl->mode = mode &= ~SILC_CHANNEL_UMODE_CHANFO;
@@ -975,9 +999,9 @@ void silc_server_notify(SilcServer server,
 
       /* Send the same notify to the channel */
       if (!notify_sent)
-       silc_server_packet_send_to_channel(server, NULL, channel, 
-                                          packet->type, 
-                                          FALSE, packet->buffer->data, 
+       silc_server_packet_send_to_channel(server, NULL, channel,
+                                          packet->type,
+                                          FALSE, packet->buffer->data,
                                           packet->buffer->len, FALSE);
       
       silc_free(channel_id);
@@ -1044,46 +1068,34 @@ void silc_server_notify(SilcServer server,
       goto out;
     }
 
-    /* Get the added invite */
+    /* Get the invite action */
     tmp = silc_argument_get_arg_type(args, 4, &tmp_len);
-    if (tmp) {
-      if (!channel->invite_list)
-       channel->invite_list = silc_calloc(tmp_len + 2, 
-                                          sizeof(*channel->invite_list));
-      else
-       channel->invite_list = silc_realloc(channel->invite_list, 
-                                           sizeof(*channel->invite_list) * 
-                                           (tmp_len + 
-                                            strlen(channel->invite_list) + 
-                                            2));
-      if (tmp[tmp_len - 1] == ',')
-       tmp[tmp_len - 1] = '\0';
-      
-      strncat(channel->invite_list, tmp, tmp_len);
-      strncat(channel->invite_list, ",", 1);
-    }
+    if (tmp && tmp_len == 1) {
+      SilcUInt8 action = (SilcUInt8)tmp[0];
+      SilcUInt16 iargc = 0;
+      SilcArgumentPayload iargs;
+
+      /* Get invite list */
+      tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
+      if (!tmp || tmp_len < 2)
+       goto out;
 
-    /* Get the deleted invite */
-    tmp = silc_argument_get_arg_type(args, 5, &tmp_len);
-    if (tmp && channel->invite_list) {
-      char *start, *end, *n;
-      
-      if (!strncmp(channel->invite_list, tmp, 
-                  strlen(channel->invite_list) - 1)) {
-       silc_free(channel->invite_list);
-       channel->invite_list = NULL;
-      } else {
-       start = strstr(channel->invite_list, tmp);
-       if (start && strlen(start) >= tmp_len) {
-         end = start + tmp_len;
-         n = silc_calloc(strlen(channel->invite_list) - tmp_len, sizeof(*n));
-         strncat(n, channel->invite_list, start - channel->invite_list);
-         strncat(n, end + 1, ((channel->invite_list + 
-                               strlen(channel->invite_list)) - end) - 1);
-         silc_free(channel->invite_list);
-         channel->invite_list = n;
-       }
-      }
+      /* Parse the arguments to see they are constructed correctly */
+      SILC_GET16_MSB(iargc, tmp);
+      iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+      if (!iargs)
+       goto out;
+
+      if (action == 0 && !channel->invite_list)
+       channel->invite_list =
+         silc_hash_table_alloc(0, silc_hash_ptr,
+                               NULL, NULL, NULL,
+                               silc_server_inviteban_destruct, channel, TRUE);
+
+      /* Proces the invite action */
+      silc_server_inviteban_process(server, channel->invite_list, action,
+                                   iargs);
+      silc_argument_payload_free(iargs);
     }
 
     break;
@@ -1214,10 +1226,16 @@ void silc_server_notify(SilcServer server,
     if (!server_id)
       goto out;
 
+    /* If the ID is mine, this notify is not allowed. */
+    if (SILC_ID_SERVER_COMPARE(server_id, server->id)) {
+      SILC_LOG_DEBUG(("Ignoring my own ID for SERVER_SIGNOFF"));
+      break;
+    }
+
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    local = TRUE;
+    local = FALSE;
     if (!server_entry) {
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
@@ -1264,7 +1282,7 @@ void silc_server_notify(SilcServer server,
 
            /* Remove the client from all channels. */
            silc_server_remove_from_channels(server, NULL, client, 
-                                            TRUE, NULL, FALSE);
+                                            TRUE, NULL, FALSE, FALSE);
 
            /* Check if anyone is watching this nickname */
            if (server->server_type == SILC_ROUTER)
@@ -1276,6 +1294,7 @@ void silc_server_notify(SilcServer server,
              silc_server_del_from_watcher_list(server, client);
 
            /* Remove the client */
+           silc_idlist_del_data(client);
            silc_idlist_del_client(local ? server->local_list :
                                   server->global_list, client);
          }
@@ -1287,9 +1306,32 @@ 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);
+    /* For local entrys SERVER_SIGNOFF is processed only on backup router.
+       It is possible that router sends server signoff for a server.  If
+       backup router has it as local connection it will be closed. */
+    if (SILC_IS_LOCAL(server_entry)) {
+      if (server->server_type == SILC_BACKUP_ROUTER) {
+       sock = server_entry->connection;
+       SILC_LOG_DEBUG(("Closing connection %s after SERVER_SIGNOFF",
+                      sock->hostname));
+       SILC_SET_DISCONNECTING(sock);
+       if (sock->user_data)
+         silc_server_free_sock_user_data(server, sock, NULL);
+       silc_server_close_connection(server, sock);
+      }
+
+      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->router,
+                                        server_entry, TRUE);
+    silc_server_backup_del(server, server_entry);
 
     /* Remove the server entry */
     silc_idlist_del_server(local ? server->local_list :
@@ -1356,41 +1398,53 @@ void silc_server_notify(SilcServer server,
     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO)
       goto out;
     
-    /* From protocol version 1.1 we get the kicker's ID as well. */
+    /* Get the kicker's Client ID */
     tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
-    if (tmp) {
-      client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
-      if (!client_id)
-       goto out;
+    if (!tmp)
+      goto out;
+    client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
+    if (!client_id)
+      goto out;
 
-      /* If the the client is not in local list we check global list */
-      client2 = silc_idlist_find_client_by_id(server->global_list, 
+    /* If the the client is not in local list we check global list */
+    client2 = silc_idlist_find_client_by_id(server->global_list, 
+                                           client_id, TRUE, NULL);
+    if (!client2) {
+      client2 = silc_idlist_find_client_by_id(server->local_list, 
                                              client_id, TRUE, NULL);
       if (!client2) {
-       client2 = silc_idlist_find_client_by_id(server->local_list, 
-                                               client_id, TRUE, NULL);
-       if (!client2) {
-         silc_free(client_id);
-         goto out;
-       }
-      }
-      silc_free(client_id);
-
-      /* Kicker must be operator on channel */
-      if (!silc_server_client_on_channel(client2, channel, &chl))
-       goto out;
-      if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
-         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
-       SILC_LOG_DEBUG(("Kicking is not allowed"));
+       silc_free(client_id);
        goto out;
       }
     }
+    silc_free(client_id);
+
+    /* Kicker must be operator on channel */
+    if (!silc_server_client_on_channel(client2, channel, &chl))
+      goto out;
+    if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
+       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
+      SILC_LOG_DEBUG(("Kicking is not allowed"));
+      goto out;
+    }
 
     /* Send to channel */
     silc_server_packet_send_to_channel(server, sock, channel, packet->type, 
                                       FALSE, packet->buffer->data, 
                                       packet->buffer->len, FALSE);
 
+    /* Remove the client from channel's invite list */
+    if (channel->invite_list && silc_hash_table_count(channel->invite_list)) {
+      SilcBuffer ab;
+      SilcArgumentPayload iargs;
+      tmp = silc_argument_get_arg_type(args, 1, &tmp_len);
+      ab = silc_argument_payload_encode_one(NULL, tmp, tmp_len, 3);
+      iargs = silc_argument_payload_parse(ab->data, ab->len, 1);
+      silc_server_inviteban_process(server, channel->invite_list, 1, iargs);
+      silc_buffer_free(ab);
+      silc_argument_payload_free(iargs);
+    }
+
     /* Remove the client from channel */
     silc_server_remove_from_one_channel(server, sock, channel, client, FALSE);
 
@@ -1441,34 +1495,34 @@ void silc_server_notify(SilcServer server,
       if (comment_len > 128)
        comment_len = 127;
 
-      /* From protocol version 1.1 we get the killer's ID as well. */
+      /* Get the killer's Client ID */
       tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
-      if (tmp) {
-       client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
-       if (!client_id)
-         goto out;
+      if (!tmp)
+       goto out;
+      client_id = silc_id_payload_parse_id(tmp, tmp_len, &id_type);
+      if (!client_id)
+       goto out;
 
-       if (id_type == SILC_ID_CLIENT) {
-         /* If the the client is not in local list we check global list */
-         client2 = silc_idlist_find_client_by_id(server->global_list, 
+      if (id_type == SILC_ID_CLIENT) {
+       /* If the the client is not in local list we check global list */
+       client2 = silc_idlist_find_client_by_id(server->global_list, 
+                                               client_id, TRUE, NULL);
+       if (!client2) {
+         client2 = silc_idlist_find_client_by_id(server->local_list, 
                                                  client_id, TRUE, NULL);
          if (!client2) {
-           client2 = silc_idlist_find_client_by_id(server->local_list, 
-                                                   client_id, TRUE, NULL);
-           if (!client2) {
-             silc_free(client_id);
-             goto out;
-           }
-         }
-         silc_free(client_id);
-
-         /* Killer must be router operator */
-         if (server->server_type != SILC_SERVER &&
-             !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
-           SILC_LOG_DEBUG(("Killing is not allowed"));
+           silc_free(client_id);
            goto out;
          }
        }
+       silc_free(client_id);
+
+       /* Killer must be router operator */
+       if (server->server_type != SILC_SERVER &&
+           !(client2->mode & SILC_UMODE_ROUTER_OPERATOR)) {
+         SILC_LOG_DEBUG(("Killing is not allowed"));
+         goto out;
+       }
       }
 
       /* Send the notify to local clients on the channels except to the
@@ -1480,7 +1534,7 @@ void silc_server_notify(SilcServer server,
 
       /* Remove the client from all channels */
       silc_server_remove_from_channels(server, NULL, client, FALSE, NULL, 
-                                      FALSE);
+                                      FALSE, TRUE);
 
       /* Check if anyone is watching this nickname */
       silc_server_check_watcher_list(server, client, NULL,
@@ -1539,12 +1593,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;
@@ -1566,6 +1614,8 @@ void silc_server_notify(SilcServer server,
          server->stat.detached--;
       }
     }
+    SILC_UMODE_STATS_UPDATE(server, SILC_UMODE_SERVER_OPERATOR);
+    SILC_UMODE_STATS_UPDATE(router, SILC_UMODE_ROUTER_OPERATOR);
 
     /* Change the mode */
     client->mode = mode;
@@ -1606,41 +1656,34 @@ void silc_server_notify(SilcServer server,
     }
     silc_free(channel_id);
 
-    /* Get the new ban and add it to the ban list */
+    /* Get the ban action */
     tmp = silc_argument_get_arg_type(args, 2, &tmp_len);
-    if (tmp) {
-      if (!channel->ban_list)
-       channel->ban_list = silc_calloc(tmp_len + 2, 
-                                       sizeof(*channel->ban_list));
-      else
-       channel->ban_list = silc_realloc(channel->ban_list, 
-                                        sizeof(*channel->ban_list) * 
-                                        (tmp_len + 
-                                         strlen(channel->ban_list) + 2));
-      strncat(channel->ban_list, tmp, tmp_len);
-      strncat(channel->ban_list, ",", 1);
-    }
+    if (tmp && tmp_len == 1) {
+      SilcUInt8 action = (SilcUInt8)tmp[0];
+      SilcUInt16 iargc = 0;
+      SilcArgumentPayload iargs;
 
-    /* Get the ban to be removed and remove it from the list */
-    tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
-    if (tmp && channel->ban_list) {
-      char *start, *end, *n;
-      
-      if (!strncmp(channel->ban_list, tmp, strlen(channel->ban_list) - 1)) {
-       silc_free(channel->ban_list);
-       channel->ban_list = NULL;
-      } else {
-       start = strstr(channel->ban_list, tmp);
-       if (start && strlen(start) >= tmp_len) {
-         end = start + tmp_len;
-         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
-         strncat(n, channel->ban_list, start - channel->ban_list);
-         strncat(n, end + 1, ((channel->ban_list + 
-                               strlen(channel->ban_list)) - end) - 1);
-         silc_free(channel->ban_list);
-         channel->ban_list = n;
-       }
-      }
+      /* Get ban list */
+      tmp = silc_argument_get_arg_type(args, 3, &tmp_len);
+      if (!tmp || tmp_len < 2)
+       goto out;
+
+      /* Parse the arguments to see they are constructed correctly */
+      SILC_GET16_MSB(iargc, tmp);
+      iargs = silc_argument_payload_parse(tmp + 2, tmp_len - 2, iargc);
+      if (!iargs)
+       goto out;
+
+      if (action == 0 && !channel->ban_list)
+       channel->ban_list =
+         silc_hash_table_alloc(0, silc_hash_ptr,
+                               NULL, NULL, NULL,
+                               silc_server_inviteban_destruct, channel, TRUE);
+
+      /* Proces the ban action */
+      silc_server_inviteban_process(server, channel->ban_list, action,
+                                   iargs);
+      silc_argument_payload_free(iargs);
     }
     break;
 
@@ -1671,7 +1714,8 @@ void silc_server_notify(SilcServer server,
                                                 client_id, FALSE, NULL);
          if (client) {
            silc_server_remove_from_channels(server, NULL, client, TRUE, 
-                                            NULL, TRUE);
+                                            NULL, TRUE, FALSE);
+           silc_idlist_del_data(client);
            silc_idlist_del_client(server->global_list, client);
          }
          silc_free(client_id);
@@ -1870,11 +1914,6 @@ void silc_server_command_reply(SilcServer server,
 
   SILC_LOG_DEBUG(("Start"));
 
-  /* Source must be server or router */
-  if (packet->src_id_type != SILC_ID_SERVER &&
-      sock->type != SILC_SOCKET_TYPE_ROUTER)
-    return;
-
   if (packet->dst_id_type == SILC_ID_CHANNEL)
     return;
 
@@ -2064,22 +2103,25 @@ void silc_server_channel_key(SilcServer server,
   SilcChannelEntry channel;
 
   if (packet->src_id_type != SILC_ID_SERVER ||
-      (server->server_type == SILC_ROUTER &&
+      (server->server_type == SILC_ROUTER && !server->backup_router &&
        sock->type == SILC_SOCKET_TYPE_ROUTER))
     return;
 
   /* Save the channel key */
   channel = silc_server_save_channel_key(server, buffer, NULL);
-  if (!channel)
+  if (!channel) {
+    SILC_LOG_ERROR(("Bad channel key from %s (%s)",
+                   sock->hostname, sock->ip));
     return;
-
+  }
+    
   /* Distribute the key to everybody who is on the channel. If we are router
      we will also send it to locally connected servers. */
   silc_server_send_channel_key(server, sock, channel, FALSE);
   
   if (server->server_type != SILC_BACKUP_ROUTER) {
     /* Distribute to local cell backup routers. */
-    silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
+    silc_server_backup_send(server, sock->user_data, 
                            SILC_PACKET_CHANNEL_KEY, 0,
                            buffer->data, buffer->len, FALSE, TRUE);
   }
@@ -2266,11 +2308,30 @@ SilcClientEntry silc_server_new_client(SilcServer server,
     snprintf(&nickname[strlen(nickname) - 1], 1, "%d", nickfail);
   }
 
+  /* If client marked as anonymous, scramble the username and hostname */
+  if (client->mode & SILC_UMODE_ANONYMOUS) {
+    char *scramble;
+
+    if (strlen(username) >= 2) {
+      username[0] = silc_rng_get_byte_fast(server->rng);
+      username[1] = silc_rng_get_byte_fast(server->rng);
+    }
+
+    scramble = silc_hash_babbleprint(server->sha1hash, username,
+                                    strlen(username));
+    scramble[5] = '@';
+    scramble[11] = '.';
+    memcpy(&scramble[16], ".silc", 5);
+    scramble[21] = '\0';
+    silc_free(username);
+    username = scramble;
+  }
+
   /* Update client entry */
   idata->status |= SILC_IDLIST_STATUS_REGISTERED;
   client->nickname = nickname;
   client->username = username;
-  client->userinfo = realname ? realname : strdup(" ");
+  client->userinfo = realname ? realname : strdup(username);
   client->id = client_id;
   id_len = silc_id_get_len(client_id, SILC_ID_CLIENT);
 
@@ -2286,7 +2347,7 @@ SilcClientEntry silc_server_new_client(SilcServer server,
   /* Distribute to backup routers */
   if (server->server_type == SILC_ROUTER) {
     SilcBuffer idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+    silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
                            idp->data, idp->len, FALSE, TRUE);
     silc_buffer_free(idp);
   }
@@ -2446,7 +2507,7 @@ SilcServerEntry silc_server_new_server(SilcServer server,
   if (server->server_type == SILC_ROUTER) {
     /* Distribute to backup routers */
     SilcBuffer idp = silc_id_payload_encode(new_server->id, SILC_ID_SERVER);
-    silc_server_backup_send(server, NULL, SILC_PACKET_NEW_ID, 0,
+    silc_server_backup_send(server, sock->user_data, SILC_PACKET_NEW_ID, 0,
                            idp->data, idp->len, FALSE, TRUE);
     silc_buffer_free(idp);
 
@@ -2484,6 +2545,36 @@ SilcServerEntry silc_server_new_server(SilcServer server,
       silc_server_announce_clients(server, 0, sock);
       silc_server_announce_channels(server, 0, sock);
     }
+
+    /* Announce our information to backup router */
+    if (new_server->server_type == SILC_BACKUP_ROUTER &&
+       sock->type == SILC_SOCKET_TYPE_SERVER &&
+       server->server_type == SILC_ROUTER) {
+      silc_server_announce_servers(server, TRUE, 0, sock);
+      silc_server_announce_clients(server, 0, sock);
+      silc_server_announce_channels(server, 0, sock);
+    }
+
+    /* If backup router, mark it as one of ours.  This server is considered
+       to be backup router after this setting. */
+    if (new_server->server_type == SILC_BACKUP_ROUTER) {
+      SilcServerConfigRouter *backup;
+      backup = silc_server_config_find_backup_conn(server, sock->ip);
+      if (!backup)
+       backup = silc_server_config_find_backup_conn(server, sock->hostname);
+      if (backup) {
+       /* Add as our backup router */
+       silc_server_backup_add(server, new_server, backup->backup_replace_ip,
+                              backup->backup_replace_port,
+                              backup->backup_local);
+      }
+    }
+
+    /* 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;
@@ -2679,7 +2770,7 @@ static void silc_server_new_id_real(SilcServer server,
                            packet->type, 
                            packet->flags | SILC_PACKET_FLAG_BROADCAST,
                            buffer->data, buffer->len, FALSE);
-    silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
+    silc_server_backup_send(server, sock->user_data, 
                            packet->type, packet->flags,
                            packet->buffer->data, packet->buffer->len, 
                            FALSE, TRUE);
@@ -2727,7 +2818,7 @@ void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
                            packet->flags | SILC_PACKET_FLAG_BROADCAST,
                            packet->buffer->data, 
                            packet->buffer->len, FALSE);
-    silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
+    silc_server_backup_send(server, sock->user_data, 
                            packet->type, packet->flags,
                            packet->buffer->data, packet->buffer->len, 
                            FALSE, TRUE);
@@ -2737,7 +2828,7 @@ void silc_server_new_id_list(SilcServer server, SilcSocketConnection sock,
      data buffer, which we will here now fetch from the original buffer. */
   new_id = silc_packet_context_alloc();
   new_id->type = SILC_PACKET_NEW_ID;
-  new_id->flags = packet->flags;
+  new_id->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
   new_id->src_id = packet->src_id;
   new_id->src_id_len = packet->src_id_len;
   new_id->src_id_type = packet->src_id_type;
@@ -2782,9 +2873,10 @@ void silc_server_new_channel(SilcServer server,
   char *channel_name;
   SilcUInt32 name_len;
   unsigned char *id;
-  SilcUInt32 id_len;
+  SilcUInt32 id_len, cipher_len;
   SilcServerEntry server_entry;
   SilcChannelEntry channel;
+  const char *cipher;
 
   if (sock->type == SILC_SOCKET_TYPE_CLIENT ||
       packet->src_id_type != SILC_ID_SERVER ||
@@ -2830,9 +2922,12 @@ void silc_server_new_channel(SilcServer server,
       channel = 
        silc_idlist_add_channel(server->global_list, strdup(channel_name), 
                                0, channel_id, sock->user_data, NULL, NULL, 0);
-      if (!channel)
+      if (!channel) {
+       silc_channel_payload_free(payload);
+       silc_free(channel_id);
        return;
-      channel->disabled = TRUE;
+      }
+      channel->disabled = TRUE;    /* Disabled until someone JOINs */
 
       server->stat.channels++;
       if (server->server_type == SILC_ROUTER)
@@ -2867,13 +2962,16 @@ void silc_server_new_channel(SilcServer server,
          !SILC_ID_COMPARE(channel_id, server->id, server->id->ip.data_len)) {
        SilcChannelID *tmp;
        SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
-       
        if (silc_id_create_channel_id(server, server->id, server->rng, &tmp)) {
          silc_server_send_notify_channel_change(server, sock, FALSE, 
                                                 channel_id, tmp);
+         silc_channel_payload_free(payload);
          silc_free(channel_id);
-         channel_id = tmp;
+         silc_free(tmp);
        }
+
+       /* Wait that server re-announces this channel */
+       return;
       }
 
       /* Create the channel with the provided Channel ID */
@@ -2885,21 +2983,30 @@ void silc_server_new_channel(SilcServer server,
        silc_free(channel_id);
        return;
       }
-      channel->disabled = TRUE;
-      channel->mode = silc_channel_get_mode(payload);
+      channel->disabled = TRUE;    /* Disabled until someone JOINs */
+
+#if 0 /* We assume that CMODE_CHANGE notify is sent to us after this. */
+
+      /* XXX Dunno if this is supposed to be set in any server type.  If set
+        here the CMODE_CHANGE that may follow sets mode that we already
+        have, and we may loose data from the CMODE_CHANGE notify. */
+      if (server_entry->server_type != SILC_BACKUP_ROUTER)
+       channel->mode = silc_channel_get_mode(payload);
+#endif
 
       /* Send the new channel key to the server */
       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
       id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+      cipher = silc_cipher_get_name(channel->channel_key);
+      cipher_len = strlen(cipher);
       chk = silc_channel_key_payload_encode(id_len, id,
-                                           strlen(channel->channel_key->
-                                                  cipher->name),
-                                           channel->channel_key->cipher->name,
+                                           cipher_len, cipher,
                                            channel->key_len / 8, 
                                            channel->key);
       silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
                              chk->data, chk->len, FALSE);
       silc_buffer_free(chk);
+      silc_free(id);
     } else {
       /* The channel exist by that name, check whether the ID's match.
         If they don't then we'll force the server to use the ID we have.
@@ -2914,6 +3021,8 @@ void silc_server_new_channel(SilcServer server,
        SILC_LOG_DEBUG(("Forcing the server to change Channel ID"));
        silc_server_send_notify_channel_change(server, sock, FALSE, 
                                               channel_id, channel->id);
+       silc_channel_payload_free(payload);
+       silc_free(channel_id);
 
        /* Wait that server re-announces this channel */
        return;
@@ -2939,20 +3048,25 @@ void silc_server_new_channel(SilcServer server,
       /* Create new key for the channel and send it to the server and
         everybody else possibly on the channel. */
       if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
-       if (!silc_server_create_channel_key(server, channel, 0))
-         return;
-       
-       /* Send to the channel */
-       silc_server_send_channel_key(server, sock, channel, FALSE);
-       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
-       id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+
+       if (silc_hash_table_count(channel->user_list)) {
+         if (!silc_server_create_channel_key(server, channel, 0)) {
+           silc_channel_payload_free(payload);
+           silc_free(channel_id);
+           return;
+         }
+
+         /* Send to the channel */
+         silc_server_send_channel_key(server, sock, channel, FALSE);
+       }
 
        /* Send to the server */
+       id = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+       id_len = silc_id_get_len(channel->id, SILC_ID_CHANNEL);
+       cipher = silc_cipher_get_name(channel->channel_key);
+       cipher_len = strlen(cipher);
        chk = silc_channel_key_payload_encode(id_len, id,
-                                             strlen(channel->channel_key->
-                                                    cipher->name),
-                                             channel->channel_key->
-                                             cipher->name,
+                                             cipher_len, cipher,
                                              channel->key_len / 8, 
                                              channel->key);
        silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
@@ -2963,10 +3077,6 @@ void silc_server_new_channel(SilcServer server,
 
       silc_free(channel_id);
 
-      /* Update statistics */
-      server->stat.channels++;
-      server->stat.cell_channels++;
-
       /* Since the channel is coming from server and we also know about it
         then send the JOIN notify to the server so that it see's our
         users on the channel "joining" the channel. */
@@ -3006,6 +3116,24 @@ void silc_server_new_channel(SilcServer server,
     }
   }
 
+  /* If the sender of this packet is server and we are router we need to
+     broadcast this packet to other routers in the network. Broadcast
+     this list packet instead of multiple New Channel packets. */
+  if (server->server_type == SILC_ROUTER &&
+      sock->type == SILC_SOCKET_TYPE_SERVER &&
+      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+    SILC_LOG_DEBUG(("Broadcasting received New Channel packet"));
+    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, sock->user_data, 
+                           packet->type, packet->flags,
+                           packet->buffer->data, packet->buffer->len, 
+                           FALSE, TRUE);
+  }
+
   silc_channel_payload_free(payload);
 }
 
@@ -3027,29 +3155,11 @@ void silc_server_new_channel_list(SilcServer server,
       server->server_type == SILC_SERVER)
     return;
 
-  /* If the sender of this packet is server and we are router we need to
-     broadcast this packet to other routers in the network. Broadcast
-     this list packet instead of multiple New Channel packets. */
-  if (server->server_type == SILC_ROUTER &&
-      sock->type == SILC_SOCKET_TYPE_SERVER &&
-      !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-    SILC_LOG_DEBUG(("Broadcasting received New Channel List packet"));
-    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, 
-                           FALSE, TRUE);
-  }
-
   /* Make copy of the original packet context, except for the actual
      data buffer, which we will here now fetch from the original buffer. */
   new = silc_packet_context_alloc();
   new->type = SILC_PACKET_NEW_CHANNEL;
-  new->flags = packet->flags;
+  new->flags = packet->flags & (~SILC_PACKET_FLAG_LIST);
   new->src_id = packet->src_id;
   new->src_id_len = packet->src_id_len;
   new->src_id_type = packet->src_id_type;
@@ -3299,6 +3409,8 @@ SILC_SERVER_CMD_FUNC(resume_resolve)
        silc_server_free_sock_user_data(server, sock, NULL);
       goto out;
     }
+
+    client->data.status |= SILC_IDLIST_STATUS_RESUME_RES;
   }
 
   /* Reprocess the packet */
@@ -3322,6 +3434,7 @@ void silc_server_resume_client(SilcServer server,
 {
   SilcBuffer buffer = packet->buffer, buf;
   SilcIDListData idata;
+  SilcIDCacheEntry id_cache = NULL;
   SilcClientEntry detached_client;
   SilcClientID *client_id = NULL;
   unsigned char *id_string, *auth = NULL;
@@ -3332,6 +3445,7 @@ void silc_server_resume_client(SilcServer server,
   SilcHashTableList htl;
   SilcChannelClientEntry chl;
   SilcServerResumeResolve r;
+  const char *cipher;
 
   ret = silc_buffer_unformat(buffer,
                             SILC_STR_UI16_NSTRING(&id_string, &id_len),
@@ -3368,8 +3482,8 @@ void silc_server_resume_client(SilcServer server,
     idata = (SilcIDListData)client;
 
     /* Get entry to the client, and resolve it if we don't have it. */
-    detached_client = silc_server_get_client_resolve(server, client_id, FALSE,
-                                                    &resolved);
+    detached_client = silc_server_query_client(server, client_id, FALSE,
+                                              &resolved);
     if (!detached_client) {
       if (resolved) {
        /* The client info is being resolved. Reprocess this packet after
@@ -3405,13 +3519,15 @@ void silc_server_resume_client(SilcServer server,
       resolve = TRUE;
     if (!detached_client->nickname)
       resolve = TRUE;
+    if (detached_client->data.status & SILC_IDLIST_STATUS_RESUME_RES)
+      resolve = FALSE;
 
     if (resolve) {
       if (server->server_type == SILC_SERVER && !server->standalone) {
        /* The client info is being resolved. Reprocess this packet after
           receiving the reply to the query. */
        SILC_LOG_DEBUG(("Resolving client info"));
-       silc_server_get_client_resolve(server, client_id, TRUE, NULL);
+       silc_server_query_client(server, client_id, TRUE, NULL);
        r = silc_calloc(1, sizeof(*r));
        if (!r)
          return;
@@ -3524,6 +3640,8 @@ void silc_server_resume_client(SilcServer server,
     silc_idlist_add_data(detached_client, idata);
     detached_client->data.status |= SILC_IDLIST_STATUS_REGISTERED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+    detached_client->data.status |= SILC_IDLIST_STATUS_LOCAL;
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_RESUME_RES;
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     server->stat.my_detached--;
 
@@ -3539,6 +3657,9 @@ void silc_server_resume_client(SilcServer server,
     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
                            SILC_PACKET_RESUME_CLIENT, 0, 
                            buf->data, buf->len, TRUE);
+    silc_server_backup_send(server, detached_client->router,
+                           SILC_PACKET_RESUME_CLIENT, 0,
+                           buf->data, buf->len, TRUE, TRUE);
 
     /* As router we must deliver this packet directly to the original
        server whom this client was earlier. */
@@ -3556,9 +3677,14 @@ void silc_server_resume_client(SilcServer server,
     server->stat.clients--;
     if (server->stat.cell_clients)
       server->stat.cell_clients--;
+    silc_server_remove_from_channels(server, NULL, client, FALSE,
+                                    NULL, FALSE, FALSE);
     silc_server_del_from_watcher_list(server, client);
-    silc_idlist_del_client(server->local_list, client);
+    if (!silc_idlist_del_client(server->local_list, client))
+      silc_idlist_del_client(server->global_list, client);
     client = detached_client;
+    silc_free(client->servername);
+    client->servername = strdup(server->server_name);
 
     /* If the ID is not based in our ID then change it */
     if (!SILC_ID_COMPARE(client->id, server->id, server->id->ip.data_len)) {
@@ -3655,24 +3781,27 @@ void silc_server_resume_client(SilcServer server,
       }
 
       id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
+      cipher = silc_cipher_get_name(channel->channel_key);
       keyp = 
        silc_channel_key_payload_encode(silc_id_get_len(channel->id,
                                                        SILC_ID_CHANNEL), 
                                        id_string,
-                                       strlen(channel->channel_key->
-                                              cipher->name),
-                                       channel->channel_key->cipher->name,
+                                       strlen(cipher), cipher,
                                        channel->key_len / 8, channel->key);
       silc_free(id_string);
 
-      /* Send the key packet to client */
+      /* Send the channel key to the client */
       silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
                              keyp->data, keyp->len, FALSE);
 
-      if (created && server->server_type == SILC_SERVER)
-       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server), 
-                               SILC_PACKET_CHANNEL_KEY, 0, 
-                               keyp->data, keyp->len, FALSE);
+      /* Distribute the channel key to channel */
+      if (created) {
+       silc_server_send_channel_key(server, NULL, channel,
+                                    server->server_type == SILC_ROUTER ? 
+                                    FALSE : !server->standalone);
+       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
+                               keyp->data, keyp->len, FALSE, TRUE);
+      }
 
       silc_buffer_free(keyp);
     }
@@ -3691,10 +3820,12 @@ void silc_server_resume_client(SilcServer server,
 
     /* Get entry to the client, and resolve it if we don't have it. */
     detached_client = silc_idlist_find_client_by_id(server->local_list, 
-                                                   client_id, TRUE, NULL);
+                                                   client_id, TRUE,
+                                                   &id_cache);
     if (!detached_client) {
       detached_client = silc_idlist_find_client_by_id(server->global_list,
-                                                     client_id, TRUE, NULL);
+                                                     client_id, TRUE,
+                                                     &id_cache);
       if (!detached_client) {
        SILC_LOG_DEBUG(("Resuming client is unknown"));
        silc_free(client_id);
@@ -3724,10 +3855,33 @@ void silc_server_resume_client(SilcServer server,
       return;
     }
 
+    SILC_LOG_DEBUG(("Resuming detached client"));
+
+    /* If the sender of this packet is server and we are router we need to
+       broadcast this packet to other routers in the network. */
+    if (server->server_type == SILC_ROUTER &&
+       sock->type == SILC_SOCKET_TYPE_SERVER &&
+       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
+      SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
+      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
+                             packet->type, 
+                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
+                             buffer->data, buffer->len, FALSE);
+      silc_server_backup_send(server, sock->user_data, 
+                             packet->type, packet->flags,
+                             packet->buffer->data, packet->buffer->len, 
+                             FALSE, TRUE);
+    }
+
     /* Client is detached, and now it is resumed.  Remove the detached
        mode and mark that it is resumed. */
+    silc_idlist_del_data(detached_client);
     detached_client->mode &= ~SILC_UMODE_DETACHED;
     detached_client->data.status |= SILC_IDLIST_STATUS_RESUMED;
+    detached_client->data.status &= ~SILC_IDLIST_STATUS_LOCAL;
+    id_cache->expire = 0;
+
+    silc_schedule_task_del_by_context(server->schedule, detached_client);
 
     /* Get the new owner of the resumed client */
     server_id = silc_id_str2id(packet->src_id, packet->src_id_len,
@@ -3740,11 +3894,11 @@ void silc_server_resume_client(SilcServer server,
     /* Get server entry */
     server_entry = silc_idlist_find_server_by_id(server->global_list, 
                                                 server_id, TRUE, NULL);
-    local = TRUE;
+    local = FALSE;
     if (!server_entry) {
       server_entry = silc_idlist_find_server_by_id(server->local_list, 
                                                   server_id, TRUE, NULL);
-      local = FALSE;
+      local = TRUE;
       if (!server_entry) {
        silc_free(server_id);
        silc_free(client_id);
@@ -3753,30 +3907,26 @@ void silc_server_resume_client(SilcServer server,
     }
 
     if (server->server_type == SILC_ROUTER &&
-       sock->type == SILC_SOCKET_TYPE_ROUTER && 
+       sock->type == SILC_SOCKET_TYPE_ROUTER &&
        server_entry->server_type == SILC_ROUTER)
       local = FALSE;
 
-    SILC_LOG_DEBUG(("Resuming detached client"));
-
     /* Change the client to correct list. */
     if (!silc_idcache_del_by_context(server->local_list->clients,
                                     detached_client))
       silc_idcache_del_by_context(server->global_list->clients,
                                  detached_client);
-    silc_idcache_add(local && server->server_type == SILC_ROUTER ? 
-                    server->local_list->clients : 
-                    server->global_list->clients, 
+    silc_idcache_add(local && server->server_type == SILC_ROUTER ?
+                    server->local_list->clients :
+                    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)
-      detached_client->router = server_entry;
+    /* Change the owner of the client */
+    detached_client->router = server_entry;
 
     /* Update channel information regarding global clients on channel. */
-    if (server->server_type == SILC_SERVER) {
+    if (server->server_type != SILC_ROUTER) {
       silc_hash_table_list(detached_client->channels, &htl);
       while (silc_hash_table_get(&htl, NULL, (void **)&chl))
        chl->channel->global_users = 
@@ -3784,24 +3934,6 @@ void silc_server_resume_client(SilcServer server,
       silc_hash_table_list_reset(&htl);
     }
 
-    silc_schedule_task_del_by_context(server->schedule, detached_client);
-
-    /* If the sender of this packet is server and we are router we need to
-       broadcast this packet to other routers in the network. */
-    if (server->server_type == SILC_ROUTER &&
-       sock->type == SILC_SOCKET_TYPE_SERVER &&
-       !(packet->flags & SILC_PACKET_FLAG_BROADCAST)) {
-      SILC_LOG_DEBUG(("Broadcasting received Resume Client packet"));
-      silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
-                             packet->type, 
-                             packet->flags | SILC_PACKET_FLAG_BROADCAST,
-                             buffer->data, buffer->len, FALSE);
-      silc_server_backup_send(server, (SilcServerEntry)sock->user_data, 
-                             packet->type, packet->flags,
-                             packet->buffer->data, packet->buffer->len, 
-                             FALSE, TRUE);
-    }
-
     silc_free(server_id);
   }