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