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, client->id);
1768
1769   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1770
1771   /* Free old ID */
1772   if (client->id)
1773     silc_free(client->id);
1774
1775   /* Save the nickname as this client is our local client */
1776   if (client->nickname)
1777     silc_free(client->nickname);
1778
1779   client->nickname = strdup(nick);
1780   client->id = new_id;
1781
1782   /* Update client cache */
1783   silc_idcache_add(server->local_list->clients, client->nickname, 
1784                    strlen(client->nickname), client->id, 
1785                    (void *)client, FALSE);
1786
1787   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1788
1789   /* Send NICK_CHANGE notify to the client's channels */
1790   silc_server_send_notify_on_channels(server, NULL, client, 
1791                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1792                                       oidp->data, oidp->len, 
1793                                       nidp->data, nidp->len);
1794
1795   /* Send the new Client ID as reply command back to client */
1796   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1797                                                 SILC_STATUS_OK, ident, 1, 
1798                                                 2, nidp->data, nidp->len);
1799   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1800                           0, packet->data, packet->len, FALSE);
1801
1802   silc_buffer_free(packet);
1803   silc_buffer_free(nidp);
1804   silc_buffer_free(oidp);
1805   
1806  out:
1807   silc_server_command_free(cmd);
1808 }
1809
1810 /* Sends the LIST command reply */
1811
1812 static void
1813 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1814                                     SilcChannelEntry *lch, 
1815                                     uint32 lch_count,
1816                                     SilcChannelEntry *gch,
1817                                     uint32 gch_count)
1818 {
1819   int i;
1820   SilcBuffer packet, idp;
1821   SilcChannelEntry entry;
1822   SilcCommandStatus status;
1823   uint16 ident = silc_command_get_ident(cmd->payload);
1824   char *topic;
1825   unsigned char usercount[4];
1826   uint32 users;
1827
1828   for (i = 0; i < lch_count; i++)
1829     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1830       lch[i] = NULL;
1831   for (i = 0; i < gch_count; i++)
1832     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1833       gch[i] = NULL;
1834
1835   status = SILC_STATUS_OK;
1836   if ((lch_count + gch_count) > 1)
1837     status = SILC_STATUS_LIST_START;
1838
1839   /* Local list */
1840   for (i = 0; i < lch_count; i++) {
1841     entry = lch[i];
1842
1843     if (!entry)
1844       continue;
1845
1846     if (i >= 1)
1847       status = SILC_STATUS_LIST_ITEM;
1848
1849     if (i == lch_count - 1 && gch_count)
1850       break;
1851     if (lch_count > 1 && i == lch_count - 1)
1852       status = SILC_STATUS_LIST_END;
1853
1854     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1855
1856     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1857       topic = "*private*";
1858       memset(usercount, 0, sizeof(usercount));
1859     } else {
1860       topic = entry->topic;
1861       users = silc_list_count(entry->user_list);
1862       SILC_PUT32_MSB(users, usercount);
1863     }
1864
1865     /* Send the reply */
1866     if (topic)
1867       packet = 
1868         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1869                                              status, ident, 4, 
1870                                              2, idp->data, idp->len,
1871                                              3, entry->channel_name, 
1872                                              strlen(entry->channel_name),
1873                                              4, topic, strlen(topic),
1874                                              5, usercount, 4);
1875     else
1876       packet = 
1877         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1878                                              status, ident, 3, 
1879                                              2, idp->data, idp->len,
1880                                              3, entry->channel_name, 
1881                                              strlen(entry->channel_name),
1882                                              5, usercount, 4);
1883     silc_server_packet_send(cmd->server, cmd->sock, 
1884                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1885                             packet->len, FALSE);
1886     silc_buffer_free(packet);
1887     silc_buffer_free(idp);
1888   }
1889
1890   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1891
1892   /* Global list */
1893   for (i = 0; i < gch_count; i++) {
1894     entry = gch[i];
1895
1896     if (!entry)
1897       continue;
1898
1899     if (i >= 1)
1900       status = SILC_STATUS_LIST_ITEM;
1901
1902     if (gch_count > 1 && i == lch_count - 1)
1903       status = SILC_STATUS_LIST_END;
1904
1905     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1906
1907     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1908       topic = "*private*";
1909       memset(usercount, 0, sizeof(usercount));
1910     } else {
1911       topic = entry->topic;
1912       users = silc_list_count(entry->user_list);
1913       SILC_PUT32_MSB(users, usercount);
1914     }
1915
1916     /* Send the reply */
1917     if (topic)
1918       packet = 
1919         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1920                                              status, ident, 4, 
1921                                              2, idp->data, idp->len,
1922                                              3, entry->channel_name, 
1923                                              strlen(entry->channel_name),
1924                                              4, topic, strlen(topic),
1925                                              5, usercount, 4);
1926     else
1927       packet = 
1928         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1929                                              status, ident, 3, 
1930                                              2, idp->data, idp->len,
1931                                              3, entry->channel_name, 
1932                                              strlen(entry->channel_name),
1933                                              5, usercount, 4);
1934     silc_server_packet_send(cmd->server, cmd->sock, 
1935                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1936                             packet->len, FALSE);
1937     silc_buffer_free(packet);
1938     silc_buffer_free(idp);
1939   }
1940 }
1941
1942 /* Server side of LIST command. This lists the channel of the requested
1943    server. Secret channels are not listed. */
1944
1945 SILC_SERVER_CMD_FUNC(list)
1946 {
1947   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1948   SilcServer server = cmd->server;
1949   SilcChannelID *channel_id = NULL;
1950   unsigned char *tmp;
1951   uint32 tmp_len;
1952   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1953   uint32 lch_count = 0, gch_count = 0;
1954
1955   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1956
1957   /* Get Channel ID */
1958   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1959   if (tmp) {
1960     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1961     if (!channel_id) {
1962       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1963                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
1964       goto out;
1965     }
1966   }
1967
1968   /* Get the channels from local list */
1969   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1970                                        &lch_count);
1971   
1972   /* Get the channels from global list if we are router */
1973   if (server->server_type == SILC_ROUTER) 
1974     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1975                                          &gch_count);
1976
1977   /* Send the reply */
1978   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
1979                                       gchannels, gch_count);
1980
1981  out:
1982   silc_server_command_free(cmd);
1983 }
1984
1985 /* Server side of TOPIC command. Sets topic for channel and/or returns
1986    current topic to client. */
1987
1988 SILC_SERVER_CMD_FUNC(topic)
1989 {
1990   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1991   SilcServer server = cmd->server;
1992   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1993   SilcChannelID *channel_id;
1994   SilcChannelEntry channel;
1995   SilcChannelClientEntry chl;
1996   SilcBuffer packet, idp;
1997   unsigned char *tmp;
1998   uint32 argc, tmp_len;
1999   uint16 ident = silc_command_get_ident(cmd->payload);
2000
2001   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
2002
2003   argc = silc_argument_get_arg_num(cmd->args);
2004
2005   /* Get Channel ID */
2006   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2007   if (!tmp) {
2008     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2009                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2010     goto out;
2011   }
2012   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2013   if (!channel_id) {
2014     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2015                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2016     goto out;
2017   }
2018
2019   /* Check whether the channel exists */
2020   channel = silc_idlist_find_channel_by_id(server->local_list, 
2021                                            channel_id, NULL);
2022   if (!channel) {
2023     channel = silc_idlist_find_channel_by_id(server->global_list, 
2024                                              channel_id, NULL);
2025     if (!channel) {
2026       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2027                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2028       goto out;
2029     }
2030   }
2031
2032   if (argc > 1) {
2033     /* Get the topic */
2034     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2035     if (!tmp) {
2036       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2037                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2038       goto out;
2039     }
2040
2041     if (strlen(tmp) > 256) {
2042       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2044       goto out;
2045     }
2046
2047     /* See whether has rights to change topic */
2048     silc_list_start(channel->user_list);
2049     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2050       if (chl->client == client)
2051         break;
2052
2053     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2054       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2055         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2056                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2057         goto out;
2058       }
2059     }
2060
2061     /* Set the topic for channel */
2062     if (channel->topic)
2063       silc_free(channel->topic);
2064     channel->topic = strdup(tmp);
2065
2066     /* Send TOPIC_SET notify type to the network */
2067     if (!server->standalone)
2068       silc_server_send_notify_topic_set(server, server->router->connection,
2069                                         server->server_type == SILC_ROUTER ?
2070                                         TRUE : FALSE, channel, client->id,
2071                                         channel->topic);
2072
2073     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2074
2075     /* Send notify about topic change to all clients on the channel */
2076     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2077                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2078                                        idp->data, idp->len,
2079                                        channel->topic, strlen(channel->topic));
2080     silc_buffer_free(idp);
2081   }
2082
2083   /* Send the topic to client as reply packet */
2084   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2085   if (channel->topic)
2086     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2087                                                   SILC_STATUS_OK, ident, 2, 
2088                                                   2, idp->data, idp->len,
2089                                                   3, channel->topic, 
2090                                                   strlen(channel->topic));
2091   else
2092     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2093                                                   SILC_STATUS_OK, ident, 1, 
2094                                                   2, idp->data, idp->len);
2095   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2096                           0, packet->data, packet->len, FALSE);
2097
2098   silc_buffer_free(packet);
2099   silc_buffer_free(idp);
2100   silc_free(channel_id);
2101
2102  out:
2103   silc_server_command_free(cmd);
2104 }
2105
2106 /* Server side of INVITE command. Invites some client to join some channel. 
2107    This command is also used to manage the invite list of the channel. */
2108
2109 SILC_SERVER_CMD_FUNC(invite)
2110 {
2111   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2112   SilcServer server = cmd->server;
2113   SilcSocketConnection sock = cmd->sock, dest_sock;
2114   SilcChannelClientEntry chl;
2115   SilcClientEntry sender, dest;
2116   SilcClientID *dest_id = NULL;
2117   SilcChannelEntry channel;
2118   SilcChannelID *channel_id = NULL;
2119   SilcIDListData idata;
2120   SilcBuffer idp, idp2, packet;
2121   unsigned char *tmp, *add, *del;
2122   uint32 len;
2123   uint16 ident = silc_command_get_ident(cmd->payload);
2124
2125   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2126
2127   /* Get Channel ID */
2128   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2129   if (!tmp) {
2130     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2131                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2132     goto out;
2133   }
2134   channel_id = silc_id_payload_parse_id(tmp, len);
2135   if (!channel_id) {
2136     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2137                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2138     goto out;
2139   }
2140
2141   /* Get the channel entry */
2142   channel = silc_idlist_find_channel_by_id(server->local_list, 
2143                                            channel_id, NULL);
2144   if (!channel) {
2145     channel = silc_idlist_find_channel_by_id(server->global_list, 
2146                                              channel_id, NULL);
2147     if (!channel) {
2148       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2149                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2150       goto out;
2151     }
2152   }
2153
2154   /* Check whether the sender of this command is on the channel. */
2155   sender = (SilcClientEntry)sock->user_data;
2156   if (!silc_server_client_on_channel(sender, channel)) {
2157     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2158                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2159     goto out;
2160   }
2161
2162   /* Check whether the channel is invite-only channel. If yes then the
2163      sender of this command must be at least channel operator. */
2164   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2165     silc_list_start(channel->user_list);
2166     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2167       if (chl->client == sender) {
2168         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2169           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2170                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2171           goto out;
2172         }
2173         break;
2174       }
2175   }
2176
2177   /* Get destination client ID */
2178   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2179   if (tmp) {
2180     char invite[512];
2181
2182     dest_id = silc_id_payload_parse_id(tmp, len);
2183     if (!dest_id) {
2184       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2185                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2186       goto out;
2187     }
2188
2189     /* Get the client entry */
2190     dest = silc_server_get_client_resolve(server, dest_id);
2191     if (!dest) {
2192       if (server->server_type == SILC_ROUTER) {
2193         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2194                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2195         goto out;
2196       }
2197       
2198       /* The client info is being resolved. Reprocess this packet after
2199          receiving the reply to the query. */
2200       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2201                                   server->cmd_ident,
2202                                   silc_server_command_destructor,
2203                                   silc_server_command_invite, 
2204                                   silc_server_command_dup(cmd));
2205       cmd->pending = TRUE;
2206       silc_free(channel_id);
2207       silc_free(dest_id);
2208       return;
2209     }
2210
2211     /* Check whether the requested client is already on the channel. */
2212     if (silc_server_client_on_channel(dest, channel)) {
2213       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2214                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2215       goto out;
2216     }
2217     
2218     /* Get route to the client */
2219     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2220
2221     memset(invite, 0, sizeof(invite));
2222     strncat(invite, dest->nickname, strlen(dest->nickname));
2223     strncat(invite, "!", 1);
2224     strncat(invite, dest->username, strlen(dest->username));
2225     if (!strchr(dest->username, '@')) {
2226       strncat(invite, "@", 1);
2227       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2228     }
2229
2230     len = strlen(invite);
2231     if (!channel->invite_list)
2232       channel->invite_list = silc_calloc(len + 2, 
2233                                          sizeof(*channel->invite_list));
2234     else
2235       channel->invite_list = silc_realloc(channel->invite_list, 
2236                                           sizeof(*channel->invite_list) * 
2237                                           (len + 
2238                                            strlen(channel->invite_list) + 2));
2239     strncat(channel->invite_list, invite, len);
2240     strncat(channel->invite_list, ",", 1);
2241
2242     /* Send notify to the client that is invited to the channel */
2243     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2244     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2245     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2246                                  SILC_ID_CLIENT,
2247                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2248                                  idp->data, idp->len, 
2249                                  channel->channel_name, 
2250                                  strlen(channel->channel_name),
2251                                  idp2->data, idp2->len);
2252     silc_buffer_free(idp);
2253     silc_buffer_free(idp2);
2254   }
2255
2256   /* Add the client to the invite list of the channel */
2257   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2258   if (add) {
2259     if (!channel->invite_list)
2260       channel->invite_list = silc_calloc(len + 2, 
2261                                          sizeof(*channel->invite_list));
2262     else
2263       channel->invite_list = silc_realloc(channel->invite_list, 
2264                                           sizeof(*channel->invite_list) * 
2265                                           (len + 
2266                                            strlen(channel->invite_list) + 2));
2267     if (add[len - 1] == ',')
2268       add[len - 1] = '\0';
2269     
2270     strncat(channel->invite_list, add, len);
2271     strncat(channel->invite_list, ",", 1);
2272   }
2273
2274   /* Get the invite to be removed and remove it from the list */
2275   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2276   if (del && channel->invite_list) {
2277     char *start, *end, *n;
2278
2279     if (!strncmp(channel->invite_list, del, 
2280                  strlen(channel->invite_list) - 1)) {
2281       silc_free(channel->invite_list);
2282       channel->invite_list = NULL;
2283     } else {
2284       start = strstr(channel->invite_list, del);
2285       if (start && strlen(start) >= len) {
2286         end = start + len;
2287         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2288         strncat(n, channel->invite_list, start - channel->invite_list);
2289         strncat(n, end + 1, ((channel->invite_list + 
2290                               strlen(channel->invite_list)) - end) - 1);
2291         silc_free(channel->invite_list);
2292         channel->invite_list = n;
2293       }
2294     }
2295   }
2296
2297   /* Send notify to the primary router */
2298   if (!server->standalone)
2299     silc_server_send_notify_invite(server, server->router->connection,
2300                                    server->server_type == SILC_ROUTER ?
2301                                    TRUE : FALSE, channel,
2302                                    sender->id, add, del);
2303
2304   /* Send command reply */
2305   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2306   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2307                                                 SILC_STATUS_OK, ident, 2,
2308                                                 2, tmp, len,
2309                                                 3, channel->invite_list,
2310                                                 channel->invite_list ?
2311                                                 strlen(channel->invite_list) :
2312                                                 0);
2313   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2314                           packet->data, packet->len, FALSE);
2315   silc_buffer_free(packet);
2316
2317  out:
2318   if (dest_id)
2319     silc_free(dest_id);
2320   if (channel_id)
2321     silc_free(channel_id);
2322   silc_server_command_free(cmd);
2323 }
2324
2325 typedef struct {
2326   SilcServer server;
2327   SilcSocketConnection sock;
2328   char *signoff;
2329 } *QuitInternal;
2330
2331 /* Quits connection to client. This gets called if client won't
2332    close the connection even when it has issued QUIT command. */
2333
2334 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2335 {
2336   QuitInternal q = (QuitInternal)context;
2337
2338   /* Free all client specific data, such as client entry and entires
2339      on channels this client may be on. */
2340   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2341                                TRUE, q->signoff);
2342   q->sock->user_data = NULL;
2343
2344   /* Close the connection on our side */
2345   silc_server_close_connection(q->server, q->sock);
2346
2347   silc_free(q->signoff);
2348   silc_free(q);
2349 }
2350
2351 /* Quits SILC session. This is the normal way to disconnect client. */
2352  
2353 SILC_SERVER_CMD_FUNC(quit)
2354 {
2355   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2356   SilcServer server = cmd->server;
2357   SilcSocketConnection sock = cmd->sock;
2358   QuitInternal q;
2359   unsigned char *tmp = NULL;
2360   uint32 len = 0;
2361
2362   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2363
2364   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2365     goto out;
2366
2367   /* Get destination ID */
2368   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2369   if (len > 128)
2370     tmp = NULL;
2371
2372   q = silc_calloc(1, sizeof(*q));
2373   q->server = server;
2374   q->sock = sock;
2375   q->signoff = tmp ? strdup(tmp) : NULL;
2376
2377   /* We quit the connection with little timeout */
2378   silc_task_register(server->timeout_queue, sock->sock,
2379                      silc_server_command_quit_cb, (void *)q,
2380                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2381
2382  out:
2383   silc_server_command_free(cmd);
2384 }
2385
2386 /* Server side of command KILL. This command is used by router operator
2387    to remove an client from the SILC Network temporarily. */
2388
2389 SILC_SERVER_CMD_FUNC(kill)
2390 {
2391   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2392   SilcServer server = cmd->server;
2393   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2394   SilcClientEntry remote_client;
2395   SilcClientID *client_id;
2396   unsigned char *tmp, *comment;
2397   uint32 tmp_len, tmp_len2;
2398
2399   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2400
2401   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2402     goto out;
2403
2404   /* KILL command works only on router */
2405   if (server->server_type != SILC_ROUTER) {
2406     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2407                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2408     goto out;
2409   }
2410
2411   /* Check whether client has the permissions. */
2412   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2413     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2414                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2415     goto out;
2416   }
2417
2418   /* Get the client ID */
2419   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2420   if (!tmp) {
2421     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2422                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2423     goto out;
2424   }
2425   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2426   if (!client_id) {
2427     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2428                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2429     goto out;
2430   }
2431
2432   /* Get the client entry */
2433   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2434                                                 client_id, NULL);
2435   if (!remote_client) {
2436     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2437                                                   client_id, NULL);
2438     if (!remote_client) {
2439       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2440                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2441       goto out;
2442     }
2443   }
2444
2445   /* Get comment */
2446   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2447   if (tmp_len2 > 128)
2448     comment = NULL;
2449
2450   /* Send reply to the sender */
2451   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2452                                         SILC_STATUS_OK);
2453
2454   /* Send the KILL notify packets. First send it to the channel, then
2455      to our primary router and then directly to the client who is being
2456      killed right now. */
2457
2458   /* Send KILLED notify to the channels. It is not sent to the client
2459      as it will be sent differently destined directly to the client and not
2460      to the channel. */
2461   silc_server_send_notify_on_channels(server, remote_client, 
2462                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2463                                       comment ? 2 : 1,
2464                                       tmp, tmp_len,
2465                                       comment, comment ? tmp_len2 : 0);
2466
2467   /* Send KILLED notify to primary route */
2468   if (!server->standalone)
2469     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2470                                    remote_client->id, comment);
2471
2472   /* Send KILLED notify to the client directly */
2473   silc_server_send_notify_killed(server, remote_client->connection ? 
2474                                  remote_client->connection : 
2475                                  remote_client->router->connection, FALSE,
2476                                  remote_client->id, comment);
2477
2478   /* Remove the client from all channels. This generates new keys to the
2479      channels as well. */
2480   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2481                                    NULL, TRUE);
2482
2483   /* Remove the client entry, If it is locally connected then we will also
2484      disconnect the client here */
2485   if (remote_client->data.registered && remote_client->connection) {
2486     /* Remove locally conneted client */
2487     SilcSocketConnection sock = remote_client->connection;
2488     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2489     silc_server_close_connection(server, sock);
2490   } else {
2491     /* Remove remote client */
2492     if (!silc_idlist_del_client(server->global_list, remote_client))
2493       silc_idlist_del_client(server->local_list, remote_client);
2494   }
2495
2496  out:
2497   silc_server_command_free(cmd);
2498 }
2499
2500 /* Server side of command INFO. This sends information about us to 
2501    the client. If client requested specific server we will send the 
2502    command to that server. */
2503
2504 SILC_SERVER_CMD_FUNC(info)
2505 {
2506   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2507   SilcServer server = cmd->server;
2508   SilcBuffer packet, idp;
2509   unsigned char *tmp;
2510   uint32 tmp_len;
2511   char *dest_server, *server_info = NULL, *server_name;
2512   uint16 ident = silc_command_get_ident(cmd->payload);
2513   SilcServerEntry entry = NULL;
2514   SilcServerID *server_id = NULL;
2515
2516   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 0, 2);
2517
2518   /* Get server name */
2519   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2520
2521   /* Get Server ID */
2522   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2523   if (tmp) {
2524     server_id = silc_id_payload_parse_id(tmp, tmp_len);
2525     if (!server_id) {
2526       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2527                                             SILC_STATUS_ERR_NO_SERVER_ID);
2528       goto out;
2529     }
2530   }
2531
2532   if (server_id) {
2533     /* Check whether we have this server cached */
2534     entry = silc_idlist_find_server_by_id(server->local_list,
2535                                           server_id, NULL);
2536     if (!entry) {
2537       entry = silc_idlist_find_server_by_id(server->global_list,
2538                                             server_id, NULL);
2539       if (!entry && server->server_type == SILC_ROUTER) {
2540         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2541                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2542         goto out;
2543       }
2544     }
2545   }
2546
2547   if ((!dest_server && !server_id) || 
2548       (dest_server && !cmd->pending && 
2549        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2550     /* Send our reply */
2551     char info_string[256];
2552
2553     memset(info_string, 0, sizeof(info_string));
2554     snprintf(info_string, sizeof(info_string), 
2555              "location: %s server: %s admin: %s <%s>",
2556              server->config->admin_info->location,
2557              server->config->admin_info->server_type,
2558              server->config->admin_info->admin_name,
2559              server->config->admin_info->admin_email);
2560
2561     server_info = info_string;
2562     entry = server->id_entry;
2563   } else {
2564     /* Check whether we have this server cached */
2565     if (!entry && dest_server) {
2566       entry = silc_idlist_find_server_by_name(server->global_list,
2567                                               dest_server, NULL);
2568       if (!entry) {
2569         entry = silc_idlist_find_server_by_name(server->local_list,
2570                                                 dest_server, NULL);
2571       }
2572     }
2573
2574     if (!cmd->pending &&
2575         server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2576       /* Send to the server */
2577       SilcBuffer tmpbuf;
2578       uint16 old_ident;
2579
2580       old_ident = silc_command_get_ident(cmd->payload);
2581       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2582       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2583
2584       silc_server_packet_send(server, entry->connection,
2585                               SILC_PACKET_COMMAND, cmd->packet->flags,
2586                               tmpbuf->data, tmpbuf->len, TRUE);
2587
2588       /* Reprocess this packet after received reply from router */
2589       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2590                                   silc_command_get_ident(cmd->payload),
2591                                   silc_server_command_destructor,
2592                                   silc_server_command_info,
2593                                   silc_server_command_dup(cmd));
2594       cmd->pending = TRUE;
2595       silc_command_set_ident(cmd->payload, old_ident);
2596       silc_buffer_free(tmpbuf);
2597       return;
2598     }
2599
2600     if (!entry && !cmd->pending && !server->standalone) {
2601       /* Send to the primary router */
2602       SilcBuffer tmpbuf;
2603       uint16 old_ident;
2604
2605       old_ident = silc_command_get_ident(cmd->payload);
2606       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2607       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2608
2609       silc_server_packet_send(server, server->router->connection,
2610                               SILC_PACKET_COMMAND, cmd->packet->flags,
2611                               tmpbuf->data, tmpbuf->len, TRUE);
2612
2613       /* Reprocess this packet after received reply from router */
2614       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2615                                   silc_command_get_ident(cmd->payload),
2616                                   silc_server_command_destructor,
2617                                   silc_server_command_info,
2618                                   silc_server_command_dup(cmd));
2619       cmd->pending = TRUE;
2620       silc_command_set_ident(cmd->payload, old_ident);
2621       silc_buffer_free(tmpbuf);
2622       return;
2623     }
2624   }
2625
2626   if (server_id)
2627     silc_free(server_id);
2628
2629   if (!entry) {
2630     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2631                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2632     goto out;
2633   }
2634
2635   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2636   if (!server_info)
2637     server_info = entry->server_info;
2638   server_name = entry->server_name;
2639
2640   /* Send the reply */
2641   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2642                                                 SILC_STATUS_OK, ident, 3,
2643                                                 2, idp->data, idp->len,
2644                                                 3, server_name, 
2645                                                 strlen(server_name),
2646                                                 4, server_info, 
2647                                                 strlen(server_info));
2648   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2649                           packet->data, packet->len, FALSE);
2650     
2651   silc_buffer_free(packet);
2652   silc_buffer_free(idp);
2653
2654  out:
2655   silc_server_command_free(cmd);
2656 }
2657
2658 /* Server side of command PING. This just replies to the ping. */
2659
2660 SILC_SERVER_CMD_FUNC(ping)
2661 {
2662   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2663   SilcServer server = cmd->server;
2664   SilcServerID *id;
2665   uint32 len;
2666   unsigned char *tmp;
2667
2668   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2669
2670   /* Get Server ID */
2671   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2672   if (!tmp) {
2673     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2674                                           SILC_STATUS_ERR_NO_SERVER_ID);
2675     goto out;
2676   }
2677   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2678   if (!id)
2679     goto out;
2680
2681   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2682     /* Send our reply */
2683     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2684                                           SILC_STATUS_OK);
2685   } else {
2686     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2687                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2688     goto out;
2689   }
2690
2691   silc_free(id);
2692
2693  out:
2694   silc_server_command_free(cmd);
2695 }
2696
2697 /* Internal routine to join channel. The channel sent to this function
2698    has been either created or resolved from ID lists. This joins the sent
2699    client to the channel. */
2700
2701 static void silc_server_command_join_channel(SilcServer server, 
2702                                              SilcServerCommandContext cmd,
2703                                              SilcChannelEntry channel,
2704                                              SilcClientID *client_id,
2705                                              int created,
2706                                              uint32 umode)
2707 {
2708   SilcSocketConnection sock = cmd->sock;
2709   unsigned char *tmp;
2710   uint32 tmp_len, user_count;
2711   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2712   SilcClientEntry client;
2713   SilcChannelClientEntry chl;
2714   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2715   uint16 ident = silc_command_get_ident(cmd->payload);
2716   char check[512];
2717
2718   SILC_LOG_DEBUG(("Start"));
2719
2720   if (!channel)
2721     return;
2722
2723   /* Get the client entry */
2724   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2725     client = (SilcClientEntry)sock->user_data;
2726   } else {
2727     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2728                                            NULL);
2729     if (!client)
2730       goto out;
2731   }
2732
2733   /*
2734    * Check channel modes
2735    */
2736
2737   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2738     strncat(check, client->nickname, strlen(client->nickname));
2739     if (!strchr(client->nickname, '@')) {
2740       strncat(check, "@", 1);
2741       strncat(check, server->server_name, strlen(server->server_name));
2742     }
2743     strncat(check, "!", 1);
2744     strncat(check, client->username, strlen(client->username));
2745     if (!strchr(client->username, '@')) {
2746       strncat(check, "@", 1);
2747       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2748     }
2749   }
2750
2751   /* Check invite list if channel is invite-only channel */
2752   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
2753       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2754     if (!channel->invite_list) {
2755       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2756                                             SILC_STATUS_ERR_NOT_INVITED);
2757       goto out;
2758     }
2759
2760     if (!silc_string_match(channel->invite_list, check)) {
2761       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2762                                             SILC_STATUS_ERR_NOT_INVITED);
2763       goto out;
2764     }
2765   }
2766
2767   /* Check ban list if it exists. If the client's nickname, server,
2768      username and/or hostname is in the ban list the access to the
2769      channel is denied. */
2770   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2771     if (silc_string_match(channel->ban_list, check)) {
2772       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2773                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2774       goto out;
2775     }
2776   }
2777
2778   /* Get passphrase */
2779   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2780   if (tmp) {
2781     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2782     memcpy(passphrase, tmp, tmp_len);
2783   }
2784   
2785   /* Check the channel passphrase if set. */
2786   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2787     if (!passphrase || memcmp(channel->passphrase, passphrase,
2788                               strlen(channel->passphrase))) {
2789       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2790                                             SILC_STATUS_ERR_BAD_PASSWORD);
2791       goto out;
2792     }
2793   }
2794
2795   /* Check user count limit if set. */
2796   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2797     if (silc_list_count(channel->user_list) + 1 > 
2798         channel->user_limit) {
2799       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2800                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2801       goto out;
2802     }
2803   }
2804
2805   /*
2806    * Client is allowed to join to the channel. Make it happen.
2807    */
2808
2809   /* Check whether the client already is on the channel */
2810   if (silc_server_client_on_channel(client, channel)) {
2811     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2812                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2813     goto out;
2814   }
2815
2816   /* Generate new channel key as protocol dictates */
2817   if ((!created && silc_list_count(channel->user_list) > 0) || 
2818       !channel->channel_key)
2819     silc_server_create_channel_key(server, channel, 0);
2820
2821   /* Send the channel key. This is broadcasted to the channel but is not
2822      sent to the client who is joining to the channel. */
2823   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2824     silc_server_send_channel_key(server, NULL, channel, 
2825                                  server->server_type == SILC_ROUTER ? 
2826                                  FALSE : !server->standalone);
2827
2828   /* Join the client to the channel by adding it to channel's user list.
2829      Add also the channel to client entry's channels list for fast cross-
2830      referencing. */
2831   chl = silc_calloc(1, sizeof(*chl));
2832   chl->mode = umode;
2833   chl->client = client;
2834   chl->channel = channel;
2835   silc_list_add(channel->user_list, chl);
2836   silc_list_add(client->channels, chl);
2837
2838   /* Get users on the channel */
2839   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2840                                    &user_count);
2841
2842   /* Encode Client ID Payload of the original client who wants to join */
2843   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2844
2845   /* Encode command reply packet */
2846   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2847   SILC_PUT32_MSB(channel->mode, mode);
2848   SILC_PUT32_MSB(created, tmp2);
2849   SILC_PUT32_MSB(user_count, tmp3);
2850
2851   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2852     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2853     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2854                                            strlen(channel->channel_key->
2855                                                   cipher->name),
2856                                            channel->channel_key->cipher->name,
2857                                            channel->key_len / 8, channel->key);
2858     silc_free(tmp);
2859   }
2860
2861   reply = 
2862     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2863                                          SILC_STATUS_OK, ident, 13,
2864                                          2, channel->channel_name,
2865                                          strlen(channel->channel_name),
2866                                          3, chidp->data, chidp->len,
2867                                          4, clidp->data, clidp->len,
2868                                          5, mode, 4,
2869                                          6, tmp2, 4,
2870                                          7, keyp ? keyp->data : NULL, 
2871                                          keyp ? keyp->len : 0,
2872                                          8, channel->ban_list, 
2873                                          channel->ban_list ?
2874                                          strlen(channel->ban_list) : 0,
2875                                          9, channel->invite_list,
2876                                          channel->invite_list ?
2877                                          strlen(channel->invite_list) : 0,
2878                                          10, channel->topic,
2879                                          channel->topic ?
2880                                          strlen(channel->topic) : 0,
2881                                          11, channel->hmac->hmac->name,
2882                                          strlen(channel->hmac->hmac->name),
2883                                          12, tmp3, 4,
2884                                          13, user_list->data, user_list->len,
2885                                          14, mode_list->data, 
2886                                          mode_list->len);
2887
2888   /* Send command reply */
2889   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2890                           reply->data, reply->len, FALSE);
2891
2892   if (!cmd->pending) {
2893     /* Send JOIN notify to locally connected clients on the channel */
2894     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2895                                        SILC_NOTIFY_TYPE_JOIN, 2,
2896                                        clidp->data, clidp->len,
2897                                        chidp->data, chidp->len);
2898
2899     /* Send JOIN notify packet to our primary router */
2900     if (!server->standalone)
2901       silc_server_send_notify_join(server, server->router->connection,
2902                                    server->server_type == SILC_ROUTER ?
2903                                    TRUE : FALSE, channel, client->id);
2904   }
2905
2906   silc_buffer_free(reply);
2907   silc_buffer_free(clidp);
2908   silc_buffer_free(chidp);
2909   silc_buffer_free(keyp);
2910   silc_buffer_free(user_list);
2911   silc_buffer_free(mode_list);
2912
2913  out:
2914   if (passphrase)
2915     silc_free(passphrase);
2916 }
2917
2918 /* Server side of command JOIN. Joins client into requested channel. If 
2919    the channel does not exist it will be created. */
2920
2921 SILC_SERVER_CMD_FUNC(join)
2922 {
2923   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2924   SilcServer server = cmd->server;
2925   uint32 tmp_len;
2926   char *tmp, *channel_name = NULL, *cipher, *hmac;
2927   SilcChannelEntry channel;
2928   uint32 umode = 0;
2929   int created = FALSE;
2930   SilcClientID *client_id;
2931
2932   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2933
2934   /* Get channel name */
2935   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2936   if (!tmp) {
2937     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2938                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2939     goto out;
2940   }
2941   channel_name = tmp;
2942
2943   if (strlen(channel_name) > 256)
2944     channel_name[255] = '\0';
2945
2946   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2947     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2948                                           SILC_STATUS_ERR_BAD_CHANNEL);
2949     silc_free(channel_name);
2950     goto out;
2951   }
2952
2953   /* Get Client ID of the client who is joining to the channel */
2954   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2955   if (!tmp) {
2956     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2957                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2958     goto out;
2959   }
2960   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2961   if (!client_id) {
2962     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2963                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2964     goto out;
2965   }
2966
2967   /* Get cipher and hmac name */
2968   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2969   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2970
2971   /* See if the channel exists */
2972   channel = silc_idlist_find_channel_by_name(server->local_list, 
2973                                              channel_name, NULL);
2974
2975   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2976     /* If this is coming from client the Client ID in the command packet must
2977        be same as the client's ID. */
2978     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2979       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2980       if (!SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2981         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2982                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2983         goto out;
2984       }
2985     }
2986
2987     if (!channel || !channel->id) {
2988       /* Channel not found */
2989
2990       /* If we are standalone server we don't have a router, we just create 
2991          the channel by ourselves. */
2992       if (server->standalone) {
2993         channel = silc_server_create_new_channel(server, server->id, cipher, 
2994                                                  hmac, channel_name, TRUE);
2995         if (!channel) {
2996           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2997                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2998           goto out;
2999         }
3000
3001         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3002         created = TRUE;
3003
3004       } else {
3005
3006         /* The channel does not exist on our server. If we are normal server 
3007            we will send JOIN command to our router which will handle the
3008            joining procedure (either creates the channel if it doesn't exist 
3009            or joins the client to it). */
3010         if (server->server_type == SILC_SERVER) {
3011           SilcBuffer tmpbuf;
3012           uint16 old_ident;
3013           
3014           old_ident = silc_command_get_ident(cmd->payload);
3015           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3016           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3017           
3018           /* Send JOIN command to our router */
3019           silc_server_packet_send(server, (SilcSocketConnection)
3020                                   server->router->connection,
3021                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3022                                   tmpbuf->data, tmpbuf->len, TRUE);
3023           
3024           /* Reprocess this packet after received reply from router */
3025           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3026                                       silc_command_get_ident(cmd->payload),
3027                                       silc_server_command_destructor,
3028                                       silc_server_command_join,
3029                                       silc_server_command_dup(cmd));
3030           cmd->pending = TRUE;
3031           return;
3032         }
3033         
3034         /* We are router and the channel does not seem exist so we will check
3035            our global list as well for the channel. */
3036         channel = silc_idlist_find_channel_by_name(server->global_list, 
3037                                                    channel_name, NULL);
3038         if (!channel) {
3039           /* Channel really does not exist, create it */
3040           channel = silc_server_create_new_channel(server, server->id, cipher, 
3041                                                    hmac, channel_name, TRUE);
3042           if (!channel) {
3043             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3044                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3045             goto out;
3046           }
3047
3048           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3049           created = TRUE;
3050         }
3051       }
3052     }
3053   } else {
3054     if (!channel) {
3055       /* Channel not found */
3056
3057       /* If the command came from router and/or we are normal server then
3058          something went wrong with the joining as the channel was not found.
3059          We can't do anything else but ignore this. */
3060       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3061           server->server_type == SILC_SERVER)
3062         goto out;
3063       
3064       /* We are router and the channel does not seem exist so we will check
3065          our global list as well for the channel. */
3066       channel = silc_idlist_find_channel_by_name(server->global_list, 
3067                                                  channel_name, NULL);
3068       if (!channel) {
3069         /* Channel really does not exist, create it */
3070         channel = silc_server_create_new_channel(server, server->id, cipher, 
3071                                                  hmac, channel_name, TRUE);
3072         if (!channel) {
3073           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3074                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3075           goto out;
3076         }
3077
3078         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3079         created = TRUE;
3080       }
3081     }
3082   }
3083
3084   /* If the channel does not have global users and is also empty it means the
3085      channel was created globally (by our router) and the client will be the
3086      channel founder and operator. */
3087   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3088     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3089     created = TRUE;             /* Created globally by our router */
3090   }
3091
3092   /* Join to the channel */
3093   silc_server_command_join_channel(server, cmd, channel, client_id,
3094                                    created, umode);
3095
3096   silc_free(client_id);
3097
3098  out:
3099   silc_server_command_free(cmd);
3100 }
3101
3102 /* Server side of command MOTD. Sends server's current "message of the
3103    day" to the client. */
3104
3105 SILC_SERVER_CMD_FUNC(motd)
3106 {
3107   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3108   SilcServer server = cmd->server;
3109   SilcBuffer packet, idp;
3110   char *motd, *dest_server;
3111   uint32 motd_len;
3112   uint16 ident = silc_command_get_ident(cmd->payload);
3113   
3114   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3115
3116   /* Get server name */
3117   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3118   if (!dest_server) {
3119     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3120                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3121     goto out;
3122   }
3123
3124   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3125     /* Send our MOTD */
3126
3127     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3128
3129     if (server->config && server->config->motd && 
3130         server->config->motd->motd_file) {
3131       /* Send motd */
3132       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3133       if (!motd)
3134         goto out;
3135       
3136       motd[motd_len] = 0;
3137       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3138                                                     SILC_STATUS_OK, ident, 2,
3139                                                     2, idp, idp->len,
3140                                                     3, motd, motd_len);
3141       goto out;
3142     } else {
3143       /* No motd */
3144       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3145                                                     SILC_STATUS_OK, ident, 1,
3146                                                     2, idp, idp->len);
3147     }
3148
3149     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3150                             packet->data, packet->len, FALSE);
3151     silc_buffer_free(packet);
3152     silc_buffer_free(idp);
3153   } else {
3154     SilcServerEntry entry;
3155
3156     /* Check whether we have this server cached */
3157     entry = silc_idlist_find_server_by_name(server->global_list,
3158                                             dest_server, NULL);
3159     if (!entry) {
3160       entry = silc_idlist_find_server_by_name(server->local_list,
3161                                               dest_server, NULL);
3162     }
3163
3164     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3165         entry && !entry->motd) {
3166       /* Send to the server */
3167       SilcBuffer tmpbuf;
3168       uint16 old_ident;
3169
3170       old_ident = silc_command_get_ident(cmd->payload);
3171       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3172       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3173
3174       silc_server_packet_send(server, entry->connection,
3175                               SILC_PACKET_COMMAND, cmd->packet->flags,
3176                               tmpbuf->data, tmpbuf->len, TRUE);
3177
3178       /* Reprocess this packet after received reply from router */
3179       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3180                                   silc_command_get_ident(cmd->payload),
3181                                   silc_server_command_destructor,
3182                                   silc_server_command_motd,
3183                                   silc_server_command_dup(cmd));
3184       cmd->pending = TRUE;
3185       silc_command_set_ident(cmd->payload, old_ident);
3186       silc_buffer_free(tmpbuf);
3187       return;
3188     }
3189
3190     if (!entry && !cmd->pending && !server->standalone) {
3191       /* Send to the primary router */
3192       SilcBuffer tmpbuf;
3193       uint16 old_ident;
3194
3195       old_ident = silc_command_get_ident(cmd->payload);
3196       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3197       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3198
3199       silc_server_packet_send(server, server->router->connection,
3200                               SILC_PACKET_COMMAND, cmd->packet->flags,
3201                               tmpbuf->data, tmpbuf->len, TRUE);
3202
3203       /* Reprocess this packet after received reply from router */
3204       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3205                                   silc_command_get_ident(cmd->payload),
3206                                   silc_server_command_destructor,
3207                                   silc_server_command_motd,
3208                                   silc_server_command_dup(cmd));
3209       cmd->pending = TRUE;
3210       silc_command_set_ident(cmd->payload, old_ident);
3211       silc_buffer_free(tmpbuf);
3212       return;
3213     }
3214
3215     if (!entry) {
3216       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3217                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3218       goto out;
3219     }
3220
3221     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3222
3223     if (entry->motd)
3224       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3225                                                     SILC_STATUS_OK, ident, 2,
3226                                                     2, idp, idp->len,
3227                                                     3, entry->motd,
3228                                                     strlen(entry->motd));
3229     else
3230       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3231                                                     SILC_STATUS_OK, ident, 1,
3232                                                     2, idp, idp->len);
3233
3234     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3235                             packet->data, packet->len, FALSE);
3236     silc_buffer_free(packet);
3237     silc_buffer_free(idp);
3238   }
3239
3240  out:
3241   silc_server_command_free(cmd);
3242 }
3243
3244 /* Server side of command UMODE. Client can use this command to set/unset
3245    user mode. Client actually cannot set itself to be as server/router
3246    operator so this can be used only to unset the modes. */
3247
3248 SILC_SERVER_CMD_FUNC(umode)
3249 {
3250   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3251   SilcServer server = cmd->server;
3252   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3253   SilcBuffer packet;
3254   unsigned char *tmp_mask;
3255   uint32 mask;
3256   uint16 ident = silc_command_get_ident(cmd->payload);
3257
3258   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3259     goto out;
3260
3261   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3262
3263   /* Get the client's mode mask */
3264   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3265   if (!tmp_mask) {
3266     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3267                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3268     goto out;
3269   }
3270   SILC_GET32_MSB(mask, tmp_mask);
3271
3272   /* 
3273    * Change the mode 
3274    */
3275
3276   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3277     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3278       /* Cannot operator mode */
3279       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3280                                             SILC_STATUS_ERR_PERM_DENIED);
3281       goto out;
3282     }
3283   } else {
3284     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3285       /* Remove the server operator rights */
3286       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3287   }
3288
3289   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3290     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3291       /* Cannot operator mode */
3292       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3293                                             SILC_STATUS_ERR_PERM_DENIED);
3294       goto out;
3295     }
3296   } else {
3297     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3298       /* Remove the router operator rights */
3299       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3300   }
3301
3302   if (mask & SILC_UMODE_GONE) {
3303     client->mode |= SILC_UMODE_GONE;
3304   } else {
3305     if (client->mode & SILC_UMODE_GONE)
3306       /* Remove the gone status */
3307       client->mode &= ~SILC_UMODE_GONE;
3308   }
3309
3310   /* Send UMODE change to primary router */
3311   if (!server->standalone)
3312     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3313                                   client->id, client->mode);
3314
3315   /* Send command reply to sender */
3316   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3317                                                 SILC_STATUS_OK, ident, 1,
3318                                                 2, tmp_mask, 4);
3319   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3320                           packet->data, packet->len, FALSE);
3321   silc_buffer_free(packet);
3322
3323  out:
3324   silc_server_command_free(cmd);
3325 }
3326
3327 /* Checks that client has rights to add or remove channel modes. If any
3328    of the checks fails FALSE is returned. */
3329
3330 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3331                                    SilcChannelClientEntry client,
3332                                    uint32 mode)
3333 {
3334   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3335   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3336
3337   /* Check whether has rights to change anything */
3338   if (!is_op && !is_fo)
3339     return FALSE;
3340
3341   /* Check whether has rights to change everything */
3342   if (is_op && is_fo)
3343     return TRUE;
3344
3345   /* We know that client is channel operator, check that they are not
3346      changing anything that requires channel founder rights. Rest of the
3347      modes are available automatically for channel operator. */
3348
3349   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3350     if (is_op && !is_fo)
3351       return FALSE;
3352   } else {
3353     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3354       if (is_op && !is_fo)
3355         return FALSE;
3356     }
3357   }
3358   
3359   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3360     if (is_op && !is_fo)
3361       return FALSE;
3362   } else {
3363     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3364       if (is_op && !is_fo)
3365         return FALSE;
3366     }
3367   }
3368
3369   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3370     if (is_op && !is_fo)
3371       return FALSE;
3372   } else {
3373     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3374       if (is_op && !is_fo)
3375         return FALSE;
3376     }
3377   }
3378   
3379   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3380     if (is_op && !is_fo)
3381       return FALSE;
3382   } else {
3383     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3384       if (is_op && !is_fo)
3385         return FALSE;
3386     }
3387   }
3388   
3389   return TRUE;
3390 }
3391
3392 /* Server side command of CMODE. Changes channel mode */
3393
3394 SILC_SERVER_CMD_FUNC(cmode)
3395 {
3396   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3397   SilcServer server = cmd->server;
3398   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3399   SilcIDListData idata = (SilcIDListData)client;
3400   SilcChannelID *channel_id;
3401   SilcChannelEntry channel;
3402   SilcChannelClientEntry chl;
3403   SilcBuffer packet, cidp;
3404   unsigned char *tmp, *tmp_id, *tmp_mask;
3405   char *cipher = NULL, *hmac = NULL;
3406   uint32 mode_mask, tmp_len, tmp_len2;
3407   uint16 ident = silc_command_get_ident(cmd->payload);
3408
3409   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CMODE, cmd, 2, 7);
3410
3411   /* Get Channel ID */
3412   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3413   if (!tmp_id) {
3414     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3415                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3416     goto out;
3417   }
3418   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3419   if (!channel_id) {
3420     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3421                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3422     goto out;
3423   }
3424
3425   /* Get the channel mode mask */
3426   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3427   if (!tmp_mask) {
3428     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3429                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3430     goto out;
3431   }
3432   SILC_GET32_MSB(mode_mask, tmp_mask);
3433
3434   /* Get channel entry */
3435   channel = silc_idlist_find_channel_by_id(server->local_list, 
3436                                            channel_id, NULL);
3437   if (!channel) {
3438     channel = silc_idlist_find_channel_by_id(server->global_list, 
3439                                              channel_id, NULL);
3440     if (!channel) {
3441       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3442                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3443       goto out;
3444     }
3445   }
3446
3447   /* Check whether this client is on the channel */
3448   if (!silc_server_client_on_channel(client, channel)) {
3449     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3450                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3451     goto out;
3452   }
3453
3454   /* Get entry to the channel user list */
3455   silc_list_start(channel->user_list);
3456   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3457     if (chl->client == client)
3458       break;
3459
3460   /* Check that client has rights to change any requested channel modes */
3461   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3462     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3463                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3464     goto out;
3465   }
3466
3467   /*
3468    * Check the modes. Modes that requires nothing special operation are
3469    * not checked here.
3470    */
3471
3472   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3473     /* Channel uses private keys to protect traffic. Client(s) has set the
3474        key locally they want to use, server does not know that key. */
3475     /* Nothing interesting to do here */
3476   } else {
3477     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3478       /* The mode is removed and we need to generate and distribute
3479          new channel key. Clients are not using private channel keys
3480          anymore after this. */
3481
3482       /* Re-generate channel key */
3483       silc_server_create_channel_key(server, channel, 0);
3484       
3485       /* Send the channel key. This sends it to our local clients and if
3486          we are normal server to our router as well. */
3487       silc_server_send_channel_key(server, NULL, channel, 
3488                                    server->server_type == SILC_ROUTER ? 
3489                                    FALSE : !server->standalone);
3490
3491       cipher = channel->channel_key->cipher->name;
3492       hmac = channel->hmac->hmac->name;
3493     }
3494   }
3495   
3496   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3497     /* User limit is set on channel */
3498     uint32 user_limit;
3499       
3500     /* Get user limit */
3501     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3502     if (!tmp) {
3503       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3504         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3505                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3506         goto out;
3507       }
3508     } else {
3509       SILC_GET32_MSB(user_limit, tmp);
3510       channel->user_limit = user_limit;
3511     }
3512   } else {
3513     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3514       /* User limit mode is unset. Remove user limit */
3515       channel->user_limit = 0;
3516   }
3517
3518   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3519     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3520       /* Passphrase has been set to channel */
3521       
3522       /* Get the passphrase */
3523       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3524       if (!tmp) {
3525         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3526                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3527         goto out;
3528       }
3529
3530       /* Save the passphrase */
3531       channel->passphrase = strdup(tmp);
3532     }
3533   } else {
3534     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3535       /* Passphrase mode is unset. remove the passphrase */
3536       if (channel->passphrase) {
3537         silc_free(channel->passphrase);
3538         channel->passphrase = NULL;
3539       }
3540     }
3541   }
3542
3543   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3544     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3545       /* Cipher to use protect the traffic */
3546
3547       /* Get cipher */
3548       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3549       if (!cipher) {
3550         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3551                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3552         goto out;
3553       }
3554
3555       /* Delete old cipher and allocate the new one */
3556       silc_cipher_free(channel->channel_key);
3557       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3558         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3559                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3560         goto out;
3561       }
3562
3563       /* Re-generate channel key */
3564       silc_server_create_channel_key(server, channel, 0);
3565     
3566       /* Send the channel key. This sends it to our local clients and if
3567          we are normal server to our router as well. */
3568       silc_server_send_channel_key(server, NULL, channel, 
3569                                    server->server_type == SILC_ROUTER ? 
3570                                    FALSE : !server->standalone);
3571     }
3572   } else {
3573     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3574       /* Cipher mode is unset. Remove the cipher and revert back to 
3575          default cipher */
3576       cipher = channel->cipher;
3577
3578       /* Delete old cipher and allocate default one */
3579       silc_cipher_free(channel->channel_key);
3580       if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", 
3581                              &channel->channel_key)) {
3582         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3583                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3584         goto out;
3585       }
3586
3587       /* Re-generate channel key */
3588       silc_server_create_channel_key(server, channel, 0);
3589       
3590       /* Send the channel key. This sends it to our local clients and if
3591          we are normal server to our router as well. */
3592       silc_server_send_channel_key(server, NULL, channel, 
3593                                    server->server_type == SILC_ROUTER ? 
3594                                    FALSE : !server->standalone);
3595     }
3596   }
3597
3598   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3599     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3600       /* HMAC to use protect the traffic */
3601       unsigned char hash[32];
3602
3603       /* Get hmac */
3604       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3605       if (!hmac) {
3606         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3607                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3608         goto out;
3609       }
3610
3611       /* Delete old hmac and allocate the new one */
3612       silc_hmac_free(channel->hmac);
3613       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3614         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3615                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3616         goto out;
3617       }
3618
3619       /* Set the HMAC key out of current channel key. The client must do
3620          this locally. */
3621       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3622                      hash);
3623       silc_hmac_set_key(channel->hmac, hash, 
3624                         silc_hash_len(channel->hmac->hash));
3625       memset(hash, 0, sizeof(hash));
3626     }
3627   } else {
3628     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3629       /* Hmac mode is unset. Remove the hmac and revert back to 
3630          default hmac */
3631       unsigned char hash[32];
3632       hmac = channel->hmac_name;
3633
3634       /* Delete old hmac and allocate default one */
3635       silc_hmac_free(channel->hmac);
3636       if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
3637                            &channel->hmac)) {
3638         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3639                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3640         goto out;
3641       }
3642
3643       /* Set the HMAC key out of current channel key. The client must do
3644          this locally. */
3645       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3646                      hash);
3647       silc_hmac_set_key(channel->hmac, hash, 
3648                         silc_hash_len(channel->hmac->hash));
3649       memset(hash, 0, sizeof(hash));
3650     }
3651   }
3652
3653   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3654     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3655       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
3656         /* Set the founder authentication */
3657         SilcAuthPayload auth;
3658         
3659         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
3660         if (!tmp) {
3661           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3662                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3663           goto out;
3664         }
3665
3666         auth = silc_auth_payload_parse(tmp, tmp_len);
3667         if (!auth) {
3668           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3669                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3670           goto out;
3671         }
3672
3673         /* Save the public key */
3674         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
3675         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
3676         silc_free(tmp);
3677         
3678         channel->founder_method = silc_auth_get_method(auth);
3679
3680         if (channel->founder_method == SILC_AUTH_PASSWORD) {
3681           tmp = silc_auth_get_data(auth, &tmp_len);
3682           channel->founder_passwd = 
3683             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
3684           memcpy(channel->founder_passwd, tmp, tmp_len);
3685           channel->founder_passwd_len = tmp_len;
3686         }
3687
3688         silc_auth_payload_free(auth);
3689       }
3690     }
3691   } else {
3692     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3693       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3694         if (channel->founder_key)
3695           silc_pkcs_public_key_free(channel->founder_key);
3696         if (channel->founder_passwd) {
3697           silc_free(channel->founder_passwd);
3698           channel->founder_passwd = NULL;
3699         }
3700       }
3701     }
3702   }
3703
3704   /* Finally, set the mode */
3705   channel->mode = mode_mask;
3706
3707   /* Send CMODE_CHANGE notify */
3708   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3709   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3710                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3711                                      cidp->data, cidp->len, 
3712                                      tmp_mask, 4,
3713                                      cipher, cipher ? strlen(cipher) : 0,
3714                                      hmac, hmac ? strlen(hmac) : 0);
3715
3716   /* Set CMODE notify type to network */
3717   if (!server->standalone)
3718     silc_server_send_notify_cmode(server, server->router->connection,
3719                                   server->server_type == SILC_ROUTER ? 
3720                                   TRUE : FALSE, channel,
3721                                   mode_mask, client->id, SILC_ID_CLIENT,
3722                                   cipher, hmac);
3723
3724   /* Send command reply to sender */
3725   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3726                                                 SILC_STATUS_OK, ident, 1,
3727                                                 2, tmp_mask, 4);
3728   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3729                           packet->data, packet->len, FALSE);
3730     
3731   silc_buffer_free(packet);
3732   silc_free(channel_id);
3733   silc_free(cidp);
3734
3735  out:
3736   silc_server_command_free(cmd);
3737 }
3738
3739 /* Server side of CUMODE command. Changes client's mode on a channel. */
3740
3741 SILC_SERVER_CMD_FUNC(cumode)
3742 {
3743   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3744   SilcServer server = cmd->server;
3745   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3746   SilcIDListData idata = (SilcIDListData)client;
3747   SilcChannelID *channel_id;
3748   SilcClientID *client_id;
3749   SilcChannelEntry channel;
3750   SilcClientEntry target_client;
3751   SilcChannelClientEntry chl;
3752   SilcBuffer packet, idp;
3753   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3754   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
3755   int notify = FALSE;
3756   uint16 ident = silc_command_get_ident(cmd->payload);
3757
3758   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 4);
3759
3760   /* Get Channel ID */
3761   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3762   if (!tmp_ch_id) {
3763     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3764                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3765     goto out;
3766   }
3767   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3768   if (!channel_id) {
3769     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3770                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3771     goto out;
3772   }
3773
3774   /* Get channel entry */
3775   channel = silc_idlist_find_channel_by_id(server->local_list, 
3776                                            channel_id, NULL);
3777   if (!channel) {
3778     channel = silc_idlist_find_channel_by_id(server->global_list, 
3779                                              channel_id, NULL);
3780     if (!channel) {
3781       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3782                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3783       goto out;
3784     }
3785   }
3786
3787   /* Check whether sender is on the channel */
3788   if (!silc_server_client_on_channel(client, channel)) {
3789     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3790                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3791     goto out;
3792   }
3793
3794   /* Check that client has rights to change other's rights */
3795   silc_list_start(channel->user_list);
3796   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3797     if (chl->client == client) {
3798       sender_mask = chl->mode;
3799       break;
3800     }
3801   }
3802   
3803   /* Get the target client's channel mode mask */
3804   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3805   if (!tmp_mask) {
3806     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3807                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3808     goto out;
3809   }
3810   SILC_GET32_MSB(target_mask, tmp_mask);
3811
3812   /* Get target Client ID */
3813   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3814   if (!tmp_id) {
3815     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3816                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3817     goto out;
3818   }
3819   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3820   if (!client_id) {
3821     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3822                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3823     goto out;
3824   }
3825
3826   /* Get target client's entry */
3827   target_client = silc_idlist_find_client_by_id(server->local_list, 
3828                                                 client_id, NULL);
3829   if (!target_client) {
3830     target_client = silc_idlist_find_client_by_id(server->global_list, 
3831                                                   client_id, NULL);
3832   }
3833
3834   if (target_client != client &&
3835       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
3836       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
3837     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3838                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3839     goto out;
3840   }
3841
3842   /* Check whether target client is on the channel */
3843   if (target_client != client) {
3844     if (!silc_server_client_on_channel(target_client, channel)) {
3845       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3846                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3847       goto out;
3848     }
3849
3850     /* Get entry to the channel user list */
3851     silc_list_start(channel->user_list);
3852     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3853       if (chl->client == target_client)
3854         break;
3855   }
3856
3857   /* 
3858    * Change the mode 
3859    */
3860
3861   /* If the target client is founder, no one else can change their mode
3862      but themselves. */
3863   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3864     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3865                                           SILC_STATUS_ERR_NOT_YOU);
3866     goto out;
3867   }
3868
3869   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3870     /* The client tries to claim the founder rights. */
3871     unsigned char *tmp_auth;
3872     uint32 tmp_auth_len, auth_len;
3873     void *auth;
3874     
3875     if (target_client != client) {
3876       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3877                                             SILC_STATUS_ERR_NOT_YOU);
3878       goto out;
3879     }
3880
3881     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3882         !channel->founder_key) {
3883       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3884                                             SILC_STATUS_ERR_NOT_YOU);
3885       goto out;
3886     }
3887
3888     tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3889     if (!tmp_auth) {
3890       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3891                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3892       goto out;
3893     }
3894
3895     auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
3896             (void *)channel->founder_passwd : (void *)channel->founder_key);
3897     auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
3898                 channel->founder_passwd_len : 0);
3899     
3900     if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
3901                                channel->founder_method, auth, auth_len,
3902                                idata->hash, client->id, SILC_ID_CLIENT)) {
3903       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3904                                             SILC_STATUS_ERR_AUTH_FAILED);
3905       goto out;
3906     }
3907
3908     sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3909     notify = TRUE;
3910   } else {
3911     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3912       if (target_client == client) {
3913         /* Remove channel founder rights from itself */
3914         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3915         notify = TRUE;
3916       } else {
3917         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3918                                               SILC_STATUS_ERR_NOT_YOU);
3919         goto out;
3920       }
3921     }
3922   }
3923
3924   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3925     /* Promote to operator */
3926     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3927       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3928           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3929         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3930                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3931         goto out;
3932       }
3933
3934       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3935       notify = TRUE;
3936     }
3937   } else {
3938     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3939       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3940           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3941         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3942                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3943         goto out;
3944       }
3945
3946       /* Demote to normal user */
3947       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3948       notify = TRUE;
3949     }
3950   }
3951
3952   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3953   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3954
3955   /* Send notify to channel, notify only if mode was actually changed. */
3956   if (notify) {
3957     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3958                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3959                                        idp->data, idp->len,
3960                                        tmp_mask, 4, 
3961                                        tmp_id, tmp_len);
3962
3963     /* Set CUMODE notify type to network */
3964     if (!server->standalone)
3965       silc_server_send_notify_cumode(server, server->router->connection,
3966                                      server->server_type == SILC_ROUTER ? 
3967                                      TRUE : FALSE, channel,
3968                                      target_mask, client->id, 
3969                                      SILC_ID_CLIENT,
3970                                      target_client->id);
3971   }
3972
3973   /* Send command reply to sender */
3974   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3975                                                 SILC_STATUS_OK, ident, 2,
3976                                                 2, tmp_mask, 4,
3977                                                 3, tmp_id, tmp_len);
3978   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3979                           packet->data, packet->len, FALSE);
3980     
3981   silc_buffer_free(packet);
3982   silc_free(channel_id);
3983   silc_free(client_id);
3984   silc_buffer_free(idp);
3985
3986  out:
3987   silc_server_command_free(cmd);
3988 }
3989
3990 /* Server side of KICK command. Kicks client out of channel. */
3991
3992 SILC_SERVER_CMD_FUNC(kick)
3993 {
3994   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3995   SilcServer server = cmd->server;
3996   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3997   SilcClientEntry target_client;
3998   SilcChannelID *channel_id;
3999   SilcClientID *client_id;
4000   SilcChannelEntry channel;
4001   SilcChannelClientEntry chl;
4002   SilcBuffer idp;
4003   uint32 tmp_len;
4004   unsigned char *tmp, *comment;
4005
4006   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
4007
4008   /* Get Channel ID */
4009   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4010   if (!tmp) {
4011     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4012                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4013     goto out;
4014   }
4015   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4016   if (!channel_id) {
4017     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4018                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4019     goto out;
4020   }
4021
4022   /* Get channel entry */
4023   channel = silc_idlist_find_channel_by_id(server->local_list, 
4024                                            channel_id, NULL);
4025   if (!channel) {
4026     channel = silc_idlist_find_channel_by_id(server->local_list, 
4027                                              channel_id, NULL);
4028     if (!channel) {
4029       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4030                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4031       goto out;
4032     }
4033   }
4034
4035   /* Check whether sender is on the channel */
4036   if (!silc_server_client_on_channel(client, channel)) {
4037     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4038                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4039     goto out;
4040   }
4041
4042   /* Check that the kicker is channel operator or channel founder */
4043   silc_list_start(channel->user_list);
4044   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4045     if (chl->client == client) {
4046       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4047         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4048                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4049         goto out;
4050       }
4051       break;
4052     }
4053   }
4054   
4055   /* Get target Client ID */
4056   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4057   if (!tmp) {
4058     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4059                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4060     goto out;
4061   }
4062   client_id = silc_id_payload_parse_id(tmp, tmp_len);
4063   if (!client_id) {
4064     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4065                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4066     goto out;
4067   }
4068
4069   /* Get target client's entry */
4070   target_client = silc_idlist_find_client_by_id(server->local_list, 
4071                                                 client_id, NULL);
4072   if (!target_client) {
4073     target_client = silc_idlist_find_client_by_id(server->global_list, 
4074                                                   client_id, NULL);
4075   }
4076
4077   /* Check that the target client is not channel founder. Channel founder
4078      cannot be kicked from the channel. */
4079   silc_list_start(channel->user_list);
4080   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
4081     if (chl->client == target_client) {
4082       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4083         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4084                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4085         goto out;
4086       }
4087       break;
4088     }
4089   }
4090   
4091   /* Check whether target client is on the channel */
4092   if (!silc_server_client_on_channel(target_client, channel)) {
4093     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4094                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4095     goto out;
4096   }
4097
4098   /* Get comment */
4099   tmp_len = 0;
4100   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4101   if (tmp_len > 128)
4102     comment = NULL;
4103
4104   /* Send command reply to sender */
4105   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4106                                         SILC_STATUS_OK);
4107
4108   /* Send KICKED notify to local clients on the channel */
4109   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
4110   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4111                                      SILC_NOTIFY_TYPE_KICKED, 
4112                                      comment ? 2 : 1,
4113                                      idp->data, idp->len,
4114                                      comment, comment ? strlen(comment) : 0);
4115   silc_buffer_free(idp);
4116
4117   /* Remove the client from the channel. If the channel does not exist
4118      after removing the client then the client kicked itself off the channel
4119      and we don't have to send anything after that. */
4120   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4121                                            target_client, FALSE))
4122     goto out;
4123
4124   /* Send KICKED notify to primary route */
4125   if (!server->standalone)
4126     silc_server_send_notify_kicked(server, server->router->connection,
4127                                    server->server_type == SILC_ROUTER ?
4128                                    TRUE : FALSE, channel,
4129                                    target_client->id, comment);
4130
4131   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4132     /* Re-generate channel key */
4133     silc_server_create_channel_key(server, channel, 0);
4134     
4135     /* Send the channel key to the channel. The key of course is not sent
4136        to the client who was kicked off the channel. */
4137     silc_server_send_channel_key(server, target_client->connection, channel, 
4138                                  server->server_type == SILC_ROUTER ? 
4139                                  FALSE : !server->standalone);
4140   }
4141
4142  out:
4143   silc_server_command_free(cmd);
4144 }
4145
4146 /* Server side of OPER command. Client uses this comand to obtain server
4147    operator privileges to this server/router. */
4148
4149 SILC_SERVER_CMD_FUNC(oper)
4150 {
4151   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4152   SilcServer server = cmd->server;
4153   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4154   unsigned char *username, *auth;
4155   uint32 tmp_len;
4156   SilcServerConfigSectionAdminConnection *admin;
4157   SilcIDListData idata = (SilcIDListData)client;
4158
4159   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4160
4161   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4162     goto out;
4163
4164   /* Get the username */
4165   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4166   if (!username) {
4167     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4168                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4169     goto out;
4170   }
4171
4172   /* Get the admin configuration */
4173   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4174                                         username, client->nickname);
4175   if (!admin) {
4176     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4177                                           username, client->nickname);
4178     if (!admin) {
4179       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4180                                             SILC_STATUS_ERR_AUTH_FAILED);
4181       goto out;
4182     }
4183   }
4184
4185   /* Get the authentication payload */
4186   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4187   if (!auth) {
4188     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4189                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4190     goto out;
4191   }
4192
4193   /* Verify the authentication data */
4194   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4195                              admin->auth_data, admin->auth_data_len,
4196                              idata->hash, client->id, SILC_ID_CLIENT)) {
4197     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4198                                           SILC_STATUS_ERR_AUTH_FAILED);
4199     goto out;
4200   }
4201
4202   /* Client is now server operator */
4203   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4204
4205   /* Send UMODE change to primary router */
4206   if (!server->standalone)
4207     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4208                                   client->id, client->mode);
4209
4210   /* Send reply to the sender */
4211   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4212                                         SILC_STATUS_OK);
4213
4214  out:
4215   silc_server_command_free(cmd);
4216 }
4217
4218 /* Server side of SILCOPER command. Client uses this comand to obtain router
4219    operator privileges to this router. */
4220
4221 SILC_SERVER_CMD_FUNC(silcoper)
4222 {
4223   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4224   SilcServer server = cmd->server;
4225   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4226   unsigned char *username, *auth;
4227   uint32 tmp_len;
4228   SilcServerConfigSectionAdminConnection *admin;
4229   SilcIDListData idata = (SilcIDListData)client;
4230
4231   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4232
4233   if (server->server_type == SILC_SERVER)
4234     goto out;
4235
4236   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4237     goto out;
4238
4239   /* Get the username */
4240   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4241   if (!username) {
4242     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4243                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4244     goto out;
4245   }
4246
4247   /* Get the admin configuration */
4248   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4249                                         username, client->nickname);
4250   if (!admin) {
4251     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4252                                           username, client->nickname);
4253     if (!admin) {
4254       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4255                                             SILC_STATUS_ERR_AUTH_FAILED);
4256       goto out;
4257     }
4258   }
4259
4260   /* Get the authentication payload */
4261   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4262   if (!auth) {
4263     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4264                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4265     goto out;
4266   }
4267
4268   /* Verify the authentication data */
4269   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4270                              admin->auth_data, admin->auth_data_len,
4271                              idata->hash, client->id, SILC_ID_CLIENT)) {
4272     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4273                                           SILC_STATUS_ERR_AUTH_FAILED);
4274     goto out;
4275   }
4276
4277   /* Client is now router operator */
4278   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4279
4280   /* Send UMODE change to primary router */
4281   if (!server->standalone)
4282     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4283                                   client->id, client->mode);
4284
4285   /* Send reply to the sender */
4286   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4287                                         SILC_STATUS_OK);
4288
4289  out:
4290   silc_server_command_free(cmd);
4291 }
4292
4293 /* Server side command of CONNECT. Connects us to the specified remote
4294    server or router. */
4295
4296 SILC_SERVER_CMD_FUNC(connect)
4297 {
4298   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4299   SilcServer server = cmd->server;
4300   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4301   unsigned char *tmp, *host;
4302   uint32 tmp_len;
4303   uint32 port = SILC_PORT;
4304
4305   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4306
4307   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4308     goto out;
4309
4310   /* Check whether client has the permissions. */
4311   if (client->mode == SILC_UMODE_NONE) {
4312     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4313                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4314     goto out;
4315   }
4316
4317   if (server->server_type == SILC_ROUTER && 
4318       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4319     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4320                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4321     goto out;
4322   }
4323
4324   /* Get the remote server */
4325   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4326   if (!host) {
4327     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4328                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4329     goto out;
4330   }
4331
4332   /* Get port */
4333   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4334   if (tmp)
4335     SILC_GET32_MSB(port, tmp);
4336
4337   /* Create the connection. It is done with timeout and is async. */
4338   silc_server_create_connection(server, host, port);
4339
4340   /* Send reply to the sender */
4341   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4342                                         SILC_STATUS_OK);
4343
4344  out:
4345   silc_server_command_free(cmd);
4346 }
4347
4348 /* Server side of command BAN. This is used to manage the ban list of the
4349    channel. To add clients and remove clients from the ban list. */
4350
4351 SILC_SERVER_CMD_FUNC(ban)
4352 {
4353   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4354   SilcServer server = cmd->server;
4355   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4356   SilcBuffer packet;
4357   SilcChannelEntry channel;
4358   SilcChannelClientEntry chl;
4359   SilcChannelID *channel_id = NULL;
4360   unsigned char *id, *add, *del;
4361   uint32 id_len, tmp_len;
4362   uint16 ident = silc_command_get_ident(cmd->payload);
4363
4364   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4365     goto out;
4366
4367   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4368
4369   /* Get Channel ID */
4370   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4371   if (id) {
4372     channel_id = silc_id_payload_parse_id(id, id_len);
4373     if (!channel_id) {
4374       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4375                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4376       goto out;
4377     }
4378   }
4379
4380   /* Get channel entry. The server must know about the channel since the
4381      client is expected to be on the channel. */
4382   channel = silc_idlist_find_channel_by_id(server->local_list, 
4383                                            channel_id, NULL);
4384   if (!channel) {
4385     channel = silc_idlist_find_channel_by_id(server->global_list, 
4386                                              channel_id, NULL);
4387     if (!channel) {
4388       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4389                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4390       goto out;
4391     }
4392   }
4393
4394   /* Check whether this client is on the channel */
4395   if (!silc_server_client_on_channel(client, channel)) {
4396     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4397                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4398     goto out;
4399   }
4400
4401   /* Get entry to the channel user list */
4402   silc_list_start(channel->user_list);
4403   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4404     if (chl->client == client)
4405       break;
4406
4407   /* The client must be at least channel operator. */
4408   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4409     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4410                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4411     goto out;
4412   }
4413
4414   /* Get the new ban and add it to the ban list */
4415   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4416   if (add) {
4417     if (!channel->ban_list)
4418       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4419     else
4420       channel->ban_list = silc_realloc(channel->ban_list, 
4421                                        sizeof(*channel->ban_list) * 
4422                                        (tmp_len + 
4423                                         strlen(channel->ban_list) + 2));
4424     if (add[tmp_len - 1] == ',')
4425       add[tmp_len - 1] = '\0';
4426
4427     strncat(channel->ban_list, add, tmp_len);
4428     strncat(channel->ban_list, ",", 1);
4429   }
4430
4431   /* Get the ban to be removed and remove it from the list */
4432   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4433   if (del && channel->ban_list) {
4434     char *start, *end, *n;
4435
4436     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4437       silc_free(channel->ban_list);
4438       channel->ban_list = NULL;
4439     } else {
4440       start = strstr(channel->ban_list, del);
4441       if (start && strlen(start) >= tmp_len) {
4442         end = start + tmp_len;
4443         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4444         strncat(n, channel->ban_list, start - channel->ban_list);
4445         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4446                              end) - 1);
4447         silc_free(channel->ban_list);
4448         channel->ban_list = n;
4449       }
4450     }
4451   }
4452
4453   /* Send the BAN notify type to our primary router. */
4454   if (!server->standalone && (add || del))
4455     silc_server_send_notify_ban(server, server->router->connection,
4456                                 server->server_type == SILC_ROUTER ?
4457                                 TRUE : FALSE, channel, add, del);
4458
4459   /* Send the reply back to the client */
4460   if (channel->ban_list)
4461     packet = 
4462       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4463                                            SILC_STATUS_OK, ident, 2,
4464                                            2, id, id_len,
4465                                            3, channel->ban_list, 
4466                                            strlen(channel->ban_list) - 1);
4467   else
4468     packet = 
4469       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4470                                            SILC_STATUS_OK, ident, 1,
4471                                            2, id, id_len);
4472
4473   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4474                           packet->data, packet->len, FALSE);
4475     
4476   silc_buffer_free(packet);
4477
4478  out:
4479   if (channel_id)
4480     silc_free(channel_id);
4481   silc_server_command_free(cmd);
4482 }
4483
4484 /* Server side command of CLOSE. Closes connection to a specified server. */
4485  
4486 SILC_SERVER_CMD_FUNC(close)
4487 {
4488   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4489   SilcServer server = cmd->server;
4490   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4491   SilcServerEntry server_entry;
4492   SilcSocketConnection sock;
4493   unsigned char *tmp;
4494   uint32 tmp_len;
4495   unsigned char *name;
4496   uint32 port = SILC_PORT;
4497
4498   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4499
4500   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4501     goto out;
4502
4503   /* Check whether client has the permissions. */
4504   if (client->mode == SILC_UMODE_NONE) {
4505     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4506                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4507     goto out;
4508   }
4509
4510   /* Get the remote server */
4511   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4512   if (!name) {
4513     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4514                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4515     goto out;
4516   }
4517
4518   /* Get port */
4519   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4520   if (tmp)
4521     SILC_GET32_MSB(port, tmp);
4522
4523   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4524                                                  name, port, NULL);
4525   if (!server_entry) {
4526     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4527                                           SILC_STATUS_ERR_NO_SERVER_ID);
4528     goto out;
4529   }
4530
4531   /* Send reply to the sender */
4532   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4533                                         SILC_STATUS_OK);
4534
4535   /* Close the connection to the server */
4536   sock = (SilcSocketConnection)server_entry->connection;
4537   silc_server_free_sock_user_data(server, sock);
4538   silc_server_close_connection(server, sock);
4539   
4540  out:
4541   silc_server_command_free(cmd);
4542 }
4543
4544 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4545    active connections. */
4546  
4547 SILC_SERVER_CMD_FUNC(shutdown)
4548 {
4549   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4550   SilcServer server = cmd->server;
4551   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4552
4553   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4554
4555   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4556     goto out;
4557
4558   /* Check whether client has the permission. */
4559   if (client->mode == SILC_UMODE_NONE) {
4560     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4561                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4562     goto out;
4563   }
4564
4565   /* Send reply to the sender */
4566   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4567                                         SILC_STATUS_OK);
4568
4569   /* Then, gracefully, or not, bring the server down. */
4570   silc_server_stop(server);
4571   exit(0);
4572
4573  out:
4574   silc_server_command_free(cmd);
4575 }
4576  
4577 /* Server side command of LEAVE. Removes client from a channel. */
4578
4579 SILC_SERVER_CMD_FUNC(leave)
4580 {
4581   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4582   SilcServer server = cmd->server;
4583   SilcSocketConnection sock = cmd->sock;
4584   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4585   SilcChannelID *id = NULL;
4586   SilcChannelEntry channel;
4587   uint32 len;
4588   unsigned char *tmp;
4589
4590   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4591
4592   /* Get Channel ID */
4593   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4594   if (!tmp) {
4595     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4596                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4597     goto out;
4598   }
4599   id = silc_id_payload_parse_id(tmp, len);
4600   if (!id) {
4601     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4602                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4603     goto out;
4604   }
4605
4606   /* Get channel entry */
4607   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4608   if (!channel) {
4609     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4610     if (!channel) {
4611       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4612                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4613       goto out;
4614     }
4615   }
4616
4617   /* Check whether this client is on the channel */
4618   if (!silc_server_client_on_channel(id_entry, channel)) {
4619     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4620                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4621     goto out;
4622   }
4623
4624   /* Notify routers that they should remove this client from their list
4625      of clients on the channel. Send LEAVE notify type. */
4626   if (!server->standalone)
4627     silc_server_send_notify_leave(server, server->router->connection,
4628                                   server->server_type == SILC_ROUTER ?
4629                                   TRUE : FALSE, channel, id_entry->id);
4630
4631   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4632                                         SILC_STATUS_OK);
4633
4634   /* Remove client from channel */
4635   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4636                                            TRUE))
4637     /* If the channel does not exist anymore we won't send anything */
4638     goto out;
4639
4640   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4641     /* Re-generate channel key */
4642     silc_server_create_channel_key(server, channel, 0);
4643
4644     /* Send the channel key */
4645     silc_server_send_channel_key(server, NULL, channel, 
4646                                  server->server_type == SILC_ROUTER ? 
4647                                  FALSE : !server->standalone);
4648   }
4649
4650  out:
4651   if (id)
4652     silc_free(id);
4653   silc_server_command_free(cmd);
4654 }
4655
4656 /* Server side of command USERS. Resolves clients and their USERS currently
4657    joined on the requested channel. The list of Client ID's and their modes
4658    on the channel is sent back. */
4659
4660 SILC_SERVER_CMD_FUNC(users)
4661 {
4662   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4663   SilcServer server = cmd->server;
4664   SilcChannelEntry channel;
4665   SilcChannelID *id;
4666   SilcBuffer packet;
4667   unsigned char *channel_id;
4668   uint32 channel_id_len;
4669   SilcBuffer client_id_list;
4670   SilcBuffer client_mode_list;
4671   unsigned char lc[4];
4672   uint32 list_count = 0;
4673   uint16 ident = silc_command_get_ident(cmd->payload);
4674
4675   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4676
4677   /* Get Channel ID */
4678   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4679   if (!channel_id) {
4680     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4681                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4682     goto out;
4683   }
4684   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4685   if (!id) {
4686     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4687                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4688     goto out;
4689   }
4690
4691   /* If we are server and we don't know about this channel we will send
4692      the command to our router. If we know about the channel then we also
4693      have the list of users already. */
4694   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4695   if (!channel) {
4696     if (server->server_type == SILC_SERVER && !server->standalone &&
4697         !cmd->pending) {
4698       SilcBuffer tmpbuf;
4699       
4700       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4701       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4702       
4703       /* Send USERS command */
4704       silc_server_packet_send(server, server->router->connection,
4705                               SILC_PACKET_COMMAND, cmd->packet->flags,
4706                               tmpbuf->data, tmpbuf->len, TRUE);
4707       
4708       /* Reprocess this packet after received reply */
4709       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4710                                   silc_command_get_ident(cmd->payload),
4711                                   silc_server_command_destructor,
4712                                   silc_server_command_users,
4713                                   silc_server_command_dup(cmd));
4714       cmd->pending = TRUE;
4715       silc_command_set_ident(cmd->payload, ident);
4716       
4717       silc_buffer_free(tmpbuf);
4718       silc_free(id);
4719       return;
4720     }
4721
4722     /* We are router and we will check the global list as well. */
4723     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4724     if (!channel) {
4725       /* Channel really does not exist */
4726       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4727                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4728       goto out;
4729     }
4730   }
4731
4732   /* Get the users list */
4733   silc_server_get_users_on_channel(server, channel, &client_id_list,
4734                                    &client_mode_list, &list_count);
4735
4736   /* List count */
4737   SILC_PUT32_MSB(list_count, lc);
4738
4739   /* Send reply */
4740   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4741                                                 SILC_STATUS_OK, ident, 4,
4742                                                 2, channel_id, channel_id_len,
4743                                                 3, lc, 4,
4744                                                 4, client_id_list->data,
4745                                                 client_id_list->len,
4746                                                 5, client_mode_list->data,
4747                                                 client_mode_list->len);
4748   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4749                           packet->data, packet->len, FALSE);
4750     
4751   silc_buffer_free(packet);
4752   silc_buffer_free(client_id_list);
4753   silc_buffer_free(client_mode_list);
4754   silc_free(id);
4755
4756  out:
4757   silc_server_command_free(cmd);
4758 }
4759
4760 /* Server side of command GETKEY. This fetches the client's public key
4761    from the server where to the client is connected. */
4762
4763 SILC_SERVER_CMD_FUNC(getkey)
4764 {
4765   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4766   SilcServer server = cmd->server;
4767   SilcBuffer packet;
4768   SilcClientEntry client;
4769   SilcServerEntry server_entry;
4770   SilcClientID *client_id = NULL;
4771   SilcServerID *server_id = NULL;
4772   SilcIDPayload idp = NULL;
4773   uint16 ident = silc_command_get_ident(cmd->payload);
4774   unsigned char *tmp;
4775   uint32 tmp_len;
4776   SilcBuffer pk;
4777   SilcIdType id_type;
4778
4779   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4780   if (!tmp) {
4781     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4782                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4783     goto out;
4784   }
4785   idp = silc_id_payload_parse_data(tmp, tmp_len);
4786   if (!idp) {
4787     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4788                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4789     goto out;
4790   }
4791
4792   id_type = silc_id_payload_get_type(idp);
4793   if (id_type == SILC_ID_CLIENT) {
4794     client_id = silc_id_payload_get_id(idp);
4795
4796     /* If the client is not found from local list there is no chance it
4797        would be locally connected client so send the command further. */
4798     client = silc_idlist_find_client_by_id(server->local_list, 
4799                                            client_id, NULL);
4800     
4801     if ((!client && !cmd->pending && !server->standalone) ||
4802         (client && !client->connection)) {
4803       SilcBuffer tmpbuf;
4804       uint16 old_ident;
4805       SilcSocketConnection dest_sock;
4806       
4807       dest_sock = silc_server_get_client_route(server, NULL, 0, 
4808                                                client_id, NULL);
4809       if (!dest_sock)
4810         goto out;
4811       
4812       old_ident = silc_command_get_ident(cmd->payload);
4813       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4814       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4815       
4816       silc_server_packet_send(server, dest_sock,
4817                               SILC_PACKET_COMMAND, cmd->packet->flags,
4818                               tmpbuf->data, tmpbuf->len, TRUE);
4819       
4820       /* Reprocess this packet after received reply from router */
4821       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4822                                   silc_command_get_ident(cmd->payload),
4823                                   silc_server_command_destructor,
4824                                   silc_server_command_getkey,
4825                                   silc_server_command_dup(cmd));
4826       cmd->pending = TRUE;
4827       
4828       silc_command_set_ident(cmd->payload, old_ident);
4829       silc_buffer_free(tmpbuf);
4830       return;
4831     }
4832
4833     if (!client && cmd->pending) {
4834       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4835                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
4836       goto out;
4837     }
4838
4839     /* The client is locally connected, just get the public key and
4840        send it back. */
4841     tmp = silc_pkcs_public_key_encode(client->data.public_key, &tmp_len);
4842     pk = silc_buffer_alloc(4 + tmp_len);
4843     silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4844     silc_buffer_format(pk,
4845                        SILC_STR_UI_SHORT(tmp_len),
4846                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4847                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
4848                        SILC_STR_END);
4849     silc_free(tmp);
4850
4851   } else if (id_type == SILC_ID_SERVER) {
4852     server_id = silc_id_payload_get_id(idp);
4853
4854     /* If the server is not found from local list there is no chance it
4855        would be locally connected server so send the command further. */
4856     server_entry = silc_idlist_find_server_by_id(server->local_list, 
4857                                                  server_id, NULL);
4858     
4859     if ((!server_entry && !cmd->pending && !server->standalone) ||
4860         (server_entry && !server_entry->connection)) {
4861       SilcBuffer tmpbuf;
4862       uint16 old_ident;
4863       
4864       old_ident = silc_command_get_ident(cmd->payload);
4865       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4866       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4867       
4868       silc_server_packet_send(server, server->router->connection,
4869                               SILC_PACKET_COMMAND, cmd->packet->flags,
4870                               tmpbuf->data, tmpbuf->len, TRUE);
4871       
4872       /* Reprocess this packet after received reply from router */
4873       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4874                                   silc_command_get_ident(cmd->payload),
4875                                   silc_server_command_destructor,
4876                                   silc_server_command_getkey,
4877                                   silc_server_command_dup(cmd));
4878       cmd->pending = TRUE;
4879       
4880       silc_command_set_ident(cmd->payload, old_ident);
4881       silc_buffer_free(tmpbuf);
4882       return;
4883     }
4884
4885     if (!server_entry && cmd->pending) {
4886       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4887                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
4888       goto out;
4889     }
4890
4891     /* The client is locally connected, just get the public key and
4892        send it back. */
4893     tmp = silc_pkcs_public_key_encode(server_entry->data.public_key, &tmp_len);
4894     pk = silc_buffer_alloc(4 + tmp_len);
4895     silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4896     silc_buffer_format(pk,
4897                        SILC_STR_UI_SHORT(tmp_len),
4898                        SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4899                        SILC_STR_UI_XNSTRING(tmp, tmp_len),
4900                        SILC_STR_END);
4901     silc_free(tmp);
4902   } else {
4903     goto out;
4904   }
4905
4906   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4907   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4908                                                 SILC_STATUS_OK, ident, 2,
4909                                                 2, tmp, tmp_len,
4910                                                 3, pk->data, pk->len);
4911   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4912                           packet->data, packet->len, FALSE);
4913   silc_buffer_free(packet);
4914   silc_buffer_free(pk);
4915
4916  out:
4917   if (idp)
4918     silc_id_payload_free(idp);
4919   silc_free(client_id);
4920   silc_free(server_id);
4921   silc_server_command_free(cmd);
4922 }