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