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