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