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