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