Code auditing weekend results and fixes committing.
[silc.git] / apps / silcd / command.c
index 87eebd88d208b0c19f1714db6ab7c62d226ed6d7..3241d595406245020f09e3cc794c5c79f1812161 100644 (file)
@@ -4,7 +4,7 @@
 
   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
 
-  Copyright (C) 1997 - 2000 Pekka Riikonen
+  Copyright (C) 1997 - 2001 Pekka Riikonen
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -38,9 +38,10 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
                                     unsigned char *arg,
                                     unsigned int arg_len);
 static void silc_server_command_free(SilcServerCommandContext cmd);
-void silc_server_command_send_names(SilcServer server,
+void silc_server_command_send_users(SilcServer server,
                                    SilcSocketConnection sock,
-                                   SilcChannelEntry channel);
+                                   SilcChannelEntry channel,
+                                   int pending);
 
 /* Server command list. */
 SilcServerCommand silc_command_list[] =
@@ -73,7 +74,7 @@ SilcServerCommand silc_command_list[] =
   SILC_SERVER_CMD(silcoper, SILCOPER,
                  SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
-  SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
+  SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
 
   { NULL, 0 },
 };
@@ -312,17 +313,20 @@ silc_server_command_send_status_data(SilcServerCommandContext cmd,
 
 static int
 silc_server_command_whois_parse(SilcServerCommandContext cmd,
-                               SilcClientID **client_id,
+                               SilcClientID ***client_id,
+                               unsigned int *client_id_count,
                                char **nickname,
                                char **server_name,
-                               int *count)
+                               int *count,
+                               SilcCommand command)
 {
   unsigned char *tmp;
   unsigned int len;
   unsigned int 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 */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
+  tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
   if (!tmp) {
     /* No ID, get the nickname@server string and parse it. */
     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
@@ -337,30 +341,51 @@ silc_server_command_whois_parse(SilcServerCommandContext cmd,
        *nickname = strdup(tmp);
       }
     } else {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
+      silc_server_command_send_status_reply(cmd, command,
                                            SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
       return FALSE;
     }
   } else {
+    /* Command includes ID, we must use that.  Also check whether the command
+       has more than one ID set - take them all. */
+
+    *client_id = silc_calloc(1, sizeof(**client_id));
+    (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
+    if ((*client_id)[0] == NULL) {
+      silc_free(*client_id);
+      return FALSE;
+    }
+    *client_id_count = 1;
+
+    /* Take all ID's from the command packet */
+    if (argc > 3) {
+      for (k = 1, i = 4; i < argc; i++) {
+       tmp = silc_argument_get_arg_type(cmd->args, i, &len);
+       if (tmp) {
+         *client_id = silc_realloc(*client_id, sizeof(**client_id) *
+                                   (*client_id_count + 1));
+         (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
+         if ((*client_id)[k] == NULL) {
+           for (i = 0; i < k; i++)
+             silc_free((*client_id)[i]);
+           silc_free(*client_id);
+           return FALSE;
+         }
+         (*client_id_count)++;
+         k++;
+       }
+      }
+    }
+
     /* Command includes ID, use that */
-    *client_id = silc_id_payload_parse_id(tmp, len);
   }
 
   /* Get the max count of reply messages allowed */
-  if (argc == 3) {
-    tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
-    if (!tmp) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
-                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
-      if (*nickname)
-       silc_free(*nickname);
-      if (*server_name)
-       silc_free(*server_name);
-
-      return FALSE;
-    }
+  tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
+  if (tmp)
     *count = atoi(tmp);
-  }
+  else
+    *count = 0;
 
   return TRUE;
 }
@@ -380,6 +405,9 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
     if (!entry->nickname || !entry->username || !entry->userinfo) {
       SilcBuffer tmpbuf;
       unsigned short old_ident;
+
+      if (!entry->router)
+       continue;
       
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
@@ -501,15 +529,11 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count;
-  SilcClientID *client_id = NULL;
+  int count = 0, clients_count = 0;
   SilcClientEntry *clients = NULL, entry;
-  int ret = 0;
-
-  /* Parse the whois request */
-  if (!silc_server_command_whois_parse(cmd, &client_id, &nick, 
-                                      &server_name, &count))
-    return 0;
+  SilcClientID **client_id = NULL;
+  unsigned int client_id_count = 0;
+  int i, ret = 0;
 
   /* Protocol dictates that we must always send the received WHOIS request
      to our router if we are normal server, so let's do it now unless we
@@ -546,13 +570,23 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   /* We are ready to process the command request. Let's search for the
      requested client and send reply to the requesting client. */
 
+  /* Parse the whois request */
+  if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
+                                      &nick, &server_name, &count,
+                                      SILC_COMMAND_WHOIS))
+    return 0;
+
   /* Get all clients matching that ID or nickname from local list */
-  if (client_id) {
-    entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
-    if (entry) {
-      clients = silc_calloc(1, sizeof(*clients));
-      clients[0] = entry;
-      clients_count = 1;
+  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->local_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_nickname(server->local_list, 
@@ -562,13 +596,16 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   
   /* Check global list as well */
   if (!clients) {
-    if (client_id) {
-      entry = silc_idlist_find_client_by_id(server->global_list, 
-                                           client_id, NULL);
-      if (entry) {
-       clients = silc_calloc(1, sizeof(*clients));
-       clients[0] = entry;
-       clients_count = 1;
+    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_nickname(server->global_list, 
@@ -578,10 +615,18 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   }
   
   if (!clients) {
-    /* Such a client really does not exist in the SILC network. */
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
-                                        SILC_STATUS_ERR_NO_SUCH_NICK,
-                                        3, nick, strlen(nick));
+    /* Such client(s) really does not exist in the SILC network. */
+    if (!client_id_count) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
+                                          SILC_STATUS_ERR_NO_SUCH_NICK,
+                                          3, nick, strlen(nick));
+    } else {
+      SilcBuffer idp = silc_id_payload_encode(client_id[0], 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);
+    }
     goto out;
   }
 
@@ -600,10 +645,13 @@ silc_server_command_whois_from_client(SilcServerCommandContext cmd)
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
 
  out:
+  if (client_id_count) {
+    for (i = 0; i < client_id_count; i++)
+      silc_free(client_id[i]);
+    silc_free(client_id);
+  }
   if (clients)
     silc_free(clients);
-  if (client_id)
-    silc_free(client_id);
   if (nick)
     silc_free(nick);
   if (server_name)
@@ -617,25 +665,31 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count;
-  SilcClientID *client_id = NULL;
+  int count = 0, clients_count = 0;
   SilcClientEntry *clients = NULL, entry;
-  int ret = 0;
+  SilcClientID **client_id = NULL;
+  unsigned int client_id_count = 0;
+  int i, ret = 0;
 
   /* Parse the whois request */
-  if (!silc_server_command_whois_parse(cmd, &client_id, &nick, 
-                                      &server_name, &count))
+  if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
+                                      &nick, &server_name, &count,
+                                      SILC_COMMAND_WHOIS))
     return 0;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
 
-  if (client_id) {
-    entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
-    if (entry) {
-      clients = silc_calloc(1, sizeof(*clients));
-      clients[0] = entry;
-      clients_count = 1;
+  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->local_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_nickname(server->local_list, 
@@ -649,13 +703,16 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
   
   /* If we are router we will check our global list as well. */
   if (!clients && server->server_type == SILC_ROUTER) {
-    if (client_id) {
-      entry = silc_idlist_find_client_by_id(server->global_list, 
-                                           client_id, NULL);
-      if (entry) {
-       clients = silc_calloc(1, sizeof(*clients));
-       clients[0] = entry;
-       clients_count = 1;
+    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_nickname(server->global_list, 
@@ -670,12 +727,12 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
 
   if (!clients) {
     /* Such a client really does not exist in the SILC network. */
-    if (!client_id) {
+    if (!client_id_count) {
       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
                                           SILC_STATUS_ERR_NO_SUCH_NICK,
                                           3, nick, strlen(nick));
     } else {
-      SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+      SilcBuffer idp = silc_id_payload_encode(client_id[0], 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);
@@ -699,10 +756,13 @@ silc_server_command_whois_from_server(SilcServerCommandContext cmd)
   silc_server_command_whois_send_reply(cmd, clients, clients_count);
 
  out:
+  if (client_id_count) {
+    for (i = 0; i < client_id_count; i++)
+      silc_free(client_id[i]);
+    silc_free(client_id);
+  }
   if (clients)
     silc_free(clients);
-  if (client_id)
-    silc_free(client_id);
   if (nick)
     silc_free(nick);
   if (server_name)
@@ -719,7 +779,7 @@ SILC_SERVER_CMD_FUNC(whois)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   int ret;
 
-  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     ret = silc_server_command_whois_from_client(cmd);
@@ -740,61 +800,6 @@ SILC_SERVER_CMD_FUNC(whowas)
 
 ******************************************************************************/
 
-static int
-silc_server_command_identify_parse(SilcServerCommandContext cmd,
-                                  SilcClientID **client_id,
-                                  char **nickname,
-                                  char **server_name,
-                                  int *count)
-{
-  unsigned char *tmp;
-  unsigned int len;
-  unsigned int argc = silc_argument_get_arg_num(cmd->args);
-
-  /* If client ID is in the command it must be used instead of nickname */
-  tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
-  if (!tmp) {
-    /* No ID, get the nickname@server string and parse it. */
-    tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
-    if (tmp) {
-      if (strchr(tmp, '@')) {
-       len = strcspn(tmp, "@");
-       *nickname = silc_calloc(len + 1, sizeof(char));
-       memcpy(*nickname, tmp, len);
-       *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
-       memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
-      } else {
-       *nickname = strdup(tmp);
-      }
-    } else {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
-                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
-      return FALSE;
-    }
-  } else {
-    /* Command includes ID, use that */
-    *client_id = silc_id_payload_parse_id(tmp, len);
-  }
-
-  /* Get the max count of reply messages allowed */
-  if (argc == 3) {
-    tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
-    if (!tmp) {
-      silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
-                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
-      if (*nickname)
-       silc_free(*nickname);
-      if (*server_name)
-       silc_free(*server_name);
-
-      return FALSE;
-    }
-    *count = atoi(tmp);
-  }
-
-  return TRUE;
-}
-
 /* Checks that all mandatory fields are present. If not then send WHOIS 
    request to the server who owns the client. We use WHOIS because we want
    to get as much information as possible at once. */
@@ -815,6 +820,9 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
       SilcBuffer tmpbuf;
       unsigned short old_ident;
       
+      if (!entry->router)
+       continue;
+      
       old_ident = silc_command_get_ident(cmd->payload);
       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
@@ -929,15 +937,11 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count;
-  SilcClientID *client_id = NULL;
+  int count = 0, clients_count = 0; 
   SilcClientEntry *clients = NULL, entry;
-  int ret = 0;
-
-  /* Parse the IDENTIFY request */
-  if (!silc_server_command_identify_parse(cmd, &client_id, &nick, 
-                                         &server_name, &count))
-    return 0;
+  SilcClientID **client_id = NULL;
+  unsigned int client_id_count = 0;
+  int i, ret = 0;
 
   /* Protocol dictates that we must always send the received IDENTIFY request
      to our router if we are normal server, so let's do it now unless we
@@ -974,13 +978,23 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   /* We are ready to process the command request. Let's search for the
      requested client and send reply to the requesting client. */
 
+  /* Parse the IDENTIFY request */
+  if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+                                      &nick, &server_name, &count,
+                                      SILC_COMMAND_IDENTIFY))
+    return 0;
+
   /* Get all clients matching that ID or nickname from local list */
-  if (client_id) {
-    entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
-    if (entry) {
-      clients = silc_calloc(1, sizeof(*clients));
-      clients[0] = entry;
-      clients_count = 1;
+  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->local_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_nickname(server->local_list, 
@@ -990,13 +1004,16 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   
   /* Check global list as well */
   if (!clients) {
-    if (client_id) {
-      entry = silc_idlist_find_client_by_id(server->global_list, 
-                                           client_id, NULL);
-      if (entry) {
-       clients = silc_calloc(1, sizeof(*clients));
-       clients[0] = entry;
-       clients_count = 1;
+    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_nickname(server->global_list, 
@@ -1007,12 +1024,12 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   
   if (!clients) {
     /* Such a client really does not exist in the SILC network. */
-    if (!client_id) {
+    if (!client_id_count) {
       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
                                           SILC_STATUS_ERR_NO_SUCH_NICK,
                                           3, nick, strlen(nick));
     } else {
-      SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
+      SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
                                           2, idp->data, idp->len);
@@ -1033,10 +1050,13 @@ silc_server_command_identify_from_client(SilcServerCommandContext cmd)
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
 
  out:
+  if (client_id_count) {
+    for (i = 0; i < client_id_count; i++)
+      silc_free(client_id[i]);
+    silc_free(client_id);
+  }
   if (clients)
     silc_free(clients);
-  if (client_id)
-    silc_free(client_id);
   if (nick)
     silc_free(nick);
   if (server_name)
@@ -1050,25 +1070,31 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 {
   SilcServer server = cmd->server;
   char *nick = NULL, *server_name = NULL;
-  int count = 0, clients_count;
-  SilcClientID *client_id = NULL;
+  int count = 0, clients_count = 0;
   SilcClientEntry *clients = NULL, entry;
-  int ret = 0;
+  SilcClientID **client_id = NULL;
+  unsigned int client_id_count = 0;
+  int i, ret = 0;
 
   /* Parse the IDENTIFY request */
-  if (!silc_server_command_identify_parse(cmd, &client_id, &nick, 
-                                         &server_name, &count))
+  if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
+                                      &nick, &server_name, &count,
+                                      SILC_COMMAND_IDENTIFY))
     return 0;
 
   /* Process the command request. Let's search for the requested client and
      send reply to the requesting server. */
 
-  if (client_id) {
-    entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
-    if (entry) {
-      clients = silc_calloc(1, sizeof(*clients));
-      clients[0] = entry;
-      clients_count = 1;
+  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->local_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_nickname(server->local_list, 
@@ -1082,13 +1108,16 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
   
   /* If we are router we will check our global list as well. */
   if (!clients && server->server_type == SILC_ROUTER) {
-    if (client_id) {
-      entry = silc_idlist_find_client_by_id(server->global_list, 
-                                           client_id, NULL);
-      if (entry) {
-       clients = silc_calloc(1, sizeof(*clients));
-       clients[0] = entry;
-       clients_count = 1;
+    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_nickname(server->global_list, 
@@ -1103,9 +1132,17 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
 
   if (!clients) {
     /* Such a client really does not exist in the SILC network. */
-    silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
-                                        SILC_STATUS_ERR_NO_SUCH_NICK,
-                                        3, nick, strlen(nick));
+    if (!client_id_count) {
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                          SILC_STATUS_ERR_NO_SUCH_NICK,
+                                          3, nick, strlen(nick));
+    } else {
+      SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
+      silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
+                                          SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
+                                          2, idp->data, idp->len);
+      silc_buffer_free(idp);
+    }
     goto out;
   }
 
@@ -1121,10 +1158,13 @@ silc_server_command_identify_from_server(SilcServerCommandContext cmd)
   silc_server_command_identify_send_reply(cmd, clients, clients_count);
 
  out:
+  if (client_id_count) {
+    for (i = 0; i < client_id_count; i++)
+      silc_free(client_id[i]);
+    silc_free(client_id);
+  }
   if (clients)
     silc_free(clients);
-  if (client_id)
-    silc_free(client_id);
   if (nick)
     silc_free(nick);
   if (server_name)
@@ -1138,7 +1178,7 @@ SILC_SERVER_CMD_FUNC(identify)
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   int ret;
 
-  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
 
   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
     ret = silc_server_command_identify_from_client(cmd);
@@ -1196,7 +1236,7 @@ SILC_SERVER_CMD_FUNC(nick)
   /* Send notify about nickname change to our router. We send the new
      ID and ask to replace it with the old one. If we are router the
      packet is broadcasted. */
-  if (!cmd->server->standalone)
+  if (!server->standalone)
     silc_server_send_replace_id(server, server->router->connection, 
                                server->server_type == SILC_SERVER ? 
                                FALSE : TRUE, client->id,
@@ -1280,6 +1320,11 @@ SILC_SERVER_CMD_FUNC(topic)
     goto out;
   }
   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
+  if (!channel_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Check whether the channel exists */
   channel = silc_idlist_find_channel_by_id(server->local_list, 
@@ -1327,7 +1372,7 @@ SILC_SERVER_CMD_FUNC(topic)
     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
 
     /* Send notify about topic change to all clients on the channel */
-    silc_server_send_notify_to_channel(server, channel, TRUE,
+    silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
                                       SILC_NOTIFY_TYPE_TOPIC_SET, 2,
                                       idp->data, idp->len,
                                       channel->topic, strlen(channel->topic));
@@ -1382,6 +1427,11 @@ SILC_SERVER_CMD_FUNC(invite)
     goto out;
   }
   dest_id = silc_id_payload_parse_id(tmp, len);
+  if (!dest_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                         SILC_STATUS_ERR_NO_CLIENT_ID);
+    goto out;
+  }
 
   /* Get Channel ID */
   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
@@ -1391,6 +1441,11 @@ SILC_SERVER_CMD_FUNC(invite)
     goto out;
   }
   channel_id = silc_id_payload_parse_id(tmp, len);
+  if (!channel_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Check whether the channel exists */
   channel = silc_idlist_find_channel_by_id(server->local_list, 
@@ -1436,7 +1491,7 @@ SILC_SERVER_CMD_FUNC(invite)
 
   /* Check whether the requested client is already on the channel. */
   /* XXX if we are normal server we don't know about global clients on
-     the channel thus we must request it (NAMES command), check from
+     the channel thus we must request it (USERS command), check from
      local cache as well. */
   if (silc_server_client_on_channel(dest, channel)) {
     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
@@ -1581,7 +1636,7 @@ SILC_SERVER_CMD_FUNC(ping)
                                          SILC_STATUS_ERR_NO_SERVER_ID);
     goto out;
   }
-  id = silc_id_str2id(tmp, SILC_ID_SERVER);
+  id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
   if (!id)
     goto out;
 
@@ -1605,114 +1660,64 @@ SILC_SERVER_CMD_FUNC(oper)
 {
 }
 
-typedef struct {
-  char *channel_name;
-  char *nickname;
-  char *username;
-  char *hostname;
-  SilcChannelEntry channel;
-  SilcServer server;
-  SilcClientEntry client;
-} JoinInternalContext;
-
-SILC_TASK_CALLBACK(silc_server_command_join_notify)
-{
-  JoinInternalContext *ctx = (JoinInternalContext *)context;
-
-  if (ctx->channel->key && ctx->channel->key_len) {
-    SilcBuffer clidp;
-
-    clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
-
-    silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
-                                      SILC_NOTIFY_TYPE_JOIN, 1,
-                                      clidp->data, clidp->len);
-#if 0
-    /* Send NEW_CHANNEL_USER packet to primary route */
-    silc_server_send_new_channel_user(server, server->router->connection,
-                                     server->server_type == SILC_SERVER ?
-                                     FALSE : TRUE,
-                                     channel->id, SILC_ID_CHANNEL_LEN,
-                                     client->id, SILC_ID_CLIENT_LEN);
-#endif
-
-    /* Send NAMES command reply to the joined channel so the user sees who
-       is currently on the channel. */
-    silc_server_command_send_names(ctx->server, ctx->client->connection, 
-                                  ctx->channel);
-
-    silc_buffer_free(clidp);
-    silc_free(ctx);
-  } else {
-    silc_task_register(ctx->server->timeout_queue, fd,
-                      silc_server_command_join_notify, context,
-                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
-  }
-}
-
-/* Assembles NAMES command and executes it. This is called when client
-   joins to a channel and we wan't to send NAMES command reply to the 
+/* Assembles USERS command and executes it. This is called when client
+   joins to a channel and we wan't to send USERS command reply to the 
    client. */
 
-void silc_server_command_send_names(SilcServer server,
+void silc_server_command_send_users(SilcServer server,
                                    SilcSocketConnection sock,
-                                   SilcChannelEntry channel)
+                                   SilcChannelEntry channel,
+                                   int pending)
 {
   SilcServerCommandContext cmd;
   SilcBuffer buffer, idp;
+  SilcPacketContext *packet = silc_packet_context_alloc();
+
+  SILC_LOG_DEBUG(("Start"));
 
+  /* Create USERS command packet and process it. */
   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
-  buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
+  buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
                                          1, idp->data, idp->len);
 
+  packet->buffer = silc_buffer_copy(buffer);
+  packet->sock = sock;
+  packet->type = SILC_PACKET_COMMAND;
+
   cmd = silc_calloc(1, sizeof(*cmd));
   cmd->payload = silc_command_payload_parse(buffer);
+  if (!cmd->payload) {
+    silc_free(cmd);
+    silc_buffer_free(buffer);
+    silc_buffer_free(idp);
+    silc_packet_context_free(packet);
+    return;
+  }
   cmd->args = silc_command_get_args(cmd->payload);
   cmd->server = server;
   cmd->sock = sock;
+  cmd->packet = silc_packet_context_dup(packet);
   cmd->pending = FALSE;
 
-  silc_server_command_names((void *)cmd);
-  silc_free(buffer);
-  silc_free(idp);
-}
-
-/* Internal routine that is called after router has replied to server's
-   JOIN command it forwarded to the router. The route has joined and possibly
-   creaetd the channel. This function adds the client to the channel's user
-   list. */
-
-SILC_SERVER_CMD_FUNC(add_to_channel)
-{
-  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
-  SilcServer server = cmd->server;
-  SilcClientEntry client;
-  SilcChannelEntry channel;
-  SilcChannelClientEntry chl;
-  char *channel_name;
-
-  /* Get channel name */
-  channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
-
-  /* Get client entry */
-  client = (SilcClientEntry)cmd->sock->user_data;
-
-  /* Get channel entry */
-  channel = silc_idlist_find_channel_by_name(server->local_list, 
-                                            channel_name, NULL);
-  if (channel) {
-    /* Join the client to the channel by adding it to channel's user list.
-       Add also the channel to client entry's channels list for fast cross-
-       referencing. */
-    chl = silc_calloc(1, sizeof(*chl));
-    //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
-    chl->client = client;
-    chl->channel = channel;
-    silc_list_add(channel->user_list, chl);
-    silc_list_add(client->channels, chl);
+  if (pending) {
+    /* If this function was called from pending command then instead of
+       processing the command now, register a pending command callback which
+       will process it after we've received the automatic USERS command 
+       reply. */
+    silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
+                               silc_server_command_users, (void *)cmd);
+    cmd->pending = TRUE;
+    silc_buffer_free(buffer);
+    silc_buffer_free(idp);
+    return;
   }
 
-  silc_server_command_free(cmd);
+  /* Process USERS command. */
+  silc_server_command_users((void *)cmd);
+  silc_buffer_free(buffer);
+  silc_buffer_free(idp);
+  silc_packet_context_free(packet);
 }
 
 /* Internal routine to join channel. The channel sent to this function
@@ -1820,7 +1825,7 @@ static void silc_server_command_join_channel(SilcServer server,
 
   /* Send the channel key. This is broadcasted to the channel but is not
      sent to the client who is joining to the channel. */
-  silc_server_send_channel_key(server, channel, 
+  silc_server_send_channel_key(server, NULL, channel, 
                               server->server_type == SILC_ROUTER ? 
                               FALSE : server->standalone);
 
@@ -1875,34 +1880,24 @@ static void silc_server_command_join_channel(SilcServer server,
   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
                          reply->data, reply->len, FALSE);
 
-  if (!cmd->pending)
+  if (!cmd->pending) {
     /* Send JOIN notify to locally connected clients on the channel */
-    silc_server_send_notify_to_channel(server, channel, FALSE,
+    silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
                                       SILC_NOTIFY_TYPE_JOIN, 1,
                                       clidp->data, clidp->len);
 
-  /* Send NEW_CHANNEL_USER packet to our primary router */
-  if (!cmd->pending && !server->standalone)
-    silc_server_send_new_channel_user(server, server->router->connection,
-                                     server->server_type == SILC_SERVER ?
-                                     FALSE : TRUE,
-                                     channel->id, SILC_ID_CHANNEL_LEN,
-                                     client->id, SILC_ID_CLIENT_LEN);
+    /* Send NEW_CHANNEL_USER packet to our primary router */
+    if (!server->standalone)
+      silc_server_send_new_channel_user(server, server->router->connection,
+                                       server->server_type == SILC_SERVER ?
+                                       FALSE : TRUE,
+                                       channel->id, SILC_ID_CHANNEL_LEN,
+                                       client->id, SILC_ID_CLIENT_LEN);
+  }
 
-  /* Send NAMES command reply to the joined channel so the user sees who
+  /* Send USERS command reply to the joined channel so the user sees who
      is currently on the channel. */
-  silc_server_command_send_names(server, sock, channel);
-
-  /*
-
-    FAQ:
-
-   * Kuinka NAMES komento händlätään serverissä kun router lähettää sen
-   serverille joka on lähettäny sille clientin puolesta JOIN komennon?
-   
-   R: Serverin pitää ymmärtää NAMES comman replyjä.
-
-  */
+  silc_server_command_send_users(server, sock, channel, cmd->pending);
 
   silc_buffer_free(reply);
   silc_buffer_free(clidp);
@@ -1954,6 +1949,11 @@ SILC_SERVER_CMD_FUNC(join)
     goto out;
   }
   client_id = silc_id_payload_parse_id(tmp, tmp_len);
+  if (!client_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
+                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
+    goto out;
+  }
 
   /* Get cipher name */
   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
@@ -2201,6 +2201,11 @@ SILC_SERVER_CMD_FUNC(cmode)
     goto out;
   }
   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
+  if (!channel_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Get the channel mode mask */
   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
@@ -2508,7 +2513,7 @@ SILC_SERVER_CMD_FUNC(cmode)
 
   /* Send CMODE_CHANGE notify */
   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-  silc_server_send_notify_to_channel(server, channel, TRUE,
+  silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
                                     SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
                                     cidp->data, cidp->len, 
                                     tmp_mask, tmp_len);
@@ -2555,6 +2560,11 @@ SILC_SERVER_CMD_FUNC(cumode)
     goto out;
   }
   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
+  if (!channel_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list, 
@@ -2605,6 +2615,11 @@ SILC_SERVER_CMD_FUNC(cumode)
     goto out;
   }
   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
+  if (!client_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Get target client's entry */
   target_client = silc_idlist_find_client_by_id(server->local_list, 
@@ -2674,7 +2689,7 @@ SILC_SERVER_CMD_FUNC(cumode)
   /* Send notify to channel, notify only if mode was actually changed. */
   if (notify) {
     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
-    silc_server_send_notify_to_channel(server, channel, TRUE,
+    silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
                                       SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
                                       idp->data, idp->len,
                                       tmp_mask, 4, tmp_id, tmp_len);
@@ -2743,6 +2758,11 @@ SILC_SERVER_CMD_FUNC(leave)
     goto out;
   }
   id = silc_id_payload_parse_id(tmp, len);
+  if (!id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
 
   /* Get channel entry */
   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
@@ -2812,11 +2832,11 @@ SILC_SERVER_CMD_FUNC(leave)
   silc_server_command_free(cmd);
 }
 
-/* Server side of command NAMES. Resolves clients and their names currently
-   joined on the requested channel. The name list is sent back to the
-   client. */
+/* Server side of command USERS. Resolves clients and their USERS currently
+   joined on the requested channel. The list of Client ID's and their modes
+   on the channel is sent back. */
 
-SILC_SERVER_CMD_FUNC(names)
+SILC_SERVER_CMD_FUNC(users)
 {
   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
   SilcServer server = cmd->server;
@@ -2824,102 +2844,106 @@ SILC_SERVER_CMD_FUNC(names)
   SilcChannelClientEntry chl;
   SilcChannelID *id;
   SilcBuffer packet;
-  unsigned int i, len, len2, tmp_len;
-  unsigned char *tmp;
-  char *name_list = NULL, *n;
+  unsigned char *channel_id;
+  unsigned int channel_id_len;
   SilcBuffer client_id_list;
   SilcBuffer client_mode_list;
+  SilcBuffer idp;
+  unsigned char lc[4];
+  unsigned int list_count = 0;
+  unsigned short ident = silc_command_get_ident(cmd->payload);
 
-  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NAMES, cmd, 1, 2);
+  SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
 
   /* Get Channel ID */
-  tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
-  if (!tmp) {
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
+  channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
+  if (!channel_id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
+                                         SILC_STATUS_ERR_NO_CHANNEL_ID);
+    goto out;
+  }
+  id = silc_id_payload_parse_id(channel_id, channel_id_len);
+  if (!id) {
+    silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
                                          SILC_STATUS_ERR_NO_CHANNEL_ID);
     goto out;
   }
-  id = silc_id_payload_parse_id(tmp, tmp_len);
 
-  /* Check whether the channel exists. If we are normal server and the
-     channel does not exist we will send this same command to our router
-     which will know if the channel exists. */
+  /* If we are server and we don't know about this channel we will send
+     the command to our router. If we know about the channel then we also
+     have the list of users already. */
   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
   if (!channel) {
-    if (server->server_type == SILC_SERVER && !server->standalone) {
-      /* XXX Send names command */
-
+    if (server->server_type == SILC_SERVER && !server->standalone &&
+       !cmd->pending) {
+      SilcBuffer tmpbuf;
+      
+      silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
+      tmpbuf = silc_command_payload_encode_payload(cmd->payload);
+      
+      /* Send USERS command */
+      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 */
+      silc_server_command_pending(server, SILC_COMMAND_USERS, 
+                                 silc_command_get_ident(cmd->payload),
+                                 silc_server_command_users, (void *)cmd);
       cmd->pending = TRUE;
-      silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
-                                 silc_server_command_names, context);
+      silc_command_set_ident(cmd->payload, ident);
+      
+      silc_buffer_free(tmpbuf);
+      silc_free(id);
       return;
     }
 
-    silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
-                                         SILC_STATUS_ERR_NO_SUCH_CHANNEL);
-    goto out;
-  }
-
-  /* Assemble the name list now */
-  name_list = NULL;
-  len = 0;
-  silc_list_start(channel->user_list);
-  i = 0;
-  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-    n = chl->client->nickname;
-    if (n) {
-      len2 = strlen(n);
-      len += len2;
-      name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
-      memcpy(name_list + (len - len2), n, len2);
-      name_list[len] = 0;
-
-      if (i == silc_list_count(channel->user_list) - 1)
-       break;
-      memcpy(name_list + len, ",", 1);
-      len++;
-      i++;
+    /* We are router and we will check the global list as well. */
+    channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
+    if (!channel) {
+      /* Channel really does not exist */
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
+                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
+      goto out;
     }
   }
-  if (!name_list)
-    name_list = "";
 
-  /* Assemble the Client ID list now */
+  /* Assemble the lists now */
+
   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
                                     silc_list_count(channel->user_list));
   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
+  client_mode_list = 
+    silc_buffer_alloc(4 * silc_list_count(channel->user_list));
+  silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
+
   silc_list_start(channel->user_list);
   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
-    SilcBuffer idp;
-
+    /* Client ID */
     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
-    silc_buffer_format(client_id_list,
-                      SILC_STR_UI_XNSTRING(idp->data, idp->len),
-                      SILC_STR_END);
+    silc_buffer_put(client_id_list, idp->data, idp->len);
     silc_buffer_pull(client_id_list, idp->len);
     silc_buffer_free(idp);
-  }
-  silc_buffer_push(client_id_list, 
-                  client_id_list->data - client_id_list->head);
 
-  /* Assemble mode list */
-  client_mode_list = silc_buffer_alloc(4 * 
-                                      silc_list_count(channel->user_list));
-  silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
-  silc_list_start(channel->user_list);
-  while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
+    /* Client's mode on channel */
     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
     silc_buffer_pull(client_mode_list, 4);
+
+    list_count++;
   }
+  silc_buffer_push(client_id_list, 
+                  client_id_list->data - client_id_list->head);
   silc_buffer_push(client_mode_list, 
                   client_mode_list->data - client_mode_list->head);
 
+  /* List count */
+  SILC_PUT32_MSB(list_count, lc);
+
   /* Send reply */
-  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
+  packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
                                                SILC_STATUS_OK, 0, 4,
-                                               2, tmp, tmp_len,
-                                               3, name_list, 
-                                               strlen(name_list),
+                                               2, channel_id, channel_id_len,
+                                               3, lc, 4,
                                                4, client_id_list->data,
                                                client_id_list->len,
                                                5, client_mode_list->data,
@@ -2928,7 +2952,6 @@ SILC_SERVER_CMD_FUNC(names)
                          packet->data, packet->len, FALSE);
     
   silc_buffer_free(packet);
-  silc_free(name_list);
   silc_buffer_free(client_id_list);
   silc_buffer_free(client_mode_list);
   silc_free(id);