Statistics updating fixes to not go negative.
[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
3878     /* Change the mode */
3879     client->mode = mask;
3880
3881     /* Send UMODE change to primary router */
3882     if (!server->standalone)
3883       silc_server_send_notify_umode(server, server->router->connection, TRUE,
3884                                     client->id, client->mode);
3885
3886     /* Check if anyone is watching this nickname */
3887     if (server->server_type == SILC_ROUTER)
3888       silc_server_check_watcher_list(server, client, NULL,
3889                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
3890   }
3891
3892   /* Send command reply to sender */
3893   SILC_PUT32_MSB(client->mode, m);
3894   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3895                                                 SILC_STATUS_OK, 0, ident, 1,
3896                                                 2, m, sizeof(m));
3897   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3898                           packet->data, packet->len, FALSE);
3899   silc_buffer_free(packet);
3900
3901  out:
3902   silc_server_command_free(cmd);
3903 }
3904
3905 /* Server side command of CMODE. Changes channel mode */
3906
3907 SILC_SERVER_CMD_FUNC(cmode)
3908 {
3909   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3910   SilcServer server = cmd->server;
3911   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3912   SilcIDListData idata = (SilcIDListData)client;
3913   SilcChannelID *channel_id = NULL;
3914   SilcChannelEntry channel;
3915   SilcChannelClientEntry chl;
3916   SilcBuffer packet, cidp;
3917   unsigned char *tmp, *tmp_id, *tmp_mask;
3918   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3919   SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3920   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3921   bool set_mask = FALSE;
3922   SilcPublicKey founder_key = NULL;
3923   unsigned char *fkey = NULL;
3924   SilcUInt32 fkey_len = 0;
3925
3926   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3927
3928   /* Get Channel ID */
3929   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3930   if (!tmp_id) {
3931     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3932                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3933     goto out;
3934   }
3935   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3936   if (!channel_id) {
3937     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3938                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3939     goto out;
3940   }
3941
3942   /* Get the channel mode mask */
3943   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3944   if (tmp_mask) {
3945     SILC_GET32_MSB(mode_mask, tmp_mask);
3946     set_mask = TRUE;
3947   }
3948
3949   /* Get channel entry */
3950   channel = silc_idlist_find_channel_by_id(server->local_list, 
3951                                            channel_id, NULL);
3952   if (!channel) {
3953     channel = silc_idlist_find_channel_by_id(server->global_list, 
3954                                              channel_id, NULL);
3955     if (!channel) {
3956       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3957                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3958                                             0);
3959       goto out;
3960     }
3961   }
3962
3963   /* Check whether this client is on the channel */
3964   if (!silc_server_client_on_channel(client, channel, &chl)) {
3965     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3966                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3967     goto out;
3968   }
3969
3970   /* Check that client has rights to change any requested channel modes */
3971   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
3972                                                   mode_mask)) {
3973     silc_server_command_send_status_reply(
3974                              cmd, SILC_COMMAND_CMODE,
3975                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
3976                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3977                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3978     goto out;
3979   }
3980
3981   /* If mode mask was not sent as argument then merely return the current
3982      mode mask to the sender. */
3983   if (!set_mask) {
3984     unsigned char m[4];
3985     SILC_PUT32_MSB(channel->mode, m);
3986     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3987                                                   SILC_STATUS_OK, 0, ident, 2,
3988                                                   2, tmp_id, tmp_len2,
3989                                                   3, m, sizeof(m));
3990     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3991                             packet->data, packet->len, FALSE);
3992     silc_buffer_free(packet);
3993     goto out;
3994   }
3995
3996   /*
3997    * Check the modes. Modes that requires nothing special operation are
3998    * not checked here.
3999    */
4000
4001   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4002     /* Channel uses private keys to protect traffic. Client(s) has set the
4003        key locally they want to use, server does not know that key. */
4004     /* Nothing interesting to do here */
4005   } else {
4006     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4007       /* The mode is removed and we need to generate and distribute
4008          new channel key. Clients are not using private channel keys
4009          anymore after this. */
4010       
4011       /* Re-generate channel key */
4012       if (!silc_server_create_channel_key(server, channel, 0))
4013         goto out;
4014         
4015       /* Send the channel key. This sends it to our local clients and if
4016          we are normal server to our router as well. */
4017       silc_server_send_channel_key(server, NULL, channel, 
4018                                    server->server_type == SILC_ROUTER ? 
4019                                    FALSE : !server->standalone);
4020         
4021       cipher = channel->channel_key->cipher->name;
4022       hmac = (char *)silc_hmac_get_name(channel->hmac);
4023     }
4024   }
4025
4026   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4027     /* User limit is set on channel */
4028     SilcUInt32 user_limit;
4029       
4030     /* Get user limit */
4031     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4032     if (!tmp) {
4033       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4034         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4035                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4036         goto out;
4037       }
4038     } else {
4039       SILC_GET32_MSB(user_limit, tmp);
4040       channel->user_limit = user_limit;
4041     }
4042   } else {
4043     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4044       /* User limit mode is unset. Remove user limit */
4045       channel->user_limit = 0;
4046   }
4047
4048   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4049     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4050       /* Passphrase has been set to channel */
4051       
4052       /* Get the passphrase */
4053       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4054       if (!tmp) {
4055         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4056                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4057         goto out;
4058       }
4059
4060       /* Save the passphrase */
4061       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4062     }
4063   } else {
4064     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4065       /* Passphrase mode is unset. remove the passphrase */
4066       silc_free(channel->passphrase);
4067       channel->passphrase = NULL;
4068     }
4069   }
4070
4071   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4072     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4073       /* Cipher to use protect the traffic */
4074       SilcCipher newkey, oldkey;
4075
4076       /* Get cipher */
4077       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4078       if (!cipher) {
4079         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4080                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4081         goto out;
4082       }
4083
4084       /* Delete old cipher and allocate the new one */
4085       if (!silc_cipher_alloc(cipher, &newkey)) {
4086         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4087                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4088         goto out;
4089       }
4090
4091       oldkey = channel->channel_key;
4092       channel->channel_key = newkey;
4093
4094       /* Re-generate channel key */
4095       if (!silc_server_create_channel_key(server, channel, 0)) {
4096         /* We don't have new key, revert to old one */
4097         channel->channel_key = oldkey;
4098         goto out;
4099       }
4100
4101       /* Remove old channel key for good */
4102       silc_cipher_free(oldkey);
4103
4104       /* Send the channel key. This sends it to our local clients and if
4105          we are normal server to our router as well. */
4106       silc_server_send_channel_key(server, NULL, channel, 
4107                                    server->server_type == SILC_ROUTER ? 
4108                                    FALSE : !server->standalone);
4109     }
4110   } else {
4111     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4112       /* Cipher mode is unset. Remove the cipher and revert back to 
4113          default cipher */
4114       SilcCipher newkey, oldkey;
4115       cipher = channel->cipher;
4116
4117       /* Delete old cipher and allocate default one */
4118       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4119         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4120                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4121         goto out;
4122       }
4123
4124       oldkey = channel->channel_key;
4125       channel->channel_key = newkey;
4126
4127       /* Re-generate channel key */
4128       if (!silc_server_create_channel_key(server, channel, 0)) {
4129         /* We don't have new key, revert to old one */
4130         channel->channel_key = oldkey;
4131         goto out;
4132       }
4133       
4134       /* Remove old channel key for good */
4135       silc_cipher_free(oldkey);
4136
4137       /* Send the channel key. This sends it to our local clients and if
4138          we are normal server to our router as well. */
4139       silc_server_send_channel_key(server, NULL, channel, 
4140                                    server->server_type == SILC_ROUTER ? 
4141                                    FALSE : !server->standalone);
4142     }
4143   }
4144
4145   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4146     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4147       /* HMAC to use protect the traffic */
4148       unsigned char hash[32];
4149       SilcHmac newhmac;
4150
4151       /* Get hmac */
4152       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4153       if (!hmac) {
4154         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4155                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4156         goto out;
4157       }
4158
4159       /* Delete old hmac and allocate the new one */
4160       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4161         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4162                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4163         goto out;
4164       }
4165
4166       silc_hmac_free(channel->hmac);
4167       channel->hmac = newhmac;
4168
4169       /* Set the HMAC key out of current channel key. The client must do
4170          this locally. */
4171       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4172                      channel->key_len / 8, hash);
4173       silc_hmac_set_key(channel->hmac, hash, 
4174                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4175       memset(hash, 0, sizeof(hash));
4176     }
4177   } else {
4178     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4179       /* Hmac mode is unset. Remove the hmac and revert back to 
4180          default hmac */
4181       SilcHmac newhmac;
4182       unsigned char hash[32];
4183       hmac = channel->hmac_name;
4184
4185       /* Delete old hmac and allocate default one */
4186       silc_hmac_free(channel->hmac);
4187       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4188         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4189                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4190         goto out;
4191       }
4192
4193       silc_hmac_free(channel->hmac);
4194       channel->hmac = newhmac;
4195
4196       /* Set the HMAC key out of current channel key. The client must do
4197          this locally. */
4198       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4199                      channel->key_len / 8, 
4200                      hash);
4201       silc_hmac_set_key(channel->hmac, hash, 
4202                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4203       memset(hash, 0, sizeof(hash));
4204     }
4205   }
4206
4207   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4208     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4209       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4210         /* Set the founder authentication */
4211         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4212         if (!tmp) {
4213           silc_server_command_send_status_reply(
4214                                      cmd, SILC_COMMAND_CMODE,
4215                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4216           goto out;
4217         }
4218
4219         /* Verify the payload before setting the mode */
4220         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
4221                                    idata->public_key, 0, server->sha1hash,
4222                                    client->id, SILC_ID_CLIENT)) {
4223           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4224                                                 SILC_STATUS_ERR_AUTH_FAILED,
4225                                                 0);
4226           goto out;
4227         }
4228
4229         /* Save the public key */
4230         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4231         if (!channel->founder_key) {
4232           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4233                                                 SILC_STATUS_ERR_AUTH_FAILED,
4234                                                 0);
4235           goto out;
4236         }
4237
4238         founder_key = channel->founder_key;
4239         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4240         if (!fkey) {
4241           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4242                                                 SILC_STATUS_ERR_AUTH_FAILED,
4243                                                 0);
4244           goto out;
4245         }
4246       }
4247     }
4248   } else {
4249     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4250       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4251         if (channel->founder_key)
4252           silc_pkcs_public_key_free(channel->founder_key);
4253         channel->founder_key = NULL;
4254       }
4255     }
4256   }
4257
4258   /* Finally, set the mode */
4259   channel->mode = mode_mask;
4260
4261   /* Send CMODE_CHANGE notify. */
4262   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4263   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4264                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4265                                      cidp->data, cidp->len, 
4266                                      tmp_mask, 4,
4267                                      cipher, cipher ? strlen(cipher) : 0,
4268                                      hmac, hmac ? strlen(hmac) : 0,
4269                                      passphrase, passphrase ? 
4270                                      strlen(passphrase) : 0,
4271                                      fkey, fkey_len);
4272
4273   /* Set CMODE notify type to network */
4274   if (!server->standalone)
4275     silc_server_send_notify_cmode(server, server->router->connection,
4276                                   server->server_type == SILC_ROUTER ? 
4277                                   TRUE : FALSE, channel,
4278                                   mode_mask, client->id, SILC_ID_CLIENT,
4279                                   cipher, hmac, passphrase, founder_key);
4280
4281   /* Send command reply to sender */
4282   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4283                                                 SILC_STATUS_OK, 0, ident, 2,
4284                                                 2, tmp_id, tmp_len2,
4285                                                 3, tmp_mask, 4);
4286   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4287                           packet->data, packet->len, FALSE);
4288     
4289   silc_buffer_free(packet);
4290   silc_buffer_free(cidp);
4291
4292  out:
4293   silc_free(fkey);
4294   silc_free(channel_id);
4295   silc_server_command_free(cmd);
4296 }
4297
4298 /* Server side of CUMODE command. Changes client's mode on a channel. */
4299
4300 SILC_SERVER_CMD_FUNC(cumode)
4301 {
4302   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4303   SilcServer server = cmd->server;
4304   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4305   SilcIDListData idata = (SilcIDListData)client;
4306   SilcChannelID *channel_id;
4307   SilcClientID *client_id;
4308   SilcChannelEntry channel;
4309   SilcClientEntry target_client;
4310   SilcChannelClientEntry chl;
4311   SilcBuffer packet, idp;
4312   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4313   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4314   int notify = FALSE;
4315   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4316   SilcPublicKey founder_key = NULL;
4317   unsigned char *fkey = NULL;
4318   SilcUInt32 fkey_len = 0;
4319
4320   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4321
4322   /* Get Channel ID */
4323   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4324   if (!tmp_ch_id) {
4325     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4326                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4327     goto out;
4328   }
4329   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4330   if (!channel_id) {
4331     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4332                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4333     goto out;
4334   }
4335
4336   /* Get channel entry */
4337   channel = silc_idlist_find_channel_by_id(server->local_list, 
4338                                            channel_id, NULL);
4339   if (!channel) {
4340     channel = silc_idlist_find_channel_by_id(server->global_list, 
4341                                              channel_id, NULL);
4342     if (!channel) {
4343       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4344                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4345                                             0);
4346       goto out;
4347     }
4348   }
4349
4350   /* Check whether sender is on the channel */
4351   if (!silc_server_client_on_channel(client, channel, &chl)) {
4352     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4353                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4354     goto out;
4355   }
4356   sender_mask = chl->mode;
4357   
4358   /* Get the target client's channel mode mask */
4359   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4360   if (!tmp_mask) {
4361     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4362                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4363                                           0);
4364     goto out;
4365   }
4366   SILC_GET32_MSB(target_mask, tmp_mask);
4367
4368   /* Get target Client ID */
4369   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4370   if (!tmp_id) {
4371     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4373     goto out;
4374   }
4375   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4376   if (!client_id) {
4377     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4378                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4379     goto out;
4380   }
4381
4382   /* Get target client's entry */
4383   target_client = silc_idlist_find_client_by_id(server->local_list, 
4384                                                 client_id, TRUE, NULL);
4385   if (!target_client) {
4386     target_client = silc_idlist_find_client_by_id(server->global_list, 
4387                                                   client_id, TRUE, NULL);
4388   }
4389
4390   if (target_client != client &&
4391       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4392       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4393     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4395     goto out;
4396   }
4397
4398   /* Check whether target client is on the channel */
4399   if (target_client != client) {
4400     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4401       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4402                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4403       goto out;
4404     }
4405   }
4406
4407   /* 
4408    * Change the mode 
4409    */
4410
4411   /* If the target client is founder, no one else can change their mode
4412      but themselves. */
4413   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4414     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4415                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4416                                           0);
4417     goto out;
4418   }
4419
4420   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4421     if (target_client != client) {
4422       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4423                                             SILC_STATUS_ERR_NOT_YOU, 0);
4424       goto out;
4425     }
4426
4427     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4428       /* The client tries to claim the founder rights. */
4429       unsigned char *tmp_auth;
4430       SilcUInt32 tmp_auth_len;
4431       SilcChannelClientEntry chl2;
4432       SilcHashTableList htl;
4433
4434       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4435           !channel->founder_key || !idata->public_key ||
4436           !silc_pkcs_public_key_compare(channel->founder_key, 
4437                                         idata->public_key)) {
4438         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4439                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4440         goto out;
4441       }
4442
4443       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4444       if (!tmp_auth) {
4445         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4446                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4447         goto out;
4448       }
4449
4450       /* Verify the authentication payload */
4451       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4452                                  channel->founder_key, 0, server->sha1hash,
4453                                  client->id, SILC_ID_CLIENT)) {
4454         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4455                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4456         goto out;
4457       }
4458
4459       notify = TRUE;
4460       founder_key = channel->founder_key;
4461       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4462       if (!fkey) {
4463         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4464                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4465         goto out;
4466       }
4467
4468       /* There cannot be anyone else as founder on the channel now.  This
4469          client is definitely the founder due to this authentication */
4470       silc_hash_table_list(channel->user_list, &htl);
4471       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4472         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4473           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4474           silc_server_force_cumode_change(server, NULL, channel, chl2,
4475                                           chl2->mode);
4476           break;
4477         }
4478       silc_hash_table_list_reset(&htl);
4479
4480       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4481     }
4482   } else {
4483     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4484       if (target_client == client) {
4485         /* Remove channel founder rights from itself */
4486         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4487         notify = TRUE;
4488       } else {
4489         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4490                                               SILC_STATUS_ERR_NOT_YOU, 0);
4491         goto out;
4492       }
4493     }
4494   }
4495
4496   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4497     /* Promote to operator */
4498     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4499       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) && 
4500           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4501         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4502                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4503                                               0);
4504         goto out;
4505       }
4506
4507       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4508       notify = TRUE;
4509     }
4510   } else {
4511     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4512       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4513           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4514         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,   
4515                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4516                                               0);
4517         goto out;
4518       }
4519       
4520       /* Demote to normal user */
4521       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4522       notify = TRUE;
4523     }
4524   }
4525
4526   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4527     if (target_client != client) {
4528       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4529                                             SILC_STATUS_ERR_NOT_YOU, 0);
4530       goto out;
4531     }
4532
4533     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4534       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4535       notify = TRUE;
4536     }
4537   } else {
4538     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4539       if (target_client != client) {
4540         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4541                                               SILC_STATUS_ERR_NOT_YOU, 0);
4542         goto out;
4543       }
4544
4545       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4546       notify = TRUE;
4547     }
4548   }
4549
4550   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4551     if (target_client != client) {
4552       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4553                                             SILC_STATUS_ERR_NOT_YOU, 0);
4554       goto out;
4555     }
4556
4557     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4558       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4559       notify = TRUE;
4560     }
4561   } else {
4562     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4563       if (target_client != client) {
4564         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4565                                               SILC_STATUS_ERR_NOT_YOU, 0);
4566         goto out;
4567       }
4568
4569       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4570       notify = TRUE;
4571     }
4572   }
4573
4574   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4575     if (target_client != client) {
4576       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4577                                             SILC_STATUS_ERR_NOT_YOU, 0);
4578       goto out;
4579     }
4580
4581     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4582       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4583       notify = TRUE;
4584     }
4585   } else {
4586     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4587       if (target_client != client) {
4588         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4589                                               SILC_STATUS_ERR_NOT_YOU, 0);
4590         goto out;
4591       }
4592
4593       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4594       notify = TRUE;
4595     }
4596   }
4597
4598   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4599     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4600       if (client == target_client) {
4601         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4602                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4603         goto out;
4604       }
4605       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4606       notify = TRUE;
4607     }
4608   } else {
4609     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4610       if (client == target_client) {
4611         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4612                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4613         goto out;
4614       }
4615       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4616       notify = TRUE;
4617     }
4618   }
4619
4620   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4621   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4622
4623   /* Send notify to channel, notify only if mode was actually changed. */
4624   if (notify) {
4625     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4626                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4627                                        idp->data, idp->len,
4628                                        tmp_mask, 4, 
4629                                        tmp_id, tmp_len,
4630                                        fkey, fkey_len);
4631
4632     /* Set CUMODE notify type to network */
4633     if (!server->standalone)
4634       silc_server_send_notify_cumode(server, server->router->connection,
4635                                      server->server_type == SILC_ROUTER ? 
4636                                      TRUE : FALSE, channel,
4637                                      target_mask, client->id, 
4638                                      SILC_ID_CLIENT,
4639                                      target_client->id, founder_key);
4640   }
4641
4642   /* Send command reply to sender */
4643   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4644                                                 SILC_STATUS_OK, 0, ident, 3,
4645                                                 2, tmp_mask, 4,
4646                                                 3, tmp_ch_id, tmp_ch_len,
4647                                                 4, tmp_id, tmp_len);
4648   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4649                           packet->data, packet->len, FALSE);
4650     
4651   silc_buffer_free(packet);
4652   silc_free(channel_id);
4653   silc_free(client_id);
4654   silc_buffer_free(idp);
4655
4656  out:
4657   silc_free(fkey);
4658   silc_server_command_free(cmd);
4659 }
4660
4661 /* Server side of KICK command. Kicks client out of channel. */
4662
4663 SILC_SERVER_CMD_FUNC(kick)
4664 {
4665   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4666   SilcServer server = cmd->server;
4667   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4668   SilcClientEntry target_client;
4669   SilcChannelID *channel_id;
4670   SilcClientID *client_id;
4671   SilcChannelEntry channel;
4672   SilcChannelClientEntry chl;
4673   SilcBuffer idp;
4674   SilcUInt32 tmp_len, target_idp_len;
4675   unsigned char *tmp, *comment, *target_idp;
4676
4677   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4678
4679   /* Get Channel ID */
4680   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4681   if (!tmp) {
4682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4683                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4684     goto out;
4685   }
4686   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4687   if (!channel_id) {
4688     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4689                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4690     goto out;
4691   }
4692
4693   /* Get channel entry */
4694   channel = silc_idlist_find_channel_by_id(server->local_list, 
4695                                            channel_id, NULL);
4696   if (!channel) {
4697     channel = silc_idlist_find_channel_by_id(server->local_list, 
4698                                              channel_id, NULL);
4699     if (!channel) {
4700       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4701                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4702                                             0);
4703       goto out;
4704     }
4705   }
4706
4707   /* Check whether sender is on the channel */
4708   if (!silc_server_client_on_channel(client, channel, &chl)) {
4709     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4710                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4711     goto out;
4712   }
4713
4714   /* Check that the kicker is channel operator or channel founder */
4715   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4716       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4717     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4718                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4719     goto out;
4720   }
4721   
4722   /* Get target Client ID */
4723   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4724   if (!target_idp) {
4725     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4726                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4727     goto out;
4728   }
4729   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4730   if (!client_id) {
4731     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4732                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4733     goto out;
4734   }
4735
4736   /* Get target client's entry */
4737   target_client = silc_idlist_find_client_by_id(server->local_list, 
4738                                                 client_id, TRUE, NULL);
4739   if (!target_client) {
4740     target_client = silc_idlist_find_client_by_id(server->global_list, 
4741                                                   client_id, TRUE, NULL);
4742   }
4743
4744   /* Check whether target client is on the channel */
4745   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4746     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4747                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4748                                           0);
4749     goto out;
4750   }
4751
4752   /* Check that the target client is not channel founder. Channel founder
4753      cannot be kicked from the channel. */
4754   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4755     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4756                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4757                                           0);
4758     goto out;
4759   }
4760   
4761   /* Get comment */
4762   tmp_len = 0;
4763   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4764   if (tmp_len > 128)
4765     comment = NULL;
4766
4767   /* Send command reply to sender */
4768   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4769                                         SILC_STATUS_OK, 0);
4770
4771   /* Send KICKED notify to local clients on the channel */
4772   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4773   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4774                                      SILC_NOTIFY_TYPE_KICKED, 3,
4775                                      target_idp, target_idp_len,
4776                                      comment, comment ? strlen(comment) : 0,
4777                                      idp->data, idp->len);
4778   silc_buffer_free(idp);
4779
4780   /* Remove the client from the channel. If the channel does not exist
4781      after removing the client then the client kicked itself off the channel
4782      and we don't have to send anything after that. */
4783   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4784                                            target_client, FALSE))
4785     goto out;
4786
4787   /* Send KICKED notify to primary route */
4788   if (!server->standalone)
4789     silc_server_send_notify_kicked(server, server->router->connection,
4790                                    server->server_type == SILC_ROUTER ?
4791                                    TRUE : FALSE, channel,
4792                                    target_client->id, client->id, comment);
4793
4794   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4795     /* Re-generate channel key */
4796     if (!silc_server_create_channel_key(server, channel, 0))
4797       goto out;
4798     
4799     /* Send the channel key to the channel. The key of course is not sent
4800        to the client who was kicked off the channel. */
4801     silc_server_send_channel_key(server, target_client->connection, channel, 
4802                                  server->server_type == SILC_ROUTER ? 
4803                                  FALSE : !server->standalone);
4804   }
4805
4806  out:
4807   silc_server_command_free(cmd);
4808 }
4809
4810 /* Server side of OPER command. Client uses this comand to obtain server
4811    operator privileges to this server/router. */
4812
4813 SILC_SERVER_CMD_FUNC(oper)
4814 {
4815   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4816   SilcServer server = cmd->server;
4817   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4818   unsigned char *username, *auth;
4819   SilcUInt32 tmp_len;
4820   SilcServerConfigAdmin *admin;
4821   SilcIDListData idata = (SilcIDListData)client;
4822   bool result = FALSE;
4823   SilcPublicKey cached_key;
4824
4825   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4826
4827   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4828     goto out;
4829
4830   /* Get the username */
4831   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4832   if (!username) {
4833     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4834                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4835                                           0);
4836     goto out;
4837   }
4838
4839   /* Get the admin configuration */
4840   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4841                                         username, client->nickname);
4842   if (!admin) {
4843     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4844                                           username, client->nickname);
4845     if (!admin) {
4846       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4847                                             SILC_STATUS_ERR_AUTH_FAILED,
4848                                             0);
4849       goto out;
4850     }
4851   }
4852
4853   /* Get the authentication payload */
4854   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4855   if (!auth) {
4856     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4857                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4858                                           0);
4859     goto out;
4860   }
4861
4862   /* Verify the authentication data. If both passphrase and public key
4863      is set then try both of them. */
4864   if (admin->passphrase)
4865     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4866                                    admin->passphrase, admin->passphrase_len,
4867                                    idata->hash, client->id, SILC_ID_CLIENT);
4868   if (!result && admin->publickeys) {
4869     cached_key = silc_server_get_public_key(server, admin->publickeys);
4870     if (!cached_key)
4871       goto out;
4872     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4873                                    cached_key, 0, idata->hash, 
4874                                    client->id, SILC_ID_CLIENT);
4875   }
4876   if (!result) {
4877     /* Authentication failed */
4878     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4879                                           SILC_STATUS_ERR_AUTH_FAILED,
4880                                           0);
4881     goto out;
4882   }
4883
4884   /* Client is now server operator */
4885   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4886
4887   /* Update statistics */
4888   if (client->connection)
4889     server->stat.my_server_ops++;
4890   if (server->server_type == SILC_ROUTER)
4891     server->stat.server_ops++;
4892
4893   /* Send UMODE change to primary router */
4894   if (!server->standalone)
4895     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4896                                   client->id, client->mode);
4897
4898   /* Check if anyone is watching this nickname */
4899   if (server->server_type == SILC_ROUTER)
4900     silc_server_check_watcher_list(server, client, NULL,
4901                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4902
4903   /* Send reply to the sender */
4904   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4905                                         SILC_STATUS_OK, 0);
4906
4907  out:
4908   silc_server_command_free(cmd);
4909 }
4910
4911 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4912 {
4913   QuitInternal q = (QuitInternal)context;
4914   SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4915
4916   /* If there is pending outgoing data for the client then purge it
4917      to the network before closing connection. */
4918   silc_server_packet_queue_purge(q->server, q->sock);
4919
4920   /* Close the connection on our side */
4921   client->router = NULL;
4922   client->connection = NULL;
4923   q->sock->user_data = NULL;
4924   silc_server_close_connection(q->server, q->sock);
4925
4926   silc_free(q);
4927 }
4928
4929 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4930 {
4931   QuitInternal q = (QuitInternal)context;
4932   SilcClientID *client_id = (SilcClientID *)q->sock;
4933   SilcClientEntry client;
4934
4935   SILC_LOG_DEBUG(("Start"));
4936
4937   client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4938                                          FALSE, NULL);
4939
4940   if (client && client->mode & SILC_UMODE_DETACHED)
4941     silc_server_free_client_data(q->server, NULL, client, TRUE,
4942                                  "Detach timeout");
4943
4944   silc_free(client_id);
4945   silc_free(q);
4946 }
4947
4948 /* Server side of DETACH command.  Detached the client from the network
4949    by closing the connection but preserving the session. */
4950
4951 SILC_SERVER_CMD_FUNC(detach)
4952 {
4953   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4954   SilcServer server = cmd->server;
4955   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4956   QuitInternal q;
4957
4958   if (server->config->detach_disabled) {
4959     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4960                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
4961     goto out;
4962   }
4963
4964   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4965     goto out;
4966
4967   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4968
4969   /* Send the user mode notify to notify that client is detached */
4970   client->mode |= SILC_UMODE_DETACHED;
4971   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4972   client->last_command = 0;
4973   client->fast_command = 0;
4974   if (!server->standalone)
4975     silc_server_send_notify_umode(server, server->router->connection,
4976                                   server->server_type == SILC_SERVER ?
4977                                   FALSE : TRUE, client->id, client->mode);
4978   server->stat.my_detached++;
4979
4980   /* Check if anyone is watching this nickname */
4981   if (server->server_type == SILC_ROUTER)
4982     silc_server_check_watcher_list(server, client, NULL,
4983                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4984
4985   q = silc_calloc(1, sizeof(*q));
4986   q->server = server;
4987   q->sock = cmd->sock;
4988   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4989                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4990
4991   if (server->config->detach_timeout) {
4992     q = silc_calloc(1, sizeof(*q));
4993     q->server = server;
4994     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
4995     silc_schedule_task_add(server->schedule, 0, 
4996                            silc_server_command_detach_timeout,
4997                            q, server->config->detach_timeout * 60,
4998                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4999   }
5000
5001   /* Send reply to the sender */
5002   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5003                                         SILC_STATUS_OK, 0);
5004
5005  out:
5006   silc_server_command_free(cmd);
5007 }
5008
5009 /* Server side of WATCH command. */
5010
5011 SILC_SERVER_CMD_FUNC(watch)
5012 {
5013   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5014   SilcServer server = cmd->server;
5015   char *add_nick, *del_nick;
5016   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5017   char nick[128 + 1];
5018   unsigned char hash[16], *tmp;
5019   SilcClientEntry client;
5020   SilcClientID *client_id = NULL;
5021
5022   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5023
5024   if (server->server_type == SILC_SERVER && !server->standalone) {
5025     if (!cmd->pending) {
5026       /* Send the command to router */
5027       SilcBuffer tmpbuf;
5028       SilcUInt16 old_ident;
5029
5030       old_ident = silc_command_get_ident(cmd->payload);
5031       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5032       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5033
5034       silc_server_packet_send(server, server->router->connection,
5035                               SILC_PACKET_COMMAND, cmd->packet->flags,
5036                               tmpbuf->data, tmpbuf->len, TRUE);
5037
5038       /* Reprocess this packet after received reply from router */
5039       silc_server_command_pending(server, SILC_COMMAND_WATCH,
5040                                   silc_command_get_ident(cmd->payload),
5041                                   silc_server_command_watch,
5042                                   silc_server_command_dup(cmd));
5043       cmd->pending = TRUE;
5044       silc_command_set_ident(cmd->payload, old_ident);
5045       silc_buffer_free(tmpbuf);
5046     } else if (context2) {
5047       /* Received reply from router, just send same data to the client. */
5048       SilcServerCommandReplyContext reply = context2;
5049       SilcStatus status;
5050       silc_command_get_status(reply->payload, &status, NULL);
5051       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5052                                             0);
5053     }
5054
5055     goto out;
5056   }
5057
5058   /* We are router and keep the watch list for local cell */
5059
5060   /* Get the client ID */
5061   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5062   if (!tmp) {
5063     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5064                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5065                                           0);
5066     goto out;
5067   }
5068   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5069   if (!client_id) {
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   /* Get the client entry which must be in local list */
5077   client = silc_idlist_find_client_by_id(server->local_list, 
5078                                          client_id, TRUE, NULL);
5079   if (!client) {
5080     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5081                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5082                                           0);
5083     goto out;
5084   }
5085
5086   /* Take nickname */
5087   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5088   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5089   if (!add_nick && !del_nick) {
5090     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5091                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5092                                           0);
5093     goto out;
5094   }
5095
5096   if (add_nick && add_nick_len > 128)
5097     add_nick[128] = '\0';
5098   if (del_nick && del_nick_len > 128)
5099     del_nick[128] = '\0';
5100
5101   memset(nick, 0, sizeof(nick));
5102
5103   /* Add new nickname to be watched in our cell */
5104   if (add_nick) {
5105     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5106       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5107                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5108       goto out;
5109     }
5110
5111     /* Hash the nick, we have the hash saved, not nicks because we can
5112        do one to one mapping to the nick from Client ID hash this way. */
5113     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5114     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5115
5116     /* Check whether this client is already watching this nickname */
5117     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
5118                                         client, NULL)) {
5119       /* Nickname is alredy being watched for this client */
5120       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5121                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
5122                                             0);
5123       goto out;
5124     }
5125
5126     /* Get the nickname from the watcher list and use the same key in
5127        new entries as well.  If key doesn't exist then create it. */
5128     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5129       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5130
5131     /* Add the client to the watcher list with the specified nickname hash. */
5132     silc_hash_table_add(server->watcher_list, tmp, client);
5133   }
5134
5135   /* Delete nickname from watch list */
5136   if (del_nick) {
5137     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5138       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5139                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5140       goto out;
5141     }
5142
5143     /* Hash the nick, we have the hash saved, not nicks because we can
5144        do one to one mapping to the nick from Client ID hash this way. */
5145     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5146     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5147
5148     /* Check that this client is watching for this nickname */
5149     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
5150                                          client, (void **)&tmp)) {
5151       /* Nickname is alredy being watched for this client */
5152       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5153                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5154       goto out;
5155     }
5156
5157     /* Delete the nickname from the watcher list. */
5158     silc_hash_table_del_by_context(server->watcher_list, hash, client);
5159
5160     /* Now check whether there still exists entries with this key, if not
5161        then free the key to not leak memory. */
5162     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5163       silc_free(tmp);
5164   }
5165
5166   /* Distribute the watch list to backup routers too */
5167   if (server->backup) {
5168     SilcBuffer tmpbuf;
5169     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5170     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5171     silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5172                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5173                             FALSE, TRUE);
5174     silc_buffer_free(tmpbuf);
5175   }
5176
5177   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5178                                         SILC_STATUS_OK, 0);
5179
5180  out:
5181   silc_free(client_id);
5182   silc_server_command_free(cmd);
5183 }
5184
5185 /* Server side of SILCOPER command. Client uses this comand to obtain router
5186    operator privileges to this router. */
5187
5188 SILC_SERVER_CMD_FUNC(silcoper)
5189 {
5190   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5191   SilcServer server = cmd->server;
5192   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5193   unsigned char *username, *auth;
5194   SilcUInt32 tmp_len;
5195   SilcServerConfigAdmin *admin;
5196   SilcIDListData idata = (SilcIDListData)client;
5197   bool result = FALSE;
5198   SilcPublicKey cached_key;
5199
5200   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5201
5202   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5203     goto out;
5204
5205   if (server->server_type != SILC_ROUTER) {
5206     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5207                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5208     goto out;
5209   }
5210
5211   /* Get the username */
5212   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5213   if (!username) {
5214     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5215                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5216                                           0);
5217     goto out;
5218   }
5219
5220   /* Get the admin configuration */
5221   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5222                                         username, client->nickname);
5223   if (!admin) {
5224     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5225                                           username, client->nickname);
5226     if (!admin) {
5227       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5228                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
5229       goto out;
5230     }
5231   }
5232
5233   /* Get the authentication payload */
5234   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5235   if (!auth) {
5236     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5237                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5238                                           0);
5239     goto out;
5240   }
5241
5242   /* Verify the authentication data. If both passphrase and public key
5243      is set then try both of them. */
5244   if (admin->passphrase)
5245     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5246                                    admin->passphrase, admin->passphrase_len,
5247                                    idata->hash, client->id, SILC_ID_CLIENT);
5248   if (!result && admin->publickeys) {
5249     cached_key = silc_server_get_public_key(server, admin->publickeys);
5250     if (!cached_key)
5251       goto out;
5252     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5253                                    cached_key, 0, idata->hash, 
5254                                    client->id, SILC_ID_CLIENT);
5255   }
5256   if (!result) {
5257     /* Authentication failed */
5258     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5259                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5260     goto out;
5261   }
5262
5263   /* Client is now router operator */
5264   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5265
5266   /* Update statistics */
5267   if (client->connection)
5268     server->stat.my_router_ops++;
5269   if (server->server_type == SILC_ROUTER)
5270     server->stat.router_ops++;
5271
5272   /* Send UMODE change to primary router */
5273   if (!server->standalone)
5274     silc_server_send_notify_umode(server, server->router->connection, TRUE,
5275                                   client->id, client->mode);
5276
5277   /* Check if anyone is watching this nickname */
5278   if (server->server_type == SILC_ROUTER)
5279     silc_server_check_watcher_list(server, client, NULL,
5280                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5281
5282   /* Send reply to the sender */
5283   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5284                                         SILC_STATUS_OK, 0);
5285
5286  out:
5287   silc_server_command_free(cmd);
5288 }
5289
5290 /* Server side of command BAN. This is used to manage the ban list of the
5291    channel. To add clients and remove clients from the ban list. */
5292
5293 SILC_SERVER_CMD_FUNC(ban)
5294 {
5295   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5296   SilcServer server = cmd->server;
5297   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5298   SilcBuffer packet;
5299   SilcChannelEntry channel;
5300   SilcChannelClientEntry chl;
5301   SilcChannelID *channel_id = NULL;
5302   unsigned char *id, *add, *del;
5303   SilcUInt32 id_len, tmp_len;
5304   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5305
5306   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5307     goto out;
5308
5309   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5310
5311   /* Get Channel ID */
5312   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5313   if (id) {
5314     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5315     if (!channel_id) {
5316       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5317                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5318       goto out;
5319     }
5320   }
5321
5322   /* Get channel entry. The server must know about the channel since the
5323      client is expected to be on the channel. */
5324   channel = silc_idlist_find_channel_by_id(server->local_list, 
5325                                            channel_id, NULL);
5326   if (!channel) {
5327     channel = silc_idlist_find_channel_by_id(server->global_list, 
5328                                              channel_id, NULL);
5329     if (!channel) {
5330       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5331                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5332                                             0);
5333       goto out;
5334     }
5335   }
5336
5337   /* Check whether this client is on the channel */
5338   if (!silc_server_client_on_channel(client, channel, &chl)) {
5339     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5340                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5341     goto out;
5342   }
5343
5344   /* The client must be at least channel operator. */
5345   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5346     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5347                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5348     goto out;
5349   }
5350
5351   /* Get the new ban and add it to the ban list */
5352   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5353   if (add) {
5354     if (!channel->ban_list)
5355       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5356     else
5357       channel->ban_list = silc_realloc(channel->ban_list, 
5358                                        sizeof(*channel->ban_list) * 
5359                                        (tmp_len + 
5360                                         strlen(channel->ban_list) + 2));
5361     if (add[tmp_len - 1] == ',')
5362       add[tmp_len - 1] = '\0';
5363
5364     strncat(channel->ban_list, add, tmp_len);
5365     strncat(channel->ban_list, ",", 1);
5366   }
5367
5368   /* Get the ban to be removed and remove it from the list */
5369   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5370   if (del && channel->ban_list) {
5371     char *start, *end, *n;
5372
5373     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5374       silc_free(channel->ban_list);
5375       channel->ban_list = NULL;
5376     } else {
5377       start = strstr(channel->ban_list, del);
5378       if (start && strlen(start) >= tmp_len) {
5379         end = start + tmp_len;
5380         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5381         strncat(n, channel->ban_list, start - channel->ban_list);
5382         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
5383                              end) - 1);
5384         silc_free(channel->ban_list);
5385         channel->ban_list = n;
5386       }
5387     }
5388   }
5389
5390   /* Send the BAN notify type to our primary router. */
5391   if (!server->standalone && (add || del))
5392     silc_server_send_notify_ban(server, server->router->connection,
5393                                 server->server_type == SILC_ROUTER ?
5394                                 TRUE : FALSE, channel, add, del);
5395
5396   /* Send the reply back to the client */
5397   packet = 
5398     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5399                                          SILC_STATUS_OK, 0, ident, 2,
5400                                          2, id, id_len,
5401                                          3, channel->ban_list, 
5402                                          channel->ban_list ? 
5403                                          strlen(channel->ban_list) -1 : 0);
5404   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5405                           packet->data, packet->len, FALSE);
5406     
5407   silc_buffer_free(packet);
5408
5409  out:
5410   silc_free(channel_id);
5411   silc_server_command_free(cmd);
5412 }
5413
5414 /* Server side command of LEAVE. Removes client from a channel. */
5415
5416 SILC_SERVER_CMD_FUNC(leave)
5417 {
5418   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5419   SilcServer server = cmd->server;
5420   SilcSocketConnection sock = cmd->sock;
5421   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5422   SilcChannelID *id = NULL;
5423   SilcChannelEntry channel;
5424   SilcUInt32 len;
5425   unsigned char *tmp;
5426
5427   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5428
5429   /* Get Channel ID */
5430   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5431   if (!tmp) {
5432     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5433                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5434     goto out;
5435   }
5436   id = silc_id_payload_parse_id(tmp, len, NULL);
5437   if (!id) {
5438     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5439                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5440     goto out;
5441   }
5442
5443   /* Get channel entry */
5444   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5445   if (!channel) {
5446     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5447     if (!channel) {
5448       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5449                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5450                                             0);
5451       goto out;
5452     }
5453   }
5454
5455   /* Check whether this client is on the channel */
5456   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5457     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5458                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5459     goto out;
5460   }
5461
5462   /* Notify routers that they should remove this client from their list
5463      of clients on the channel. Send LEAVE notify type. */
5464   if (!server->standalone)
5465     silc_server_send_notify_leave(server, server->router->connection,
5466                                   server->server_type == SILC_ROUTER ?
5467                                   TRUE : FALSE, channel, id_entry->id);
5468
5469   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5470                                        SILC_STATUS_OK, 0, 2, tmp, len);
5471
5472   /* Remove client from channel */
5473   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5474                                            TRUE))
5475     /* If the channel does not exist anymore we won't send anything */
5476     goto out;
5477
5478   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5479     /* Re-generate channel key */
5480     if (!silc_server_create_channel_key(server, channel, 0))
5481       goto out;
5482
5483     /* Send the channel key */
5484     silc_server_send_channel_key(server, NULL, channel, 
5485                                  server->server_type == SILC_ROUTER ? 
5486                                  FALSE : !server->standalone);
5487   }
5488
5489  out:
5490   silc_free(id);
5491   silc_server_command_free(cmd);
5492 }
5493
5494 /* Server side of command USERS. Resolves clients and their USERS currently
5495    joined on the requested channel. The list of Client ID's and their modes
5496    on the channel is sent back. */
5497
5498 SILC_SERVER_CMD_FUNC(users)
5499 {
5500   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5501   SilcServer server = cmd->server;
5502   SilcChannelEntry channel;
5503   SilcChannelID *id = NULL;
5504   SilcBuffer packet, idp;
5505   unsigned char *channel_id;
5506   SilcUInt32 channel_id_len;
5507   SilcBuffer client_id_list;
5508   SilcBuffer client_mode_list;
5509   unsigned char lc[4];
5510   SilcUInt32 list_count = 0;
5511   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5512   char *channel_name;
5513
5514   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5515
5516   /* Get Channel ID */
5517   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5518
5519   /* Get channel name */
5520   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5521
5522   if (!channel_id && !channel_name) {
5523     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5524                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5525     goto out;
5526   }
5527
5528   if (channel_id) {
5529     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5530     if (!id) {
5531       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5532                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5533       goto out;
5534     }
5535   }
5536
5537   /* If we are server and we don't know about this channel we will send
5538      the command to our router. If we know about the channel then we also
5539      have the list of users already. */
5540   if (id)
5541     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5542   else
5543     channel = silc_idlist_find_channel_by_name(server->local_list, 
5544                                                channel_name, NULL);
5545
5546   if (!channel || (!server->standalone && (channel->disabled || 
5547                     !channel->users_resolved))) {
5548     if (server->server_type != SILC_ROUTER && !server->standalone &&
5549         !cmd->pending) {
5550       SilcBuffer tmpbuf;
5551       
5552       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5553       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5554       
5555       /* Send USERS command */
5556       silc_server_packet_send(server, server->router->connection,
5557                               SILC_PACKET_COMMAND, cmd->packet->flags,
5558                               tmpbuf->data, tmpbuf->len, TRUE);
5559       
5560       /* Reprocess this packet after received reply */
5561       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5562                                   silc_command_get_ident(cmd->payload),
5563                                   silc_server_command_users,
5564                                   silc_server_command_dup(cmd));
5565       cmd->pending = TRUE;
5566       silc_command_set_ident(cmd->payload, ident);
5567       silc_buffer_free(tmpbuf);
5568       silc_free(id);
5569       goto out;
5570     }
5571
5572     /* Check the global list as well. */
5573     if (id)
5574       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5575     else
5576       channel = silc_idlist_find_channel_by_name(server->global_list, 
5577                                                  channel_name, NULL);
5578     if (!channel) {
5579       /* Channel really does not exist */
5580       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5581                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5582                                             0);
5583       goto out;
5584     }
5585   }
5586
5587   /* If the channel is private or secret do not send anything, unless the
5588      user requesting this command is on the channel or is server */
5589   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5590     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5591         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5592                                           NULL)) {
5593       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5594                                             SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5595       goto out;
5596     }
5597   }
5598
5599   /* Get the users list */
5600   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5601                                         &client_mode_list, &list_count)) {
5602     list_count = 0;
5603     client_id_list = NULL;
5604     client_mode_list = NULL;
5605   }
5606
5607   /* List count */
5608   SILC_PUT32_MSB(list_count, lc);
5609
5610   /* Send reply */
5611   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5612   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5613                                                 SILC_STATUS_OK, 0, ident, 4,
5614                                                 2, idp->data, idp->len,
5615                                                 3, lc, 4,
5616                                                 4, client_id_list ? 
5617                                                 client_id_list->data : NULL,
5618                                                 client_id_list ?
5619                                                 client_id_list->len : 0,
5620                                                 5, client_mode_list ?
5621                                                 client_mode_list->data : NULL,
5622                                                 client_mode_list ?
5623                                                 client_mode_list->len : 0);
5624   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5625                           packet->data, packet->len, FALSE);
5626     
5627   silc_buffer_free(idp);
5628   silc_buffer_free(packet);
5629   if (client_id_list)
5630     silc_buffer_free(client_id_list);
5631   if (client_mode_list)
5632     silc_buffer_free(client_mode_list);
5633   silc_free(id);
5634
5635  out:
5636   silc_server_command_free(cmd);
5637 }
5638
5639 /* Server side of command GETKEY. This fetches the client's public key
5640    from the server where to the client is connected. */
5641
5642 SILC_SERVER_CMD_FUNC(getkey)
5643 {
5644   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5645   SilcServer server = cmd->server;
5646   SilcBuffer packet;
5647   SilcClientEntry client;
5648   SilcServerEntry server_entry;
5649   SilcClientID *client_id = NULL;
5650   SilcServerID *server_id = NULL;
5651   SilcIDPayload idp = NULL;
5652   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5653   unsigned char *tmp, *pkdata;
5654   SilcUInt32 tmp_len, pklen;
5655   SilcBuffer pk = NULL;
5656   SilcIdType id_type;
5657   SilcPublicKey public_key;
5658
5659   SILC_LOG_DEBUG(("Start"));
5660
5661   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5662   if (!tmp) {
5663     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5664                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5665                                           0);
5666     goto out;
5667   }
5668   idp = silc_id_payload_parse(tmp, tmp_len);
5669   if (!idp) {
5670     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5671                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5672                                           0);
5673     goto out;
5674   }
5675
5676   id_type = silc_id_payload_get_type(idp);
5677   if (id_type == SILC_ID_CLIENT) {
5678     client_id = silc_id_payload_get_id(idp);
5679
5680     /* If the client is not found from local list there is no chance it
5681        would be locally connected client so send the command further. */
5682     client = silc_idlist_find_client_by_id(server->local_list, 
5683                                            client_id, TRUE, NULL);
5684     if (!client)
5685       client = silc_idlist_find_client_by_id(server->global_list, 
5686                                              client_id, TRUE, NULL);
5687     
5688     if ((!client && !cmd->pending && !server->standalone) ||
5689         (client && !client->connection && !cmd->pending &&
5690          !(client->mode & SILC_UMODE_DETACHED)) ||
5691         (client && !client->data.public_key && !cmd->pending)) {
5692       SilcBuffer tmpbuf;
5693       SilcUInt16 old_ident;
5694       SilcSocketConnection dest_sock;
5695       
5696       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5697                                                client_id, NULL, NULL);
5698       if (!dest_sock)
5699         goto out;
5700       
5701       old_ident = silc_command_get_ident(cmd->payload);
5702       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5703       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5704       
5705       silc_server_packet_send(server, dest_sock,
5706                               SILC_PACKET_COMMAND, cmd->packet->flags,
5707                               tmpbuf->data, tmpbuf->len, TRUE);
5708       
5709       /* Reprocess this packet after received reply from router */
5710       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5711                                   silc_command_get_ident(cmd->payload),
5712                                   silc_server_command_getkey,
5713                                   silc_server_command_dup(cmd));
5714       cmd->pending = TRUE;
5715       silc_command_set_ident(cmd->payload, old_ident);
5716       silc_buffer_free(tmpbuf);
5717       goto out;
5718     }
5719
5720     if (!client) {
5721       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5722                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5723                                             0);
5724       goto out;
5725     }
5726
5727     /* The client is locally connected, just get the public key and
5728        send it back. If they key does not exist then do not send it, 
5729        send just OK reply */
5730     public_key = client->data.public_key;
5731     if (!public_key) {
5732       pkdata = NULL;
5733       pklen = 0;
5734     } else {
5735       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5736       pk = silc_buffer_alloc(4 + tmp_len);
5737       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5738       silc_buffer_format(pk,
5739                          SILC_STR_UI_SHORT(tmp_len),
5740                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5741                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5742                          SILC_STR_END);
5743       silc_free(tmp);
5744       pkdata = pk->data;
5745       pklen = pk->len;
5746     }
5747   } else if (id_type == SILC_ID_SERVER) {
5748     server_id = silc_id_payload_get_id(idp);
5749
5750     /* If the server is not found from local list there is no chance it
5751        would be locally connected server so send the command further. */
5752     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5753                                                  server_id, TRUE, NULL);
5754     if (!server_entry)
5755       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5756                                                    server_id, TRUE, NULL);
5757     
5758     if (server_entry != server->id_entry &&
5759         ((!server_entry && !cmd->pending && !server->standalone) ||
5760          (server_entry && !server_entry->connection && !cmd->pending &&
5761           !server->standalone) ||
5762          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5763           !server->standalone))) {
5764       SilcBuffer tmpbuf;
5765       SilcUInt16 old_ident;
5766       
5767       old_ident = silc_command_get_ident(cmd->payload);
5768       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5769       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5770       
5771       silc_server_packet_send(server, server->router->connection,
5772                               SILC_PACKET_COMMAND, cmd->packet->flags,
5773                               tmpbuf->data, tmpbuf->len, TRUE);
5774       
5775       /* Reprocess this packet after received reply from router */
5776       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5777                                   silc_command_get_ident(cmd->payload),
5778                                   silc_server_command_getkey,
5779                                   silc_server_command_dup(cmd));
5780       cmd->pending = TRUE;
5781       silc_command_set_ident(cmd->payload, old_ident);
5782       silc_buffer_free(tmpbuf);
5783       goto out;
5784     }
5785
5786     if (!server_entry) {
5787       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5788                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5789                                             0);
5790       goto out;
5791     }
5792
5793     /* If they key does not exist then do not send it, send just OK reply */
5794     public_key = (!server_entry->data.public_key ? 
5795                   (server_entry == server->id_entry ? server->public_key :
5796                    NULL) : server_entry->data.public_key);
5797     if (!public_key) {
5798       pkdata = NULL;
5799       pklen = 0;
5800     } else {
5801       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5802       pk = silc_buffer_alloc(4 + tmp_len);
5803       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5804       silc_buffer_format(pk,
5805                          SILC_STR_UI_SHORT(tmp_len),
5806                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5807                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5808                          SILC_STR_END);
5809       silc_free(tmp);
5810       pkdata = pk->data;
5811       pklen = pk->len;
5812     }
5813   } else {
5814     goto out;
5815   }
5816
5817   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5818   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5819                                                 SILC_STATUS_OK, 0, ident, 
5820                                                 pkdata ? 2 : 1,
5821                                                 2, tmp, tmp_len,
5822                                                 3, pkdata, pklen);
5823   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5824                           packet->data, packet->len, FALSE);
5825   silc_buffer_free(packet);
5826
5827   if (pk)
5828     silc_buffer_free(pk);
5829
5830  out:
5831   if (idp)
5832     silc_id_payload_free(idp);
5833   silc_free(client_id);
5834   silc_free(server_id);
5835   silc_server_command_free(cmd);
5836 }
5837
5838
5839 /* Private range commands, specific to this implementation */
5840
5841 /* Server side command of CONNECT. Connects us to the specified remote
5842    server or router. */
5843
5844 SILC_SERVER_CMD_FUNC(connect)
5845 {
5846   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5847   SilcServer server = cmd->server;
5848   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5849   unsigned char *tmp, *host;
5850   SilcUInt32 tmp_len;
5851   SilcUInt32 port = SILC_PORT;
5852
5853   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5854
5855   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5856     goto out;
5857
5858   /* Check whether client has the permissions. */
5859   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5860       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5861     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5862                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5863     goto out;
5864   }
5865
5866   if (server->server_type == SILC_ROUTER && 
5867       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5868     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5869                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5870     goto out;
5871   }
5872
5873   /* Get the remote server */
5874   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5875   if (!host) {
5876     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5877                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5878                                           0);
5879     goto out;
5880   }
5881
5882   /* Get port */
5883   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5884   if (tmp)
5885     SILC_GET32_MSB(port, tmp);
5886
5887   /* Create the connection. It is done with timeout and is async. */
5888   silc_server_create_connection(server, host, port);
5889
5890   /* Send reply to the sender */
5891   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5892                                         SILC_STATUS_OK, 0);
5893
5894  out:
5895   silc_server_command_free(cmd);
5896 }
5897
5898 /* Server side command of CLOSE. Closes connection to a specified server. */
5899  
5900 SILC_SERVER_CMD_FUNC(close)
5901 {
5902   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5903   SilcServer server = cmd->server;
5904   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5905   SilcServerEntry server_entry;
5906   SilcSocketConnection sock;
5907   unsigned char *tmp;
5908   SilcUInt32 tmp_len;
5909   unsigned char *name;
5910   SilcUInt32 port = SILC_PORT;
5911
5912   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5913
5914   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5915     goto out;
5916
5917   /* Check whether client has the permissions. */
5918   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5919       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5920     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5921                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5922                                           0);
5923     goto out;
5924   }
5925
5926   /* Get the remote server */
5927   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5928   if (!name) {
5929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5930                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5931                                           0);
5932     goto out;
5933   }
5934
5935   /* Get port */
5936   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5937   if (tmp)
5938     SILC_GET32_MSB(port, tmp);
5939
5940   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5941                                                  name, port, FALSE, NULL);
5942   if (!server_entry)
5943     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5944                                                    name, port, FALSE, NULL);
5945   if (!server_entry) {
5946     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5947                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5948     goto out;
5949   }
5950
5951   /* Send reply to the sender */
5952   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5953                                         SILC_STATUS_OK, 0);
5954
5955   /* Close the connection to the server */
5956   sock = (SilcSocketConnection)server_entry->connection;
5957
5958   /* If we shutdown primary router connection manually then don't trigger
5959      any reconnect or backup router connections, by setting the router
5960      to NULL here. */
5961   if (server->router == server_entry) {
5962     server->id_entry->router = NULL;
5963     server->router = NULL;
5964     server->standalone = TRUE;
5965   }
5966   silc_server_free_sock_user_data(server, sock, NULL);
5967   silc_server_close_connection(server, sock);
5968   
5969  out:
5970   silc_server_command_free(cmd);
5971 }
5972
5973 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5974    active connections. */
5975  
5976 SILC_SERVER_CMD_FUNC(shutdown)
5977 {
5978   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5979   SilcServer server = cmd->server;
5980   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5981
5982   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5983
5984   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5985     goto out;
5986
5987   /* Check whether client has the permission. */
5988   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5989       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5990     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5991                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5992                                           0);
5993     goto out;
5994   }
5995
5996   /* Send reply to the sender */
5997   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5998                                         SILC_STATUS_OK, 0);
5999
6000   /* Then, gracefully, or not, bring the server down. */
6001   silc_server_stop(server);
6002   exit(0);
6003
6004  out:
6005   silc_server_command_free(cmd);
6006 }