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 '^'
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.
 
+       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.
index 4abfcfb86ba5a70f822fd47e9c96b9b3fd5e65cc..4e07b0ce40502355bbca0bb2b7f7580e33ee4c71 100644 (file)
@@ -1298,9 +1298,14 @@ void silc_server_notify(SilcServer server,
     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 */
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. */
-  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;
   }
@@ -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. */
-  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;
   }
@@ -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;
 
+  /* 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);
@@ -267,13 +283,6 @@ void silc_server_packet_send_srcdest(SilcServer server,
     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;
index ebb3e811fc4b5f1184ed35882db0b7dd83a8127d..75e84719f20557a732c7d2e7d4737b08e27eac27 100644 (file)
@@ -893,20 +893,15 @@ SILC_TASK_CALLBACK(silc_server_connect_to_router)
   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. */
-    SILC_LOG_DEBUG(("No router(s), server will be standalone"));
+    SILC_LOG_DEBUG(("No router(s), we are standalone"));
     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;
+
+           /* We stop here to take a breath */
+           sleep(2);
          }
 
          if (server->server_type == SILC_BACKUP_ROUTER) {
@@ -3024,24 +3022,38 @@ void silc_server_free_sock_user_data(SilcServer server,
       }
 
       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 {
-       /* 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_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,
@@ -4828,8 +4840,6 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   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));
@@ -4847,6 +4857,8 @@ SILC_TASK_CALLBACK(silc_server_rekey_callback)
   /* 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,
index 19b467844a231eb70c8567abe33d59acaac2909a..5ec8945f68cd439d64c0d21e9fc91eb9c1db021e 100644 (file)
@@ -183,7 +183,7 @@ void silc_server_backup_replaced_add(SilcServer server,
     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));
 
index 75091e945e0e12916a1c545993684463ba95167e..89beb68a2db28d50ef471446d1ad6efb34ccda39 100644 (file)
@@ -39,11 +39,11 @@ silc_server_remove_clients_channels(SilcServer server,
   SilcChannelClientEntry chl, chl2;
   SilcHashTableList htl, htl2;
 
-  SILC_LOG_DEBUG(("Start"));
-
   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);
 
@@ -119,13 +119,13 @@ silc_server_remove_clients_channels(SilcServer server,
   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. */
 
-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)
 {
@@ -143,7 +143,11 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   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
@@ -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_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
@@ -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 (!(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
@@ -290,8 +289,8 @@ bool silc_server_remove_clients_by_server(SilcServer server,
   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) {
@@ -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'. */
-    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
@@ -781,6 +780,79 @@ void silc_server_local_servers_toggle_enabled(SilcServer server,
     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, 
index 6d906485d32ddca51f9195181ec4c501734db73f..6831ce31407caf7340f94beace0c73c721489f35 100644 (file)
 #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. */
-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);
 
@@ -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);
 
+/* 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);