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(silcoper, SILCOPER,
70                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
71   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
72   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
73   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
74
75   SILC_SERVER_CMD(connect, PRIV_CONNECT, 
76                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
77   SILC_SERVER_CMD(close, PRIV_CLOSE,
78                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
79   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
80                   SILC_CF_OPER),
81
82   { NULL, 0 },
83 };
84
85 /* Performs several checks to the command. It first checks whether this
86    command was called as pending command callback. If it was then it checks
87    whether error occurred in the command reply where the pending command
88    callback was called. 
89
90    It also checks that the requested command includes correct amount
91    of arguments. */
92 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                 \
93 do {                                                                          \
94   SilcUInt32 _argc;                                                                   \
95                                                                               \
96   SILC_LOG_DEBUG(("Start"));                                                  \
97                                                                               \
98   if (silc_server_command_pending_error_check(cmd, context2, command)) {      \
99     silc_server_command_free(cmd);                                            \
100     return;                                                                   \
101   }                                                                           \
102                                                                               \
103   _argc = silc_argument_get_arg_num(cmd->args);                               \
104   if (_argc < min) {                                                          \
105     silc_server_command_send_status_reply(cmd, command,                       \
106                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
107     silc_server_command_free(cmd);                                            \
108     return;                                                                   \
109   }                                                                           \
110   if (_argc > max) {                                                          \
111     silc_server_command_send_status_reply(cmd, command,                       \
112                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
113     silc_server_command_free(cmd);                                            \
114     return;                                                                   \
115   }                                                                           \
116 } while(0)
117
118 /* Returns TRUE if the connection is registered. Unregistered connections
119    usually cannot send commands hence the check. */
120
121 static int silc_server_is_registered(SilcServer server,
122                                      SilcSocketConnection sock,
123                                      SilcServerCommandContext cmd,
124                                      SilcCommand command)
125 {
126   SilcIDListData idata = (SilcIDListData)sock->user_data;
127
128   if (!idata)
129     return FALSE;
130
131   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
132     return TRUE;
133
134   silc_server_command_send_status_reply(cmd, command,
135                                         SILC_STATUS_ERR_NOT_REGISTERED);
136   return FALSE;
137 }
138
139 /* Internal context to hold data when executed command with timeout. */
140 typedef struct {
141   SilcServerCommandContext ctx;
142   SilcServerCommand *cmd;
143 } *SilcServerCommandTimeout;
144
145 /* Timeout callback to process commands with timeout for client. Client's
146    commands are always executed with timeout. */
147
148 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
149 {
150   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
151   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
152
153   if (!client) {
154     silc_server_command_free(timeout->ctx);
155     silc_free(timeout);
156   }
157
158   /* Update access time */
159   client->last_command = time(NULL);
160
161   if (!(timeout->cmd->flags & SILC_CF_REG))
162     timeout->cmd->cb(timeout->ctx, NULL);
163   else if (silc_server_is_registered(timeout->ctx->server, 
164                                      timeout->ctx->sock, 
165                                      timeout->ctx, 
166                                      timeout->cmd->cmd))
167     timeout->cmd->cb(timeout->ctx, NULL);
168   else
169     silc_server_command_free(timeout->ctx);
170
171   silc_free(timeout);
172 }
173
174 /* Processes received command packet. */
175
176 void silc_server_command_process(SilcServer server,
177                                  SilcSocketConnection sock,
178                                  SilcPacketContext *packet)
179 {
180   SilcServerCommandContext ctx;
181   SilcServerCommand *cmd;
182   SilcCommand command;
183
184   /* Allocate command context. This must be free'd by the
185      command routine receiving it. */
186   ctx = silc_server_command_alloc();
187   ctx->server = server;
188   ctx->sock = silc_socket_dup(sock);
189   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
190   
191   /* Parse the command payload in the packet */
192   ctx->payload = silc_command_payload_parse(packet->buffer->data,
193                                             packet->buffer->len);
194   if (!ctx->payload) {
195     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
196     silc_buffer_free(packet->buffer);
197     silc_packet_context_free(packet);
198     silc_socket_free(ctx->sock);
199     silc_free(ctx);
200     return;
201   }
202   ctx->args = silc_command_get_args(ctx->payload);
203
204   /* Get the command */
205   command = silc_command_get(ctx->payload);
206   for (cmd = silc_command_list; cmd->cb; cmd++)
207     if (cmd->cmd == command)
208       break;
209
210   if (!cmd || !cmd->cb) {
211     silc_server_command_send_status_reply(ctx, command,
212                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
213     silc_server_command_free(ctx);
214     return;
215   }
216
217   /* Execute client's commands always with timeout.  Normally they are
218      executed with zero (0) timeout but if client is sending command more
219      frequently than once in 2 seconds, then the timeout may be 0 to 2
220      seconds. */
221   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
222     SilcClientEntry client = (SilcClientEntry)sock->user_data;
223     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
224     int fast;
225
226     timeout->ctx = ctx;
227     timeout->cmd = cmd;
228
229     if (client->last_command && (time(NULL) - client->last_command) < 2) {
230       client->fast_command++;
231       fast = FALSE;
232     } else {
233       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
234                               client->fast_command--);
235       fast = TRUE;
236     }
237
238     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
239                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
240       silc_schedule_task_add(server->schedule, sock->sock, 
241                          silc_server_command_process_timeout,
242                          (void *)timeout, 
243                          2 - (time(NULL) - client->last_command), 0,
244                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
245     else
246       silc_schedule_task_add(server->schedule, sock->sock, 
247                          silc_server_command_process_timeout,
248                          (void *)timeout, 0, 1,
249                          SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
250     return;
251   }
252
253   /* Execute for server */
254
255   if (!(cmd->flags & SILC_CF_REG))
256     cmd->cb(ctx, NULL);
257   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
258     cmd->cb(ctx, NULL);
259   else
260     silc_server_command_free(ctx);
261 }
262
263 /* Allocate Command Context */
264
265 SilcServerCommandContext silc_server_command_alloc()
266 {
267   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
268   ctx->users++;
269   return ctx;
270 }
271
272 /* Free's the command context allocated before executing the command */
273
274 void silc_server_command_free(SilcServerCommandContext ctx)
275 {
276   ctx->users--;
277   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
278                   ctx->users));
279   if (ctx->users < 1) {
280     if (ctx->payload)
281       silc_command_payload_free(ctx->payload);
282     if (ctx->packet)
283       silc_packet_context_free(ctx->packet);
284     if (ctx->sock)
285       silc_socket_free(ctx->sock); /* Decrease reference counter */
286     silc_free(ctx);
287   }
288 }
289
290 /* Duplicate Command Context by adding reference counter. The context won't
291    be free'd untill it hits zero. */
292
293 SilcServerCommandContext 
294 silc_server_command_dup(SilcServerCommandContext ctx)
295 {
296   ctx->users++;
297   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
298                   ctx->users));
299   return ctx;
300 }
301
302 /* Add new pending command to be executed when reply to a command has been
303    received. The `reply_cmd' is the command that will call the `callback'
304    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
305    to match any command with the `ident'.  If `ident' is non-zero
306    the `callback' will be executed when received reply with command
307    identifier `ident'. If there already exists pending command for the
308    specified command, ident, callback and context this function has no
309    effect. */
310
311 bool silc_server_command_pending(SilcServer server,
312                                  SilcCommand reply_cmd,
313                                  SilcUInt16 ident,
314                                  SilcCommandCb callback,
315                                  void *context)
316 {
317   SilcServerCommandPending *reply;
318
319   /* Check whether identical pending already exists for same command,
320      ident, callback and callback context. If it does then it would be
321      error to register it again. */
322   silc_dlist_start(server->pending_commands);
323   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
324     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
325         reply->callback == callback && reply->context == context)
326       return FALSE;
327   }
328
329   reply = silc_calloc(1, sizeof(*reply));
330   reply->reply_cmd = reply_cmd;
331   reply->ident = ident;
332   reply->context = context;
333   reply->callback = callback;
334   silc_dlist_add(server->pending_commands, reply);
335
336   return TRUE;
337 }
338
339 /* Deletes pending command by reply command type. */
340
341 void silc_server_command_pending_del(SilcServer server,
342                                      SilcCommand reply_cmd,
343                                      SilcUInt16 ident)
344 {
345   SilcServerCommandPending *r;
346
347   silc_dlist_start(server->pending_commands);
348   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
349     if (r->reply_cmd == reply_cmd && r->ident == ident) {
350       silc_dlist_del(server->pending_commands, r);
351       break;
352     }
353   }
354 }
355
356 /* Checks for pending commands and marks callbacks to be called from
357    the command reply function. Returns TRUE if there were pending command. */
358
359 SilcServerCommandPendingCallbacks
360 silc_server_command_pending_check(SilcServer server,
361                                   SilcServerCommandReplyContext ctx,
362                                   SilcCommand command, 
363                                   SilcUInt16 ident,
364                                   SilcUInt32 *callbacks_count)
365 {
366   SilcServerCommandPending *r;
367   SilcServerCommandPendingCallbacks callbacks = NULL;
368   int i = 0;
369
370   silc_dlist_start(server->pending_commands);
371   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
372     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
373         && r->ident == ident) {
374       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
375       callbacks[i].context = r->context;
376       callbacks[i].callback = r->callback;
377       ctx->ident = ident;
378       i++;
379     }
380   }
381
382   *callbacks_count = i;
383   return callbacks;
384 }
385
386 /* Sends simple status message as command reply packet */
387
388 static void 
389 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
390                                       SilcCommand command,
391                                       SilcCommandStatus status)
392 {
393   SilcBuffer buffer;
394
395   SILC_LOG_DEBUG(("Sending command status %d", status));
396
397   buffer = 
398     silc_command_reply_payload_encode_va(command, status, 0,
399                                          silc_command_get_ident(cmd->payload),
400                                          0);
401   silc_server_packet_send(cmd->server, cmd->sock,
402                           SILC_PACKET_COMMAND_REPLY, 0, 
403                           buffer->data, buffer->len, FALSE);
404   silc_buffer_free(buffer);
405 }
406
407 /* Sends command status reply with one extra argument. The argument
408    type must be sent as argument. */
409
410 static void 
411 silc_server_command_send_status_data(SilcServerCommandContext cmd,
412                                      SilcCommand command,
413                                      SilcCommandStatus status,
414                                      SilcUInt32 arg_type,
415                                      const unsigned char *arg,
416                                      SilcUInt32 arg_len)
417 {
418   SilcBuffer buffer;
419
420   SILC_LOG_DEBUG(("Sending command status %d", status));
421
422   buffer = 
423     silc_command_reply_payload_encode_va(command, status, 0,
424                                          silc_command_get_ident(cmd->payload),
425                                          1, arg_type, arg, arg_len);
426   silc_server_packet_send(cmd->server, cmd->sock,
427                           SILC_PACKET_COMMAND_REPLY, 0, 
428                           buffer->data, buffer->len, FALSE);
429   silc_buffer_free(buffer);
430 }
431
432 /* This function can be called to check whether in the command reply
433    an error occurred. This function has no effect if this is called
434    when the command function was not called as pending command callback. 
435    This returns TRUE if error had occurred. */
436
437 static bool
438 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
439                                         SilcServerCommandReplyContext cmdr,
440                                         SilcCommand command)
441 {
442   if (!cmd->pending || !cmdr)
443     return FALSE;
444
445   if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
446     SilcBuffer buffer;
447
448     /* Send the same command reply payload */
449     silc_command_set_ident(cmdr->payload, 
450                            silc_command_get_ident(cmd->payload));
451     buffer = silc_command_payload_encode_payload(cmdr->payload);
452     silc_server_packet_send(cmd->server, cmd->sock,
453                             SILC_PACKET_COMMAND_REPLY, 0, 
454                             buffer->data, buffer->len, FALSE);
455     silc_buffer_free(buffer);
456     return TRUE;
457   }
458
459   return FALSE;
460 }
461
462 /******************************************************************************
463
464                               WHOIS Functions
465
466 ******************************************************************************/
467
468 static int
469 silc_server_command_whois_parse(SilcServerCommandContext cmd,
470                                 SilcClientID ***client_id,
471                                 SilcUInt32 *client_id_count,
472                                 char **nickname,
473                                 char **server_name,
474                                 int *count,
475                                 SilcCommand command)
476 {
477   unsigned char *tmp;
478   SilcUInt32 len;
479   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
480   int i, k;
481
482   /* If client ID is in the command it must be used instead of nickname */
483   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
484   if (!tmp) {
485     /* No ID, get the nickname@server string and parse it. */
486     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
487     if (tmp) {
488       silc_parse_userfqdn(tmp, nickname, server_name);
489     } else {
490       silc_server_command_send_status_reply(cmd, command,
491                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
492       return FALSE;
493     }
494   } else {
495     /* Command includes ID, we must use that.  Also check whether the command
496        has more than one ID set - take them all. */
497
498     *client_id = silc_calloc(1, sizeof(**client_id));
499     (*client_id)[0] = silc_id_payload_parse_id(tmp, len, NULL);
500     if ((*client_id)[0] == NULL) {
501       silc_free(*client_id);
502       silc_server_command_send_status_reply(cmd, command,
503                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
504       return FALSE;
505     }
506     *client_id_count = 1;
507
508     /* Take all ID's from the command packet */
509     if (argc > 1) {
510       for (k = 1, i = 1; i < argc; i++) {
511         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
512         if (tmp) {
513           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
514                                     (*client_id_count + 1));
515           (*client_id)[k] = silc_id_payload_parse_id(tmp, len, NULL);
516           if ((*client_id)[k] == NULL) {
517             /* Cleanup all and fail */
518             for (i = 0; i < *client_id_count; i++)
519               silc_free((*client_id)[i]);
520             silc_free(*client_id);
521             silc_server_command_send_status_reply(
522                                          cmd, command,
523                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
524             return FALSE;
525           }
526           (*client_id_count)++;
527           k++;
528         }
529       }
530     }
531   }
532
533   /* Get the max count of reply messages allowed */
534   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
535   if (tmp)
536     *count = atoi(tmp);
537   else
538     *count = 0;
539
540   return TRUE;
541 }
542
543 /* Resolve context used by both WHOIS and IDENTIFY commands */
544 typedef struct {
545   SilcServerEntry router;
546   SilcUInt16 ident;
547   unsigned char **res_argv;
548   SilcUInt32 *res_argv_lens;
549   SilcUInt32 *res_argv_types;
550   SilcUInt32 res_argc;
551 } *SilcServerResolveContext;
552
553 static bool
554 silc_server_command_whois_check(SilcServerCommandContext cmd,
555                                 SilcClientEntry *clients,
556                                 SilcUInt32 clients_count)
557 {
558   SilcServer server = cmd->server;
559   SilcClientEntry entry;
560   SilcServerResolveContext resolve = NULL, r = NULL;
561   SilcUInt32 resolve_count = 0;
562   int i, k;
563   bool no_res = TRUE;
564
565   SILC_LOG_DEBUG(("Start"));
566
567   for (i = 0; i < clients_count; i++) {
568     entry = clients[i];
569     if (!entry)
570       continue;
571
572     if ((entry->nickname && entry->username && entry->userinfo) ||
573         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
574       if (!entry->router)
575         continue;
576
577       /* If we are normal server, and we've not resolved this client from
578          router and it is global client, we'll check whether it is on some
579          channel.  If not then we cannot be sure about its validity, and
580          we'll resolve it from router. */
581       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
582           entry->connection || silc_hash_table_count(entry->channels))
583         continue;
584     }
585
586     /* We need to resolve this entry since it is not complete */
587
588     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
589       /* The entry is being resolved (and we are not the resolver) so attach
590          to the command reply and we're done with this one. */
591       silc_server_command_pending(server, SILC_COMMAND_NONE, 
592                                   entry->resolve_cmd_ident,
593                                   silc_server_command_whois,
594                                   silc_server_command_dup(cmd));
595       no_res = FALSE;
596     } else {
597       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
598         /* We've resolved this and it still is not ready.  We'll return
599            and are that this will be handled again after it is resolved. */
600         for (i = 0; i < resolve_count; i++) {
601           for (k = 0; k < r->res_argc; k++)
602             silc_free(r->res_argv[k]);
603           silc_free(r->res_argv);
604           silc_free(r->res_argv_lens);
605           silc_free(r->res_argv_types);
606         }
607         silc_free(resolve);
608         return FALSE;
609       } else {
610         /* We'll resolve this client */
611         SilcBuffer idp;
612
613         r = NULL;
614         for (k = 0; k < resolve_count; k++) {
615           if (resolve[k].router == entry->router) {
616             r = &resolve[k];
617             break;
618           }
619         }
620
621         if (!r) {
622           resolve = silc_realloc(resolve, sizeof(*resolve) * 
623                                  (resolve_count + 1));
624           r = &resolve[resolve_count];
625           memset(r, 0, sizeof(*r));
626           r->router = entry->router;
627           r->ident = ++server->cmd_ident;
628           resolve_count++;
629         }
630
631         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
632                                    (r->res_argc + 1));
633         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
634                                         sizeof(*r->res_argv_lens) *
635                                         (r->res_argc + 1));
636         r->res_argv_types = silc_realloc(r->res_argv_types, 
637                                          sizeof(*r->res_argv_types) *
638                                          (r->res_argc + 1));
639         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
640         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
641                                                sizeof(**r->res_argv));
642         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
643         r->res_argv_lens[r->res_argc] = idp->len;
644         r->res_argv_types[r->res_argc] = r->res_argc + 3;
645         r->res_argc++;
646         silc_buffer_free(idp);
647
648         entry->resolve_cmd_ident = r->ident;
649         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
650         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
651       }
652     }
653   }
654
655   /* Do the resolving */
656   for (i = 0; i < resolve_count; i++) {
657     SilcBuffer res_cmd;
658
659     r = &resolve[i];
660
661     /* Send WHOIS request. We send WHOIS since we're doing the requesting
662        now anyway so make it a good one. */
663     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
664                                           r->res_argc, r->res_argv, 
665                                           r->res_argv_lens,
666                                           r->res_argv_types, 
667                                           r->ident);
668     silc_server_packet_send(server, r->router->connection,
669                             SILC_PACKET_COMMAND, cmd->packet->flags,
670                             res_cmd->data, res_cmd->len, FALSE);
671
672     /* Reprocess this packet after received reply */
673     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
674                                 r->ident,
675                                 silc_server_command_whois,
676                                 silc_server_command_dup(cmd));
677     cmd->pending = TRUE;
678
679     silc_buffer_free(res_cmd);
680     for (k = 0; k < r->res_argc; k++)
681       silc_free(r->res_argv[k]);
682     silc_free(r->res_argv);
683     silc_free(r->res_argv_lens);
684     silc_free(r->res_argv_types);
685     no_res = FALSE;
686   }
687   silc_free(resolve);
688
689   return no_res;
690 }
691
692 static void
693 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
694                                      SilcClientEntry *clients,
695                                      SilcUInt32 clients_count,
696                                      int count,
697                                      const char *nickname,
698                                      SilcClientID **client_ids)
699 {
700   SilcServer server = cmd->server;
701   char *tmp;
702   int i, k, len, valid_count;
703   SilcBuffer packet, idp, channels;
704   SilcClientEntry entry;
705   SilcCommandStatus status;
706   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
707   char nh[256], uh[256];
708   unsigned char idle[4], mode[4];
709   unsigned char *fingerprint;
710   SilcSocketConnection hsock;
711
712   /* Process only valid clients and ignore those that are not registered. */
713   valid_count = 0;
714   for (i = 0; i < clients_count; i++) {
715     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
716       valid_count++;
717     else
718       clients[i] = NULL;
719   }
720
721   if (!valid_count) {
722     /* No valid clients found, send error reply */
723     if (nickname) {
724       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
725                                            SILC_STATUS_ERR_NO_SUCH_NICK,
726                                            3, nickname, strlen(nickname));
727     } else if (client_ids && client_ids[0]) {
728       SilcBuffer idp = silc_id_payload_encode(client_ids[0], SILC_ID_CLIENT);
729       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
730                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
731                                            2, idp->data, idp->len);
732       silc_buffer_free(idp);
733     }
734     return;
735   }
736
737   /* Start processing found clients. */
738   if (valid_count > 1)
739     status = SILC_STATUS_LIST_START;
740   else
741     status = SILC_STATUS_OK;
742
743   for (i = 0, k = 0; i < clients_count; i++) {
744     entry = clients[i];
745     if (!entry)
746       continue;
747
748     if (k >= 1)
749       status = SILC_STATUS_LIST_ITEM;
750     if (valid_count > 1 && k == valid_count - 1)
751       status = SILC_STATUS_LIST_END;
752     if (count && k - 1 == count)
753       status = SILC_STATUS_LIST_END;
754
755     /* Send WHOIS reply */
756     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
757     tmp = silc_argument_get_first_arg(cmd->args, NULL);
758     
759     memset(uh, 0, sizeof(uh));
760     memset(nh, 0, sizeof(nh));
761     memset(idle, 0, sizeof(idle));
762     
763     strncat(nh, entry->nickname, strlen(entry->nickname));
764     if (!strchr(entry->nickname, '@')) {
765       strncat(nh, "@", 1);
766       if (entry->servername) {
767         strncat(nh, entry->servername, strlen(entry->servername));
768       } else {
769         len = entry->router ? strlen(entry->router->server_name) :
770           strlen(server->server_name);
771         strncat(nh, entry->router ? entry->router->server_name :
772                 server->server_name, len);
773       }
774     }
775       
776     strncat(uh, entry->username, strlen(entry->username));
777     if (!strchr(entry->username, '@')) {
778       strncat(uh, "@", 1);
779       hsock = (SilcSocketConnection)entry->connection;
780       len = strlen(hsock->hostname);
781       strncat(uh, hsock->hostname, len);
782     }
783
784     channels = silc_server_get_client_channel_list(server, entry);
785
786     if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
787       fingerprint = entry->data.fingerprint;
788     else
789       fingerprint = NULL;
790       
791     SILC_PUT32_MSB(entry->mode, mode);
792
793     if (entry->connection) {
794       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
795     }
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     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2017   }
2018
2019   /* Send notify about nickname change to our router. We send the new
2020      ID and ask to replace it with the old one. If we are router the
2021      packet is broadcasted. Send NICK_CHANGE notify. */
2022   if (!server->standalone)
2023     silc_server_send_notify_nick_change(server, server->router->connection, 
2024                                         server->server_type == SILC_SERVER ? 
2025                                         FALSE : TRUE, client->id,
2026                                         new_id, nick);
2027
2028   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2029
2030   /* Remove old cache entry */
2031   silc_idcache_del_by_context(server->local_list->clients, client);
2032
2033   /* Free old ID */
2034   silc_free(client->id);
2035
2036   /* Save the nickname as this client is our local client */
2037   silc_free(client->nickname);
2038
2039   client->nickname = strdup(nick);
2040   client->id = new_id;
2041
2042   /* Update client cache */
2043   silc_idcache_add(server->local_list->clients, client->nickname, 
2044                    client->id, (void *)client, 0, NULL);
2045
2046   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2047
2048   /* Send NICK_CHANGE notify to the client's channels */
2049   silc_server_send_notify_on_channels(server, NULL, client, 
2050                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2051                                       oidp->data, oidp->len, 
2052                                       nidp->data, nidp->len,
2053                                       client->nickname, 
2054                                       strlen(client->nickname));
2055
2056  send_reply:
2057   /* Send the new Client ID as reply command back to client */
2058   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2059                                                 SILC_STATUS_OK, 0, ident, 1, 
2060                                                 2, nidp->data, nidp->len);
2061   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2062                           0, packet->data, packet->len, FALSE);
2063
2064   silc_buffer_free(packet);
2065   silc_buffer_free(nidp);
2066   if (oidp)
2067     silc_buffer_free(oidp);
2068   
2069  out:
2070   silc_server_command_free(cmd);
2071 }
2072
2073 /* Sends the LIST command reply */
2074
2075 static void
2076 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2077                                     SilcChannelEntry *lch, 
2078                                     SilcUInt32 lch_count,
2079                                     SilcChannelEntry *gch,
2080                                     SilcUInt32 gch_count)
2081 {
2082   int i, k;
2083   SilcBuffer packet, idp;
2084   SilcChannelEntry entry;
2085   SilcCommandStatus status;
2086   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2087   char *topic;
2088   unsigned char usercount[4];
2089   SilcUInt32 users;
2090   int valid_lcount = 0, valid_rcount = 0;
2091
2092   for (i = 0; i < lch_count; i++) {
2093     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2094       lch[i] = NULL;
2095     else
2096       valid_lcount++;
2097   }
2098   for (i = 0; i < gch_count; i++) {
2099     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2100       gch[i] = NULL;
2101     else
2102       valid_rcount++;
2103   }
2104
2105   status = SILC_STATUS_OK;
2106   if ((lch_count + gch_count) > 1)
2107     status = SILC_STATUS_LIST_START;
2108
2109   /* Local list */
2110   for (i = 0, k = 0; i < lch_count; i++) {
2111     entry = lch[i];
2112     if (!entry)
2113       continue;
2114
2115     if (k >= 1)
2116       status = SILC_STATUS_LIST_ITEM;
2117     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2118       status = SILC_STATUS_LIST_END;
2119
2120     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2121
2122     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2123       topic = "*private*";
2124       memset(usercount, 0, sizeof(usercount));
2125     } else {
2126       topic = entry->topic;
2127       users = silc_hash_table_count(entry->user_list);
2128       SILC_PUT32_MSB(users, usercount);
2129     }
2130
2131     /* Send the reply */
2132     packet = 
2133       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2134                                            status, 0, ident, 4,
2135                                            2, idp->data, idp->len,
2136                                            3, entry->channel_name, 
2137                                            strlen(entry->channel_name),
2138                                            4, topic, topic ? strlen(topic) : 0,
2139                                            5, usercount, 4);
2140     silc_server_packet_send(cmd->server, cmd->sock, 
2141                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2142                             packet->len, FALSE);
2143     silc_buffer_free(packet);
2144     silc_buffer_free(idp);
2145     k++;
2146   }
2147
2148   /* Global list */
2149   for (i = 0, k = 0; i < gch_count; i++) {
2150     entry = gch[i];
2151     if (!entry)
2152       continue;
2153
2154     if (k >= 1)
2155       status = SILC_STATUS_LIST_ITEM;
2156     if (valid_rcount > 1 && k == valid_rcount - 1)
2157       status = SILC_STATUS_LIST_END;
2158
2159     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2160
2161     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2162       topic = "*private*";
2163       memset(usercount, 0, sizeof(usercount));
2164     } else {
2165       topic = entry->topic;
2166       users = entry->user_count;
2167       SILC_PUT32_MSB(users, usercount);
2168     }
2169
2170     /* Send the reply */
2171     packet = 
2172       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2173                                            status, 0, ident, 4,
2174                                            2, idp->data, idp->len,
2175                                            3, entry->channel_name, 
2176                                            strlen(entry->channel_name),
2177                                            4, topic, topic ? strlen(topic) : 0,
2178                                            5, usercount, 4);
2179     silc_server_packet_send(cmd->server, cmd->sock, 
2180                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2181                             packet->len, FALSE);
2182     silc_buffer_free(packet);
2183     silc_buffer_free(idp);
2184     k++;
2185   }
2186 }
2187
2188 /* Server side of LIST command. This lists the channel of the requested
2189    server. Secret channels are not listed. */
2190
2191 SILC_SERVER_CMD_FUNC(list)
2192 {
2193   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2194   SilcServer server = cmd->server;
2195   SilcChannelID *channel_id = NULL;
2196   unsigned char *tmp;
2197   SilcUInt32 tmp_len;
2198   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2199   SilcUInt32 lch_count = 0, gch_count = 0;
2200
2201   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2202
2203   /* If we are normal server, send the command to router, since we
2204      want to know all channels in the network. */
2205   if (!cmd->pending && server->server_type == SILC_SERVER && 
2206       !server->standalone) {
2207     SilcBuffer tmpbuf;
2208     SilcUInt16 old_ident;
2209     
2210     old_ident = silc_command_get_ident(cmd->payload);
2211     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2212     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2213     silc_server_packet_send(server, server->router->connection,
2214                             SILC_PACKET_COMMAND, cmd->packet->flags,
2215                             tmpbuf->data, tmpbuf->len, TRUE);
2216
2217     /* Reprocess this packet after received reply from router */
2218     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2219                                 silc_command_get_ident(cmd->payload),
2220                                 silc_server_command_list, 
2221                                 silc_server_command_dup(cmd));
2222     cmd->pending = TRUE;
2223     silc_command_set_ident(cmd->payload, old_ident);
2224     silc_buffer_free(tmpbuf);
2225     goto out;
2226   }
2227
2228   /* Get Channel ID */
2229   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2230   if (tmp) {
2231     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2232     if (!channel_id) {
2233       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2234                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
2235       goto out;
2236     }
2237   }
2238
2239   /* Get the channels from local list */
2240   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2241                                        &lch_count);
2242   
2243   /* Get the channels from global list */
2244   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2245                                        &gch_count);
2246
2247   /* Send the reply */
2248   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2249                                       gchannels, gch_count);
2250
2251   silc_free(lchannels);
2252   silc_free(gchannels);
2253
2254  out:
2255   silc_server_command_free(cmd);
2256 }
2257
2258 /* Server side of TOPIC command. Sets topic for channel and/or returns
2259    current topic to client. */
2260
2261 SILC_SERVER_CMD_FUNC(topic)
2262 {
2263   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2264   SilcServer server = cmd->server;
2265   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2266   SilcChannelID *channel_id;
2267   SilcChannelEntry channel;
2268   SilcChannelClientEntry chl;
2269   SilcBuffer packet, idp;
2270   unsigned char *tmp;
2271   SilcUInt32 argc, tmp_len;
2272   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2273
2274   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2275
2276   argc = silc_argument_get_arg_num(cmd->args);
2277
2278   /* Get Channel ID */
2279   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2280   if (!tmp) {
2281     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2282                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2283     goto out;
2284   }
2285   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2286   if (!channel_id) {
2287     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2288                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2289     goto out;
2290   }
2291
2292   /* Check whether the channel exists */
2293   channel = silc_idlist_find_channel_by_id(server->local_list, 
2294                                            channel_id, NULL);
2295   if (!channel) {
2296     channel = silc_idlist_find_channel_by_id(server->global_list, 
2297                                              channel_id, NULL);
2298     if (!channel) {
2299       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2300                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2301       goto out;
2302     }
2303   }
2304
2305   if (argc > 1) {
2306     /* Get the topic */
2307     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2308     if (!tmp) {
2309       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2310                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311       goto out;
2312     }
2313
2314     if (strlen(tmp) > 256) {
2315       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2316                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2317       goto out;
2318     }
2319
2320     /* See whether the client is on channel and has rights to change topic */
2321     if (!silc_server_client_on_channel(client, channel, &chl)) {
2322       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2323                                             SILC_STATUS_ERR_NOT_ON_CHANNEL);
2324       goto out;
2325     }
2326
2327     if (chl->mode == SILC_CHANNEL_UMODE_NONE && 
2328         channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2329       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2330                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2331       goto out;
2332     }
2333
2334     /* Set the topic for channel */
2335     silc_free(channel->topic);
2336     channel->topic = strdup(tmp);
2337
2338     /* Send TOPIC_SET notify type to the network */
2339     if (!server->standalone)
2340       silc_server_send_notify_topic_set(server, server->router->connection,
2341                                         server->server_type == SILC_ROUTER ?
2342                                         TRUE : FALSE, channel, 
2343                                         client->id, SILC_ID_CLIENT,
2344                                         channel->topic);
2345
2346     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2347
2348     /* Send notify about topic change to all clients on the channel */
2349     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2350                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2351                                        idp->data, idp->len,
2352                                        channel->topic, strlen(channel->topic));
2353     silc_buffer_free(idp);
2354   }
2355
2356   /* Send the topic to client as reply packet */
2357   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2358   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2359                                                 SILC_STATUS_OK, 0, ident, 2, 
2360                                                 2, idp->data, idp->len,
2361                                                 3, channel->topic, 
2362                                                 channel->topic ? 
2363                                                 strlen(channel->topic) : 0);
2364   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2365                           0, packet->data, packet->len, FALSE);
2366
2367   silc_buffer_free(packet);
2368   silc_buffer_free(idp);
2369   silc_free(channel_id);
2370
2371  out:
2372   silc_server_command_free(cmd);
2373 }
2374
2375 /* Server side of INVITE command. Invites some client to join some channel. 
2376    This command is also used to manage the invite list of the channel. */
2377
2378 SILC_SERVER_CMD_FUNC(invite)
2379 {
2380   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2381   SilcServer server = cmd->server;
2382   SilcSocketConnection sock = cmd->sock, dest_sock;
2383   SilcChannelClientEntry chl;
2384   SilcClientEntry sender, dest;
2385   SilcClientID *dest_id = NULL;
2386   SilcChannelEntry channel;
2387   SilcChannelID *channel_id = NULL;
2388   SilcIDListData idata;
2389   SilcBuffer idp, idp2, packet;
2390   unsigned char *tmp, *add, *del;
2391   SilcUInt32 len;
2392   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2393
2394   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2395
2396   /* Get Channel ID */
2397   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2398   if (!tmp) {
2399     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2400                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2401     goto out;
2402   }
2403   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2404   if (!channel_id) {
2405     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2406                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2407     goto out;
2408   }
2409
2410   /* Get the channel entry */
2411   channel = silc_idlist_find_channel_by_id(server->local_list, 
2412                                            channel_id, NULL);
2413   if (!channel) {
2414     channel = silc_idlist_find_channel_by_id(server->global_list, 
2415                                              channel_id, NULL);
2416     if (!channel) {
2417       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2418                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2419       goto out;
2420     }
2421   }
2422
2423   /* Check whether the sender of this command is on the channel. */
2424   sender = (SilcClientEntry)sock->user_data;
2425   if (!silc_server_client_on_channel(sender, channel, &chl)) {
2426     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2427                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2428     goto out;
2429   }
2430
2431   /* Check whether the channel is invite-only channel. If yes then the
2432      sender of this command must be at least channel operator. */
2433   if (chl->mode == SILC_CHANNEL_UMODE_NONE &&
2434       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2435     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2436                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2437     goto out;
2438   }
2439
2440   /* Get destination client ID */
2441   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2442   if (tmp) {
2443     char invite[512];
2444     bool resolve;
2445
2446     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2447     if (!dest_id) {
2448       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2449                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2450       goto out;
2451     }
2452
2453     /* Get the client entry */
2454     dest = silc_server_get_client_resolve(server, dest_id, &resolve);
2455     if (!dest) {
2456       if (server->server_type != SILC_SERVER || !resolve) {
2457         silc_server_command_send_status_reply(
2458                                         cmd, SILC_COMMAND_INVITE,
2459                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2460         goto out;
2461       }
2462       
2463       /* The client info is being resolved. Reprocess this packet after
2464          receiving the reply to the query. */
2465       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2466                                   server->cmd_ident,
2467                                   silc_server_command_invite, 
2468                                   silc_server_command_dup(cmd));
2469       cmd->pending = TRUE;
2470       silc_free(channel_id);
2471       silc_free(dest_id);
2472       goto out;
2473     }
2474
2475     /* Check whether the requested client is already on the channel. */
2476     if (silc_server_client_on_channel(dest, channel, NULL)) {
2477       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2478                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2479       goto out;
2480     }
2481     
2482     /* Get route to the client */
2483     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, 
2484                                              &idata, NULL);
2485     if (!dest_sock) {
2486       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2487                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2488       goto out;
2489     }
2490
2491     memset(invite, 0, sizeof(invite));
2492     strncat(invite, dest->nickname, strlen(dest->nickname));
2493     strncat(invite, "!", 1);
2494     strncat(invite, dest->username, strlen(dest->username));
2495     if (!strchr(dest->username, '@')) {
2496       strncat(invite, "@", 1);
2497       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2498     }
2499
2500     len = strlen(invite);
2501     if (!channel->invite_list)
2502       channel->invite_list = silc_calloc(len + 2, 
2503                                          sizeof(*channel->invite_list));
2504     else
2505       channel->invite_list = silc_realloc(channel->invite_list, 
2506                                           sizeof(*channel->invite_list) * 
2507                                           (len + 
2508                                            strlen(channel->invite_list) + 2));
2509     strncat(channel->invite_list, invite, len);
2510     strncat(channel->invite_list, ",", 1);
2511
2512     /* Send notify to the client that is invited to the channel */
2513     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2514     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2515     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2516                                  SILC_ID_CLIENT,
2517                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2518                                  idp->data, idp->len, 
2519                                  channel->channel_name, 
2520                                  strlen(channel->channel_name),
2521                                  idp2->data, idp2->len);
2522     silc_buffer_free(idp);
2523     silc_buffer_free(idp2);
2524   }
2525
2526   /* Add the client to the invite list of the channel */
2527   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2528   if (add) {
2529     if (!channel->invite_list)
2530       channel->invite_list = silc_calloc(len + 2, 
2531                                          sizeof(*channel->invite_list));
2532     else
2533       channel->invite_list = silc_realloc(channel->invite_list, 
2534                                           sizeof(*channel->invite_list) * 
2535                                           (len + 
2536                                            strlen(channel->invite_list) + 2));
2537     if (add[len - 1] == ',')
2538       add[len - 1] = '\0';
2539     
2540     strncat(channel->invite_list, add, len);
2541     strncat(channel->invite_list, ",", 1);
2542   }
2543
2544   /* Get the invite to be removed and remove it from the list */
2545   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2546   if (del && channel->invite_list) {
2547     char *start, *end, *n;
2548
2549     if (!strncmp(channel->invite_list, del, 
2550                  strlen(channel->invite_list) - 1)) {
2551       silc_free(channel->invite_list);
2552       channel->invite_list = NULL;
2553     } else {
2554       start = strstr(channel->invite_list, del);
2555       if (start && strlen(start) >= len) {
2556         end = start + len;
2557         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2558         strncat(n, channel->invite_list, start - channel->invite_list);
2559         strncat(n, end + 1, ((channel->invite_list + 
2560                               strlen(channel->invite_list)) - end) - 1);
2561         silc_free(channel->invite_list);
2562         channel->invite_list = n;
2563       }
2564     }
2565   }
2566
2567   /* Send notify to the primary router */
2568   if (!server->standalone)
2569     silc_server_send_notify_invite(server, server->router->connection,
2570                                    server->server_type == SILC_ROUTER ?
2571                                    TRUE : FALSE, channel,
2572                                    sender->id, add, del);
2573
2574   /* Send command reply */
2575   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2576
2577   if (add || del)
2578     packet = 
2579       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2580                                            SILC_STATUS_OK, 0, ident, 2,
2581                                            2, tmp, len,
2582                                            3, channel->invite_list,
2583                                            channel->invite_list ?
2584                                            strlen(channel->invite_list) : 0);
2585   else
2586     packet = 
2587       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2588                                            SILC_STATUS_OK, 0, ident, 1,
2589                                            2, tmp, len);
2590   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2591                           packet->data, packet->len, FALSE);
2592   silc_buffer_free(packet);
2593
2594  out:
2595   silc_free(dest_id);
2596   silc_free(channel_id);
2597   silc_server_command_free(cmd);
2598 }
2599
2600 typedef struct {
2601   SilcServer server;
2602   SilcSocketConnection sock;
2603   char *signoff;
2604 } *QuitInternal;
2605
2606 /* Quits connection to client. This gets called if client won't
2607    close the connection even when it has issued QUIT command. */
2608
2609 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2610 {
2611   QuitInternal q = (QuitInternal)context;
2612
2613   /* Free all client specific data, such as client entry and entires
2614      on channels this client may be on. */
2615   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2616                                TRUE, q->signoff);
2617   q->sock->user_data = NULL;
2618
2619   /* Close the connection on our side */
2620   silc_server_close_connection(q->server, q->sock);
2621
2622   silc_free(q->signoff);
2623   silc_free(q);
2624 }
2625
2626 /* Quits SILC session. This is the normal way to disconnect client. */
2627  
2628 SILC_SERVER_CMD_FUNC(quit)
2629 {
2630   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2631   SilcServer server = cmd->server;
2632   SilcSocketConnection sock = cmd->sock;
2633   QuitInternal q;
2634   unsigned char *tmp = NULL;
2635   SilcUInt32 len = 0;
2636
2637   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2638
2639   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2640     goto out;
2641
2642   /* Get destination ID */
2643   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2644   if (len > 128)
2645     tmp = NULL;
2646
2647   q = silc_calloc(1, sizeof(*q));
2648   q->server = server;
2649   q->sock = sock;
2650   q->signoff = tmp ? strdup(tmp) : NULL;
2651
2652   /* We quit the connection with little timeout */
2653   silc_schedule_task_add(server->schedule, sock->sock,
2654                      silc_server_command_quit_cb, (void *)q,
2655                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2656
2657  out:
2658   silc_server_command_free(cmd);
2659 }
2660
2661 /* Server side of command KILL. This command is used by router operator
2662    to remove an client from the SILC Network temporarily. */
2663
2664 SILC_SERVER_CMD_FUNC(kill)
2665 {
2666   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2667   SilcServer server = cmd->server;
2668   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2669   SilcClientEntry remote_client;
2670   SilcClientID *client_id;
2671   unsigned char *tmp, *comment;
2672   SilcUInt32 tmp_len, tmp_len2;
2673   SilcBuffer killer;
2674   bool local;
2675
2676   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2677
2678   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2679     goto out;
2680
2681   /* KILL command works only on router */
2682   if (server->server_type != SILC_ROUTER) {
2683     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2684                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2685     goto out;
2686   }
2687
2688   /* Check whether client has the permissions. */
2689   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2690     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2691                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2692     goto out;
2693   }
2694
2695   /* Get the client ID */
2696   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2697   if (!tmp) {
2698     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2699                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2700     goto out;
2701   }
2702   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2703   if (!client_id) {
2704     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2705                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2706     goto out;
2707   }
2708
2709   /* Get the client entry */
2710   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2711                                                 client_id, TRUE, NULL);
2712   local = TRUE;
2713   if (!remote_client) {
2714     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2715                                                   client_id, TRUE, NULL);
2716     local = FALSE;
2717     if (!remote_client) {
2718       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2719                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2720       goto out;
2721     }
2722   }
2723
2724   /* Get comment */
2725   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2726   if (tmp_len2 > 128)
2727     tmp_len2 = 128;
2728
2729   /* Send reply to the sender */
2730   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2731                                         SILC_STATUS_OK);
2732
2733   /* Send the KILL notify packets. First send it to the channel, then
2734      to our primary router and then directly to the client who is being
2735      killed right now. */
2736
2737   /* Send KILLED notify to the channels. It is not sent to the client
2738      as it will be sent differently destined directly to the client and not
2739      to the channel. */
2740   killer = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2741   silc_server_send_notify_on_channels(server, remote_client, 
2742                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2743                                       3, tmp, tmp_len,
2744                                       comment, comment ? tmp_len2 : 0,
2745                                       killer->data, killer->len);
2746   silc_buffer_free(killer);
2747
2748   /* Send KILLED notify to primary route */
2749   if (!server->standalone)
2750     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2751                                    remote_client->id, comment, client->id);
2752
2753   /* Send KILLED notify to the client directly */
2754   silc_server_send_notify_killed(server, remote_client->connection ? 
2755                                  remote_client->connection : 
2756                                  remote_client->router->connection, FALSE,
2757                                  remote_client->id, comment, client->id);
2758
2759   /* Remove the client from all channels. This generates new keys to the
2760      channels as well. */
2761   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2762                                    NULL, TRUE);
2763
2764   /* Remove the client entry, If it is locally connected then we will also
2765      disconnect the client here */
2766   if (remote_client->connection) {
2767     /* Remove locally conneted client */
2768     SilcSocketConnection sock = remote_client->connection;
2769     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2770     silc_server_close_connection(server, sock);
2771   } else {
2772     /* Update statistics */
2773     if (remote_client->connection)
2774       server->stat.my_clients--;
2775     if (server->stat.cell_clients)
2776       server->stat.cell_clients--;
2777     SILC_OPER_STATS_UPDATE(remote_client, server, SILC_UMODE_SERVER_OPERATOR);
2778     SILC_OPER_STATS_UPDATE(remote_client, router, SILC_UMODE_ROUTER_OPERATOR);
2779
2780     /* Remove remote client */
2781     silc_idlist_del_client(local ? server->local_list :
2782                            server->global_list, remote_client);
2783   }
2784
2785  out:
2786   silc_server_command_free(cmd);
2787 }
2788
2789 /* Server side of command INFO. This sends information about us to 
2790    the client. If client requested specific server we will send the 
2791    command to that server. */
2792
2793 SILC_SERVER_CMD_FUNC(info)
2794 {
2795   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2796   SilcServer server = cmd->server;
2797   SilcBuffer packet, idp;
2798   unsigned char *tmp;
2799   SilcUInt32 tmp_len;
2800   char *dest_server, *server_info = NULL, *server_name;
2801   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2802   SilcServerEntry entry = NULL;
2803   SilcServerID *server_id = NULL;
2804
2805   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2806
2807   /* Get server name */
2808   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2809
2810   /* Get Server ID */
2811   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2812   if (tmp) {
2813     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2814     if (!server_id) {
2815       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2816                                             SILC_STATUS_ERR_NO_SERVER_ID);
2817       goto out;
2818     }
2819   }
2820
2821   if (server_id) {
2822     /* Check whether we have this server cached */
2823     entry = silc_idlist_find_server_by_id(server->local_list,
2824                                           server_id, TRUE, NULL);
2825     if (!entry) {
2826       entry = silc_idlist_find_server_by_id(server->global_list,
2827                                             server_id, TRUE, NULL);
2828       if (!entry && server->server_type != SILC_SERVER) {
2829         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2830                                               SILC_STATUS_ERR_NO_SUCH_SERVER);
2831         goto out;
2832       }
2833     }
2834   }
2835
2836   /* Some buggy servers has sent request to router about themselves. */
2837   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2838     goto out;
2839
2840   if ((!dest_server && !server_id && !entry) || (entry && 
2841                                                  entry == server->id_entry) ||
2842       (dest_server && !cmd->pending && 
2843        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2844     /* Send our reply */
2845     char info_string[256];
2846
2847     memset(info_string, 0, sizeof(info_string));
2848     snprintf(info_string, sizeof(info_string), 
2849              "location: %s server: %s admin: %s <%s>",
2850              server->config->server_info->location,
2851              server->config->server_info->server_type,
2852              server->config->server_info->admin,
2853              server->config->server_info->email);
2854
2855     server_info = info_string;
2856     entry = server->id_entry;
2857   } else {
2858     /* Check whether we have this server cached */
2859     if (!entry && dest_server) {
2860       entry = silc_idlist_find_server_by_name(server->global_list,
2861                                               dest_server, TRUE, NULL);
2862       if (!entry) {
2863         entry = silc_idlist_find_server_by_name(server->local_list,
2864                                                 dest_server, TRUE, NULL);
2865       }
2866     }
2867
2868     if (!cmd->pending &&
2869         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2870       /* Send to the server */
2871       SilcBuffer tmpbuf;
2872       SilcUInt16 old_ident;
2873
2874       old_ident = silc_command_get_ident(cmd->payload);
2875       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2876       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2877
2878       silc_server_packet_send(server, entry->connection,
2879                               SILC_PACKET_COMMAND, cmd->packet->flags,
2880                               tmpbuf->data, tmpbuf->len, TRUE);
2881
2882       /* Reprocess this packet after received reply from router */
2883       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2884                                   silc_command_get_ident(cmd->payload),
2885                                   silc_server_command_info,
2886                                   silc_server_command_dup(cmd));
2887       cmd->pending = TRUE;
2888       silc_command_set_ident(cmd->payload, old_ident);
2889       silc_buffer_free(tmpbuf);
2890       goto out;
2891     }
2892
2893     if (!entry && !cmd->pending && !server->standalone) {
2894       /* Send to the primary router */
2895       SilcBuffer tmpbuf;
2896       SilcUInt16 old_ident;
2897
2898       old_ident = silc_command_get_ident(cmd->payload);
2899       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2900       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2901
2902       silc_server_packet_send(server, server->router->connection,
2903                               SILC_PACKET_COMMAND, cmd->packet->flags,
2904                               tmpbuf->data, tmpbuf->len, TRUE);
2905
2906       /* Reprocess this packet after received reply from router */
2907       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2908                                   silc_command_get_ident(cmd->payload),
2909                                   silc_server_command_info,
2910                                   silc_server_command_dup(cmd));
2911       cmd->pending = TRUE;
2912       silc_command_set_ident(cmd->payload, old_ident);
2913       silc_buffer_free(tmpbuf);
2914       goto out;
2915     }
2916   }
2917
2918   silc_free(server_id);
2919
2920   if (!entry) {
2921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2922                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2923     goto out;
2924   }
2925
2926   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2927   if (!server_info)
2928     server_info = entry->server_info;
2929   server_name = entry->server_name;
2930
2931   /* Send the reply */
2932   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2933                                                 SILC_STATUS_OK, 0, ident, 3,
2934                                                 2, idp->data, idp->len,
2935                                                 3, server_name, 
2936                                                 strlen(server_name),
2937                                                 4, server_info, 
2938                                                 server_info ? 
2939                                                 strlen(server_info) : 0);
2940   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2941                           packet->data, packet->len, FALSE);
2942     
2943   silc_buffer_free(packet);
2944   silc_buffer_free(idp);
2945
2946  out:
2947   silc_server_command_free(cmd);
2948 }
2949
2950 /* Server side of command PING. This just replies to the ping. */
2951
2952 SILC_SERVER_CMD_FUNC(ping)
2953 {
2954   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2955   SilcServer server = cmd->server;
2956   SilcServerID *id;
2957   SilcUInt32 len;
2958   unsigned char *tmp;
2959
2960   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
2961
2962   /* Get Server ID */
2963   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2964   if (!tmp) {
2965     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2966                                           SILC_STATUS_ERR_NO_SERVER_ID);
2967     goto out;
2968   }
2969   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2970   if (!id)
2971     goto out;
2972
2973   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
2974     /* Send our reply */
2975     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2976                                           SILC_STATUS_OK);
2977   } else {
2978     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2979                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2980     goto out;
2981   }
2982
2983   silc_free(id);
2984
2985  out:
2986   silc_server_command_free(cmd);
2987 }
2988
2989 /* Server side of command STATS. */
2990
2991 SILC_SERVER_CMD_FUNC(stats)
2992 {
2993   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2994   SilcServer server = cmd->server;
2995   SilcServerID *server_id;
2996   unsigned char *tmp;
2997   SilcUInt32 tmp_len;
2998   SilcBuffer packet, stats;
2999   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3000   SilcUInt32 uptime;
3001
3002   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3003
3004   /* Get Server ID */
3005   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3006   if (!tmp) {
3007     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3008                                           SILC_STATUS_ERR_NO_SERVER_ID);
3009     goto out;
3010   }
3011   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3012   if (!server_id)
3013     goto out;
3014
3015   /* The ID must be ours */
3016   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3017     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3018                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3019     silc_free(server_id);
3020     goto out;
3021   }
3022   silc_free(server_id);
3023
3024   /* If we are router then just send everything we got. If we are normal
3025      server then we'll send this to our router to get all the latest
3026      statistical information. */
3027   if (!cmd->pending && server->server_type != SILC_ROUTER && 
3028       !server->standalone) {
3029     /* Send request to our router */
3030     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
3031                                             SILC_ID_SERVER);
3032     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
3033                                             ++server->cmd_ident, 1,
3034                                             1, idp->data, idp->len);
3035     silc_server_packet_send(server, server->router->connection,
3036                             SILC_PACKET_COMMAND, 0, packet->data,
3037                             packet->len, FALSE);
3038
3039     /* Reprocess this packet after received reply from router */
3040     silc_server_command_pending(server, SILC_COMMAND_STATS, 
3041                                 server->cmd_ident,
3042                                 silc_server_command_stats,
3043                                 silc_server_command_dup(cmd));
3044     cmd->pending = TRUE;
3045     silc_buffer_free(packet);
3046     silc_buffer_free(idp);
3047     goto out;
3048   }
3049
3050   /* Send our reply to sender */
3051   uptime = time(NULL) - server->starttime;
3052
3053   stats = silc_buffer_alloc_size(60);
3054   silc_buffer_format(stats,
3055                      SILC_STR_UI_INT(server->starttime),
3056                      SILC_STR_UI_INT(uptime),
3057                      SILC_STR_UI_INT(server->stat.my_clients),
3058                      SILC_STR_UI_INT(server->stat.my_channels),
3059                      SILC_STR_UI_INT(server->stat.my_server_ops),
3060                      SILC_STR_UI_INT(server->stat.my_router_ops),
3061                      SILC_STR_UI_INT(server->stat.cell_clients),
3062                      SILC_STR_UI_INT(server->stat.cell_channels),
3063                      SILC_STR_UI_INT(server->stat.cell_servers),
3064                      SILC_STR_UI_INT(server->stat.clients),
3065                      SILC_STR_UI_INT(server->stat.channels),
3066                      SILC_STR_UI_INT(server->stat.servers),
3067                      SILC_STR_UI_INT(server->stat.routers),
3068                      SILC_STR_UI_INT(server->stat.server_ops),
3069                      SILC_STR_UI_INT(server->stat.router_ops),
3070                      SILC_STR_END);
3071
3072   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
3073                                                 SILC_STATUS_OK, 0, ident, 2,
3074                                                 2, tmp, tmp_len,
3075                                                 3, stats->data, stats->len);
3076   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3077                           0, packet->data, packet->len, FALSE);
3078   silc_buffer_free(packet);
3079   silc_buffer_free(stats);
3080
3081  out:
3082   silc_server_command_free(cmd);
3083 }
3084
3085 /* Internal routine to join channel. The channel sent to this function
3086    has been either created or resolved from ID lists. This joins the sent
3087    client to the channel. */
3088
3089 static void silc_server_command_join_channel(SilcServer server, 
3090                                              SilcServerCommandContext cmd,
3091                                              SilcChannelEntry channel,
3092                                              SilcClientID *client_id,
3093                                              bool created,
3094                                              bool create_key,
3095                                              SilcUInt32 umode,
3096                                              const unsigned char *auth,
3097                                              SilcUInt32 auth_len)
3098 {
3099   SilcSocketConnection sock = cmd->sock;
3100   unsigned char *tmp;
3101   SilcUInt32 tmp_len, user_count;
3102   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3103   SilcClientEntry client;
3104   SilcChannelClientEntry chl;
3105   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3106   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3107   char check[512], check2[512];
3108   bool founder = FALSE;
3109   bool resolve;
3110
3111   SILC_LOG_DEBUG(("Start"));
3112
3113   if (!channel)
3114     return;
3115
3116   /* Get the client entry */
3117   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3118     client = (SilcClientEntry)sock->user_data;
3119   } else {
3120     client = silc_server_get_client_resolve(server, client_id, &resolve);
3121     if (!client) {
3122       if (cmd->pending)
3123         goto out;
3124
3125       if (!resolve) {
3126         silc_server_command_send_status_reply(
3127                                          cmd, SILC_COMMAND_JOIN,
3128                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3129         goto out;
3130       }
3131
3132       /* The client info is being resolved. Reprocess this packet after
3133          receiving the reply to the query. */
3134       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3135                                   server->cmd_ident,
3136                                   silc_server_command_join, 
3137                                   silc_server_command_dup(cmd));
3138       cmd->pending = TRUE;
3139       goto out;
3140     }
3141
3142     cmd->pending = FALSE;
3143   }
3144
3145   /*
3146    * Check founder auth payload if provided.  If client can gain founder
3147    * privileges it can override various conditions on joining the channel,
3148    * and can have directly the founder mode set on the channel.
3149    */
3150   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3151     SilcIDListData idata = (SilcIDListData)client;
3152
3153     if (channel->founder_key && idata->public_key &&
3154         silc_pkcs_public_key_compare(channel->founder_key, 
3155                                      idata->public_key)) {
3156       void *auth_data = (channel->founder_method == SILC_AUTH_PASSWORD ?
3157                          (void *)channel->founder_passwd : 
3158                          (void *)channel->founder_key);
3159       SilcUInt32 auth_data_len = 
3160         (channel->founder_method == SILC_AUTH_PASSWORD ?
3161          channel->founder_passwd_len : 0);
3162
3163       /* Check whether the client is to become founder */
3164       if (silc_auth_verify_data(auth, auth_len, channel->founder_method, 
3165                                 auth_data, auth_data_len,
3166                                 idata->hash, client->id, SILC_ID_CLIENT)) {
3167         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3168         founder = TRUE;
3169       }
3170     }
3171   }
3172
3173   /*
3174    * Check channel modes
3175    */
3176
3177   if (!umode) {
3178     memset(check, 0, sizeof(check));
3179     memset(check2, 0, sizeof(check2));
3180     strncat(check, client->nickname, strlen(client->nickname));
3181     strncat(check, "!", 1);
3182     strncat(check, client->username, strlen(client->username));
3183     if (!strchr(client->username, '@')) {
3184       strncat(check, "@", 1);
3185       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3186     }
3187
3188     strncat(check2, client->nickname, strlen(client->nickname));
3189     if (!strchr(client->nickname, '@')) {
3190       strncat(check2, "@", 1);
3191       strncat(check2, server->server_name, strlen(server->server_name));
3192     }
3193     strncat(check2, "!", 1);
3194     strncat(check2, client->username, strlen(client->username));
3195     if (!strchr(client->username, '@')) {
3196       strncat(check2, "@", 1);
3197       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3198     }
3199     
3200     /* Check invite list if channel is invite-only channel */
3201     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3202       if (!channel->invite_list ||
3203           (!silc_string_match(channel->invite_list, check) &&
3204            !silc_string_match(channel->invite_list, check2))) {
3205         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3206                                               SILC_STATUS_ERR_NOT_INVITED);
3207         goto out;
3208       }
3209     }
3210
3211     /* Check ban list if it exists. If the client's nickname, server,
3212        username and/or hostname is in the ban list the access to the
3213        channel is denied. */
3214     if (channel->ban_list) {
3215       if (silc_string_match(channel->ban_list, check) ||
3216           silc_string_match(channel->ban_list, check2)) {
3217         silc_server_command_send_status_reply(
3218                                       cmd, SILC_COMMAND_JOIN,
3219                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
3220         goto out;
3221       }
3222     }
3223     
3224     /* Check user count limit if set. */
3225     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3226       if (silc_hash_table_count(channel->user_list) + 1 > 
3227           channel->user_limit) {
3228         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3229                                               SILC_STATUS_ERR_CHANNEL_IS_FULL);
3230         goto out;
3231       }
3232     }
3233   }
3234
3235   /* Check the channel passphrase if set. */
3236   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3237     /* Get passphrase */
3238     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3239     if (tmp)
3240       passphrase = silc_memdup(tmp, tmp_len);
3241   
3242     if (!passphrase || !channel->passphrase ||
3243         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3244       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3245                                             SILC_STATUS_ERR_BAD_PASSWORD);
3246       goto out;
3247     }
3248   }
3249
3250   /*
3251    * Client is allowed to join to the channel. Make it happen.
3252    */
3253
3254   /* Check whether the client already is on the channel */
3255   if (silc_server_client_on_channel(client, channel, NULL)) {
3256     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3257                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
3258     goto out;
3259   }
3260
3261   /* Generate new channel key as protocol dictates */
3262   if (create_key) {
3263     if (!silc_server_create_channel_key(server, channel, 0))
3264       goto out;
3265
3266     /* Send the channel key. This is broadcasted to the channel but is not
3267        sent to the client who is joining to the channel. */
3268     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3269       silc_server_send_channel_key(server, NULL, channel, 
3270                                    server->server_type == SILC_ROUTER ? 
3271                                    FALSE : !server->standalone);
3272   }
3273
3274   /* Join the client to the channel by adding it to channel's user list.
3275      Add also the channel to client entry's channels list for fast cross-
3276      referencing. */
3277   chl = silc_calloc(1, sizeof(*chl));
3278   chl->mode = umode;
3279   chl->client = client;
3280   chl->channel = channel;
3281   silc_hash_table_add(channel->user_list, client, chl);
3282   silc_hash_table_add(client->channels, channel, chl);
3283   channel->user_count++;
3284
3285   /* Get users on the channel */
3286   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3287                                    &user_count);
3288
3289   /* Encode Client ID Payload of the original client who wants to join */
3290   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3291
3292   /* Encode command reply packet */
3293   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3294   SILC_PUT32_MSB(channel->mode, mode);
3295   SILC_PUT32_MSB(created, tmp2);
3296   SILC_PUT32_MSB(user_count, tmp3);
3297
3298   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3299     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3300     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
3301                                            strlen(channel->channel_key->
3302                                                   cipher->name),
3303                                            channel->channel_key->cipher->name,
3304                                            channel->key_len / 8, channel->key);
3305     silc_free(tmp);
3306   }
3307
3308   reply = 
3309     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3310                                          SILC_STATUS_OK, 0, ident, 13,
3311                                          2, channel->channel_name,
3312                                          strlen(channel->channel_name),
3313                                          3, chidp->data, chidp->len,
3314                                          4, clidp->data, clidp->len,
3315                                          5, mode, 4,
3316                                          6, tmp2, 4,
3317                                          7, keyp ? keyp->data : NULL, 
3318                                          keyp ? keyp->len : 0,
3319                                          8, channel->ban_list, 
3320                                          channel->ban_list ?
3321                                          strlen(channel->ban_list) : 0,
3322                                          9, channel->invite_list,
3323                                          channel->invite_list ?
3324                                          strlen(channel->invite_list) : 0,
3325                                          10, channel->topic,
3326                                          channel->topic ?
3327                                          strlen(channel->topic) : 0,
3328                                          11, silc_hmac_get_name(channel->hmac),
3329                                          strlen(silc_hmac_get_name(channel->
3330                                                                    hmac)),
3331                                          12, tmp3, 4,
3332                                          13, user_list->data, user_list->len,
3333                                          14, mode_list->data, 
3334                                          mode_list->len);
3335
3336   /* Send command reply */
3337   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3338                           reply->data, reply->len, FALSE);
3339
3340   /* Send JOIN notify to locally connected clients on the channel. If
3341      we are normal server then router will send or have sent JOIN notify
3342      already. However since we've added the client already to our channel
3343      we'll ignore it (in packet_receive.c) so we must send it here. If
3344      we are router then this will send it to local clients and local
3345      servers. */
3346   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3347                                      SILC_NOTIFY_TYPE_JOIN, 2,
3348                                      clidp->data, clidp->len,
3349                                      chidp->data, chidp->len);
3350
3351   if (!cmd->pending) {
3352     /* Send JOIN notify packet to our primary router */
3353     if (!server->standalone)
3354       silc_server_send_notify_join(server, server->router->connection,
3355                                    server->server_type == SILC_ROUTER ?
3356                                    TRUE : FALSE, channel, client->id);
3357
3358     if (keyp)
3359       /* Distribute the channel key to all backup routers. */
3360       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3361                               keyp->data, keyp->len, FALSE, TRUE);
3362   }
3363
3364   /* If client became founder by providing correct founder auth data
3365      notify the mode change to the channel. */
3366   if (founder) {
3367     SILC_PUT32_MSB(chl->mode, mode);
3368     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3369                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3370                                        clidp->data, clidp->len,
3371                                        mode, 4, clidp->data, clidp->len);
3372       
3373     /* Set CUMODE notify type to network */
3374     if (!server->standalone)
3375       silc_server_send_notify_cumode(server, server->router->connection,
3376                                      server->server_type == SILC_ROUTER ? 
3377                                      TRUE : FALSE, channel,
3378                                      chl->mode, client->id, SILC_ID_CLIENT,
3379                                      client->id);
3380   }
3381
3382   silc_buffer_free(reply);
3383   silc_buffer_free(clidp);
3384   silc_buffer_free(chidp);
3385   silc_buffer_free(keyp);
3386   silc_buffer_free(user_list);
3387   silc_buffer_free(mode_list);
3388
3389  out:
3390   silc_free(passphrase);
3391 }
3392
3393 /* Server side of command JOIN. Joins client into requested channel. If 
3394    the channel does not exist it will be created. */
3395
3396 SILC_SERVER_CMD_FUNC(join)
3397 {
3398   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3399   SilcServer server = cmd->server;
3400   unsigned char *auth;
3401   SilcUInt32 tmp_len, auth_len;
3402   char *tmp, *channel_name = NULL, *cipher, *hmac;
3403   SilcChannelEntry channel;
3404   SilcUInt32 umode = 0;
3405   bool created = FALSE, create_key = TRUE;
3406   SilcClientID *client_id;
3407
3408   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3409
3410   /* Get channel name */
3411   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3412   if (!tmp) {
3413     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3414                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3415     goto out;
3416   }
3417   channel_name = tmp;
3418
3419   if (tmp_len > 256)
3420     channel_name[255] = '\0';
3421
3422   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3423     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3424                                           SILC_STATUS_ERR_BAD_CHANNEL);
3425     goto out;
3426   }
3427
3428   /* Get Client ID of the client who is joining to the channel */
3429   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3430   if (!tmp) {
3431     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3432                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3433     goto out;
3434   }
3435   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3436   if (!client_id) {
3437     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3438                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3439     goto out;
3440   }
3441
3442   /* Get cipher, hmac name and auth payload */
3443   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3444   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3445   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3446
3447   /* See if the channel exists */
3448   channel = silc_idlist_find_channel_by_name(server->local_list, 
3449                                              channel_name, NULL);
3450
3451   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3452     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3453     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3454
3455     if (!channel || channel->disabled) {
3456       /* Channel not found */
3457
3458       /* If we are standalone server we don't have a router, we just create 
3459          the channel by ourselves. */
3460       if (server->standalone) {
3461         channel = silc_server_create_new_channel(server, server->id, cipher, 
3462                                                  hmac, channel_name, TRUE);
3463         if (!channel) {
3464           silc_server_command_send_status_reply(
3465                                          cmd, SILC_COMMAND_JOIN,
3466                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3467           goto out;
3468         }
3469         
3470         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3471         created = TRUE;
3472         create_key = FALSE;
3473         
3474       } else {
3475
3476         /* The channel does not exist on our server. If we are normal server 
3477            we will send JOIN command to our router which will handle the
3478            joining procedure (either creates the channel if it doesn't exist 
3479            or joins the client to it). */
3480         if (server->server_type != SILC_ROUTER) {
3481           SilcBuffer tmpbuf;
3482           SilcUInt16 old_ident;
3483
3484           /* If this is pending command callback then we've resolved
3485              it and it didn't work, return since we've notified the
3486              client already in the command reply callback. */
3487           if (cmd->pending)
3488             goto out;
3489           
3490           old_ident = silc_command_get_ident(cmd->payload);
3491           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3492           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3493           
3494           /* Send JOIN command to our router */
3495           silc_server_packet_send(server, (SilcSocketConnection)
3496                                   server->router->connection,
3497                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3498                                   tmpbuf->data, tmpbuf->len, TRUE);
3499           
3500           /* Reprocess this packet after received reply from router */
3501           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3502                                       silc_command_get_ident(cmd->payload),
3503                                       silc_server_command_join,
3504                                       silc_server_command_dup(cmd));
3505           cmd->pending = TRUE;
3506           silc_command_set_ident(cmd->payload, old_ident);
3507           silc_buffer_free(tmpbuf);
3508           goto out;
3509         }
3510         
3511         /* We are router and the channel does not seem exist so we will check
3512            our global list as well for the channel. */
3513         channel = silc_idlist_find_channel_by_name(server->global_list, 
3514                                                    channel_name, NULL);
3515         if (!channel) {
3516           /* Channel really does not exist, create it */
3517           channel = silc_server_create_new_channel(server, server->id, cipher, 
3518                                                    hmac, channel_name, TRUE);
3519           if (!channel) {
3520             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3521                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3522             goto out;
3523           }
3524
3525           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3526           created = TRUE;
3527           create_key = FALSE;
3528         }
3529       }
3530     }
3531   } else {
3532     if (!channel) {
3533       /* Channel not found */
3534
3535       /* If the command came from router and we are normal server then
3536          something went wrong with the joining as the channel was not found.
3537          We can't do anything else but ignore this. */
3538       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3539           server->server_type != SILC_ROUTER)
3540         goto out;
3541       
3542       /* We are router and the channel does not seem exist so we will check
3543          our global list as well for the channel. */
3544       channel = silc_idlist_find_channel_by_name(server->global_list, 
3545                                                  channel_name, NULL);
3546       if (!channel) {
3547         /* Channel really does not exist, create it */
3548         channel = silc_server_create_new_channel(server, server->id, cipher, 
3549                                                  hmac, channel_name, TRUE);
3550         if (!channel) {
3551           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3552                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3553           goto out;
3554         }
3555
3556         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3557         created = TRUE;
3558         create_key = FALSE;
3559       }
3560     }
3561   }
3562
3563   /* Check whether the channel was created by our router */
3564   if (cmd->pending && context2) {
3565     SilcServerCommandReplyContext reply = context2;
3566
3567     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3568       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3569       SILC_GET32_MSB(created, tmp);
3570       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3571         create_key = FALSE;     /* Router returned the key already */
3572     }
3573
3574     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3575         !silc_hash_table_count(channel->user_list))
3576       created = TRUE;
3577   }
3578
3579   /* If the channel does not have global users and is also empty the client
3580      will be the channel founder and operator. */
3581   if (!channel->global_users && !silc_hash_table_count(channel->user_list))
3582     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3583
3584   /* Join to the channel */
3585   silc_server_command_join_channel(server, cmd, channel, client_id,
3586                                    created, create_key, umode,
3587                                    auth, auth_len);
3588
3589   silc_free(client_id);
3590
3591  out:
3592   silc_server_command_free(cmd);
3593 }
3594
3595 /* Server side of command MOTD. Sends server's current "message of the
3596    day" to the client. */
3597
3598 SILC_SERVER_CMD_FUNC(motd)
3599 {
3600   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3601   SilcServer server = cmd->server;
3602   SilcBuffer packet, idp;
3603   char *motd, *dest_server;
3604   SilcUInt32 motd_len;
3605   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3606   
3607   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3608
3609   /* Get server name */
3610   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3611   if (!dest_server) {
3612     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3613                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3614     goto out;
3615   }
3616
3617   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3618     /* Send our MOTD */
3619
3620     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3621
3622     if (server->config && server->config->server_info &&
3623         server->config->server_info->motd_file) {
3624       /* Send motd */
3625       motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3626       if (!motd)
3627         goto out;
3628       
3629       motd[motd_len] = 0;
3630       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3631                                                     SILC_STATUS_OK, 0, 
3632                                                     ident, 2,
3633                                                     2, idp, idp->len,
3634                                                     3, motd, motd_len);
3635     } else {
3636       /* No motd */
3637       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3638                                                     SILC_STATUS_OK, 0, 
3639                                                     ident, 1,
3640                                                     2, idp, idp->len);
3641     }
3642
3643     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3644                             packet->data, packet->len, FALSE);
3645     silc_buffer_free(packet);
3646     silc_buffer_free(idp);
3647   } else {
3648     SilcServerEntry entry;
3649
3650     /* Check whether we have this server cached */
3651     entry = silc_idlist_find_server_by_name(server->global_list,
3652                                             dest_server, TRUE, NULL);
3653     if (!entry) {
3654       entry = silc_idlist_find_server_by_name(server->local_list,
3655                                               dest_server, TRUE, NULL);
3656     }
3657
3658     if (server->server_type != SILC_SERVER && !cmd->pending && 
3659         entry && !entry->motd) {
3660       /* Send to the server */
3661       SilcBuffer tmpbuf;
3662       SilcUInt16 old_ident;
3663
3664       old_ident = silc_command_get_ident(cmd->payload);
3665       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3666       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3667
3668       silc_server_packet_send(server, entry->connection,
3669                               SILC_PACKET_COMMAND, cmd->packet->flags,
3670                               tmpbuf->data, tmpbuf->len, TRUE);
3671
3672       /* Reprocess this packet after received reply from router */
3673       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3674                                   silc_command_get_ident(cmd->payload),
3675                                   silc_server_command_motd,
3676                                   silc_server_command_dup(cmd));
3677       cmd->pending = TRUE;
3678       silc_command_set_ident(cmd->payload, old_ident);
3679       silc_buffer_free(tmpbuf);
3680       goto out;
3681     }
3682
3683     if (!entry && !cmd->pending && !server->standalone) {
3684       /* Send to the primary router */
3685       SilcBuffer tmpbuf;
3686       SilcUInt16 old_ident;
3687
3688       old_ident = silc_command_get_ident(cmd->payload);
3689       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3690       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3691
3692       silc_server_packet_send(server, server->router->connection,
3693                               SILC_PACKET_COMMAND, cmd->packet->flags,
3694                               tmpbuf->data, tmpbuf->len, TRUE);
3695
3696       /* Reprocess this packet after received reply from router */
3697       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3698                                   silc_command_get_ident(cmd->payload),
3699                                   silc_server_command_motd,
3700                                   silc_server_command_dup(cmd));
3701       cmd->pending = TRUE;
3702       silc_command_set_ident(cmd->payload, old_ident);
3703       silc_buffer_free(tmpbuf);
3704       goto out;
3705     }
3706
3707     if (!entry) {
3708       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3709                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3710       goto out;
3711     }
3712
3713     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3714     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3715                                                   SILC_STATUS_OK, 0, ident, 2,
3716                                                   2, idp, idp->len,
3717                                                   3, entry->motd,
3718                                                   entry->motd ? 
3719                                                   strlen(entry->motd) : 0);
3720     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3721                             packet->data, packet->len, FALSE);
3722     silc_buffer_free(packet);
3723     silc_buffer_free(idp);
3724   }
3725
3726  out:
3727   silc_server_command_free(cmd);
3728 }
3729
3730 /* Server side of command UMODE. Client can use this command to set/unset
3731    user mode. Client actually cannot set itself to be as server/router
3732    operator so this can be used only to unset the modes. */
3733
3734 SILC_SERVER_CMD_FUNC(umode)
3735 {
3736   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3737   SilcServer server = cmd->server;
3738   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3739   SilcBuffer packet;
3740   unsigned char *tmp_mask;
3741   SilcUInt32 mask;
3742   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3743
3744   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3745     goto out;
3746
3747   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 2, 2);
3748
3749   /* Get the client's mode mask */
3750   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3751   if (!tmp_mask) {
3752     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3753                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3754     goto out;
3755   }
3756   SILC_GET32_MSB(mask, tmp_mask);
3757
3758   /* Check that mode changing is allowed. */
3759   if (!silc_server_check_umode_rights(server, client, mask)) {
3760     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3761                                           SILC_STATUS_ERR_PERM_DENIED);
3762     goto out;
3763   }
3764
3765   /* Anonymous mode cannot be set by client */
3766   if (mask & SILC_UMODE_ANONYMOUS) {
3767     if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3768       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3769                                             SILC_STATUS_ERR_PERM_DENIED);
3770       goto out;
3771     }
3772   } else {
3773     if (client->mode & SILC_UMODE_ANONYMOUS) {
3774       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3775                                             SILC_STATUS_ERR_PERM_DENIED);
3776       goto out;
3777     }
3778   }
3779
3780   /* Change the mode */
3781   client->mode = mask;
3782
3783   /* Send UMODE change to primary router */
3784   if (!server->standalone)
3785     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3786                                   client->id, client->mode);
3787
3788   /* Send command reply to sender */
3789   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3790                                                 SILC_STATUS_OK, 0, ident, 1,
3791                                                 2, tmp_mask, 4);
3792   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3793                           packet->data, packet->len, FALSE);
3794   silc_buffer_free(packet);
3795
3796  out:
3797   silc_server_command_free(cmd);
3798 }
3799
3800 /* Server side command of CMODE. Changes channel mode */
3801
3802 SILC_SERVER_CMD_FUNC(cmode)
3803 {
3804   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3805   SilcServer server = cmd->server;
3806   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3807   SilcIDListData idata = (SilcIDListData)client;
3808   SilcChannelID *channel_id;
3809   SilcChannelEntry channel;
3810   SilcChannelClientEntry chl;
3811   SilcBuffer packet, cidp;
3812   unsigned char *tmp, *tmp_id, *tmp_mask;
3813   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3814   SilcUInt32 mode_mask, tmp_len, tmp_len2;
3815   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3816
3817   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 2, 7);
3818
3819   /* Get Channel ID */
3820   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3821   if (!tmp_id) {
3822     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3823                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3824     goto out;
3825   }
3826   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3827   if (!channel_id) {
3828     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3829                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3830     goto out;
3831   }
3832
3833   /* Get the channel mode mask */
3834   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3835   if (!tmp_mask) {
3836     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3837                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3838     goto out;
3839   }
3840   SILC_GET32_MSB(mode_mask, tmp_mask);
3841
3842   /* Get channel entry */
3843   channel = silc_idlist_find_channel_by_id(server->local_list, 
3844                                            channel_id, NULL);
3845   if (!channel) {
3846     channel = silc_idlist_find_channel_by_id(server->global_list, 
3847                                              channel_id, NULL);
3848     if (!channel) {
3849       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3850                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3851       goto out;
3852     }
3853   }
3854
3855   /* Check whether this client is on the channel */
3856   if (!silc_server_client_on_channel(client, channel, &chl)) {
3857     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3858                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3859     goto out;
3860   }
3861
3862   /* Check that client has rights to change any requested channel modes */
3863   if (!silc_server_check_cmode_rights(server, channel, chl, mode_mask)) {
3864     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3865                                           (chl->mode == 0 ? 
3866                                            SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3867                                            SILC_STATUS_ERR_NO_CHANNEL_FOPRIV));
3868     goto out;
3869   }
3870
3871   /*
3872    * Check the modes. Modes that requires nothing special operation are
3873    * not checked here.
3874    */
3875
3876   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3877     /* Channel uses private keys to protect traffic. Client(s) has set the
3878        key locally they want to use, server does not know that key. */
3879     /* Nothing interesting to do here */
3880   } else {
3881     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3882       /* The mode is removed and we need to generate and distribute
3883          new channel key. Clients are not using private channel keys
3884          anymore after this. */
3885       
3886       /* Re-generate channel key */
3887       if (!silc_server_create_channel_key(server, channel, 0))
3888         goto out;
3889         
3890       /* Send the channel key. This sends it to our local clients and if
3891          we are normal server to our router as well. */
3892       silc_server_send_channel_key(server, NULL, channel, 
3893                                    server->server_type == SILC_ROUTER ? 
3894                                    FALSE : !server->standalone);
3895         
3896       cipher = channel->channel_key->cipher->name;
3897       hmac = (char *)silc_hmac_get_name(channel->hmac);
3898     }
3899   }
3900
3901   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3902     /* User limit is set on channel */
3903     SilcUInt32 user_limit;
3904       
3905     /* Get user limit */
3906     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3907     if (!tmp) {
3908       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3909         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3911         goto out;
3912       }
3913     } else {
3914       SILC_GET32_MSB(user_limit, tmp);
3915       channel->user_limit = user_limit;
3916     }
3917   } else {
3918     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3919       /* User limit mode is unset. Remove user limit */
3920       channel->user_limit = 0;
3921   }
3922
3923   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3924     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3925       /* Passphrase has been set to channel */
3926       
3927       /* Get the passphrase */
3928       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3929       if (!tmp) {
3930         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3931                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3932         goto out;
3933       }
3934
3935       /* Save the passphrase */
3936       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
3937     }
3938   } else {
3939     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3940       /* Passphrase mode is unset. remove the passphrase */
3941       silc_free(channel->passphrase);
3942       channel->passphrase = NULL;
3943     }
3944   }
3945
3946   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3947     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3948       /* Cipher to use protect the traffic */
3949       SilcCipher newkey, oldkey;
3950
3951       /* Get cipher */
3952       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3953       if (!cipher) {
3954         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3955                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3956         goto out;
3957       }
3958
3959       /* Delete old cipher and allocate the new one */
3960       if (!silc_cipher_alloc(cipher, &newkey)) {
3961         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3962                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3963         goto out;
3964       }
3965
3966       oldkey = channel->channel_key;
3967       channel->channel_key = newkey;
3968
3969       /* Re-generate channel key */
3970       if (!silc_server_create_channel_key(server, channel, 0)) {
3971         /* We don't have new key, revert to old one */
3972         channel->channel_key = oldkey;
3973         goto out;
3974       }
3975
3976       /* Remove old channel key for good */
3977       silc_cipher_free(oldkey);
3978
3979       /* Send the channel key. This sends it to our local clients and if
3980          we are normal server to our router as well. */
3981       silc_server_send_channel_key(server, NULL, channel, 
3982                                    server->server_type == SILC_ROUTER ? 
3983                                    FALSE : !server->standalone);
3984     }
3985   } else {
3986     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3987       /* Cipher mode is unset. Remove the cipher and revert back to 
3988          default cipher */
3989       SilcCipher newkey, oldkey;
3990       cipher = channel->cipher;
3991
3992       /* Delete old cipher and allocate default one */
3993       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
3994         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3996         goto out;
3997       }
3998
3999       oldkey = channel->channel_key;
4000       channel->channel_key = newkey;
4001
4002       /* Re-generate channel key */
4003       if (!silc_server_create_channel_key(server, channel, 0)) {
4004         /* We don't have new key, revert to old one */
4005         channel->channel_key = oldkey;
4006         goto out;
4007       }
4008       
4009       /* Remove old channel key for good */
4010       silc_cipher_free(oldkey);
4011
4012       /* Send the channel key. This sends it to our local clients and if
4013          we are normal server to our router as well. */
4014       silc_server_send_channel_key(server, NULL, channel, 
4015                                    server->server_type == SILC_ROUTER ? 
4016                                    FALSE : !server->standalone);
4017     }
4018   }
4019
4020   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4021     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4022       /* HMAC to use protect the traffic */
4023       unsigned char hash[32];
4024       SilcHmac newhmac;
4025
4026       /* Get hmac */
4027       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4028       if (!hmac) {
4029         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4030                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4031         goto out;
4032       }
4033
4034       /* Delete old hmac and allocate the new one */
4035       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4036         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4037                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4038         goto out;
4039       }
4040
4041       silc_hmac_free(channel->hmac);
4042       channel->hmac = newhmac;
4043
4044       /* Set the HMAC key out of current channel key. The client must do
4045          this locally. */
4046       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4047                      channel->key_len / 8, hash);
4048       silc_hmac_set_key(channel->hmac, hash, 
4049                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4050       memset(hash, 0, sizeof(hash));
4051     }
4052   } else {
4053     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4054       /* Hmac mode is unset. Remove the hmac and revert back to 
4055          default hmac */
4056       SilcHmac newhmac;
4057       unsigned char hash[32];
4058       hmac = channel->hmac_name;
4059
4060       /* Delete old hmac and allocate default one */
4061       silc_hmac_free(channel->hmac);
4062       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4063         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4064                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
4065         goto out;
4066       }
4067
4068       silc_hmac_free(channel->hmac);
4069       channel->hmac = newhmac;
4070
4071       /* Set the HMAC key out of current channel key. The client must do
4072          this locally. */
4073       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4074                      channel->key_len / 8, 
4075                      hash);
4076       silc_hmac_set_key(channel->hmac, hash, 
4077                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4078       memset(hash, 0, sizeof(hash));
4079     }
4080   }
4081
4082   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4083     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4084       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4085         /* Set the founder authentication */
4086         SilcAuthPayload auth;
4087         
4088         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4089         if (!tmp) {
4090           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4091                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4092           goto out;
4093         }
4094
4095         auth = silc_auth_payload_parse(tmp, tmp_len);
4096         if (!auth) {
4097           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4098                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4099           goto out;
4100         }
4101
4102         /* Save the public key */
4103         tmp = silc_pkcs_public_key_encode(idata->public_key, &tmp_len);
4104         silc_pkcs_public_key_decode(tmp, tmp_len, &channel->founder_key);
4105         silc_free(tmp);
4106         
4107         channel->founder_method = silc_auth_get_method(auth);
4108
4109         if (channel->founder_method == SILC_AUTH_PASSWORD) {
4110           tmp = silc_auth_get_data(auth, &tmp_len);
4111           channel->founder_passwd = silc_memdup(tmp, tmp_len);
4112           channel->founder_passwd_len = tmp_len;
4113         } else {
4114           /* Verify the payload before setting the mode */
4115           if (!silc_auth_verify(auth, channel->founder_method, 
4116                                 channel->founder_key, 0, idata->hash,
4117                                 client->id, SILC_ID_CLIENT)) {
4118             silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4119                                                   SILC_STATUS_ERR_AUTH_FAILED);
4120             goto out;
4121           }
4122         }
4123
4124         silc_auth_payload_free(auth);
4125       }
4126     }
4127   } else {
4128     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4129       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4130         if (channel->founder_key)
4131           silc_pkcs_public_key_free(channel->founder_key);
4132         if (channel->founder_passwd) {
4133           silc_free(channel->founder_passwd);
4134           channel->founder_passwd = NULL;
4135         }
4136       }
4137     }
4138   }
4139
4140   /* Finally, set the mode */
4141   channel->mode = mode_mask;
4142
4143   /* Send CMODE_CHANGE notify. */
4144   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4145   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4146                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 5,
4147                                      cidp->data, cidp->len, 
4148                                      tmp_mask, 4,
4149                                      cipher, cipher ? strlen(cipher) : 0,
4150                                      hmac, hmac ? strlen(hmac) : 0,
4151                                      passphrase, passphrase ? 
4152                                      strlen(passphrase) : 0);
4153
4154   /* Set CMODE notify type to network */
4155   if (!server->standalone)
4156     silc_server_send_notify_cmode(server, server->router->connection,
4157                                   server->server_type == SILC_ROUTER ? 
4158                                   TRUE : FALSE, channel,
4159                                   mode_mask, client->id, SILC_ID_CLIENT,
4160                                   cipher, hmac, passphrase);
4161
4162   /* Send command reply to sender */
4163   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4164                                                 SILC_STATUS_OK, 0, ident, 2,
4165                                                 2, tmp_id, tmp_len2,
4166                                                 3, tmp_mask, 4);
4167   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4168                           packet->data, packet->len, FALSE);
4169     
4170   silc_buffer_free(packet);
4171   silc_free(channel_id);
4172   silc_buffer_free(cidp);
4173
4174  out:
4175   silc_server_command_free(cmd);
4176 }
4177
4178 /* Server side of CUMODE command. Changes client's mode on a channel. */
4179
4180 SILC_SERVER_CMD_FUNC(cumode)
4181 {
4182   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4183   SilcServer server = cmd->server;
4184   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4185   SilcIDListData idata = (SilcIDListData)client;
4186   SilcChannelID *channel_id;
4187   SilcClientID *client_id;
4188   SilcChannelEntry channel;
4189   SilcClientEntry target_client;
4190   SilcChannelClientEntry chl;
4191   SilcBuffer packet, idp;
4192   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4193   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4194   int notify = FALSE;
4195   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4196
4197   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4198
4199   /* Get Channel ID */
4200   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4201   if (!tmp_ch_id) {
4202     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4203                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4204     goto out;
4205   }
4206   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4207   if (!channel_id) {
4208     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4209                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4210     goto out;
4211   }
4212
4213   /* Get channel entry */
4214   channel = silc_idlist_find_channel_by_id(server->local_list, 
4215                                            channel_id, NULL);
4216   if (!channel) {
4217     channel = silc_idlist_find_channel_by_id(server->global_list, 
4218                                              channel_id, NULL);
4219     if (!channel) {
4220       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4221                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4222       goto out;
4223     }
4224   }
4225
4226   /* Check whether sender is on the channel */
4227   if (!silc_server_client_on_channel(client, channel, &chl)) {
4228     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4229                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4230     goto out;
4231   }
4232   sender_mask = chl->mode;
4233   
4234   /* Get the target client's channel mode mask */
4235   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4236   if (!tmp_mask) {
4237     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4238                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4239     goto out;
4240   }
4241   SILC_GET32_MSB(target_mask, tmp_mask);
4242
4243   /* Get target Client ID */
4244   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4245   if (!tmp_id) {
4246     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4247                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4248     goto out;
4249   }
4250   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4251   if (!client_id) {
4252     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4253                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4254     goto out;
4255   }
4256
4257   /* Get target client's entry */
4258   target_client = silc_idlist_find_client_by_id(server->local_list, 
4259                                                 client_id, TRUE, NULL);
4260   if (!target_client) {
4261     target_client = silc_idlist_find_client_by_id(server->global_list, 
4262                                                   client_id, TRUE, NULL);
4263   }
4264
4265   if (target_client != client &&
4266       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4267       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4268     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4269                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4270     goto out;
4271   }
4272
4273   /* Check whether target client is on the channel */
4274   if (target_client != client) {
4275     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4276       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4277                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4278       goto out;
4279     }
4280   }
4281
4282   /* 
4283    * Change the mode 
4284    */
4285
4286   /* If the target client is founder, no one else can change their mode
4287      but themselves. */
4288   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4289     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4290                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4291     goto out;
4292   }
4293
4294   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4295     if (target_client != client) {
4296       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4297                                             SILC_STATUS_ERR_NOT_YOU);
4298       goto out;
4299     }
4300
4301     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4302       /* The client tries to claim the founder rights. */
4303       unsigned char *tmp_auth;
4304       SilcUInt32 tmp_auth_len, auth_len;
4305       void *auth;
4306       
4307       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4308           !channel->founder_key || !idata->public_key ||
4309           !silc_pkcs_public_key_compare(channel->founder_key, 
4310                                         idata->public_key)) {
4311         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4312                                               SILC_STATUS_ERR_NOT_YOU);
4313         goto out;
4314       }
4315
4316       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4317       if (!tmp_auth) {
4318         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4319                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4320         goto out;
4321       }
4322
4323       auth = (channel->founder_method == SILC_AUTH_PASSWORD ?
4324               (void *)channel->founder_passwd : (void *)channel->founder_key);
4325       auth_len = (channel->founder_method == SILC_AUTH_PASSWORD ?
4326                   channel->founder_passwd_len : 0);
4327       
4328       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len,
4329                                  channel->founder_method, auth, auth_len,
4330                                  idata->hash, client->id, SILC_ID_CLIENT)) {
4331         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4332                                               SILC_STATUS_ERR_AUTH_FAILED);
4333         goto out;
4334       }
4335       
4336       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4337       notify = TRUE;
4338     }
4339   } else {
4340     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4341       if (target_client == client) {
4342         /* Remove channel founder rights from itself */
4343         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4344         notify = TRUE;
4345       } else {
4346         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4347                                               SILC_STATUS_ERR_NOT_YOU);
4348         goto out;
4349       }
4350     }
4351   }
4352
4353   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4354     /* Promote to operator */
4355     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4356       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4357           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4358         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4359                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4360         goto out;
4361       }
4362
4363       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4364       notify = TRUE;
4365     }
4366   } else {
4367     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4368       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4369           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4370         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4371                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4372         goto out;
4373       }
4374
4375       /* Demote to normal user */
4376       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4377       notify = TRUE;
4378     }
4379   }
4380
4381   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4382     if (target_client != client) {
4383       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4384                                             SILC_STATUS_ERR_NOT_YOU);
4385       goto out;
4386     }
4387
4388     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4389       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4390       notify = TRUE;
4391     }
4392   } else {
4393     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4394       if (target_client != client) {
4395         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4396                                               SILC_STATUS_ERR_NOT_YOU);
4397         goto out;
4398       }
4399
4400       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4401       notify = TRUE;
4402     }
4403   }
4404
4405
4406   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4407   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4408
4409   /* Send notify to channel, notify only if mode was actually changed. */
4410   if (notify) {
4411     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4412                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
4413                                        idp->data, idp->len,
4414                                        tmp_mask, 4, 
4415                                        tmp_id, tmp_len);
4416
4417     /* Set CUMODE notify type to network */
4418     if (!server->standalone)
4419       silc_server_send_notify_cumode(server, server->router->connection,
4420                                      server->server_type == SILC_ROUTER ? 
4421                                      TRUE : FALSE, channel,
4422                                      target_mask, client->id, 
4423                                      SILC_ID_CLIENT,
4424                                      target_client->id);
4425   }
4426
4427   /* Send command reply to sender */
4428   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4429                                                 SILC_STATUS_OK, 0, ident, 3,
4430                                                 2, tmp_mask, 4,
4431                                                 3, tmp_ch_id, tmp_ch_len,
4432                                                 4, tmp_id, tmp_len);
4433   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4434                           packet->data, packet->len, FALSE);
4435     
4436   silc_buffer_free(packet);
4437   silc_free(channel_id);
4438   silc_free(client_id);
4439   silc_buffer_free(idp);
4440
4441  out:
4442   silc_server_command_free(cmd);
4443 }
4444
4445 /* Server side of KICK command. Kicks client out of channel. */
4446
4447 SILC_SERVER_CMD_FUNC(kick)
4448 {
4449   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4450   SilcServer server = cmd->server;
4451   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4452   SilcClientEntry target_client;
4453   SilcChannelID *channel_id;
4454   SilcClientID *client_id;
4455   SilcChannelEntry channel;
4456   SilcChannelClientEntry chl;
4457   SilcBuffer idp;
4458   SilcUInt32 tmp_len, target_idp_len;
4459   unsigned char *tmp, *comment, *target_idp;
4460
4461   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4462
4463   /* Get Channel ID */
4464   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4465   if (!tmp) {
4466     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4467                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4468     goto out;
4469   }
4470   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4471   if (!channel_id) {
4472     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4473                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4474     goto out;
4475   }
4476
4477   /* Get channel entry */
4478   channel = silc_idlist_find_channel_by_id(server->local_list, 
4479                                            channel_id, NULL);
4480   if (!channel) {
4481     channel = silc_idlist_find_channel_by_id(server->local_list, 
4482                                              channel_id, NULL);
4483     if (!channel) {
4484       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4485                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4486       goto out;
4487     }
4488   }
4489
4490   /* Check whether sender is on the channel */
4491   if (!silc_server_client_on_channel(client, channel, &chl)) {
4492     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4493                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4494     goto out;
4495   }
4496
4497   /* Check that the kicker is channel operator or channel founder */
4498   if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
4499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4500                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4501     goto out;
4502   }
4503   
4504   /* Get target Client ID */
4505   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4506   if (!target_idp) {
4507     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4508                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4509     goto out;
4510   }
4511   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4512   if (!client_id) {
4513     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4514                                           SILC_STATUS_ERR_NO_CLIENT_ID);
4515     goto out;
4516   }
4517
4518   /* Get target client's entry */
4519   target_client = silc_idlist_find_client_by_id(server->local_list, 
4520                                                 client_id, TRUE, NULL);
4521   if (!target_client) {
4522     target_client = silc_idlist_find_client_by_id(server->global_list, 
4523                                                   client_id, TRUE, NULL);
4524   }
4525
4526   /* Check whether target client is on the channel */
4527   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4528     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4529                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
4530     goto out;
4531   }
4532
4533   /* Check that the target client is not channel founder. Channel founder
4534      cannot be kicked from the channel. */
4535   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4536     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4537                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
4538     goto out;
4539   }
4540   
4541   /* Get comment */
4542   tmp_len = 0;
4543   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4544   if (tmp_len > 128)
4545     comment = NULL;
4546
4547   /* Send command reply to sender */
4548   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4549                                         SILC_STATUS_OK);
4550
4551   /* Send KICKED notify to local clients on the channel */
4552   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4553   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4554                                      SILC_NOTIFY_TYPE_KICKED, 3,
4555                                      target_idp, target_idp_len,
4556                                      comment, comment ? strlen(comment) : 0,
4557                                      idp->data, idp->len);
4558   silc_buffer_free(idp);
4559
4560   /* Remove the client from the channel. If the channel does not exist
4561      after removing the client then the client kicked itself off the channel
4562      and we don't have to send anything after that. */
4563   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4564                                            target_client, FALSE))
4565     goto out;
4566
4567   /* Send KICKED notify to primary route */
4568   if (!server->standalone)
4569     silc_server_send_notify_kicked(server, server->router->connection,
4570                                    server->server_type == SILC_ROUTER ?
4571                                    TRUE : FALSE, channel,
4572                                    target_client->id, client->id, comment);
4573
4574   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4575     /* Re-generate channel key */
4576     if (!silc_server_create_channel_key(server, channel, 0))
4577       goto out;
4578     
4579     /* Send the channel key to the channel. The key of course is not sent
4580        to the client who was kicked off the channel. */
4581     silc_server_send_channel_key(server, target_client->connection, channel, 
4582                                  server->server_type == SILC_ROUTER ? 
4583                                  FALSE : !server->standalone);
4584   }
4585
4586  out:
4587   silc_server_command_free(cmd);
4588 }
4589
4590 /* Server side of OPER command. Client uses this comand to obtain server
4591    operator privileges to this server/router. */
4592
4593 SILC_SERVER_CMD_FUNC(oper)
4594 {
4595   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4596   SilcServer server = cmd->server;
4597   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4598   unsigned char *username, *auth;
4599   SilcUInt32 tmp_len;
4600   SilcServerConfigAdmin *admin;
4601   SilcIDListData idata = (SilcIDListData)client;
4602   bool result = FALSE;
4603   SilcPublicKey cached_key;
4604
4605   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4606
4607   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4608     goto out;
4609
4610   /* Get the username */
4611   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4612   if (!username) {
4613     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4614                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4615     goto out;
4616   }
4617
4618   /* Get the admin configuration */
4619   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4620                                         username, client->nickname);
4621   if (!admin) {
4622     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4623                                           username, client->nickname);
4624     if (!admin) {
4625       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4626                                             SILC_STATUS_ERR_AUTH_FAILED);
4627       goto out;
4628     }
4629   }
4630
4631   /* Get the authentication payload */
4632   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4633   if (!auth) {
4634     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4635                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4636     goto out;
4637   }
4638
4639   /* Verify the authentication data. If both passphrase and public key
4640      is set then try both of them. */
4641   if (admin->passphrase)
4642     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4643                                    admin->passphrase, admin->passphrase_len,
4644                                    idata->hash, client->id, SILC_ID_CLIENT);
4645   if (!result && admin->publickeys) {
4646     cached_key = silc_server_get_public_key(server, admin->publickeys);
4647     if (!cached_key)
4648       goto out;
4649     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4650                                    cached_key, 0, idata->hash, 
4651                                    client->id, SILC_ID_CLIENT);
4652   }
4653   if (!result) {
4654     /* Authentication failed */
4655     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4656                                           SILC_STATUS_ERR_AUTH_FAILED);
4657     goto out;
4658   }
4659
4660   /* Client is now server operator */
4661   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4662
4663   /* Update statistics */
4664   if (client->connection)
4665     server->stat.my_server_ops++;
4666   if (server->server_type == SILC_ROUTER)
4667     server->stat.server_ops++;
4668
4669   /* Send UMODE change to primary router */
4670   if (!server->standalone)
4671     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4672                                   client->id, client->mode);
4673
4674   /* Send reply to the sender */
4675   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4676                                         SILC_STATUS_OK);
4677
4678  out:
4679   silc_server_command_free(cmd);
4680 }
4681
4682 /* Server side of SILCOPER command. Client uses this comand to obtain router
4683    operator privileges to this router. */
4684
4685 SILC_SERVER_CMD_FUNC(silcoper)
4686 {
4687   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4688   SilcServer server = cmd->server;
4689   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4690   unsigned char *username, *auth;
4691   SilcUInt32 tmp_len;
4692   SilcServerConfigAdmin *admin;
4693   SilcIDListData idata = (SilcIDListData)client;
4694   bool result = FALSE;
4695   SilcPublicKey cached_key;
4696
4697   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4698
4699   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4700     goto out;
4701
4702   if (server->server_type != SILC_ROUTER) {
4703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4704                                           SILC_STATUS_ERR_AUTH_FAILED);
4705     goto out;
4706   }
4707
4708   /* Get the username */
4709   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4710   if (!username) {
4711     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4712                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4713     goto out;
4714   }
4715
4716   /* Get the admin configuration */
4717   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4718                                         username, client->nickname);
4719   if (!admin) {
4720     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4721                                           username, client->nickname);
4722     if (!admin) {
4723       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4724                                             SILC_STATUS_ERR_AUTH_FAILED);
4725       goto out;
4726     }
4727   }
4728
4729   /* Get the authentication payload */
4730   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4731   if (!auth) {
4732     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4733                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4734     goto out;
4735   }
4736
4737   /* Verify the authentication data. If both passphrase and public key
4738      is set then try both of them. */
4739   if (admin->passphrase)
4740     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4741                                    admin->passphrase, admin->passphrase_len,
4742                                    idata->hash, client->id, SILC_ID_CLIENT);
4743   if (!result && admin->publickeys) {
4744     cached_key = silc_server_get_public_key(server, admin->publickeys);
4745     if (!cached_key)
4746       goto out;
4747     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4748                                    cached_key, 0, idata->hash, 
4749                                    client->id, SILC_ID_CLIENT);
4750   }
4751   if (!result) {
4752     /* Authentication failed */
4753     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4754                                           SILC_STATUS_ERR_AUTH_FAILED);
4755     goto out;
4756   }
4757
4758   /* Client is now router operator */
4759   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4760
4761   /* Update statistics */
4762   if (client->connection)
4763     server->stat.my_router_ops++;
4764   if (server->server_type == SILC_ROUTER)
4765     server->stat.router_ops++;
4766
4767   /* Send UMODE change to primary router */
4768   if (!server->standalone)
4769     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4770                                   client->id, client->mode);
4771
4772   /* Send reply to the sender */
4773   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4774                                         SILC_STATUS_OK);
4775
4776  out:
4777   silc_server_command_free(cmd);
4778 }
4779
4780 /* Server side of command BAN. This is used to manage the ban list of the
4781    channel. To add clients and remove clients from the ban list. */
4782
4783 SILC_SERVER_CMD_FUNC(ban)
4784 {
4785   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4786   SilcServer server = cmd->server;
4787   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4788   SilcBuffer packet;
4789   SilcChannelEntry channel;
4790   SilcChannelClientEntry chl;
4791   SilcChannelID *channel_id = NULL;
4792   unsigned char *id, *add, *del;
4793   SilcUInt32 id_len, tmp_len;
4794   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4795
4796   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4797     goto out;
4798
4799   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
4800
4801   /* Get Channel ID */
4802   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4803   if (id) {
4804     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
4805     if (!channel_id) {
4806       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4807                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4808       goto out;
4809     }
4810   }
4811
4812   /* Get channel entry. The server must know about the channel since the
4813      client is expected to be on the channel. */
4814   channel = silc_idlist_find_channel_by_id(server->local_list, 
4815                                            channel_id, NULL);
4816   if (!channel) {
4817     channel = silc_idlist_find_channel_by_id(server->global_list, 
4818                                              channel_id, NULL);
4819     if (!channel) {
4820       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4821                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4822       goto out;
4823     }
4824   }
4825
4826   /* Check whether this client is on the channel */
4827   if (!silc_server_client_on_channel(client, channel, &chl)) {
4828     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4829                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4830     goto out;
4831   }
4832
4833   /* The client must be at least channel operator. */
4834   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4835     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4836                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4837     goto out;
4838   }
4839
4840   /* Get the new ban and add it to the ban list */
4841   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4842   if (add) {
4843     if (!channel->ban_list)
4844       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4845     else
4846       channel->ban_list = silc_realloc(channel->ban_list, 
4847                                        sizeof(*channel->ban_list) * 
4848                                        (tmp_len + 
4849                                         strlen(channel->ban_list) + 2));
4850     if (add[tmp_len - 1] == ',')
4851       add[tmp_len - 1] = '\0';
4852
4853     strncat(channel->ban_list, add, tmp_len);
4854     strncat(channel->ban_list, ",", 1);
4855   }
4856
4857   /* Get the ban to be removed and remove it from the list */
4858   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4859   if (del && channel->ban_list) {
4860     char *start, *end, *n;
4861
4862     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4863       silc_free(channel->ban_list);
4864       channel->ban_list = NULL;
4865     } else {
4866       start = strstr(channel->ban_list, del);
4867       if (start && strlen(start) >= tmp_len) {
4868         end = start + tmp_len;
4869         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4870         strncat(n, channel->ban_list, start - channel->ban_list);
4871         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4872                              end) - 1);
4873         silc_free(channel->ban_list);
4874         channel->ban_list = n;
4875       }
4876     }
4877   }
4878
4879   /* Send the BAN notify type to our primary router. */
4880   if (!server->standalone && (add || del))
4881     silc_server_send_notify_ban(server, server->router->connection,
4882                                 server->server_type == SILC_ROUTER ?
4883                                 TRUE : FALSE, channel, add, del);
4884
4885   /* Send the reply back to the client */
4886   packet = 
4887     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4888                                          SILC_STATUS_OK, 0, ident, 2,
4889                                          2, id, id_len,
4890                                          3, channel->ban_list, 
4891                                          channel->ban_list ? 
4892                                          strlen(channel->ban_list) -1 : 0);
4893   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4894                           packet->data, packet->len, FALSE);
4895     
4896   silc_buffer_free(packet);
4897
4898  out:
4899   silc_free(channel_id);
4900   silc_server_command_free(cmd);
4901 }
4902
4903 /* Server side command of LEAVE. Removes client from a channel. */
4904
4905 SILC_SERVER_CMD_FUNC(leave)
4906 {
4907   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4908   SilcServer server = cmd->server;
4909   SilcSocketConnection sock = cmd->sock;
4910   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4911   SilcChannelID *id = NULL;
4912   SilcChannelEntry channel;
4913   SilcUInt32 len;
4914   unsigned char *tmp;
4915
4916   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4917
4918   /* Get Channel ID */
4919   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4920   if (!tmp) {
4921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4922                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4923     goto out;
4924   }
4925   id = silc_id_payload_parse_id(tmp, len, NULL);
4926   if (!id) {
4927     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4928                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4929     goto out;
4930   }
4931
4932   /* Get channel entry */
4933   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4934   if (!channel) {
4935     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4936     if (!channel) {
4937       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4938                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4939       goto out;
4940     }
4941   }
4942
4943   /* Check whether this client is on the channel */
4944   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4945     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4946                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4947     goto out;
4948   }
4949
4950   /* Notify routers that they should remove this client from their list
4951      of clients on the channel. Send LEAVE notify type. */
4952   if (!server->standalone)
4953     silc_server_send_notify_leave(server, server->router->connection,
4954                                   server->server_type == SILC_ROUTER ?
4955                                   TRUE : FALSE, channel, id_entry->id);
4956
4957   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4958                                        SILC_STATUS_OK, 2, tmp, len);
4959
4960   /* Remove client from channel */
4961   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4962                                            TRUE))
4963     /* If the channel does not exist anymore we won't send anything */
4964     goto out;
4965
4966   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4967     /* Re-generate channel key */
4968     if (!silc_server_create_channel_key(server, channel, 0))
4969       goto out;
4970
4971     /* Send the channel key */
4972     silc_server_send_channel_key(server, NULL, channel, 
4973                                  server->server_type == SILC_ROUTER ? 
4974                                  FALSE : !server->standalone);
4975   }
4976
4977  out:
4978   silc_free(id);
4979   silc_server_command_free(cmd);
4980 }
4981
4982 /* Server side of command USERS. Resolves clients and their USERS currently
4983    joined on the requested channel. The list of Client ID's and their modes
4984    on the channel is sent back. */
4985
4986 SILC_SERVER_CMD_FUNC(users)
4987 {
4988   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4989   SilcServer server = cmd->server;
4990   SilcChannelEntry channel;
4991   SilcChannelID *id = NULL;
4992   SilcBuffer packet, idp;
4993   unsigned char *channel_id;
4994   SilcUInt32 channel_id_len;
4995   SilcBuffer client_id_list;
4996   SilcBuffer client_mode_list;
4997   unsigned char lc[4];
4998   SilcUInt32 list_count = 0;
4999   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5000   char *channel_name;
5001
5002   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5003
5004   /* Get Channel ID */
5005   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5006
5007   /* Get channel name */
5008   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5009
5010   if (!channel_id && !channel_name) {
5011     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5012                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
5013     goto out;
5014   }
5015
5016   if (channel_id) {
5017     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5018     if (!id) {
5019       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5020                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
5021       goto out;
5022     }
5023   }
5024
5025   /* If we are server and we don't know about this channel we will send
5026      the command to our router. If we know about the channel then we also
5027      have the list of users already. */
5028   if (id)
5029     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5030   else
5031     channel = silc_idlist_find_channel_by_name(server->local_list, 
5032                                                channel_name, NULL);
5033
5034   if (!channel || channel->disabled) {
5035     if (server->server_type != SILC_ROUTER && !server->standalone &&
5036         !cmd->pending) {
5037       SilcBuffer tmpbuf;
5038       
5039       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5040       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5041       
5042       /* Send USERS command */
5043       silc_server_packet_send(server, server->router->connection,
5044                               SILC_PACKET_COMMAND, cmd->packet->flags,
5045                               tmpbuf->data, tmpbuf->len, TRUE);
5046       
5047       /* Reprocess this packet after received reply */
5048       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5049                                   silc_command_get_ident(cmd->payload),
5050                                   silc_server_command_users,
5051                                   silc_server_command_dup(cmd));
5052       cmd->pending = TRUE;
5053       silc_command_set_ident(cmd->payload, ident);
5054       silc_buffer_free(tmpbuf);
5055       silc_free(id);
5056       goto out;
5057     }
5058
5059     /* Check the global list as well. */
5060     if (id)
5061       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5062     else
5063       channel = silc_idlist_find_channel_by_name(server->global_list, 
5064                                                  channel_name, NULL);
5065     if (!channel) {
5066       /* Channel really does not exist */
5067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5068                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5069       goto out;
5070     }
5071   }
5072
5073   /* If the channel is private or secret do not send anything, unless the
5074      user requesting this command is on the channel. */
5075   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5076     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5077         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5078                                           NULL)) {
5079       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5080                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5081       goto out;
5082     }
5083   } else {
5084     if (channel->mode & 
5085         (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)) {
5086       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5087                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
5088       goto out;
5089     }
5090   }
5091
5092   /* Get the users list */
5093   silc_server_get_users_on_channel(server, channel, &client_id_list,
5094                                    &client_mode_list, &list_count);
5095
5096   /* List count */
5097   SILC_PUT32_MSB(list_count, lc);
5098
5099   /* Send reply */
5100   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5101   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5102                                                 SILC_STATUS_OK, 0, ident, 4,
5103                                                 2, idp->data, idp->len,
5104                                                 3, lc, 4,
5105                                                 4, client_id_list->data,
5106                                                 client_id_list->len,
5107                                                 5, client_mode_list->data,
5108                                                 client_mode_list->len);
5109   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5110                           packet->data, packet->len, FALSE);
5111     
5112   silc_buffer_free(idp);
5113   silc_buffer_free(packet);
5114   silc_buffer_free(client_id_list);
5115   silc_buffer_free(client_mode_list);
5116   silc_free(id);
5117
5118  out:
5119   silc_server_command_free(cmd);
5120 }
5121
5122 /* Server side of command GETKEY. This fetches the client's public key
5123    from the server where to the client is connected. */
5124
5125 SILC_SERVER_CMD_FUNC(getkey)
5126 {
5127   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5128   SilcServer server = cmd->server;
5129   SilcBuffer packet;
5130   SilcClientEntry client;
5131   SilcServerEntry server_entry;
5132   SilcClientID *client_id = NULL;
5133   SilcServerID *server_id = NULL;
5134   SilcIDPayload idp = NULL;
5135   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5136   unsigned char *tmp, *pkdata;
5137   SilcUInt32 tmp_len, pklen;
5138   SilcBuffer pk = NULL;
5139   SilcIdType id_type;
5140   SilcPublicKey public_key;
5141
5142   SILC_LOG_DEBUG(("Start"));
5143
5144   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5145   if (!tmp) {
5146     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5147                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5148     goto out;
5149   }
5150   idp = silc_id_payload_parse(tmp, tmp_len);
5151   if (!idp) {
5152     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5153                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5154     goto out;
5155   }
5156
5157   id_type = silc_id_payload_get_type(idp);
5158   if (id_type == SILC_ID_CLIENT) {
5159     client_id = silc_id_payload_get_id(idp);
5160
5161     /* If the client is not found from local list there is no chance it
5162        would be locally connected client so send the command further. */
5163     client = silc_idlist_find_client_by_id(server->local_list, 
5164                                            client_id, TRUE, NULL);
5165     if (!client)
5166       client = silc_idlist_find_client_by_id(server->global_list, 
5167                                              client_id, TRUE, NULL);
5168     
5169     if ((!client && !cmd->pending && !server->standalone) ||
5170         (client && !client->connection && !cmd->pending) ||
5171         (client && !client->data.public_key && !cmd->pending)) {
5172       SilcBuffer tmpbuf;
5173       SilcUInt16 old_ident;
5174       SilcSocketConnection dest_sock;
5175       
5176       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5177                                                client_id, NULL, NULL);
5178       if (!dest_sock)
5179         goto out;
5180       
5181       old_ident = silc_command_get_ident(cmd->payload);
5182       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5183       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5184       
5185       silc_server_packet_send(server, dest_sock,
5186                               SILC_PACKET_COMMAND, cmd->packet->flags,
5187                               tmpbuf->data, tmpbuf->len, TRUE);
5188       
5189       /* Reprocess this packet after received reply from router */
5190       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5191                                   silc_command_get_ident(cmd->payload),
5192                                   silc_server_command_getkey,
5193                                   silc_server_command_dup(cmd));
5194       cmd->pending = TRUE;
5195       silc_command_set_ident(cmd->payload, old_ident);
5196       silc_buffer_free(tmpbuf);
5197       goto out;
5198     }
5199
5200     if (!client) {
5201       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5202                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
5203       goto out;
5204     }
5205
5206     /* The client is locally connected, just get the public key and
5207        send it back. If they key does not exist then do not send it, 
5208        send just OK reply */
5209     public_key = client->data.public_key;
5210     if (!public_key) {
5211       pkdata = NULL;
5212       pklen = 0;
5213     } else {
5214       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5215       pk = silc_buffer_alloc(4 + tmp_len);
5216       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5217       silc_buffer_format(pk,
5218                          SILC_STR_UI_SHORT(tmp_len),
5219                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5220                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5221                          SILC_STR_END);
5222       silc_free(tmp);
5223       pkdata = pk->data;
5224       pklen = pk->len;
5225     }
5226   } else if (id_type == SILC_ID_SERVER) {
5227     server_id = silc_id_payload_get_id(idp);
5228
5229     /* If the server is not found from local list there is no chance it
5230        would be locally connected server so send the command further. */
5231     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5232                                                  server_id, TRUE, NULL);
5233     if (!server_entry)
5234       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5235                                                    server_id, TRUE, NULL);
5236     
5237     if (server_entry != server->id_entry &&
5238         ((!server_entry && !cmd->pending && !server->standalone) ||
5239          (server_entry && !server_entry->connection && !cmd->pending &&
5240           !server->standalone) ||
5241          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5242           !server->standalone))) {
5243       SilcBuffer tmpbuf;
5244       SilcUInt16 old_ident;
5245       
5246       old_ident = silc_command_get_ident(cmd->payload);
5247       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5248       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5249       
5250       silc_server_packet_send(server, server->router->connection,
5251                               SILC_PACKET_COMMAND, cmd->packet->flags,
5252                               tmpbuf->data, tmpbuf->len, TRUE);
5253       
5254       /* Reprocess this packet after received reply from router */
5255       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5256                                   silc_command_get_ident(cmd->payload),
5257                                   silc_server_command_getkey,
5258                                   silc_server_command_dup(cmd));
5259       cmd->pending = TRUE;
5260       silc_command_set_ident(cmd->payload, old_ident);
5261       silc_buffer_free(tmpbuf);
5262       goto out;
5263     }
5264
5265     if (!server_entry) {
5266       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5267                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
5268       goto out;
5269     }
5270
5271     /* If they key does not exist then do not send it, send just OK reply */
5272     public_key = (!server_entry->data.public_key ? 
5273                   (server_entry == server->id_entry ? server->public_key :
5274                    NULL) : server_entry->data.public_key);
5275     if (!public_key) {
5276       pkdata = NULL;
5277       pklen = 0;
5278     } else {
5279       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5280       pk = silc_buffer_alloc(4 + tmp_len);
5281       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5282       silc_buffer_format(pk,
5283                          SILC_STR_UI_SHORT(tmp_len),
5284                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5285                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5286                          SILC_STR_END);
5287       silc_free(tmp);
5288       pkdata = pk->data;
5289       pklen = pk->len;
5290     }
5291   } else {
5292     goto out;
5293   }
5294
5295   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5296   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5297                                                 SILC_STATUS_OK, 0, ident, 
5298                                                 pkdata ? 2 : 1,
5299                                                 2, tmp, tmp_len,
5300                                                 3, pkdata, pklen);
5301   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5302                           packet->data, packet->len, FALSE);
5303   silc_buffer_free(packet);
5304
5305   if (pk)
5306     silc_buffer_free(pk);
5307
5308  out:
5309   if (idp)
5310     silc_id_payload_free(idp);
5311   silc_free(client_id);
5312   silc_free(server_id);
5313   silc_server_command_free(cmd);
5314 }
5315
5316
5317 /* Private range commands, specific to this implementation */
5318
5319 /* Server side command of CONNECT. Connects us to the specified remote
5320    server or router. */
5321
5322 SILC_SERVER_CMD_FUNC(connect)
5323 {
5324   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5325   SilcServer server = cmd->server;
5326   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5327   unsigned char *tmp, *host;
5328   SilcUInt32 tmp_len;
5329   SilcUInt32 port = SILC_PORT;
5330
5331   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5332
5333   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5334     goto out;
5335
5336   /* Check whether client has the permissions. */
5337   if (client->mode == SILC_UMODE_NONE) {
5338     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5339                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5340     goto out;
5341   }
5342
5343   if (server->server_type == SILC_ROUTER && 
5344       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5345     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5346                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
5347     goto out;
5348   }
5349
5350   /* Get the remote server */
5351   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5352   if (!host) {
5353     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5354                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5355     goto out;
5356   }
5357
5358   /* Get port */
5359   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5360   if (tmp)
5361     SILC_GET32_MSB(port, tmp);
5362
5363   /* Create the connection. It is done with timeout and is async. */
5364   silc_server_create_connection(server, host, port);
5365
5366   /* Send reply to the sender */
5367   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5368                                         SILC_STATUS_OK);
5369
5370  out:
5371   silc_server_command_free(cmd);
5372 }
5373
5374 /* Server side command of CLOSE. Closes connection to a specified server. */
5375  
5376 SILC_SERVER_CMD_FUNC(close)
5377 {
5378   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5379   SilcServer server = cmd->server;
5380   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5381   SilcServerEntry server_entry;
5382   SilcSocketConnection sock;
5383   unsigned char *tmp;
5384   SilcUInt32 tmp_len;
5385   unsigned char *name;
5386   SilcUInt32 port = SILC_PORT;
5387
5388   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5389
5390   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5391     goto out;
5392
5393   /* Check whether client has the permissions. */
5394   if (client->mode == SILC_UMODE_NONE) {
5395     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5396                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5397     goto out;
5398   }
5399
5400   /* Get the remote server */
5401   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5402   if (!name) {
5403     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5404                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
5405     goto out;
5406   }
5407
5408   /* Get port */
5409   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5410   if (tmp)
5411     SILC_GET32_MSB(port, tmp);
5412
5413   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5414                                                  name, port, FALSE, NULL);
5415   if (!server_entry)
5416     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5417                                                    name, port, FALSE, NULL);
5418   if (!server_entry) {
5419     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5420                                           SILC_STATUS_ERR_NO_SERVER_ID);
5421     goto out;
5422   }
5423
5424   /* Send reply to the sender */
5425   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5426                                         SILC_STATUS_OK);
5427
5428   /* Close the connection to the server */
5429   sock = (SilcSocketConnection)server_entry->connection;
5430
5431   /* If we shutdown primary router connection manually then don't trigger
5432      any reconnect or backup router connections, by setting the router
5433      to NULL here. */
5434   if (server->router == server_entry) {
5435     server->id_entry->router = NULL;
5436     server->router = NULL;
5437     server->standalone = TRUE;
5438   }
5439   silc_server_free_sock_user_data(server, sock, NULL);
5440   silc_server_close_connection(server, sock);
5441   
5442  out:
5443   silc_server_command_free(cmd);
5444 }
5445
5446 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5447    active connections. */
5448  
5449 SILC_SERVER_CMD_FUNC(shutdown)
5450 {
5451   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5452   SilcServer server = cmd->server;
5453   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5454
5455   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5456
5457   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5458     goto out;
5459
5460   /* Check whether client has the permission. */
5461   if (client->mode == SILC_UMODE_NONE) {
5462     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5463                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
5464     goto out;
5465   }
5466
5467   /* Send reply to the sender */
5468   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5469                                         SILC_STATUS_OK);
5470
5471   /* Then, gracefully, or not, bring the server down. */
5472   silc_server_stop(server);
5473   exit(0);
5474
5475  out:
5476   silc_server_command_free(cmd);
5477 }