updates.
[silc.git] / apps / silcd / command.c
index d72636f44453ef5404c368b2eebcc8f3c4230ca6..554fbb942b3a6b0c30b4f5f21776093f8d214e34 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. */
@@ -71,13 +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(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"));                                                 \
                                                                              \
@@ -277,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)
@@ -297,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;
 
@@ -316,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;
 
@@ -370,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;
 
@@ -397,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 */
@@ -477,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;
@@ -491,7 +492,7 @@ silc_server_command_whois_check(SilcServerCommandContext cmd,
 
     if (!entry->nickname || !entry->username || !entry->userinfo) {
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
 
       if (!entry->router)
        continue;
@@ -526,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;
@@ -535,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;
@@ -591,10 +592,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));
@@ -653,10 +658,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
@@ -666,7 +671,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));
@@ -795,10 +800,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 */
@@ -932,7 +937,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) {
@@ -964,7 +969,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;
@@ -975,7 +980,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;
@@ -1010,7 +1015,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;
@@ -1018,7 +1023,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];
 
@@ -1063,10 +1068,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));
@@ -1111,8 +1120,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
@@ -1122,7 +1132,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));
@@ -1196,8 +1206,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 */
@@ -1278,7 +1289,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;
@@ -1292,7 +1303,7 @@ silc_server_command_identify_check(SilcServerCommandContext cmd,
 
     if (!entry->nickname) {
       SilcBuffer tmpbuf;
-      unsigned short old_ident;
+      uint16 old_ident;
       
       if (!entry->router)
        continue;
@@ -1332,7 +1343,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;
@@ -1341,7 +1352,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;
 
@@ -1390,10 +1401,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) {
@@ -1432,10 +1447,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
@@ -1445,7 +1460,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));
@@ -1571,10 +1586,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 */
@@ -1716,7 +1731,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;
@@ -1800,18 +1815,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)
@@ -1936,9 +1951,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);
 
@@ -1983,8 +1998,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);
 
@@ -2107,8 +2122,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);
 
@@ -2346,7 +2361,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);
 
@@ -2383,7 +2398,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);
 
@@ -2498,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;
 
@@ -2566,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));
@@ -2591,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));
@@ -2653,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);
@@ -2694,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"));
@@ -2914,10 +2929,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;
 
@@ -3001,7 +3016,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));
@@ -3100,8 +3115,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);
 
@@ -3157,7 +3172,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));
@@ -3182,7 +3197,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));
@@ -3244,8 +3259,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,7 +3337,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;
@@ -3396,8 +3411,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);
 
@@ -3488,7 +3503,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);
@@ -3745,9 +3760,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);
 
@@ -3863,7 +3878,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) {
@@ -3960,7 +3975,7 @@ SILC_SERVER_CMD_FUNC(cumode)
                                     server->server_type == SILC_ROUTER ? 
                                     TRUE : FALSE, channel,
                                     target_mask, client->id, 
-                                    SILC_ID_CLIENT_LEN,
+                                    SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
                                     target_client->id, 
                                     SILC_ID_CLIENT_LEN);
   }
@@ -3995,7 +4010,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);
@@ -4148,7 +4163,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,7 +4236,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 +4312,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);
 
@@ -4356,8 +4371,8 @@ SILC_SERVER_CMD_FUNC(ban)
   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);
+  uint32 id_len, tmp_len;
+  uint16 ident = silc_command_get_ident(cmd->payload);
 
   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
     goto out;
@@ -4489,9 +4504,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);
 
@@ -4582,7 +4597,7 @@ SILC_SERVER_CMD_FUNC(leave)
   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
   SilcChannelID *id = NULL;
   SilcChannelEntry channel;
-  unsigned int len;
+  uint32 len;
   unsigned char *tmp;
 
   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
@@ -4646,8 +4661,6 @@ SILC_SERVER_CMD_FUNC(leave)
                                 FALSE : !server->standalone);
   }
 
-  silc_free(id);
-
  out:
   if (id)
     silc_free(id);
@@ -4666,12 +4679,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);
 
@@ -4757,3 +4770,167 @@ SILC_SERVER_CMD_FUNC(users)
  out:
   silc_server_command_free(cmd);
 }
+
+/* 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(getkey)
+{
+  SilcServerCommandContext cmd = (SilcServerCommandContext)context;
+  SilcServer server = cmd->server;
+  SilcBuffer packet;
+  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;
+
+  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;
+  }
+  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;
+  }
+
+  id_type = silc_id_payload_get_type(idp);
+  if (id_type == SILC_ID_CLIENT) {
+    client_id = silc_id_payload_get_id(idp);
+
+    /* 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;
+    }
+
+    if (!client && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
+      goto out;
+    }
+
+    /* 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);
+
+  } else if (id_type == SILC_ID_SERVER) {
+    server_id = silc_id_payload_get_id(idp);
+
+    /* 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;
+    }
+
+    if (!server_entry && cmd->pending) {
+      silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
+                                           SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
+      goto out;
+    }
+
+    /* 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 (idp)
+    silc_id_payload_free(idp);
+  silc_free(client_id);
+  silc_free(server_id);
+  silc_server_command_free(cmd);
+}