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