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