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