Added silc_server_remove_servers_by_server to remove servers
authorPekka Riikonen <priikone@silcnet.org>
Wed, 26 Jun 2002 12:33:36 +0000 (12:33 +0000)
committerPekka Riikonen <priikone@silcnet.org>
Wed, 26 Jun 2002 12:33:36 +0000 (12:33 +0000)
and clients of those servers.

CHANGES
TODO
apps/silcd/packet_receive.c
apps/silcd/packet_send.c
apps/silcd/server.c
apps/silcd/server_backup.c
apps/silcd/server_util.c
apps/silcd/server_util.h

diff --git a/CHANGES b/CHANGES
index b6eb31ec3e502448e9cb5630cc472e1ad8cf797e..6d87f8edc56c3bc03b0e46b95e1be9e61707e732 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,13 @@
+Wed Jun 26 15:14:12 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
+
+       * Stop for a couple seconds after badkup router has become
+         primary router.  Affected file silcd/server.c.
+
+       * Added silc_server_remove_servers_by_server, which is used
+         to remove servers originated from some other server.  Also
+         clients of those servers can be removed too.  Affected file
+         silcd/server_util.[ch].
+
 Wed Jun 26 10:38:11 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed a bug in silc_string_regexify which did not add '^'
 Wed Jun 26 10:38:11 EEST 2002 Pekka Riikonen <priikone@silcnet.org>
 
        * Fixed a bug in silc_string_regexify which did not add '^'
diff --git a/TODO b/TODO
index b3e6b13c934fd28bef11c240cb0a967239aaba99..911a25ad0b7d32a8ae54e423204dc1ff6e64c7fa 100644 (file)
--- a/TODO
+++ b/TODO
@@ -43,6 +43,10 @@ TODO/bugs In SILC Server
            not the server's ID, which it should include.  The notify
            is sent by backup.
 
            not the server's ID, which it should include.  The notify
            is sent by backup.
 
+       o When removing clients by server in signoff, EOF etc, find also
+         the client's real server (based on the Client ID's IP), and
+         remove the server too.
+
        o Testing
 
  o Close unconfigured client connections in rehash.
        o Testing
 
  o Close unconfigured client connections in rehash.
index 4abfcfb86ba5a70f822fd47e9c96b9b3fd5e65cc..4e07b0ce40502355bbca0bb2b7f7580e33ee4c71 100644 (file)
@@ -1298,9 +1298,14 @@ void silc_server_notify(SilcServer server,
     if (SILC_IS_LOCAL(server_entry))
       break;
 
     if (SILC_IS_LOCAL(server_entry))
       break;
 
-    /* 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);
+    /* 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_server_backup_del(server, server_entry);
 
     /* Remove the server entry */
index b159c9314a66ea41108ddb1082739c8efc421b7c..7d7e0a5ec2627c27e3837978c96cfb9f57107a64 100644 (file)
@@ -97,7 +97,8 @@ void silc_server_packet_send(SilcServer server,
     return;
 
   /* If entry is disabled do not sent anything. */
     return;
 
   /* If entry is disabled do not sent anything. */
-  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+      sock->user_data == server->id_entry) {
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
@@ -159,7 +160,8 @@ void silc_server_packet_send_dest(SilcServer server,
   idata = (SilcIDListData)sock->user_data;
 
   /* If entry is disabled do not sent anything. */
   idata = (SilcIDListData)sock->user_data;
 
   /* If entry is disabled do not sent anything. */
-  if (idata && idata->status & SILC_IDLIST_STATUS_DISABLED) {
+  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+      sock->user_data == server->id_entry) {
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
     SILC_LOG_DEBUG(("Connection is disabled"));
     return;
   }
@@ -257,6 +259,20 @@ void silc_server_packet_send_srcdest(SilcServer server,
   /* Get data used in the packet sending, keys and stuff */
   idata = (SilcIDListData)sock->user_data;
 
   /* Get data used in the packet sending, keys and stuff */
   idata = (SilcIDListData)sock->user_data;
 
+  /* If entry is disabled do not sent anything. */
+  if ((idata && idata->status & SILC_IDLIST_STATUS_DISABLED) ||
+      sock->user_data == server->id_entry) {
+    SILC_LOG_DEBUG(("Connection is disabled"));
+    return;
+  }
+
+  if (idata) {
+    cipher = idata->send_key;
+    hmac = idata->hmac_send;
+    sequence = idata->psn_send++;
+    block_len = silc_cipher_get_block_len(cipher);
+  }
+
   if (dst_id) {
     dst_id_data = silc_id_id2str(dst_id, dst_id_type);
     dst_id_len = silc_id_get_len(dst_id, dst_id_type);
   if (dst_id) {
     dst_id_data = silc_id_id2str(dst_id, dst_id_type);
     dst_id_len = silc_id_get_len(dst_id, dst_id_type);
@@ -267,13 +283,6 @@ void silc_server_packet_send_srcdest(SilcServer server,
     src_id_len = silc_id_get_len(src_id, src_id_type);
   }
 
     src_id_len = silc_id_get_len(src_id, src_id_type);
   }
 
-  if (idata) {
-    cipher = idata->send_key;
-    hmac = idata->hmac_send;
-    sequence = idata->psn_send++;
-    block_len = silc_cipher_get_block_len(cipher);
-  }
-
   /* Set the packet context pointers */
   packetdata.type = type;
   packetdata.flags = flags;
   /* Set the packet context pointers */
   packetdata.type = type;
   packetdata.flags = flags;
index ebb3e811fc4b5f1184ed35882db0b7dd83a8127d..75e84719f20557a732c7d2e7d4737b08e27eac27 100644 (file)
@@ -893,20 +893,15 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
   SilcServerConnection sconn;
   SilcServerConfigRouter *ptr;
 
   SilcServerConnection sconn;
   SilcServerConfigRouter *ptr;
 
-  SILC_LOG_DEBUG(("Connecting to router(s)"));
-
-  if (server->server_type == SILC_SERVER) {
-    SILC_LOG_DEBUG(("We are normal server"));
-  } else if (server->server_type == SILC_ROUTER) {
-    SILC_LOG_DEBUG(("We are router"));
-  } else {
-    SILC_LOG_DEBUG(("We are backup router/normal server"));
-  }
+  SILC_LOG_DEBUG(("We are %s",
+                 (server->server_type == SILC_SERVER ?
+                  "normal server" : server->server_type == SILC_ROUTER ?
+                  "router" : "backup router/normal server")));
 
   if (!server->config->routers) {
     /* There wasn't a configured router, we will continue but we don't
        have a connection to outside world.  We will be standalone server. */
 
   if (!server->config->routers) {
     /* There wasn't a configured router, we will continue but we don't
        have a connection to outside world.  We will be standalone server. */
-    SILC_LOG_DEBUG(("No router(s), server will be standalone"));
+    SILC_LOG_DEBUG(("No router(s), we are standalone"));
     server->standalone = TRUE;
     return;
   }
     server->standalone = TRUE;
     return;
   }
@@ -2996,6 +2991,9 @@ void silc_server_free_sock_user_data(SilcServer server,
            server->id_entry->router = NULL;
            server->router = NULL;
            server->standalone = TRUE;
            server->id_entry->router = NULL;
            server->router = NULL;
            server->standalone = TRUE;
+
+           /* We stop here to take a breath */
+           sleep(2);
          }
 
          if (server->server_type == SILC_BACKUP_ROUTER) {
          }
 
          if (server->server_type == SILC_BACKUP_ROUTER) {
@@ -3024,24 +3022,38 @@ void silc_server_free_sock_user_data(SilcServer server,
       }
 
       if (!backup_router) {
       }
 
       if (!backup_router) {
-       /* As router, remove clients and channels always.  As normal server
-          remove only if it is our primary router.  Other connections
-          may be backup routers and these normal server don't handle here. */
-       if (server->server_type != SILC_SERVER ||
-           server->standalone || sock == SILC_PRIMARY_ROUTE(server)) {
-         /* Free all client entries that this server owns as they will
-            become invalid now as well. */
-         silc_server_remove_clients_by_server(server, user_data, TRUE);
-         if (server->server_type == SILC_SERVER)
-           silc_server_remove_channels_by_server(server, user_data);
-       }
+       /* Remove all servers that are originated from this server, and
+          remove the clients of those servers too. */
+       silc_server_remove_servers_by_server(server, user_data, TRUE);
+
+       /* Remove the clients that this server owns as they will become
+          invalid now too. */
+       silc_server_remove_clients_by_server(server, user_data,
+                                            user_data, TRUE);
+
+       /* Remove channels owned by this server */
+       if (server->server_type == SILC_SERVER)
+         silc_server_remove_channels_by_server(server, user_data);
       } else {
       } else {
-       /* Update the client entries of this server to the new backup
-          router. This also removes the clients that *really* was owned
-          by the primary router and went down with the router.  */
+       /* Enable local server connections that may be disabled */
        silc_server_local_servers_toggle_enabled(server, TRUE);
        silc_server_local_servers_toggle_enabled(server, TRUE);
-       silc_server_update_clients_by_server(server, user_data, backup_router,
-                                            TRUE, TRUE);
+
+       /* If we are router and just lost our primary router (now standlaone)
+          we remove everything that was behind it, since we don't know
+          any better. */
+       if (server->server_type == SILC_ROUTER && server->standalone)
+         /* Remove all servers that are originated from this server, and
+            remove the clients of those servers too. */
+         silc_server_remove_servers_by_server(server, user_data, TRUE);
+
+       /* Update the client entries of this server to the new backup
+          router.  If we are the backup router we also resolve the real
+          servers for the clients.  After updating is over this also
+          removes the clients that this server explicitly owns. */
+       silc_server_update_clients_by_server(server, user_data,
+                                            backup_router, TRUE, TRUE);
+
+       /* Update our server cache to use the new backup router too. */
        silc_server_update_servers_by_server(server, user_data, backup_router);
        if (server->server_type == SILC_SERVER)
          silc_server_update_channels_by_server(server, user_data,
        silc_server_update_servers_by_server(server, user_data, backup_router);
        if (server->server_type == SILC_SERVER)
          silc_server_update_channels_by_server(server, user_data,
@@ -4828,8 +4840,6 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   SilcProtocol protocol;
   SilcServerRekeyInternalContext *proto_ctx;
 
   SilcProtocol protocol;
   SilcServerRekeyInternalContext *proto_ctx;
 
-  SILC_LOG_DEBUG(("Start"));
-
   /* Allocate internal protocol context. This is sent as context
      to the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
   /* Allocate internal protocol context. This is sent as context
      to the protocol. */
   proto_ctx = silc_calloc(1, sizeof(*proto_ctx));
@@ -4847,6 +4857,8 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   /* Run the protocol */
   silc_protocol_execute(protocol, server->schedule, 0, 0);
 
   /* Run the protocol */
   silc_protocol_execute(protocol, server->schedule, 0, 0);
 
+  SILC_LOG_DEBUG(("Rekey protocol completed"));
+
   /* Re-register re-key timeout */
   silc_schedule_task_add(server->schedule, sock->sock,
                         silc_server_rekey_callback,
   /* Re-register re-key timeout */
   silc_schedule_task_add(server->schedule, sock->sock,
                         silc_server_rekey_callback,
index 19b467844a231eb70c8567abe33d59acaac2909a..5ec8945f68cd439d64c0d21e9fc91eb9c1db021e 100644 (file)
@@ -183,7 +183,7 @@ void silc_server_backup_replaced_add(SilcServer server,
     server->backup->replaced_count = 1;
   }
 
     server->backup->replaced_count = 1;
   }
 
-  SILC_LOG_DEBUG(("Replacing router %s with %s backup",
+  SILC_LOG_DEBUG(("Replacing router %s with %s",
                  silc_id_render(server_id, SILC_ID_SERVER),
                  server_entry->server_name));
 
                  silc_id_render(server_id, SILC_ID_SERVER),
                  server_entry->server_name));
 
index 75091e945e0e12916a1c545993684463ba95167e..89beb68a2db28d50ef471446d1ad6efb34ccda39 100644 (file)
@@ -39,11 +39,11 @@ silc_server_remove_clients_channels(SilcServer server,
   SilcChannelClientEntry chl, chl2;
   SilcHashTableList htl, htl2;
 
   SilcChannelClientEntry chl, chl2;
   SilcHashTableList htl, htl2;
 
-  SILC_LOG_DEBUG(("Start"));
-
   if (!client)
     return;
 
   if (!client)
     return;
 
+  SILC_LOG_DEBUG(("Remove client from all channels"));
+
   if (silc_hash_table_find(clients, client, NULL, NULL))
     silc_hash_table_del(clients, client);
 
   if (silc_hash_table_find(clients, client, NULL, NULL))
     silc_hash_table_del(clients, client);
 
@@ -119,13 +119,13 @@ silc_server_remove_clients_channels(SilcServer server,
   silc_hash_table_list_reset(&htl);
 }
 
   silc_hash_table_list_reset(&htl);
 }
 
-/* This function is used to remove all client entries by the server `entry'.
-   This is called when the connection is lost to the server. In this case
-   we must invalidate all the client entries owned by the server `entry'. 
-   If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
+/* This function removes all client entries that are originated from
+   `router' and are owned by `entry'.  `router' and `entry' can be same
+   too.  If `server_signoff' is TRUE then SERVER_SIGNOFF notify is 
    distributed to our local clients. */
 
    distributed to our local clients. */
 
-bool silc_server_remove_clients_by_server(SilcServer server, 
+bool silc_server_remove_clients_by_server(SilcServer server,
+                                         SilcServerEntry router,
                                          SilcServerEntry entry,
                                          bool server_signoff)
 {
                                          SilcServerEntry entry,
                                          bool server_signoff)
 {
@@ -143,7 +143,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
     return FALSE;
 
   if (!(entry->data.status & SILC_IDLIST_STATUS_REGISTERED))
     return FALSE;
 
-  SILC_LOG_DEBUG(("Start"));
+  SILC_LOG_DEBUG(("Removing clients by %s",
+                 entry->server_name ? entry->server_name : "server"));
+
+  if (!router)
+    router = entry;
 
   /* Allocate the hash table that holds the channels that require
      channel key re-generation after we've removed this server's clients
 
   /* Allocate the hash table that holds the channels that require
      channel key re-generation after we've removed this server's clients
@@ -167,18 +171,15 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   }
 
   if (silc_idcache_get_all(server->local_list->clients, &list)) {
   }
 
   if (silc_idcache_get_all(server->local_list->clients, &list)) {
-
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
-         if (!silc_idcache_list_next(list, &id_cache))
-           break;
-         else
-           continue;
-       }
 
 
-       if (client->router != entry) {
+       /* If client is not registered, is not originated from `router'
+          or is not owned by `entry', skip it. */
+       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+           client->router != router ||
+           !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
@@ -231,14 +232,12 @@ bool silc_server_remove_clients_by_server(SilcServer server,
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
     if (silc_idcache_list_first(list, &id_cache)) {
       while (id_cache) {
        client = (SilcClientEntry)id_cache->context;
-       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
-         if (!silc_idcache_list_next(list, &id_cache))
-           break;
-         else
-           continue;
-       }
-       
-       if (client->router != entry) {
+
+       /* If client is not registered, is not originated from `router'
+          or is not owned by `entry', skip it. */
+       if (!(client->data.status & SILC_IDLIST_STATUS_REGISTERED) ||
+           client->router != router ||
+           !SILC_ID_COMPARE(client->id, entry->id, client->id->ip.data_len)) {
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
          if (!silc_idcache_list_next(list, &id_cache))
            break;
          else
@@ -290,8 +289,8 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   if (server_signoff) {
     SilcBuffer args, not;
 
   if (server_signoff) {
     SilcBuffer args, not;
 
-    SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %d clients",
-                   argc - 1));
+    SILC_LOG_DEBUG(("Sending SERVER_SIGNOFF for %s with %d clients",
+                   silc_id_render(entry->id, SILC_ID_SERVER), argc - 1));
 
     /* Send SERVER_SIGNOFF notify to our primary router */
     if (server->router != entry) {
 
     /* Send SERVER_SIGNOFF notify to our primary router */
     if (server->router != entry) {
@@ -614,7 +613,7 @@ void silc_server_update_clients_by_server(SilcServer server,
     /* Now remove the clients that are still marked as orignated from the
        `from'. These are the clients that really was owned by the `from' and
        not just exist behind the `from'. */
     /* Now remove the clients that are still marked as orignated from the
        `from'. These are the clients that really was owned by the `from' and
        not just exist behind the `from'. */
-    silc_server_remove_clients_by_server(server, from, TRUE);
+    silc_server_remove_clients_by_server(server, from, from, TRUE);
 }
 
 /* Updates servers that are from `from' to be originated from `to'.  This
 }
 
 /* Updates servers that are from `from' to be originated from `to'.  This
@@ -781,6 +780,79 @@ void silc_server_local_servers_toggle_enabled(SilcServer server,
     silc_idcache_list_free(list);
   }
 }
     silc_idcache_list_free(list);
   }
 }
+
+/* Removes servers that are originated from the `from'.  The server
+   entry is deleted in this function.  If `remove_clients' is TRUE then
+   all clients originated from the server are removed too, and server
+   signoff is sent.  Note that this does not remove the `from'.  This
+   also does not remove locally connected servers. */
+
+void silc_server_remove_servers_by_server(SilcServer server,
+                                         SilcServerEntry from,
+                                         bool remove_clients)
+{
+  SilcIDCacheList list = NULL;
+  SilcIDCacheEntry id_cache = NULL;
+  SilcServerEntry server_entry = NULL;
+
+  SILC_LOG_DEBUG(("Removing servers by %s",
+                 from->server_name ? from->server_name : "server"));
+
+  if (silc_idcache_get_all(server->local_list->servers, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       server_entry = (SilcServerEntry)id_cache->context;
+       if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+         server_entry->router != from || server_entry == from) {
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         else
+           continue;
+       }
+
+       /* Remove clients owned by this server */
+       if (remove_clients)
+         silc_server_remove_clients_by_server(server, from, server_entry,
+                                              TRUE);
+
+       /* Remove the server */
+       silc_idlist_del_server(server->local_list, server_entry);
+
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+
+  if (silc_idcache_get_all(server->global_list->servers, &list)) {
+    if (silc_idcache_list_first(list, &id_cache)) {
+      while (id_cache) {
+       server_entry = (SilcServerEntry)id_cache->context;
+       if (SILC_IS_LOCAL(server_entry) || server_entry == server->id_entry ||
+         server_entry->router != from || server_entry == from) {
+         if (!silc_idcache_list_next(list, &id_cache))
+           break;
+         else
+           continue;
+       }
+
+       /* Remove clients owned by this server */
+       if (remove_clients)
+         silc_server_remove_clients_by_server(server, from, server_entry,
+                                              TRUE);
+
+       /* Remove the server */
+       silc_idlist_del_server(server->global_list, server_entry);
+
+       if (!silc_idcache_list_next(list, &id_cache))
+         break;
+      }
+    }
+    silc_idcache_list_free(list);
+  }
+}
+
 /* Removes channels that are from `from. */
 
 void silc_server_remove_channels_by_server(SilcServer server, 
 /* Removes channels that are from `from. */
 
 void silc_server_remove_channels_by_server(SilcServer server, 
index 6d906485d32ddca51f9195181ec4c501734db73f..6831ce31407caf7340f94beace0c73c721489f35 100644 (file)
 #ifndef SERVER_UTIL_H
 #define SERVER_UTIL_H
 
 #ifndef SERVER_UTIL_H
 #define SERVER_UTIL_H
 
-/* This function is used to remove all client entries by the server `entry'.
-   This is called when the connection is lost to the server. In this case
-   we must invalidate all the client entries owned by the server `entry'. 
-   If the `server_signoff' is TRUE then the SERVER_SIGNOFF notify is
+/* This function removes all client entries that are originated from
+   `router' and are owned by `entry'.  `router' and `entry' can be same
+   too.  If `server_signoff' is TRUE then SERVER_SIGNOFF notify is 
    distributed to our local clients. */
    distributed to our local clients. */
-bool silc_server_remove_clients_by_server(SilcServer server, 
+bool silc_server_remove_clients_by_server(SilcServer server,
+                                         SilcServerEntry router,
                                          SilcServerEntry entry,
                                          bool server_signoff);
 
                                          SilcServerEntry entry,
                                          bool server_signoff);
 
@@ -57,6 +57,15 @@ void silc_server_update_servers_by_server(SilcServer server,
 void silc_server_local_servers_toggle_enabled(SilcServer server,
                                              bool toggle_enabled);
 
 void silc_server_local_servers_toggle_enabled(SilcServer server,
                                              bool toggle_enabled);
 
+/* Removes servers that are originated from the `from'.  The server
+   entry is deleted in this function.  If `remove_clients' is TRUE then
+   all clients originated from the server are removed too, and server
+   signoff is sent.  Note that this does not remove the `from'.  This
+   also does not remove locally connected servers. */
+void silc_server_remove_servers_by_server(SilcServer server,
+                                         SilcServerEntry from,
+                                         bool remove_clients);
+
 /* Removes channels that are from `from. */
 void silc_server_remove_channels_by_server(SilcServer server, 
                                           SilcServerEntry from);
 /* Removes channels that are from `from. */
 void silc_server_remove_channels_by_server(SilcServer server, 
                                           SilcServerEntry from);