Fixed KILLED notify handling in normal server.
[silc.git] / apps / silcd / idlist.c
index ab8f7d53af5abb6b9b0773020d25001fb2e4526d..c9599deb2ed21ff1236496e9a8007689dc81a23e 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "serverincludes.h"
 #include "idlist.h"
+#include "server_internal.h"
 
 /******************************************************************************
 
@@ -75,6 +76,14 @@ void silc_idlist_del_data(void *entry)
     silc_hash_free(idata->hash);
   if (idata->public_key)
     silc_pkcs_public_key_free(idata->public_key);
+
+  idata->send_key = NULL;
+  idata->receive_key = NULL;
+  idata->rekey = NULL;
+  idata->hmac_send = NULL;
+  idata->hmac_receive = NULL;
+  idata->hash = NULL;
+  idata->public_key = NULL;
 }
 
 /* Purges ID cache */
@@ -285,13 +294,13 @@ int silc_idlist_del_server(SilcIDList id_list, SilcServerEntry entry)
 
   if (entry) {
     /* Remove from cache */
-    if (entry->id)
-      if (!silc_idcache_del_by_id(id_list->servers, (void *)entry->id))
-       return FALSE;
+    if (!silc_idcache_del_by_context(id_list->servers, entry))
+      return FALSE;
 
     /* Free data */
     silc_free(entry->server_name);
     silc_free(entry->id);
+    silc_free(entry->server_info);
 
     memset(entry, 'F', sizeof(*entry));
     silc_free(entry);
@@ -355,12 +364,12 @@ int silc_idlist_del_client(SilcIDList id_list, SilcClientEntry entry)
 
   if (entry) {
     /* Remove from cache */
-    if (entry->id)
-      if (!silc_idcache_del_by_context(id_list->clients, entry))
-       return FALSE;
+    if (!silc_idcache_del_by_context(id_list->clients, entry))
+      return FALSE;
 
     /* Free data */
     silc_free(entry->nickname);
+    silc_free(entry->servername);
     silc_free(entry->username);
     silc_free(entry->userinfo);
     silc_free(entry->id);
@@ -420,10 +429,13 @@ int silc_idlist_get_clients_by_hash(SilcIDList id_list, char *nickname,
   SilcIDCacheEntry id_cache = NULL;
   unsigned char hash[32];
   SilcClientID client_id;
+  char nick[128 + 1];
 
   SILC_LOG_DEBUG(("Start"));
 
-  silc_hash_make(md5hash, nickname, strlen(nickname), hash);
+  memset(nick, 0, sizeof(nick));
+  silc_to_lower(nickname, nick, sizeof(nick) - 1);
+  silc_hash_make(md5hash, nick, strlen(nick), hash);
 
   /* As the Client ID is hashed in the ID cache by hashing only the hash
      from the Client ID, we can do a lookup with only the hash not the
@@ -493,7 +505,8 @@ silc_idlist_find_client_by_id(SilcIDList id_list, SilcClientID *id,
 /* Replaces old Client ID with new one */
 
 SilcClientEntry
-silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
+silc_idlist_replace_client_id(SilcServer server,
+                             SilcIDList id_list, SilcClientID *old_id,
                              SilcClientID *new_id, const char *nickname)
 {
   SilcIDCacheEntry id_cache = NULL;
@@ -521,11 +534,21 @@ silc_idlist_replace_client_id(SilcIDList id_list, SilcClientID *old_id,
   if (!silc_idcache_del_by_context(id_list->clients, client))
     return NULL;
 
+  /* Check if anyone is watching old nickname */
+  if (server->server_type == SILC_ROUTER)
+    silc_server_check_watcher_list(server, client, nickname,
+                                  SILC_NOTIFY_TYPE_NICK_CHANGE);
+
   silc_free(client->id);
   silc_free(client->nickname);
   client->id = new_id;
   client->nickname = nickname ? strdup(nickname) : NULL;
 
+  /* Check if anyone is watching new nickname */
+  if (server->server_type == SILC_ROUTER)
+    silc_server_check_watcher_list(server, client, nickname,
+                                  SILC_NOTIFY_TYPE_NICK_CHANGE);
+
   if (!silc_idcache_add(id_list->clients, client->nickname, client->id, 
                        client, 0, NULL))
     return NULL;
@@ -550,7 +573,7 @@ void silc_idlist_client_destructor(SilcIDCache cache,
     silc_free(client->id);
     silc_hash_table_free(client->channels);
 
-    memset(client, 'F', sizeof(*client));
+    memset(client, 'A', sizeof(*client));
     silc_free(client);
   }
 }
@@ -572,7 +595,7 @@ silc_idlist_add_channel(SilcIDList id_list, char *channel_name, int mode,
 {
   SilcChannelEntry channel;
 
-  SILC_LOG_DEBUG(("Adding new channel entry"));
+  SILC_LOG_DEBUG(("Adding new channel %s", channel_name));
 
   channel = silc_calloc(1, sizeof(*channel));
   channel->channel_name = channel_name;
@@ -623,13 +646,12 @@ static void silc_idlist_del_channel_foreach(void *key, void *context,
 
 int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
 {
-  SILC_LOG_DEBUG(("Start"));
-
   if (entry) {
+    SILC_LOG_DEBUG(("Deleting channel %s", entry->channel_name));
+
     /* Remove from cache */
-    if (entry->id)
-      if (!silc_idcache_del_by_id(id_list->channels, (void *)entry->id))
-       return FALSE;
+    if (!silc_idcache_del_by_context(id_list->channels, entry))
+      return FALSE;
 
     /* Free all client entrys from the users list. The silc_hash_table_free
        will free all the entries so they are not freed at the foreach 
@@ -653,6 +675,8 @@ int silc_idlist_del_channel(SilcIDList id_list, SilcChannelEntry entry)
       silc_hmac_free(entry->hmac);
     silc_free(entry->hmac_name);
     silc_free(entry->rekey);
+    if (entry->founder_key)
+      silc_pkcs_public_key_free(entry->founder_key);
 
     memset(entry, 'F', sizeof(*entry));
     silc_free(entry);