Optimized PING command handling a bit.
[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   SilcUInt32 len;
1549   unsigned char *tmp;
1550
1551   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PING, cmd, 1, 2);
1552
1553   /* Get Server ID */
1554   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1555   if (!tmp) {
1556     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1557                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
1558     goto out;
1559   }
1560
1561   if (!memcmp(tmp, server->id_string, server->id_string_len)) {
1562     /* Send our reply */
1563     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1564                                           SILC_STATUS_OK, 0);
1565   } else {
1566     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1567                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1568     goto out;
1569   }
1570
1571  out:
1572   silc_server_command_free(cmd);
1573 }
1574
1575 /* Server side of command STATS. */
1576
1577 SILC_SERVER_CMD_FUNC(stats)
1578 {
1579   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1580   SilcServer server = cmd->server;
1581   SilcServerID *server_id;
1582   unsigned char *tmp;
1583   SilcUInt32 tmp_len;
1584   SilcBuffer packet, stats;
1585   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1586   SilcUInt32 uptime;
1587
1588   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
1589
1590   /* Get Server ID */
1591   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1592   if (!tmp) {
1593     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1594                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
1595     goto out;
1596   }
1597   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
1598   if (!server_id)
1599     goto out;
1600
1601   /* The ID must be ours */
1602   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
1603     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1604                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
1605     silc_free(server_id);
1606     goto out;
1607   }
1608   silc_free(server_id);
1609
1610   /* If we are router then just send everything we got. If we are normal
1611      server then we'll send this to our router to get all the latest
1612      statistical information. */
1613   if (!cmd->pending && server->server_type != SILC_ROUTER && 
1614       !server->standalone) {
1615     /* Send request to our router */
1616     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
1617                                             SILC_ID_SERVER);
1618     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
1619                                             ++server->cmd_ident, 1,
1620                                             1, idp->data, idp->len);
1621     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1622                             SILC_PACKET_COMMAND, 0, packet->data,
1623                             packet->len, FALSE);
1624
1625     /* Reprocess this packet after received reply from router */
1626     silc_server_command_pending(server, SILC_COMMAND_STATS, 
1627                                 server->cmd_ident,
1628                                 silc_server_command_stats,
1629                                 silc_server_command_dup(cmd));
1630     cmd->pending = TRUE;
1631     silc_buffer_free(packet);
1632     silc_buffer_free(idp);
1633     goto out;
1634   }
1635
1636   /* Send our reply to sender */
1637   uptime = time(NULL) - server->starttime;
1638
1639   stats = silc_buffer_alloc_size(60);
1640   silc_buffer_format(stats,
1641                      SILC_STR_UI_INT(server->starttime),
1642                      SILC_STR_UI_INT(uptime),
1643                      SILC_STR_UI_INT(server->stat.my_clients),
1644                      SILC_STR_UI_INT(server->stat.my_channels),
1645                      SILC_STR_UI_INT(server->stat.my_server_ops),
1646                      SILC_STR_UI_INT(server->stat.my_router_ops),
1647                      SILC_STR_UI_INT(server->stat.cell_clients),
1648                      SILC_STR_UI_INT(server->stat.cell_channels),
1649                      SILC_STR_UI_INT(server->stat.cell_servers),
1650                      SILC_STR_UI_INT(server->stat.clients),
1651                      SILC_STR_UI_INT(server->stat.channels),
1652                      SILC_STR_UI_INT(server->stat.servers),
1653                      SILC_STR_UI_INT(server->stat.routers),
1654                      SILC_STR_UI_INT(server->stat.server_ops),
1655                      SILC_STR_UI_INT(server->stat.router_ops),
1656                      SILC_STR_END);
1657
1658   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
1659                                                 SILC_STATUS_OK, 0, ident, 2,
1660                                                 2, tmp, tmp_len,
1661                                                 3, stats->data, stats->len);
1662   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1663                           0, packet->data, packet->len, FALSE);
1664   silc_buffer_free(packet);
1665   silc_buffer_free(stats);
1666
1667  out:
1668   silc_server_command_free(cmd);
1669 }
1670
1671 /* Internal routine to join channel. The channel sent to this function
1672    has been either created or resolved from ID lists. This joins the sent
1673    client to the channel. */
1674
1675 static void silc_server_command_join_channel(SilcServer server, 
1676                                              SilcServerCommandContext cmd,
1677                                              SilcChannelEntry channel,
1678                                              SilcClientID *client_id,
1679                                              bool created,
1680                                              bool create_key,
1681                                              SilcUInt32 umode,
1682                                              const unsigned char *auth,
1683                                              SilcUInt32 auth_len)
1684 {
1685   SilcSocketConnection sock = cmd->sock;
1686   unsigned char *tmp;
1687   SilcUInt32 tmp_len, user_count;
1688   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1689   SilcClientEntry client;
1690   SilcChannelClientEntry chl;
1691   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
1692   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1693   char check[512], check2[512];
1694   bool founder = FALSE;
1695   bool resolve;
1696   unsigned char *fkey = NULL;
1697   SilcUInt32 fkey_len = 0;
1698   const char *cipher;
1699
1700   SILC_LOG_DEBUG(("Joining client to channel"));
1701
1702   if (!channel)
1703     return;
1704
1705   /* Get the client entry */
1706   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1707     client = (SilcClientEntry)sock->user_data;
1708     if (!client)
1709       return;
1710   } else {
1711     client = silc_server_query_client(server, client_id, FALSE, 
1712                                       &resolve);
1713     if (!client) {
1714       if (cmd->pending)
1715         goto out;
1716
1717       if (!resolve) {
1718         silc_server_command_send_status_reply(
1719                                          cmd, SILC_COMMAND_JOIN,
1720                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
1721         goto out;
1722       }
1723
1724       /* The client info is being resolved. Reprocess this packet after
1725          receiving the reply to the query. */
1726       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1727                                   server->cmd_ident,
1728                                   silc_server_command_join, 
1729                                   silc_server_command_dup(cmd));
1730       cmd->pending = TRUE;
1731       goto out;
1732     }
1733
1734     if (auth && auth_len && !client->data.public_key) {
1735       if (cmd->pending == 2)
1736         goto out;
1737
1738       /* We must retrieve the detached client's public key by sending
1739          GETKEY command. Reprocess this packet after receiving the key */
1740       clidp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1741       silc_server_send_command(server, cmd->sock,
1742                                SILC_COMMAND_GETKEY, ++server->cmd_ident,
1743                                1, 1, clidp->data, clidp->len);
1744       silc_buffer_free(clidp);
1745       silc_server_command_pending(server, SILC_COMMAND_GETKEY,
1746                                   server->cmd_ident,
1747                                   silc_server_command_join, 
1748                                   silc_server_command_dup(cmd));
1749       cmd->pending = 2;
1750       goto out;
1751     }
1752
1753     cmd->pending = FALSE;
1754   }
1755
1756   /*
1757    * Check founder auth payload if provided.  If client can gain founder
1758    * privileges it can override various conditions on joining the channel,
1759    * and can have directly the founder mode set on the channel.
1760    */
1761   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
1762     SilcIDListData idata = (SilcIDListData)client;
1763     SilcChannelClientEntry chl2;
1764     SilcHashTableList htl;
1765
1766     if (channel->founder_key && idata->public_key &&
1767         silc_pkcs_public_key_compare(channel->founder_key, 
1768                                      idata->public_key)) {
1769       /* Check whether the client is to become founder */
1770       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
1771                                 channel->founder_key, 0, server->sha1hash,
1772                                 client->id, SILC_ID_CLIENT)) {
1773
1774         /* There cannot be anyone else as founder on the channel now.  This
1775            client is definitely the founder due to this authentication */
1776         silc_hash_table_list(channel->user_list, &htl);
1777         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
1778           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
1779             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
1780             silc_server_force_cumode_change(server, NULL, channel, chl2,
1781                                             chl2->mode);
1782             break;
1783           }
1784         silc_hash_table_list_reset(&htl);
1785
1786         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1787         founder = TRUE;
1788       }
1789     }
1790   }
1791
1792   /*
1793    * Check channel modes
1794    */
1795
1796   if (!umode) {
1797     memset(check, 0, sizeof(check));
1798     memset(check2, 0, sizeof(check2));
1799     silc_strncat(check, sizeof(check),
1800                  client->nickname, strlen(client->nickname));
1801     silc_strncat(check, sizeof(check), "!", 1);
1802     silc_strncat(check, sizeof(check),
1803                  client->username, strlen(client->username));
1804     if (!strchr(client->username, '@')) {
1805       silc_strncat(check, sizeof(check), "@", 1);
1806       silc_strncat(check, sizeof(check),
1807                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1808     }
1809
1810     silc_strncat(check2, sizeof(check2),
1811                  client->nickname, strlen(client->nickname));
1812     if (!strchr(client->nickname, '@')) {
1813       silc_strncat(check2, sizeof(check2), "@", 1);
1814       silc_strncat(check2, sizeof(check2),
1815                    server->server_name, strlen(server->server_name));
1816     }
1817     silc_strncat(check2, sizeof(check2), "!", 1);
1818     silc_strncat(check2, sizeof(check2),
1819                  client->username, strlen(client->username));
1820     if (!strchr(client->username, '@')) {
1821       silc_strncat(check2, sizeof(check2), "@", 1);
1822       silc_strncat(check2, sizeof(check2),
1823                    cmd->sock->hostname, strlen(cmd->sock->hostname));
1824     }
1825     
1826     /* Check invite list if channel is invite-only channel */
1827     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1828       if (!channel->invite_list ||
1829           (!silc_string_match(channel->invite_list, check) &&
1830            !silc_string_match(channel->invite_list, check2))) {
1831         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1832                                               SILC_STATUS_ERR_NOT_INVITED, 0);
1833         goto out;
1834       }
1835     }
1836
1837     /* Check ban list if it exists. If the client's nickname, server,
1838        username and/or hostname is in the ban list the access to the
1839        channel is denied. */
1840     if (channel->ban_list) {
1841       if (silc_string_match(channel->ban_list, check) ||
1842           silc_string_match(channel->ban_list, check2)) {
1843         silc_server_command_send_status_reply(
1844                                       cmd, SILC_COMMAND_JOIN,
1845                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
1846         goto out;
1847       }
1848     }
1849     
1850     /* Check user count limit if set. */
1851     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1852       if (silc_hash_table_count(channel->user_list) + 1 > 
1853           channel->user_limit) {
1854         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1855                                               SILC_STATUS_ERR_CHANNEL_IS_FULL,
1856                                               0);
1857         goto out;
1858       }
1859     }
1860   }
1861
1862   /* Check the channel passphrase if set. */
1863   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1864     /* Get passphrase */
1865     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1866     if (tmp)
1867       passphrase = silc_memdup(tmp, tmp_len);
1868   
1869     if (!passphrase || !channel->passphrase ||
1870         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
1871       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1872                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
1873       goto out;
1874     }
1875   }
1876
1877   /*
1878    * Client is allowed to join to the channel. Make it happen.
1879    */
1880
1881   /* Check whether the client already is on the channel */
1882   if (silc_server_client_on_channel(client, channel, NULL)) {
1883     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1884                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
1885     goto out;
1886   }
1887
1888   /* Generate new channel key as protocol dictates */
1889   if (create_key) {
1890     if (!silc_server_create_channel_key(server, channel, 0))
1891       goto out;
1892
1893     /* Send the channel key. This is broadcasted to the channel but is not
1894        sent to the client who is joining to the channel. */
1895     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
1896       silc_server_send_channel_key(server, NULL, channel, 
1897                                    server->server_type == SILC_ROUTER ? 
1898                                    FALSE : !server->standalone);
1899   }
1900
1901   /* Join the client to the channel by adding it to channel's user list.
1902      Add also the channel to client entry's channels list for fast cross-
1903      referencing. */
1904   chl = silc_calloc(1, sizeof(*chl));
1905   chl->mode = umode;
1906   chl->client = client;
1907   chl->channel = channel;
1908   silc_hash_table_add(channel->user_list, client, chl);
1909   silc_hash_table_add(client->channels, channel, chl);
1910   channel->user_count++;
1911   channel->disabled = FALSE;
1912
1913   /* Get users on the channel */
1914   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1915                                    &user_count);
1916
1917   /* Encode Client ID Payload of the original client who wants to join */
1918   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1919
1920   /* Encode command reply packet */
1921   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1922   SILC_PUT32_MSB(channel->mode, mode);
1923   SILC_PUT32_MSB(created, tmp2);
1924   SILC_PUT32_MSB(user_count, tmp3);
1925
1926   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
1927     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1928     cipher = silc_cipher_get_name(channel->channel_key);
1929     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
1930                                                            SILC_ID_CHANNEL), 
1931                                            tmp,
1932                                            strlen(cipher), cipher,
1933                                            channel->key_len / 8, channel->key);
1934     silc_free(tmp);
1935   }
1936
1937   if (channel->founder_key)
1938     fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
1939
1940   reply = 
1941     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1942                                          SILC_STATUS_OK, 0, ident, 14,
1943                                          2, channel->channel_name,
1944                                          strlen(channel->channel_name),
1945                                          3, chidp->data, chidp->len,
1946                                          4, clidp->data, clidp->len,
1947                                          5, mode, 4,
1948                                          6, tmp2, 4,
1949                                          7, keyp ? keyp->data : NULL, 
1950                                          keyp ? keyp->len : 0,
1951                                          8, channel->ban_list, 
1952                                          channel->ban_list ?
1953                                          strlen(channel->ban_list) : 0,
1954                                          9, channel->invite_list,
1955                                          channel->invite_list ?
1956                                          strlen(channel->invite_list) : 0,
1957                                          10, channel->topic,
1958                                          channel->topic ?
1959                                          strlen(channel->topic) : 0,
1960                                          11, silc_hmac_get_name(channel->hmac),
1961                                          strlen(silc_hmac_get_name(channel->
1962                                                                    hmac)),
1963                                          12, tmp3, 4,
1964                                          13, user_list->data, user_list->len,
1965                                          14, mode_list->data, 
1966                                          mode_list->len,
1967                                          15, fkey, fkey_len);
1968
1969   /* Send command reply */
1970   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1971                           reply->data, reply->len, FALSE);
1972
1973   /* Send JOIN notify to locally connected clients on the channel. If
1974      we are normal server then router will send or have sent JOIN notify
1975      already. However since we've added the client already to our channel
1976      we'll ignore it (in packet_receive.c) so we must send it here. If
1977      we are router then this will send it to local clients and local
1978      servers. */
1979   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
1980   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
1981                                      SILC_NOTIFY_TYPE_JOIN, 2,
1982                                      clidp->data, clidp->len,
1983                                      chidp->data, chidp->len);
1984
1985   /* Update statistics */
1986   server->stat.my_chanclients++;
1987   if (server->server_type == SILC_ROUTER) {
1988     server->stat.cell_chanclients++;
1989     server->stat.chanclients++;
1990   }
1991
1992   if (!cmd->pending) {
1993     /* Send JOIN notify packet to our primary router */
1994     silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
1995                                  SILC_BROADCAST(server), channel, client->id);
1996
1997     if (keyp)
1998       /* Distribute the channel key to all backup routers. */
1999       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
2000                               keyp->data, keyp->len, FALSE, TRUE);
2001
2002     /* If client became founder by providing correct founder auth data
2003        notify the mode change to the channel. */
2004     if (founder) {
2005       SILC_PUT32_MSB(chl->mode, mode);
2006       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
2007       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2008                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
2009                                          clidp->data, clidp->len,
2010                                          mode, 4, clidp->data, clidp->len,
2011                                          fkey, fkey_len);
2012     }
2013   }
2014
2015   /* Set CUMODE notify type to network */
2016   if (founder)
2017     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
2018                                    SILC_BROADCAST(server), channel,
2019                                    chl->mode, client->id, SILC_ID_CLIENT,
2020                                    client->id, channel->founder_key);
2021
2022   silc_buffer_free(reply);
2023   silc_buffer_free(clidp);
2024   silc_buffer_free(chidp);
2025   silc_buffer_free(keyp);
2026   silc_buffer_free(user_list);
2027   silc_buffer_free(mode_list);
2028   silc_free(fkey);
2029
2030  out:
2031   silc_free(passphrase);
2032 }
2033
2034 /* Server side of command JOIN. Joins client into requested channel. If 
2035    the channel does not exist it will be created. */
2036
2037 SILC_SERVER_CMD_FUNC(join)
2038 {
2039   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2040   SilcServer server = cmd->server;
2041   unsigned char *auth;
2042   SilcUInt32 tmp_len, auth_len;
2043   char *tmp, *channel_name = NULL, *cipher, *hmac;
2044   SilcChannelEntry channel;
2045   SilcUInt32 umode = 0;
2046   bool created = FALSE, create_key = TRUE;
2047   SilcClientID *client_id;
2048
2049   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
2050
2051   /* Get channel name */
2052   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2053   if (!tmp) {
2054     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2055                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2056                                           0);
2057     goto out;
2058   }
2059   channel_name = tmp;
2060
2061   if (tmp_len > 256)
2062     channel_name[255] = '\0';
2063
2064   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
2065     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2066                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
2067     goto out;
2068   }
2069
2070   /* Get Client ID of the client who is joining to the channel */
2071   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2072   if (!tmp) {
2073     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2074                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2075                                           0);
2076     goto out;
2077   }
2078   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2079   if (!client_id) {
2080     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2081                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2082                                           0);
2083     goto out;
2084   }
2085
2086   /* Get cipher, hmac name and auth payload */
2087   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2088   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2089   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
2090
2091   /* See if the channel exists */
2092   channel = silc_idlist_find_channel_by_name(server->local_list, 
2093                                              channel_name, NULL);
2094
2095   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2096     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2097     if (!entry) {
2098       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2099                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2100                                             0);
2101       goto out;
2102     }
2103
2104     silc_free(client_id);
2105     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
2106
2107     if (!channel || 
2108         (channel->disabled && server->server_type != SILC_ROUTER)) {
2109       /* Channel not found or not valid */
2110
2111       /* If we are standalone server we don't have a router, we just create 
2112          the channel by ourselves (unless it existed). */
2113       if (server->standalone) {
2114         if (!channel) {
2115           channel = silc_server_create_new_channel(server, server->id, cipher, 
2116                                                    hmac, channel_name, TRUE);
2117           if (!channel) {
2118             silc_server_command_send_status_reply(
2119                                   cmd, SILC_COMMAND_JOIN,
2120                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
2121                                   0);
2122             silc_free(client_id);
2123             goto out;
2124           }
2125         
2126           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2127           created = TRUE;
2128           create_key = FALSE;
2129         }
2130       } else {
2131
2132         /* The channel does not exist on our server. If we are normal server 
2133            we will send JOIN command to our router which will handle the
2134            joining procedure (either creates the channel if it doesn't exist 
2135            or joins the client to it). */
2136         if (server->server_type != SILC_ROUTER) {
2137           SilcBuffer tmpbuf;
2138           SilcUInt16 old_ident;
2139
2140           /* If this is pending command callback then we've resolved
2141              it and it didn't work, return since we've notified the
2142              client already in the command reply callback. */
2143           if (cmd->pending) {
2144             silc_free(client_id);
2145             goto out;
2146           }
2147           
2148           old_ident = silc_command_get_ident(cmd->payload);
2149           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2150           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2151           
2152           /* Send JOIN command to our router */
2153           silc_server_packet_send(server, (SilcSocketConnection)
2154                                   SILC_PRIMARY_ROUTE(server),
2155                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2156                                   tmpbuf->data, tmpbuf->len, TRUE);
2157           
2158           /* Reprocess this packet after received reply from router */
2159           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2160                                       silc_command_get_ident(cmd->payload),
2161                                       silc_server_command_join,
2162                                       silc_server_command_dup(cmd));
2163           cmd->pending = TRUE;
2164           silc_command_set_ident(cmd->payload, old_ident);
2165           silc_buffer_free(tmpbuf);
2166           silc_free(client_id);
2167           goto out;
2168         }
2169         
2170         /* We are router and the channel does not seem exist so we will check
2171            our global list as well for the channel. */
2172         channel = silc_idlist_find_channel_by_name(server->global_list, 
2173                                                    channel_name, NULL);
2174         if (!channel) {
2175           /* Channel really does not exist, create it */
2176           channel = silc_server_create_new_channel(server, server->id, cipher, 
2177                                                    hmac, channel_name, TRUE);
2178           if (!channel) {
2179             silc_server_command_send_status_reply(
2180                                        cmd, SILC_COMMAND_JOIN,
2181                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2182             silc_free(client_id);
2183             goto out;
2184           }
2185
2186           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2187           created = TRUE;
2188           create_key = FALSE;
2189         }
2190       }
2191     }
2192   } else {
2193     if (!channel) {
2194       /* Channel not found */
2195
2196       /* If the command came from router and we are normal server then
2197          something went wrong with the joining as the channel was not found.
2198          We can't do anything else but ignore this. */
2199       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2200           server->server_type != SILC_ROUTER) {
2201         silc_free(client_id);
2202         goto out;
2203       }
2204       
2205       /* We are router and the channel does not seem exist so we will check
2206          our global list as well for the channel. */
2207       channel = silc_idlist_find_channel_by_name(server->global_list, 
2208                                                  channel_name, NULL);
2209       if (!channel) {
2210         /* Channel really does not exist, create it */
2211         channel = silc_server_create_new_channel(server, server->id, cipher, 
2212                                                  hmac, channel_name, TRUE);
2213         if (!channel) {
2214           silc_server_command_send_status_reply(
2215                                        cmd, SILC_COMMAND_JOIN,
2216                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2217           silc_free(client_id);
2218           goto out;
2219         }
2220
2221         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2222         created = TRUE;
2223         create_key = FALSE;
2224       }
2225     }
2226   }
2227
2228   /* Check whether the channel was created by our router */
2229   if (cmd->pending && context2) {
2230     SilcServerCommandReplyContext reply = context2;
2231
2232     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
2233       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
2234       SILC_GET32_MSB(created, tmp);
2235       if (silc_argument_get_arg_type(reply->args, 7, NULL))
2236         create_key = FALSE;     /* Router returned the key already */
2237
2238       if (silc_command_get_status(reply->payload, NULL, NULL) &&
2239           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2240         /* Save channel passphrase, if user provided it successfully */
2241         unsigned char *pa;
2242         SilcUInt32 pa_len;
2243         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
2244         if (pa) {
2245           silc_free(channel->passphrase);
2246           channel->passphrase = silc_memdup(pa, pa_len);
2247         }
2248       }
2249     }
2250
2251     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
2252         !channel->disabled && !silc_hash_table_count(channel->user_list))
2253       created = TRUE;
2254   }
2255
2256   /* If the channel does not have global users and is also empty the client
2257      will be the channel founder and operator. */
2258   if (!channel->disabled &&
2259       !channel->global_users && !silc_hash_table_count(channel->user_list))
2260     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2261
2262   /* Join to the channel */
2263   silc_server_command_join_channel(server, cmd, channel, client_id,
2264                                    created, create_key, umode,
2265                                    auth, auth_len);
2266
2267   silc_free(client_id);
2268
2269  out:
2270   silc_server_command_free(cmd);
2271 }
2272
2273 /* Server side of command MOTD. Sends server's current "message of the
2274    day" to the client. */
2275
2276 SILC_SERVER_CMD_FUNC(motd)
2277 {
2278   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2279   SilcServer server = cmd->server;
2280   SilcBuffer packet, idp;
2281   char *motd, *dest_server;
2282   SilcUInt32 motd_len;
2283   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2284   
2285   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
2286
2287   /* Get server name */
2288   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2289   if (!dest_server) {
2290     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2291                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2292     goto out;
2293   }
2294
2295   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2296     /* Send our MOTD */
2297
2298     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2299
2300     if (server->config && server->config->server_info &&
2301         server->config->server_info->motd_file) {
2302       /* Send motd */
2303       motd = silc_file_readfile(server->config->server_info->motd_file,
2304                                 &motd_len);
2305       if (!motd)
2306         goto out;
2307       
2308       motd[motd_len] = 0;
2309       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2310                                                     SILC_STATUS_OK, 0, 
2311                                                     ident, 2,
2312                                                     2, idp, idp->len,
2313                                                     3, motd, motd_len);
2314     } else {
2315       /* No motd */
2316       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2317                                                     SILC_STATUS_OK, 0, 
2318                                                     ident, 1,
2319                                                     2, idp, idp->len);
2320     }
2321
2322     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2323                             packet->data, packet->len, FALSE);
2324     silc_buffer_free(packet);
2325     silc_buffer_free(idp);
2326   } else {
2327     SilcServerEntry entry;
2328
2329     /* Check whether we have this server cached */
2330     entry = silc_idlist_find_server_by_name(server->global_list,
2331                                             dest_server, TRUE, NULL);
2332     if (!entry) {
2333       entry = silc_idlist_find_server_by_name(server->local_list,
2334                                               dest_server, TRUE, NULL);
2335     }
2336
2337     if (server->server_type != SILC_SERVER && !cmd->pending && 
2338         entry && !entry->motd) {
2339       /* Send to the server */
2340       SilcBuffer tmpbuf;
2341       SilcUInt16 old_ident;
2342
2343       old_ident = silc_command_get_ident(cmd->payload);
2344       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2345       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2346
2347       silc_server_packet_send(server, entry->connection,
2348                               SILC_PACKET_COMMAND, cmd->packet->flags,
2349                               tmpbuf->data, tmpbuf->len, TRUE);
2350
2351       /* Reprocess this packet after received reply from router */
2352       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
2353                                   silc_command_get_ident(cmd->payload),
2354                                   silc_server_command_motd,
2355                                   silc_server_command_dup(cmd));
2356       cmd->pending = TRUE;
2357       silc_command_set_ident(cmd->payload, old_ident);
2358       silc_buffer_free(tmpbuf);
2359       goto out;
2360     }
2361
2362     if (!entry && !cmd->pending && !server->standalone) {
2363       /* Send to the primary router */
2364       SilcBuffer tmpbuf;
2365       SilcUInt16 old_ident;
2366
2367       old_ident = silc_command_get_ident(cmd->payload);
2368       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2369       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2370
2371       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2372                               SILC_PACKET_COMMAND, cmd->packet->flags,
2373                               tmpbuf->data, tmpbuf->len, TRUE);
2374
2375       /* Reprocess this packet after received reply from router */
2376       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
2377                                   silc_command_get_ident(cmd->payload),
2378                                   silc_server_command_motd,
2379                                   silc_server_command_dup(cmd));
2380       cmd->pending = TRUE;
2381       silc_command_set_ident(cmd->payload, old_ident);
2382       silc_buffer_free(tmpbuf);
2383       goto out;
2384     }
2385
2386     if (!entry) {
2387       silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2388                                             SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2389       goto out;
2390     }
2391
2392     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
2393     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
2394                                                   SILC_STATUS_OK, 0, ident, 2,
2395                                                   2, idp, idp->len,
2396                                                   3, entry->motd,
2397                                                   entry->motd ? 
2398                                                   strlen(entry->motd) : 0);
2399     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2400                             packet->data, packet->len, FALSE);
2401     silc_buffer_free(packet);
2402     silc_buffer_free(idp);
2403   }
2404
2405  out:
2406   silc_server_command_free(cmd);
2407 }
2408
2409 /* Server side of command UMODE. Client can use this command to set/unset
2410    user mode. Client actually cannot set itself to be as server/router
2411    operator so this can be used only to unset the modes. */
2412
2413 SILC_SERVER_CMD_FUNC(umode)
2414 {
2415   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2416   SilcServer server = cmd->server;
2417   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2418   SilcBuffer packet;
2419   unsigned char *tmp_mask, m[4];
2420   SilcUInt32 mask = 0;
2421   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2422   bool set_mask = FALSE;
2423
2424   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2425     goto out;
2426
2427   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
2428
2429   /* Get the client's mode mask */
2430   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2431   if (tmp_mask) {
2432     SILC_GET32_MSB(mask, tmp_mask);
2433     set_mask = TRUE;
2434   }
2435
2436   if (set_mask) {
2437     /* Check that mode changing is allowed. */
2438     if (!silc_server_check_umode_rights(server, client, mask)) {
2439       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2440                                             SILC_STATUS_ERR_PERM_DENIED, 0);
2441       goto out;
2442     }
2443
2444     /* Anonymous mode cannot be set by client */
2445     if (mask & SILC_UMODE_ANONYMOUS) {
2446       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
2447         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2448                                               SILC_STATUS_ERR_PERM_DENIED, 0);
2449         goto out;
2450       }
2451     } else {
2452       if (client->mode & SILC_UMODE_ANONYMOUS) {
2453         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
2454                                               SILC_STATUS_ERR_PERM_DENIED, 0);
2455         goto out;
2456       }
2457     }
2458
2459     /* Update statistics */
2460     if (mask & SILC_UMODE_GONE) {
2461       if (!(client->mode & SILC_UMODE_GONE))
2462         server->stat.my_aways++;
2463     } else {
2464       if (client->mode & SILC_UMODE_GONE)
2465         server->stat.my_aways--;
2466     }
2467
2468     /* Change the mode */
2469     client->mode = mask;
2470
2471     /* Send UMODE change to primary router */
2472     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
2473                                   SILC_BROADCAST(server), client->id,
2474                                   client->mode);
2475
2476     /* Check if anyone is watching this nickname */
2477     if (server->server_type == SILC_ROUTER)
2478       silc_server_check_watcher_list(server, client, NULL,
2479                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
2480   }
2481
2482   /* Send command reply to sender */
2483   SILC_PUT32_MSB(client->mode, m);
2484   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
2485                                                 SILC_STATUS_OK, 0, ident, 1,
2486                                                 2, m, sizeof(m));
2487   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2488                           packet->data, packet->len, FALSE);
2489   silc_buffer_free(packet);
2490
2491  out:
2492   silc_server_command_free(cmd);
2493 }
2494
2495 /* Server side command of CMODE. Changes channel mode */
2496
2497 SILC_SERVER_CMD_FUNC(cmode)
2498 {
2499   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2500   SilcServer server = cmd->server;
2501   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2502   SilcIDListData idata = (SilcIDListData)client;
2503   SilcChannelID *channel_id = NULL;
2504   SilcChannelEntry channel;
2505   SilcChannelClientEntry chl;
2506   SilcBuffer packet, cidp;
2507   unsigned char *tmp, *tmp_id, *tmp_mask;
2508   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
2509   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
2510   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2511   bool set_mask = FALSE;
2512   SilcPublicKey founder_key = NULL;
2513   unsigned char *fkey = NULL;
2514   SilcUInt32 fkey_len = 0;
2515
2516   if (!client) {
2517     silc_server_command_free(cmd);
2518     return;
2519   }
2520
2521   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
2522
2523   /* Get Channel ID */
2524   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2525   if (!tmp_id) {
2526     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2527                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2528     silc_server_command_free(cmd);
2529     return;
2530   }
2531   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
2532   if (!channel_id) {
2533     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2534                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2535     silc_server_command_free(cmd);
2536     return;
2537   }
2538
2539   /* Get channel entry */
2540   channel = silc_idlist_find_channel_by_id(server->local_list, 
2541                                            channel_id, NULL);
2542   if (!channel) {
2543     channel = silc_idlist_find_channel_by_id(server->global_list, 
2544                                              channel_id, NULL);
2545     if (!channel) {
2546       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2547                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2548                                             0);
2549       silc_free(channel_id);
2550       silc_server_command_free(cmd);
2551       return;
2552     }
2553   }
2554   old_mask = channel->mode;
2555
2556   /* Get the channel mode mask */
2557   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2558   if (tmp_mask) {
2559     SILC_GET32_MSB(mode_mask, tmp_mask);
2560     set_mask = TRUE;
2561   }
2562
2563   /* Check whether this client is on the channel */
2564   if (!silc_server_client_on_channel(client, channel, &chl)) {
2565     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2566                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2567     goto out;
2568   }
2569
2570   /* Check that client has rights to change any requested channel modes */
2571   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
2572                                                   mode_mask)) {
2573     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
2574     silc_server_command_send_status_reply(
2575                              cmd, SILC_COMMAND_CMODE,
2576                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
2577                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
2578                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
2579     goto out;
2580   }
2581
2582   /* If mode mask was not sent as argument then merely return the current
2583      mode mask to the sender. */
2584   if (!set_mask) {
2585     unsigned char m[4];
2586     SILC_PUT32_MSB(channel->mode, m);
2587     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2588                                                   SILC_STATUS_OK, 0, ident, 2,
2589                                                   2, tmp_id, tmp_len2,
2590                                                   3, m, sizeof(m));
2591     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2592                             packet->data, packet->len, FALSE);
2593     silc_buffer_free(packet);
2594     goto out;
2595   }
2596
2597   /*
2598    * Check the modes. Modes that requires nothing special operation are
2599    * not checked here.
2600    */
2601
2602   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2603     /* Channel uses private keys to protect traffic. Client(s) has set the
2604        key locally they want to use, server does not know that key. */
2605     /* Nothing interesting to do here */
2606   } else {
2607     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2608       /* The mode is removed and we need to generate and distribute
2609          new channel key. Clients are not using private channel keys
2610          anymore after this. */
2611       
2612       /* Re-generate channel key */
2613       if (!silc_server_create_channel_key(server, channel, 0))
2614         goto out;
2615         
2616       /* Send the channel key. This sends it to our local clients and if
2617          we are normal server to our router as well. */
2618       silc_server_send_channel_key(server, NULL, channel, 
2619                                    server->server_type == SILC_ROUTER ? 
2620                                    FALSE : !server->standalone);
2621
2622       cipher = (char *)silc_cipher_get_name(channel->channel_key);
2623       hmac = (char *)silc_hmac_get_name(channel->hmac);
2624     }
2625   }
2626
2627   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2628     /* User limit is set on channel */
2629     SilcUInt32 user_limit;
2630       
2631     /* Get user limit */
2632     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2633     if (!tmp) {
2634       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2635         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2636                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2637         goto out;
2638       }
2639     } else {
2640       SILC_GET32_MSB(user_limit, tmp);
2641       channel->user_limit = user_limit;
2642     }
2643   } else {
2644     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2645       /* User limit mode is unset. Remove user limit */
2646       channel->user_limit = 0;
2647   }
2648
2649   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2650     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2651       /* Passphrase has been set to channel */
2652       
2653       /* Get the passphrase */
2654       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2655       if (!tmp) {
2656         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2657                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2658         goto out;
2659       }
2660
2661       /* Save the passphrase */
2662       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
2663     }
2664   } else {
2665     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2666       /* Passphrase mode is unset. remove the passphrase */
2667       silc_free(channel->passphrase);
2668       channel->passphrase = NULL;
2669     }
2670   }
2671
2672   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2673     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2674       /* Cipher to use protect the traffic */
2675       SilcCipher newkey, oldkey;
2676
2677       /* Get cipher */
2678       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
2679       if (!cipher) {
2680         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2681                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2682         goto out;
2683       }
2684
2685       /* Delete old cipher and allocate the new one */
2686       if (!silc_cipher_alloc(cipher, &newkey)) {
2687         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2688                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2689         goto out;
2690       }
2691
2692       oldkey = channel->channel_key;
2693       channel->channel_key = newkey;
2694
2695       /* Re-generate channel key */
2696       if (!silc_server_create_channel_key(server, channel, 0)) {
2697         /* We don't have new key, revert to old one */
2698         channel->channel_key = oldkey;
2699         goto out;
2700       }
2701
2702       /* Remove old channel key for good */
2703       silc_cipher_free(oldkey);
2704
2705       /* Send the channel key. This sends it to our local clients and if
2706          we are normal server to our router as well. */
2707       silc_server_send_channel_key(server, NULL, channel, 
2708                                    server->server_type == SILC_ROUTER ? 
2709                                    FALSE : !server->standalone);
2710     }
2711   } else {
2712     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2713       /* Cipher mode is unset. Remove the cipher and revert back to 
2714          default cipher */
2715       SilcCipher newkey, oldkey;
2716       cipher = channel->cipher;
2717
2718       /* Delete old cipher and allocate default one */
2719       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
2720         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2721                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2722         goto out;
2723       }
2724
2725       oldkey = channel->channel_key;
2726       channel->channel_key = newkey;
2727
2728       /* Re-generate channel key */
2729       if (!silc_server_create_channel_key(server, channel, 0)) {
2730         /* We don't have new key, revert to old one */
2731         channel->channel_key = oldkey;
2732         goto out;
2733       }
2734       
2735       /* Remove old channel key for good */
2736       silc_cipher_free(oldkey);
2737
2738       /* Send the channel key. This sends it to our local clients and if
2739          we are normal server to our router as well. */
2740       silc_server_send_channel_key(server, NULL, channel, 
2741                                    server->server_type == SILC_ROUTER ? 
2742                                    FALSE : !server->standalone);
2743     }
2744   }
2745
2746   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
2747     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
2748       /* HMAC to use protect the traffic */
2749       unsigned char hash[32];
2750       SilcHmac newhmac;
2751
2752       /* Get hmac */
2753       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
2754       if (!hmac) {
2755         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2756                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2757         goto out;
2758       }
2759
2760       /* Delete old hmac and allocate the new one */
2761       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
2762         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2763                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2764         goto out;
2765       }
2766
2767       silc_hmac_free(channel->hmac);
2768       channel->hmac = newhmac;
2769
2770       /* Set the HMAC key out of current channel key. The client must do
2771          this locally. */
2772       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
2773                      channel->key_len / 8, hash);
2774       silc_hmac_set_key(channel->hmac, hash, 
2775                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2776       memset(hash, 0, sizeof(hash));
2777     }
2778   } else {
2779     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
2780       /* Hmac mode is unset. Remove the hmac and revert back to 
2781          default hmac */
2782       SilcHmac newhmac;
2783       unsigned char hash[32];
2784       hmac = channel->hmac_name;
2785
2786       /* Delete old hmac and allocate default one */
2787       silc_hmac_free(channel->hmac);
2788       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
2789         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2790                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
2791         goto out;
2792       }
2793
2794       silc_hmac_free(channel->hmac);
2795       channel->hmac = newhmac;
2796
2797       /* Set the HMAC key out of current channel key. The client must do
2798          this locally. */
2799       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
2800                      channel->key_len / 8, 
2801                      hash);
2802       silc_hmac_set_key(channel->hmac, hash, 
2803                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
2804       memset(hash, 0, sizeof(hash));
2805     }
2806   }
2807
2808   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2809     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2810       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
2811         /* Set the founder authentication */
2812         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
2813         if (!tmp) {
2814           silc_server_command_send_status_reply(
2815                                      cmd, SILC_COMMAND_CMODE,
2816                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
2817           goto out;
2818         }
2819
2820         /* Verify the payload before setting the mode */
2821         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
2822                                    idata->public_key, 0, server->sha1hash,
2823                                    client->id, SILC_ID_CLIENT)) {
2824           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2825                                                 SILC_STATUS_ERR_AUTH_FAILED,
2826                                                 0);
2827           goto out;
2828         }
2829
2830         /* Save the public key */
2831         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
2832         if (!channel->founder_key) {
2833           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2834                                                 SILC_STATUS_ERR_AUTH_FAILED,
2835                                                 0);
2836           goto out;
2837         }
2838
2839         founder_key = channel->founder_key;
2840         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
2841         if (!fkey) {
2842           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2843                                                 SILC_STATUS_ERR_AUTH_FAILED,
2844                                                 0);
2845           silc_pkcs_public_key_free(channel->founder_key);
2846           channel->founder_key = NULL;
2847           goto out;
2848         }
2849       }
2850     }
2851   } else {
2852     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2853       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
2854         if (channel->founder_key)
2855           silc_pkcs_public_key_free(channel->founder_key);
2856         channel->founder_key = NULL;
2857       }
2858     }
2859   }
2860
2861   /* Finally, set the mode */
2862   old_mask = channel->mode = mode_mask;
2863
2864   /* Send CMODE_CHANGE notify. */
2865   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2866   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2867                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
2868                                      cidp->data, cidp->len, 
2869                                      tmp_mask, 4,
2870                                      cipher, cipher ? strlen(cipher) : 0,
2871                                      hmac, hmac ? strlen(hmac) : 0,
2872                                      passphrase, passphrase ? 
2873                                      strlen(passphrase) : 0,
2874                                      fkey, fkey_len);
2875
2876   /* Set CMODE notify type to network */
2877   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
2878                                 SILC_BROADCAST(server), channel,
2879                                 mode_mask, client->id, SILC_ID_CLIENT,
2880                                 cipher, hmac, passphrase, founder_key);
2881
2882   /* Send command reply to sender */
2883   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2884                                                 SILC_STATUS_OK, 0, ident, 2,
2885                                                 2, tmp_id, tmp_len2,
2886                                                 3, tmp_mask, 4);
2887   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2888                           packet->data, packet->len, FALSE);
2889
2890   silc_buffer_free(packet);
2891   silc_buffer_free(cidp);
2892
2893  out:
2894   channel->mode = old_mask;
2895   silc_free(fkey);
2896   silc_free(channel_id);
2897   silc_server_command_free(cmd);
2898 }
2899
2900 /* Server side of CUMODE command. Changes client's mode on a channel. */
2901
2902 SILC_SERVER_CMD_FUNC(cumode)
2903 {
2904   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2905   SilcServer server = cmd->server;
2906   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2907   SilcIDListData idata = (SilcIDListData)client;
2908   SilcChannelID *channel_id = NULL;
2909   SilcClientID *client_id = NULL;
2910   SilcChannelEntry channel;
2911   SilcClientEntry target_client;
2912   SilcChannelClientEntry chl;
2913   SilcBuffer packet, idp;
2914   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2915   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
2916   int notify = FALSE;
2917   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2918   SilcPublicKey founder_key = NULL;
2919   unsigned char *fkey = NULL;
2920   SilcUInt32 fkey_len = 0;
2921
2922   if (!client)
2923     goto out;
2924
2925   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
2926
2927   /* Get Channel ID */
2928   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2929   if (!tmp_ch_id) {
2930     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2931                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2932     goto out;
2933   }
2934   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
2935   if (!channel_id) {
2936     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2937                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2938     goto out;
2939   }
2940
2941   /* Get channel entry */
2942   channel = silc_idlist_find_channel_by_id(server->local_list, 
2943                                            channel_id, NULL);
2944   if (!channel) {
2945     channel = silc_idlist_find_channel_by_id(server->global_list, 
2946                                              channel_id, NULL);
2947     if (!channel) {
2948       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2949                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2950                                             0);
2951       goto out;
2952     }
2953   }
2954
2955   /* Check whether sender is on the channel */
2956   if (!silc_server_client_on_channel(client, channel, &chl)) {
2957     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2958                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2959     goto out;
2960   }
2961   sender_mask = chl->mode;
2962   
2963   /* Get the target client's channel mode mask */
2964   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2965   if (!tmp_mask) {
2966     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2967                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2968                                           0);
2969     goto out;
2970   }
2971   SILC_GET32_MSB(target_mask, tmp_mask);
2972
2973   /* Get target Client ID */
2974   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2975   if (!tmp_id) {
2976     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2977                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2978     goto out;
2979   }
2980   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
2981   if (!client_id) {
2982     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2983                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2984     goto out;
2985   }
2986
2987   /* Get target client's entry */
2988   target_client = silc_idlist_find_client_by_id(server->local_list, 
2989                                                 client_id, TRUE, NULL);
2990   if (!target_client) {
2991     target_client = silc_idlist_find_client_by_id(server->global_list, 
2992                                                   client_id, TRUE, NULL);
2993   }
2994
2995   if (target_client != client &&
2996       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
2997       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
2998     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2999                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3000     goto out;
3001   }
3002
3003   /* Check whether target client is on the channel */
3004   if (target_client != client) {
3005     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3006       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3007                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
3008       goto out;
3009     }
3010   }
3011
3012   /* 
3013    * Change the mode 
3014    */
3015
3016   /* If the target client is founder, no one else can change their mode
3017      but themselves. */
3018   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
3019     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3020                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3021                                           0);
3022     goto out;
3023   }
3024
3025   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3026     if (target_client != client) {
3027       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3028                                             SILC_STATUS_ERR_NOT_YOU, 0);
3029       goto out;
3030     }
3031
3032     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3033       /* The client tries to claim the founder rights. */
3034       unsigned char *tmp_auth;
3035       SilcUInt32 tmp_auth_len;
3036       SilcChannelClientEntry chl2;
3037       SilcHashTableList htl;
3038
3039       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
3040           !channel->founder_key || !idata->public_key ||
3041           !silc_pkcs_public_key_compare(channel->founder_key, 
3042                                         idata->public_key)) {
3043         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3044                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3045         goto out;
3046       }
3047
3048       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
3049       if (!tmp_auth) {
3050         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3051                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3052         goto out;
3053       }
3054
3055       /* Verify the authentication payload */
3056       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
3057                                  channel->founder_key, 0, server->sha1hash,
3058                                  client->id, SILC_ID_CLIENT)) {
3059         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3060                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3061         goto out;
3062       }
3063
3064       notify = TRUE;
3065       founder_key = channel->founder_key;
3066       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
3067       if (!fkey) {
3068         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3069                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
3070         goto out;
3071       }
3072
3073       /* There cannot be anyone else as founder on the channel now.  This
3074          client is definitely the founder due to this authentication */
3075       silc_hash_table_list(channel->user_list, &htl);
3076       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3077         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3078           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3079           silc_server_force_cumode_change(server, NULL, channel, chl2,
3080                                           chl2->mode);
3081           break;
3082         }
3083       silc_hash_table_list_reset(&htl);
3084
3085       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
3086     }
3087   } else {
3088     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3089       if (target_client == client) {
3090         /* Remove channel founder rights from itself */
3091         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3092         notify = TRUE;
3093       } else {
3094         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3095                                               SILC_STATUS_ERR_NOT_YOU, 0);
3096         goto out;
3097       }
3098     }
3099   }
3100
3101   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3102     /* Promote to operator */
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       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3113       notify = TRUE;
3114     }
3115   } else {
3116     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3117       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
3118           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
3119         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,   
3120                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
3121                                               0);
3122         goto out;
3123       }
3124       
3125       /* Demote to normal user */
3126       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3127       notify = TRUE;
3128     }
3129   }
3130
3131   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3132     if (target_client != client) {
3133       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3134                                             SILC_STATUS_ERR_NOT_YOU, 0);
3135       goto out;
3136     }
3137
3138     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
3139       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3140       notify = TRUE;
3141     }
3142   } else {
3143     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
3144       if (target_client != client) {
3145         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3146                                               SILC_STATUS_ERR_NOT_YOU, 0);
3147         goto out;
3148       }
3149
3150       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
3151       notify = TRUE;
3152     }
3153   }
3154
3155   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3156     if (target_client != client) {
3157       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3158                                             SILC_STATUS_ERR_NOT_YOU, 0);
3159       goto out;
3160     }
3161
3162     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
3163       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3164       notify = TRUE;
3165     }
3166   } else {
3167     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
3168       if (target_client != client) {
3169         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3170                                               SILC_STATUS_ERR_NOT_YOU, 0);
3171         goto out;
3172       }
3173
3174       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
3175       notify = TRUE;
3176     }
3177   }
3178
3179   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3180     if (target_client != client) {
3181       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3182                                             SILC_STATUS_ERR_NOT_YOU, 0);
3183       goto out;
3184     }
3185
3186     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
3187       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3188       notify = TRUE;
3189     }
3190   } else {
3191     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
3192       if (target_client != client) {
3193         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3194                                               SILC_STATUS_ERR_NOT_YOU, 0);
3195         goto out;
3196       }
3197
3198       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
3199       notify = TRUE;
3200     }
3201   }
3202
3203   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
3204     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
3205       if (client == target_client) {
3206         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3207                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3208         goto out;
3209       }
3210       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
3211       notify = TRUE;
3212     }
3213   } else {
3214     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
3215       if (client == target_client) {
3216         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3217                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3218         goto out;
3219       }
3220       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
3221       notify = TRUE;
3222     }
3223   }
3224
3225   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3226   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3227
3228   /* Send notify to channel, notify only if mode was actually changed. */
3229   if (notify) {
3230     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3231                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3232                                        idp->data, idp->len,
3233                                        tmp_mask, 4, 
3234                                        tmp_id, tmp_len,
3235                                        fkey, fkey_len);
3236
3237     /* Set CUMODE notify type to network */
3238     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3239                                    SILC_BROADCAST(server), channel,
3240                                    target_mask, client->id, SILC_ID_CLIENT,
3241                                    target_client->id, founder_key);
3242   }
3243
3244   /* Send command reply to sender */
3245   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3246                                                 SILC_STATUS_OK, 0, ident, 3,
3247                                                 2, tmp_mask, 4,
3248                                                 3, tmp_ch_id, tmp_ch_len,
3249                                                 4, tmp_id, tmp_len);
3250   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3251                           packet->data, packet->len, FALSE);
3252     
3253   silc_buffer_free(packet);
3254   silc_buffer_free(idp);
3255
3256  out:
3257   silc_free(channel_id);
3258   silc_free(client_id);
3259   silc_free(fkey);
3260   silc_server_command_free(cmd);
3261 }
3262
3263 /* Server side of KICK command. Kicks client out of channel. */
3264
3265 SILC_SERVER_CMD_FUNC(kick)
3266 {
3267   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3268   SilcServer server = cmd->server;
3269   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3270   SilcClientEntry target_client;
3271   SilcChannelID *channel_id;
3272   SilcClientID *client_id;
3273   SilcChannelEntry channel;
3274   SilcChannelClientEntry chl;
3275   SilcBuffer idp;
3276   SilcUInt32 tmp_len, target_idp_len;
3277   unsigned char *tmp, *comment, *target_idp;
3278
3279   if (!client)
3280     goto out;
3281
3282   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
3283
3284   /* Get Channel ID */
3285   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3286   if (!tmp) {
3287     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3288                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3289     goto out;
3290   }
3291   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3292   if (!channel_id) {
3293     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3294                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3295     goto out;
3296   }
3297
3298   /* Get channel entry */
3299   channel = silc_idlist_find_channel_by_id(server->local_list, 
3300                                            channel_id, NULL);
3301   if (!channel) {
3302     channel = silc_idlist_find_channel_by_id(server->local_list, 
3303                                              channel_id, NULL);
3304     if (!channel) {
3305       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3306                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3307                                             0);
3308       goto out;
3309     }
3310   }
3311
3312   /* Check whether sender is on the channel */
3313   if (!silc_server_client_on_channel(client, channel, &chl)) {
3314     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3315                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3316     goto out;
3317   }
3318
3319   /* Check that the kicker is channel operator or channel founder */
3320   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
3321       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
3322     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3323                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3324     goto out;
3325   }
3326   
3327   /* Get target Client ID */
3328   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
3329   if (!target_idp) {
3330     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3331                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3332     goto out;
3333   }
3334   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
3335   if (!client_id) {
3336     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3337                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
3338     goto out;
3339   }
3340
3341   /* Get target client's entry */
3342   target_client = silc_idlist_find_client_by_id(server->local_list, 
3343                                                 client_id, TRUE, NULL);
3344   if (!target_client) {
3345     target_client = silc_idlist_find_client_by_id(server->global_list, 
3346                                                   client_id, TRUE, NULL);
3347   }
3348
3349   /* Check whether target client is on the channel */
3350   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
3351     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3352                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
3353                                           0);
3354     goto out;
3355   }
3356
3357   /* Check that the target client is not channel founder. Channel founder
3358      cannot be kicked from the channel. */
3359   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3360     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3361                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
3362                                           0);
3363     goto out;
3364   }
3365   
3366   /* Get comment */
3367   tmp_len = 0;
3368   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3369   if (tmp_len > 128)
3370     comment = NULL;
3371
3372   /* Send command reply to sender */
3373   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
3374                                         SILC_STATUS_OK, 0);
3375
3376   /* Send KICKED notify to local clients on the channel */
3377   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3378   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3379                                      SILC_NOTIFY_TYPE_KICKED, 3,
3380                                      target_idp, target_idp_len,
3381                                      comment, comment ? strlen(comment) : 0,
3382                                      idp->data, idp->len);
3383   silc_buffer_free(idp);
3384
3385   /* Send KICKED notify to primary route */
3386   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
3387                                  SILC_BROADCAST(server), channel,
3388                                  target_client->id, client->id, comment);
3389
3390   /* Remove the client from the channel. If the channel does not exist
3391      after removing the client then the client kicked itself off the channel
3392      and we don't have to send anything after that. */
3393   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
3394                                            target_client, FALSE))
3395     goto out;
3396
3397   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3398     /* Re-generate channel key */
3399     if (!silc_server_create_channel_key(server, channel, 0))
3400       goto out;
3401     
3402     /* Send the channel key to the channel. The key of course is not sent
3403        to the client who was kicked off the channel. */
3404     silc_server_send_channel_key(server, target_client->connection, channel, 
3405                                  server->server_type == SILC_ROUTER ? 
3406                                  FALSE : !server->standalone);
3407   }
3408
3409  out:
3410   silc_server_command_free(cmd);
3411 }
3412
3413 /* Server side of OPER command. Client uses this comand to obtain server
3414    operator privileges to this server/router. */
3415
3416 SILC_SERVER_CMD_FUNC(oper)
3417 {
3418   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3419   SilcServer server = cmd->server;
3420   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3421   unsigned char *username, *auth;
3422   SilcUInt32 tmp_len;
3423   SilcServerConfigAdmin *admin;
3424   SilcIDListData idata = (SilcIDListData)client;
3425   bool result = FALSE;
3426   SilcPublicKey cached_key;
3427
3428   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3429     goto out;
3430
3431   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
3432
3433   /* Get the username */
3434   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3435   if (!username) {
3436     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3437                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3438                                           0);
3439     goto out;
3440   }
3441
3442   /* Get the admin configuration */
3443   admin = silc_server_config_find_admin(server, cmd->sock->ip,
3444                                         username, client->nickname);
3445   if (!admin) {
3446     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3447                                           username, client->nickname);
3448     if (!admin) {
3449       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3450                                             SILC_STATUS_ERR_AUTH_FAILED,
3451                                             0);
3452       SILC_LOG_INFO(("OPER authentication failed for username '%s' by "
3453                      "nickname '%s' from %s", username,
3454                      client->nickname, cmd->sock->hostname));
3455       goto out;
3456     }
3457   }
3458
3459   /* Get the authentication payload */
3460   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3461   if (!auth) {
3462     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3463                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3464                                           0);
3465     goto out;
3466   }
3467
3468   /* Verify the authentication data. If both passphrase and public key
3469      is set then try both of them. */
3470   if (admin->passphrase)
3471     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3472                                    admin->passphrase, admin->passphrase_len,
3473                                    idata->hash, client->id, SILC_ID_CLIENT);
3474   if (!result && admin->publickeys) {
3475     cached_key = silc_server_get_public_key(server, admin->publickeys);
3476     if (!cached_key)
3477       goto out;
3478     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3479                                    cached_key, 0, idata->hash, 
3480                                    client->id, SILC_ID_CLIENT);
3481   }
3482   if (!result) {
3483     /* Authentication failed */
3484     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3485                                           SILC_STATUS_ERR_AUTH_FAILED,
3486                                           0);
3487     goto out;
3488   }
3489
3490   /* Client is now server operator */
3491   client->mode |= SILC_UMODE_SERVER_OPERATOR;
3492
3493   /* Update statistics */
3494   if (SILC_IS_LOCAL(client))
3495     server->stat.my_server_ops++;
3496   if (server->server_type == SILC_ROUTER)
3497     server->stat.server_ops++;
3498
3499   /* Send UMODE change to primary router */
3500   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3501                                 SILC_BROADCAST(server), client->id,
3502                                 client->mode);
3503
3504   /* Check if anyone is watching this nickname */
3505   if (server->server_type == SILC_ROUTER)
3506     silc_server_check_watcher_list(server, client, NULL,
3507                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3508
3509   /* Send reply to the sender */
3510   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3511                                         SILC_STATUS_OK, 0);
3512
3513  out:
3514   silc_server_command_free(cmd);
3515 }
3516
3517 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
3518 {
3519   SilcServer server = app_context;
3520   QuitInternal q = (QuitInternal)context;
3521   SilcClientID *client_id = (SilcClientID *)q->sock;
3522   SilcClientEntry client;
3523   SilcSocketConnection sock;
3524
3525   client = silc_idlist_find_client_by_id(server->local_list, client_id,
3526                                          TRUE, NULL);
3527   if (client && client->connection) {
3528     sock = client->connection;
3529
3530     /* If there is pending outgoing data for the client then purge it
3531        to the network before closing connection. */
3532     silc_server_packet_queue_purge(server, sock);
3533
3534     /* Close the connection on our side */
3535     client->router = NULL;
3536     client->connection = NULL;
3537     sock->user_data = NULL;
3538     silc_server_close_connection(server, sock);
3539   }
3540
3541   silc_free(client_id);
3542   silc_free(q);
3543 }
3544
3545 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
3546 {
3547   SilcServer server = app_context;
3548   QuitInternal q = (QuitInternal)context;
3549   SilcClientID *client_id = (SilcClientID *)q->sock;
3550   SilcClientEntry client;
3551
3552   client = silc_idlist_find_client_by_id(server->local_list, client_id,
3553                                          TRUE, NULL);
3554   if (client && client->mode & SILC_UMODE_DETACHED) {
3555     SILC_LOG_DEBUG(("Detach timeout"));
3556     silc_server_free_client_data(server, NULL, client, TRUE,
3557                                  "Detach timeout");
3558   }
3559
3560   silc_free(client_id);
3561   silc_free(q);
3562 }
3563
3564 /* Server side of DETACH command.  Detached the client from the network
3565    by closing the connection but preserving the session. */
3566
3567 SILC_SERVER_CMD_FUNC(detach)
3568 {
3569   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3570   SilcServer server = cmd->server;
3571   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3572   QuitInternal q;
3573
3574   if (server->config->detach_disabled) {
3575     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3576                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
3577     goto out;
3578   }
3579
3580   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3581     goto out;
3582
3583   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
3584
3585   /* Remove operator privileges, since the client may resume in some
3586      other server which to it does not have operator privileges. */
3587   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
3588   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
3589
3590   /* Send the user mode notify to notify that client is detached */
3591   client->mode |= SILC_UMODE_DETACHED;
3592   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
3593   client->data.status &= ~SILC_IDLIST_STATUS_NOATTR;
3594   client->last_command = 0;
3595   client->fast_command = 0;
3596   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3597                                 SILC_BROADCAST(server), client->id,
3598                                 client->mode);
3599   server->stat.my_detached++;
3600
3601   /* Check if anyone is watching this nickname */
3602   if (server->server_type == SILC_ROUTER)
3603     silc_server_check_watcher_list(server, client, NULL,
3604                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3605
3606   q = silc_calloc(1, sizeof(*q));
3607   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3608   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
3609                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3610
3611   if (server->config->detach_timeout) {
3612     q = silc_calloc(1, sizeof(*q));
3613     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
3614     silc_schedule_task_add(server->schedule, 0, 
3615                            silc_server_command_detach_timeout,
3616                            q, server->config->detach_timeout * 60,
3617                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
3618   }
3619
3620   /* Send reply to the sender */
3621   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
3622                                         SILC_STATUS_OK, 0);
3623
3624  out:
3625   silc_server_command_free(cmd);
3626 }
3627
3628 /* Server side of WATCH command. */
3629
3630 SILC_SERVER_CMD_FUNC(watch)
3631 {
3632   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3633   SilcServer server = cmd->server;
3634   char *add_nick, *del_nick;
3635   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
3636   char nick[128 + 1];
3637   unsigned char hash[16], *tmp;
3638   SilcClientEntry client;
3639   SilcClientID *client_id = NULL;
3640
3641   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
3642
3643   if (server->server_type != SILC_ROUTER && !server->standalone) {
3644     if (!cmd->pending) {
3645       /* Send the command to router */
3646       SilcBuffer tmpbuf;
3647       SilcUInt16 old_ident;
3648
3649       SILC_LOG_DEBUG(("Forwarding WATCH to router"));
3650
3651       old_ident = silc_command_get_ident(cmd->payload);
3652       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3653       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3654
3655       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3656                               SILC_PACKET_COMMAND, cmd->packet->flags,
3657                               tmpbuf->data, tmpbuf->len, TRUE);
3658
3659       /* Reprocess this packet after received reply from router */
3660       silc_server_command_pending(server, SILC_COMMAND_WATCH,
3661                                   silc_command_get_ident(cmd->payload),
3662                                   silc_server_command_watch,
3663                                   silc_server_command_dup(cmd));
3664       cmd->pending = TRUE;
3665       silc_command_set_ident(cmd->payload, old_ident);
3666       silc_buffer_free(tmpbuf);
3667     } else if (context2) {
3668       /* Received reply from router, just send same data to the client. */
3669       SilcServerCommandReplyContext reply = context2;
3670       SilcStatus status;
3671
3672       SILC_LOG_DEBUG(("Received reply to WATCH from router"));
3673       silc_command_get_status(reply->payload, &status, NULL);
3674       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
3675                                             0);
3676     }
3677
3678     goto out;
3679   }
3680
3681   /* We are router and keep the watch list for local cell */
3682
3683   /* Get the client ID */
3684   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3685   if (!tmp) {
3686     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3687                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3688                                           0);
3689     goto out;
3690   }
3691   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3692   if (!client_id) {
3693     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3694                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3695                                           0);
3696     goto out;
3697   }
3698
3699   /* Get the client entry which must be in local list */
3700   client = silc_idlist_find_client_by_id(server->local_list, 
3701                                          client_id, TRUE, NULL);
3702   if (!client) {
3703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3704                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
3705                                           0);
3706     goto out;
3707   }
3708
3709   /* Take nickname */
3710   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
3711   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
3712   if (!add_nick && !del_nick) {
3713     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3714                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3715                                           0);
3716     goto out;
3717   }
3718
3719   if (add_nick && add_nick_len > 128)
3720     add_nick[128] = '\0';
3721   if (del_nick && del_nick_len > 128)
3722     del_nick[128] = '\0';
3723
3724   memset(nick, 0, sizeof(nick));
3725
3726   /* Add new nickname to be watched in our cell */
3727   if (add_nick) {
3728     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
3729       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3730                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
3731       goto out;
3732     }
3733
3734     /* Hash the nick, we have the hash saved, not nicks because we can
3735        do one to one mapping to the nick from Client ID hash this way. */
3736     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
3737     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3738
3739     /* Check whether this client is already watching this nickname */
3740     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
3741                                         client, NULL)) {
3742       /* Nickname is alredy being watched for this client */
3743       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3744                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
3745                                             0);
3746       goto out;
3747     }
3748
3749     /* Get the nickname from the watcher list and use the same key in
3750        new entries as well.  If key doesn't exist then create it. */
3751     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
3752       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
3753
3754     /* Add the client to the watcher list with the specified nickname hash. */
3755     silc_hash_table_add(server->watcher_list, tmp, client);
3756   }
3757
3758   /* Delete nickname from watch list */
3759   if (del_nick) {
3760     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
3761       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3762                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
3763       goto out;
3764     }
3765
3766     /* Hash the nick, we have the hash saved, not nicks because we can
3767        do one to one mapping to the nick from Client ID hash this way. */
3768     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
3769     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
3770
3771     /* Check that this client is watching for this nickname */
3772     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
3773                                          client, (void **)&tmp)) {
3774       /* Nickname is alredy being watched for this client */
3775       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3776                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
3777       goto out;
3778     }
3779
3780     /* Delete the nickname from the watcher list. */
3781     silc_hash_table_del_by_context(server->watcher_list, hash, client);
3782
3783     /* Now check whether there still exists entries with this key, if not
3784        then free the key to not leak memory. */
3785     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
3786       silc_free(tmp);
3787   }
3788
3789   /* Distribute the watch list to backup routers too */
3790   if (server->backup) {
3791     SilcBuffer tmpbuf;
3792     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3793     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3794     silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
3795                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
3796                             FALSE, TRUE);
3797     silc_buffer_free(tmpbuf);
3798   }
3799
3800   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
3801                                         SILC_STATUS_OK, 0);
3802
3803  out:
3804   silc_free(client_id);
3805   silc_server_command_free(cmd);
3806 }
3807
3808 /* Server side of SILCOPER command. Client uses this comand to obtain router
3809    operator privileges to this router. */
3810
3811 SILC_SERVER_CMD_FUNC(silcoper)
3812 {
3813   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3814   SilcServer server = cmd->server;
3815   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3816   unsigned char *username, *auth;
3817   SilcUInt32 tmp_len;
3818   SilcServerConfigAdmin *admin;
3819   SilcIDListData idata = (SilcIDListData)client;
3820   bool result = FALSE;
3821   SilcPublicKey cached_key;
3822
3823   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3824     goto out;
3825
3826   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3827
3828   if (server->server_type != SILC_ROUTER) {
3829     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3830                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
3831     goto out;
3832   }
3833
3834   /* Get the username */
3835   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3836   if (!username) {
3837     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3838                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3839                                           0);
3840     goto out;
3841   }
3842
3843   /* Get the admin configuration */
3844   admin = silc_server_config_find_admin(server, cmd->sock->ip,
3845                                         username, client->nickname);
3846   if (!admin) {
3847     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
3848                                           username, client->nickname);
3849     if (!admin) {
3850       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3851                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
3852       SILC_LOG_INFO(("SILCOPER authentication failed for username '%s' by "
3853                      "nickname '%s' from %s", username,
3854                      client->nickname, cmd->sock->hostname));
3855       goto out;
3856     }
3857   }
3858
3859   /* Get the authentication payload */
3860   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3861   if (!auth) {
3862     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3863                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3864                                           0);
3865     goto out;
3866   }
3867
3868   /* Verify the authentication data. If both passphrase and public key
3869      is set then try both of them. */
3870   if (admin->passphrase)
3871     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
3872                                    admin->passphrase, admin->passphrase_len,
3873                                    idata->hash, client->id, SILC_ID_CLIENT);
3874   if (!result && admin->publickeys) {
3875     cached_key = silc_server_get_public_key(server, admin->publickeys);
3876     if (!cached_key)
3877       goto out;
3878     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
3879                                    cached_key, 0, idata->hash, 
3880                                    client->id, SILC_ID_CLIENT);
3881   }
3882   if (!result) {
3883     /* Authentication failed */
3884     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3885                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
3886     goto out;
3887   }
3888
3889   /* Client is now router operator */
3890   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3891
3892   /* Update statistics */
3893   if (SILC_IS_LOCAL(client))
3894     server->stat.my_router_ops++;
3895   if (server->server_type == SILC_ROUTER)
3896     server->stat.router_ops++;
3897
3898   /* Send UMODE change to primary router */
3899   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3900                                 SILC_BROADCAST(server), client->id,
3901                                 client->mode);
3902
3903   /* Check if anyone is watching this nickname */
3904   if (server->server_type == SILC_ROUTER)
3905     silc_server_check_watcher_list(server, client, NULL,
3906                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
3907
3908   /* Send reply to the sender */
3909   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3910                                         SILC_STATUS_OK, 0);
3911
3912  out:
3913   silc_server_command_free(cmd);
3914 }
3915
3916 /* Server side of command BAN. This is used to manage the ban list of the
3917    channel. To add clients and remove clients from the ban list. */
3918
3919 SILC_SERVER_CMD_FUNC(ban)
3920 {
3921   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3922   SilcServer server = cmd->server;
3923   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3924   SilcBuffer packet;
3925   SilcChannelEntry channel;
3926   SilcChannelClientEntry chl;
3927   SilcChannelID *channel_id = NULL;
3928   unsigned char *id, *add, *del;
3929   SilcUInt32 id_len, tmp_len;
3930   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3931
3932   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
3933     goto out;
3934
3935   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
3936
3937   /* Get Channel ID */
3938   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
3939   if (id) {
3940     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
3941     if (!channel_id) {
3942       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3943                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3944       goto out;
3945     }
3946   }
3947
3948   /* Get channel entry. The server must know about the channel since the
3949      client is expected to be on the channel. */
3950   channel = silc_idlist_find_channel_by_id(server->local_list, 
3951                                            channel_id, NULL);
3952   if (!channel) {
3953     channel = silc_idlist_find_channel_by_id(server->global_list, 
3954                                              channel_id, NULL);
3955     if (!channel) {
3956       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3957                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3958                                             0);
3959       goto out;
3960     }
3961   }
3962
3963   /* Check whether this client is on the channel */
3964   if (!silc_server_client_on_channel(client, channel, &chl)) {
3965     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3966                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3967     goto out;
3968   }
3969
3970   /* The client must be at least channel operator. */
3971   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3972     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
3973                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
3974     goto out;
3975   }
3976
3977   /* Get the new ban and add it to the ban list */
3978   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3979   if (add) {
3980     if (!channel->ban_list)
3981       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
3982     else
3983       channel->ban_list = silc_realloc(channel->ban_list, 
3984                                        sizeof(*channel->ban_list) * 
3985                                        (tmp_len + 
3986                                         strlen(channel->ban_list) + 2));
3987     if (add[tmp_len - 1] == ',')
3988       add[tmp_len - 1] = '\0';
3989
3990     strncat(channel->ban_list, add, tmp_len);
3991     strncat(channel->ban_list, ",", 1);
3992   }
3993
3994   /* Get the ban to be removed and remove it from the list */
3995   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3996   if (del && channel->ban_list) {
3997     char *start, *end, *n;
3998
3999     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4000       silc_free(channel->ban_list);
4001       channel->ban_list = NULL;
4002     } else {
4003       start = strstr(channel->ban_list, del);
4004       if (start && strlen(start) >= tmp_len) {
4005         end = start + tmp_len;
4006         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4007         strncat(n, channel->ban_list, start - channel->ban_list);
4008         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4009                              end) - 1);
4010         silc_free(channel->ban_list);
4011         channel->ban_list = n;
4012       }
4013     }
4014   }
4015
4016   /* Send the BAN notify type to our primary router. */
4017   if (add || del)
4018     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
4019                                 SILC_BROADCAST(server), channel, add, del);
4020
4021   /* Send the reply back to the client */
4022   packet = 
4023     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4024                                          SILC_STATUS_OK, 0, ident, 2,
4025                                          2, id, id_len,
4026                                          3, channel->ban_list, 
4027                                          channel->ban_list ? 
4028                                          strlen(channel->ban_list) -1 : 0);
4029   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4030                           packet->data, packet->len, FALSE);
4031     
4032   silc_buffer_free(packet);
4033
4034  out:
4035   silc_free(channel_id);
4036   silc_server_command_free(cmd);
4037 }
4038
4039 /* Server side command of LEAVE. Removes client from a channel. */
4040
4041 SILC_SERVER_CMD_FUNC(leave)
4042 {
4043   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4044   SilcServer server = cmd->server;
4045   SilcSocketConnection sock = cmd->sock;
4046   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4047   SilcChannelID *id = NULL;
4048   SilcChannelEntry channel;
4049   SilcUInt32 len;
4050   unsigned char *tmp;
4051
4052   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
4053     goto out;
4054
4055   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
4056
4057   /* Get Channel ID */
4058   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4059   if (!tmp) {
4060     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4061                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4062     goto out;
4063   }
4064   id = silc_id_payload_parse_id(tmp, len, NULL);
4065   if (!id) {
4066     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4067                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4068     goto out;
4069   }
4070
4071   /* Get channel entry */
4072   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4073   if (!channel) {
4074     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4075     if (!channel) {
4076       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4077                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4078                                             0);
4079       goto out;
4080     }
4081   }
4082
4083   /* Check whether this client is on the channel */
4084   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
4085     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4086                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4087     goto out;
4088   }
4089
4090   /* Notify routers that they should remove this client from their list
4091      of clients on the channel. Send LEAVE notify type. */
4092   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
4093                                 SILC_BROADCAST(server), channel, id_entry->id);
4094
4095   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
4096                                        SILC_STATUS_OK, 0, 2, tmp, len);
4097
4098   /* Remove client from channel */
4099   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4100                                            TRUE))
4101     /* If the channel does not exist anymore we won't send anything */
4102     goto out;
4103
4104   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4105     /* Re-generate channel key */
4106     if (!silc_server_create_channel_key(server, channel, 0))
4107       goto out;
4108
4109     /* Send the channel key */
4110     silc_server_send_channel_key(server, NULL, channel, 
4111                                  server->server_type == SILC_ROUTER ? 
4112                                  FALSE : !server->standalone);
4113   }
4114
4115  out:
4116   silc_free(id);
4117   silc_server_command_free(cmd);
4118 }
4119
4120 /* Server side of command USERS. Resolves clients and their USERS currently
4121    joined on the requested channel. The list of Client ID's and their modes
4122    on the channel is sent back. */
4123
4124 SILC_SERVER_CMD_FUNC(users)
4125 {
4126   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4127   SilcServer server = cmd->server;
4128   SilcChannelEntry channel;
4129   SilcChannelID *id = NULL;
4130   SilcBuffer packet, idp;
4131   unsigned char *channel_id;
4132   SilcUInt32 channel_id_len;
4133   SilcBuffer client_id_list;
4134   SilcBuffer client_mode_list;
4135   unsigned char lc[4];
4136   SilcUInt32 list_count = 0;
4137   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4138   char *channel_name;
4139
4140   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
4141
4142   /* Get Channel ID */
4143   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4144
4145   /* Get channel name */
4146   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
4147
4148   if (!channel_id && !channel_name) {
4149     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4150                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4151     goto out;
4152   }
4153
4154   if (channel_id) {
4155     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
4156     if (!id) {
4157       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4158                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4159       goto out;
4160     }
4161   }
4162
4163   /* If we are server and we don't know about this channel we will send
4164      the command to our router. If we know about the channel then we also
4165      have the list of users already. */
4166   if (id)
4167     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4168   else
4169     channel = silc_idlist_find_channel_by_name(server->local_list, 
4170                                                channel_name, NULL);
4171
4172   if (!channel || (!server->standalone && (channel->disabled || 
4173                     !channel->users_resolved))) {
4174     if (server->server_type != SILC_ROUTER && !server->standalone &&
4175         !cmd->pending) {
4176       SilcBuffer tmpbuf;
4177       
4178       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4179       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4180       
4181       /* Send USERS command */
4182       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4183                               SILC_PACKET_COMMAND, cmd->packet->flags,
4184                               tmpbuf->data, tmpbuf->len, TRUE);
4185       
4186       /* Reprocess this packet after received reply */
4187       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4188                                   silc_command_get_ident(cmd->payload),
4189                                   silc_server_command_users,
4190                                   silc_server_command_dup(cmd));
4191       cmd->pending = TRUE;
4192       silc_command_set_ident(cmd->payload, ident);
4193       silc_buffer_free(tmpbuf);
4194       silc_free(id);
4195       goto out;
4196     }
4197
4198     /* Check the global list as well. */
4199     if (id)
4200       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4201     else
4202       channel = silc_idlist_find_channel_by_name(server->global_list, 
4203                                                  channel_name, NULL);
4204     if (!channel) {
4205       /* Channel really does not exist */
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   /* If the channel is private or secret do not send anything, unless the
4214      user requesting this command is on the channel or is server */
4215   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
4216     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
4217         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
4218                                           NULL)) {
4219       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4220                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4221                                             0);
4222       goto out;
4223     }
4224   }
4225
4226   /* Get the users list */
4227   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
4228                                         &client_mode_list, &list_count)) {
4229     list_count = 0;
4230     client_id_list = NULL;
4231     client_mode_list = NULL;
4232   }
4233
4234   /* List count */
4235   SILC_PUT32_MSB(list_count, lc);
4236
4237   /* Send reply */
4238   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
4239   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4240                                                 SILC_STATUS_OK, 0, ident, 4,
4241                                                 2, idp->data, idp->len,
4242                                                 3, lc, 4,
4243                                                 4, client_id_list ? 
4244                                                 client_id_list->data : NULL,
4245                                                 client_id_list ?
4246                                                 client_id_list->len : 0,
4247                                                 5, client_mode_list ?
4248                                                 client_mode_list->data : NULL,
4249                                                 client_mode_list ?
4250                                                 client_mode_list->len : 0);
4251   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4252                           packet->data, packet->len, FALSE);
4253     
4254   silc_buffer_free(idp);
4255   silc_buffer_free(packet);
4256   if (client_id_list)
4257     silc_buffer_free(client_id_list);
4258   if (client_mode_list)
4259     silc_buffer_free(client_mode_list);
4260   silc_free(id);
4261
4262  out:
4263   silc_server_command_free(cmd);
4264 }
4265
4266 /* Server side of command GETKEY. This fetches the client's public key
4267    from the server where to the client is connected. */
4268
4269 SILC_SERVER_CMD_FUNC(getkey)
4270 {
4271   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4272   SilcServer server = cmd->server;
4273   SilcBuffer packet;
4274   SilcClientEntry client;
4275   SilcServerEntry server_entry;
4276   SilcClientID *client_id = NULL;
4277   SilcServerID *server_id = NULL;
4278   SilcIDPayload idp = NULL;
4279   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4280   unsigned char *tmp, *pkdata;
4281   SilcUInt32 tmp_len, pklen;
4282   SilcBuffer pk = NULL;
4283   SilcIdType id_type;
4284   SilcPublicKey public_key;
4285
4286   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4287   if (!tmp) {
4288     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4289                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4290                                           0);
4291     goto out;
4292   }
4293   idp = silc_id_payload_parse(tmp, tmp_len);
4294   if (!idp) {
4295     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4296                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4297                                           0);
4298     goto out;
4299   }
4300
4301   id_type = silc_id_payload_get_type(idp);
4302   if (id_type == SILC_ID_CLIENT) {
4303     client_id = silc_id_payload_get_id(idp);
4304
4305     /* If the client is not found from local list there is no chance it
4306        would be locally connected client so send the command further. */
4307     client = silc_idlist_find_client_by_id(server->local_list, 
4308                                            client_id, TRUE, NULL);
4309     if (!client)
4310       client = silc_idlist_find_client_by_id(server->global_list, 
4311                                              client_id, TRUE, NULL);
4312     
4313     if ((!client && !cmd->pending && !server->standalone) ||
4314         (client && !client->connection && !cmd->pending &&
4315          !(client->mode & SILC_UMODE_DETACHED)) ||
4316         (client && !client->data.public_key && !cmd->pending)) {
4317       SilcBuffer tmpbuf;
4318       SilcUInt16 old_ident;
4319       SilcSocketConnection dest_sock;
4320       
4321       dest_sock = silc_server_get_client_route(server, NULL, 0, 
4322                                                client_id, NULL, NULL);
4323       if (!dest_sock)
4324         goto out;
4325       
4326       old_ident = silc_command_get_ident(cmd->payload);
4327       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4328       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4329       
4330       silc_server_packet_send(server, dest_sock,
4331                               SILC_PACKET_COMMAND, cmd->packet->flags,
4332                               tmpbuf->data, tmpbuf->len, TRUE);
4333       
4334       /* Reprocess this packet after received reply from router */
4335       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4336                                   silc_command_get_ident(cmd->payload),
4337                                   silc_server_command_getkey,
4338                                   silc_server_command_dup(cmd));
4339       cmd->pending = TRUE;
4340       silc_command_set_ident(cmd->payload, old_ident);
4341       silc_buffer_free(tmpbuf);
4342       goto out;
4343     }
4344
4345     if (!client) {
4346       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4347                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
4348                                             0);
4349       goto out;
4350     }
4351
4352     /* The client is locally connected, just get the public key and
4353        send it back. If they key does not exist then do not send it, 
4354        send just OK reply */
4355     public_key = client->data.public_key;
4356     if (!public_key) {
4357       pkdata = NULL;
4358       pklen = 0;
4359     } else {
4360       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4361       pk = silc_buffer_alloc(4 + tmp_len);
4362       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4363       silc_buffer_format(pk,
4364                          SILC_STR_UI_SHORT(tmp_len),
4365                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4366                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
4367                          SILC_STR_END);
4368       silc_free(tmp);
4369       pkdata = pk->data;
4370       pklen = pk->len;
4371     }
4372   } else if (id_type == SILC_ID_SERVER) {
4373     server_id = silc_id_payload_get_id(idp);
4374
4375     /* If the server is not found from local list there is no chance it
4376        would be locally connected server so send the command further. */
4377     server_entry = silc_idlist_find_server_by_id(server->local_list, 
4378                                                  server_id, TRUE, NULL);
4379     if (!server_entry)
4380       server_entry = silc_idlist_find_server_by_id(server->global_list, 
4381                                                    server_id, TRUE, NULL);
4382     
4383     if (server_entry != server->id_entry &&
4384         ((!server_entry && !cmd->pending && !server->standalone) ||
4385          (server_entry && !server_entry->connection && !cmd->pending &&
4386           !server->standalone) ||
4387          (server_entry && !server_entry->data.public_key && !cmd->pending &&
4388           !server->standalone))) {
4389       SilcBuffer tmpbuf;
4390       SilcUInt16 old_ident;
4391       
4392       old_ident = silc_command_get_ident(cmd->payload);
4393       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4394       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4395       
4396       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
4397                               SILC_PACKET_COMMAND, cmd->packet->flags,
4398                               tmpbuf->data, tmpbuf->len, TRUE);
4399       
4400       /* Reprocess this packet after received reply from router */
4401       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
4402                                   silc_command_get_ident(cmd->payload),
4403                                   silc_server_command_getkey,
4404                                   silc_server_command_dup(cmd));
4405       cmd->pending = TRUE;
4406       silc_command_set_ident(cmd->payload, old_ident);
4407       silc_buffer_free(tmpbuf);
4408       goto out;
4409     }
4410
4411     if (!server_entry) {
4412       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
4413                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
4414                                             0);
4415       goto out;
4416     }
4417
4418     /* If they key does not exist then do not send it, send just OK reply */
4419     public_key = (!server_entry->data.public_key ? 
4420                   (server_entry == server->id_entry ? server->public_key :
4421                    NULL) : server_entry->data.public_key);
4422     if (!public_key) {
4423       pkdata = NULL;
4424       pklen = 0;
4425     } else {
4426       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
4427       pk = silc_buffer_alloc(4 + tmp_len);
4428       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
4429       silc_buffer_format(pk,
4430                          SILC_STR_UI_SHORT(tmp_len),
4431                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
4432                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
4433                          SILC_STR_END);
4434       silc_free(tmp);
4435       pkdata = pk->data;
4436       pklen = pk->len;
4437     }
4438   } else {
4439     goto out;
4440   }
4441
4442   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4443   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
4444                                                 SILC_STATUS_OK, 0, ident, 
4445                                                 pkdata ? 2 : 1,
4446                                                 2, tmp, tmp_len,
4447                                                 3, pkdata, pklen);
4448   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4449                           packet->data, packet->len, FALSE);
4450   silc_buffer_free(packet);
4451
4452   if (pk)
4453     silc_buffer_free(pk);
4454
4455  out:
4456   if (idp)
4457     silc_id_payload_free(idp);
4458   silc_free(client_id);
4459   silc_free(server_id);
4460   silc_server_command_free(cmd);
4461 }
4462
4463
4464 /* Private range commands, specific to this implementation */
4465
4466 /* Server side command of CONNECT. Connects us to the specified remote
4467    server or router. */
4468
4469 SILC_SERVER_CMD_FUNC(connect)
4470 {
4471   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4472   SilcServer server = cmd->server;
4473   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4474   unsigned char *tmp, *host;
4475   SilcUInt32 tmp_len;
4476   SilcUInt32 port = SILC_PORT;
4477
4478   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4479     goto out;
4480
4481   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
4482
4483   /* Check whether client has the permissions. */
4484   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4485       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4486     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4487                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
4488     goto out;
4489   }
4490
4491   if (server->server_type == SILC_ROUTER && !server->backup_router &&
4492       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4493     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4494                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
4495     goto out;
4496   }
4497
4498   /* Get the remote server */
4499   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4500   if (!host) {
4501     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4502                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4503                                           0);
4504     goto out;
4505   }
4506
4507   /* Get port */
4508   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4509   if (tmp)
4510     SILC_GET32_MSB(port, tmp);
4511
4512   /* Create the connection. It is done with timeout and is async. */
4513   silc_server_create_connection(server, host, port);
4514
4515   /* Send reply to the sender */
4516   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
4517                                         SILC_STATUS_OK, 0);
4518
4519  out:
4520   silc_server_command_free(cmd);
4521 }
4522
4523 /* Server side command of CLOSE. Closes connection to a specified server. */
4524  
4525 SILC_SERVER_CMD_FUNC(close)
4526 {
4527   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4528   SilcServer server = cmd->server;
4529   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4530   SilcServerEntry server_entry;
4531   SilcSocketConnection sock;
4532   unsigned char *tmp;
4533   SilcUInt32 tmp_len;
4534   unsigned char *name;
4535   SilcUInt32 port = SILC_PORT;
4536
4537   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4538     goto out;
4539
4540   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
4541
4542   /* Check whether client has the permissions. */
4543   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4544       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4545     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4546                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
4547                                           0);
4548     goto out;
4549   }
4550
4551   /* Get the remote server */
4552   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4553   if (!name) {
4554     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4555                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4556                                           0);
4557     goto out;
4558   }
4559
4560   /* Get port */
4561   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4562   if (tmp)
4563     SILC_GET32_MSB(port, tmp);
4564
4565   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4566                                                  name, port, FALSE, NULL);
4567   if (!server_entry)
4568     server_entry = silc_idlist_find_server_by_conn(server->global_list,
4569                                                    name, port, FALSE, NULL);
4570   if (!server_entry) {
4571     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4572                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
4573     goto out;
4574   }
4575
4576   if (server_entry == server->id_entry) {
4577     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4578                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
4579     goto out;
4580   }
4581
4582   /* Send reply to the sender */
4583   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
4584                                         SILC_STATUS_OK, 0);
4585
4586   /* Close the connection to the server */
4587   sock = (SilcSocketConnection)server_entry->connection;
4588
4589   /* If we shutdown primary router connection manually then don't trigger
4590      any reconnect or backup router connections, by setting the router
4591      to NULL here. */
4592   if (server->router == server_entry) {
4593     server->id_entry->router = NULL;
4594     server->router = NULL;
4595     server->standalone = TRUE;
4596   }
4597   silc_server_free_sock_user_data(server, sock, NULL);
4598   silc_server_close_connection(server, sock);
4599   
4600  out:
4601   silc_server_command_free(cmd);
4602 }
4603
4604 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4605    active connections. */
4606  
4607 SILC_SERVER_CMD_FUNC(shutdown)
4608 {
4609   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4610   SilcServer server = cmd->server;
4611   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4612
4613   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4614     goto out;
4615
4616   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
4617
4618   /* Check whether client has the permission. */
4619   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
4620       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
4621     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4622                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
4623                                           0);
4624     goto out;
4625   }
4626
4627   /* Send reply to the sender */
4628   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
4629                                         SILC_STATUS_OK, 0);
4630
4631   /* Then, gracefully, or not, bring the server down. */
4632   silc_server_stop(server);
4633   exit(0);
4634
4635  out:
4636   silc_server_command_free(cmd);
4637 }