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