updates.
[silc.git] / apps / silcd / command.c
index 75afbfd92f472408088af380bf379badd5d83149..31283fd0f098a3e64c14749b6f3e12938d9bb05e 100644 (file)
@@ -34,9 +34,9 @@ static void
 silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     SilcCommand command,
                                     SilcCommandStatus status,
-                                    unsigned int arg_type,
+                                    uint32 arg_type,
                                     unsigned char *arg,
-                                    unsigned int arg_len);
+                                    uint32 arg_len);
 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
 
 /* Server command list. */
@@ -62,8 +62,7 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
-  SILC_SERVER_CMD(restart, RESTART, 
-                 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
+  SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(close, CLOSE,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
@@ -72,14 +71,14 @@ SilcServerCommand silc_command_list[] =
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
+  SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
 
   { NULL, 0 },
 };
 
 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max)           \
 do {                                                                         \
-  unsigned int _argc = silc_argument_get_arg_num(cmd->args);                 \
+  uint32 _argc = silc_argument_get_arg_num(cmd->args);               \
                                                                              \
   SILC_LOG_DEBUG(("Start"));                                                 \
                                                                              \
@@ -279,7 +278,7 @@ silc_server_command_dup(SilcServerCommandContext ctx)
 
 void silc_server_command_pending(SilcServer server,
                                 SilcCommand reply_cmd,
-                                unsigned short ident,
+                                uint16 ident,
                                 SilcServerPendingDestructor destructor,
                                 SilcCommandCb callback,
                                 void *context)
@@ -299,7 +298,7 @@ void silc_server_command_pending(SilcServer server,
 
 void silc_server_command_pending_del(SilcServer server,
                                     SilcCommand reply_cmd,
-                                    unsigned short ident)
+                                    uint16 ident)
 {
   SilcServerCommandPending *r;
 
@@ -318,7 +317,7 @@ void silc_server_command_pending_del(SilcServer server,
 int silc_server_command_pending_check(SilcServer server,
                                      SilcServerCommandReplyContext ctx,
                                      SilcCommand command, 
-                                     unsigned short ident)
+                                     uint16 ident)
 {
   SilcServerCommandPending *r;
 
@@ -372,9 +371,9 @@ static void
 silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     SilcCommand command,
                                     SilcCommandStatus status,
-                                    unsigned int arg_type,
+                                    uint32 arg_type,
                                     unsigned char *arg,
-                                    unsigned int arg_len)
+                                    uint32 arg_len)
 {
   SilcBuffer buffer;
 
@@ -399,15 +398,15 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
 static int
 silc_server_command_whois_parse(SilcServerCommandContext cmd,
                                SilcClientID ***client_id,
-                               unsigned int *client_id_count,
+                               uint32 *client_id_count,
                                char **nickname,
                                char **server_name,
                                int *count,
                                SilcCommand command)
 {
   unsigned char *tmp;
-  unsigned int len;
-  unsigned int argc = silc_argument_get_arg_num(cmd->args);
+  uint32 len;
+  uint32 argc = silc_argument_get_arg_num(cmd->args);
   int i, k;
 
   /* If client ID is in the command it must be used instead of nickname */
@@ -479,7 +478,7 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
 static char
 silc_server_command_whois_check(SilcServerCommandContext cmd,
                                SilcClientEntry *clients,
-                               unsigned int clients_count)
+                               uint32 clients_count)
 {
   SilcServer server = cmd->server;
   int i;
@@ -488,12 +487,12 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->data.registered == FALSE)
+    if (!entry || entry->data.registered == FALSE)
       continue;
 
     if (!entry->nickname || !entry->username || !entry->userinfo) {
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       if (!entry->router)
        continue;
@@ -528,7 +527,7 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
 static void
 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
                                     SilcClientEntry *clients,
-                                    unsigned int clients_count,
+                                    uint32 clients_count,
                                     int count)
 {
   SilcServer server = cmd->server;
@@ -537,7 +536,7 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
   SilcBuffer packet, idp, channels;
   SilcClientEntry entry;
   SilcCommandStatus status;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   char nh[128], uh[128];
   unsigned char idle[4], mode[4];
   SilcSocketConnection hsock;
@@ -556,11 +555,18 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
 
     if (entry->data.registered == FALSE) {
       if (clients_count == 1) {
-       SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
-       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
-                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
-                                            2, idp->data, idp->len);
-       silc_buffer_free(idp);
+       if (entry->nickname) {
+         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                              SILC_STATUS_ERR_NO_SUCH_NICK,
+                                              3, entry->nickname, 
+                                              strlen(entry->nickname));
+       } else {
+         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
+         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                    SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                              2, idp->data, idp->len);
+         silc_buffer_free(idp);
+       }
       }
       continue;
     }
@@ -593,10 +599,14 @@ silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
     strncat(nh, entry->nickname, strlen(entry->nickname));
     if (!strchr(entry->nickname, '@')) {
       strncat(nh, "@", 1);
-      len = entry->router ? strlen(entry->router->server_name) :
-       strlen(server->server_name);
-      strncat(nh, entry->router ? entry->router->server_name :
-             server->server_name, len);
+      if (entry->servername) {
+       strncat(nh, entry->servername, strlen(entry->servername));
+      } else {
+       len = entry->router ? strlen(entry->router->server_name) :
+         strlen(server->server_name);
+       strncat(nh, entry->router ? entry->router->server_name :
+               server->server_name, len);
+      }
     }
       
     strncat(uh, entry->username, strlen(entry->username));
@@ -655,10 +665,10 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0;
+  int count = 0;
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
-  unsigned int client_id_count = 0;
+  uint32 client_id_count = 0, clients_count = 0;
   int i, ret = 0;
 
   /* Protocol dictates that we must always send the received WHOIS request
@@ -668,7 +678,7 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   if (server->server_type == SILC_SERVER && !cmd->pending && 
       !server->standalone) {
     SilcBuffer tmpbuf;
-    unsigned short old_ident;
+    uint16 old_ident;
 
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -717,37 +727,33 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* Check global list as well */
-  if (!clients) {
-    if (client_id_count) {
-      /* Check all Client ID's received in the command packet */
-      for (i = 0; i < client_id_count; i++) {
-       entry = silc_idlist_find_client_by_id(server->global_list, 
-                                             client_id[i], NULL);
-       if (entry) {
-         clients = silc_realloc(clients, sizeof(*clients) * 
-                                (clients_count + 1));
-         clients[clients_count++] = entry;
-       }
+  if (client_id_count) {
+    /* Check all Client ID's received in the command packet */
+    for (i = 0; i < client_id_count; i++) {
+      entry = silc_idlist_find_client_by_id(server->global_list, 
+                                           client_id[i], NULL);
+      if (entry) {
+       clients = silc_realloc(clients, sizeof(*clients) * 
+                              (clients_count + 1));
+       clients[clients_count++] = entry;
       }
-    } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
     }
+  } else {
+    if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->global_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   if (!clients) {
@@ -801,10 +807,10 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0;
+  int count = 0;
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
-  unsigned int client_id_count = 0;
+  uint32 client_id_count = 0, clients_count = 0;
   int i, ret = 0;
 
   /* Parse the whois request */
@@ -828,17 +834,16 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
+  if (server->server_type == SILC_ROUTER) {
     if (client_id_count) {
       /* Check all Client ID's received in the command packet */
       for (i = 0; i < client_id_count; i++) {
@@ -851,13 +856,12 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
+      if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                          nick, server->md5hash,
+                                          &clients, &clients_count))
+       silc_idlist_get_clients_by_nickname(server->global_list, 
+                                           nick, server_name,
+                                           &clients, &clients_count);
     }
   }
 
@@ -940,7 +944,7 @@ silc_server_command_whowas_parse(SilcServerCommandContext cmd,
                                 int *count)
 {
   unsigned char *tmp;
-  unsigned int len;
+  uint32 len;
 
   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
   if (!tmp) {
@@ -972,7 +976,7 @@ silc_server_command_whowas_parse(SilcServerCommandContext cmd,
 static char
 silc_server_command_whowas_check(SilcServerCommandContext cmd,
                                 SilcClientEntry *clients,
-                                unsigned int clients_count)
+                                uint32 clients_count)
 {
   SilcServer server = cmd->server;
   int i;
@@ -983,7 +987,7 @@ silc_server_command_whowas_check(SilcServerCommandContext cmd,
 
     if (!entry->nickname || !entry->username) {
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       if (!entry->router)
        continue;
@@ -1018,7 +1022,7 @@ silc_server_command_whowas_check(SilcServerCommandContext cmd,
 static void
 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
                                      SilcClientEntry *clients,
-                                     unsigned int clients_count)
+                                     uint32 clients_count)
 {
   SilcServer server = cmd->server;
   char *tmp;
@@ -1026,7 +1030,7 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
   SilcBuffer packet, idp;
   SilcClientEntry entry = NULL;
   SilcCommandStatus status;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   char found = FALSE;
   char nh[256], uh[256];
 
@@ -1071,10 +1075,14 @@ silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
     strncat(nh, entry->nickname, strlen(entry->nickname));
     if (!strchr(entry->nickname, '@')) {
       strncat(nh, "@", 1);
-      len = entry->router ? strlen(entry->router->server_name) :
-       strlen(server->server_name);
-      strncat(nh, entry->router ? entry->router->server_name :
-             server->server_name, len);
+      if (entry->servername) {
+       strncat(nh, entry->servername, strlen(entry->servername));
+      } else {
+       len = entry->router ? strlen(entry->router->server_name) :
+         strlen(server->server_name);
+       strncat(nh, entry->router ? entry->router->server_name :
+               server->server_name, len);
+      }
     }
       
     strncat(uh, entry->username, strlen(entry->username));
@@ -1119,8 +1127,9 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0;
+  int count = 0;
   SilcClientEntry *clients = NULL;
+  uint32 clients_count = 0;
   int ret = 0;
 
   /* Protocol dictates that we must always send the received WHOWAS request
@@ -1130,7 +1139,7 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
   if (server->server_type == SILC_SERVER && 
       !cmd->pending && !server->standalone) {
     SilcBuffer tmpbuf;
-    unsigned short old_ident;
+    uint16 old_ident;
 
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -1165,24 +1174,20 @@ silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
     return 0;
 
   /* Get all clients matching that nickname from local list */
-  clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                               nick, server_name,
-                                               &clients_count);
-  if (!clients)
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
+  if (!silc_idlist_get_clients_by_nickname(server->local_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->local_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   /* Check global list as well */
-  if (!clients) {
-    clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-  }
+  if (!silc_idlist_get_clients_by_nickname(server->global_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->global_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
     ret = -1;
@@ -1208,8 +1213,9 @@ silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0;
+  int count = 0;
   SilcClientEntry *clients = NULL;
+  uint32 clients_count = 0;
   int ret = 0;
 
   /* Parse the whowas request */
@@ -1219,23 +1225,21 @@ silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
 
-  clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                               nick, server_name,
-                                               &clients_count);
-  if (!clients)
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
+  if (!silc_idlist_get_clients_by_nickname(server->local_list, 
+                                          nick, server_name,
+                                          &clients, &clients_count))
+    silc_idlist_get_clients_by_hash(server->local_list, 
+                                   nick, server->md5hash,
+                                   &clients, &clients_count);
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
-    clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                 nick, server_name,
-                                                 &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
+  if (server->server_type == SILC_ROUTER) {
+    if (!silc_idlist_get_clients_by_nickname(server->global_list, 
+                                            nick, server_name,
+                                            &clients, &clients_count))
+      silc_idlist_get_clients_by_hash(server->global_list, 
+                                     nick, server->md5hash,
+                                     &clients, &clients_count);
   }
 
   if (!clients) {
@@ -1292,7 +1296,7 @@ SILC_SERVER_CMD_FUNC(whowas)
 static char
 silc_server_command_identify_check(SilcServerCommandContext cmd,
                                   SilcClientEntry *clients,
-                                  unsigned int clients_count)
+                                  uint32 clients_count)
 {
   SilcServer server = cmd->server;
   int i;
@@ -1301,12 +1305,12 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
   for (i = 0; i < clients_count; i++) {
     entry = clients[i];
 
-    if (entry->data.registered == FALSE)
+    if (!entry || entry->data.registered == FALSE)
       continue;
 
     if (!entry->nickname) {
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
       
       if (!entry->router)
        continue;
@@ -1346,7 +1350,7 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
 static void
 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
                                        SilcClientEntry *clients,
-                                       unsigned int clients_count,
+                                       uint32 clients_count,
                                        int count)
 {
   SilcServer server = cmd->server;
@@ -1355,7 +1359,7 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
   SilcBuffer packet, idp;
   SilcClientEntry entry;
   SilcCommandStatus status;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   char nh[256], uh[256];
   SilcSocketConnection hsock;
 
@@ -1404,10 +1408,14 @@ silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
     strncat(nh, entry->nickname, strlen(entry->nickname));
     if (!strchr(entry->nickname, '@')) {
       strncat(nh, "@", 1);
-      len = entry->router ? strlen(entry->router->server_name) :
-       strlen(server->server_name);
-      strncat(nh, entry->router ? entry->router->server_name :
-             server->server_name, len);
+      if (entry->servername) {
+       strncat(nh, entry->servername, strlen(entry->servername));
+      } else {
+       len = entry->router ? strlen(entry->router->server_name) :
+         strlen(server->server_name);
+       strncat(nh, entry->router ? entry->router->server_name :
+               server->server_name, len);
+      }
     }
       
     if (!entry->username) {
@@ -1446,10 +1454,10 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0; 
+  int count = 0;
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
-  unsigned int client_id_count = 0;
+  uint32 client_id_count = 0, clients_count = 0;
   int i, ret = 0;
 
   /* Protocol dictates that we must always send the received IDENTIFY request
@@ -1459,7 +1467,7 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   if (server->server_type == SILC_SERVER && 
       !cmd->pending && !server->standalone) {
     SilcBuffer tmpbuf;
-    unsigned short old_ident;
+    uint16 old_ident;
 
     old_ident = silc_command_get_ident(cmd->payload);
     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -1508,37 +1516,33 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* Check global list as well */
-  if (!clients) {
-    if (client_id_count) {
-      /* Check all Client ID's received in the command packet */
-      for (i = 0; i < client_id_count; i++) {
-       entry = silc_idlist_find_client_by_id(server->global_list, 
-                                             client_id[i], NULL);
-       if (entry) {
-         clients = silc_realloc(clients, sizeof(*clients) * 
-                                (clients_count + 1));
-         clients[clients_count++] = entry;
-       }
+  if (client_id_count) {
+    /* Check all Client ID's received in the command packet */
+    for (i = 0; i < client_id_count; i++) {
+      entry = silc_idlist_find_client_by_id(server->global_list, 
+                                           client_id[i], NULL);
+      if (entry) {
+       clients = silc_realloc(clients, sizeof(*clients) * 
+                              (clients_count + 1));
+       clients[clients_count++] = entry;
       }
-    } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
     }
+  } else {
+    if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->global_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   if (!clients) {
@@ -1589,10 +1593,10 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count = 0;
+  int count = 0;
   SilcClientEntry *clients = NULL, entry;
   SilcClientID **client_id = NULL;
-  unsigned int client_id_count = 0;
+  uint32 client_id_count = 0, clients_count = 0;
   int i, ret = 0;
 
   /* Parse the IDENTIFY request */
@@ -1616,17 +1620,16 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
       }
     }
   } else {
-    clients = silc_idlist_get_clients_by_hash(server->local_list, 
-                                             nick, server->md5hash,
-                                             &clients_count);
-    if (!clients)
-      clients = silc_idlist_get_clients_by_nickname(server->local_list, 
-                                                   nick, server_name,
-                                                   &clients_count);
+    if (!silc_idlist_get_clients_by_hash(server->local_list, 
+                                        nick, server->md5hash,
+                                        &clients, &clients_count))
+      silc_idlist_get_clients_by_nickname(server->local_list, 
+                                         nick, server_name,
+                                         &clients, &clients_count);
   }
   
   /* If we are router we will check our global list as well. */
-  if (!clients && server->server_type == SILC_ROUTER) {
+  if (server->server_type == SILC_ROUTER) {
     if (client_id_count) {
       /* Check all Client ID's received in the command packet */
       for (i = 0; i < client_id_count; i++) {
@@ -1639,13 +1642,12 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
        }
       }
     } else {
-      clients = silc_idlist_get_clients_by_hash(server->global_list, 
-                                               nick, server->md5hash,
-                                               &clients_count);
-      if (!clients)
-       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
-                                                     nick, server_name,
-                                                     &clients_count);
+      if (!silc_idlist_get_clients_by_hash(server->global_list, 
+                                          nick, server->md5hash,
+                                          &clients, &clients_count))
+       silc_idlist_get_clients_by_nickname(server->global_list, 
+                                           nick, server_name,
+                                           &clients, &clients_count);
     }
   }
 
@@ -1736,7 +1738,7 @@ SILC_SERVER_CMD_FUNC(nick)
   SilcBuffer packet, nidp, oidp;
   SilcClientID *new_id;
   char *nick;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
@@ -1766,19 +1768,16 @@ SILC_SERVER_CMD_FUNC(nick)
     silc_server_send_notify_nick_change(server, server->router->connection, 
                                        server->server_type == SILC_SERVER ? 
                                        FALSE : TRUE, client->id,
-                                       new_id, SILC_ID_CLIENT_LEN);
+                                       new_id);
 
   /* Remove old cache entry */
-  silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
-                        client->id); 
+  silc_idcache_del_by_context(server->local_list->clients, client);
 
   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
   /* Free old ID */
-  if (client->id) {
-    memset(client->id, 0, SILC_ID_CLIENT_LEN);
+  if (client->id)
     silc_free(client->id);
-  }
 
   /* Save the nickname as this client is our local client */
   if (client->nickname)
@@ -1789,8 +1788,7 @@ SILC_SERVER_CMD_FUNC(nick)
 
   /* Update client cache */
   silc_idcache_add(server->local_list->clients, client->nickname, 
-                  strlen(client->nickname), SILC_ID_CLIENT, client->id, 
-                  (void *)client, TRUE, FALSE);
+                  client->id, (void *)client, FALSE);
 
   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
@@ -1820,18 +1818,18 @@ SILC_SERVER_CMD_FUNC(nick)
 static void
 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
                                    SilcChannelEntry *lch, 
-                                   unsigned int lch_count,
+                                   uint32 lch_count,
                                    SilcChannelEntry *gch,
-                                   unsigned int gch_count)
+                                   uint32 gch_count)
 {
   int i;
   SilcBuffer packet, idp;
   SilcChannelEntry entry;
   SilcCommandStatus status;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   char *topic;
   unsigned char usercount[4];
-  unsigned int users;
+  uint32 users;
 
   for (i = 0; i < lch_count; i++)
     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
@@ -1956,9 +1954,9 @@ SILC_SERVER_CMD_FUNC(list)
   SilcServer server = cmd->server;
   SilcChannelID *channel_id = NULL;
   unsigned char *tmp;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
-  unsigned int lch_count = 0, gch_count = 0;
+  uint32 lch_count = 0, gch_count = 0;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
 
@@ -2003,8 +2001,8 @@ SILC_SERVER_CMD_FUNC(topic)
   SilcChannelClientEntry chl;
   SilcBuffer packet, idp;
   unsigned char *tmp;
-  unsigned int argc, tmp_len;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 argc, tmp_len;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
 
@@ -2076,7 +2074,7 @@ SILC_SERVER_CMD_FUNC(topic)
       silc_server_send_notify_topic_set(server, server->router->connection,
                                        server->server_type == SILC_ROUTER ?
                                        TRUE : FALSE, channel, client->id,
-                                       SILC_ID_CLIENT_LEN, channel->topic);
+                                       channel->topic);
 
     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
@@ -2127,8 +2125,8 @@ SILC_SERVER_CMD_FUNC(invite)
   SilcIDListData idata;
   SilcBuffer idp, idp2, packet;
   unsigned char *tmp, *add, *del;
-  unsigned int len;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 len;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
 
@@ -2307,8 +2305,7 @@ SILC_SERVER_CMD_FUNC(invite)
     silc_server_send_notify_invite(server, server->router->connection,
                                   server->server_type == SILC_ROUTER ?
                                   TRUE : FALSE, channel,
-                                  sender->id, SILC_ID_CLIENT_LEN,
-                                  add, del);
+                                  sender->id, add, del);
 
   /* Send command reply */
   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
@@ -2366,7 +2363,7 @@ SILC_SERVER_CMD_FUNC(quit)
   SilcSocketConnection sock = cmd->sock;
   QuitInternal q;
   unsigned char *tmp = NULL;
-  unsigned int len = 0;
+  uint32 len = 0;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
 
@@ -2403,7 +2400,7 @@ SILC_SERVER_CMD_FUNC(kill)
   SilcClientEntry remote_client;
   SilcClientID *client_id;
   unsigned char *tmp, *comment;
-  unsigned int tmp_len, tmp_len2;
+  uint32 tmp_len, tmp_len2;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
 
@@ -2476,15 +2473,13 @@ SILC_SERVER_CMD_FUNC(kill)
   /* Send KILLED notify to primary route */
   if (!server->standalone)
     silc_server_send_notify_killed(server, server->router->connection, TRUE,
-                                  remote_client->id, SILC_ID_CLIENT_LEN,
-                                  comment);
+                                  remote_client->id, comment);
 
   /* Send KILLED notify to the client directly */
   silc_server_send_notify_killed(server, remote_client->connection ? 
                                 remote_client->connection : 
                                 remote_client->router->connection, FALSE,
-                                remote_client->id, SILC_ID_CLIENT_LEN,
-                                comment);
+                                remote_client->id, comment);
 
   /* Remove the client from all channels. This generates new keys to the
      channels as well. */
@@ -2518,9 +2513,9 @@ SILC_SERVER_CMD_FUNC(info)
   SilcServer server = cmd->server;
   SilcBuffer packet, idp;
   unsigned char *tmp;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   char *dest_server, *server_info = NULL, *server_name;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   SilcServerEntry entry = NULL;
   SilcServerID *server_id = NULL;
 
@@ -2586,7 +2581,7 @@ SILC_SERVER_CMD_FUNC(info)
        server->server_type == SILC_ROUTER && entry && !entry->server_info) {
       /* Send to the server */
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -2611,7 +2606,7 @@ SILC_SERVER_CMD_FUNC(info)
     if (!entry && !cmd->pending && !server->standalone) {
       /* Send to the primary router */
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -2673,7 +2668,7 @@ SILC_SERVER_CMD_FUNC(ping)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
   SilcServerID *id;
-  unsigned int len;
+  uint32 len;
   unsigned char *tmp;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
@@ -2689,7 +2684,7 @@ SILC_SERVER_CMD_FUNC(ping)
   if (!id)
     goto out;
 
-  if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
+  if (SILC_ID_SERVER_COMPARE(id, server->id)) {
     /* Send our reply */
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
                                          SILC_STATUS_OK);
@@ -2714,16 +2709,16 @@ static void silc_server_command_join_channel(SilcServer server,
                                             SilcChannelEntry channel,
                                             SilcClientID *client_id,
                                             int created,
-                                            unsigned int umode)
+                                            uint32 umode)
 {
   SilcSocketConnection sock = cmd->sock;
   unsigned char *tmp;
-  unsigned int tmp_len, user_count;
+  uint32 tmp_len, user_count;
   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
   SilcClientEntry client;
   SilcChannelClientEntry chl;
   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
   char check[512];
 
   SILC_LOG_DEBUG(("Start"));
@@ -2911,8 +2906,7 @@ static void silc_server_command_join_channel(SilcServer server,
     if (!server->standalone)
       silc_server_send_notify_join(server, server->router->connection,
                                   server->server_type == SILC_ROUTER ?
-                                  TRUE : FALSE, channel, client->id,
-                                  SILC_ID_CLIENT_LEN);
+                                  TRUE : FALSE, channel, client->id);
   }
 
   silc_buffer_free(reply);
@@ -2934,10 +2928,10 @@ SILC_SERVER_CMD_FUNC(join)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  int tmp_len;
+  uint32 tmp_len;
   char *tmp, *channel_name = NULL, *cipher, *hmac;
   SilcChannelEntry channel;
-  unsigned int umode = 0;
+  uint32 umode = 0;
   int created = FALSE;
   SilcClientID *client_id;
 
@@ -2989,7 +2983,7 @@ SILC_SERVER_CMD_FUNC(join)
        be same as the client's ID. */
     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
-      if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
+      if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
        silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
                                        SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
        goto out;
@@ -3021,7 +3015,7 @@ SILC_SERVER_CMD_FUNC(join)
           or joins the client to it). */
        if (server->server_type == SILC_SERVER) {
          SilcBuffer tmpbuf;
-         unsigned short old_ident;
+         uint16 old_ident;
          
          old_ident = silc_command_get_ident(cmd->payload);
          silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -3120,8 +3114,8 @@ SILC_SERVER_CMD_FUNC(motd)
   SilcServer server = cmd->server;
   SilcBuffer packet, idp;
   char *motd, *dest_server;
-  int motd_len;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 motd_len;
+  uint16 ident = silc_command_get_ident(cmd->payload);
   
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
 
@@ -3177,7 +3171,7 @@ SILC_SERVER_CMD_FUNC(motd)
        entry && !entry->motd) {
       /* Send to the server */
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -3202,7 +3196,7 @@ SILC_SERVER_CMD_FUNC(motd)
     if (!entry && !cmd->pending && !server->standalone) {
       /* Send to the primary router */
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -3264,8 +3258,8 @@ SILC_SERVER_CMD_FUNC(umode)
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   SilcBuffer packet;
   unsigned char *tmp_mask;
-  unsigned int mask;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 mask;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
@@ -3322,8 +3316,7 @@ SILC_SERVER_CMD_FUNC(umode)
   /* Send UMODE change to primary router */
   if (!server->standalone)
     silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                 client->id, SILC_ID_CLIENT_LEN,
-                                 client->mode);
+                                 client->id, client->mode);
 
   /* Send command reply to sender */
   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
@@ -3342,7 +3335,7 @@ SILC_SERVER_CMD_FUNC(umode)
 
 int silc_server_check_cmode_rights(SilcChannelEntry channel,
                                   SilcChannelClientEntry client,
-                                  unsigned int mode)
+                                  uint32 mode)
 {
   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
@@ -3416,8 +3409,8 @@ SILC_SERVER_CMD_FUNC(cmode)
   SilcBuffer packet, cidp;
   unsigned char *tmp, *tmp_id, *tmp_mask;
   char *cipher = NULL, *hmac = NULL;
-  unsigned int mode_mask, tmp_len, tmp_len2;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 mode_mask, tmp_len, tmp_len2;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
 
@@ -3508,7 +3501,7 @@ SILC_SERVER_CMD_FUNC(cmode)
   
   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
     /* User limit is set on channel */
-    unsigned int user_limit;
+    uint32 user_limit;
       
     /* Get user limit */
     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
@@ -3732,7 +3725,6 @@ SILC_SERVER_CMD_FUNC(cmode)
                                  server->server_type == SILC_ROUTER ? 
                                  TRUE : FALSE, channel,
                                  mode_mask, client->id, SILC_ID_CLIENT,
-                                 SILC_ID_CLIENT_LEN,
                                  cipher, hmac);
 
   /* Send command reply to sender */
@@ -3765,9 +3757,9 @@ SILC_SERVER_CMD_FUNC(cumode)
   SilcChannelClientEntry chl;
   SilcBuffer packet, idp;
   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
-  unsigned int target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
+  uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
   int notify = FALSE;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
 
@@ -3883,7 +3875,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
     /* The client tries to claim the founder rights. */
     unsigned char *tmp_auth;
-    unsigned int tmp_auth_len, auth_len;
+    uint32 tmp_auth_len, auth_len;
     void *auth;
     
     if (target_client != client) {
@@ -3980,9 +3972,8 @@ SILC_SERVER_CMD_FUNC(cumode)
                                     server->server_type == SILC_ROUTER ? 
                                     TRUE : FALSE, channel,
                                     target_mask, client->id, 
-                                    SILC_ID_CLIENT_LEN,
-                                    target_client->id, 
-                                    SILC_ID_CLIENT_LEN);
+                                    SILC_ID_CLIENT,
+                                    target_client->id);
   }
 
   /* Send command reply to sender */
@@ -4015,7 +4006,7 @@ SILC_SERVER_CMD_FUNC(kick)
   SilcChannelEntry channel;
   SilcChannelClientEntry chl;
   SilcBuffer idp;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   unsigned char *tmp, *comment;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
@@ -4141,8 +4132,7 @@ SILC_SERVER_CMD_FUNC(kick)
     silc_server_send_notify_kicked(server, server->router->connection,
                                   server->server_type == SILC_ROUTER ?
                                   TRUE : FALSE, channel,
-                                  target_client->id, SILC_ID_CLIENT_LEN,
-                                  comment);
+                                  target_client->id, comment);
 
   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
     /* Re-generate channel key */
@@ -4168,7 +4158,7 @@ SILC_SERVER_CMD_FUNC(oper)
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   unsigned char *username, *auth;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   SilcServerConfigSectionAdminConnection *admin;
   SilcIDListData idata = (SilcIDListData)client;
 
@@ -4221,8 +4211,7 @@ SILC_SERVER_CMD_FUNC(oper)
   /* Send UMODE change to primary router */
   if (!server->standalone)
     silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                 client->id, SILC_ID_CLIENT_LEN,
-                                 client->mode);
+                                 client->id, client->mode);
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
@@ -4241,7 +4230,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   unsigned char *username, *auth;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   SilcServerConfigSectionAdminConnection *admin;
   SilcIDListData idata = (SilcIDListData)client;
 
@@ -4297,8 +4286,7 @@ SILC_SERVER_CMD_FUNC(silcoper)
   /* Send UMODE change to primary router */
   if (!server->standalone)
     silc_server_send_notify_umode(server, server->router->connection, TRUE,
-                                 client->id, SILC_ID_CLIENT_LEN,
-                                 client->mode);
+                                 client->id, client->mode);
 
   /* Send reply to the sender */
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
@@ -4317,8 +4305,8 @@ SILC_SERVER_CMD_FUNC(connect)
   SilcServer server = cmd->server;
   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   unsigned char *tmp, *host;
-  unsigned int tmp_len;
-  unsigned int port = SILC_PORT;
+  uint32 tmp_len;
+  uint32 port = SILC_PORT;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
 
@@ -4363,10 +4351,139 @@ SILC_SERVER_CMD_FUNC(connect)
   silc_server_command_free(cmd);
 }
 
-SILC_SERVER_CMD_FUNC(restart)
+/* Server side of command BAN. This is used to manage the ban list of the
+   channel. To add clients and remove clients from the ban list. */
+
+SILC_SERVER_CMD_FUNC(ban)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
+  SilcBuffer packet;
+  SilcChannelEntry channel;
+  SilcChannelClientEntry chl;
+  SilcChannelID *channel_id = NULL;
+  unsigned char *id, *add, *del;
+  uint32 id_len, tmp_len;
+  uint16 ident = silc_command_get_ident(cmd->payload);
+
+  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+    goto out;
+
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
+
+  /* Get Channel ID */
+  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
+  if (id) {
+    channel_id = silc_id_payload_parse_id(id, id_len);
+    if (!channel_id) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
+      goto out;
+    }
+  }
+
+  /* Get channel entry. The server must know about the channel since the
+     client is expected to be on the channel. */
+  channel = silc_idlist_find_channel_by_id(server->local_list, 
+                                          channel_id, NULL);
+  if (!channel) {
+    channel = silc_idlist_find_channel_by_id(server->global_list, 
+                                            channel_id, NULL);
+    if (!channel) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+      goto out;
+    }
+  }
+
+  /* Check whether this client is on the channel */
+  if (!silc_server_client_on_channel(client, channel)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
+    goto out;
+  }
+
+  /* Get entry to the channel user list */
+  silc_list_start(channel->user_list);
+  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
+    if (chl->client == client)
+      break;
+
+  /* The client must be at least channel operator. */
+  if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
+                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
+    goto out;
+  }
+
+  /* Get the new ban and add it to the ban list */
+  add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
+  if (add) {
+    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));
+    if (add[tmp_len - 1] == ',')
+      add[tmp_len - 1] = '\0';
+
+    strncat(channel->ban_list, add, tmp_len);
+    strncat(channel->ban_list, ",", 1);
+  }
+
+  /* Get the ban to be removed and remove it from the list */
+  del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
+  if (del && channel->ban_list) {
+    char *start, *end, *n;
 
+    if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
+      silc_free(channel->ban_list);
+      channel->ban_list = NULL;
+    } else {
+      start = strstr(channel->ban_list, del);
+      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;
+      }
+    }
+  }
+
+  /* Send the BAN notify type to our primary router. */
+  if (!server->standalone && (add || del))
+    silc_server_send_notify_ban(server, server->router->connection,
+                               server->server_type == SILC_ROUTER ?
+                               TRUE : FALSE, channel, add, del);
+
+  /* Send the reply back to the client */
+  if (channel->ban_list)
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 2,
+                                          2, id, id_len,
+                                          3, channel->ban_list, 
+                                          strlen(channel->ban_list) - 1);
+  else
+    packet = 
+      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
+                                          SILC_STATUS_OK, ident, 1,
+                                          2, id, id_len);
+
+  silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
+                         packet->data, packet->len, FALSE);
+    
+  silc_buffer_free(packet);
+
+ out:
+  if (channel_id)
+    silc_free(channel_id);
   silc_server_command_free(cmd);
 }
 
@@ -4380,9 +4497,9 @@ SILC_SERVER_CMD_FUNC(close)
   SilcServerEntry server_entry;
   SilcSocketConnection sock;
   unsigned char *tmp;
-  unsigned int tmp_len;
+  uint32 tmp_len;
   unsigned char *name;
-  unsigned int port = SILC_PORT;
+  uint32 port = SILC_PORT;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
 
@@ -4471,9 +4588,9 @@ SILC_SERVER_CMD_FUNC(leave)
   SilcServer server = cmd->server;
   SilcSocketConnection sock = cmd->sock;
   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
-  SilcChannelID *id;
+  SilcChannelID *id = NULL;
   SilcChannelEntry channel;
-  unsigned int len;
+  uint32 len;
   unsigned char *tmp;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
@@ -4515,8 +4632,7 @@ SILC_SERVER_CMD_FUNC(leave)
   if (!server->standalone)
     silc_server_send_notify_leave(server, server->router->connection,
                                  server->server_type == SILC_ROUTER ?
-                                 TRUE : FALSE, channel, id_entry->id,
-                                 SILC_ID_CLIENT_LEN);
+                                 TRUE : FALSE, channel, id_entry->id);
 
   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
                                        SILC_STATUS_OK);
@@ -4537,9 +4653,9 @@ SILC_SERVER_CMD_FUNC(leave)
                                 FALSE : !server->standalone);
   }
 
-  silc_free(id);
-
  out:
+  if (id)
+    silc_free(id);
   silc_server_command_free(cmd);
 }
 
@@ -4555,12 +4671,12 @@ SILC_SERVER_CMD_FUNC(users)
   SilcChannelID *id;
   SilcBuffer packet;
   unsigned char *channel_id;
-  unsigned int channel_id_len;
+  uint32 channel_id_len;
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
   unsigned char lc[4];
-  unsigned int list_count = 0;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  uint32 list_count = 0;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
 
@@ -4647,138 +4763,166 @@ SILC_SERVER_CMD_FUNC(users)
   silc_server_command_free(cmd);
 }
 
-/* Server side of command BAN. This is used to manage the ban list of the
-   channel. To add clients and remove clients from the ban list. */
+/* Server side of command GETKEY. This fetches the client's public key
+   from the server where to the client is connected. */
 
-SILC_SERVER_CMD_FUNC(ban)
+SILC_SERVER_CMD_FUNC(getkey)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
-  SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
   SilcBuffer packet;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
-  SilcChannelID *channel_id = NULL;
-  unsigned char *id, *add, *del;
-  unsigned int id_len, tmp_len;
-  unsigned short ident = silc_command_get_ident(cmd->payload);
+  SilcClientEntry client;
+  SilcServerEntry server_entry;
+  SilcClientID *client_id = NULL;
+  SilcServerID *server_id = NULL;
+  SilcIDPayload idp = NULL;
+  uint16 ident = silc_command_get_ident(cmd->payload);
+  unsigned char *tmp;
+  uint32 tmp_len;
+  SilcBuffer pk;
+  SilcIdType id_type;
 
-  if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  if (!tmp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
-
-  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
-
-  /* Get Channel ID */
-  id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
-  if (id) {
-    channel_id = silc_id_payload_parse_id(id, id_len);
-    if (!channel_id) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
-      goto out;
-    }
-  }
-
-  /* Get channel entry. The server must know about the channel since the
-     client is expected to be on the channel. */
-  channel = silc_idlist_find_channel_by_id(server->local_list, 
-                                          channel_id, NULL);
-  if (!channel) {
-    channel = silc_idlist_find_channel_by_id(server->global_list, 
-                                            channel_id, NULL);
-    if (!channel) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
-      goto out;
-    }
   }
-
-  /* Check whether this client is on the channel */
-  if (!silc_server_client_on_channel(client, channel)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                         SILC_STATUS_ERR_NOT_ON_CHANNEL);
+  idp = silc_id_payload_parse_data(tmp, tmp_len);
+  if (!idp) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
     goto out;
   }
 
-  /* Get entry to the channel user list */
-  silc_list_start(channel->user_list);
-  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
-    if (chl->client == client)
-      break;
+  id_type = silc_id_payload_get_type(idp);
+  if (id_type == SILC_ID_CLIENT) {
+    client_id = silc_id_payload_get_id(idp);
 
-  /* The client must be at least channel operator. */
-  if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
-                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
-    goto out;
-  }
+    /* If the client is not found from local list there is no chance it
+       would be locally connected client so send the command further. */
+    client = silc_idlist_find_client_by_id(server->local_list, 
+                                          client_id, NULL);
+    
+    if ((!client && !cmd->pending && !server->standalone) ||
+       (client && !client->connection)) {
+      SilcBuffer tmpbuf;
+      uint16 old_ident;
+      SilcSocketConnection dest_sock;
+      
+      dest_sock = silc_server_get_client_route(server, NULL, 0, 
+                                              client_id, NULL);
+      if (!dest_sock)
+       goto out;
+      
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+      
+      silc_server_packet_send(server, dest_sock,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+      
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_getkey,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
+    }
 
-  /* Get the new ban and add it to the ban list */
-  add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
-  if (add) {
-    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));
-    if (add[tmp_len - 1] == ',')
-      add[tmp_len - 1] = '\0';
+    if (!client && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+      goto out;
+    }
 
-    strncat(channel->ban_list, add, tmp_len);
-    strncat(channel->ban_list, ",", 1);
-  }
+    /* The client is locally connected, just get the public key and
+       send it back. */
+    tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
+    pk = silc_buffer_alloc(4 + tmp_len);
+    silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+    silc_buffer_format(pk,
+                      SILC_STR_UI_SHORT(tmp_len),
+                      SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+                      SILC_STR_UI_XNSTRING(tmp, tmp_len),
+                      SILC_STR_END);
+    silc_free(tmp);
 
-  /* Get the ban to be removed and remove it from the list */
-  del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
-  if (del && channel->ban_list) {
-    char *start, *end, *n;
+  } else if (id_type == SILC_ID_SERVER) {
+    server_id = silc_id_payload_get_id(idp);
 
-    if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
-      silc_free(channel->ban_list);
-      channel->ban_list = NULL;
-    } else {
-      start = strstr(channel->ban_list, del);
-      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;
-      }
+    /* If the server is not found from local list there is no chance it
+       would be locally connected server so send the command further. */
+    server_entry = silc_idlist_find_server_by_id(server->local_list, 
+                                                server_id, NULL);
+    
+    if ((!server_entry && !cmd->pending && !server->standalone) ||
+       (server_entry && !server_entry->connection)) {
+      SilcBuffer tmpbuf;
+      uint16 old_ident;
+      
+      old_ident = silc_command_get_ident(cmd->payload);
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+      
+      silc_server_packet_send(server, server->router->connection,
+                             SILC_PACKET_COMMAND, cmd->packet->flags,
+                             tmpbuf->data, tmpbuf->len, TRUE);
+      
+      /* Reprocess this packet after received reply from router */
+      silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_destructor,
+                                 silc_server_command_getkey,
+                                 silc_server_command_dup(cmd));
+      cmd->pending = TRUE;
+      
+      silc_command_set_ident(cmd->payload, old_ident);
+      silc_buffer_free(tmpbuf);
+      return;
     }
-  }
 
-  /* Send the BAN notify type to our primary router. */
-  if (!server->standalone && (add || del))
-    silc_server_send_notify_ban(server, server->router->connection,
-                               server->server_type == SILC_ROUTER ?
-                               TRUE : FALSE, channel, add, del);
+    if (!server_entry && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
+      goto out;
+    }
 
-  /* Send the reply back to the client */
-  if (channel->ban_list)
-    packet = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
-                                          SILC_STATUS_OK, ident, 2,
-                                          2, id, id_len,
-                                          3, channel->ban_list, 
-                                          strlen(channel->ban_list) - 1);
-  else
-    packet = 
-      silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
-                                          SILC_STATUS_OK, ident, 1,
-                                          2, id, id_len);
+    /* The client is locally connected, just get the public key and
+       send it back. */
+    tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
+    pk = silc_buffer_alloc(4 + tmp_len);
+    silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
+    silc_buffer_format(pk,
+                      SILC_STR_UI_SHORT(tmp_len),
+                      SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
+                      SILC_STR_UI_XNSTRING(tmp, tmp_len),
+                      SILC_STR_END);
+    silc_free(tmp);
+  } else {
+    goto out;
+  }
 
+  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
+  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
+                                               SILC_STATUS_OK, ident, 2,
+                                               2, tmp, tmp_len,
+                                               3, pk->data, pk->len);
   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          packet->data, packet->len, FALSE);
-    
   silc_buffer_free(packet);
+  silc_buffer_free(pk);
 
  out:
-  if (channel_id)
-    silc_free(channel_id);
+  if (idp)
+    silc_id_payload_free(idp);
+  silc_free(client_id);
+  silc_free(server_id);
   silc_server_command_free(cmd);
 }