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       create_key = FALSE;       /* Router returned the key already */
3459     }
3460
3461     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3462         !silc_hash_table_count(channel->user_list))
3463       created = TRUE;
3464   }
3465
3466   /* If the channel does not have global users and is also empty the client
3467      will be the channel founder and operator. */
3468   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3469     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3470
3471   /* Join to the channel */
3472   silc_server_command_join_channel(server, cmd, channel, client_id,
3473                                    created, create_key, umode,
3474                                    auth, auth_len);
3475
3476   silc_free(client_id);
3477
3478  out:
3479   silc_server_command_free(cmd);
3480 }
3481
3482 /* Server side of command MOTD. Sends server's current "message of the
3483    day" to the client. */
3484
3485 SILC_SERVER_CMD_FUNC(motd)
3486 {
3487   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3488   SilcServer server = cmd->server;
3489   SilcBuffer packet, idp;
3490   char *motd, *dest_server;
3491   uint32 motd_len;
3492   uint16 ident = silc_command_get_ident(cmd->payload);
3493   
3494   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3495
3496   /* Get server name */
3497   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3498   if (!dest_server) {
3499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3500                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3501     goto out;
3502   }
3503
3504   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3505     /* Send our MOTD */
3506
3507     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3508
3509     if (server->config && server->config->motd && 
3510         server->config->motd->motd_file) {
3511       /* Send motd */
3512       motd = silc_file_readfile(server->config->motd->motd_file, &motd_len);
3513       if (!motd)
3514         goto out;
3515       
3516       motd[motd_len] = 0;
3517       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3518                                                     SILC_STATUS_OK, ident, 2,
3519                                                     2, idp, idp->len,
3520                                                     3, motd, motd_len);
3521     } else {
3522       /* No motd */
3523       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3524                                                     SILC_STATUS_OK, ident, 1,
3525                                                     2, idp, idp->len);
3526     }
3527
3528     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3529                             packet->data, packet->len, FALSE);
3530     silc_buffer_free(packet);
3531     silc_buffer_free(idp);
3532   } else {
3533     SilcServerEntry entry;
3534
3535     /* Check whether we have this server cached */
3536     entry = silc_idlist_find_server_by_name(server->global_list,
3537                                             dest_server, TRUE, NULL);
3538     if (!entry) {
3539       entry = silc_idlist_find_server_by_name(server->local_list,
3540                                               dest_server, TRUE, NULL);
3541     }
3542
3543     if (server->server_type != SILC_SERVER && !cmd->pending && 
3544         entry && !entry->motd) {
3545       /* Send to the server */
3546       SilcBuffer tmpbuf;
3547       uint16 old_ident;
3548
3549       old_ident = silc_command_get_ident(cmd->payload);
3550       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3551       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3552
3553       silc_server_packet_send(server, entry->connection,
3554                               SILC_PACKET_COMMAND, cmd->packet->flags,
3555                               tmpbuf->data, tmpbuf->len, TRUE);
3556
3557       /* Reprocess this packet after received reply from router */
3558       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3559                                   silc_command_get_ident(cmd->payload),
3560                                   silc_server_command_motd,
3561                                   silc_server_command_dup(cmd));
3562       cmd->pending = TRUE;
3563       silc_command_set_ident(cmd->payload, old_ident);
3564       silc_buffer_free(tmpbuf);
3565       goto out;
3566     }
3567
3568     if (!entry && !cmd->pending && !server->standalone) {
3569       /* Send to the primary router */
3570       SilcBuffer tmpbuf;
3571       uint16 old_ident;
3572
3573       old_ident = silc_command_get_ident(cmd->payload);
3574       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3575       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3576
3577       silc_server_packet_send(server, server->router->connection,
3578                               SILC_PACKET_COMMAND, cmd->packet->flags,
3579                               tmpbuf->data, tmpbuf->len, TRUE);
3580
3581       /* Reprocess this packet after received reply from router */
3582       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3583                                   silc_command_get_ident(cmd->payload),
3584                                   silc_server_command_motd,
3585                                   silc_server_command_dup(cmd));
3586       cmd->pending = TRUE;
3587       silc_command_set_ident(cmd->payload, old_ident);
3588       silc_buffer_free(tmpbuf);
3589       goto out;
3590     }
3591
3592     if (!entry) {
3593       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3594                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3595       goto out;
3596     }
3597
3598     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3599     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3600                                                   SILC_STATUS_OK, ident, 2,
3601                                                   2, idp, idp->len,
3602                                                   3, entry->motd,
3603                                                   entry->motd ? 
3604                                                   strlen(entry->motd) : 0);
3605     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3606                             packet->data, packet->len, FALSE);
3607     silc_buffer_free(packet);
3608     silc_buffer_free(idp);
3609   }
3610
3611  out:
3612   silc_server_command_free(cmd);
3613 }
3614
3615 /* Server side of command UMODE. Client can use this command to set/unset
3616    user mode. Client actually cannot set itself to be as server/router
3617    operator so this can be used only to unset the modes. */
3618
3619 SILC_SERVER_CMD_FUNC(umode)
3620 {
3621   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3622   SilcServer server = cmd->server;
3623   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3624   SilcBuffer packet;
3625   unsigned char *tmp_mask;
3626   uint32 mask;
3627   uint16 ident = silc_command_get_ident(cmd->payload);
3628
3629   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3630     goto out;
3631
3632   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3633
3634   /* Get the client's mode mask */
3635   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3636   if (!tmp_mask) {
3637     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3638                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3639     goto out;
3640   }
3641   SILC_GET32_MSB(mask, tmp_mask);
3642
3643   /* 
3644    * Change the mode 
3645    */
3646
3647   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3648     if (!(client->mode & SILC_UMODE_SERVER_OPERATOR)) {
3649       /* Cannot operator mode */
3650       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3651                                             SILC_STATUS_ERR_PERM_DENIED);
3652       goto out;
3653     }
3654   } else {
3655     /* Remove the server operator rights */
3656     if (client->mode & SILC_UMODE_SERVER_OPERATOR) {
3657       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3658       if (client->connection)
3659         server->stat.my_server_ops--;
3660       if (server->server_type == SILC_ROUTER)
3661         server->stat.server_ops--;
3662     }
3663   }
3664
3665   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3666     if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
3667       /* Cannot operator mode */
3668       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3669                                             SILC_STATUS_ERR_PERM_DENIED);
3670       goto out;
3671     }
3672   } else {
3673     /* Remove the router operator rights */
3674     if (client->mode & SILC_UMODE_ROUTER_OPERATOR) {
3675       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3676       if (client->connection)
3677         server->stat.my_router_ops--;
3678       if (server->server_type == SILC_ROUTER)
3679         server->stat.router_ops--;
3680     }
3681   }
3682
3683   if (mask & SILC_UMODE_GONE) {
3684     client->mode |= SILC_UMODE_GONE;
3685   } else {
3686     if (client->mode & SILC_UMODE_GONE)
3687       /* Remove the gone status */
3688       client->mode &= ~SILC_UMODE_GONE;
3689   }
3690
3691   /* Send UMODE change to primary router */
3692   if (!server->standalone)
3693     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3694                                   client->id, client->mode);
3695
3696   /* Send command reply to sender */
3697   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3698                                                 SILC_STATUS_OK, ident, 1,
3699                                                 2, tmp_mask, 4);
3700   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3701                           packet->data, packet->len, FALSE);
3702   silc_buffer_free(packet);
3703
3704  out:
3705   silc_server_command_free(cmd);
3706 }
3707
3708 /* Checks that client has rights to add or remove channel modes. If any
3709    of the checks fails FALSE is returned. */
3710
3711 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3712                                    SilcChannelClientEntry client,
3713                                    uint32 mode)
3714 {
3715   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3716   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3717
3718   /* Check whether has rights to change anything */
3719   if (!is_op && !is_fo)
3720     return FALSE;
3721
3722   /* Check whether has rights to change everything */
3723   if (is_op && is_fo)
3724     return TRUE;
3725
3726   /* We know that client is channel operator, check that they are not
3727      changing anything that requires channel founder rights. Rest of the
3728      modes are available automatically for channel operator. */
3729
3730   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3731     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3732       if (is_op && !is_fo)
3733         return FALSE;
3734   } else {
3735     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3736       if (is_op && !is_fo)
3737         return FALSE;
3738     }
3739   }
3740   
3741   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3742     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE))
3743       if (is_op && !is_fo)
3744         return FALSE;
3745   } else {
3746     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3747       if (is_op && !is_fo)
3748         return FALSE;
3749     }
3750   }
3751
3752   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3753     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER))
3754       if (is_op && !is_fo)
3755         return FALSE;
3756   } else {
3757     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3758       if (is_op && !is_fo)
3759         return FALSE;
3760     }
3761   }
3762   
3763   if (mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3764     if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH))
3765       if (is_op && !is_fo)
3766         return FALSE;
3767   } else {
3768     if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3769       if (is_op && !is_fo)
3770         return FALSE;
3771     }
3772   }
3773   
3774   return TRUE;
3775 }
3776
3777 /* Server side command of CMODE. Changes channel mode */
3778
3779 SILC_SERVER_CMD_FUNC(cmode)
3780 {
3781   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3782   SilcServer server = cmd->server;
3783   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3784   SilcIDListData idata = (SilcIDListData)client;
3785   SilcChannelID *channel_id;
3786   SilcChannelEntry channel;
3787   SilcChannelClientEntry chl;
3788   SilcBuffer packet, cidp;
3789   unsigned char *tmp, *tmp_id, *tmp_mask;
3790   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3791   uint32 mode_mask, tmp_len, tmp_len2;
3792   uint16 ident = silc_command_get_ident(cmd->payload);
3793
3794   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3795
3796   /* Get Channel ID */
3797   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3798   if (!tmp_id) {
3799     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3800                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3801     goto out;
3802   }
3803   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3804   if (!channel_id) {
3805     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3806                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3807     goto out;
3808   }
3809
3810   /* Get the channel mode mask */
3811   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3812   if (!tmp_mask) {
3813     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3814                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3815     goto out;
3816   }
3817   SILC_GET32_MSB(mode_mask, tmp_mask);
3818
3819   /* Get channel entry */
3820   channel = silc_idlist_find_channel_by_id(server->local_list, 
3821                                            channel_id, NULL);
3822   if (!channel) {
3823     channel = silc_idlist_find_channel_by_id(server->global_list, 
3824                                              channel_id, NULL);
3825     if (!channel) {
3826       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3827                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3828       goto out;
3829     }
3830   }
3831
3832   /* Check whether this client is on the channel */
3833   if (!silc_server_client_on_channel(client, channel)) {
3834     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3835                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3836     goto out;
3837   }
3838
3839   /* Get entry to the channel user list */
3840   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
3841
3842   /* Check that client has rights to change any requested channel modes */
3843   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3844     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3845                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3846     goto out;
3847   }
3848
3849   /*
3850    * Check the modes. Modes that requires nothing special operation are
3851    * not checked here.
3852    */
3853
3854   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3855     /* Channel uses private keys to protect traffic. Client(s) has set the
3856        key locally they want to use, server does not know that key. */
3857     /* Nothing interesting to do here */
3858   } else {
3859     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3860       /* The mode is removed and we need to generate and distribute
3861          new channel key. Clients are not using private channel keys
3862          anymore after this. */
3863       
3864       /* Re-generate channel key */
3865       if (!silc_server_create_channel_key(server, channel, 0))
3866         goto out;
3867         
3868       /* Send the channel key. This sends it to our local clients and if
3869          we are normal server to our router as well. */
3870       silc_server_send_channel_key(server, NULL, channel, 
3871                                    server->server_type == SILC_ROUTER ? 
3872                                    FALSE : !server->standalone);
3873         
3874       cipher = channel->channel_key->cipher->name;
3875       hmac = (char *)silc_hmac_get_name(channel->hmac);
3876     }
3877   }
3878
3879   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3880     /* User limit is set on channel */
3881     uint32 user_limit;
3882       
3883     /* Get user limit */
3884     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3885     if (!tmp) {
3886       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3887         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3888                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3889         goto out;
3890       }
3891     } else {
3892       SILC_GET32_MSB(user_limit, tmp);
3893       channel->user_limit = user_limit;
3894     }
3895   } else {
3896     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3897       /* User limit mode is unset. Remove user limit */
3898       channel->user_limit = 0;
3899   }
3900
3901   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3902     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3903       /* Passphrase has been set to channel */
3904       
3905       /* Get the passphrase */
3906       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3907       if (!tmp) {
3908         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3909                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3910         goto out;
3911       }
3912
3913       /* Save the passphrase */
3914       passphrase = channel->passphrase = strdup(tmp);
3915     }
3916   } else {
3917     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3918       /* Passphrase mode is unset. remove the passphrase */
3919       if (channel->passphrase) {
3920         silc_free(channel->passphrase);
3921         channel->passphrase = NULL;
3922       }
3923     }
3924   }
3925
3926   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3927     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3928       /* Cipher to use protect the traffic */
3929       SilcCipher newkey, oldkey;
3930
3931       /* Get cipher */
3932       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3933       if (!cipher) {
3934         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3935                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3936         goto out;
3937       }
3938
3939       /* Delete old cipher and allocate the new one */
3940       if (!silc_cipher_alloc(cipher, &newkey)) {
3941         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3942                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3943         goto out;
3944       }
3945
3946       oldkey = channel->channel_key;
3947       channel->channel_key = newkey;
3948
3949       /* Re-generate channel key */
3950       if (!silc_server_create_channel_key(server, channel, 0)) {
3951         /* We don't have new key, revert to old one */
3952         channel->channel_key = oldkey;
3953         goto out;
3954       }
3955
3956       /* Remove old channel key for good */
3957       silc_cipher_free(oldkey);
3958
3959       /* Send the channel key. This sends it to our local clients and if
3960          we are normal server to our router as well. */
3961       silc_server_send_channel_key(server, NULL, channel, 
3962                                    server->server_type == SILC_ROUTER ? 
3963                                    FALSE : !server->standalone);
3964     }
3965   } else {
3966     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3967       /* Cipher mode is unset. Remove the cipher and revert back to 
3968          default cipher */
3969       SilcCipher newkey, oldkey;
3970       cipher = channel->cipher;
3971
3972       /* Delete old cipher and allocate default one */
3973       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3974         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3975                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3976         goto out;
3977       }
3978
3979       oldkey = channel->channel_key;
3980       channel->channel_key = newkey;
3981
3982       /* Re-generate channel key */
3983       if (!silc_server_create_channel_key(server, channel, 0)) {
3984         /* We don't have new key, revert to old one */
3985         channel->channel_key = oldkey;
3986         goto out;
3987       }
3988       
3989       /* Remove old channel key for good */
3990       silc_cipher_free(oldkey);
3991
3992       /* Send the channel key. This sends it to our local clients and if
3993          we are normal server to our router as well. */
3994       silc_server_send_channel_key(server, NULL, channel, 
3995                                    server->server_type == SILC_ROUTER ? 
3996                                    FALSE : !server->standalone);
3997     }
3998   }
3999
4000   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4001     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4002       /* HMAC to use protect the traffic */
4003       unsigned char hash[32];
4004       SilcHmac newhmac;
4005
4006       /* Get hmac */
4007       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4008       if (!hmac) {
4009         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4010                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4011         goto out;
4012       }
4013
4014       /* Delete old hmac and allocate the new one */
4015       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4016         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4017                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4018         goto out;
4019       }
4020
4021       silc_hmac_free(channel->hmac);
4022       channel->hmac = newhmac;
4023
4024       /* Set the HMAC key out of current channel key. The client must do
4025          this locally. */
4026       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4027                      channel->key_len / 8, hash);
4028       silc_hmac_set_key(channel->hmac, hash, 
4029                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4030       memset(hash, 0, sizeof(hash));
4031     }
4032   } else {
4033     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4034       /* Hmac mode is unset. Remove the hmac and revert back to 
4035          default hmac */
4036       SilcHmac newhmac;
4037       unsigned char hash[32];
4038       hmac = channel->hmac_name;
4039
4040       /* Delete old hmac and allocate default one */
4041       silc_hmac_free(channel->hmac);
4042       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4043         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4044                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4045         goto out;
4046       }
4047
4048       silc_hmac_free(channel->hmac);
4049       channel->hmac = newhmac;
4050
4051       /* Set the HMAC key out of current channel key. The client must do
4052          this locally. */
4053       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4054                      channel->key_len / 8, 
4055                      hash);
4056       silc_hmac_set_key(channel->hmac, hash, 
4057                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4058       memset(hash, 0, sizeof(hash));
4059     }
4060   }
4061
4062   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4063     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4064       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4065         /* Set the founder authentication */
4066         SilcAuthPayload auth;
4067         
4068         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4069         if (!tmp) {
4070           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4071                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4072           goto out;
4073         }
4074
4075         auth = silc_auth_payload_parse(tmp, tmp_len);
4076         if (!auth) {
4077           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4078                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4079           goto out;
4080         }
4081
4082         /* Save the public key */
4083         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4084         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4085         silc_free(tmp);
4086         
4087         channel->founder_method = silc_auth_get_method(auth);
4088
4089         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4090           tmp = silc_auth_get_data(auth, &tmp_len);
4091           channel->founder_passwd = 
4092             silc_calloc(tmp_len + 1, sizeof(*channel->founder_passwd));
4093           memcpy(channel->founder_passwd, tmp, tmp_len);
4094           channel->founder_passwd_len = tmp_len;
4095         } else {
4096           /* Verify the payload before setting the mode */
4097           if (!silc_auth_verify(auth, channel->founder_method, 
4098                                 channel->founder_key, 0, idata->hash,
4099                                 client->id, SILC_ID_CLIENT)) {
4100             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4101                                                   SILC_STATUS_ERR_AUTH_FAILED);
4102             goto out;
4103           }
4104         }
4105
4106         silc_auth_payload_free(auth);
4107       }
4108     }
4109   } else {
4110     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4111       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4112         if (channel->founder_key)
4113           silc_pkcs_public_key_free(channel->founder_key);
4114         if (channel->founder_passwd) {
4115           silc_free(channel->founder_passwd);
4116           channel->founder_passwd = NULL;
4117         }
4118       }
4119     }
4120   }
4121
4122   /* Finally, set the mode */
4123   channel->mode = mode_mask;
4124
4125   /* Send CMODE_CHANGE notify. */
4126   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4127   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4128                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4129                                      cidp->data, cidp->len, 
4130                                      tmp_mask, 4,
4131                                      cipher, cipher ? strlen(cipher) : 0,
4132                                      hmac, hmac ? strlen(hmac) : 0,
4133                                      passphrase, passphrase ? 
4134                                      strlen(passphrase) : 0);
4135
4136   /* Set CMODE notify type to network */
4137   if (!server->standalone)
4138     silc_server_send_notify_cmode(server, server->router->connection,
4139                                   server->server_type == SILC_ROUTER ? 
4140                                   TRUE : FALSE, channel,
4141                                   mode_mask, client->id, SILC_ID_CLIENT,
4142                                   cipher, hmac, passphrase);
4143
4144   /* Send command reply to sender */
4145   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4146                                                 SILC_STATUS_OK, ident, 2,
4147                                                 2, tmp_id, tmp_len2,
4148                                                 3, tmp_mask, 4);
4149   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4150                           packet->data, packet->len, FALSE);
4151     
4152   silc_buffer_free(packet);
4153   silc_free(channel_id);
4154   silc_buffer_free(cidp);
4155
4156  out:
4157   silc_server_command_free(cmd);
4158 }
4159
4160 /* Server side of CUMODE command. Changes client's mode on a channel. */
4161
4162 SILC_SERVER_CMD_FUNC(cumode)
4163 {
4164   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4165   SilcServer server = cmd->server;
4166   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4167   SilcIDListData idata = (SilcIDListData)client;
4168   SilcChannelID *channel_id;
4169   SilcClientID *client_id;
4170   SilcChannelEntry channel;
4171   SilcClientEntry target_client;
4172   SilcChannelClientEntry chl;
4173   SilcBuffer packet, idp;
4174   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4175   uint32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4176   int notify = FALSE;
4177   uint16 ident = silc_command_get_ident(cmd->payload);
4178
4179   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4180
4181   /* Get Channel ID */
4182   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4183   if (!tmp_ch_id) {
4184     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4185                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4186     goto out;
4187   }
4188   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
4189   if (!channel_id) {
4190     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4191                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4192     goto out;
4193   }
4194
4195   /* Get channel entry */
4196   channel = silc_idlist_find_channel_by_id(server->local_list, 
4197                                            channel_id, NULL);
4198   if (!channel) {
4199     channel = silc_idlist_find_channel_by_id(server->global_list, 
4200                                              channel_id, NULL);
4201     if (!channel) {
4202       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4203                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4204       goto out;
4205     }
4206   }
4207
4208   /* Check whether sender is on the channel */
4209   if (!silc_server_client_on_channel(client, channel)) {
4210     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4211                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4212     goto out;
4213   }
4214
4215   /* Check that client has rights to change other's rights */
4216   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4217   sender_mask = chl->mode;
4218   
4219   /* Get the target client's channel mode mask */
4220   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4221   if (!tmp_mask) {
4222     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4223                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4224     goto out;
4225   }
4226   SILC_GET32_MSB(target_mask, tmp_mask);
4227
4228   /* Get target Client ID */
4229   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4230   if (!tmp_id) {
4231     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4232                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4233     goto out;
4234   }
4235   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
4236   if (!client_id) {
4237     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4238                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4239     goto out;
4240   }
4241
4242   /* Get target client's entry */
4243   target_client = silc_idlist_find_client_by_id(server->local_list, 
4244                                                 client_id, TRUE, NULL);
4245   if (!target_client) {
4246     target_client = silc_idlist_find_client_by_id(server->global_list, 
4247                                                   client_id, TRUE, NULL);
4248   }
4249
4250   if (target_client != client &&
4251       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4252       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4253     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4254                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4255     goto out;
4256   }
4257
4258   /* Check whether target client is on the channel */
4259   if (target_client != client) {
4260     if (!silc_server_client_on_channel(target_client, channel)) {
4261       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4262                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4263       goto out;
4264     }
4265
4266     /* Get entry to the channel user list */
4267     silc_hash_table_find(channel->user_list, target_client, NULL, 
4268                          (void *)&chl);
4269   }
4270
4271   /* 
4272    * Change the mode 
4273    */
4274
4275   /* If the target client is founder, no one else can change their mode
4276      but themselves. */
4277   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4279                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4280     goto out;
4281   }
4282
4283   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4284     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4285       /* The client tries to claim the founder rights. */
4286       unsigned char *tmp_auth;
4287       uint32 tmp_auth_len, auth_len;
4288       void *auth;
4289       
4290       if (target_client != client) {
4291         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4292                                               SILC_STATUS_ERR_NOT_YOU);
4293         goto out;
4294       }
4295
4296       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4297           !channel->founder_key || !idata->public_key ||
4298           !silc_pkcs_public_key_compare(channel->founder_key, 
4299                                         idata->public_key)) {
4300         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4301                                               SILC_STATUS_ERR_NOT_YOU);
4302         goto out;
4303       }
4304
4305       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4306       if (!tmp_auth) {
4307         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4308                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4309         goto out;
4310       }
4311
4312       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4313               (void *)channel->founder_passwd : (void *)channel->founder_key);
4314       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4315                   channel->founder_passwd_len : 0);
4316       
4317       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4318                                  channel->founder_method, auth, auth_len,
4319                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4320         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4321                                               SILC_STATUS_ERR_AUTH_FAILED);
4322         goto out;
4323       }
4324       
4325       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4326       notify = TRUE;
4327     }
4328   } else {
4329     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4330       if (target_client == client) {
4331         /* Remove channel founder rights from itself */
4332         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4333         notify = TRUE;
4334       } else {
4335         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4336                                               SILC_STATUS_ERR_NOT_YOU);
4337         goto out;
4338       }
4339     }
4340   }
4341
4342   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4343     /* Promote to operator */
4344     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4345       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4346           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4347         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4348                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4349         goto out;
4350       }
4351
4352       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4353       notify = TRUE;
4354     }
4355   } else {
4356     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4357       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4358           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4359         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4360                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4361         goto out;
4362       }
4363
4364       /* Demote to normal user */
4365       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4366       notify = TRUE;
4367     }
4368   }
4369
4370   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4371   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4372
4373   /* Send notify to channel, notify only if mode was actually changed. */
4374   if (notify) {
4375     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4376                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4377                                        idp->data, idp->len,
4378                                        tmp_mask, 4, 
4379                                        tmp_id, tmp_len);
4380
4381     /* Set CUMODE notify type to network */
4382     if (!server->standalone)
4383       silc_server_send_notify_cumode(server, server->router->connection,
4384                                      server->server_type == SILC_ROUTER ? 
4385                                      TRUE : FALSE, channel,
4386                                      target_mask, client->id, 
4387                                      SILC_ID_CLIENT,
4388                                      target_client->id);
4389   }
4390
4391   /* Send command reply to sender */
4392   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4393                                                 SILC_STATUS_OK, ident, 3,
4394                                                 2, tmp_mask, 4,
4395                                                 3, tmp_ch_id, tmp_ch_len,
4396                                                 4, tmp_id, tmp_len);
4397   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4398                           packet->data, packet->len, FALSE);
4399     
4400   silc_buffer_free(packet);
4401   silc_free(channel_id);
4402   silc_free(client_id);
4403   silc_buffer_free(idp);
4404
4405  out:
4406   silc_server_command_free(cmd);
4407 }
4408
4409 /* Server side of KICK command. Kicks client out of channel. */
4410
4411 SILC_SERVER_CMD_FUNC(kick)
4412 {
4413   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4414   SilcServer server = cmd->server;
4415   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4416   SilcClientEntry target_client;
4417   SilcChannelID *channel_id;
4418   SilcClientID *client_id;
4419   SilcChannelEntry channel;
4420   SilcChannelClientEntry chl;
4421   SilcBuffer idp;
4422   uint32 tmp_len, target_idp_len;
4423   unsigned char *tmp, *comment, *target_idp;
4424
4425   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4426
4427   /* Get Channel ID */
4428   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4429   if (!tmp) {
4430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4431                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4432     goto out;
4433   }
4434   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
4435   if (!channel_id) {
4436     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4437                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4438     goto out;
4439   }
4440
4441   /* Get channel entry */
4442   channel = silc_idlist_find_channel_by_id(server->local_list, 
4443                                            channel_id, NULL);
4444   if (!channel) {
4445     channel = silc_idlist_find_channel_by_id(server->local_list, 
4446                                              channel_id, NULL);
4447     if (!channel) {
4448       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4449                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4450       goto out;
4451     }
4452   }
4453
4454   /* Check whether sender is on the channel */
4455   if (!silc_server_client_on_channel(client, channel)) {
4456     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4457                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4458     goto out;
4459   }
4460
4461   /* Check that the kicker is channel operator or channel founder */
4462   silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl);
4463   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4464     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4465                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4466     goto out;
4467   }
4468   
4469   /* Get target Client ID */
4470   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4471   if (!target_idp) {
4472     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4474     goto out;
4475   }
4476   client_id = silc_id_payload_parse_id(target_idp, target_idp_len);
4477   if (!client_id) {
4478     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4479                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4480     goto out;
4481   }
4482
4483   /* Get target client's entry */
4484   target_client = silc_idlist_find_client_by_id(server->local_list, 
4485                                                 client_id, TRUE, NULL);
4486   if (!target_client) {
4487     target_client = silc_idlist_find_client_by_id(server->global_list, 
4488                                                   client_id, TRUE, NULL);
4489   }
4490
4491   /* Check that the target client is not channel founder. Channel founder
4492      cannot be kicked from the channel. */
4493   silc_hash_table_find(channel->user_list, target_client, NULL, (void *)&chl);
4494   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4495     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4496                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4497     goto out;
4498   }
4499   
4500   /* Check whether target client is on the channel */
4501   if (!silc_server_client_on_channel(target_client, channel)) {
4502     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4503                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4504     goto out;
4505   }
4506
4507   /* Get comment */
4508   tmp_len = 0;
4509   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4510   if (tmp_len > 128)
4511     comment = NULL;
4512
4513   /* Send command reply to sender */
4514   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4515                                         SILC_STATUS_OK);
4516
4517   /* Send KICKED notify to local clients on the channel */
4518   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4519   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4520                                      SILC_NOTIFY_TYPE_KICKED, 3,
4521                                      target_idp, target_idp_len,
4522                                      comment, comment ? strlen(comment) : 0,
4523                                      idp->data, idp->len);
4524   silc_buffer_free(idp);
4525
4526   /* Remove the client from the channel. If the channel does not exist
4527      after removing the client then the client kicked itself off the channel
4528      and we don't have to send anything after that. */
4529   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4530                                            target_client, FALSE))
4531     goto out;
4532
4533   /* Send KICKED notify to primary route */
4534   if (!server->standalone)
4535     silc_server_send_notify_kicked(server, server->router->connection,
4536                                    server->server_type == SILC_ROUTER ?
4537                                    TRUE : FALSE, channel,
4538                                    target_client->id, client->id, comment);
4539
4540   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4541     /* Re-generate channel key */
4542     if (!silc_server_create_channel_key(server, channel, 0))
4543       goto out;
4544     
4545     /* Send the channel key to the channel. The key of course is not sent
4546        to the client who was kicked off the channel. */
4547     silc_server_send_channel_key(server, target_client->connection, channel, 
4548                                  server->server_type == SILC_ROUTER ? 
4549                                  FALSE : !server->standalone);
4550   }
4551
4552  out:
4553   silc_server_command_free(cmd);
4554 }
4555
4556 /* Server side of OPER command. Client uses this comand to obtain server
4557    operator privileges to this server/router. */
4558
4559 SILC_SERVER_CMD_FUNC(oper)
4560 {
4561   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4562   SilcServer server = cmd->server;
4563   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4564   unsigned char *username, *auth;
4565   uint32 tmp_len;
4566   SilcServerConfigSectionAdminConnection *admin;
4567   SilcIDListData idata = (SilcIDListData)client;
4568
4569   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4570
4571   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4572     goto out;
4573
4574   /* Get the username */
4575   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4576   if (!username) {
4577     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4578                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4579     goto out;
4580   }
4581
4582   /* Get the admin configuration */
4583   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4584                                         username, client->nickname);
4585   if (!admin) {
4586     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4587                                           username, client->nickname);
4588     if (!admin) {
4589       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4590                                             SILC_STATUS_ERR_AUTH_FAILED);
4591       goto out;
4592     }
4593   }
4594
4595   /* Get the authentication payload */
4596   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4597   if (!auth) {
4598     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4599                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4600     goto out;
4601   }
4602
4603   /* Verify the authentication data */
4604   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4605                              admin->auth_data, admin->auth_data_len,
4606                              idata->hash, client->id, SILC_ID_CLIENT)) {
4607     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4608                                           SILC_STATUS_ERR_AUTH_FAILED);
4609     goto out;
4610   }
4611
4612   /* Client is now server operator */
4613   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4614
4615   /* Update statistics */
4616   if (client->connection)
4617     server->stat.my_server_ops++;
4618   if (server->server_type == SILC_ROUTER)
4619     server->stat.server_ops++;
4620
4621   /* Send UMODE change to primary router */
4622   if (!server->standalone)
4623     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4624                                   client->id, client->mode);
4625
4626   /* Send reply to the sender */
4627   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4628                                         SILC_STATUS_OK);
4629
4630  out:
4631   silc_server_command_free(cmd);
4632 }
4633
4634 /* Server side of SILCOPER command. Client uses this comand to obtain router
4635    operator privileges to this router. */
4636
4637 SILC_SERVER_CMD_FUNC(silcoper)
4638 {
4639   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4640   SilcServer server = cmd->server;
4641   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4642   unsigned char *username, *auth;
4643   uint32 tmp_len;
4644   SilcServerConfigSectionAdminConnection *admin;
4645   SilcIDListData idata = (SilcIDListData)client;
4646
4647   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4648
4649   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4650     goto out;
4651
4652   if (server->server_type != SILC_ROUTER) {
4653     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4654                                           SILC_STATUS_ERR_AUTH_FAILED);
4655     goto out;
4656   }
4657
4658   /* Get the username */
4659   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4660   if (!username) {
4661     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4662                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4663     goto out;
4664   }
4665
4666   /* Get the admin configuration */
4667   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4668                                         username, client->nickname);
4669   if (!admin) {
4670     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4671                                           username, client->nickname);
4672     if (!admin) {
4673       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4674                                             SILC_STATUS_ERR_AUTH_FAILED);
4675       goto out;
4676     }
4677   }
4678
4679   /* Get the authentication payload */
4680   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4681   if (!auth) {
4682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4683                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4684     goto out;
4685   }
4686
4687   /* Verify the authentication data */
4688   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4689                              admin->auth_data, admin->auth_data_len,
4690                              idata->hash, client->id, SILC_ID_CLIENT)) {
4691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4692                                           SILC_STATUS_ERR_AUTH_FAILED);
4693     goto out;
4694   }
4695
4696   /* Client is now router operator */
4697   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4698
4699   /* Update statistics */
4700   if (client->connection)
4701     server->stat.my_router_ops++;
4702   if (server->server_type == SILC_ROUTER)
4703     server->stat.router_ops++;
4704
4705   /* Send UMODE change to primary router */
4706   if (!server->standalone)
4707     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4708                                   client->id, client->mode);
4709
4710   /* Send reply to the sender */
4711   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4712                                         SILC_STATUS_OK);
4713
4714  out:
4715   silc_server_command_free(cmd);
4716 }
4717
4718 /* Server side command of CONNECT. Connects us to the specified remote
4719    server or router. */
4720
4721 SILC_SERVER_CMD_FUNC(connect)
4722 {
4723   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4724   SilcServer server = cmd->server;
4725   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4726   unsigned char *tmp, *host;
4727   uint32 tmp_len;
4728   uint32 port = SILC_PORT;
4729
4730   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CONNECT, cmd, 1, 2);
4731
4732   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4733     goto out;
4734
4735   /* Check whether client has the permissions. */
4736   if (client->mode == SILC_UMODE_NONE) {
4737     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4738                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4739     goto out;
4740   }
4741
4742   if (server->server_type == SILC_ROUTER && 
4743       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4744     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4745                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4746     goto out;
4747   }
4748
4749   /* Get the remote server */
4750   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4751   if (!host) {
4752     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4753                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4754     goto out;
4755   }
4756
4757   /* Get port */
4758   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4759   if (tmp)
4760     SILC_GET32_MSB(port, tmp);
4761
4762   /* Create the connection. It is done with timeout and is async. */
4763   silc_server_create_connection(server, host, port);
4764
4765   /* Send reply to the sender */
4766   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4767                                         SILC_STATUS_OK);
4768
4769  out:
4770   silc_server_command_free(cmd);
4771 }
4772
4773 /* Server side of command BAN. This is used to manage the ban list of the
4774    channel. To add clients and remove clients from the ban list. */
4775
4776 SILC_SERVER_CMD_FUNC(ban)
4777 {
4778   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4779   SilcServer server = cmd->server;
4780   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4781   SilcBuffer packet;
4782   SilcChannelEntry channel;
4783   SilcChannelClientEntry chl;
4784   SilcChannelID *channel_id = NULL;
4785   unsigned char *id, *add, *del;
4786   uint32 id_len, tmp_len;
4787   uint16 ident = silc_command_get_ident(cmd->payload);
4788
4789   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4790     goto out;
4791
4792   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4793
4794   /* Get Channel ID */
4795   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4796   if (id) {
4797     channel_id = silc_id_payload_parse_id(id, id_len);
4798     if (!channel_id) {
4799       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4800                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4801       goto out;
4802     }
4803   }
4804
4805   /* Get channel entry. The server must know about the channel since the
4806      client is expected to be on the channel. */
4807   channel = silc_idlist_find_channel_by_id(server->local_list, 
4808                                            channel_id, NULL);
4809   if (!channel) {
4810     channel = silc_idlist_find_channel_by_id(server->global_list, 
4811                                              channel_id, NULL);
4812     if (!channel) {
4813       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4814                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4815       goto out;
4816     }
4817   }
4818
4819   /* Check whether this client is on the channel */
4820   if (!silc_server_client_on_channel(client, channel)) {
4821     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4822                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4823     goto out;
4824   }
4825
4826   /* Get entry to the channel user list */
4827   if (!silc_hash_table_find(channel->user_list, client, NULL, (void *)&chl)) {
4828     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4829                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4830     goto out;
4831   }
4832
4833   /* The client must be at least channel operator. */
4834   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4835     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4836                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4837     goto out;
4838   }
4839
4840   /* Get the new ban and add it to the ban list */
4841   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4842   if (add) {
4843     if (!channel->ban_list)
4844       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4845     else
4846       channel->ban_list = silc_realloc(channel->ban_list, 
4847                                        sizeof(*channel->ban_list) * 
4848                                        (tmp_len + 
4849                                         strlen(channel->ban_list) + 2));
4850     if (add[tmp_len - 1] == ',')
4851       add[tmp_len - 1] = '\0';
4852
4853     strncat(channel->ban_list, add, tmp_len);
4854     strncat(channel->ban_list, ",", 1);
4855   }
4856
4857   /* Get the ban to be removed and remove it from the list */
4858   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4859   if (del && channel->ban_list) {
4860     char *start, *end, *n;
4861
4862     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4863       silc_free(channel->ban_list);
4864       channel->ban_list = NULL;
4865     } else {
4866       start = strstr(channel->ban_list, del);
4867       if (start && strlen(start) >= tmp_len) {
4868         end = start + tmp_len;
4869         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4870         strncat(n, channel->ban_list, start - channel->ban_list);
4871         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4872                              end) - 1);
4873         silc_free(channel->ban_list);
4874         channel->ban_list = n;
4875       }
4876     }
4877   }
4878
4879   /* Send the BAN notify type to our primary router. */
4880   if (!server->standalone && (add || del))
4881     silc_server_send_notify_ban(server, server->router->connection,
4882                                 server->server_type == SILC_ROUTER ?
4883                                 TRUE : FALSE, channel, add, del);
4884
4885   /* Send the reply back to the client */
4886   packet = 
4887     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4888                                          SILC_STATUS_OK, ident, 2,
4889                                          2, id, id_len,
4890                                          3, channel->ban_list, 
4891                                          channel->ban_list ? 
4892                                          strlen(channel->ban_list) : 0);
4893   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4894                           packet->data, packet->len, FALSE);
4895     
4896   silc_buffer_free(packet);
4897
4898  out:
4899   silc_free(channel_id);
4900   silc_server_command_free(cmd);
4901 }
4902
4903 /* Server side command of CLOSE. Closes connection to a specified server. */
4904  
4905 SILC_SERVER_CMD_FUNC(close)
4906 {
4907   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4908   SilcServer server = cmd->server;
4909   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4910   SilcServerEntry server_entry;
4911   SilcSocketConnection sock;
4912   unsigned char *tmp;
4913   uint32 tmp_len;
4914   unsigned char *name;
4915   uint32 port = SILC_PORT;
4916
4917   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CLOSE, cmd, 1, 2);
4918
4919   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4920     goto out;
4921
4922   /* Check whether client has the permissions. */
4923   if (client->mode == SILC_UMODE_NONE) {
4924     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4925                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4926     goto out;
4927   }
4928
4929   /* Get the remote server */
4930   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4931   if (!name) {
4932     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4933                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4934     goto out;
4935   }
4936
4937   /* Get port */
4938   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4939   if (tmp)
4940     SILC_GET32_MSB(port, tmp);
4941
4942   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4943                                                  name, port, FALSE, NULL);
4944   if (!server_entry)
4945     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4946                                                    name, port, FALSE, NULL);
4947   if (!server_entry) {
4948     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4949                                           SILC_STATUS_ERR_NO_SERVER_ID);
4950     goto out;
4951   }
4952
4953   /* Send reply to the sender */
4954   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4955                                         SILC_STATUS_OK);
4956
4957   /* Close the connection to the server */
4958   sock = (SilcSocketConnection)server_entry->connection;
4959
4960   /* If we shutdown primary router connection manually then don't trigger
4961      any reconnect or backup router connections, by setting the router
4962      to NULL here. */
4963   if (server->router == server_entry) {
4964     server->id_entry->router = NULL;
4965     server->router = NULL;
4966     server->standalone = TRUE;
4967   }
4968   silc_server_free_sock_user_data(server, sock, NULL);
4969   silc_server_close_connection(server, sock);
4970   
4971  out:
4972   silc_server_command_free(cmd);
4973 }
4974
4975 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4976    active connections. */
4977  
4978 SILC_SERVER_CMD_FUNC(shutdown)
4979 {
4980   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4981   SilcServer server = cmd->server;
4982   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4983
4984   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4985
4986   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4987     goto out;
4988
4989   /* Check whether client has the permission. */
4990   if (client->mode == SILC_UMODE_NONE) {
4991     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4992                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4993     goto out;
4994   }
4995
4996   /* Send reply to the sender */
4997   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4998                                         SILC_STATUS_OK);
4999
5000   /* Then, gracefully, or not, bring the server down. */
5001   silc_server_stop(server);
5002   exit(0);
5003
5004  out:
5005   silc_server_command_free(cmd);
5006 }
5007  
5008 /* Server side command of LEAVE. Removes client from a channel. */
5009
5010 SILC_SERVER_CMD_FUNC(leave)
5011 {
5012   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5013   SilcServer server = cmd->server;
5014   SilcSocketConnection sock = cmd->sock;
5015   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5016   SilcChannelID *id = NULL;
5017   SilcChannelEntry channel;
5018   uint32 len;
5019   unsigned char *tmp;
5020
5021   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5022
5023   /* Get Channel ID */
5024   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5025   if (!tmp) {
5026     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5027                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5028     goto out;
5029   }
5030   id = silc_id_payload_parse_id(tmp, len);
5031   if (!id) {
5032     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5033                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5034     goto out;
5035   }
5036
5037   /* Get channel entry */
5038   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5039   if (!channel) {
5040     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5041     if (!channel) {
5042       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5043                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5044       goto out;
5045     }
5046   }
5047
5048   /* Check whether this client is on the channel */
5049   if (!silc_server_client_on_channel(id_entry, channel)) {
5050     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5051                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
5052     goto out;
5053   }
5054
5055   /* Notify routers that they should remove this client from their list
5056      of clients on the channel. Send LEAVE notify type. */
5057   if (!server->standalone)
5058     silc_server_send_notify_leave(server, server->router->connection,
5059                                   server->server_type == SILC_ROUTER ?
5060                                   TRUE : FALSE, channel, id_entry->id);
5061
5062   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5063                                         SILC_STATUS_OK);
5064
5065   /* Remove client from channel */
5066   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5067                                            TRUE))
5068     /* If the channel does not exist anymore we won't send anything */
5069     goto out;
5070
5071   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5072     /* Re-generate channel key */
5073     if (!silc_server_create_channel_key(server, channel, 0))
5074       goto out;
5075
5076     /* Send the channel key */
5077     silc_server_send_channel_key(server, NULL, channel, 
5078                                  server->server_type == SILC_ROUTER ? 
5079                                  FALSE : !server->standalone);
5080   }
5081
5082  out:
5083   silc_free(id);
5084   silc_server_command_free(cmd);
5085 }
5086
5087 /* Server side of command USERS. Resolves clients and their USERS currently
5088    joined on the requested channel. The list of Client ID's and their modes
5089    on the channel is sent back. */
5090
5091 SILC_SERVER_CMD_FUNC(users)
5092 {
5093   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5094   SilcServer server = cmd->server;
5095   SilcChannelEntry channel;
5096   SilcChannelID *id = NULL;
5097   SilcBuffer packet, idp;
5098   unsigned char *channel_id;
5099   uint32 channel_id_len;
5100   SilcBuffer client_id_list;
5101   SilcBuffer client_mode_list;
5102   unsigned char lc[4];
5103   uint32 list_count = 0;
5104   uint16 ident = silc_command_get_ident(cmd->payload);
5105   char *channel_name;
5106
5107   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5108
5109   /* Get Channel ID */
5110   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5111
5112   /* Get channel name */
5113   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5114
5115   if (!channel_id && !channel_name) {
5116     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5117                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5118     goto out;
5119   }
5120
5121   if (channel_id) {
5122     id = silc_id_payload_parse_id(channel_id, channel_id_len);
5123     if (!id) {
5124       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5125                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5126       goto out;
5127     }
5128   }
5129
5130   /* If we are server and we don't know about this channel we will send
5131      the command to our router. If we know about the channel then we also
5132      have the list of users already. */
5133   if (id)
5134     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5135   else
5136     channel = silc_idlist_find_channel_by_name(server->local_list, 
5137                                                channel_name, NULL);
5138
5139   if (!channel || channel->disabled) {
5140     if (server->server_type != SILC_ROUTER && !server->standalone &&
5141         !cmd->pending) {
5142       SilcBuffer tmpbuf;
5143       
5144       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5145       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5146       
5147       /* Send USERS command */
5148       silc_server_packet_send(server, server->router->connection,
5149                               SILC_PACKET_COMMAND, cmd->packet->flags,
5150                               tmpbuf->data, tmpbuf->len, TRUE);
5151       
5152       /* Reprocess this packet after received reply */
5153       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5154                                   silc_command_get_ident(cmd->payload),
5155                                   silc_server_command_users,
5156                                   silc_server_command_dup(cmd));
5157       cmd->pending = TRUE;
5158       silc_command_set_ident(cmd->payload, ident);
5159       silc_buffer_free(tmpbuf);
5160       silc_free(id);
5161       goto out;
5162     }
5163
5164     /* Check the global list as well. */
5165     if (id)
5166       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5167     else
5168       channel = silc_idlist_find_channel_by_name(server->global_list, 
5169                                                  channel_name, NULL);
5170     if (!channel) {
5171       /* Channel really does not exist */
5172       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5173                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5174       goto out;
5175     }
5176   }
5177
5178   /* If the channel is private or secret do not send anything, unless the
5179      user requesting this command is on the channel. */
5180   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5181     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5182         && !silc_server_client_on_channel(cmd->sock->user_data, channel)) {
5183       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5184                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5185       goto out;
5186     }
5187   } else {
5188     if (channel->mode & 
5189         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5190       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5191                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5192       goto out;
5193     }
5194   }
5195
5196   /* Get the users list */
5197   silc_server_get_users_on_channel(server, channel, &client_id_list,
5198                                    &client_mode_list, &list_count);
5199
5200   /* List count */
5201   SILC_PUT32_MSB(list_count, lc);
5202
5203   /* Send reply */
5204   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5205   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5206                                                 SILC_STATUS_OK, ident, 4,
5207                                                 2, idp->data, idp->len,
5208                                                 3, lc, 4,
5209                                                 4, client_id_list->data,
5210                                                 client_id_list->len,
5211                                                 5, client_mode_list->data,
5212                                                 client_mode_list->len);
5213   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5214                           packet->data, packet->len, FALSE);
5215     
5216   silc_buffer_free(idp);
5217   silc_buffer_free(packet);
5218   silc_buffer_free(client_id_list);
5219   silc_buffer_free(client_mode_list);
5220   silc_free(id);
5221
5222  out:
5223   silc_server_command_free(cmd);
5224 }
5225
5226 /* Server side of command GETKEY. This fetches the client's public key
5227    from the server where to the client is connected. */
5228
5229 SILC_SERVER_CMD_FUNC(getkey)
5230 {
5231   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5232   SilcServer server = cmd->server;
5233   SilcBuffer packet;
5234   SilcClientEntry client;
5235   SilcServerEntry server_entry;
5236   SilcClientID *client_id = NULL;
5237   SilcServerID *server_id = NULL;
5238   SilcIDPayload idp = NULL;
5239   uint16 ident = silc_command_get_ident(cmd->payload);
5240   unsigned char *tmp, *pkdata;
5241   uint32 tmp_len, pklen;
5242   SilcBuffer pk = NULL;
5243   SilcIdType id_type;
5244   SilcPublicKey public_key;
5245
5246   SILC_LOG_DEBUG(("Start"));
5247
5248   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5249   if (!tmp) {
5250     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5251                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5252     goto out;
5253   }
5254   idp = silc_id_payload_parse(tmp, tmp_len);
5255   if (!idp) {
5256     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5257                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5258     goto out;
5259   }
5260
5261   id_type = silc_id_payload_get_type(idp);
5262   if (id_type == SILC_ID_CLIENT) {
5263     client_id = silc_id_payload_get_id(idp);
5264
5265     /* If the client is not found from local list there is no chance it
5266        would be locally connected client so send the command further. */
5267     client = silc_idlist_find_client_by_id(server->local_list, 
5268                                            client_id, TRUE, NULL);
5269     if (!client)
5270       client = silc_idlist_find_client_by_id(server->global_list, 
5271                                              client_id, TRUE, NULL);
5272     
5273     if ((!client && !cmd->pending && !server->standalone) ||
5274         (client && !client->connection && !cmd->pending) ||
5275         (client && !client->data.public_key && !cmd->pending)) {
5276       SilcBuffer tmpbuf;
5277       uint16 old_ident;
5278       SilcSocketConnection dest_sock;
5279       
5280       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5281                                                client_id, NULL);
5282       if (!dest_sock)
5283         goto out;
5284       
5285       old_ident = silc_command_get_ident(cmd->payload);
5286       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5287       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5288       
5289       silc_server_packet_send(server, dest_sock,
5290                               SILC_PACKET_COMMAND, cmd->packet->flags,
5291                               tmpbuf->data, tmpbuf->len, TRUE);
5292       
5293       /* Reprocess this packet after received reply from router */
5294       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5295                                   silc_command_get_ident(cmd->payload),
5296                                   silc_server_command_getkey,
5297                                   silc_server_command_dup(cmd));
5298       cmd->pending = TRUE;
5299       silc_command_set_ident(cmd->payload, old_ident);
5300       silc_buffer_free(tmpbuf);
5301       goto out;
5302     }
5303
5304     if (!client) {
5305       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5306                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5307       goto out;
5308     }
5309
5310     /* The client is locally connected, just get the public key and
5311        send it back. If they key does not exist then do not send it, 
5312        send just OK reply */
5313     public_key = client->data.public_key;
5314     if (!public_key) {
5315       pkdata = NULL;
5316       pklen = 0;
5317     } else {
5318       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5319       pk = silc_buffer_alloc(4 + tmp_len);
5320       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5321       silc_buffer_format(pk,
5322                          SILC_STR_UI_SHORT(tmp_len),
5323                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5324                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5325                          SILC_STR_END);
5326       silc_free(tmp);
5327       pkdata = pk->data;
5328       pklen = pk->len;
5329     }
5330   } else if (id_type == SILC_ID_SERVER) {
5331     server_id = silc_id_payload_get_id(idp);
5332
5333     /* If the server is not found from local list there is no chance it
5334        would be locally connected server so send the command further. */
5335     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5336                                                  server_id, TRUE, NULL);
5337     if (!server_entry)
5338       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5339                                                    server_id, TRUE, NULL);
5340     
5341     if (server_entry != server->id_entry &&
5342         ((!server_entry && !cmd->pending && !server->standalone) ||
5343          (server_entry && !server_entry->connection && !cmd->pending &&
5344           !server->standalone) ||
5345          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5346           !server->standalone))) {
5347       SilcBuffer tmpbuf;
5348       uint16 old_ident;
5349       
5350       old_ident = silc_command_get_ident(cmd->payload);
5351       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5352       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5353       
5354       silc_server_packet_send(server, server->router->connection,
5355                               SILC_PACKET_COMMAND, cmd->packet->flags,
5356                               tmpbuf->data, tmpbuf->len, TRUE);
5357       
5358       /* Reprocess this packet after received reply from router */
5359       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5360                                   silc_command_get_ident(cmd->payload),
5361                                   silc_server_command_getkey,
5362                                   silc_server_command_dup(cmd));
5363       cmd->pending = TRUE;
5364       silc_command_set_ident(cmd->payload, old_ident);
5365       silc_buffer_free(tmpbuf);
5366       goto out;
5367     }
5368
5369     if (!server_entry) {
5370       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5371                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5372       goto out;
5373     }
5374
5375     /* If they key does not exist then do not send it, send just OK reply */
5376     public_key = (!server_entry->data.public_key ? 
5377                   (server_entry == server->id_entry ? server->public_key :
5378                    NULL) : server_entry->data.public_key);
5379     if (!public_key) {
5380       pkdata = NULL;
5381       pklen = 0;
5382     } else {
5383       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5384       pk = silc_buffer_alloc(4 + tmp_len);
5385       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5386       silc_buffer_format(pk,
5387                          SILC_STR_UI_SHORT(tmp_len),
5388                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5389                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5390                          SILC_STR_END);
5391       silc_free(tmp);
5392       pkdata = pk->data;
5393       pklen = pk->len;
5394     }
5395   } else {
5396     goto out;
5397   }
5398
5399   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5400   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5401                                                 SILC_STATUS_OK, ident, 
5402                                                 pkdata ? 2 : 1,
5403                                                 2, tmp, tmp_len,
5404                                                 3, pkdata, pklen);
5405   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5406                           packet->data, packet->len, FALSE);
5407   silc_buffer_free(packet);
5408
5409   if (pk)
5410     silc_buffer_free(pk);
5411
5412  out:
5413   if (idp)
5414     silc_id_payload_free(idp);
5415   silc_free(client_id);
5416   silc_free(server_id);
5417   silc_server_command_free(cmd);
5418 }