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