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