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     packet = 
798       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
799                                            status, 0, ident, 8, 
800                                            2, idp->data, idp->len,
801                                            3, nh, strlen(nh),
802                                            4, uh, strlen(uh),
803                                            5, entry->userinfo, 
804                                            strlen(entry->userinfo),
805                                            6, channels ? channels->data : NULL,
806                                            channels ? channels->len : 0,
807                                            7, mode, 4,
808                                            8, idle, 4,
809                                            9, fingerprint,
810                                            fingerprint ? 20 : 0);
811
812     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
813                             0, packet->data, packet->len, FALSE);
814     
815     silc_buffer_free(packet);
816     silc_buffer_free(idp);
817     if (channels)
818       silc_buffer_free(channels);
819
820     k++;
821   }
822 }
823
824 static void 
825 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
826 {
827   SilcServer server = cmd->server;
828   SilcBuffer tmpbuf;
829   SilcUInt16 old_ident;
830
831   old_ident = silc_command_get_ident(cmd->payload);
832   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
833   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
834
835   /* Send WHOIS command to our router */
836   silc_server_packet_send(server, (SilcSocketConnection)
837                           server->router->connection,
838                           SILC_PACKET_COMMAND, cmd->packet->flags,
839                           tmpbuf->data, tmpbuf->len, TRUE);
840
841   /* Reprocess this packet after received reply from router */
842   silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
843                               silc_command_get_ident(cmd->payload),
844                               silc_server_command_whois,
845                               silc_server_command_dup(cmd));
846   cmd->pending = TRUE;
847   silc_command_set_ident(cmd->payload, old_ident);
848   silc_buffer_free(tmpbuf);
849 }
850
851 static int
852 silc_server_command_whois_process(SilcServerCommandContext cmd)
853 {
854   SilcServer server = cmd->server;
855   char *nick = NULL, *server_name = NULL;
856   int count = 0;
857   SilcClientEntry *clients = NULL, entry;
858   SilcClientID **client_id = NULL;
859   SilcUInt32 client_id_count = 0, clients_count = 0;
860   int i, ret = 0;
861   bool check_global = FALSE;
862
863   /* Parse the whois request */
864   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
865                                        &nick, &server_name, &count,
866                                        SILC_COMMAND_WHOIS))
867     return 0;
868
869   /* Send the WHOIS request to the router only if it included nickname.
870      Since nicknames can be expanded into many clients we need to send it
871      to router.  If the WHOIS included only client ID's we will check them
872      first locally since we just might have them. */
873   if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
874       server->server_type == SILC_SERVER && !cmd->pending &&
875       !server->standalone) {
876     silc_server_command_whois_send_router(cmd);
877     ret = -1;
878     goto out;
879   }
880
881   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
882     check_global = TRUE;
883   else if (server->server_type != SILC_SERVER)
884     check_global = TRUE;
885
886   /* Get all clients matching that ID or nickname from local list */
887   if (client_id_count) {
888     /* Check all Client ID's received in the command packet */
889     for (i = 0; i < client_id_count; i++) {
890       entry = silc_idlist_find_client_by_id(server->local_list, 
891                                             client_id[i], TRUE, NULL);
892       if (!entry && check_global)
893         entry = silc_idlist_find_client_by_id(server->global_list, 
894                                               client_id[i], TRUE, NULL);
895       if (entry) {
896         clients = silc_realloc(clients, sizeof(*clients) * 
897                                (clients_count + 1));
898         clients[clients_count++] = entry;
899       } else {
900         /* If we are normal server and did not send the request first to router
901            do it now, since we do not have the Client ID information. */
902         if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
903             server->server_type == SILC_SERVER && !cmd->pending && 
904             !server->standalone) {
905           silc_server_command_whois_send_router(cmd);
906           ret = -1;
907           goto out;
908         }
909       }
910     }
911   } else {
912     /* Find by nickname */
913     if (!silc_idlist_get_clients_by_hash(server->local_list, 
914                                          nick, server->md5hash,
915                                          &clients, &clients_count))
916       silc_idlist_get_clients_by_nickname(server->local_list, 
917                                           nick, server_name,
918                                           &clients, &clients_count);
919     if (check_global) {
920       if (!silc_idlist_get_clients_by_hash(server->global_list, 
921                                            nick, server->md5hash,
922                                            &clients, &clients_count))
923         silc_idlist_get_clients_by_nickname(server->global_list, 
924                                             nick, server_name,
925                                             &clients, &clients_count);
926     }
927   }
928   
929   if (!clients) {
930     /* If we are normal server and did not send the request first to router
931        do it now, since we do not have the information. */
932     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
933         server->server_type == SILC_SERVER && !cmd->pending && 
934         !server->standalone) {
935       silc_server_command_whois_send_router(cmd);
936       ret = -1;
937       goto out;
938     }
939
940     /* Such client(s) really does not exist in the SILC network. */
941     if (!client_id_count) {
942       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
943                                            SILC_STATUS_ERR_NO_SUCH_NICK,
944                                            3, nick, strlen(nick));
945     } else {
946       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
947       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
948                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
949                                            2, idp->data, idp->len);
950       silc_buffer_free(idp);
951     }
952     goto out;
953   }
954
955   /* Router always finds the client entry if it exists in the SILC network.
956      However, it might be incomplete entry and does not include all the
957      mandatory fields that WHOIS command reply requires. Check for these and
958      make query from the server who owns the client if some fields are 
959      missing. */
960   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
961     ret = -1;
962     goto out;
963   }
964
965   /* Send the command reply */
966   silc_server_command_whois_send_reply(cmd, clients, clients_count,
967                                        count, nick, client_id);
968
969  out:
970   if (client_id_count) {
971     for (i = 0; i < client_id_count; i++)
972       silc_free(client_id[i]);
973     silc_free(client_id);
974   }
975   silc_free(clients);
976   silc_free(nick);
977   silc_free(server_name);
978
979   return ret;
980 }
981
982 /* Server side of command WHOIS. Processes user's query and sends found 
983    results as command replies back to the client. */
984
985 SILC_SERVER_CMD_FUNC(whois)
986 {
987   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
988   int ret = 0;
989
990   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
991
992   ret = silc_server_command_whois_process(cmd);
993   silc_server_command_free(cmd);
994 }
995
996 /******************************************************************************
997
998                               WHOWAS Functions
999
1000 ******************************************************************************/
1001
1002 static int
1003 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1004                                  char **nickname,
1005                                  char **server_name,
1006                                  int *count)
1007 {
1008   unsigned char *tmp;
1009   SilcUInt32 len;
1010
1011   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1012   if (!tmp) {
1013     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1014                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1015     return FALSE;
1016   }
1017
1018   /* Get the nickname@server string and parse it. */
1019   silc_parse_userfqdn(tmp, nickname, server_name);
1020
1021   /* Get the max count of reply messages allowed */
1022   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1023   if (tmp)
1024     *count = atoi(tmp);
1025   else
1026     *count = 0;
1027
1028   return TRUE;
1029 }
1030
1031 static char
1032 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1033                                  SilcClientEntry *clients,
1034                                  SilcUInt32 clients_count)
1035 {
1036   SilcServer server = cmd->server;
1037   int i;
1038   SilcClientEntry entry;
1039
1040   for (i = 0; i < clients_count; i++) {
1041     entry = clients[i];
1042
1043     if (!entry->nickname || !entry->username) {
1044       SilcBuffer tmpbuf;
1045       SilcUInt16 old_ident;
1046
1047       if (!entry->router)
1048         continue;
1049       
1050       old_ident = silc_command_get_ident(cmd->payload);
1051       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1052       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1053
1054       /* Send WHOWAS command */
1055       silc_server_packet_send(server, entry->router->connection,
1056                               SILC_PACKET_COMMAND, cmd->packet->flags,
1057                               tmpbuf->data, tmpbuf->len, TRUE);
1058       
1059       /* Reprocess this packet after received reply */
1060       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1061                                   silc_command_get_ident(cmd->payload),
1062                                   silc_server_command_whowas, 
1063                                   silc_server_command_dup(cmd));
1064       cmd->pending = TRUE;
1065       silc_command_set_ident(cmd->payload, old_ident);
1066
1067       silc_buffer_free(tmpbuf);
1068       return FALSE;
1069     }
1070   }
1071
1072   return TRUE;
1073 }
1074
1075 static void
1076 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1077                                       SilcClientEntry *clients,
1078                                       SilcUInt32 clients_count)
1079 {
1080   SilcServer server = cmd->server;
1081   char *tmp;
1082   int i, k, count = 0, len;
1083   SilcBuffer packet, idp;
1084   SilcClientEntry entry = NULL;
1085   SilcCommandStatus status;
1086   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1087   char nh[256], uh[256];
1088   int valid_count;
1089
1090   status = SILC_STATUS_OK;
1091
1092   /* Process only entries that are not registered anymore. */
1093   valid_count = 0;
1094   for (i = 0; i < clients_count; i++) {
1095     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1096       clients[i] = NULL;
1097     else
1098       valid_count++;
1099   }
1100
1101   if (!valid_count) {
1102     /* No valid entries found at all, just send error */
1103     unsigned char *tmp;
1104     
1105     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1106     if (tmp)
1107       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1108                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1109                                            3, tmp, strlen(tmp));
1110     return;
1111   }
1112
1113   if (valid_count > 1)
1114     status = SILC_STATUS_LIST_START;
1115
1116   for (i = 0, k = 0; i < clients_count; i++) {
1117     entry = clients[i];
1118     if (!entry)
1119       continue;
1120
1121     if (k >= 1)
1122       status = SILC_STATUS_LIST_ITEM;
1123     if (valid_count > 1 && k == valid_count - 1)
1124       status = SILC_STATUS_LIST_END;
1125     if (count && k - 1 == count)
1126       status = SILC_STATUS_LIST_END;
1127     if (count && k - 1 > count)
1128       break;
1129
1130     /* Send WHOWAS reply */
1131     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1132     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1133     memset(uh, 0, sizeof(uh));
1134     memset(nh, 0, sizeof(nh));
1135
1136     strncat(nh, entry->nickname, strlen(entry->nickname));
1137     if (!strchr(entry->nickname, '@')) {
1138       strncat(nh, "@", 1);
1139       if (entry->servername) {
1140         strncat(nh, entry->servername, strlen(entry->servername));
1141       } else {
1142         len = entry->router ? strlen(entry->router->server_name) :
1143           strlen(server->server_name);
1144         strncat(nh, entry->router ? entry->router->server_name :
1145                 server->server_name, len);
1146       }
1147     }
1148       
1149     strncat(uh, entry->username, strlen(entry->username));
1150     if (!strchr(entry->username, '@')) {
1151       strncat(uh, "@", 1);
1152       strcat(uh, "*private*");
1153     }
1154       
1155     packet = 
1156       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1157                                            status, 0, ident, 4, 
1158                                            2, idp->data, idp->len,
1159                                            3, nh, strlen(nh),
1160                                            4, uh, strlen(uh),
1161                                            5, entry->userinfo, 
1162                                            entry->userinfo ? 
1163                                            strlen(entry->userinfo) : 0);
1164     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1165                             0, packet->data, packet->len, FALSE);
1166     
1167     silc_buffer_free(packet);
1168     silc_buffer_free(idp);
1169
1170     k++;
1171   }
1172 }
1173
1174 static int
1175 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1176 {
1177   SilcServer server = cmd->server;
1178   char *nick = NULL, *server_name = NULL;
1179   int count = 0;
1180   SilcClientEntry *clients = NULL;
1181   SilcUInt32 clients_count = 0;
1182   int ret = 0;
1183   bool check_global = FALSE;
1184
1185   /* Protocol dictates that we must always send the received WHOWAS request
1186      to our router if we are normal server, so let's do it now unless we
1187      are standalone. We will not send any replies to the client until we
1188      have received reply from the router. */
1189   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1190       server->server_type == SILC_SERVER && !cmd->pending && 
1191       !server->standalone) {
1192     SilcBuffer tmpbuf;
1193     SilcUInt16 old_ident;
1194
1195     old_ident = silc_command_get_ident(cmd->payload);
1196     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1197     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1198
1199     /* Send WHOWAS command to our router */
1200     silc_server_packet_send(server, (SilcSocketConnection)
1201                             server->router->connection,
1202                             SILC_PACKET_COMMAND, cmd->packet->flags,
1203                             tmpbuf->data, tmpbuf->len, TRUE);
1204
1205     /* Reprocess this packet after received reply from router */
1206     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1207                                 silc_command_get_ident(cmd->payload),
1208                                 silc_server_command_whowas,
1209                                 silc_server_command_dup(cmd));
1210     cmd->pending = TRUE;
1211     silc_command_set_ident(cmd->payload, old_ident);
1212
1213     silc_buffer_free(tmpbuf);
1214     ret = -1;
1215     goto out;
1216   }
1217
1218   /* We are ready to process the command request. Let's search for the
1219      requested client and send reply to the requesting client. */
1220
1221   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1222     check_global = TRUE;
1223   else if (server->server_type != SILC_SERVER)
1224     check_global = TRUE;
1225
1226   /* Parse the whowas request */
1227   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1228     return 0;
1229
1230   /* Get all clients matching that nickname from local list */
1231   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1232                                            nick, server_name,
1233                                            &clients, &clients_count))
1234     silc_idlist_get_clients_by_hash(server->local_list, 
1235                                     nick, server->md5hash,
1236                                     &clients, &clients_count);
1237   
1238   /* Check global list as well */
1239   if (check_global) {
1240     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1241                                              nick, server_name,
1242                                              &clients, &clients_count))
1243       silc_idlist_get_clients_by_hash(server->global_list, 
1244                                       nick, server->md5hash,
1245                                       &clients, &clients_count);
1246   }
1247   
1248   if (!clients) {
1249     /* Such a client really does not exist in the SILC network. */
1250     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1251                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1252                                          3, nick, strlen(nick));
1253     goto out;
1254   }
1255
1256   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1257     ret = -1;
1258     goto out;
1259   }
1260
1261   /* Send the command reply to the client */
1262   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1263
1264  out:
1265   silc_free(clients);
1266   silc_free(nick);
1267   silc_free(server_name);
1268   return ret;
1269 }
1270
1271 /* Server side of command WHOWAS. */
1272
1273 SILC_SERVER_CMD_FUNC(whowas)
1274 {
1275   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1276   int ret = 0;
1277
1278   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1279
1280   ret = silc_server_command_whowas_process(cmd);
1281   silc_server_command_free(cmd);
1282 }
1283
1284 /******************************************************************************
1285
1286                               IDENTIFY Functions
1287
1288 ******************************************************************************/
1289
1290 static void 
1291 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1292 {
1293   SilcServer server = cmd->server;
1294   SilcBuffer tmpbuf;
1295   SilcUInt16 old_ident;
1296
1297   old_ident = silc_command_get_ident(cmd->payload);
1298   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1299   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1300
1301   /* Send IDENTIFY command to our router */
1302   silc_server_packet_send(server, (SilcSocketConnection)
1303                           server->router->connection,
1304                           SILC_PACKET_COMMAND, cmd->packet->flags,
1305                           tmpbuf->data, tmpbuf->len, TRUE);
1306
1307   /* Reprocess this packet after received reply from router */
1308   silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1309                               silc_command_get_ident(cmd->payload),
1310                               silc_server_command_identify,
1311                               silc_server_command_dup(cmd));
1312   cmd->pending = TRUE;
1313   silc_command_set_ident(cmd->payload, old_ident);
1314   silc_buffer_free(tmpbuf);
1315 }
1316
1317 static int
1318 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1319                                    SilcClientEntry **clients,
1320                                    SilcUInt32 *clients_count,
1321                                    SilcServerEntry **servers,
1322                                    SilcUInt32 *servers_count,
1323                                    SilcChannelEntry **channels,
1324                                    SilcUInt32 *channels_count,
1325                                    SilcUInt32 *count)
1326 {
1327   SilcServer server = cmd->server;
1328   unsigned char *tmp;
1329   SilcUInt32 len;
1330   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1331   SilcIDPayload idp;
1332   bool check_global = FALSE;
1333   void *entry;
1334   int i;
1335   bool error = FALSE;
1336
1337   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1338     check_global = TRUE;
1339   else if (server->server_type != SILC_SERVER)
1340     check_global = TRUE;
1341
1342   /* If ID Payload is in the command it must be used instead of names */
1343   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1344   if (!tmp) {
1345     /* No ID, get the names. */
1346
1347     /* If we are normal server and have not resolved information from
1348        router yet, do so now. */
1349     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1350         server->server_type == SILC_SERVER && !cmd->pending && 
1351         !server->standalone) {
1352       silc_server_command_identify_send_router(cmd);
1353       return -1;
1354     }
1355
1356     /* Try to get nickname@server. */
1357     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1358     if (tmp) {
1359       char *nick = NULL;
1360       char *nick_server = NULL;
1361
1362       silc_parse_userfqdn(tmp, &nick, &nick_server);
1363
1364       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1365                                            nick, server->md5hash,
1366                                            clients, clients_count))
1367         silc_idlist_get_clients_by_nickname(server->local_list, 
1368                                             nick, nick_server,
1369                                             clients, clients_count);
1370       if (check_global) {
1371         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1372                                              nick, server->md5hash,
1373                                              clients, clients_count))
1374           silc_idlist_get_clients_by_nickname(server->global_list, 
1375                                               nick, nick_server,
1376                                               clients, clients_count);
1377       }
1378
1379       silc_free(nick);
1380       silc_free(nick_server);
1381
1382       if (!(*clients)) {
1383         /* the nickname does not exist, send error reply */
1384         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1385                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1386                                              3, tmp, strlen(tmp));
1387         return 0;
1388       }
1389     }
1390
1391     /* Try to get server name */
1392     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1393     if (tmp) {
1394       entry = silc_idlist_find_server_by_name(server->local_list,
1395                                               tmp, TRUE, NULL);
1396       if (!entry && check_global)
1397         entry = silc_idlist_find_server_by_name(server->global_list,
1398                                                 tmp, TRUE, NULL);
1399       if (entry) {
1400         *servers = silc_realloc(*servers, sizeof(**servers) * 
1401                                 (*servers_count + 1));
1402         (*servers)[(*servers_count)++] = entry;
1403       }
1404
1405       if (!(*servers)) {
1406         /* the server does not exist, send error reply */
1407         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1408                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1409                                              3, tmp, strlen(tmp));
1410         return 0;
1411       }
1412     }
1413
1414     /* Try to get channel name */
1415     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1416     if (tmp) {
1417       entry = silc_idlist_find_channel_by_name(server->local_list,
1418                                                tmp, NULL);
1419       if (!entry && check_global)
1420         entry = silc_idlist_find_channel_by_name(server->global_list,
1421                                                  tmp, NULL);
1422       if (entry) {
1423         *channels = silc_realloc(*channels, sizeof(**channels) * 
1424                                  (*channels_count + 1));
1425         (*channels)[(*channels_count)++] = entry;
1426       }
1427
1428       if (!(*channels)) {
1429         /* The channel does not exist, send error reply */
1430         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1431                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1432                                              3, tmp, strlen(tmp));
1433         return 0;
1434       }
1435     }
1436
1437     if (!(*clients) && !(*servers) && !(*channels)) {
1438       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1439                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1440       return 0;
1441     }
1442   } else {
1443     /* Command includes ID, we must use that.  Also check whether the command
1444        has more than one ID set - take them all. */
1445
1446     /* Take all ID's from the command packet */
1447     for (i = 0; i < argc; i++) {
1448       void *id;
1449
1450       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1451       if (!tmp)
1452         continue;
1453       
1454       idp = silc_id_payload_parse(tmp, len);
1455       if (!idp) {
1456         silc_free(*clients);
1457         silc_free(*servers);
1458         silc_free(*channels);
1459         silc_server_command_send_status_reply(
1460                                        cmd, SILC_COMMAND_IDENTIFY,
1461                                        SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1462         return 0;
1463       }
1464
1465       id = silc_id_payload_get_id(idp);
1466       
1467       switch (silc_id_payload_get_type(idp)) {
1468         
1469       case SILC_ID_CLIENT:
1470         entry = (void *)silc_idlist_find_client_by_id(server->local_list, 
1471                                                       id, TRUE, NULL);
1472         if (!entry && check_global)
1473           entry = (void *)silc_idlist_find_client_by_id(server->global_list, 
1474                                                         id, TRUE, NULL);
1475         if (entry) {
1476           *clients = silc_realloc(*clients, sizeof(**clients) * 
1477                                   (*clients_count + 1));
1478           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1479         } else {
1480           /* If we are normal server and have not resolved information from
1481              router yet, do so now. */
1482           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1483               server->server_type == SILC_SERVER && !cmd->pending && 
1484               !server->standalone) {
1485             silc_server_command_identify_send_router(cmd);
1486             silc_free(*clients);
1487             silc_free(*servers);
1488             silc_free(*channels);
1489             return -1;
1490           } else {
1491             silc_server_command_send_status_data(
1492                                         cmd, SILC_COMMAND_IDENTIFY,
1493                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1494                                         2, tmp, len);
1495             error = TRUE;
1496           }
1497         }
1498
1499         break;
1500         
1501       case SILC_ID_SERVER:
1502         entry = (void *)silc_idlist_find_server_by_id(server->local_list, 
1503                                                       id, TRUE, NULL);
1504         if (!entry && check_global)
1505           entry = (void *)silc_idlist_find_server_by_id(server->global_list, 
1506                                                         id, TRUE, NULL);
1507         if (entry) {
1508           *servers = silc_realloc(*servers, sizeof(**servers) * 
1509                                   (*servers_count + 1));
1510           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1511         } else {
1512           /* If we are normal server and have not resolved information from
1513              router yet, do so now. */
1514           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1515               server->server_type == SILC_SERVER && !cmd->pending && 
1516               !server->standalone) {
1517             silc_server_command_identify_send_router(cmd);
1518             silc_free(*clients);
1519             silc_free(*servers);
1520             silc_free(*channels);
1521             return -1;
1522           } else {
1523             silc_server_command_send_status_data(
1524                                          cmd, SILC_COMMAND_IDENTIFY,
1525                                          SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
1526                                          2, tmp, len);
1527             error = TRUE;
1528           }
1529         }
1530         break;
1531         
1532       case SILC_ID_CHANNEL:
1533         entry = (void *)silc_idlist_find_channel_by_id(server->local_list, 
1534                                                        id, NULL);
1535         if (!entry && check_global)
1536           entry = (void *)silc_idlist_find_channel_by_id(server->global_list, 
1537                                                          id, NULL);
1538         if (entry) {
1539           *channels = silc_realloc(*channels, sizeof(**channels) * 
1540                                    (*channels_count + 1));
1541           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1542         } else {
1543           /* If we are normal server and have not resolved information from
1544              router yet, do so now. */
1545           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1546               server->server_type == SILC_SERVER && !cmd->pending && 
1547               !server->standalone) {
1548             silc_server_command_identify_send_router(cmd);
1549             silc_free(*clients);
1550             silc_free(*servers);
1551             silc_free(*channels);
1552             return -1;
1553           } else {
1554             silc_server_command_send_status_data(
1555                                          cmd, SILC_COMMAND_IDENTIFY,
1556                                          SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID,
1557                                          2, tmp, len);
1558             error = TRUE;
1559           }
1560         }
1561         break;
1562       }
1563
1564       silc_free(id);
1565     }
1566   }
1567
1568   if (error) {
1569     silc_free(*clients);
1570     silc_free(*servers);
1571     silc_free(*channels);
1572     return FALSE;
1573   }
1574   
1575   /* Get the max count of reply messages allowed */
1576   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1577   if (tmp)
1578     *count = atoi(tmp);
1579   else
1580     *count = 0;
1581
1582   return 1;
1583 }
1584
1585 /* Checks that all mandatory fields in client entry are present. If not
1586    then send WHOIS request to the server who owns the client. We use
1587    WHOIS because we want to get as much information as possible at once. */
1588
1589 static bool
1590 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1591                                           SilcClientEntry *clients,
1592                                           SilcUInt32 clients_count)
1593 {
1594   SilcServer server = cmd->server;
1595   SilcClientEntry entry;
1596   SilcServerResolveContext resolve = NULL, r = NULL;
1597   SilcUInt32 resolve_count = 0;
1598   int i, k;
1599   bool no_res = TRUE;
1600
1601   for (i = 0; i < clients_count; i++) {
1602     entry = clients[i];
1603     if (!entry)
1604       continue;
1605
1606     if (entry->nickname || 
1607         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1608       if (!entry->router)
1609         continue;
1610
1611       /* If we are normal server, and we've not resolved this client from
1612          router and it is global client, we'll check whether it is on some
1613          channel.  If not then we cannot be sure about its validity, and
1614          we'll resolve it from router. */
1615       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1616           entry->connection || silc_hash_table_count(entry->channels))
1617         continue;
1618     }
1619
1620     /* We need to resolve this entry since it is not complete */
1621
1622     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1623       /* The entry is being resolved (and we are not the resolver) so attach
1624          to the command reply and we're done with this one. */
1625       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1626                                   entry->resolve_cmd_ident,
1627                                   silc_server_command_identify,
1628                                   silc_server_command_dup(cmd));
1629       no_res = FALSE;
1630     } else {
1631       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1632         /* We've resolved this and it still is not ready.  We'll return
1633            and are that this will be handled again after it is resolved. */
1634         for (i = 0; i < resolve_count; i++) {
1635           for (k = 0; k < r->res_argc; k++)
1636             silc_free(r->res_argv[k]);
1637           silc_free(r->res_argv);
1638           silc_free(r->res_argv_lens);
1639           silc_free(r->res_argv_types);
1640         }
1641         silc_free(resolve);
1642         return FALSE;
1643       } else {
1644         /* We'll resolve this client */
1645         SilcBuffer idp;
1646
1647         r = NULL;
1648         for (k = 0; k < resolve_count; k++) {
1649           if (resolve[k].router == entry->router) {
1650             r = &resolve[k];
1651             break;
1652           }
1653         }
1654
1655         if (!r) {
1656           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1657                                  (resolve_count + 1));
1658           r = &resolve[resolve_count];
1659           memset(r, 0, sizeof(*r));
1660           r->router = entry->router;
1661           r->ident = ++server->cmd_ident;
1662           resolve_count++;
1663         }
1664
1665         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1666                                    (r->res_argc + 1));
1667         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1668                                         sizeof(*r->res_argv_lens) *
1669                                         (r->res_argc + 1));
1670         r->res_argv_types = silc_realloc(r->res_argv_types, 
1671                                          sizeof(*r->res_argv_types) *
1672                                          (r->res_argc + 1));
1673         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1674         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1675                                                sizeof(**r->res_argv));
1676         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1677         r->res_argv_lens[r->res_argc] = idp->len;
1678         r->res_argv_types[r->res_argc] = r->res_argc + 3;
1679         r->res_argc++;
1680         silc_buffer_free(idp);
1681
1682         entry->resolve_cmd_ident = r->ident;
1683         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1684         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1685       }
1686     }
1687   }
1688
1689   /* Do the resolving */
1690   for (i = 0; i < resolve_count; i++) {
1691     SilcBuffer res_cmd;
1692
1693     r = &resolve[i];
1694
1695     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1696        now anyway so make it a good one. */
1697     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1698                                           r->res_argc, r->res_argv, 
1699                                           r->res_argv_lens,
1700                                           r->res_argv_types, 
1701                                           r->ident);
1702     silc_server_packet_send(server, r->router->connection,
1703                             SILC_PACKET_COMMAND, cmd->packet->flags,
1704                             res_cmd->data, res_cmd->len, FALSE);
1705
1706     /* Reprocess this packet after received reply */
1707     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1708                                 r->ident,
1709                                 silc_server_command_identify,
1710                                 silc_server_command_dup(cmd));
1711     cmd->pending = TRUE;
1712
1713     silc_buffer_free(res_cmd);
1714     for (k = 0; k < r->res_argc; k++)
1715       silc_free(r->res_argv[k]);
1716     silc_free(r->res_argv);
1717     silc_free(r->res_argv_lens);
1718     silc_free(r->res_argv_types);
1719     no_res = FALSE;
1720   }
1721   silc_free(resolve);
1722
1723   return no_res;
1724 }
1725
1726 static void
1727 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1728                                         SilcClientEntry *clients,
1729                                         SilcUInt32 clients_count,
1730                                         SilcServerEntry *servers,
1731                                         SilcUInt32 servers_count,
1732                                         SilcChannelEntry *channels,
1733                                         SilcUInt32 channels_count,
1734                                         int count)
1735 {
1736   SilcServer server = cmd->server;
1737   int i, k, len, valid_count;
1738   SilcBuffer packet, idp;
1739   SilcCommandStatus status;
1740   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1741   char nh[256], uh[256];
1742   SilcSocketConnection hsock;
1743
1744   status = SILC_STATUS_OK;
1745
1746   if (clients) {
1747     SilcClientEntry entry;
1748
1749     /* Process only valid entries. */
1750     valid_count = 0;
1751     for (i = 0; i < clients_count; i++) {
1752       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1753         valid_count++;
1754       else
1755         clients[i] = NULL;
1756     }
1757
1758     if (!valid_count) {
1759       /* No valid entries found at all, just send error */
1760       unsigned char *tmp;
1761
1762       tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1763       if (tmp) {
1764         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1765                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1766                                              3, tmp, strlen(tmp));
1767       } else {
1768         tmp = silc_argument_get_arg_type(cmd->args, 5, (SilcUInt32 *)&len);
1769         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1770                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1771                                              2, tmp, len);
1772       }
1773       return;
1774     }
1775
1776     /* Process all valid client entries and send command replies */
1777
1778     if (valid_count > 1)
1779       status = SILC_STATUS_LIST_START;
1780
1781     for (i = 0, k = 0; i < clients_count; i++) {
1782       entry = clients[i];
1783       if (!entry)
1784         continue;
1785
1786       if (k >= 1)
1787         status = SILC_STATUS_LIST_ITEM;
1788       if (valid_count > 1 && k == valid_count - 1 
1789           && !servers_count && !channels_count)
1790         status = SILC_STATUS_LIST_END;
1791       if (count && k - 1 == count)
1792         status = SILC_STATUS_LIST_END;
1793       if (count && k - 1 > count)
1794         break;
1795
1796       /* Send IDENTIFY reply */
1797
1798       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1799       memset(uh, 0, sizeof(uh));
1800       memset(nh, 0, sizeof(nh));
1801       strncat(nh, entry->nickname, strlen(entry->nickname));
1802       if (!strchr(entry->nickname, '@')) {
1803         strncat(nh, "@", 1);
1804         if (entry->servername) {
1805           strncat(nh, entry->servername, strlen(entry->servername));
1806         } else {
1807           len = entry->router ? strlen(entry->router->server_name) :
1808             strlen(server->server_name);
1809           strncat(nh, entry->router ? entry->router->server_name :
1810                   server->server_name, len);
1811         }
1812       }
1813
1814       if (!entry->username) {
1815         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1816                                                       status, 0, ident, 2,
1817                                                       2, idp->data, idp->len, 
1818                                                       3, nh, strlen(nh));
1819       } else {
1820         strncat(uh, entry->username, strlen(entry->username));
1821         if (!strchr(entry->username, '@')) {
1822           strncat(uh, "@", 1);
1823           hsock = (SilcSocketConnection)entry->connection;
1824           len = strlen(hsock->hostname);
1825           strncat(uh, hsock->hostname, len);
1826         }
1827         
1828         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1829                                                       status, 0, ident, 3,
1830                                                       2, idp->data, idp->len, 
1831                                                       3, nh, strlen(nh),
1832                                                       4, uh, strlen(uh));
1833       }
1834       
1835       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1836                               0, packet->data, packet->len, FALSE);
1837       
1838       silc_buffer_free(packet);
1839       silc_buffer_free(idp);
1840       
1841       k++;
1842     }
1843   }
1844
1845   if (servers) {
1846     SilcServerEntry entry;
1847
1848     if (status == SILC_STATUS_OK && servers_count > 1)
1849       status = SILC_STATUS_LIST_START;
1850
1851     for (i = 0, k = 0; i < servers_count; i++) {
1852       entry = servers[i];
1853       
1854       if (k >= 1)
1855         status = SILC_STATUS_LIST_ITEM;
1856       if (servers_count > 1 && k == servers_count - 1 && !channels_count)
1857         status = SILC_STATUS_LIST_END;
1858       if (count && k - 1 == count)
1859         status = SILC_STATUS_LIST_END;
1860       if (count && k - 1 > count)
1861         break;
1862       
1863       /* Send IDENTIFY reply */
1864       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1865       packet = 
1866         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1867                                              status, 0, ident, 2,
1868                                              2, idp->data, idp->len, 
1869                                              3, entry->server_name, 
1870                                              entry->server_name ? 
1871                                              strlen(entry->server_name) : 0);
1872       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1873                               0, packet->data, packet->len, FALSE);
1874       
1875       silc_buffer_free(packet);
1876       silc_buffer_free(idp);
1877       
1878       k++;
1879     }
1880   }
1881
1882   if (channels) {
1883     SilcChannelEntry entry;
1884
1885     if (status == SILC_STATUS_OK && channels_count > 1)
1886       status = SILC_STATUS_LIST_START;
1887
1888     for (i = 0, k = 0; i < channels_count; i++) {
1889       entry = channels[i];
1890       
1891       if (k >= 1)
1892         status = SILC_STATUS_LIST_ITEM;
1893       if (channels_count > 1 && k == channels_count - 1)
1894         status = SILC_STATUS_LIST_END;
1895       if (count && k - 1 == count)
1896         status = SILC_STATUS_LIST_END;
1897       if (count && k - 1 > count)
1898         break;
1899       
1900       /* Send IDENTIFY reply */
1901       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1902       packet = 
1903         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1904                                              status, 0, ident, 2,
1905                                              2, idp->data, idp->len, 
1906                                              3, entry->channel_name, 
1907                                              entry->channel_name ? 
1908                                              strlen(entry->channel_name): 0);
1909       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1910                               0, packet->data, packet->len, FALSE);
1911       
1912       silc_buffer_free(packet);
1913       silc_buffer_free(idp);
1914       
1915       k++;
1916     }
1917   }
1918 }
1919
1920 static int
1921 silc_server_command_identify_process(SilcServerCommandContext cmd)
1922 {
1923   SilcUInt32 count = 0;
1924   int ret = 0;
1925   SilcClientEntry *clients = NULL;
1926   SilcServerEntry *servers = NULL;
1927   SilcChannelEntry *channels = NULL;
1928   SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
1929
1930   /* Parse the IDENTIFY request */
1931   ret = silc_server_command_identify_parse(cmd,
1932                                            &clients, &clients_count,
1933                                            &servers, &servers_count,
1934                                            &channels, &channels_count,
1935                                            &count);
1936   if (ret < 1)
1937     return ret;
1938   ret = 0;
1939
1940   /* Check that all mandatory fields are present and request those data
1941      from the server who owns the client if necessary. */
1942   if (clients && !silc_server_command_identify_check_client(cmd, clients, 
1943                                                             clients_count)) {
1944     ret = -1;
1945     goto out;
1946   }
1947
1948   /* Send the command reply to the client */
1949   silc_server_command_identify_send_reply(cmd, 
1950                                           clients, clients_count,
1951                                           servers, servers_count,
1952                                           channels, channels_count, 
1953                                           count);
1954
1955  out:
1956   silc_free(clients);
1957   silc_free(servers);
1958   silc_free(channels);
1959   return ret;
1960 }
1961
1962 SILC_SERVER_CMD_FUNC(identify)
1963 {
1964   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1965   int ret = 0;
1966
1967   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1968
1969   ret = silc_server_command_identify_process(cmd);
1970   silc_server_command_free(cmd);
1971 }
1972
1973 /* Server side of command NICK. Sets nickname for user. Setting
1974    nickname causes generation of a new client ID for the client. The
1975    new client ID is sent to the client after changing the nickname. */
1976
1977 SILC_SERVER_CMD_FUNC(nick)
1978 {
1979   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1980   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1981   SilcServer server = cmd->server;
1982   SilcBuffer packet, nidp, oidp = NULL;
1983   SilcClientID *new_id;
1984   SilcUInt32 nick_len;
1985   char *nick;
1986   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1987   int nickfail = 0;
1988
1989   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1990     goto out;
1991
1992   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
1993
1994   /* Check nickname */
1995   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
1996   if (nick_len > 128)
1997     nick[128] = '\0';
1998   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
1999     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2000                                           SILC_STATUS_ERR_BAD_NICKNAME);
2001     goto out;
2002   }
2003
2004   /* Check for same nickname */
2005   if (!strcmp(client->nickname, nick)) {
2006     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2007     goto send_reply;
2008   }
2009
2010   /* Create new Client ID */
2011   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
2012                                    cmd->server->rng, 
2013                                    cmd->server->md5hash, nick,
2014                                    &new_id)) {
2015     nickfail++;
2016     if (nickfail > 9) {
2017       silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2018                                             SILC_STATUS_ERR_BAD_NICKNAME);
2019       goto out;
2020     }
2021     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2022   }
2023
2024   /* Send notify about nickname change to our router. We send the new
2025      ID and ask to replace it with the old one. If we are router the
2026      packet is broadcasted. Send NICK_CHANGE notify. */
2027   if (!server->standalone)
2028     silc_server_send_notify_nick_change(server, server->router->connection, 
2029                                         server->server_type == SILC_SERVER ? 
2030                                         FALSE : TRUE, client->id,
2031                                         new_id, nick);
2032
2033   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2034
2035   /* Remove old cache entry */
2036   silc_idcache_del_by_context(server->local_list->clients, client);
2037
2038   /* Free old ID */
2039   silc_free(client->id);
2040
2041   /* Save the nickname as this client is our local client */
2042   silc_free(client->nickname);
2043
2044   client->nickname = strdup(nick);
2045   client->id = new_id;
2046
2047   /* Update client cache */
2048   silc_idcache_add(server->local_list->clients, client->nickname, 
2049                    client->id, (void *)client, 0, NULL);
2050
2051   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2052
2053   /* Send NICK_CHANGE notify to the client's channels */
2054   silc_server_send_notify_on_channels(server, NULL, client, 
2055                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2056                                       oidp->data, oidp->len, 
2057                                       nidp->data, nidp->len,
2058                                       client->nickname, 
2059                                       strlen(client->nickname));
2060
2061  send_reply:
2062   /* Send the new Client ID as reply command back to client */
2063   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2064                                                 SILC_STATUS_OK, 0, ident, 1, 
2065                                                 2, nidp->data, nidp->len);
2066   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2067                           0, packet->data, packet->len, FALSE);
2068
2069   silc_buffer_free(packet);
2070   silc_buffer_free(nidp);
2071   if (oidp)
2072     silc_buffer_free(oidp);
2073   
2074  out:
2075   silc_server_command_free(cmd);
2076 }
2077
2078 /* Sends the LIST command reply */
2079
2080 static void
2081 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2082                                     SilcChannelEntry *lch, 
2083                                     SilcUInt32 lch_count,
2084                                     SilcChannelEntry *gch,
2085                                     SilcUInt32 gch_count)
2086 {
2087   int i, k;
2088   SilcBuffer packet, idp;
2089   SilcChannelEntry entry;
2090   SilcCommandStatus status;
2091   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2092   char *topic;
2093   unsigned char usercount[4];
2094   SilcUInt32 users;
2095   int valid_lcount = 0, valid_rcount = 0;
2096
2097   for (i = 0; i < lch_count; i++) {
2098     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2099       lch[i] = NULL;
2100     else
2101       valid_lcount++;
2102   }
2103   for (i = 0; i < gch_count; i++) {
2104     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2105       gch[i] = NULL;
2106     else
2107       valid_rcount++;
2108   }
2109
2110   status = SILC_STATUS_OK;
2111   if ((lch_count + gch_count) > 1)
2112     status = SILC_STATUS_LIST_START;
2113
2114   /* Local list */
2115   for (i = 0, k = 0; i < lch_count; i++) {
2116     entry = lch[i];
2117     if (!entry)
2118       continue;
2119
2120     if (k >= 1)
2121       status = SILC_STATUS_LIST_ITEM;
2122     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2123       status = SILC_STATUS_LIST_END;
2124
2125     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2126
2127     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2128       topic = "*private*";
2129       memset(usercount, 0, sizeof(usercount));
2130     } else {
2131       topic = entry->topic;
2132       users = silc_hash_table_count(entry->user_list);
2133       SILC_PUT32_MSB(users, usercount);
2134     }
2135
2136     /* Send the reply */
2137     packet = 
2138       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2139                                            status, 0, ident, 4,
2140                                            2, idp->data, idp->len,
2141                                            3, entry->channel_name, 
2142                                            strlen(entry->channel_name),
2143                                            4, topic, topic ? strlen(topic) : 0,
2144                                            5, usercount, 4);
2145     silc_server_packet_send(cmd->server, cmd->sock, 
2146                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2147                             packet->len, FALSE);
2148     silc_buffer_free(packet);
2149     silc_buffer_free(idp);
2150     k++;
2151   }
2152
2153   /* Global list */
2154   for (i = 0, k = 0; i < gch_count; i++) {
2155     entry = gch[i];
2156     if (!entry)
2157       continue;
2158
2159     if (k >= 1)
2160       status = SILC_STATUS_LIST_ITEM;
2161     if (valid_rcount > 1 && k == valid_rcount - 1)
2162       status = SILC_STATUS_LIST_END;
2163
2164     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2165
2166     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2167       topic = "*private*";
2168       memset(usercount, 0, sizeof(usercount));
2169     } else {
2170       topic = entry->topic;
2171       users = entry->user_count;
2172       SILC_PUT32_MSB(users, usercount);
2173     }
2174
2175     /* Send the reply */
2176     packet = 
2177       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2178                                            status, 0, ident, 4,
2179                                            2, idp->data, idp->len,
2180                                            3, entry->channel_name, 
2181                                            strlen(entry->channel_name),
2182                                            4, topic, topic ? strlen(topic) : 0,
2183                                            5, usercount, 4);
2184     silc_server_packet_send(cmd->server, cmd->sock, 
2185                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2186                             packet->len, FALSE);
2187     silc_buffer_free(packet);
2188     silc_buffer_free(idp);
2189     k++;
2190   }
2191 }
2192
2193 /* Server side of LIST command. This lists the channel of the requested
2194    server. Secret channels are not listed. */
2195
2196 SILC_SERVER_CMD_FUNC(list)
2197 {
2198   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199   SilcServer server = cmd->server;
2200   SilcChannelID *channel_id = NULL;
2201   unsigned char *tmp;
2202   SilcUInt32 tmp_len;
2203   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2204   SilcUInt32 lch_count = 0, gch_count = 0;
2205
2206   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2207
2208   /* If we are normal server, send the command to router, since we
2209      want to know all channels in the network. */
2210   if (!cmd->pending && server->server_type == SILC_SERVER && 
2211       !server->standalone) {
2212     SilcBuffer tmpbuf;
2213     SilcUInt16 old_ident;
2214     
2215     old_ident = silc_command_get_ident(cmd->payload);
2216     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2217     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2218     silc_server_packet_send(server, server->router->connection,
2219                             SILC_PACKET_COMMAND, cmd->packet->flags,
2220                             tmpbuf->data, tmpbuf->len, TRUE);
2221
2222     /* Reprocess this packet after received reply from router */
2223     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2224                                 silc_command_get_ident(cmd->payload),
2225                                 silc_server_command_list, 
2226                                 silc_server_command_dup(cmd));
2227     cmd->pending = TRUE;
2228     silc_command_set_ident(cmd->payload, old_ident);
2229     silc_buffer_free(tmpbuf);
2230     goto out;
2231   }
2232
2233   /* Get Channel ID */
2234   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2235   if (tmp) {
2236     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2237     if (!channel_id) {
2238       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2239                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2240       goto out;
2241     }
2242   }
2243
2244   /* Get the channels from local list */
2245   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2246                                        &lch_count);
2247   
2248   /* Get the channels from global list */
2249   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2250                                        &gch_count);
2251
2252   /* Send the reply */
2253   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2254                                       gchannels, gch_count);
2255
2256   silc_free(lchannels);
2257   silc_free(gchannels);
2258
2259  out:
2260   silc_server_command_free(cmd);
2261 }
2262
2263 /* Server side of TOPIC command. Sets topic for channel and/or returns
2264    current topic to client. */
2265
2266 SILC_SERVER_CMD_FUNC(topic)
2267 {
2268   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2269   SilcServer server = cmd->server;
2270   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2271   SilcChannelID *channel_id;
2272   SilcChannelEntry channel;
2273   SilcChannelClientEntry chl;
2274   SilcBuffer packet, idp;
2275   unsigned char *tmp;
2276   SilcUInt32 argc, tmp_len;
2277   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2278
2279   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2280
2281   argc = silc_argument_get_arg_num(cmd->args);
2282
2283   /* Get Channel ID */
2284   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2285   if (!tmp) {
2286     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2287                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2288     goto out;
2289   }
2290   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2291   if (!channel_id) {
2292     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2293                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2294     goto out;
2295   }
2296
2297   /* Check whether the channel exists */
2298   channel = silc_idlist_find_channel_by_id(server->local_list, 
2299                                            channel_id, NULL);
2300   if (!channel) {
2301     channel = silc_idlist_find_channel_by_id(server->global_list, 
2302                                              channel_id, NULL);
2303     if (!channel) {
2304       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2305                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2306       goto out;
2307     }
2308   }
2309
2310   if (argc > 1) {
2311     /* Get the topic */
2312     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2313     if (!tmp) {
2314       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2315                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2316       goto out;
2317     }
2318
2319     if (strlen(tmp) > 256) {
2320       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2321                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2322       goto out;
2323     }
2324
2325     /* See whether the client is on channel and has rights to change topic */
2326     if (!silc_server_client_on_channel(client, channel, &chl)) {
2327       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2328                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2329       goto out;
2330     }
2331
2332     if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
2333         channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2334       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2335                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2336       goto out;
2337     }
2338
2339     /* Set the topic for channel */
2340     silc_free(channel->topic);
2341     channel->topic = strdup(tmp);
2342
2343     /* Send TOPIC_SET notify type to the network */
2344     if (!server->standalone)
2345       silc_server_send_notify_topic_set(server, server->router->connection,
2346                                         server->server_type == SILC_ROUTER ?
2347                                         TRUE : FALSE, channel, 
2348                                         client->id, SILC_ID_CLIENT,
2349                                         channel->topic);
2350
2351     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2352
2353     /* Send notify about topic change to all clients on the channel */
2354     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2355                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2356                                        idp->data, idp->len,
2357                                        channel->topic, strlen(channel->topic));
2358     silc_buffer_free(idp);
2359   }
2360
2361   /* Send the topic to client as reply packet */
2362   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2363   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2364                                                 SILC_STATUS_OK, 0, ident, 2, 
2365                                                 2, idp->data, idp->len,
2366                                                 3, channel->topic, 
2367                                                 channel->topic ? 
2368                                                 strlen(channel->topic) : 0);
2369   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2370                           0, packet->data, packet->len, FALSE);
2371
2372   silc_buffer_free(packet);
2373   silc_buffer_free(idp);
2374   silc_free(channel_id);
2375
2376  out:
2377   silc_server_command_free(cmd);
2378 }
2379
2380 /* Server side of INVITE command. Invites some client to join some channel. 
2381    This command is also used to manage the invite list of the channel. */
2382
2383 SILC_SERVER_CMD_FUNC(invite)
2384 {
2385   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2386   SilcServer server = cmd->server;
2387   SilcSocketConnection sock = cmd->sock, dest_sock;
2388   SilcChannelClientEntry chl;
2389   SilcClientEntry sender, dest;
2390   SilcClientID *dest_id = NULL;
2391   SilcChannelEntry channel;
2392   SilcChannelID *channel_id = NULL;
2393   SilcIDListData idata;
2394   SilcBuffer idp, idp2, packet;
2395   unsigned char *tmp, *add, *del;
2396   SilcUInt32 len;
2397   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2398
2399   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2400
2401   /* Get Channel ID */
2402   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2403   if (!tmp) {
2404     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2405                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2406     goto out;
2407   }
2408   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2409   if (!channel_id) {
2410     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2411                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2412     goto out;
2413   }
2414
2415   /* Get the channel entry */
2416   channel = silc_idlist_find_channel_by_id(server->local_list, 
2417                                            channel_id, NULL);
2418   if (!channel) {
2419     channel = silc_idlist_find_channel_by_id(server->global_list, 
2420                                              channel_id, NULL);
2421     if (!channel) {
2422       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2423                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2424       goto out;
2425     }
2426   }
2427
2428   /* Check whether the sender of this command is on the channel. */
2429   sender = (SilcClientEntry)sock->user_data;
2430   if (!silc_server_client_on_channel(sender, channel, &chl)) {
2431     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2432                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2433     goto out;
2434   }
2435
2436   /* Check whether the channel is invite-only channel. If yes then the
2437      sender of this command must be at least channel operator. */
2438   if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2439       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2440     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2441                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2442     goto out;
2443   }
2444
2445   /* Get destination client ID */
2446   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2447   if (tmp) {
2448     char invite[512];
2449     bool resolve;
2450
2451     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2452     if (!dest_id) {
2453       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2454                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2455       goto out;
2456     }
2457
2458     /* Get the client entry */
2459     dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2460     if (!dest) {
2461       if (server->server_type != SILC_SERVER || !resolve) {
2462         silc_server_command_send_status_reply(
2463                                         cmd, SILC_COMMAND_INVITE,
2464                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2465         goto out;
2466       }
2467       
2468       /* The client info is being resolved. Reprocess this packet after
2469          receiving the reply to the query. */
2470       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2471                                   server->cmd_ident,
2472                                   silc_server_command_invite, 
2473                                   silc_server_command_dup(cmd));
2474       cmd->pending = TRUE;
2475       silc_free(channel_id);
2476       silc_free(dest_id);
2477       goto out;
2478     }
2479
2480     /* Check whether the requested client is already on the channel. */
2481     if (silc_server_client_on_channel(dest, channel, NULL)) {
2482       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2483                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2484       goto out;
2485     }
2486     
2487     /* Get route to the client */
2488     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, 
2489                                              &idata, NULL);
2490     if (!dest_sock) {
2491       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2492                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2493       goto out;
2494     }
2495
2496     memset(invite, 0, sizeof(invite));
2497     strncat(invite, dest->nickname, strlen(dest->nickname));
2498     strncat(invite, "!", 1);
2499     strncat(invite, dest->username, strlen(dest->username));
2500     if (!strchr(dest->username, '@')) {
2501       strncat(invite, "@", 1);
2502       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2503     }
2504
2505     len = strlen(invite);
2506     if (!channel->invite_list)
2507       channel->invite_list = silc_calloc(len + 2, 
2508                                          sizeof(*channel->invite_list));
2509     else
2510       channel->invite_list = silc_realloc(channel->invite_list, 
2511                                           sizeof(*channel->invite_list) * 
2512                                           (len + 
2513                                            strlen(channel->invite_list) + 2));
2514     strncat(channel->invite_list, invite, len);
2515     strncat(channel->invite_list, ",", 1);
2516
2517     /* Send notify to the client that is invited to the channel */
2518     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2519     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2520     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2521                                  SILC_ID_CLIENT,
2522                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2523                                  idp->data, idp->len, 
2524                                  channel->channel_name, 
2525                                  strlen(channel->channel_name),
2526                                  idp2->data, idp2->len);
2527     silc_buffer_free(idp);
2528     silc_buffer_free(idp2);
2529   }
2530
2531   /* Add the client to the invite list of the channel */
2532   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2533   if (add) {
2534     if (!channel->invite_list)
2535       channel->invite_list = silc_calloc(len + 2, 
2536                                          sizeof(*channel->invite_list));
2537     else
2538       channel->invite_list = silc_realloc(channel->invite_list, 
2539                                           sizeof(*channel->invite_list) * 
2540                                           (len + 
2541                                            strlen(channel->invite_list) + 2));
2542     if (add[len - 1] == ',')
2543       add[len - 1] = '\0';
2544     
2545     strncat(channel->invite_list, add, len);
2546     strncat(channel->invite_list, ",", 1);
2547   }
2548
2549   /* Get the invite to be removed and remove it from the list */
2550   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2551   if (del && channel->invite_list) {
2552     char *start, *end, *n;
2553
2554     if (!strncmp(channel->invite_list, del, 
2555                  strlen(channel->invite_list) - 1)) {
2556       silc_free(channel->invite_list);
2557       channel->invite_list = NULL;
2558     } else {
2559       start = strstr(channel->invite_list, del);
2560       if (start && strlen(start) >= len) {
2561         end = start + len;
2562         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2563         strncat(n, channel->invite_list, start - channel->invite_list);
2564         strncat(n, end + 1, ((channel->invite_list + 
2565                               strlen(channel->invite_list)) - end) - 1);
2566         silc_free(channel->invite_list);
2567         channel->invite_list = n;
2568       }
2569     }
2570   }
2571
2572   /* Send notify to the primary router */
2573   if (!server->standalone)
2574     silc_server_send_notify_invite(server, server->router->connection,
2575                                    server->server_type == SILC_ROUTER ?
2576                                    TRUE : FALSE, channel,
2577                                    sender->id, add, del);
2578
2579   /* Send command reply */
2580   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2581
2582   if (add || del)
2583     packet = 
2584       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2585                                            SILC_STATUS_OK, 0, ident, 2,
2586                                            2, tmp, len,
2587                                            3, channel->invite_list,
2588                                            channel->invite_list ?
2589                                            strlen(channel->invite_list) : 0);
2590   else
2591     packet = 
2592       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2593                                            SILC_STATUS_OK, 0, ident, 1,
2594                                            2, tmp, len);
2595   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2596                           packet->data, packet->len, FALSE);
2597   silc_buffer_free(packet);
2598
2599  out:
2600   silc_free(dest_id);
2601   silc_free(channel_id);
2602   silc_server_command_free(cmd);
2603 }
2604
2605 typedef struct {
2606   SilcServer server;
2607   SilcSocketConnection sock;
2608   char *signoff;
2609 } *QuitInternal;
2610
2611 /* Quits connection to client. This gets called if client won't
2612    close the connection even when it has issued QUIT command. */
2613
2614 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2615 {
2616   QuitInternal q = (QuitInternal)context;
2617
2618   /* Free all client specific data, such as client entry and entires
2619      on channels this client may be on. */
2620   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2621                                TRUE, q->signoff);
2622   q->sock->user_data = NULL;
2623
2624   /* Close the connection on our side */
2625   silc_server_close_connection(q->server, q->sock);
2626
2627   silc_free(q->signoff);
2628   silc_free(q);
2629 }
2630
2631 /* Quits SILC session. This is the normal way to disconnect client. */
2632  
2633 SILC_SERVER_CMD_FUNC(quit)
2634 {
2635   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2636   SilcServer server = cmd->server;
2637   SilcSocketConnection sock = cmd->sock;
2638   QuitInternal q;
2639   unsigned char *tmp = NULL;
2640   SilcUInt32 len = 0;
2641
2642   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2643
2644   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2645     goto out;
2646
2647   /* Get message */
2648   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2649   if (len > 128)
2650     tmp = NULL;
2651
2652   q = silc_calloc(1, sizeof(*q));
2653   q->server = server;
2654   q->sock = sock;
2655   q->signoff = tmp ? strdup(tmp) : NULL;
2656
2657   /* We quit the connection with little timeout */
2658   silc_schedule_task_add(server->schedule, sock->sock,
2659                          silc_server_command_quit_cb, (void *)q,
2660                          0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2661
2662  out:
2663   silc_server_command_free(cmd);
2664 }
2665
2666 /* Server side of command KILL. This command is used by router operator
2667    to remove an client from the SILC Network temporarily. */
2668
2669 SILC_SERVER_CMD_FUNC(kill)
2670 {
2671   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2672   SilcServer server = cmd->server;
2673   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2674   SilcClientEntry remote_client;
2675   SilcClientID *client_id;
2676   unsigned char *tmp, *comment;
2677   SilcUInt32 tmp_len, tmp_len2;
2678   bool local;
2679
2680   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2681
2682   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2683     goto out;
2684
2685   /* KILL command works only on router */
2686   if (server->server_type != SILC_ROUTER) {
2687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2688                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2689     goto out;
2690   }
2691
2692   /* Check whether client has the permissions. */
2693   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2694     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2695                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2696     goto out;
2697   }
2698
2699   /* Get the client ID */
2700   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2701   if (!tmp) {
2702     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2703                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2704     goto out;
2705   }
2706   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2707   if (!client_id) {
2708     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2709                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2710     goto out;
2711   }
2712
2713   /* Get the client entry */
2714   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2715                                                 client_id, TRUE, NULL);
2716   local = TRUE;
2717   if (!remote_client) {
2718     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2719                                                   client_id, TRUE, NULL);
2720     local = FALSE;
2721     if (!remote_client) {
2722       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2723                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2724       goto out;
2725     }
2726   }
2727
2728   /* Get comment */
2729   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2730   if (tmp_len2 > 128)
2731     tmp_len2 = 128;
2732
2733   /* Send reply to the sender */
2734   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2735                                         SILC_STATUS_OK);
2736
2737   /* Now do the killing */
2738   silc_server_kill_client(server, remote_client, comment, client->id,
2739                           SILC_ID_CLIENT);
2740
2741  out:
2742   silc_server_command_free(cmd);
2743 }
2744
2745 /* Server side of command INFO. This sends information about us to 
2746    the client. If client requested specific server we will send the 
2747    command to that server. */
2748
2749 SILC_SERVER_CMD_FUNC(info)
2750 {
2751   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2752   SilcServer server = cmd->server;
2753   SilcBuffer packet, idp;
2754   unsigned char *tmp;
2755   SilcUInt32 tmp_len;
2756   char *dest_server, *server_info = NULL, *server_name;
2757   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2758   SilcServerEntry entry = NULL;
2759   SilcServerID *server_id = NULL;
2760
2761   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2762
2763   /* Get server name */
2764   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2765
2766   /* Get Server ID */
2767   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2768   if (tmp) {
2769     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2770     if (!server_id) {
2771       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2772                                             SILC_STATUS_ERR_NO_SERVER_ID);
2773       goto out;
2774     }
2775   }
2776
2777   if (server_id) {
2778     /* Check whether we have this server cached */
2779     entry = silc_idlist_find_server_by_id(server->local_list,
2780                                           server_id, TRUE, NULL);
2781     if (!entry) {
2782       entry = silc_idlist_find_server_by_id(server->global_list,
2783                                             server_id, TRUE, NULL);
2784       if (!entry && server->server_type != SILC_SERVER) {
2785         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2786                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2787         goto out;
2788       }
2789     }
2790   }
2791
2792   /* Some buggy servers has sent request to router about themselves. */
2793   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2794     goto out;
2795
2796   if ((!dest_server && !server_id && !entry) || (entry && 
2797                                                  entry == server->id_entry) ||
2798       (dest_server && !cmd->pending && 
2799        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2800     /* Send our reply */
2801     char info_string[256];
2802
2803     memset(info_string, 0, sizeof(info_string));
2804     snprintf(info_string, sizeof(info_string), 
2805              "location: %s server: %s admin: %s <%s>",
2806              server->config->server_info->location,
2807              server->config->server_info->server_type,
2808              server->config->server_info->admin,
2809              server->config->server_info->email);
2810
2811     server_info = info_string;
2812     entry = server->id_entry;
2813   } else {
2814     /* Check whether we have this server cached */
2815     if (!entry && dest_server) {
2816       entry = silc_idlist_find_server_by_name(server->global_list,
2817                                               dest_server, TRUE, NULL);
2818       if (!entry) {
2819         entry = silc_idlist_find_server_by_name(server->local_list,
2820                                                 dest_server, TRUE, NULL);
2821       }
2822     }
2823
2824     if (!cmd->pending &&
2825         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2826       /* Send to the server */
2827       SilcBuffer tmpbuf;
2828       SilcUInt16 old_ident;
2829
2830       old_ident = silc_command_get_ident(cmd->payload);
2831       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2832       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2833
2834       silc_server_packet_send(server, entry->connection,
2835                               SILC_PACKET_COMMAND, cmd->packet->flags,
2836                               tmpbuf->data, tmpbuf->len, TRUE);
2837
2838       /* Reprocess this packet after received reply from router */
2839       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2840                                   silc_command_get_ident(cmd->payload),
2841                                   silc_server_command_info,
2842                                   silc_server_command_dup(cmd));
2843       cmd->pending = TRUE;
2844       silc_command_set_ident(cmd->payload, old_ident);
2845       silc_buffer_free(tmpbuf);
2846       goto out;
2847     }
2848
2849     if (!entry && !cmd->pending && !server->standalone) {
2850       /* Send to the primary router */
2851       SilcBuffer tmpbuf;
2852       SilcUInt16 old_ident;
2853
2854       old_ident = silc_command_get_ident(cmd->payload);
2855       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2856       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2857
2858       silc_server_packet_send(server, server->router->connection,
2859                               SILC_PACKET_COMMAND, cmd->packet->flags,
2860                               tmpbuf->data, tmpbuf->len, TRUE);
2861
2862       /* Reprocess this packet after received reply from router */
2863       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2864                                   silc_command_get_ident(cmd->payload),
2865                                   silc_server_command_info,
2866                                   silc_server_command_dup(cmd));
2867       cmd->pending = TRUE;
2868       silc_command_set_ident(cmd->payload, old_ident);
2869       silc_buffer_free(tmpbuf);
2870       goto out;
2871     }
2872   }
2873
2874   silc_free(server_id);
2875
2876   if (!entry) {
2877     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2878                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2879     goto out;
2880   }
2881
2882   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2883   if (!server_info)
2884     server_info = entry->server_info;
2885   server_name = entry->server_name;
2886
2887   /* Send the reply */
2888   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2889                                                 SILC_STATUS_OK, 0, ident, 3,
2890                                                 2, idp->data, idp->len,
2891                                                 3, server_name, 
2892                                                 strlen(server_name),
2893                                                 4, server_info, 
2894                                                 server_info ? 
2895                                                 strlen(server_info) : 0);
2896   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2897                           packet->data, packet->len, FALSE);
2898     
2899   silc_buffer_free(packet);
2900   silc_buffer_free(idp);
2901
2902  out:
2903   silc_server_command_free(cmd);
2904 }
2905
2906 /* Server side of command PING. This just replies to the ping. */
2907
2908 SILC_SERVER_CMD_FUNC(ping)
2909 {
2910   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2911   SilcServer server = cmd->server;
2912   SilcServerID *id;
2913   SilcUInt32 len;
2914   unsigned char *tmp;
2915
2916   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2917
2918   /* Get Server ID */
2919   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2920   if (!tmp) {
2921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2922                                           SILC_STATUS_ERR_NO_SERVER_ID);
2923     goto out;
2924   }
2925   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2926   if (!id)
2927     goto out;
2928
2929   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2930     /* Send our reply */
2931     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2932                                           SILC_STATUS_OK);
2933   } else {
2934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2935                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2936     goto out;
2937   }
2938
2939   silc_free(id);
2940
2941  out:
2942   silc_server_command_free(cmd);
2943 }
2944
2945 /* Server side of command STATS. */
2946
2947 SILC_SERVER_CMD_FUNC(stats)
2948 {
2949   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2950   SilcServer server = cmd->server;
2951   SilcServerID *server_id;
2952   unsigned char *tmp;
2953   SilcUInt32 tmp_len;
2954   SilcBuffer packet, stats;
2955   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2956   SilcUInt32 uptime;
2957
2958   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
2959
2960   /* Get Server ID */
2961   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2962   if (!tmp) {
2963     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2964                                           SILC_STATUS_ERR_NO_SERVER_ID);
2965     goto out;
2966   }
2967   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2968   if (!server_id)
2969     goto out;
2970
2971   /* The ID must be ours */
2972   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
2973     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2974                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2975     silc_free(server_id);
2976     goto out;
2977   }
2978   silc_free(server_id);
2979
2980   /* If we are router then just send everything we got. If we are normal
2981      server then we'll send this to our router to get all the latest
2982      statistical information. */
2983   if (!cmd->pending && server->server_type != SILC_ROUTER && 
2984       !server->standalone) {
2985     /* Send request to our router */
2986     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
2987                                             SILC_ID_SERVER);
2988     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
2989                                             ++server->cmd_ident, 1,
2990                                             1, idp->data, idp->len);
2991     silc_server_packet_send(server, server->router->connection,
2992                             SILC_PACKET_COMMAND, 0, packet->data,
2993                             packet->len, FALSE);
2994
2995     /* Reprocess this packet after received reply from router */
2996     silc_server_command_pending(server, SILC_COMMAND_STATS, 
2997                                 server->cmd_ident,
2998                                 silc_server_command_stats,
2999                                 silc_server_command_dup(cmd));
3000     cmd->pending = TRUE;
3001     silc_buffer_free(packet);
3002     silc_buffer_free(idp);
3003     goto out;
3004   }
3005
3006   /* Send our reply to sender */
3007   uptime = time(NULL) - server->starttime;
3008
3009   stats = silc_buffer_alloc_size(60);
3010   silc_buffer_format(stats,
3011                      SILC_STR_UI_INT(server->starttime),
3012                      SILC_STR_UI_INT(uptime),
3013                      SILC_STR_UI_INT(server->stat.my_clients),
3014                      SILC_STR_UI_INT(server->stat.my_channels),
3015                      SILC_STR_UI_INT(server->stat.my_server_ops),
3016                      SILC_STR_UI_INT(server->stat.my_router_ops),
3017                      SILC_STR_UI_INT(server->stat.cell_clients),
3018                      SILC_STR_UI_INT(server->stat.cell_channels),
3019                      SILC_STR_UI_INT(server->stat.cell_servers),
3020                      SILC_STR_UI_INT(server->stat.clients),
3021                      SILC_STR_UI_INT(server->stat.channels),
3022                      SILC_STR_UI_INT(server->stat.servers),
3023                      SILC_STR_UI_INT(server->stat.routers),
3024                      SILC_STR_UI_INT(server->stat.server_ops),
3025                      SILC_STR_UI_INT(server->stat.router_ops),
3026                      SILC_STR_END);
3027
3028   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
3029                                                 SILC_STATUS_OK, 0, ident, 2,
3030                                                 2, tmp, tmp_len,
3031                                                 3, stats->data, stats->len);
3032   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3033                           0, packet->data, packet->len, FALSE);
3034   silc_buffer_free(packet);
3035   silc_buffer_free(stats);
3036
3037  out:
3038   silc_server_command_free(cmd);
3039 }
3040
3041 /* Internal routine to join channel. The channel sent to this function
3042    has been either created or resolved from ID lists. This joins the sent
3043    client to the channel. */
3044
3045 static void silc_server_command_join_channel(SilcServer server, 
3046                                              SilcServerCommandContext cmd,
3047                                              SilcChannelEntry channel,
3048                                              SilcClientID *client_id,
3049                                              bool created,
3050                                              bool create_key,
3051                                              SilcUInt32 umode,
3052                                              const unsigned char *auth,
3053                                              SilcUInt32 auth_len)
3054 {
3055   SilcSocketConnection sock = cmd->sock;
3056   unsigned char *tmp;
3057   SilcUInt32 tmp_len, user_count;
3058   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3059   SilcClientEntry client;
3060   SilcChannelClientEntry chl;
3061   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3062   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3063   char check[512], check2[512];
3064   bool founder = FALSE;
3065   bool resolve;
3066
3067   SILC_LOG_DEBUG(("Start"));
3068
3069   if (!channel)
3070     return;
3071
3072   /* Get the client entry */
3073   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3074     client = (SilcClientEntry)sock->user_data;
3075   } else {
3076     client = silc_server_get_client_resolve(server, client_id, FALSE, 
3077                                             &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 or is server */
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_NOT_ON_CHANNEL);
5112       goto out;
5113     }
5114   }
5115
5116   /* Get the users list */
5117   silc_server_get_users_on_channel(server, channel, &client_id_list,
5118                                    &client_mode_list, &list_count);
5119
5120   /* List count */
5121   SILC_PUT32_MSB(list_count, lc);
5122
5123   /* Send reply */
5124   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5125   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5126                                                 SILC_STATUS_OK, 0, ident, 4,
5127                                                 2, idp->data, idp->len,
5128                                                 3, lc, 4,
5129                                                 4, client_id_list->data,
5130                                                 client_id_list->len,
5131                                                 5, client_mode_list->data,
5132                                                 client_mode_list->len);
5133   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5134                           packet->data, packet->len, FALSE);
5135     
5136   silc_buffer_free(idp);
5137   silc_buffer_free(packet);
5138   silc_buffer_free(client_id_list);
5139   silc_buffer_free(client_mode_list);
5140   silc_free(id);
5141
5142  out:
5143   silc_server_command_free(cmd);
5144 }
5145
5146 /* Server side of command GETKEY. This fetches the client's public key
5147    from the server where to the client is connected. */
5148
5149 SILC_SERVER_CMD_FUNC(getkey)
5150 {
5151   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5152   SilcServer server = cmd->server;
5153   SilcBuffer packet;
5154   SilcClientEntry client;
5155   SilcServerEntry server_entry;
5156   SilcClientID *client_id = NULL;
5157   SilcServerID *server_id = NULL;
5158   SilcIDPayload idp = NULL;
5159   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5160   unsigned char *tmp, *pkdata;
5161   SilcUInt32 tmp_len, pklen;
5162   SilcBuffer pk = NULL;
5163   SilcIdType id_type;
5164   SilcPublicKey public_key;
5165
5166   SILC_LOG_DEBUG(("Start"));
5167
5168   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5169   if (!tmp) {
5170     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5171                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5172     goto out;
5173   }
5174   idp = silc_id_payload_parse(tmp, tmp_len);
5175   if (!idp) {
5176     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5177                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5178     goto out;
5179   }
5180
5181   id_type = silc_id_payload_get_type(idp);
5182   if (id_type == SILC_ID_CLIENT) {
5183     client_id = silc_id_payload_get_id(idp);
5184
5185     /* If the client is not found from local list there is no chance it
5186        would be locally connected client so send the command further. */
5187     client = silc_idlist_find_client_by_id(server->local_list, 
5188                                            client_id, TRUE, NULL);
5189     if (!client)
5190       client = silc_idlist_find_client_by_id(server->global_list, 
5191                                              client_id, TRUE, NULL);
5192     
5193     if ((!client && !cmd->pending && !server->standalone) ||
5194         (client && !client->connection && !cmd->pending &&
5195          !(client->mode & SILC_UMODE_DETACHED)) ||
5196         (client && !client->data.public_key && !cmd->pending)) {
5197       SilcBuffer tmpbuf;
5198       SilcUInt16 old_ident;
5199       SilcSocketConnection dest_sock;
5200       
5201       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5202                                                client_id, NULL, NULL);
5203       if (!dest_sock)
5204         goto out;
5205       
5206       old_ident = silc_command_get_ident(cmd->payload);
5207       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5208       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5209       
5210       silc_server_packet_send(server, dest_sock,
5211                               SILC_PACKET_COMMAND, cmd->packet->flags,
5212                               tmpbuf->data, tmpbuf->len, TRUE);
5213       
5214       /* Reprocess this packet after received reply from router */
5215       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5216                                   silc_command_get_ident(cmd->payload),
5217                                   silc_server_command_getkey,
5218                                   silc_server_command_dup(cmd));
5219       cmd->pending = TRUE;
5220       silc_command_set_ident(cmd->payload, old_ident);
5221       silc_buffer_free(tmpbuf);
5222       goto out;
5223     }
5224
5225     if (!client) {
5226       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5227                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5228       goto out;
5229     }
5230
5231     /* The client is locally connected, just get the public key and
5232        send it back. If they key does not exist then do not send it, 
5233        send just OK reply */
5234     public_key = client->data.public_key;
5235     if (!public_key) {
5236       pkdata = NULL;
5237       pklen = 0;
5238     } else {
5239       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5240       pk = silc_buffer_alloc(4 + tmp_len);
5241       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5242       silc_buffer_format(pk,
5243                          SILC_STR_UI_SHORT(tmp_len),
5244                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5245                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5246                          SILC_STR_END);
5247       silc_free(tmp);
5248       pkdata = pk->data;
5249       pklen = pk->len;
5250     }
5251   } else if (id_type == SILC_ID_SERVER) {
5252     server_id = silc_id_payload_get_id(idp);
5253
5254     /* If the server is not found from local list there is no chance it
5255        would be locally connected server so send the command further. */
5256     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5257                                                  server_id, TRUE, NULL);
5258     if (!server_entry)
5259       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5260                                                    server_id, TRUE, NULL);
5261     
5262     if (server_entry != server->id_entry &&
5263         ((!server_entry && !cmd->pending && !server->standalone) ||
5264          (server_entry && !server_entry->connection && !cmd->pending &&
5265           !server->standalone) ||
5266          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5267           !server->standalone))) {
5268       SilcBuffer tmpbuf;
5269       SilcUInt16 old_ident;
5270       
5271       old_ident = silc_command_get_ident(cmd->payload);
5272       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5273       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5274       
5275       silc_server_packet_send(server, server->router->connection,
5276                               SILC_PACKET_COMMAND, cmd->packet->flags,
5277                               tmpbuf->data, tmpbuf->len, TRUE);
5278       
5279       /* Reprocess this packet after received reply from router */
5280       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5281                                   silc_command_get_ident(cmd->payload),
5282                                   silc_server_command_getkey,
5283                                   silc_server_command_dup(cmd));
5284       cmd->pending = TRUE;
5285       silc_command_set_ident(cmd->payload, old_ident);
5286       silc_buffer_free(tmpbuf);
5287       goto out;
5288     }
5289
5290     if (!server_entry) {
5291       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5292                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5293       goto out;
5294     }
5295
5296     /* If they key does not exist then do not send it, send just OK reply */
5297     public_key = (!server_entry->data.public_key ? 
5298                   (server_entry == server->id_entry ? server->public_key :
5299                    NULL) : server_entry->data.public_key);
5300     if (!public_key) {
5301       pkdata = NULL;
5302       pklen = 0;
5303     } else {
5304       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5305       pk = silc_buffer_alloc(4 + tmp_len);
5306       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5307       silc_buffer_format(pk,
5308                          SILC_STR_UI_SHORT(tmp_len),
5309                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5310                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5311                          SILC_STR_END);
5312       silc_free(tmp);
5313       pkdata = pk->data;
5314       pklen = pk->len;
5315     }
5316   } else {
5317     goto out;
5318   }
5319
5320   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5321   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5322                                                 SILC_STATUS_OK, 0, ident, 
5323                                                 pkdata ? 2 : 1,
5324                                                 2, tmp, tmp_len,
5325                                                 3, pkdata, pklen);
5326   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5327                           packet->data, packet->len, FALSE);
5328   silc_buffer_free(packet);
5329
5330   if (pk)
5331     silc_buffer_free(pk);
5332
5333  out:
5334   if (idp)
5335     silc_id_payload_free(idp);
5336   silc_free(client_id);
5337   silc_free(server_id);
5338   silc_server_command_free(cmd);
5339 }
5340
5341
5342 /* Private range commands, specific to this implementation */
5343
5344 /* Server side command of CONNECT. Connects us to the specified remote
5345    server or router. */
5346
5347 SILC_SERVER_CMD_FUNC(connect)
5348 {
5349   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5350   SilcServer server = cmd->server;
5351   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5352   unsigned char *tmp, *host;
5353   SilcUInt32 tmp_len;
5354   SilcUInt32 port = SILC_PORT;
5355
5356   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5357
5358   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5359     goto out;
5360
5361   /* Check whether client has the permissions. */
5362   if (client->mode == SILC_UMODE_NONE) {
5363     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5364                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5365     goto out;
5366   }
5367
5368   if (server->server_type == SILC_ROUTER && 
5369       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5371                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
5372     goto out;
5373   }
5374
5375   /* Get the remote server */
5376   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5377   if (!host) {
5378     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5379                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5380     goto out;
5381   }
5382
5383   /* Get port */
5384   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5385   if (tmp)
5386     SILC_GET32_MSB(port, tmp);
5387
5388   /* Create the connection. It is done with timeout and is async. */
5389   silc_server_create_connection(server, host, port);
5390
5391   /* Send reply to the sender */
5392   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5393                                         SILC_STATUS_OK);
5394
5395  out:
5396   silc_server_command_free(cmd);
5397 }
5398
5399 /* Server side command of CLOSE. Closes connection to a specified server. */
5400  
5401 SILC_SERVER_CMD_FUNC(close)
5402 {
5403   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5404   SilcServer server = cmd->server;
5405   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5406   SilcServerEntry server_entry;
5407   SilcSocketConnection sock;
5408   unsigned char *tmp;
5409   SilcUInt32 tmp_len;
5410   unsigned char *name;
5411   SilcUInt32 port = SILC_PORT;
5412
5413   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5414
5415   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5416     goto out;
5417
5418   /* Check whether client has the permissions. */
5419   if (client->mode == SILC_UMODE_NONE) {
5420     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5421                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5422     goto out;
5423   }
5424
5425   /* Get the remote server */
5426   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5427   if (!name) {
5428     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5429                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5430     goto out;
5431   }
5432
5433   /* Get port */
5434   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5435   if (tmp)
5436     SILC_GET32_MSB(port, tmp);
5437
5438   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5439                                                  name, port, FALSE, NULL);
5440   if (!server_entry)
5441     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5442                                                    name, port, FALSE, NULL);
5443   if (!server_entry) {
5444     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5445                                           SILC_STATUS_ERR_NO_SERVER_ID);
5446     goto out;
5447   }
5448
5449   /* Send reply to the sender */
5450   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5451                                         SILC_STATUS_OK);
5452
5453   /* Close the connection to the server */
5454   sock = (SilcSocketConnection)server_entry->connection;
5455
5456   /* If we shutdown primary router connection manually then don't trigger
5457      any reconnect or backup router connections, by setting the router
5458      to NULL here. */
5459   if (server->router == server_entry) {
5460     server->id_entry->router = NULL;
5461     server->router = NULL;
5462     server->standalone = TRUE;
5463   }
5464   silc_server_free_sock_user_data(server, sock, NULL);
5465   silc_server_close_connection(server, sock);
5466   
5467  out:
5468   silc_server_command_free(cmd);
5469 }
5470
5471 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5472    active connections. */
5473  
5474 SILC_SERVER_CMD_FUNC(shutdown)
5475 {
5476   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5477   SilcServer server = cmd->server;
5478   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5479
5480   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5481
5482   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5483     goto out;
5484
5485   /* Check whether client has the permission. */
5486   if (client->mode == SILC_UMODE_NONE) {
5487     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5488                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5489     goto out;
5490   }
5491
5492   /* Send reply to the sender */
5493   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5494                                         SILC_STATUS_OK);
5495
5496   /* Then, gracefully, or not, bring the server down. */
5497   silc_server_stop(server);
5498   exit(0);
5499
5500  out:
5501   silc_server_command_free(cmd);
5502 }