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