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