updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      uint32 arg_type,
38                                      unsigned char *arg,
39                                      uint32 arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
41
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
44 {
45   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(connect, CONNECT, 
56                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
66   SILC_SERVER_CMD(close, CLOSE,
67                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
68   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
69                   SILC_CF_OPER),
70   SILC_SERVER_CMD(silcoper, SILCOPER,
71                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
72   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
73   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
74   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
75
76   { NULL, 0 },
77 };
78
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max)            \
80 do {                                                                          \
81   uint32 _argc = silc_argument_get_arg_num(cmd->args);                \
82                                                                               \
83   SILC_LOG_DEBUG(("Start"));                                                  \
84                                                                               \
85   if (_argc < min) {                                                          \
86     silc_server_command_send_status_reply(cmd, command,                       \
87                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88     silc_server_command_free(cmd);                                            \
89     return;                                                                   \
90   }                                                                           \
91   if (_argc > max) {                                                          \
92     silc_server_command_send_status_reply(cmd, command,                       \
93                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
94     silc_server_command_free(cmd);                                            \
95     return;                                                                   \
96   }                                                                           \
97 } while(0)
98
99 /* Returns TRUE if the connection is registered. Unregistered connections
100    usually cannot send commands hence the check. */
101
102 static int silc_server_is_registered(SilcServer server,
103                                      SilcSocketConnection sock,
104                                      SilcServerCommandContext cmd,
105                                      SilcCommand command)
106 {
107   SilcIDListData idata = (SilcIDListData)sock->user_data;
108   if (idata->registered)
109     return TRUE;
110
111   silc_server_command_send_status_reply(cmd, command,
112                                         SILC_STATUS_ERR_NOT_REGISTERED);
113   silc_server_command_free(cmd);
114   return FALSE;
115 }
116
117 /* Internal context to hold data when executed command with timeout. */
118 typedef struct {
119   SilcServerCommandContext ctx;
120   SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
122
123 /* Timeout callback to process commands with timeout for client. Client's
124    commands are always executed with timeout. */
125
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
127 {
128   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
130
131   /* Update access time */
132   client->last_command = time(NULL);
133
134   if (!(timeout->cmd->flags & SILC_CF_REG))
135     timeout->cmd->cb(timeout->ctx);
136   else if (silc_server_is_registered(timeout->ctx->server, 
137                                      timeout->ctx->sock, 
138                                      timeout->ctx, 
139                                      timeout->cmd->cmd))
140     timeout->cmd->cb(timeout->ctx);
141
142   silc_free(timeout);
143 }
144
145 /* Processes received command packet. */
146
147 void silc_server_command_process(SilcServer server,
148                                  SilcSocketConnection sock,
149                                  SilcPacketContext *packet)
150 {
151   SilcServerCommandContext ctx;
152   SilcServerCommand *cmd;
153   SilcCommand command;
154
155   /* Allocate command context. This must be free'd by the
156      command routine receiving it. */
157   ctx = silc_server_command_alloc();
158   ctx->server = server;
159   ctx->sock = silc_socket_dup(sock);
160   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
161   
162   /* Parse the command payload in the packet */
163   ctx->payload = silc_command_payload_parse(packet->buffer);
164   if (!ctx->payload) {
165     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
166     silc_buffer_free(packet->buffer);
167     silc_packet_context_free(packet);
168     silc_socket_free(ctx->sock);
169     silc_free(ctx);
170     return;
171   }
172   ctx->args = silc_command_get_args(ctx->payload);
173
174   /* Get the command */
175   command = silc_command_get(ctx->payload);
176   for (cmd = silc_command_list; cmd->cb; cmd++)
177     if (cmd->cmd == command)
178       break;
179
180   if (cmd == NULL) {
181     silc_server_command_send_status_reply(ctx, command,
182                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
183     silc_server_command_free(ctx);
184     return;
185   }
186
187   /* Execute client's commands always with timeout.  Normally they are
188      executed with zero (0) timeout but if client is sending command more
189      frequently than once in 2 seconds, then the timeout may be 0 to 2
190      seconds. */
191   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
192     SilcClientEntry client = (SilcClientEntry)sock->user_data;
193     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
194     int fast;
195
196     timeout->ctx = ctx;
197     timeout->cmd = cmd;
198
199     if (client->last_command && (time(NULL) - client->last_command) < 2) {
200       client->fast_command++;
201       fast = FALSE;
202     } else {
203       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
204                               client->fast_command--);
205       fast = TRUE;
206     }
207
208     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
209                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
210       silc_task_register(server->timeout_queue, sock->sock, 
211                          silc_server_command_process_timeout,
212                          (void *)timeout, 
213                          2 - (time(NULL) - client->last_command), 0,
214                          SILC_TASK_TIMEOUT,
215                          SILC_TASK_PRI_NORMAL);
216     else
217       silc_task_register(server->timeout_queue, sock->sock, 
218                          silc_server_command_process_timeout,
219                          (void *)timeout, 
220                          0, 1,
221                          SILC_TASK_TIMEOUT,
222                          SILC_TASK_PRI_NORMAL);
223     return;
224   }
225
226   /* Execute for server */
227
228   if (!(cmd->flags & SILC_CF_REG))
229     cmd->cb(ctx);
230   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
231     cmd->cb(ctx);
232 }
233
234 /* Allocate Command Context */
235
236 SilcServerCommandContext silc_server_command_alloc()
237 {
238   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
239   ctx->users++;
240   return ctx;
241 }
242
243 /* Free's the command context allocated before executing the command */
244
245 void silc_server_command_free(SilcServerCommandContext ctx)
246 {
247   ctx->users--;
248   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
249                   ctx->users));
250   if (ctx->users < 1) {
251     if (ctx->payload)
252       silc_command_free_payload(ctx->payload);
253     if (ctx->packet)
254       silc_packet_context_free(ctx->packet);
255     if (ctx->sock)
256       silc_socket_free(ctx->sock); /* Decrease reference counter */
257     silc_free(ctx);
258   }
259 }
260
261 /* Duplicate Command Context by adding reference counter. The context won't
262    be free'd untill it hits zero. */
263
264 SilcServerCommandContext 
265 silc_server_command_dup(SilcServerCommandContext ctx)
266 {
267   ctx->users++;
268   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
269                   ctx->users));
270   return ctx;
271 }
272
273 /* Add new pending command to be executed when reply to a command has been
274    received. The `reply_cmd' is the command that will call the `callback'
275    with `context' when reply has been received.  If `ident' is non-zero
276    the `callback' will be executed when received reply with command
277    identifier `ident'. */
278
279 void silc_server_command_pending(SilcServer server,
280                                  SilcCommand reply_cmd,
281                                  uint16 ident,
282                                  SilcServerPendingDestructor destructor,
283                                  SilcCommandCb callback,
284                                  void *context)
285 {
286   SilcServerCommandPending *reply;
287
288   reply = silc_calloc(1, sizeof(*reply));
289   reply->reply_cmd = reply_cmd;
290   reply->ident = ident;
291   reply->context = context;
292   reply->callback = callback;
293   reply->destructor = destructor;
294   silc_dlist_add(server->pending_commands, reply);
295 }
296
297 /* Deletes pending command by reply command type. */
298
299 void silc_server_command_pending_del(SilcServer server,
300                                      SilcCommand reply_cmd,
301                                      uint16 ident)
302 {
303   SilcServerCommandPending *r;
304
305   silc_dlist_start(server->pending_commands);
306   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
307     if (r->reply_cmd == reply_cmd && r->ident == ident) {
308       silc_dlist_del(server->pending_commands, r);
309       break;
310     }
311   }
312 }
313
314 /* Checks for pending commands and marks callbacks to be called from
315    the command reply function. Returns TRUE if there were pending command. */
316
317 int silc_server_command_pending_check(SilcServer server,
318                                       SilcServerCommandReplyContext ctx,
319                                       SilcCommand command, 
320                                       uint16 ident)
321 {
322   SilcServerCommandPending *r;
323
324   silc_dlist_start(server->pending_commands);
325   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
326     if (r->reply_cmd == command && r->ident == ident) {
327       ctx->context = r->context;
328       ctx->callback = r->callback;
329       ctx->destructor = r->destructor;
330       ctx->ident = ident;
331       return TRUE;
332     }
333   }
334
335   return FALSE;
336 }
337
338 /* Destructor function for pending callbacks. This is called when using
339    pending commands to free the context given for the pending command. */
340
341 static void silc_server_command_destructor(void *context)
342 {
343   silc_server_command_free((SilcServerCommandContext)context);
344 }
345
346 /* Sends simple status message as command reply packet */
347
348 static void 
349 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
350                                       SilcCommand command,
351                                       SilcCommandStatus status)
352 {
353   SilcBuffer buffer;
354
355   SILC_LOG_DEBUG(("Sending command status %d", status));
356
357   buffer = 
358     silc_command_reply_payload_encode_va(command, status, 
359                                          silc_command_get_ident(cmd->payload),
360                                          0);
361   silc_server_packet_send(cmd->server, cmd->sock,
362                           SILC_PACKET_COMMAND_REPLY, 0, 
363                           buffer->data, buffer->len, FALSE);
364   silc_buffer_free(buffer);
365 }
366
367 /* Sends command status reply with one extra argument. The argument
368    type must be sent as argument. */
369
370 static void 
371 silc_server_command_send_status_data(SilcServerCommandContext cmd,
372                                      SilcCommand command,
373                                      SilcCommandStatus status,
374                                      uint32 arg_type,
375                                      unsigned char *arg,
376                                      uint32 arg_len)
377 {
378   SilcBuffer buffer;
379
380   SILC_LOG_DEBUG(("Sending command status %d", status));
381
382   buffer = 
383     silc_command_reply_payload_encode_va(command, status, 
384                                          silc_command_get_ident(cmd->payload),
385                                          1, arg_type, arg, arg_len);
386   silc_server_packet_send(cmd->server, cmd->sock,
387                           SILC_PACKET_COMMAND_REPLY, 0, 
388                           buffer->data, buffer->len, FALSE);
389   silc_buffer_free(buffer);
390 }
391
392 /******************************************************************************
393
394                               WHOIS Functions
395
396 ******************************************************************************/
397
398 static int
399 silc_server_command_whois_parse(SilcServerCommandContext cmd,
400                                 SilcClientID ***client_id,
401                                 uint32 *client_id_count,
402                                 char **nickname,
403                                 char **server_name,
404                                 int *count,
405                                 SilcCommand command)
406 {
407   unsigned char *tmp;
408   uint32 len;
409   uint32 argc = silc_argument_get_arg_num(cmd->args);
410   int i, k;
411
412   /* If client ID is in the command it must be used instead of nickname */
413   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
414   if (!tmp) {
415     /* No ID, get the nickname@server string and parse it. */
416     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
417     if (tmp) {
418       if (strchr(tmp, '@')) {
419         len = strcspn(tmp, "@");
420         *nickname = silc_calloc(len + 1, sizeof(char));
421         memcpy(*nickname, tmp, len);
422         *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
423         memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
424       } else {
425         *nickname = strdup(tmp);
426       }
427     } else {
428       silc_server_command_send_status_reply(cmd, command,
429                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
430       return FALSE;
431     }
432   } else {
433     /* Command includes ID, we must use that.  Also check whether the command
434        has more than one ID set - take them all. */
435
436     *client_id = silc_calloc(1, sizeof(**client_id));
437     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
438     if ((*client_id)[0] == NULL) {
439       silc_free(*client_id);
440       return FALSE;
441     }
442     *client_id_count = 1;
443
444     /* Take all ID's from the command packet */
445     if (argc > 1) {
446       for (k = 1, i = 1; i < argc; i++) {
447         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
448         if (tmp) {
449           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
450                                     (*client_id_count + 1));
451           (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
452           if ((*client_id)[k] == NULL) {
453             /* Cleanup all and fail */
454             for (i = 0; i < *client_id_count; i++)
455               silc_free((*client_id)[i]);
456             silc_free(*client_id);
457             return FALSE;
458           }
459           (*client_id_count)++;
460           k++;
461         }
462       }
463     }
464
465     /* Command includes ID, use that */
466   }
467
468   /* Get the max count of reply messages allowed */
469   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
470   if (tmp)
471     *count = atoi(tmp);
472   else
473     *count = 0;
474
475   return TRUE;
476 }
477
478 static char
479 silc_server_command_whois_check(SilcServerCommandContext cmd,
480                                 SilcClientEntry *clients,
481                                 uint32 clients_count)
482 {
483   SilcServer server = cmd->server;
484   int i;
485   SilcClientEntry entry;
486
487   for (i = 0; i < clients_count; i++) {
488     entry = clients[i];
489
490     if (!entry || entry->data.registered == FALSE)
491       continue;
492
493     if (!entry->nickname || !entry->username || !entry->userinfo) {
494       SilcBuffer tmpbuf;
495       uint16 old_ident;
496
497       if (!entry->router)
498         continue;
499       
500       old_ident = silc_command_get_ident(cmd->payload);
501       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
502       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
503
504       /* Send WHOIS command */
505       silc_server_packet_send(server, entry->router->connection,
506                               SILC_PACKET_COMMAND, cmd->packet->flags,
507                               tmpbuf->data, tmpbuf->len, TRUE);
508       
509       /* Reprocess this packet after received reply */
510       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
511                                   silc_command_get_ident(cmd->payload),
512                                   silc_server_command_destructor,
513                                   silc_server_command_whois, 
514                                   silc_server_command_dup(cmd));
515       cmd->pending = TRUE;
516       
517       silc_command_set_ident(cmd->payload, old_ident);
518
519       silc_buffer_free(tmpbuf);
520       return FALSE;
521     }
522   }
523
524   return TRUE;
525 }
526
527 static void
528 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
529                                      SilcClientEntry *clients,
530                                      uint32 clients_count,
531                                      int count)
532 {
533   SilcServer server = cmd->server;
534   char *tmp;
535   int i, k, len;
536   SilcBuffer packet, idp, channels;
537   SilcClientEntry entry;
538   SilcCommandStatus status;
539   uint16 ident = silc_command_get_ident(cmd->payload);
540   char nh[128], uh[128];
541   unsigned char idle[4], mode[4];
542   SilcSocketConnection hsock;
543
544   len = 0;
545   for (i = 0; i < clients_count; i++)
546     if (clients[i]->data.registered)
547       len++;
548
549   status = SILC_STATUS_OK;
550   if (len > 1)
551     status = SILC_STATUS_LIST_START;
552
553   for (i = 0, k = 0; i < clients_count; i++) {
554     entry = clients[i];
555
556     if (entry->data.registered == FALSE) {
557       if (clients_count == 1) {
558         if (entry->nickname) {
559           silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
560                                                SILC_STATUS_ERR_NO_SUCH_NICK,
561                                                3, entry->nickname, 
562                                                strlen(entry->nickname));
563         } else {
564           SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
565           silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
566                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
567                                                2, idp->data, idp->len);
568           silc_buffer_free(idp);
569         }
570       }
571       continue;
572     }
573
574     if (k >= 1)
575       status = SILC_STATUS_LIST_ITEM;
576
577     if (clients_count > 1 && k == clients_count - 1)
578       status = SILC_STATUS_LIST_END;
579
580     if (count && k - 1 == count)
581       status = SILC_STATUS_LIST_END;
582
583     if (count && k - 1 > count)
584       break;
585
586     /* Sanity check, however these should never fail. However, as
587        this sanity check has been added here they have failed. */
588     if (!entry->nickname || !entry->username || !entry->userinfo)
589       continue;
590       
591     /* Send WHOIS reply */
592     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
593     tmp = silc_argument_get_first_arg(cmd->args, NULL);
594     
595     memset(uh, 0, sizeof(uh));
596     memset(nh, 0, sizeof(nh));
597     memset(idle, 0, sizeof(idle));
598     
599     strncat(nh, entry->nickname, strlen(entry->nickname));
600     if (!strchr(entry->nickname, '@')) {
601       strncat(nh, "@", 1);
602       if (entry->servername) {
603         strncat(nh, entry->servername, strlen(entry->servername));
604       } else {
605         len = entry->router ? strlen(entry->router->server_name) :
606           strlen(server->server_name);
607         strncat(nh, entry->router ? entry->router->server_name :
608                 server->server_name, len);
609       }
610     }
611       
612     strncat(uh, entry->username, strlen(entry->username));
613     if (!strchr(entry->username, '@')) {
614       strncat(uh, "@", 1);
615       hsock = (SilcSocketConnection)entry->connection;
616       len = strlen(hsock->hostname);
617       strncat(uh, hsock->hostname, len);
618     }
619
620     channels = silc_server_get_client_channel_list(server, entry);
621       
622     SILC_PUT32_MSB(entry->mode, mode);
623
624     if (entry->connection) {
625       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
626     }
627
628     if (channels)
629       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
630                                                     status, ident, 7, 
631                                                     2, idp->data, idp->len,
632                                                     3, nh, strlen(nh),
633                                                     4, uh, strlen(uh),
634                                                     5, entry->userinfo, 
635                                                     strlen(entry->userinfo),
636                                                     6, channels->data,
637                                                     channels->len,
638                                                     7, mode, 4,
639                                                     8, idle, 4);
640     else
641       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
642                                                     status, ident, 6, 
643                                                     2, idp->data, idp->len,
644                                                     3, nh, strlen(nh),
645                                                     4, uh, strlen(uh),
646                                                     5, entry->userinfo, 
647                                                     strlen(entry->userinfo),
648                                                     7, mode, 4,
649                                                     8, idle, 4);
650     
651     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
652                             0, packet->data, packet->len, FALSE);
653     
654     silc_buffer_free(packet);
655     silc_buffer_free(idp);
656     if (channels)
657       silc_buffer_free(channels);
658
659     k++;
660   }
661 }
662
663 static int
664 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
665 {
666   SilcServer server = cmd->server;
667   char *nick = NULL, *server_name = NULL;
668   int count = 0;
669   SilcClientEntry *clients = NULL, entry;
670   SilcClientID **client_id = NULL;
671   uint32 client_id_count = 0, clients_count = 0;
672   int i, ret = 0;
673
674   /* Protocol dictates that we must always send the received WHOIS request
675      to our router if we are normal server, so let's do it now unless we
676      are standalone. We will not send any replies to the client until we
677      have received reply from the router. */
678   if (server->server_type == SILC_SERVER && !cmd->pending && 
679       !server->standalone) {
680     SilcBuffer tmpbuf;
681     uint16 old_ident;
682
683     old_ident = silc_command_get_ident(cmd->payload);
684     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
685     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
686
687     /* Send WHOIS command to our router */
688     silc_server_packet_send(server, (SilcSocketConnection)
689                             server->router->connection,
690                             SILC_PACKET_COMMAND, cmd->packet->flags,
691                             tmpbuf->data, tmpbuf->len, TRUE);
692
693     /* Reprocess this packet after received reply from router */
694     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
695                                 silc_command_get_ident(cmd->payload),
696                                 silc_server_command_destructor,
697                                 silc_server_command_whois,
698                                 silc_server_command_dup(cmd));
699     cmd->pending = TRUE;
700
701     silc_command_set_ident(cmd->payload, old_ident);
702
703     silc_buffer_free(tmpbuf);
704     ret = -1;
705     goto out;
706   }
707
708   /* We are ready to process the command request. Let's search for the
709      requested client and send reply to the requesting client. */
710
711   /* Parse the whois request */
712   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
713                                        &nick, &server_name, &count,
714                                        SILC_COMMAND_WHOIS))
715     return 0;
716
717   /* Get all clients matching that ID or nickname from local list */
718   if (client_id_count) {
719     /* Check all Client ID's received in the command packet */
720     for (i = 0; i < client_id_count; i++) {
721       entry = silc_idlist_find_client_by_id(server->local_list, 
722                                             client_id[i], NULL);
723       if (entry) {
724         clients = silc_realloc(clients, sizeof(*clients) * 
725                                (clients_count + 1));
726         clients[clients_count++] = entry;
727       }
728     }
729   } else {
730     if (!silc_idlist_get_clients_by_hash(server->local_list, 
731                                          nick, server->md5hash,
732                                          &clients, &clients_count))
733       silc_idlist_get_clients_by_nickname(server->local_list, 
734                                           nick, server_name,
735                                           &clients, &clients_count);
736   }
737   
738   /* Check global list as well */
739   if (client_id_count) {
740     /* Check all Client ID's received in the command packet */
741     for (i = 0; i < client_id_count; i++) {
742       entry = silc_idlist_find_client_by_id(server->global_list, 
743                                             client_id[i], NULL);
744       if (entry) {
745         clients = silc_realloc(clients, sizeof(*clients) * 
746                                (clients_count + 1));
747         clients[clients_count++] = entry;
748       }
749     }
750   } else {
751     if (!silc_idlist_get_clients_by_hash(server->global_list, 
752                                          nick, server->md5hash,
753                                          &clients, &clients_count))
754       silc_idlist_get_clients_by_nickname(server->global_list, 
755                                           nick, server_name,
756                                           &clients, &clients_count);
757   }
758   
759   if (!clients) {
760     /* Such client(s) really does not exist in the SILC network. */
761     if (!client_id_count) {
762       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
763                                            SILC_STATUS_ERR_NO_SUCH_NICK,
764                                            3, nick, strlen(nick));
765     } else {
766       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
767       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
768                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
769                                            2, idp->data, idp->len);
770       silc_buffer_free(idp);
771     }
772     goto out;
773   }
774
775   /* Router always finds the client entry if it exists in the SILC network.
776      However, it might be incomplete entry and does not include all the
777      mandatory fields that WHOIS command reply requires. Check for these and
778      make query from the server who owns the client if some fields are 
779      missing. */
780   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
781     ret = -1;
782     goto out;
783   }
784
785   /* Send the command reply to the client */
786   silc_server_command_whois_send_reply(cmd, clients, clients_count,
787                                        count);
788
789  out:
790   if (client_id_count) {
791     for (i = 0; i < client_id_count; i++)
792       silc_free(client_id[i]);
793     silc_free(client_id);
794   }
795   if (clients)
796     silc_free(clients);
797   if (nick)
798     silc_free(nick);
799   if (server_name)
800     silc_free(server_name);
801
802   return ret;
803 }
804
805 static int
806 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
807 {
808   SilcServer server = cmd->server;
809   char *nick = NULL, *server_name = NULL;
810   int count = 0;
811   SilcClientEntry *clients = NULL, entry;
812   SilcClientID **client_id = NULL;
813   uint32 client_id_count = 0, clients_count = 0;
814   int i, ret = 0;
815
816   /* Parse the whois request */
817   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
818                                        &nick, &server_name, &count,
819                                        SILC_COMMAND_WHOIS))
820     return 0;
821
822   /* Process the command request. Let's search for the requested client and
823      send reply to the requesting server. */
824
825   if (client_id_count) {
826     /* Check all Client ID's received in the command packet */
827     for (i = 0; i < client_id_count; i++) {
828       entry = silc_idlist_find_client_by_id(server->local_list, 
829                                             client_id[i], NULL);
830       if (entry) {
831         clients = silc_realloc(clients, sizeof(*clients) * 
832                                (clients_count + 1));
833         clients[clients_count++] = entry;
834       }
835     }
836   } else {
837     if (!silc_idlist_get_clients_by_hash(server->local_list, 
838                                          nick, server->md5hash,
839                                          &clients, &clients_count))
840       silc_idlist_get_clients_by_nickname(server->local_list, 
841                                           nick, server_name,
842                                           &clients, &clients_count);
843   }
844   
845   /* If we are router we will check our global list as well. */
846   if (server->server_type == SILC_ROUTER) {
847     if (client_id_count) {
848       /* Check all Client ID's received in the command packet */
849       for (i = 0; i < client_id_count; i++) {
850         entry = silc_idlist_find_client_by_id(server->global_list, 
851                                               client_id[i], NULL);
852         if (entry) {
853           clients = silc_realloc(clients, sizeof(*clients) * 
854                                  (clients_count + 1));
855           clients[clients_count++] = entry;
856         }
857       }
858     } else {
859       if (!silc_idlist_get_clients_by_hash(server->global_list, 
860                                            nick, server->md5hash,
861                                            &clients, &clients_count))
862         silc_idlist_get_clients_by_nickname(server->global_list, 
863                                             nick, server_name,
864                                             &clients, &clients_count);
865     }
866   }
867
868   if (!clients) {
869     /* Such a client really does not exist in the SILC network. */
870     if (!client_id_count) {
871       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
872                                            SILC_STATUS_ERR_NO_SUCH_NICK,
873                                            3, nick, strlen(nick));
874     } else {
875       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
876       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
877                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
878                                            2, idp->data, idp->len);
879       silc_buffer_free(idp);
880     }
881     goto out;
882   }
883
884   /* Router always finds the client entry if it exists in the SILC network.
885      However, it might be incomplete entry and does not include all the
886      mandatory fields that WHOIS command reply requires. Check for these and
887      make query from the server who owns the client if some fields are 
888      missing. */
889   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
890     ret = -1;
891     goto out;
892   }
893
894   /* Send the command reply to the client */
895   silc_server_command_whois_send_reply(cmd, clients, clients_count,
896                                        count);
897
898  out:
899   if (client_id_count) {
900     for (i = 0; i < client_id_count; i++)
901       silc_free(client_id[i]);
902     silc_free(client_id);
903   }
904   if (clients)
905     silc_free(clients);
906   if (nick)
907     silc_free(nick);
908   if (server_name)
909     silc_free(server_name);
910
911   return ret;
912 }
913
914 /* Server side of command WHOIS. Processes user's query and sends found 
915    results as command replies back to the client. */
916
917 SILC_SERVER_CMD_FUNC(whois)
918 {
919   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
920   int ret = 0;
921
922   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
923
924   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
925     ret = silc_server_command_whois_from_client(cmd);
926   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
927            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
928     ret = silc_server_command_whois_from_server(cmd);
929
930   if (!ret)
931     silc_server_command_free(cmd);
932 }
933
934 /******************************************************************************
935
936                               WHOWAS Functions
937
938 ******************************************************************************/
939
940 static int
941 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
942                                  char **nickname,
943                                  char **server_name,
944                                  int *count)
945 {
946   unsigned char *tmp;
947   uint32 len;
948
949   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
950   if (!tmp) {
951     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
952                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
953     return FALSE;
954   }
955
956   /* Get the nickname@server string and parse it. */
957   if (strchr(tmp, '@')) {
958     len = strcspn(tmp, "@");
959     *nickname = silc_calloc(len + 1, sizeof(char));
960     memcpy(*nickname, tmp, len);
961     *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
962     memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
963   } else {
964     *nickname = strdup(tmp);
965   }
966   /* Get the max count of reply messages allowed */
967   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
968   if (tmp)
969     *count = atoi(tmp);
970   else
971     *count = 0;
972
973   return TRUE;
974 }
975
976 static char
977 silc_server_command_whowas_check(SilcServerCommandContext cmd,
978                                  SilcClientEntry *clients,
979                                  uint32 clients_count)
980 {
981   SilcServer server = cmd->server;
982   int i;
983   SilcClientEntry entry;
984
985   for (i = 0; i < clients_count; i++) {
986     entry = clients[i];
987
988     if (!entry->nickname || !entry->username) {
989       SilcBuffer tmpbuf;
990       uint16 old_ident;
991
992       if (!entry->router)
993         continue;
994       
995       old_ident = silc_command_get_ident(cmd->payload);
996       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
997       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
998
999       /* Send WHOWAS command */
1000       silc_server_packet_send(server, entry->router->connection,
1001                               SILC_PACKET_COMMAND, cmd->packet->flags,
1002                               tmpbuf->data, tmpbuf->len, TRUE);
1003       
1004       /* Reprocess this packet after received reply */
1005       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1006                                   silc_command_get_ident(cmd->payload),
1007                                   silc_server_command_destructor,
1008                                   silc_server_command_whowas, 
1009                                   silc_server_command_dup(cmd));
1010       cmd->pending = TRUE;
1011       
1012       silc_command_set_ident(cmd->payload, old_ident);
1013
1014       silc_buffer_free(tmpbuf);
1015       return FALSE;
1016     }
1017   }
1018
1019   return TRUE;
1020 }
1021
1022 static void
1023 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1024                                       SilcClientEntry *clients,
1025                                       uint32 clients_count)
1026 {
1027   SilcServer server = cmd->server;
1028   char *tmp;
1029   int i, count = 0, len;
1030   SilcBuffer packet, idp;
1031   SilcClientEntry entry = NULL;
1032   SilcCommandStatus status;
1033   uint16 ident = silc_command_get_ident(cmd->payload);
1034   char found = FALSE;
1035   char nh[256], uh[256];
1036
1037   status = SILC_STATUS_OK;
1038   if (clients_count > 1)
1039     status = SILC_STATUS_LIST_START;
1040
1041   for (i = 0; i < clients_count; i++) {
1042     entry = clients[i];
1043
1044     /* We will take only clients that are not valid anymore. They are the
1045        ones that are not registered anymore but still have a ID. They
1046        have disconnected us, and thus valid for WHOWAS. */
1047     if (entry->data.registered == TRUE)
1048       continue;
1049     if (entry->id == NULL)
1050       continue;
1051
1052     if (count && i - 1 == count)
1053       break;
1054
1055     found = TRUE;
1056
1057     if (clients_count > 2)
1058       status = SILC_STATUS_LIST_ITEM;
1059
1060     if (clients_count > 1 && i == clients_count - 1)
1061       status = SILC_STATUS_LIST_END;
1062
1063     /* Sanity check, however these should never fail. However, as
1064        this sanity check has been added here they have failed. */
1065     if (!entry->nickname || !entry->username)
1066       continue;
1067       
1068     /* Send WHOWAS reply */
1069     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1070     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1071     
1072     memset(uh, 0, sizeof(uh));
1073     memset(nh, 0, sizeof(nh));
1074
1075     strncat(nh, entry->nickname, strlen(entry->nickname));
1076     if (!strchr(entry->nickname, '@')) {
1077       strncat(nh, "@", 1);
1078       if (entry->servername) {
1079         strncat(nh, entry->servername, strlen(entry->servername));
1080       } else {
1081         len = entry->router ? strlen(entry->router->server_name) :
1082           strlen(server->server_name);
1083         strncat(nh, entry->router ? entry->router->server_name :
1084                 server->server_name, len);
1085       }
1086     }
1087       
1088     strncat(uh, entry->username, strlen(entry->username));
1089     if (!strchr(entry->username, '@')) {
1090       strncat(uh, "@", 1);
1091       strcat(uh, "*private*");
1092     }
1093       
1094     if (entry->userinfo)
1095       packet = 
1096         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1097                                              status, ident, 4, 
1098                                              2, idp->data, idp->len,
1099                                              3, nh, strlen(nh),
1100                                              4, uh, strlen(uh),
1101                                              5, entry->userinfo, 
1102                                              strlen(entry->userinfo));
1103     else
1104       packet = 
1105         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1106                                              status, ident, 3, 
1107                                              2, idp->data, idp->len,
1108                                              3, nh, strlen(nh),
1109                                              4, uh, strlen(uh));
1110
1111     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1112                             0, packet->data, packet->len, FALSE);
1113     
1114     silc_buffer_free(packet);
1115     silc_buffer_free(idp);
1116   }
1117
1118   if (found == FALSE && entry)
1119     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1120                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1121                                          3, entry->nickname, 
1122                                          strlen(entry->nickname));
1123 }
1124
1125 static int
1126 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1127 {
1128   SilcServer server = cmd->server;
1129   char *nick = NULL, *server_name = NULL;
1130   int count = 0;
1131   SilcClientEntry *clients = NULL;
1132   uint32 clients_count = 0;
1133   int ret = 0;
1134
1135   /* Protocol dictates that we must always send the received WHOWAS request
1136      to our router if we are normal server, so let's do it now unless we
1137      are standalone. We will not send any replies to the client until we
1138      have received reply from the router. */
1139   if (server->server_type == SILC_SERVER && 
1140       !cmd->pending && !server->standalone) {
1141     SilcBuffer tmpbuf;
1142     uint16 old_ident;
1143
1144     old_ident = silc_command_get_ident(cmd->payload);
1145     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1146     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1147
1148     /* Send WHOWAS command to our router */
1149     silc_server_packet_send(server, (SilcSocketConnection)
1150                             server->router->connection,
1151                             SILC_PACKET_COMMAND, cmd->packet->flags,
1152                             tmpbuf->data, tmpbuf->len, TRUE);
1153
1154     /* Reprocess this packet after received reply from router */
1155     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1156                                 silc_command_get_ident(cmd->payload),
1157                                 silc_server_command_destructor,
1158                                 silc_server_command_whowas,
1159                                 silc_server_command_dup(cmd));
1160     cmd->pending = TRUE;
1161
1162     silc_command_set_ident(cmd->payload, old_ident);
1163
1164     silc_buffer_free(tmpbuf);
1165     ret = -1;
1166     goto out;
1167   }
1168
1169   /* We are ready to process the command request. Let's search for the
1170      requested client and send reply to the requesting client. */
1171
1172   /* Parse the whowas request */
1173   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1174     return 0;
1175
1176   /* Get all clients matching that nickname from local list */
1177   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1178                                            nick, server_name,
1179                                            &clients, &clients_count))
1180     silc_idlist_get_clients_by_hash(server->local_list, 
1181                                     nick, server->md5hash,
1182                                     &clients, &clients_count);
1183   
1184   /* Check global list as well */
1185   if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1186                                            nick, server_name,
1187                                            &clients, &clients_count))
1188     silc_idlist_get_clients_by_hash(server->global_list, 
1189                                     nick, server->md5hash,
1190                                     &clients, &clients_count);
1191   
1192   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1193     ret = -1;
1194     goto out;
1195   }
1196
1197   /* Send the command reply to the client */
1198   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1199
1200  out:
1201   if (clients)
1202     silc_free(clients);
1203   if (nick)
1204     silc_free(nick);
1205   if (server_name)
1206     silc_free(server_name);
1207
1208   return ret;
1209 }
1210
1211 static int
1212 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1213 {
1214   SilcServer server = cmd->server;
1215   char *nick = NULL, *server_name = NULL;
1216   int count = 0;
1217   SilcClientEntry *clients = NULL;
1218   uint32 clients_count = 0;
1219   int ret = 0;
1220
1221   /* Parse the whowas request */
1222   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1223     return 0;
1224
1225   /* Process the command request. Let's search for the requested client and
1226      send reply to the requesting server. */
1227
1228   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1229                                            nick, server_name,
1230                                            &clients, &clients_count))
1231     silc_idlist_get_clients_by_hash(server->local_list, 
1232                                     nick, server->md5hash,
1233                                     &clients, &clients_count);
1234   
1235   /* If we are router we will check our global list as well. */
1236   if (server->server_type == SILC_ROUTER) {
1237     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1238                                              nick, server_name,
1239                                              &clients, &clients_count))
1240       silc_idlist_get_clients_by_hash(server->global_list, 
1241                                       nick, server->md5hash,
1242                                       &clients, &clients_count);
1243   }
1244
1245   if (!clients) {
1246     /* Such a client really does not exist in the SILC network. */
1247     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1248                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1249                                          3, nick, strlen(nick));
1250     goto out;
1251   }
1252
1253   /* Send the command reply to the client */
1254   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1255
1256  out:
1257   if (clients)
1258     silc_free(clients);
1259   if (nick)
1260     silc_free(nick);
1261   if (server_name)
1262     silc_free(server_name);
1263
1264   return ret;
1265 }
1266
1267 /* Server side of command WHOWAS. */
1268
1269 SILC_SERVER_CMD_FUNC(whowas)
1270 {
1271   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1272   int ret = 0;
1273
1274   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1275
1276   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1277     ret = silc_server_command_whowas_from_client(cmd);
1278   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1279            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1280     ret = silc_server_command_whowas_from_server(cmd);
1281
1282   if (!ret)
1283     silc_server_command_free(cmd);
1284 }
1285
1286 /******************************************************************************
1287
1288                               IDENTIFY Functions
1289
1290 ******************************************************************************/
1291
1292 /* Checks that all mandatory fields are present. If not then send WHOIS 
1293    request to the server who owns the client. We use WHOIS because we want
1294    to get as much information as possible at once. */
1295
1296 static char
1297 silc_server_command_identify_check(SilcServerCommandContext cmd,
1298                                    SilcClientEntry *clients,
1299                                    uint32 clients_count)
1300 {
1301   SilcServer server = cmd->server;
1302   int i;
1303   SilcClientEntry entry;
1304
1305   for (i = 0; i < clients_count; i++) {
1306     entry = clients[i];
1307
1308     if (!entry || entry->data.registered == FALSE)
1309       continue;
1310
1311     if (!entry->nickname) {
1312       SilcBuffer tmpbuf;
1313       uint16 old_ident;
1314       
1315       if (!entry->router)
1316         continue;
1317       
1318       old_ident = silc_command_get_ident(cmd->payload);
1319       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1320       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1321       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1322       
1323       /* Send WHOIS request. We send WHOIS since we're doing the requesting
1324          now anyway so make it a good one. */
1325       silc_server_packet_send(server, entry->router->connection,
1326                               SILC_PACKET_COMMAND, cmd->packet->flags,
1327                               tmpbuf->data, tmpbuf->len, TRUE);
1328       
1329       /* Reprocess this packet after received reply */
1330       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1331                                   silc_command_get_ident(cmd->payload),
1332                                   silc_server_command_destructor,
1333                                   silc_server_command_identify,
1334                                   silc_server_command_dup(cmd));
1335
1336       cmd->pending = TRUE;
1337       
1338       /* Put old data back to the Command Payload we just changed */
1339       silc_command_set_ident(cmd->payload, old_ident);
1340       silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1341
1342       silc_buffer_free(tmpbuf);
1343       return FALSE;
1344     }
1345   }
1346
1347   return TRUE;
1348 }
1349
1350 static void
1351 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1352                                         SilcClientEntry *clients,
1353                                         uint32 clients_count,
1354                                         int count)
1355 {
1356   SilcServer server = cmd->server;
1357   char *tmp;
1358   int i, k, len;
1359   SilcBuffer packet, idp;
1360   SilcClientEntry entry;
1361   SilcCommandStatus status;
1362   uint16 ident = silc_command_get_ident(cmd->payload);
1363   char nh[256], uh[256];
1364   SilcSocketConnection hsock;
1365
1366   len = 0;
1367   for (i = 0; i < clients_count; i++)
1368     if (clients[i]->data.registered)
1369       len++;
1370
1371   status = SILC_STATUS_OK;
1372   if (len > 1)
1373     status = SILC_STATUS_LIST_START;
1374
1375   for (i = 0, k = 0; i < clients_count; i++) {
1376     entry = clients[i];
1377
1378     if (entry->data.registered == FALSE) {
1379       if (clients_count == 1) {
1380         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1381         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1382                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1383                                              2, idp->data, idp->len);
1384         silc_buffer_free(idp);
1385       }
1386       continue;
1387     }
1388
1389     if (k >= 1)
1390       status = SILC_STATUS_LIST_ITEM;
1391
1392     if (clients_count > 1 && k == clients_count - 1)
1393       status = SILC_STATUS_LIST_END;
1394
1395     if (count && k - 1 == count)
1396       status = SILC_STATUS_LIST_END;
1397
1398     if (count && k - 1 > count)
1399       break;
1400
1401     /* Send IDENTIFY reply */
1402     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1403     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1404     
1405     memset(uh, 0, sizeof(uh));
1406     memset(nh, 0, sizeof(nh));
1407       
1408     strncat(nh, entry->nickname, strlen(entry->nickname));
1409     if (!strchr(entry->nickname, '@')) {
1410       strncat(nh, "@", 1);
1411       if (entry->servername) {
1412         strncat(nh, entry->servername, strlen(entry->servername));
1413       } else {
1414         len = entry->router ? strlen(entry->router->server_name) :
1415           strlen(server->server_name);
1416         strncat(nh, entry->router ? entry->router->server_name :
1417                 server->server_name, len);
1418       }
1419     }
1420       
1421     if (!entry->username) {
1422       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1423                                                     status, ident, 2,
1424                                                     2, idp->data, idp->len, 
1425                                                     3, nh, strlen(nh));
1426     } else {
1427       strncat(uh, entry->username, strlen(entry->username));
1428       if (!strchr(entry->username, '@')) {
1429         strncat(uh, "@", 1);
1430         hsock = (SilcSocketConnection)entry->connection;
1431         len = strlen(hsock->hostname);
1432         strncat(uh, hsock->hostname, len);
1433       }
1434       
1435       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1436                                                     status, ident, 3,
1437                                                     2, idp->data, idp->len, 
1438                                                     3, nh, strlen(nh),
1439                                                     4, uh, strlen(uh));
1440     }
1441       
1442     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1443                             0, packet->data, packet->len, FALSE);
1444     
1445     silc_buffer_free(packet);
1446     silc_buffer_free(idp);
1447
1448     k++;
1449   }
1450 }
1451
1452 static int
1453 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1454 {
1455   SilcServer server = cmd->server;
1456   char *nick = NULL, *server_name = NULL;
1457   int count = 0;
1458   SilcClientEntry *clients = NULL, entry;
1459   SilcClientID **client_id = NULL;
1460   uint32 client_id_count = 0, clients_count = 0;
1461   int i, ret = 0;
1462
1463   /* Protocol dictates that we must always send the received IDENTIFY request
1464      to our router if we are normal server, so let's do it now unless we
1465      are standalone. We will not send any replies to the client until we
1466      have received reply from the router. */
1467   if (server->server_type == SILC_SERVER && 
1468       !cmd->pending && !server->standalone) {
1469     SilcBuffer tmpbuf;
1470     uint16 old_ident;
1471
1472     old_ident = silc_command_get_ident(cmd->payload);
1473     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1474     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1475
1476     /* Send IDENTIFY command to our router */
1477     silc_server_packet_send(server, (SilcSocketConnection)
1478                             server->router->connection,
1479                             SILC_PACKET_COMMAND, cmd->packet->flags,
1480                             tmpbuf->data, tmpbuf->len, TRUE);
1481
1482     /* Reprocess this packet after received reply from router */
1483     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1484                                 silc_command_get_ident(cmd->payload),
1485                                 silc_server_command_destructor,
1486                                 silc_server_command_identify,
1487                                 silc_server_command_dup(cmd));
1488     cmd->pending = TRUE;
1489
1490     silc_command_set_ident(cmd->payload, old_ident);
1491
1492     silc_buffer_free(tmpbuf);
1493     ret = -1;
1494     goto out;
1495   }
1496
1497   /* We are ready to process the command request. Let's search for the
1498      requested client and send reply to the requesting client. */
1499
1500   /* Parse the IDENTIFY request */
1501   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1502                                        &nick, &server_name, &count,
1503                                        SILC_COMMAND_IDENTIFY))
1504     return 0;
1505
1506   /* Get all clients matching that ID or nickname from local list */
1507   if (client_id_count) { 
1508     /* Check all Client ID's received in the command packet */
1509     for (i = 0; i < client_id_count; i++) {
1510       entry = silc_idlist_find_client_by_id(server->local_list, 
1511                                             client_id[i], NULL);
1512       if (entry) {
1513         clients = silc_realloc(clients, sizeof(*clients) * 
1514                                (clients_count + 1));
1515         clients[clients_count++] = entry;
1516       }
1517     }
1518   } else {
1519     if (!silc_idlist_get_clients_by_hash(server->local_list, 
1520                                          nick, server->md5hash,
1521                                          &clients, &clients_count))
1522       silc_idlist_get_clients_by_nickname(server->local_list, 
1523                                           nick, server_name,
1524                                           &clients, &clients_count);
1525   }
1526   
1527   /* Check global list as well */
1528   if (client_id_count) {
1529     /* Check all Client ID's received in the command packet */
1530     for (i = 0; i < client_id_count; i++) {
1531       entry = silc_idlist_find_client_by_id(server->global_list, 
1532                                             client_id[i], NULL);
1533       if (entry) {
1534         clients = silc_realloc(clients, sizeof(*clients) * 
1535                                (clients_count + 1));
1536         clients[clients_count++] = entry;
1537       }
1538     }
1539   } else {
1540     if (!silc_idlist_get_clients_by_hash(server->global_list, 
1541                                          nick, server->md5hash,
1542                                          &clients, &clients_count))
1543       silc_idlist_get_clients_by_nickname(server->global_list, 
1544                                           nick, server_name,
1545                                           &clients, &clients_count);
1546   }
1547   
1548   if (!clients) {
1549     /* Such a client really does not exist in the SILC network. */
1550     if (!client_id_count) {
1551       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1552                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1553                                            3, nick, strlen(nick));
1554     } else {
1555       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1556       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1557                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1558                                            2, idp->data, idp->len);
1559       silc_buffer_free(idp);
1560     }
1561     goto out;
1562   }
1563
1564   /* Check that all mandatory fields are present and request those data
1565      from the server who owns the client if necessary. */
1566   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1567     ret = -1;
1568     goto out;
1569   }
1570
1571   /* Send the command reply to the client */
1572   silc_server_command_identify_send_reply(cmd, clients, clients_count,
1573                                           count);
1574
1575  out:
1576   if (client_id_count) {
1577     for (i = 0; i < client_id_count; i++)
1578       silc_free(client_id[i]);
1579     silc_free(client_id);
1580   }
1581   if (clients)
1582     silc_free(clients);
1583   if (nick)
1584     silc_free(nick);
1585   if (server_name)
1586     silc_free(server_name);
1587
1588   return ret;
1589 }
1590
1591 static int
1592 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1593 {
1594   SilcServer server = cmd->server;
1595   char *nick = NULL, *server_name = NULL;
1596   int count = 0;
1597   SilcClientEntry *clients = NULL, entry;
1598   SilcClientID **client_id = NULL;
1599   uint32 client_id_count = 0, clients_count = 0;
1600   int i, ret = 0;
1601
1602   /* Parse the IDENTIFY request */
1603   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1604                                        &nick, &server_name, &count,
1605                                        SILC_COMMAND_IDENTIFY))
1606     return 0;
1607
1608   /* Process the command request. Let's search for the requested client and
1609      send reply to the requesting server. */
1610
1611   if (client_id_count) {
1612     /* Check all Client ID's received in the command packet */
1613     for (i = 0; i < client_id_count; i++) {
1614       entry = silc_idlist_find_client_by_id(server->local_list, 
1615                                             client_id[i], NULL);
1616       if (entry) {
1617         clients = silc_realloc(clients, sizeof(*clients) * 
1618                                (clients_count + 1));
1619         clients[clients_count++] = entry;
1620       }
1621     }
1622   } else {
1623     if (!silc_idlist_get_clients_by_hash(server->local_list, 
1624                                          nick, server->md5hash,
1625                                          &clients, &clients_count))
1626       silc_idlist_get_clients_by_nickname(server->local_list, 
1627                                           nick, server_name,
1628                                           &clients, &clients_count);
1629   }
1630   
1631   /* If we are router we will check our global list as well. */
1632   if (server->server_type == SILC_ROUTER) {
1633     if (client_id_count) {
1634       /* Check all Client ID's received in the command packet */
1635       for (i = 0; i < client_id_count; i++) {
1636         entry = silc_idlist_find_client_by_id(server->global_list, 
1637                                               client_id[i], NULL);
1638         if (entry) {
1639           clients = silc_realloc(clients, sizeof(*clients) * 
1640                                  (clients_count + 1));
1641           clients[clients_count++] = entry;
1642         }
1643       }
1644     } else {
1645       if (!silc_idlist_get_clients_by_hash(server->global_list, 
1646                                            nick, server->md5hash,
1647                                            &clients, &clients_count))
1648         silc_idlist_get_clients_by_nickname(server->global_list, 
1649                                             nick, server_name,
1650                                             &clients, &clients_count);
1651     }
1652   }
1653
1654   if (!clients) {
1655     /* Such a client really does not exist in the SILC network. */
1656     if (!client_id_count) {
1657       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1658                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1659                                            3, nick, strlen(nick));
1660     } else {
1661       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1662       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1663                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1664                                            2, idp->data, idp->len);
1665       silc_buffer_free(idp);
1666     }
1667     goto out;
1668   }
1669
1670   /* Check that all mandatory fields are present and request those data
1671      from the server who owns the client if necessary. */
1672   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1673     ret = -1;
1674     goto out;
1675   }
1676
1677   /* Send the command reply */
1678   silc_server_command_identify_send_reply(cmd, clients, clients_count, count);
1679
1680  out:
1681   if (client_id_count) {
1682     for (i = 0; i < client_id_count; i++)
1683       silc_free(client_id[i]);
1684     silc_free(client_id);
1685   }
1686   if (clients)
1687     silc_free(clients);
1688   if (nick)
1689     silc_free(nick);
1690   if (server_name)
1691     silc_free(server_name);
1692
1693   return ret;
1694 }
1695
1696 SILC_SERVER_CMD_FUNC(identify)
1697 {
1698   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1699   int ret = 0;
1700
1701   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1702
1703   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1704     ret = silc_server_command_identify_from_client(cmd);
1705   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1706            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1707     ret = silc_server_command_identify_from_server(cmd);
1708
1709   if (!ret)
1710     silc_server_command_free(cmd);
1711 }
1712
1713 /* Checks string for bad characters and returns TRUE if they are found. */
1714
1715 static int silc_server_command_bad_chars(char *nick)
1716 {
1717   if (strchr(nick, '\\')) return TRUE;
1718   if (strchr(nick, '\"')) return TRUE;
1719   if (strchr(nick, '´')) return TRUE;
1720   if (strchr(nick, '`')) return TRUE;
1721   if (strchr(nick, '\'')) return TRUE;
1722   if (strchr(nick, '*')) return TRUE;
1723   if (strchr(nick, '/')) return TRUE;
1724   if (strchr(nick, '@')) return TRUE;
1725
1726   return FALSE;
1727 }
1728
1729 /* Server side of command NICK. Sets nickname for user. Setting
1730    nickname causes generation of a new client ID for the client. The
1731    new client ID is sent to the client after changing the nickname. */
1732
1733 SILC_SERVER_CMD_FUNC(nick)
1734 {
1735   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1736   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1737   SilcServer server = cmd->server;
1738   SilcBuffer packet, nidp, oidp;
1739   SilcClientID *new_id;
1740   char *nick;
1741   uint16 ident = silc_command_get_ident(cmd->payload);
1742
1743   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1744     goto out;
1745
1746   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1747
1748   /* Check nickname */
1749   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1750   if (silc_server_command_bad_chars(nick) == TRUE) {
1751     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1752                                           SILC_STATUS_ERR_BAD_NICKNAME);
1753     goto out;
1754   }
1755
1756   if (strlen(nick) > 128)
1757     nick[127] = '\0';
1758
1759   /* Create new Client ID */
1760   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1761                            cmd->server->md5hash, nick,
1762                            &new_id);
1763
1764   /* Send notify about nickname change to our router. We send the new
1765      ID and ask to replace it with the old one. If we are router the
1766      packet is broadcasted. Send NICK_CHANGE notify. */
1767   if (!server->standalone)
1768     silc_server_send_notify_nick_change(server, server->router->connection, 
1769                                         server->server_type == SILC_SERVER ? 
1770                                         FALSE : TRUE, client->id,
1771                                         new_id);
1772
1773   /* Remove old cache entry */
1774   silc_idcache_del_by_context(server->local_list->clients, client);
1775
1776   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1777
1778   /* Free old ID */
1779   if (client->id)
1780     silc_free(client->id);
1781
1782   /* Save the nickname as this client is our local client */
1783   if (client->nickname)
1784     silc_free(client->nickname);
1785
1786   client->nickname = strdup(nick);
1787   client->id = new_id;
1788
1789   /* Update client cache */
1790   silc_idcache_add(server->local_list->clients, client->nickname, 
1791                    client->id, (void *)client, FALSE);
1792
1793   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1794
1795   /* Send NICK_CHANGE notify to the client's channels */
1796   silc_server_send_notify_on_channels(server, NULL, client, 
1797                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1798                                       oidp->data, oidp->len, 
1799                                       nidp->data, nidp->len);
1800
1801   /* Send the new Client ID as reply command back to client */
1802   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1803                                                 SILC_STATUS_OK, ident, 1, 
1804                                                 2, nidp->data, nidp->len);
1805   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1806                           0, packet->data, packet->len, FALSE);
1807
1808   silc_buffer_free(packet);
1809   silc_buffer_free(nidp);
1810   silc_buffer_free(oidp);
1811   
1812  out:
1813   silc_server_command_free(cmd);
1814 }
1815
1816 /* Sends the LIST command reply */
1817
1818 static void
1819 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1820                                     SilcChannelEntry *lch, 
1821                                     uint32 lch_count,
1822                                     SilcChannelEntry *gch,
1823                                     uint32 gch_count)
1824 {
1825   int i;
1826   SilcBuffer packet, idp;
1827   SilcChannelEntry entry;
1828   SilcCommandStatus status;
1829   uint16 ident = silc_command_get_ident(cmd->payload);
1830   char *topic;
1831   unsigned char usercount[4];
1832   uint32 users;
1833
1834   for (i = 0; i < lch_count; i++)
1835     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1836       lch[i] = NULL;
1837   for (i = 0; i < gch_count; i++)
1838     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1839       gch[i] = NULL;
1840
1841   status = SILC_STATUS_OK;
1842   if ((lch_count + gch_count) > 1)
1843     status = SILC_STATUS_LIST_START;
1844
1845   /* Local list */
1846   for (i = 0; i < lch_count; i++) {
1847     entry = lch[i];
1848
1849     if (!entry)
1850       continue;
1851
1852     if (i >= 1)
1853       status = SILC_STATUS_LIST_ITEM;
1854
1855     if (i == lch_count - 1 && gch_count)
1856       break;
1857     if (lch_count > 1 && i == lch_count - 1)
1858       status = SILC_STATUS_LIST_END;
1859
1860     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1861
1862     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1863       topic = "*private*";
1864       memset(usercount, 0, sizeof(usercount));
1865     } else {
1866       topic = entry->topic;
1867       users = silc_list_count(entry->user_list);
1868       SILC_PUT32_MSB(users, usercount);
1869     }
1870
1871     /* Send the reply */
1872     if (topic)
1873       packet = 
1874         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1875                                              status, ident, 4, 
1876                                              2, idp->data, idp->len,
1877                                              3, entry->channel_name, 
1878                                              strlen(entry->channel_name),
1879                                              4, topic, strlen(topic),
1880                                              5, usercount, 4);
1881     else
1882       packet = 
1883         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1884                                              status, ident, 3, 
1885                                              2, idp->data, idp->len,
1886                                              3, entry->channel_name, 
1887                                              strlen(entry->channel_name),
1888                                              5, usercount, 4);
1889     silc_server_packet_send(cmd->server, cmd->sock, 
1890                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1891                             packet->len, FALSE);
1892     silc_buffer_free(packet);
1893     silc_buffer_free(idp);
1894   }
1895
1896   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1897
1898   /* Global list */
1899   for (i = 0; i < gch_count; i++) {
1900     entry = gch[i];
1901
1902     if (!entry)
1903       continue;
1904
1905     if (i >= 1)
1906       status = SILC_STATUS_LIST_ITEM;
1907
1908     if (gch_count > 1 && i == lch_count - 1)
1909       status = SILC_STATUS_LIST_END;
1910
1911     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1912
1913     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1914       topic = "*private*";
1915       memset(usercount, 0, sizeof(usercount));
1916     } else {
1917       topic = entry->topic;
1918       users = silc_list_count(entry->user_list);
1919       SILC_PUT32_MSB(users, usercount);
1920     }
1921
1922     /* Send the reply */
1923     if (topic)
1924       packet = 
1925         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1926                                              status, ident, 4, 
1927                                              2, idp->data, idp->len,
1928                                              3, entry->channel_name, 
1929                                              strlen(entry->channel_name),
1930                                              4, topic, strlen(topic),
1931                                              5, usercount, 4);
1932     else
1933       packet = 
1934         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1935                                              status, ident, 3, 
1936                                              2, idp->data, idp->len,
1937                                              3, entry->channel_name, 
1938                                              strlen(entry->channel_name),
1939                                              5, usercount, 4);
1940     silc_server_packet_send(cmd->server, cmd->sock, 
1941                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1942                             packet->len, FALSE);
1943     silc_buffer_free(packet);
1944     silc_buffer_free(idp);
1945   }
1946 }
1947
1948 /* Server side of LIST command. This lists the channel of the requested
1949    server. Secret channels are not listed. */
1950
1951 SILC_SERVER_CMD_FUNC(list)
1952 {
1953   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1954   SilcServer server = cmd->server;
1955   SilcChannelID *channel_id = NULL;
1956   unsigned char *tmp;
1957   uint32 tmp_len;
1958   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1959   uint32 lch_count = 0, gch_count = 0;
1960
1961   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1962
1963   /* Get Channel ID */
1964   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1965   if (tmp) {
1966     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1967     if (!channel_id) {
1968       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1969                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
1970       goto out;
1971     }
1972   }
1973
1974   /* Get the channels from local list */
1975   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1976                                        &lch_count);
1977   
1978   /* Get the channels from global list if we are router */
1979   if (server->server_type == SILC_ROUTER) 
1980     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1981                                          &gch_count);
1982
1983   /* Send the reply */
1984   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
1985                                       gchannels, gch_count);
1986
1987  out:
1988   silc_server_command_free(cmd);
1989 }
1990
1991 /* Server side of TOPIC command. Sets topic for channel and/or returns
1992    current topic to client. */
1993
1994 SILC_SERVER_CMD_FUNC(topic)
1995 {
1996   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1997   SilcServer server = cmd->server;
1998   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1999   SilcChannelID *channel_id;
2000   SilcChannelEntry channel;
2001   SilcChannelClientEntry chl;
2002   SilcBuffer packet, idp;
2003   unsigned char *tmp;
2004   uint32 argc, tmp_len;
2005   uint16 ident = silc_command_get_ident(cmd->payload);
2006
2007   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2008
2009   argc = silc_argument_get_arg_num(cmd->args);
2010
2011   /* Get Channel ID */
2012   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2013   if (!tmp) {
2014     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2016     goto out;
2017   }
2018   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2019   if (!channel_id) {
2020     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2021                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2022     goto out;
2023   }
2024
2025   /* Check whether the channel exists */
2026   channel = silc_idlist_find_channel_by_id(server->local_list, 
2027                                            channel_id, NULL);
2028   if (!channel) {
2029     channel = silc_idlist_find_channel_by_id(server->global_list, 
2030                                              channel_id, NULL);
2031     if (!channel) {
2032       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2033                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2034       goto out;
2035     }
2036   }
2037
2038   if (argc > 1) {
2039     /* Get the topic */
2040     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2041     if (!tmp) {
2042       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2044       goto out;
2045     }
2046
2047     if (strlen(tmp) > 256) {
2048       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2049                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2050       goto out;
2051     }
2052
2053     /* See whether has rights to change topic */
2054     silc_list_start(channel->user_list);
2055     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2056       if (chl->client == client)
2057         break;
2058
2059     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2060       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2061         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2062                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2063         goto out;
2064       }
2065     }
2066
2067     /* Set the topic for channel */
2068     if (channel->topic)
2069       silc_free(channel->topic);
2070     channel->topic = strdup(tmp);
2071
2072     /* Send TOPIC_SET notify type to the network */
2073     if (!server->standalone)
2074       silc_server_send_notify_topic_set(server, server->router->connection,
2075                                         server->server_type == SILC_ROUTER ?
2076                                         TRUE : FALSE, channel, client->id,
2077                                         channel->topic);
2078
2079     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2080
2081     /* Send notify about topic change to all clients on the channel */
2082     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2083                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2084                                        idp->data, idp->len,
2085                                        channel->topic, strlen(channel->topic));
2086     silc_buffer_free(idp);
2087   }
2088
2089   /* Send the topic to client as reply packet */
2090   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2091   if (channel->topic)
2092     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2093                                                   SILC_STATUS_OK, ident, 2, 
2094                                                   2, idp->data, idp->len,
2095                                                   3, channel->topic, 
2096                                                   strlen(channel->topic));
2097   else
2098     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2099                                                   SILC_STATUS_OK, ident, 1, 
2100                                                   2, idp->data, idp->len);
2101   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2102                           0, packet->data, packet->len, FALSE);
2103
2104   silc_buffer_free(packet);
2105   silc_buffer_free(idp);
2106   silc_free(channel_id);
2107
2108  out:
2109   silc_server_command_free(cmd);
2110 }
2111
2112 /* Server side of INVITE command. Invites some client to join some channel. 
2113    This command is also used to manage the invite list of the channel. */
2114
2115 SILC_SERVER_CMD_FUNC(invite)
2116 {
2117   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2118   SilcServer server = cmd->server;
2119   SilcSocketConnection sock = cmd->sock, dest_sock;
2120   SilcChannelClientEntry chl;
2121   SilcClientEntry sender, dest;
2122   SilcClientID *dest_id = NULL;
2123   SilcChannelEntry channel;
2124   SilcChannelID *channel_id = NULL;
2125   SilcIDListData idata;
2126   SilcBuffer idp, idp2, packet;
2127   unsigned char *tmp, *add, *del;
2128   uint32 len;
2129   uint16 ident = silc_command_get_ident(cmd->payload);
2130
2131   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2132
2133   /* Get Channel ID */
2134   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2135   if (!tmp) {
2136     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2138     goto out;
2139   }
2140   channel_id = silc_id_payload_parse_id(tmp, len);
2141   if (!channel_id) {
2142     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2143                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2144     goto out;
2145   }
2146
2147   /* Get the channel entry */
2148   channel = silc_idlist_find_channel_by_id(server->local_list, 
2149                                            channel_id, NULL);
2150   if (!channel) {
2151     channel = silc_idlist_find_channel_by_id(server->global_list, 
2152                                              channel_id, NULL);
2153     if (!channel) {
2154       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2155                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2156       goto out;
2157     }
2158   }
2159
2160   /* Check whether the sender of this command is on the channel. */
2161   sender = (SilcClientEntry)sock->user_data;
2162   if (!silc_server_client_on_channel(sender, channel)) {
2163     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2164                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2165     goto out;
2166   }
2167
2168   /* Check whether the channel is invite-only channel. If yes then the
2169      sender of this command must be at least channel operator. */
2170   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2171     silc_list_start(channel->user_list);
2172     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2173       if (chl->client == sender) {
2174         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2175           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2176                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2177           goto out;
2178         }
2179         break;
2180       }
2181   }
2182
2183   /* Get destination client ID */
2184   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2185   if (tmp) {
2186     char invite[512];
2187
2188     dest_id = silc_id_payload_parse_id(tmp, len);
2189     if (!dest_id) {
2190       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2191                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2192       goto out;
2193     }
2194
2195     /* Get the client entry */
2196     dest = silc_server_get_client_resolve(server, dest_id);
2197     if (!dest) {
2198       if (server->server_type == SILC_ROUTER) {
2199         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2200                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2201         goto out;
2202       }
2203       
2204       /* The client info is being resolved. Reprocess this packet after
2205          receiving the reply to the query. */
2206       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2207                                   server->cmd_ident,
2208                                   silc_server_command_destructor,
2209                                   silc_server_command_invite, 
2210                                   silc_server_command_dup(cmd));
2211       cmd->pending = TRUE;
2212       silc_free(channel_id);
2213       silc_free(dest_id);
2214       return;
2215     }
2216
2217     /* Check whether the requested client is already on the channel. */
2218     if (silc_server_client_on_channel(dest, channel)) {
2219       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2220                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2221       goto out;
2222     }
2223     
2224     /* Get route to the client */
2225     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2226
2227     memset(invite, 0, sizeof(invite));
2228     strncat(invite, dest->nickname, strlen(dest->nickname));
2229     strncat(invite, "!", 1);
2230     strncat(invite, dest->username, strlen(dest->username));
2231     if (!strchr(dest->username, '@')) {
2232       strncat(invite, "@", 1);
2233       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2234     }
2235
2236     len = strlen(invite);
2237     if (!channel->invite_list)
2238       channel->invite_list = silc_calloc(len + 2, 
2239                                          sizeof(*channel->invite_list));
2240     else
2241       channel->invite_list = silc_realloc(channel->invite_list, 
2242                                           sizeof(*channel->invite_list) * 
2243                                           (len + 
2244                                            strlen(channel->invite_list) + 2));
2245     strncat(channel->invite_list, invite, len);
2246     strncat(channel->invite_list, ",", 1);
2247
2248     /* Send notify to the client that is invited to the channel */
2249     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2250     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2251     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2252                                  SILC_ID_CLIENT,
2253                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2254                                  idp->data, idp->len, 
2255                                  channel->channel_name, 
2256                                  strlen(channel->channel_name),
2257                                  idp2->data, idp2->len);
2258     silc_buffer_free(idp);
2259     silc_buffer_free(idp2);
2260   }
2261
2262   /* Add the client to the invite list of the channel */
2263   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2264   if (add) {
2265     if (!channel->invite_list)
2266       channel->invite_list = silc_calloc(len + 2, 
2267                                          sizeof(*channel->invite_list));
2268     else
2269       channel->invite_list = silc_realloc(channel->invite_list, 
2270                                           sizeof(*channel->invite_list) * 
2271                                           (len + 
2272                                            strlen(channel->invite_list) + 2));
2273     if (add[len - 1] == ',')
2274       add[len - 1] = '\0';
2275     
2276     strncat(channel->invite_list, add, len);
2277     strncat(channel->invite_list, ",", 1);
2278   }
2279
2280   /* Get the invite to be removed and remove it from the list */
2281   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2282   if (del && channel->invite_list) {
2283     char *start, *end, *n;
2284
2285     if (!strncmp(channel->invite_list, del, 
2286                  strlen(channel->invite_list) - 1)) {
2287       silc_free(channel->invite_list);
2288       channel->invite_list = NULL;
2289     } else {
2290       start = strstr(channel->invite_list, del);
2291       if (start && strlen(start) >= len) {
2292         end = start + len;
2293         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2294         strncat(n, channel->invite_list, start - channel->invite_list);
2295         strncat(n, end + 1, ((channel->invite_list + 
2296                               strlen(channel->invite_list)) - end) - 1);
2297         silc_free(channel->invite_list);
2298         channel->invite_list = n;
2299       }
2300     }
2301   }
2302
2303   /* Send notify to the primary router */
2304   if (!server->standalone)
2305     silc_server_send_notify_invite(server, server->router->connection,
2306                                    server->server_type == SILC_ROUTER ?
2307                                    TRUE : FALSE, channel,
2308                                    sender->id, add, del);
2309
2310   /* Send command reply */
2311   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2312   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2313                                                 SILC_STATUS_OK, ident, 2,
2314                                                 2, tmp, len,
2315                                                 3, channel->invite_list,
2316                                                 channel->invite_list ?
2317                                                 strlen(channel->invite_list) :
2318                                                 0);
2319   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2320                           packet->data, packet->len, FALSE);
2321   silc_buffer_free(packet);
2322
2323  out:
2324   if (dest_id)
2325     silc_free(dest_id);
2326   if (channel_id)
2327     silc_free(channel_id);
2328   silc_server_command_free(cmd);
2329 }
2330
2331 typedef struct {
2332   SilcServer server;
2333   SilcSocketConnection sock;
2334   char *signoff;
2335 } *QuitInternal;
2336
2337 /* Quits connection to client. This gets called if client won't
2338    close the connection even when it has issued QUIT command. */
2339
2340 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2341 {
2342   QuitInternal q = (QuitInternal)context;
2343
2344   /* Free all client specific data, such as client entry and entires
2345      on channels this client may be on. */
2346   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2347                                TRUE, q->signoff);
2348   q->sock->user_data = NULL;
2349
2350   /* Close the connection on our side */
2351   silc_server_close_connection(q->server, q->sock);
2352
2353   silc_free(q->signoff);
2354   silc_free(q);
2355 }
2356
2357 /* Quits SILC session. This is the normal way to disconnect client. */
2358  
2359 SILC_SERVER_CMD_FUNC(quit)
2360 {
2361   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2362   SilcServer server = cmd->server;
2363   SilcSocketConnection sock = cmd->sock;
2364   QuitInternal q;
2365   unsigned char *tmp = NULL;
2366   uint32 len = 0;
2367
2368   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2369
2370   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2371     goto out;
2372
2373   /* Get destination ID */
2374   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2375   if (len > 128)
2376     tmp = NULL;
2377
2378   q = silc_calloc(1, sizeof(*q));
2379   q->server = server;
2380   q->sock = sock;
2381   q->signoff = tmp ? strdup(tmp) : NULL;
2382
2383   /* We quit the connection with little timeout */
2384   silc_task_register(server->timeout_queue, sock->sock,
2385                      silc_server_command_quit_cb, (void *)q,
2386                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2387
2388  out:
2389   silc_server_command_free(cmd);
2390 }
2391
2392 /* Server side of command KILL. This command is used by router operator
2393    to remove an client from the SILC Network temporarily. */
2394
2395 SILC_SERVER_CMD_FUNC(kill)
2396 {
2397   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2398   SilcServer server = cmd->server;
2399   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2400   SilcClientEntry remote_client;
2401   SilcClientID *client_id;
2402   unsigned char *tmp, *comment;
2403   uint32 tmp_len, tmp_len2;
2404
2405   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2406
2407   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2408     goto out;
2409
2410   /* KILL command works only on router */
2411   if (server->server_type != SILC_ROUTER) {
2412     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2413                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2414     goto out;
2415   }
2416
2417   /* Check whether client has the permissions. */
2418   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2419     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2420                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2421     goto out;
2422   }
2423
2424   /* Get the client ID */
2425   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2426   if (!tmp) {
2427     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2428                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2429     goto out;
2430   }
2431   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2432   if (!client_id) {
2433     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2434                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2435     goto out;
2436   }
2437
2438   /* Get the client entry */
2439   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2440                                                 client_id, NULL);
2441   if (!remote_client) {
2442     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2443                                                   client_id, NULL);
2444     if (!remote_client) {
2445       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2446                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2447       goto out;
2448     }
2449   }
2450
2451   /* Get comment */
2452   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2453   if (tmp_len2 > 128)
2454     comment = NULL;
2455
2456   /* Send reply to the sender */
2457   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2458                                         SILC_STATUS_OK);
2459
2460   /* Send the KILL notify packets. First send it to the channel, then
2461      to our primary router and then directly to the client who is being
2462      killed right now. */
2463
2464   /* Send KILLED notify to the channels. It is not sent to the client
2465      as it will be sent differently destined directly to the client and not
2466      to the channel. */
2467   silc_server_send_notify_on_channels(server, remote_client, 
2468                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2469                                       comment ? 2 : 1,
2470                                       tmp, tmp_len,
2471                                       comment, comment ? tmp_len2 : 0);
2472
2473   /* Send KILLED notify to primary route */
2474   if (!server->standalone)
2475     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2476                                    remote_client->id, comment);
2477
2478   /* Send KILLED notify to the client directly */
2479   silc_server_send_notify_killed(server, remote_client->connection ? 
2480                                  remote_client->connection : 
2481                                  remote_client->router->connection, FALSE,
2482                                  remote_client->id, comment);
2483
2484   /* Remove the client from all channels. This generates new keys to the
2485      channels as well. */
2486   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2487                                    NULL, TRUE);
2488
2489   /* Remove the client entry, If it is locally connected then we will also
2490      disconnect the client here */
2491   if (remote_client->data.registered && remote_client->connection) {
2492     /* Remove locally conneted client */
2493     SilcSocketConnection sock = remote_client->connection;
2494     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2495     silc_server_close_connection(server, sock);
2496   } else {
2497     /* Remove remote client */
2498     if (!silc_idlist_del_client(server->global_list, remote_client))
2499       silc_idlist_del_client(server->local_list, remote_client);
2500   }
2501
2502  out:
2503   silc_server_command_free(cmd);
2504 }
2505
2506 /* Server side of command INFO. This sends information about us to 
2507    the client. If client requested specific server we will send the 
2508    command to that server. */
2509
2510 SILC_SERVER_CMD_FUNC(info)
2511 {
2512   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2513   SilcServer server = cmd->server;
2514   SilcBuffer packet, idp;
2515   unsigned char *tmp;
2516   uint32 tmp_len;
2517   char *dest_server, *server_info = NULL, *server_name;
2518   uint16 ident = silc_command_get_ident(cmd->payload);
2519   SilcServerEntry entry = NULL;
2520   SilcServerID *server_id = NULL;
2521
2522   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2523
2524   /* Get server name */
2525   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2526
2527   /* Get Server ID */
2528   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2529   if (tmp) {
2530     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2531     if (!server_id) {
2532       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2533                                             SILC_STATUS_ERR_NO_SERVER_ID);
2534       goto out;
2535     }
2536   }
2537
2538   if (server_id) {
2539     /* Check whether we have this server cached */
2540     entry = silc_idlist_find_server_by_id(server->local_list,
2541                                           server_id, NULL);
2542     if (!entry) {
2543       entry = silc_idlist_find_server_by_id(server->global_list,
2544                                             server_id, NULL);
2545       if (!entry && server->server_type == SILC_ROUTER) {
2546         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2547                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2548         goto out;
2549       }
2550     }
2551   }
2552
2553   if ((!dest_server && !server_id) || 
2554       (dest_server && !cmd->pending && 
2555        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2556     /* Send our reply */
2557     char info_string[256];
2558
2559     memset(info_string, 0, sizeof(info_string));
2560     snprintf(info_string, sizeof(info_string), 
2561              "location: %s server: %s admin: %s <%s>",
2562              server->config->admin_info->location,
2563              server->config->admin_info->server_type,
2564              server->config->admin_info->admin_name,
2565              server->config->admin_info->admin_email);
2566
2567     server_info = info_string;
2568     entry = server->id_entry;
2569   } else {
2570     /* Check whether we have this server cached */
2571     if (!entry && dest_server) {
2572       entry = silc_idlist_find_server_by_name(server->global_list,
2573                                               dest_server, NULL);
2574       if (!entry) {
2575         entry = silc_idlist_find_server_by_name(server->local_list,
2576                                                 dest_server, NULL);
2577       }
2578     }
2579
2580     if (!cmd->pending &&
2581         server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2582       /* Send to the server */
2583       SilcBuffer tmpbuf;
2584       uint16 old_ident;
2585
2586       old_ident = silc_command_get_ident(cmd->payload);
2587       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2588       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2589
2590       silc_server_packet_send(server, entry->connection,
2591                               SILC_PACKET_COMMAND, cmd->packet->flags,
2592                               tmpbuf->data, tmpbuf->len, TRUE);
2593
2594       /* Reprocess this packet after received reply from router */
2595       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2596                                   silc_command_get_ident(cmd->payload),
2597                                   silc_server_command_destructor,
2598                                   silc_server_command_info,
2599                                   silc_server_command_dup(cmd));
2600       cmd->pending = TRUE;
2601       silc_command_set_ident(cmd->payload, old_ident);
2602       silc_buffer_free(tmpbuf);
2603       return;
2604     }
2605
2606     if (!entry && !cmd->pending && !server->standalone) {
2607       /* Send to the primary router */
2608       SilcBuffer tmpbuf;
2609       uint16 old_ident;
2610
2611       old_ident = silc_command_get_ident(cmd->payload);
2612       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2613       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2614
2615       silc_server_packet_send(server, server->router->connection,
2616                               SILC_PACKET_COMMAND, cmd->packet->flags,
2617                               tmpbuf->data, tmpbuf->len, TRUE);
2618
2619       /* Reprocess this packet after received reply from router */
2620       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2621                                   silc_command_get_ident(cmd->payload),
2622                                   silc_server_command_destructor,
2623                                   silc_server_command_info,
2624                                   silc_server_command_dup(cmd));
2625       cmd->pending = TRUE;
2626       silc_command_set_ident(cmd->payload, old_ident);
2627       silc_buffer_free(tmpbuf);
2628       return;
2629     }
2630   }
2631
2632   if (server_id)
2633     silc_free(server_id);
2634
2635   if (!entry) {
2636     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2637                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2638     goto out;
2639   }
2640
2641   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2642   if (!server_info)
2643     server_info = entry->server_info;
2644   server_name = entry->server_name;
2645
2646   /* Send the reply */
2647   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2648                                                 SILC_STATUS_OK, ident, 3,
2649                                                 2, idp->data, idp->len,
2650                                                 3, server_name, 
2651                                                 strlen(server_name),
2652                                                 4, server_info, 
2653                                                 strlen(server_info));
2654   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2655                           packet->data, packet->len, FALSE);
2656     
2657   silc_buffer_free(packet);
2658   silc_buffer_free(idp);
2659
2660  out:
2661   silc_server_command_free(cmd);
2662 }
2663
2664 /* Server side of command PING. This just replies to the ping. */
2665
2666 SILC_SERVER_CMD_FUNC(ping)
2667 {
2668   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2669   SilcServer server = cmd->server;
2670   SilcServerID *id;
2671   uint32 len;
2672   unsigned char *tmp;
2673
2674   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2675
2676   /* Get Server ID */
2677   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2678   if (!tmp) {
2679     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2680                                           SILC_STATUS_ERR_NO_SERVER_ID);
2681     goto out;
2682   }
2683   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2684   if (!id)
2685     goto out;
2686
2687   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2688     /* Send our reply */
2689     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2690                                           SILC_STATUS_OK);
2691   } else {
2692     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2693                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2694     goto out;
2695   }
2696
2697   silc_free(id);
2698
2699  out:
2700   silc_server_command_free(cmd);
2701 }
2702
2703 /* Internal routine to join channel. The channel sent to this function
2704    has been either created or resolved from ID lists. This joins the sent
2705    client to the channel. */
2706
2707 static void silc_server_command_join_channel(SilcServer server, 
2708                                              SilcServerCommandContext cmd,
2709                                              SilcChannelEntry channel,
2710                                              SilcClientID *client_id,
2711                                              int created,
2712                                              uint32 umode)
2713 {
2714   SilcSocketConnection sock = cmd->sock;
2715   unsigned char *tmp;
2716   uint32 tmp_len, user_count;
2717   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2718   SilcClientEntry client;
2719   SilcChannelClientEntry chl;
2720   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2721   uint16 ident = silc_command_get_ident(cmd->payload);
2722   char check[512];
2723
2724   SILC_LOG_DEBUG(("Start"));
2725
2726   if (!channel)
2727     return;
2728
2729   /* Get the client entry */
2730   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2731     client = (SilcClientEntry)sock->user_data;
2732   } else {
2733     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2734                                            NULL);
2735     if (!client)
2736       goto out;
2737   }
2738
2739   /*
2740    * Check channel modes
2741    */
2742
2743   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2744     strncat(check, client->nickname, strlen(client->nickname));
2745     if (!strchr(client->nickname, '@')) {
2746       strncat(check, "@", 1);
2747       strncat(check, server->server_name, strlen(server->server_name));
2748     }
2749     strncat(check, "!", 1);
2750     strncat(check, client->username, strlen(client->username));
2751     if (!strchr(client->username, '@')) {
2752       strncat(check, "@", 1);
2753       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2754     }
2755   }
2756
2757   /* Check invite list if channel is invite-only channel */
2758   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
2759       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2760     if (!channel->invite_list) {
2761       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2762                                             SILC_STATUS_ERR_NOT_INVITED);
2763       goto out;
2764     }
2765
2766     if (!silc_string_match(channel->invite_list, check)) {
2767       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2768                                             SILC_STATUS_ERR_NOT_INVITED);
2769       goto out;
2770     }
2771   }
2772
2773   /* Check ban list if it exists. If the client's nickname, server,
2774      username and/or hostname is in the ban list the access to the
2775      channel is denied. */
2776   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2777     if (silc_string_match(channel->ban_list, check)) {
2778       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2779                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2780       goto out;
2781     }
2782   }
2783
2784   /* Get passphrase */
2785   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2786   if (tmp) {
2787     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2788     memcpy(passphrase, tmp, tmp_len);
2789   }
2790   
2791   /* Check the channel passphrase if set. */
2792   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2793     if (!passphrase || memcmp(channel->passphrase, passphrase,
2794                               strlen(channel->passphrase))) {
2795       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2796                                             SILC_STATUS_ERR_BAD_PASSWORD);
2797       goto out;
2798     }
2799   }
2800
2801   /* Check user count limit if set. */
2802   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2803     if (silc_list_count(channel->user_list) + 1 > 
2804         channel->user_limit) {
2805       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2806                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2807       goto out;
2808     }
2809   }
2810
2811   /*
2812    * Client is allowed to join to the channel. Make it happen.
2813    */
2814
2815   /* Check whether the client already is on the channel */
2816   if (silc_server_client_on_channel(client, channel)) {
2817     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2818                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2819     goto out;
2820   }
2821
2822   /* Generate new channel key as protocol dictates */
2823   if ((!created && silc_list_count(channel->user_list) > 0) || 
2824       !channel->channel_key)
2825     silc_server_create_channel_key(server, channel, 0);
2826
2827   /* Send the channel key. This is broadcasted to the channel but is not
2828      sent to the client who is joining to the channel. */
2829   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2830     silc_server_send_channel_key(server, NULL, channel, 
2831                                  server->server_type == SILC_ROUTER ? 
2832                                  FALSE : !server->standalone);
2833
2834   /* Join the client to the channel by adding it to channel's user list.
2835      Add also the channel to client entry's channels list for fast cross-
2836      referencing. */
2837   chl = silc_calloc(1, sizeof(*chl));
2838   chl->mode = umode;
2839   chl->client = client;
2840   chl->channel = channel;
2841   silc_list_add(channel->user_list, chl);
2842   silc_list_add(client->channels, chl);
2843
2844   /* Get users on the channel */
2845   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2846                                    &user_count);
2847
2848   /* Encode Client ID Payload of the original client who wants to join */
2849   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2850
2851   /* Encode command reply packet */
2852   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2853   SILC_PUT32_MSB(channel->mode, mode);
2854   SILC_PUT32_MSB(created, tmp2);
2855   SILC_PUT32_MSB(user_count, tmp3);
2856
2857   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2858     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2859     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2860                                            strlen(channel->channel_key->
2861                                                   cipher->name),
2862                                            channel->channel_key->cipher->name,
2863                                            channel->key_len / 8, channel->key);
2864     silc_free(tmp);
2865   }
2866
2867   reply = 
2868     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2869                                          SILC_STATUS_OK, ident, 13,
2870                                          2, channel->channel_name,
2871                                          strlen(channel->channel_name),
2872                                          3, chidp->data, chidp->len,
2873                                          4, clidp->data, clidp->len,
2874                                          5, mode, 4,
2875                                          6, tmp2, 4,
2876                                          7, keyp ? keyp->data : NULL, 
2877                                          keyp ? keyp->len : 0,
2878                                          8, channel->ban_list, 
2879                                          channel->ban_list ?
2880                                          strlen(channel->ban_list) : 0,
2881                                          9, channel->invite_list,
2882                                          channel->invite_list ?
2883                                          strlen(channel->invite_list) : 0,
2884                                          10, channel->topic,
2885                                          channel->topic ?
2886                                          strlen(channel->topic) : 0,
2887                                          11, channel->hmac->hmac->name,
2888                                          strlen(channel->hmac->hmac->name),
2889                                          12, tmp3, 4,
2890                                          13, user_list->data, user_list->len,
2891                                          14, mode_list->data, 
2892                                          mode_list->len);
2893
2894   /* Send command reply */
2895   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2896                           reply->data, reply->len, FALSE);
2897
2898   if (!cmd->pending) {
2899     /* Send JOIN notify to locally connected clients on the channel */
2900     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2901                                        SILC_NOTIFY_TYPE_JOIN, 2,
2902                                        clidp->data, clidp->len,
2903                                        chidp->data, chidp->len);
2904
2905     /* Send JOIN notify packet to our primary router */
2906     if (!server->standalone)
2907       silc_server_send_notify_join(server, server->router->connection,
2908                                    server->server_type == SILC_ROUTER ?
2909                                    TRUE : FALSE, channel, client->id);
2910   }
2911
2912   silc_buffer_free(reply);
2913   silc_buffer_free(clidp);
2914   silc_buffer_free(chidp);
2915   silc_buffer_free(keyp);
2916   silc_buffer_free(user_list);
2917   silc_buffer_free(mode_list);
2918
2919  out:
2920   if (passphrase)
2921     silc_free(passphrase);
2922 }
2923
2924 /* Server side of command JOIN. Joins client into requested channel. If 
2925    the channel does not exist it will be created. */
2926
2927 SILC_SERVER_CMD_FUNC(join)
2928 {
2929   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2930   SilcServer server = cmd->server;
2931   uint32 tmp_len;
2932   char *tmp, *channel_name = NULL, *cipher, *hmac;
2933   SilcChannelEntry channel;
2934   uint32 umode = 0;
2935   int created = FALSE;
2936   SilcClientID *client_id;
2937
2938   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2939
2940   /* Get channel name */
2941   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2942   if (!tmp) {
2943     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2944                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2945     goto out;
2946   }
2947   channel_name = tmp;
2948
2949   if (strlen(channel_name) > 256)
2950     channel_name[255] = '\0';
2951
2952   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2953     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2954                                           SILC_STATUS_ERR_BAD_CHANNEL);
2955     silc_free(channel_name);
2956     goto out;
2957   }
2958
2959   /* Get Client ID of the client who is joining to the channel */
2960   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2961   if (!tmp) {
2962     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2963                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2964     goto out;
2965   }
2966   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2967   if (!client_id) {
2968     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2969                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2970     goto out;
2971   }
2972
2973   /* Get cipher and hmac name */
2974   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2975   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2976
2977   /* See if the channel exists */
2978   channel = silc_idlist_find_channel_by_name(server->local_list, 
2979                                              channel_name, NULL);
2980
2981   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2982     /* If this is coming from client the Client ID in the command packet must
2983        be same as the client's ID. */
2984     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2985       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2986       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2987         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2988                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2989         goto out;
2990       }
2991     }
2992
2993     if (!channel || !channel->id) {
2994       /* Channel not found */
2995
2996       /* If we are standalone server we don't have a router, we just create 
2997          the channel by ourselves. */
2998       if (server->standalone) {
2999         channel = silc_server_create_new_channel(server, server->id, cipher, 
3000                                                  hmac, channel_name, TRUE);
3001         if (!channel) {
3002           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3003                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3004           goto out;
3005         }
3006
3007         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3008         created = TRUE;
3009
3010       } else {
3011
3012         /* The channel does not exist on our server. If we are normal server 
3013            we will send JOIN command to our router which will handle the
3014            joining procedure (either creates the channel if it doesn't exist 
3015            or joins the client to it). */
3016         if (server->server_type == SILC_SERVER) {
3017           SilcBuffer tmpbuf;
3018           uint16 old_ident;
3019           
3020           old_ident = silc_command_get_ident(cmd->payload);
3021           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3022           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3023           
3024           /* Send JOIN command to our router */
3025           silc_server_packet_send(server, (SilcSocketConnection)
3026                                   server->router->connection,
3027                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3028                                   tmpbuf->data, tmpbuf->len, TRUE);
3029           
3030           /* Reprocess this packet after received reply from router */
3031           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3032                                       silc_command_get_ident(cmd->payload),
3033                                       silc_server_command_destructor,
3034                                       silc_server_command_join,
3035                                       silc_server_command_dup(cmd));
3036           cmd->pending = TRUE;
3037           return;
3038         }
3039         
3040         /* We are router and the channel does not seem exist so we will check
3041            our global list as well for the channel. */
3042         channel = silc_idlist_find_channel_by_name(server->global_list, 
3043                                                    channel_name, NULL);
3044         if (!channel) {
3045           /* Channel really does not exist, create it */
3046           channel = silc_server_create_new_channel(server, server->id, cipher, 
3047                                                    hmac, channel_name, TRUE);
3048           if (!channel) {
3049             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3050                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3051             goto out;
3052           }
3053
3054           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3055           created = TRUE;
3056         }
3057       }
3058     }
3059   } else {
3060     if (!channel) {
3061       /* Channel not found */
3062
3063       /* If the command came from router and/or we are normal server then
3064          something went wrong with the joining as the channel was not found.
3065          We can't do anything else but ignore this. */
3066       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3067           server->server_type == SILC_SERVER)
3068         goto out;
3069       
3070       /* We are router and the channel does not seem exist so we will check
3071          our global list as well for the channel. */
3072       channel = silc_idlist_find_channel_by_name(server->global_list, 
3073                                                  channel_name, NULL);
3074       if (!channel) {
3075         /* Channel really does not exist, create it */
3076         channel = silc_server_create_new_channel(server, server->id, cipher, 
3077                                                  hmac, channel_name, TRUE);
3078         if (!channel) {
3079           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3080                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3081           goto out;
3082         }
3083
3084         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3085         created = TRUE;
3086       }
3087     }
3088   }
3089
3090   /* If the channel does not have global users and is also empty it means the
3091      channel was created globally (by our router) and the client will be the
3092      channel founder and operator. */
3093   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3094     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3095     created = TRUE;             /* Created globally by our router */
3096   }
3097
3098   /* Join to the channel */
3099   silc_server_command_join_channel(server, cmd, channel, client_id,
3100                                    created, umode);
3101
3102   silc_free(client_id);
3103
3104  out:
3105   silc_server_command_free(cmd);
3106 }
3107
3108 /* Server side of command MOTD. Sends server's current "message of the
3109    day" to the client. */
3110
3111 SILC_SERVER_CMD_FUNC(motd)
3112 {
3113   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3114   SilcServer server = cmd->server;
3115   SilcBuffer packet, idp;
3116   char *motd, *dest_server;
3117   uint32 motd_len;
3118   uint16 ident = silc_command_get_ident(cmd->payload);
3119   
3120   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3121
3122   /* Get server name */
3123   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3124   if (!dest_server) {
3125     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3126                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3127     goto out;
3128   }
3129
3130   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3131     /* Send our MOTD */
3132
3133     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3134
3135     if (server->config && server->config->motd && 
3136         server->config->motd->motd_file) {
3137       /* Send motd */
3138       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3139       if (!motd)
3140         goto out;
3141       
3142       motd[motd_len] = 0;
3143       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3144                                                     SILC_STATUS_OK, ident, 2,
3145                                                     2, idp, idp->len,
3146                                                     3, motd, motd_len);
3147       goto out;
3148     } else {
3149       /* No motd */
3150       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3151                                                     SILC_STATUS_OK, ident, 1,
3152                                                     2, idp, idp->len);
3153     }
3154
3155     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3156                             packet->data, packet->len, FALSE);
3157     silc_buffer_free(packet);
3158     silc_buffer_free(idp);
3159   } else {
3160     SilcServerEntry entry;
3161
3162     /* Check whether we have this server cached */
3163     entry = silc_idlist_find_server_by_name(server->global_list,
3164                                             dest_server, NULL);
3165     if (!entry) {
3166       entry = silc_idlist_find_server_by_name(server->local_list,
3167                                               dest_server, NULL);
3168     }
3169
3170     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3171         entry && !entry->motd) {
3172       /* Send to the server */
3173       SilcBuffer tmpbuf;
3174       uint16 old_ident;
3175
3176       old_ident = silc_command_get_ident(cmd->payload);
3177       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3178       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3179
3180       silc_server_packet_send(server, entry->connection,
3181                               SILC_PACKET_COMMAND, cmd->packet->flags,
3182                               tmpbuf->data, tmpbuf->len, TRUE);
3183
3184       /* Reprocess this packet after received reply from router */
3185       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3186                                   silc_command_get_ident(cmd->payload),
3187                                   silc_server_command_destructor,
3188                                   silc_server_command_motd,
3189                                   silc_server_command_dup(cmd));
3190       cmd->pending = TRUE;
3191       silc_command_set_ident(cmd->payload, old_ident);
3192       silc_buffer_free(tmpbuf);
3193       return;
3194     }
3195
3196     if (!entry && !cmd->pending && !server->standalone) {
3197       /* Send to the primary router */
3198       SilcBuffer tmpbuf;
3199       uint16 old_ident;
3200
3201       old_ident = silc_command_get_ident(cmd->payload);
3202       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3203       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3204
3205       silc_server_packet_send(server, server->router->connection,
3206                               SILC_PACKET_COMMAND, cmd->packet->flags,
3207                               tmpbuf->data, tmpbuf->len, TRUE);
3208
3209       /* Reprocess this packet after received reply from router */
3210       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3211                                   silc_command_get_ident(cmd->payload),
3212                                   silc_server_command_destructor,
3213                                   silc_server_command_motd,
3214                                   silc_server_command_dup(cmd));
3215       cmd->pending = TRUE;
3216       silc_command_set_ident(cmd->payload, old_ident);
3217       silc_buffer_free(tmpbuf);
3218       return;
3219     }
3220
3221     if (!entry) {
3222       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3223                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3224       goto out;
3225     }
3226
3227     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3228
3229     if (entry->motd)
3230       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3231                                                     SILC_STATUS_OK, ident, 2,
3232                                                     2, idp, idp->len,
3233                                                     3, entry->motd,
3234                                                     strlen(entry->motd));
3235     else
3236       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3237                                                     SILC_STATUS_OK, ident, 1,
3238                                                     2, idp, idp->len);
3239
3240     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3241                             packet->data, packet->len, FALSE);
3242     silc_buffer_free(packet);
3243     silc_buffer_free(idp);
3244   }
3245
3246  out:
3247   silc_server_command_free(cmd);
3248 }
3249
3250 /* Server side of command UMODE. Client can use this command to set/unset
3251    user mode. Client actually cannot set itself to be as server/router
3252    operator so this can be used only to unset the modes. */
3253
3254 SILC_SERVER_CMD_FUNC(umode)
3255 {
3256   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3257   SilcServer server = cmd->server;
3258   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3259   SilcBuffer packet;
3260   unsigned char *tmp_mask;
3261   uint32 mask;
3262   uint16 ident = silc_command_get_ident(cmd->payload);
3263
3264   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3265     goto out;
3266
3267   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3268
3269   /* Get the client's mode mask */
3270   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3271   if (!tmp_mask) {
3272     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3273                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3274     goto out;
3275   }
3276   SILC_GET32_MSB(mask, tmp_mask);
3277
3278   /* 
3279    * Change the mode 
3280    */
3281
3282   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3283     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3284       /* Cannot operator mode */
3285       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3286                                             SILC_STATUS_ERR_PERM_DENIED);
3287       goto out;
3288     }
3289   } else {
3290     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3291       /* Remove the server operator rights */
3292       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3293   }
3294
3295   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3296     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3297       /* Cannot operator mode */
3298       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3299                                             SILC_STATUS_ERR_PERM_DENIED);
3300       goto out;
3301     }
3302   } else {
3303     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3304       /* Remove the router operator rights */
3305       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3306   }
3307
3308   if (mask & SILC_UMODE_GONE) {
3309     client->mode |= SILC_UMODE_GONE;
3310   } else {
3311     if (client->mode & SILC_UMODE_GONE)
3312       /* Remove the gone status */
3313       client->mode &= ~SILC_UMODE_GONE;
3314   }
3315
3316   /* Send UMODE change to primary router */
3317   if (!server->standalone)
3318     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3319                                   client->id, client->mode);
3320
3321   /* Send command reply to sender */
3322   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3323                                                 SILC_STATUS_OK, ident, 1,
3324                                                 2, tmp_mask, 4);
3325   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3326                           packet->data, packet->len, FALSE);
3327   silc_buffer_free(packet);
3328
3329  out:
3330   silc_server_command_free(cmd);
3331 }
3332
3333 /* Checks that client has rights to add or remove channel modes. If any
3334    of the checks fails FALSE is returned. */
3335
3336 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3337                                    SilcChannelClientEntry client,
3338                                    uint32 mode)
3339 {
3340   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3341   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3342
3343   /* Check whether has rights to change anything */
3344   if (!is_op && !is_fo)
3345     return FALSE;
3346
3347   /* Check whether has rights to change everything */
3348   if (is_op && is_fo)
3349     return TRUE;
3350
3351   /* We know that client is channel operator, check that they are not
3352      changing anything that requires channel founder rights. Rest of the
3353      modes are available automatically for channel operator. */
3354
3355   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3356     if (is_op && !is_fo)
3357       return FALSE;
3358   } else {
3359     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3360       if (is_op && !is_fo)
3361         return FALSE;
3362     }
3363   }
3364   
3365   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3366     if (is_op && !is_fo)
3367       return FALSE;
3368   } else {
3369     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3370       if (is_op && !is_fo)
3371         return FALSE;
3372     }
3373   }
3374
3375   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3376     if (is_op && !is_fo)
3377       return FALSE;
3378   } else {
3379     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3380       if (is_op && !is_fo)
3381         return FALSE;
3382     }
3383   }
3384   
3385   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3386     if (is_op && !is_fo)
3387       return FALSE;
3388   } else {
3389     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3390       if (is_op && !is_fo)
3391         return FALSE;
3392     }
3393   }
3394   
3395   return TRUE;
3396 }
3397
3398 /* Server side command of CMODE. Changes channel mode */
3399
3400 SILC_SERVER_CMD_FUNC(cmode)
3401 {
3402   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3403   SilcServer server = cmd->server;
3404   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3405   SilcIDListData idata = (SilcIDListData)client;
3406   SilcChannelID *channel_id;
3407   SilcChannelEntry channel;
3408   SilcChannelClientEntry chl;
3409   SilcBuffer packet, cidp;
3410   unsigned char *tmp, *tmp_id, *tmp_mask;
3411   char *cipher = NULL, *hmac = NULL;
3412   uint32 mode_mask, tmp_len, tmp_len2;
3413   uint16 ident = silc_command_get_ident(cmd->payload);
3414
3415   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3416
3417   /* Get Channel ID */
3418   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3419   if (!tmp_id) {
3420     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3421                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3422     goto out;
3423   }
3424   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3425   if (!channel_id) {
3426     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3427                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3428     goto out;
3429   }
3430
3431   /* Get the channel mode mask */
3432   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3433   if (!tmp_mask) {
3434     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3436     goto out;
3437   }
3438   SILC_GET32_MSB(mode_mask, tmp_mask);
3439
3440   /* Get channel entry */
3441   channel = silc_idlist_find_channel_by_id(server->local_list, 
3442                                            channel_id, NULL);
3443   if (!channel) {
3444     channel = silc_idlist_find_channel_by_id(server->global_list, 
3445                                              channel_id, NULL);
3446     if (!channel) {
3447       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3448                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3449       goto out;
3450     }
3451   }
3452
3453   /* Check whether this client is on the channel */
3454   if (!silc_server_client_on_channel(client, channel)) {
3455     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3456                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3457     goto out;
3458   }
3459
3460   /* Get entry to the channel user list */
3461   silc_list_start(channel->user_list);
3462   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3463     if (chl->client == client)
3464       break;
3465
3466   /* Check that client has rights to change any requested channel modes */
3467   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3468     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3469                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3470     goto out;
3471   }
3472
3473   /*
3474    * Check the modes. Modes that requires nothing special operation are
3475    * not checked here.
3476    */
3477
3478   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3479     /* Channel uses private keys to protect traffic. Client(s) has set the
3480        key locally they want to use, server does not know that key. */
3481     /* Nothing interesting to do here */
3482   } else {
3483     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3484       /* The mode is removed and we need to generate and distribute
3485          new channel key. Clients are not using private channel keys
3486          anymore after this. */
3487
3488       /* Re-generate channel key */
3489       silc_server_create_channel_key(server, channel, 0);
3490       
3491       /* Send the channel key. This sends it to our local clients and if
3492          we are normal server to our router as well. */
3493       silc_server_send_channel_key(server, NULL, channel, 
3494                                    server->server_type == SILC_ROUTER ? 
3495                                    FALSE : !server->standalone);
3496
3497       cipher = channel->channel_key->cipher->name;
3498       hmac = channel->hmac->hmac->name;
3499     }
3500   }
3501   
3502   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3503     /* User limit is set on channel */
3504     uint32 user_limit;
3505       
3506     /* Get user limit */
3507     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3508     if (!tmp) {
3509       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3510         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3511                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3512         goto out;
3513       }
3514     } else {
3515       SILC_GET32_MSB(user_limit, tmp);
3516       channel->user_limit = user_limit;
3517     }
3518   } else {
3519     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3520       /* User limit mode is unset. Remove user limit */
3521       channel->user_limit = 0;
3522   }
3523
3524   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3525     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3526       /* Passphrase has been set to channel */
3527       
3528       /* Get the passphrase */
3529       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3530       if (!tmp) {
3531         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3532                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3533         goto out;
3534       }
3535
3536       /* Save the passphrase */
3537       channel->passphrase = strdup(tmp);
3538     }
3539   } else {
3540     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3541       /* Passphrase mode is unset. remove the passphrase */
3542       if (channel->passphrase) {
3543         silc_free(channel->passphrase);
3544         channel->passphrase = NULL;
3545       }
3546     }
3547   }
3548
3549   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3550     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3551       /* Cipher to use protect the traffic */
3552
3553       /* Get cipher */
3554       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3555       if (!cipher) {
3556         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3557                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3558         goto out;
3559       }
3560
3561       /* Delete old cipher and allocate the new one */
3562       silc_cipher_free(channel->channel_key);
3563       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3564         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3565                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3566         goto out;
3567       }
3568
3569       /* Re-generate channel key */
3570       silc_server_create_channel_key(server, channel, 0);
3571     
3572       /* Send the channel key. This sends it to our local clients and if
3573          we are normal server to our router as well. */
3574       silc_server_send_channel_key(server, NULL, channel, 
3575                                    server->server_type == SILC_ROUTER ? 
3576                                    FALSE : !server->standalone);
3577     }
3578   } else {
3579     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3580       /* Cipher mode is unset. Remove the cipher and revert back to 
3581          default cipher */
3582       cipher = channel->cipher;
3583
3584       /* Delete old cipher and allocate default one */
3585       silc_cipher_free(channel->channel_key);
3586       if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", 
3587                              &channel->channel_key)) {
3588         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3589                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3590         goto out;
3591       }
3592
3593       /* Re-generate channel key */
3594       silc_server_create_channel_key(server, channel, 0);
3595       
3596       /* Send the channel key. This sends it to our local clients and if
3597          we are normal server to our router as well. */
3598       silc_server_send_channel_key(server, NULL, channel, 
3599                                    server->server_type == SILC_ROUTER ? 
3600                                    FALSE : !server->standalone);
3601     }
3602   }
3603
3604   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3605     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3606       /* HMAC to use protect the traffic */
3607       unsigned char hash[32];
3608
3609       /* Get hmac */
3610       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3611       if (!hmac) {
3612         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3613                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3614         goto out;
3615       }
3616
3617       /* Delete old hmac and allocate the new one */
3618       silc_hmac_free(channel->hmac);
3619       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3620         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3621                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3622         goto out;
3623       }
3624
3625       /* Set the HMAC key out of current channel key. The client must do
3626          this locally. */
3627       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3628                      hash);
3629       silc_hmac_set_key(channel->hmac, hash, 
3630                         silc_hash_len(channel->hmac->hash));
3631       memset(hash, 0, sizeof(hash));
3632     }
3633   } else {
3634     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3635       /* Hmac mode is unset. Remove the hmac and revert back to 
3636          default hmac */
3637       unsigned char hash[32];
3638       hmac = channel->hmac_name;
3639
3640       /* Delete old hmac and allocate default one */
3641       silc_hmac_free(channel->hmac);
3642       if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
3643                            &channel->hmac)) {
3644         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3645                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3646         goto out;
3647       }
3648
3649       /* Set the HMAC key out of current channel key. The client must do
3650          this locally. */
3651       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3652                      hash);
3653       silc_hmac_set_key(channel->hmac, hash, 
3654                         silc_hash_len(channel->hmac->hash));
3655       memset(hash, 0, sizeof(hash));
3656     }
3657   }
3658
3659   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3660     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3661       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3662         /* Set the founder authentication */
3663         SilcAuthPayload auth;
3664         
3665         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3666         if (!tmp) {
3667           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3668                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3669           goto out;
3670         }
3671
3672         auth = silc_auth_payload_parse(tmp, tmp_len);
3673         if (!auth) {
3674           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3675                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3676           goto out;
3677         }
3678
3679         /* Save the public key */
3680         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3681         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3682         silc_free(tmp);
3683         
3684         channel->founder_method = silc_auth_get_method(auth);
3685
3686         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3687           tmp = silc_auth_get_data(auth, &tmp_len);
3688           channel->founder_passwd = 
3689             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3690           memcpy(channel->founder_passwd, tmp, tmp_len);
3691           channel->founder_passwd_len = tmp_len;
3692         }
3693
3694         silc_auth_payload_free(auth);
3695       }
3696     }
3697   } else {
3698     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3699       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3700         if (channel->founder_key)
3701           silc_pkcs_public_key_free(channel->founder_key);
3702         if (channel->founder_passwd) {
3703           silc_free(channel->founder_passwd);
3704           channel->founder_passwd = NULL;
3705         }
3706       }
3707     }
3708   }
3709
3710   /* Finally, set the mode */
3711   channel->mode = mode_mask;
3712
3713   /* Send CMODE_CHANGE notify */
3714   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3715   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3716                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3717                                      cidp->data, cidp->len, 
3718                                      tmp_mask, 4,
3719                                      cipher, cipher ? strlen(cipher) : 0,
3720                                      hmac, hmac ? strlen(hmac) : 0);
3721
3722   /* Set CMODE notify type to network */
3723   if (!server->standalone)
3724     silc_server_send_notify_cmode(server, server->router->connection,
3725                                   server->server_type == SILC_ROUTER ? 
3726                                   TRUE : FALSE, channel,
3727                                   mode_mask, client->id, SILC_ID_CLIENT,
3728                                   cipher, hmac);
3729
3730   /* Send command reply to sender */
3731   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3732                                                 SILC_STATUS_OK, ident, 1,
3733                                                 2, tmp_mask, 4);
3734   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3735                           packet->data, packet->len, FALSE);
3736     
3737   silc_buffer_free(packet);
3738   silc_free(channel_id);
3739   silc_free(cidp);
3740
3741  out:
3742   silc_server_command_free(cmd);
3743 }
3744
3745 /* Server side of CUMODE command. Changes client's mode on a channel. */
3746
3747 SILC_SERVER_CMD_FUNC(cumode)
3748 {
3749   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3750   SilcServer server = cmd->server;
3751   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3752   SilcIDListData idata = (SilcIDListData)client;
3753   SilcChannelID *channel_id;
3754   SilcClientID *client_id;
3755   SilcChannelEntry channel;
3756   SilcClientEntry target_client;
3757   SilcChannelClientEntry chl;
3758   SilcBuffer packet, idp;
3759   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3760   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3761   int notify = FALSE;
3762   uint16 ident = silc_command_get_ident(cmd->payload);
3763
3764   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3765
3766   /* Get Channel ID */
3767   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3768   if (!tmp_ch_id) {
3769     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3770                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3771     goto out;
3772   }
3773   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3774   if (!channel_id) {
3775     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3776                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3777     goto out;
3778   }
3779
3780   /* Get channel entry */
3781   channel = silc_idlist_find_channel_by_id(server->local_list, 
3782                                            channel_id, NULL);
3783   if (!channel) {
3784     channel = silc_idlist_find_channel_by_id(server->global_list, 
3785                                              channel_id, NULL);
3786     if (!channel) {
3787       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3788                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3789       goto out;
3790     }
3791   }
3792
3793   /* Check whether sender is on the channel */
3794   if (!silc_server_client_on_channel(client, channel)) {
3795     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3796                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3797     goto out;
3798   }
3799
3800   /* Check that client has rights to change other's rights */
3801   silc_list_start(channel->user_list);
3802   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3803     if (chl->client == client) {
3804       sender_mask = chl->mode;
3805       break;
3806     }
3807   }
3808   
3809   /* Get the target client's channel mode mask */
3810   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3811   if (!tmp_mask) {
3812     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3813                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3814     goto out;
3815   }
3816   SILC_GET32_MSB(target_mask, tmp_mask);
3817
3818   /* Get target Client ID */
3819   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3820   if (!tmp_id) {
3821     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3822                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3823     goto out;
3824   }
3825   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3826   if (!client_id) {
3827     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3828                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3829     goto out;
3830   }
3831
3832   /* Get target client's entry */
3833   target_client = silc_idlist_find_client_by_id(server->local_list, 
3834                                                 client_id, NULL);
3835   if (!target_client) {
3836     target_client = silc_idlist_find_client_by_id(server->global_list, 
3837                                                   client_id, NULL);
3838   }
3839
3840   if (target_client != client &&
3841       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3842       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3843     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3844                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3845     goto out;
3846   }
3847
3848   /* Check whether target client is on the channel */
3849   if (target_client != client) {
3850     if (!silc_server_client_on_channel(target_client, channel)) {
3851       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3852                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3853       goto out;
3854     }
3855
3856     /* Get entry to the channel user list */
3857     silc_list_start(channel->user_list);
3858     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3859       if (chl->client == target_client)
3860         break;
3861   }
3862
3863   /* 
3864    * Change the mode 
3865    */
3866
3867   /* If the target client is founder, no one else can change their mode
3868      but themselves. */
3869   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3870     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3871                                           SILC_STATUS_ERR_NOT_YOU);
3872     goto out;
3873   }
3874
3875   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3876     /* The client tries to claim the founder rights. */
3877     unsigned char *tmp_auth;
3878     uint32 tmp_auth_len, auth_len;
3879     void *auth;
3880     
3881     if (target_client != client) {
3882       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3883                                             SILC_STATUS_ERR_NOT_YOU);
3884       goto out;
3885     }
3886
3887     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3888         !channel->founder_key) {
3889       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3890                                             SILC_STATUS_ERR_NOT_YOU);
3891       goto out;
3892     }
3893
3894     tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3895     if (!tmp_auth) {
3896       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3897                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3898       goto out;
3899     }
3900
3901     auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3902             (void *)channel->founder_passwd : (void *)channel->founder_key);
3903     auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3904                 channel->founder_passwd_len : 0);
3905     
3906     if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3907                                channel->founder_method, auth, auth_len,
3908                                idata->hash, client->id, SILC_ID_CLIENT)) {
3909       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3910                                             SILC_STATUS_ERR_AUTH_FAILED);
3911       goto out;
3912     }
3913
3914     sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3915     notify = TRUE;
3916   } else {
3917     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3918       if (target_client == client) {
3919         /* Remove channel founder rights from itself */
3920         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3921         notify = TRUE;
3922       } else {
3923         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3924                                               SILC_STATUS_ERR_NOT_YOU);
3925         goto out;
3926       }
3927     }
3928   }
3929
3930   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3931     /* Promote to operator */
3932     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3933       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3934           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3935         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3936                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3937         goto out;
3938       }
3939
3940       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3941       notify = TRUE;
3942     }
3943   } else {
3944     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3945       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3946           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3947         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3948                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3949         goto out;
3950       }
3951
3952       /* Demote to normal user */
3953       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3954       notify = TRUE;
3955     }
3956   }
3957
3958   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3959   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3960
3961   /* Send notify to channel, notify only if mode was actually changed. */
3962   if (notify) {
3963     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3964                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3965                                        idp->data, idp->len,
3966                                        tmp_mask, 4, 
3967                                        tmp_id, tmp_len);
3968
3969     /* Set CUMODE notify type to network */
3970     if (!server->standalone)
3971       silc_server_send_notify_cumode(server, server->router->connection,
3972                                      server->server_type == SILC_ROUTER ? 
3973                                      TRUE : FALSE, channel,
3974                                      target_mask, client->id, 
3975                                      SILC_ID_CLIENT,
3976                                      target_client->id);
3977   }
3978
3979   /* Send command reply to sender */
3980   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3981                                                 SILC_STATUS_OK, ident, 2,
3982                                                 2, tmp_mask, 4,
3983                                                 3, tmp_id, tmp_len);
3984   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3985                           packet->data, packet->len, FALSE);
3986     
3987   silc_buffer_free(packet);
3988   silc_free(channel_id);
3989   silc_free(client_id);
3990   silc_buffer_free(idp);
3991
3992  out:
3993   silc_server_command_free(cmd);
3994 }
3995
3996 /* Server side of KICK command. Kicks client out of channel. */
3997
3998 SILC_SERVER_CMD_FUNC(kick)
3999 {
4000   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4001   SilcServer server = cmd->server;
4002   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4003   SilcClientEntry target_client;
4004   SilcChannelID *channel_id;
4005   SilcClientID *client_id;
4006   SilcChannelEntry channel;
4007   SilcChannelClientEntry chl;
4008   SilcBuffer idp;
4009   uint32 tmp_len;
4010   unsigned char *tmp, *comment;
4011
4012   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4013
4014   /* Get Channel ID */
4015   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4016   if (!tmp) {
4017     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4018                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4019     goto out;
4020   }
4021   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4022   if (!channel_id) {
4023     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4024                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4025     goto out;
4026   }
4027
4028   /* Get channel entry */
4029   channel = silc_idlist_find_channel_by_id(server->local_list, 
4030                                            channel_id, NULL);
4031   if (!channel) {
4032     channel = silc_idlist_find_channel_by_id(server->local_list, 
4033                                              channel_id, NULL);
4034     if (!channel) {
4035       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4036                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4037       goto out;
4038     }
4039   }
4040
4041   /* Check whether sender is on the channel */
4042   if (!silc_server_client_on_channel(client, channel)) {
4043     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4044                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4045     goto out;
4046   }
4047
4048   /* Check that the kicker is channel operator or channel founder */
4049   silc_list_start(channel->user_list);
4050   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4051     if (chl->client == client) {
4052       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4053         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4054                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4055         goto out;
4056       }
4057       break;
4058     }
4059   }
4060   
4061   /* Get target Client ID */
4062   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4063   if (!tmp) {
4064     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4065                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4066     goto out;
4067   }
4068   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4069   if (!client_id) {
4070     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4071                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4072     goto out;
4073   }
4074
4075   /* Get target client's entry */
4076   target_client = silc_idlist_find_client_by_id(server->local_list, 
4077                                                 client_id, NULL);
4078   if (!target_client) {
4079     target_client = silc_idlist_find_client_by_id(server->global_list, 
4080                                                   client_id, NULL);
4081   }
4082
4083   /* Check that the target client is not channel founder. Channel founder
4084      cannot be kicked from the channel. */
4085   silc_list_start(channel->user_list);
4086   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4087     if (chl->client == target_client) {
4088       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4089         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4090                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4091         goto out;
4092       }
4093       break;
4094     }
4095   }
4096   
4097   /* Check whether target client is on the channel */
4098   if (!silc_server_client_on_channel(target_client, channel)) {
4099     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4100                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4101     goto out;
4102   }
4103
4104   /* Get comment */
4105   tmp_len = 0;
4106   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4107   if (tmp_len > 128)
4108     comment = NULL;
4109
4110   /* Send command reply to sender */
4111   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4112                                         SILC_STATUS_OK);
4113
4114   /* Send KICKED notify to local clients on the channel */
4115   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4116   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4117                                      SILC_NOTIFY_TYPE_KICKED, 
4118                                      comment ? 2 : 1,
4119                                      idp->data, idp->len,
4120                                      comment, comment ? strlen(comment) : 0);
4121   silc_buffer_free(idp);
4122
4123   /* Remove the client from the channel. If the channel does not exist
4124      after removing the client then the client kicked itself off the channel
4125      and we don't have to send anything after that. */
4126   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4127                                            target_client, FALSE))
4128     goto out;
4129
4130   /* Send KICKED notify to primary route */
4131   if (!server->standalone)
4132     silc_server_send_notify_kicked(server, server->router->connection,
4133                                    server->server_type == SILC_ROUTER ?
4134                                    TRUE : FALSE, channel,
4135                                    target_client->id, comment);
4136
4137   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4138     /* Re-generate channel key */
4139     silc_server_create_channel_key(server, channel, 0);
4140     
4141     /* Send the channel key to the channel. The key of course is not sent
4142        to the client who was kicked off the channel. */
4143     silc_server_send_channel_key(server, target_client->connection, channel, 
4144                                  server->server_type == SILC_ROUTER ? 
4145                                  FALSE : !server->standalone);
4146   }
4147
4148  out:
4149   silc_server_command_free(cmd);
4150 }
4151
4152 /* Server side of OPER command. Client uses this comand to obtain server
4153    operator privileges to this server/router. */
4154
4155 SILC_SERVER_CMD_FUNC(oper)
4156 {
4157   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4158   SilcServer server = cmd->server;
4159   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4160   unsigned char *username, *auth;
4161   uint32 tmp_len;
4162   SilcServerConfigSectionAdminConnection *admin;
4163   SilcIDListData idata = (SilcIDListData)client;
4164
4165   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4166
4167   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4168     goto out;
4169
4170   /* Get the username */
4171   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4172   if (!username) {
4173     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4174                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4175     goto out;
4176   }
4177
4178   /* Get the admin configuration */
4179   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4180                                         username, client->nickname);
4181   if (!admin) {
4182     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4183                                           username, client->nickname);
4184     if (!admin) {
4185       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4186                                             SILC_STATUS_ERR_AUTH_FAILED);
4187       goto out;
4188     }
4189   }
4190
4191   /* Get the authentication payload */
4192   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4193   if (!auth) {
4194     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4195                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4196     goto out;
4197   }
4198
4199   /* Verify the authentication data */
4200   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4201                              admin->auth_data, admin->auth_data_len,
4202                              idata->hash, client->id, SILC_ID_CLIENT)) {
4203     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4204                                           SILC_STATUS_ERR_AUTH_FAILED);
4205     goto out;
4206   }
4207
4208   /* Client is now server operator */
4209   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4210
4211   /* Send UMODE change to primary router */
4212   if (!server->standalone)
4213     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4214                                   client->id, client->mode);
4215
4216   /* Send reply to the sender */
4217   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4218                                         SILC_STATUS_OK);
4219
4220  out:
4221   silc_server_command_free(cmd);
4222 }
4223
4224 /* Server side of SILCOPER command. Client uses this comand to obtain router
4225    operator privileges to this router. */
4226
4227 SILC_SERVER_CMD_FUNC(silcoper)
4228 {
4229   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4230   SilcServer server = cmd->server;
4231   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4232   unsigned char *username, *auth;
4233   uint32 tmp_len;
4234   SilcServerConfigSectionAdminConnection *admin;
4235   SilcIDListData idata = (SilcIDListData)client;
4236
4237   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4238
4239   if (server->server_type == SILC_SERVER)
4240     goto out;
4241
4242   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4243     goto out;
4244
4245   /* Get the username */
4246   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4247   if (!username) {
4248     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4249                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4250     goto out;
4251   }
4252
4253   /* Get the admin configuration */
4254   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4255                                         username, client->nickname);
4256   if (!admin) {
4257     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4258                                           username, client->nickname);
4259     if (!admin) {
4260       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4261                                             SILC_STATUS_ERR_AUTH_FAILED);
4262       goto out;
4263     }
4264   }
4265
4266   /* Get the authentication payload */
4267   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4268   if (!auth) {
4269     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4270                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4271     goto out;
4272   }
4273
4274   /* Verify the authentication data */
4275   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4276                              admin->auth_data, admin->auth_data_len,
4277                              idata->hash, client->id, SILC_ID_CLIENT)) {
4278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4279                                           SILC_STATUS_ERR_AUTH_FAILED);
4280     goto out;
4281   }
4282
4283   /* Client is now router operator */
4284   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4285
4286   /* Send UMODE change to primary router */
4287   if (!server->standalone)
4288     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4289                                   client->id, client->mode);
4290
4291   /* Send reply to the sender */
4292   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4293                                         SILC_STATUS_OK);
4294
4295  out:
4296   silc_server_command_free(cmd);
4297 }
4298
4299 /* Server side command of CONNECT. Connects us to the specified remote
4300    server or router. */
4301
4302 SILC_SERVER_CMD_FUNC(connect)
4303 {
4304   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4305   SilcServer server = cmd->server;
4306   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4307   unsigned char *tmp, *host;
4308   uint32 tmp_len;
4309   uint32 port = SILC_PORT;
4310
4311   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4312
4313   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4314     goto out;
4315
4316   /* Check whether client has the permissions. */
4317   if (client->mode == SILC_UMODE_NONE) {
4318     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4319                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4320     goto out;
4321   }
4322
4323   if (server->server_type == SILC_ROUTER && 
4324       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4325     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4326                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4327     goto out;
4328   }
4329
4330   /* Get the remote server */
4331   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4332   if (!host) {
4333     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4334                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4335     goto out;
4336   }
4337
4338   /* Get port */
4339   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4340   if (tmp)
4341     SILC_GET32_MSB(port, tmp);
4342
4343   /* Create the connection. It is done with timeout and is async. */
4344   silc_server_create_connection(server, host, port);
4345
4346   /* Send reply to the sender */
4347   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4348                                         SILC_STATUS_OK);
4349
4350  out:
4351   silc_server_command_free(cmd);
4352 }
4353
4354 /* Server side of command BAN. This is used to manage the ban list of the
4355    channel. To add clients and remove clients from the ban list. */
4356
4357 SILC_SERVER_CMD_FUNC(ban)
4358 {
4359   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4360   SilcServer server = cmd->server;
4361   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4362   SilcBuffer packet;
4363   SilcChannelEntry channel;
4364   SilcChannelClientEntry chl;
4365   SilcChannelID *channel_id = NULL;
4366   unsigned char *id, *add, *del;
4367   uint32 id_len, tmp_len;
4368   uint16 ident = silc_command_get_ident(cmd->payload);
4369
4370   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4371     goto out;
4372
4373   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4374
4375   /* Get Channel ID */
4376   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4377   if (id) {
4378     channel_id = silc_id_payload_parse_id(id, id_len);
4379     if (!channel_id) {
4380       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4381                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4382       goto out;
4383     }
4384   }
4385
4386   /* Get channel entry. The server must know about the channel since the
4387      client is expected to be on the channel. */
4388   channel = silc_idlist_find_channel_by_id(server->local_list, 
4389                                            channel_id, NULL);
4390   if (!channel) {
4391     channel = silc_idlist_find_channel_by_id(server->global_list, 
4392                                              channel_id, NULL);
4393     if (!channel) {
4394       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4395                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4396       goto out;
4397     }
4398   }
4399
4400   /* Check whether this client is on the channel */
4401   if (!silc_server_client_on_channel(client, channel)) {
4402     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4403                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4404     goto out;
4405   }
4406
4407   /* Get entry to the channel user list */
4408   silc_list_start(channel->user_list);
4409   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4410     if (chl->client == client)
4411       break;
4412
4413   /* The client must be at least channel operator. */
4414   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4415     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4416                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4417     goto out;
4418   }
4419
4420   /* Get the new ban and add it to the ban list */
4421   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4422   if (add) {
4423     if (!channel->ban_list)
4424       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4425     else
4426       channel->ban_list = silc_realloc(channel->ban_list, 
4427                                        sizeof(*channel->ban_list) * 
4428                                        (tmp_len + 
4429                                         strlen(channel->ban_list) + 2));
4430     if (add[tmp_len - 1] == ',')
4431       add[tmp_len - 1] = '\0';
4432
4433     strncat(channel->ban_list, add, tmp_len);
4434     strncat(channel->ban_list, ",", 1);
4435   }
4436
4437   /* Get the ban to be removed and remove it from the list */
4438   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4439   if (del && channel->ban_list) {
4440     char *start, *end, *n;
4441
4442     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4443       silc_free(channel->ban_list);
4444       channel->ban_list = NULL;
4445     } else {
4446       start = strstr(channel->ban_list, del);
4447       if (start && strlen(start) >= tmp_len) {
4448         end = start + tmp_len;
4449         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4450         strncat(n, channel->ban_list, start - channel->ban_list);
4451         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4452                              end) - 1);
4453         silc_free(channel->ban_list);
4454         channel->ban_list = n;
4455       }
4456     }
4457   }
4458
4459   /* Send the BAN notify type to our primary router. */
4460   if (!server->standalone && (add || del))
4461     silc_server_send_notify_ban(server, server->router->connection,
4462                                 server->server_type == SILC_ROUTER ?
4463                                 TRUE : FALSE, channel, add, del);
4464
4465   /* Send the reply back to the client */
4466   if (channel->ban_list)
4467     packet = 
4468       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4469                                            SILC_STATUS_OK, ident, 2,
4470                                            2, id, id_len,
4471                                            3, channel->ban_list, 
4472                                            strlen(channel->ban_list) - 1);
4473   else
4474     packet = 
4475       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4476                                            SILC_STATUS_OK, ident, 1,
4477                                            2, id, id_len);
4478
4479   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4480                           packet->data, packet->len, FALSE);
4481     
4482   silc_buffer_free(packet);
4483
4484  out:
4485   if (channel_id)
4486     silc_free(channel_id);
4487   silc_server_command_free(cmd);
4488 }
4489
4490 /* Server side command of CLOSE. Closes connection to a specified server. */
4491  
4492 SILC_SERVER_CMD_FUNC(close)
4493 {
4494   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4495   SilcServer server = cmd->server;
4496   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4497   SilcServerEntry server_entry;
4498   SilcSocketConnection sock;
4499   unsigned char *tmp;
4500   uint32 tmp_len;
4501   unsigned char *name;
4502   uint32 port = SILC_PORT;
4503
4504   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4505
4506   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4507     goto out;
4508
4509   /* Check whether client has the permissions. */
4510   if (client->mode == SILC_UMODE_NONE) {
4511     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4512                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4513     goto out;
4514   }
4515
4516   /* Get the remote server */
4517   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4518   if (!name) {
4519     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4520                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4521     goto out;
4522   }
4523
4524   /* Get port */
4525   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4526   if (tmp)
4527     SILC_GET32_MSB(port, tmp);
4528
4529   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4530                                                  name, port, NULL);
4531   if (!server_entry) {
4532     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4533                                           SILC_STATUS_ERR_NO_SERVER_ID);
4534     goto out;
4535   }
4536
4537   /* Send reply to the sender */
4538   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4539                                         SILC_STATUS_OK);
4540
4541   /* Close the connection to the server */
4542   sock = (SilcSocketConnection)server_entry->connection;
4543   silc_server_free_sock_user_data(server, sock);
4544   silc_server_close_connection(server, sock);
4545   
4546  out:
4547   silc_server_command_free(cmd);
4548 }
4549
4550 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4551    active connections. */
4552  
4553 SILC_SERVER_CMD_FUNC(shutdown)
4554 {
4555   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4556   SilcServer server = cmd->server;
4557   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4558
4559   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4560
4561   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4562     goto out;
4563
4564   /* Check whether client has the permission. */
4565   if (client->mode == SILC_UMODE_NONE) {
4566     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4567                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4568     goto out;
4569   }
4570
4571   /* Send reply to the sender */
4572   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4573                                         SILC_STATUS_OK);
4574
4575   /* Then, gracefully, or not, bring the server down. */
4576   silc_server_stop(server);
4577   exit(0);
4578
4579  out:
4580   silc_server_command_free(cmd);
4581 }
4582  
4583 /* Server side command of LEAVE. Removes client from a channel. */
4584
4585 SILC_SERVER_CMD_FUNC(leave)
4586 {
4587   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4588   SilcServer server = cmd->server;
4589   SilcSocketConnection sock = cmd->sock;
4590   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4591   SilcChannelID *id = NULL;
4592   SilcChannelEntry channel;
4593   uint32 len;
4594   unsigned char *tmp;
4595
4596   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4597
4598   /* Get Channel ID */
4599   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4600   if (!tmp) {
4601     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4603     goto out;
4604   }
4605   id = silc_id_payload_parse_id(tmp, len);
4606   if (!id) {
4607     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4608                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4609     goto out;
4610   }
4611
4612   /* Get channel entry */
4613   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4614   if (!channel) {
4615     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4616     if (!channel) {
4617       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4618                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4619       goto out;
4620     }
4621   }
4622
4623   /* Check whether this client is on the channel */
4624   if (!silc_server_client_on_channel(id_entry, channel)) {
4625     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4626                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4627     goto out;
4628   }
4629
4630   /* Notify routers that they should remove this client from their list
4631      of clients on the channel. Send LEAVE notify type. */
4632   if (!server->standalone)
4633     silc_server_send_notify_leave(server, server->router->connection,
4634                                   server->server_type == SILC_ROUTER ?
4635                                   TRUE : FALSE, channel, id_entry->id);
4636
4637   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4638                                         SILC_STATUS_OK);
4639
4640   /* Remove client from channel */
4641   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4642                                            TRUE))
4643     /* If the channel does not exist anymore we won't send anything */
4644     goto out;
4645
4646   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4647     /* Re-generate channel key */
4648     silc_server_create_channel_key(server, channel, 0);
4649
4650     /* Send the channel key */
4651     silc_server_send_channel_key(server, NULL, channel, 
4652                                  server->server_type == SILC_ROUTER ? 
4653                                  FALSE : !server->standalone);
4654   }
4655
4656  out:
4657   if (id)
4658     silc_free(id);
4659   silc_server_command_free(cmd);
4660 }
4661
4662 /* Server side of command USERS. Resolves clients and their USERS currently
4663    joined on the requested channel. The list of Client ID's and their modes
4664    on the channel is sent back. */
4665
4666 SILC_SERVER_CMD_FUNC(users)
4667 {
4668   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4669   SilcServer server = cmd->server;
4670   SilcChannelEntry channel;
4671   SilcChannelID *id;
4672   SilcBuffer packet;
4673   unsigned char *channel_id;
4674   uint32 channel_id_len;
4675   SilcBuffer client_id_list;
4676   SilcBuffer client_mode_list;
4677   unsigned char lc[4];
4678   uint32 list_count = 0;
4679   uint16 ident = silc_command_get_ident(cmd->payload);
4680
4681   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4682
4683   /* Get Channel ID */
4684   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4685   if (!channel_id) {
4686     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4687                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4688     goto out;
4689   }
4690   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4691   if (!id) {
4692     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4693                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4694     goto out;
4695   }
4696
4697   /* If we are server and we don't know about this channel we will send
4698      the command to our router. If we know about the channel then we also
4699      have the list of users already. */
4700   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4701   if (!channel) {
4702     if (server->server_type == SILC_SERVER && !server->standalone &&
4703         !cmd->pending) {
4704       SilcBuffer tmpbuf;
4705       
4706       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4707       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4708       
4709       /* Send USERS command */
4710       silc_server_packet_send(server, server->router->connection,
4711                               SILC_PACKET_COMMAND, cmd->packet->flags,
4712                               tmpbuf->data, tmpbuf->len, TRUE);
4713       
4714       /* Reprocess this packet after received reply */
4715       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4716                                   silc_command_get_ident(cmd->payload),
4717                                   silc_server_command_destructor,
4718                                   silc_server_command_users,
4719                                   silc_server_command_dup(cmd));
4720       cmd->pending = TRUE;
4721       silc_command_set_ident(cmd->payload, ident);
4722       
4723       silc_buffer_free(tmpbuf);
4724       silc_free(id);
4725       return;
4726     }
4727
4728     /* We are router and we will check the global list as well. */
4729     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4730     if (!channel) {
4731       /* Channel really does not exist */
4732       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4733                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4734       goto out;
4735     }
4736   }
4737
4738   /* Get the users list */
4739   silc_server_get_users_on_channel(server, channel, &client_id_list,
4740                                    &client_mode_list, &list_count);
4741
4742   /* List count */
4743   SILC_PUT32_MSB(list_count, lc);
4744
4745   /* Send reply */
4746   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4747                                                 SILC_STATUS_OK, ident, 4,
4748                                                 2, channel_id, channel_id_len,
4749                                                 3, lc, 4,
4750                                                 4, client_id_list->data,
4751                                                 client_id_list->len,
4752                                                 5, client_mode_list->data,
4753                                                 client_mode_list->len);
4754   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4755                           packet->data, packet->len, FALSE);
4756     
4757   silc_buffer_free(packet);
4758   silc_buffer_free(client_id_list);
4759   silc_buffer_free(client_mode_list);
4760   silc_free(id);
4761
4762  out:
4763   silc_server_command_free(cmd);
4764 }
4765
4766 /* Server side of command GETKEY. This fetches the client's public key
4767    from the server where to the client is connected. */
4768
4769 SILC_SERVER_CMD_FUNC(getkey)
4770 {
4771   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4772   SilcServer server = cmd->server;
4773   SilcBuffer packet;
4774   SilcClientEntry client;
4775   SilcServerEntry server_entry;
4776   SilcClientID *client_id = NULL;
4777   SilcServerID *server_id = NULL;
4778   SilcIDPayload idp = NULL;
4779   uint16 ident = silc_command_get_ident(cmd->payload);
4780   unsigned char *tmp;
4781   uint32 tmp_len;
4782   SilcBuffer pk;
4783   SilcIdType id_type;
4784
4785   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4786   if (!tmp) {
4787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4788                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4789     goto out;
4790   }
4791   idp = silc_id_payload_parse_data(tmp, tmp_len);
4792   if (!idp) {
4793     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4794                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4795     goto out;
4796   }
4797
4798   id_type = silc_id_payload_get_type(idp);
4799   if (id_type == SILC_ID_CLIENT) {
4800     client_id = silc_id_payload_get_id(idp);
4801
4802     /* If the client is not found from local list there is no chance it
4803        would be locally connected client so send the command further. */
4804     client = silc_idlist_find_client_by_id(server->local_list, 
4805                                            client_id, NULL);
4806     
4807     if ((!client && !cmd->pending && !server->standalone) ||
4808         (client && !client->connection)) {
4809       SilcBuffer tmpbuf;
4810       uint16 old_ident;
4811       SilcSocketConnection dest_sock;
4812       
4813       dest_sock = silc_server_get_client_route(server, NULL, 0, 
4814                                                client_id, NULL);
4815       if (!dest_sock)
4816         goto out;
4817       
4818       old_ident = silc_command_get_ident(cmd->payload);
4819       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4820       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4821       
4822       silc_server_packet_send(server, dest_sock,
4823                               SILC_PACKET_COMMAND, cmd->packet->flags,
4824                               tmpbuf->data, tmpbuf->len, TRUE);
4825       
4826       /* Reprocess this packet after received reply from router */
4827       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4828                                   silc_command_get_ident(cmd->payload),
4829                                   silc_server_command_destructor,
4830                                   silc_server_command_getkey,
4831                                   silc_server_command_dup(cmd));
4832       cmd->pending = TRUE;
4833       
4834       silc_command_set_ident(cmd->payload, old_ident);
4835       silc_buffer_free(tmpbuf);
4836       return;
4837     }
4838
4839     if (!client && cmd->pending) {
4840       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4841                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4842       goto out;
4843     }
4844
4845     /* The client is locally connected, just get the public key and
4846        send it back. */
4847     tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4848     pk = silc_buffer_alloc(4 + tmp_len);
4849     silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4850     silc_buffer_format(pk,
4851                        SILC_STR_UI_SHORT(tmp_len),
4852                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4853                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
4854                        SILC_STR_END);
4855     silc_free(tmp);
4856
4857   } else if (id_type == SILC_ID_SERVER) {
4858     server_id = silc_id_payload_get_id(idp);
4859
4860     /* If the server is not found from local list there is no chance it
4861        would be locally connected server so send the command further. */
4862     server_entry = silc_idlist_find_server_by_id(server->local_list, 
4863                                                  server_id, NULL);
4864     
4865     if ((!server_entry && !cmd->pending && !server->standalone) ||
4866         (server_entry && !server_entry->connection)) {
4867       SilcBuffer tmpbuf;
4868       uint16 old_ident;
4869       
4870       old_ident = silc_command_get_ident(cmd->payload);
4871       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4872       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4873       
4874       silc_server_packet_send(server, server->router->connection,
4875                               SILC_PACKET_COMMAND, cmd->packet->flags,
4876                               tmpbuf->data, tmpbuf->len, TRUE);
4877       
4878       /* Reprocess this packet after received reply from router */
4879       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4880                                   silc_command_get_ident(cmd->payload),
4881                                   silc_server_command_destructor,
4882                                   silc_server_command_getkey,
4883                                   silc_server_command_dup(cmd));
4884       cmd->pending = TRUE;
4885       
4886       silc_command_set_ident(cmd->payload, old_ident);
4887       silc_buffer_free(tmpbuf);
4888       return;
4889     }
4890
4891     if (!server_entry && cmd->pending) {
4892       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4893                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4894       goto out;
4895     }
4896
4897     /* The client is locally connected, just get the public key and
4898        send it back. */
4899     tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4900     pk = silc_buffer_alloc(4 + tmp_len);
4901     silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4902     silc_buffer_format(pk,
4903                        SILC_STR_UI_SHORT(tmp_len),
4904                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4905                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
4906                        SILC_STR_END);
4907     silc_free(tmp);
4908   } else {
4909     goto out;
4910   }
4911
4912   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4913   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4914                                                 SILC_STATUS_OK, ident, 2,
4915                                                 2, tmp, tmp_len,
4916                                                 3, pk->data, pk->len);
4917   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4918                           packet->data, packet->len, FALSE);
4919   silc_buffer_free(packet);
4920   silc_buffer_free(pk);
4921
4922  out:
4923   if (idp)
4924     silc_id_payload_free(idp);
4925   silc_free(client_id);
4926   silc_free(server_id);
4927   silc_server_command_free(cmd);
4928 }