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