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