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