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