Added support for removing unconfigured client connections in
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcStatus status,
33                                       SilcStatus error);
34 static void 
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36                                      SilcCommand command,
37                                      SilcStatus status,
38                                      SilcStatus error,
39                                      SilcUInt32 arg_type,
40                                      const unsigned char *arg,
41                                      SilcUInt32 arg_len);
42 static bool
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44                                         SilcServerCommandReplyContext cmdr,
45                                         SilcCommand command);
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
47
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
50 {
51   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71   SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72   SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73   SILC_SERVER_CMD(silcoper, SILCOPER,
74                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
78
79   SILC_SERVER_CMD(connect, PRIV_CONNECT, 
80                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81   SILC_SERVER_CMD(close, PRIV_CLOSE,
82                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
84                   SILC_CF_OPER),
85
86   { NULL, 0 },
87 };
88
89 /* Performs several checks to the command. It first checks whether this
90    command was called as pending command callback. If it was then it checks
91    whether error occurred in the command reply where the pending command
92    callback was called. 
93
94    It also checks that the requested command includes correct amount
95    of arguments. */
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                \
97 do {                                                                         \
98   SilcUInt32 _argc;                                                          \
99                                                                              \
100   if (silc_server_command_pending_error_check(cmd, context2, command)) {     \
101     SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102     silc_server_command_free(cmd);                                           \
103     return;                                                                  \
104   }                                                                          \
105                                                                              \
106   _argc = silc_argument_get_arg_num(cmd->args);                              \
107   if (_argc < min) {                                                         \
108     SILC_LOG_DEBUG(("Not enough parameters in command"));                    \
109     silc_server_command_send_status_reply(cmd, command,                      \
110                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
111                                           0);                                \
112     silc_server_command_free(cmd);                                           \
113     return;                                                                  \
114   }                                                                          \
115   if (_argc > max) {                                                         \
116     SILC_LOG_DEBUG(("Too many parameters in command"));                      \
117     silc_server_command_send_status_reply(cmd, command,                      \
118                                           SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
119                                           0);                                \
120     silc_server_command_free(cmd);                                           \
121     return;                                                                  \
122   }                                                                          \
123 } while(0)
124
125 /* Returns TRUE if the connection is registered. Unregistered connections
126    usually cannot send commands hence the check. */
127
128 static int silc_server_is_registered(SilcServer server,
129                                      SilcSocketConnection sock,
130                                      SilcServerCommandContext cmd,
131                                      SilcCommand command)
132 {
133   SilcIDListData idata = (SilcIDListData)sock->user_data;
134
135   if (!idata)
136     return FALSE;
137
138   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
139     return TRUE;
140
141   silc_server_command_send_status_reply(cmd, command,
142                                         SILC_STATUS_ERR_NOT_REGISTERED, 0);
143   return FALSE;
144 }
145
146 /* Internal context to hold data when executed command with timeout. */
147 typedef struct {
148   SilcServerCommandContext ctx;
149   SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
151
152 /* Timeout callback to process commands with timeout for client. Client's
153    commands are always executed with timeout. */
154
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 {
157   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
159
160   if (!client) {
161     SILC_LOG_DEBUG(("Client entry is invalid"));
162     silc_server_command_free(timeout->ctx);
163     silc_free(timeout);
164   }
165
166   /* Update access time */
167   client->last_command = time(NULL);
168
169   if (!(timeout->cmd->flags & SILC_CF_REG)) {
170     SILC_LOG_DEBUG(("Calling %s command",
171                     silc_get_command_name(timeout->cmd->cmd)));
172     timeout->cmd->cb(timeout->ctx, NULL);
173   } else if (silc_server_is_registered(timeout->ctx->server, 
174                                        timeout->ctx->sock, 
175                                        timeout->ctx, 
176                                        timeout->cmd->cmd)) {
177     SILC_LOG_DEBUG(("Calling %s command",
178                     silc_get_command_name(timeout->cmd->cmd)));
179     timeout->cmd->cb(timeout->ctx, NULL);
180   } else {
181     SILC_LOG_DEBUG(("Client is not registered"));
182     silc_server_command_free(timeout->ctx);
183   }
184
185   silc_free(timeout);
186 }
187
188 /* Processes received command packet. */
189
190 void silc_server_command_process(SilcServer server,
191                                  SilcSocketConnection sock,
192                                  SilcPacketContext *packet)
193 {
194   SilcServerCommandContext ctx;
195   SilcServerCommand *cmd;
196   SilcCommand command;
197
198   /* Allocate command context. This must be free'd by the
199      command routine receiving it. */
200   ctx = silc_server_command_alloc();
201   ctx->server = server;
202   ctx->sock = silc_socket_dup(sock);
203   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
204   
205   /* Parse the command payload in the packet */
206   ctx->payload = silc_command_payload_parse(packet->buffer->data,
207                                             packet->buffer->len);
208   if (!ctx->payload) {
209     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210     silc_packet_context_free(packet);
211     silc_socket_free(ctx->sock);
212     silc_free(ctx);
213     return;
214   }
215   ctx->args = silc_command_get_args(ctx->payload);
216
217   /* Get the command */
218   command = silc_command_get(ctx->payload);
219   for (cmd = silc_command_list; cmd->cb; cmd++)
220     if (cmd->cmd == command)
221       break;
222
223   if (!cmd || !cmd->cb) {
224     SILC_LOG_DEBUG(("Unknown command %d", command));
225     silc_server_command_send_status_reply(ctx, command,
226                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227     silc_server_command_free(ctx);
228     return;
229   }
230
231   /* Execute client's commands always with timeout.  Normally they are
232      executed with zero (0) timeout but if client is sending command more
233      frequently than once in 2 seconds, then the timeout may be 0 to 2
234      seconds. */
235   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236     SilcClientEntry client = (SilcClientEntry)sock->user_data;
237     SilcServerCommandTimeout timeout;
238     int fast;
239
240     if (!client) {
241       SILC_LOG_DEBUG(("Client entry is invalid"));
242       silc_server_command_free(ctx);
243     }
244
245     timeout = silc_calloc(1, sizeof(*timeout));
246     timeout->ctx = ctx;
247     timeout->cmd = cmd;
248
249     if (client->last_command && (time(NULL) - client->last_command) < 2) {
250       client->fast_command++;
251       fast = FALSE;
252     } else {
253       if (client->fast_command - 2 <= 0)
254         client->fast_command = 0;
255       else
256         client->fast_command -= 2;
257       fast = TRUE;
258     }
259
260     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
261                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
262       silc_schedule_task_add(server->schedule, sock->sock, 
263                              silc_server_command_process_timeout, timeout,
264                              (client->fast_command < 3 ? 0 :
265                               2 - (time(NULL) - client->last_command)),
266                              (client->fast_command < 3 ? 200000 : 0),
267                              SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
268     else
269       silc_schedule_task_add(server->schedule, sock->sock, 
270                              silc_server_command_process_timeout, timeout,
271                              0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
272     return;
273   }
274
275   /* Execute for server */
276
277   if (!(cmd->flags & SILC_CF_REG)) {
278     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
279     cmd->cb(ctx, NULL);
280   } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
281     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
282     cmd->cb(ctx, NULL);
283   } else {
284     SILC_LOG_DEBUG(("Server is not registered"));
285     silc_server_command_free(ctx);
286   }
287 }
288
289 /* Allocate Command Context */
290
291 SilcServerCommandContext silc_server_command_alloc()
292 {
293   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
294   ctx->users++;
295   return ctx;
296 }
297
298 /* Free's the command context allocated before executing the command */
299
300 void silc_server_command_free(SilcServerCommandContext ctx)
301 {
302   ctx->users--;
303   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
304                   ctx->users));
305   if (ctx->users < 1) {
306     if (ctx->payload)
307       silc_command_payload_free(ctx->payload);
308     if (ctx->packet)
309       silc_packet_context_free(ctx->packet);
310     if (ctx->sock)
311       silc_socket_free(ctx->sock); /* Decrease reference counter */
312     silc_free(ctx);
313   }
314 }
315
316 /* Duplicate Command Context by adding reference counter. The context won't
317    be free'd untill it hits zero. */
318
319 SilcServerCommandContext 
320 silc_server_command_dup(SilcServerCommandContext ctx)
321 {
322   ctx->users++;
323   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
324                   ctx->users));
325   return ctx;
326 }
327
328 /* Timeout for pending command.  If reply to pending command never arrives
329    this is called to free resources. */
330
331 SILC_TASK_CALLBACK(silc_server_command_pending_timeout)
332 {
333   SilcServer server = app_context;
334   SilcServerCommandPending *reply = context;
335   SilcServerCommandReplyContext cmdr;
336   SilcBuffer tmpreply;
337   int i;
338
339   SILC_LOG_DEBUG(("Timeout pending command"));
340
341   /* Allocate temporary and bogus command reply context */
342   cmdr = silc_calloc(1, sizeof(*cmdr));
343   cmdr->server = server;
344   cmdr->ident = reply->ident;
345       
346   /* Check for pending commands and mark to be exeucted */
347   cmdr->callbacks = 
348     silc_server_command_pending_check(server, reply->reply_cmd,
349                                       reply->ident, &cmdr->callbacks_count);
350
351   /* Create bogus command reply with an error inside */
352   tmpreply =
353     silc_command_reply_payload_encode_va(reply->reply_cmd,
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 /******************************************************************************
554
555                               WHOIS Functions
556
557 ******************************************************************************/
558
559 typedef struct {
560   void *id;
561   SilcIdType id_type;
562   SilcUInt32 index;
563   SilcStatus error;
564 } *ResolveError;
565
566 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
567 do {                                                                    \
568   errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1));  \
569   if (!errptr)                                                          \
570     return FALSE;                                                       \
571   errptr[errptr_count].id = _id;                                        \
572   errptr[errptr_count].id_type = _id_type;                              \
573   errptr[errptr_count].index = _index;                                  \
574   errptr[errptr_count].error = _status;                                 \
575   errptr_count++;                                                       \
576 } while(0)
577
578 static int
579 silc_server_command_whois_parse(SilcServerCommandContext cmd,
580                                 SilcClientID ***client_id,
581                                 SilcUInt32 *client_id_count,
582                                 char **nickname,
583                                 char **server_name,
584                                 int *count,
585                                 ResolveError *error_client,
586                                 SilcUInt32 *error_client_count,
587                                 SilcDList *attrs)
588 {
589   unsigned char *tmp;
590   SilcUInt32 len;
591   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
592   void *id;
593   int i, k;
594
595   /* If client ID is in the command it must be used instead of nickname */
596   tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
597   if (!tmp) {
598     /* No ID, get the nickname@server string and parse it. */
599     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
600     if (tmp) {
601       silc_parse_userfqdn(tmp, nickname, server_name);
602     } else {
603       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
604                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
605       return FALSE;
606     }
607   } else {
608     /* Command includes ID, we must use that.  Take all ID's from the 
609        command packet */
610     for (k = 0, i = 0; i < argc; i++) {
611       tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
612       if (!tmp)
613         continue;
614       id = silc_id_payload_parse_id(tmp, len, NULL);
615       if (id) {
616         *client_id = silc_realloc(*client_id, sizeof(**client_id) *
617                                   (*client_id_count + 1));
618         (*client_id)[k] = id;
619         (*client_id_count)++;
620         k++;
621       } else {
622         ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
623                   SILC_STATUS_ERR_BAD_CLIENT_ID);
624       }
625     }
626   }
627
628   /* Get the max count of reply messages allowed */
629   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
630   if (tmp)
631     SILC_GET32_MSB(*count, tmp);
632   else
633     *count = 0;
634
635   /* Get requested attributes if set */
636   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
637   if (tmp && attrs)
638     *attrs = silc_attribute_payload_parse_list(tmp, len);
639
640   return TRUE;
641 }
642
643 /* Resolve context used by both WHOIS and IDENTIFY commands */
644 typedef struct {
645   SilcSocketConnection sock;
646   SilcUInt16 ident;
647   unsigned char **res_argv;
648   SilcUInt32 *res_argv_lens;
649   SilcUInt32 *res_argv_types;
650   SilcUInt32 res_argc;
651   SilcUInt32 res_timeout;
652 } *SilcServerResolveContext;
653
654 static bool
655 silc_server_command_whois_check(SilcServerCommandContext cmd,
656                                 SilcClientEntry *clients,
657                                 SilcUInt32 clients_count,
658                                 SilcDList attrs)
659 {
660   SilcServer server = cmd->server;
661   SilcClientEntry entry;
662   SilcServerResolveContext resolve = NULL, r = NULL;
663   SilcUInt32 resolve_count = 0;
664   int i, k;
665   bool no_res = TRUE;
666
667   SILC_LOG_DEBUG(("Start"));
668
669   for (i = 0; i < clients_count; i++) {
670     entry = clients[i];
671     if (!entry)
672       continue;
673
674     /* If requested attributes is set then we always resolve the client
675        information, if not then check whether the entry is complete or not
676        and decide whether we need to resolve or not.  Usually attributes
677        are not present so the this test is performed all the time. */
678     if (!attrs) {
679       if ((entry->nickname && entry->username && entry->userinfo) ||
680           !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
681         if (!entry->router)
682           continue;
683
684         /* If we are normal server, and we've not resolved this client from
685            router and it is global client, we'll check whether it is on some
686            channel.  If not then we cannot be sure about its validity, and
687            we'll resolve it from router. */
688         if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
689             entry->connection || silc_hash_table_count(entry->channels))
690           continue;
691       }
692     }
693
694     /* When requested attributes is present and local client is detached
695        we cannot send the command to the client, we'll reply on behalf of
696        the client instead. */
697     if (attrs && SILC_IS_LOCAL(entry) && entry->mode & SILC_UMODE_DETACHED)
698       continue;
699
700     /* We need to resolve this entry since it is not complete */
701
702     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
703       /* The entry is being resolved (and we are not the resolver) so attach
704          to the command reply and we're done with this one. */
705       silc_server_command_pending(server, SILC_COMMAND_NONE,
706                                   entry->resolve_cmd_ident,
707                                   silc_server_command_whois,
708                                   silc_server_command_dup(cmd));
709       no_res = FALSE;
710     } else {
711       SilcBuffer idp;
712       SilcSocketConnection sock;
713
714       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
715         /* We've resolved this and it still is not ready.  We'll return
716            and are that this will be handled again after it is resolved. */
717         for (i = 0; i < resolve_count; i++) {
718           for (k = 0; k < r->res_argc; k++)
719             silc_free(r->res_argv[k]);
720           silc_free(r->res_argv);
721           silc_free(r->res_argv_lens);
722           silc_free(r->res_argv_types);
723         }
724         silc_free(resolve);
725         return FALSE;
726       }
727
728       /* We'll resolve this client now */
729
730       sock = (SILC_IS_LOCAL(entry) ? entry->connection :
731               entry->router->connection);
732       if (!sock)
733         continue;
734
735       r = NULL;
736       for (k = 0; k < resolve_count; k++) {
737         if (resolve[k].sock == sock) {
738           r = &resolve[k];
739           break;
740         }
741       }
742
743       if (!r) {
744         resolve = silc_realloc(resolve, sizeof(*resolve) * 
745                                (resolve_count + 1));
746         r = &resolve[resolve_count];
747         memset(r, 0, sizeof(*r));
748         r->sock = sock;
749         r->ident = ++server->cmd_ident;
750         if (SILC_IS_LOCAL(entry))
751           r->res_timeout = 2;
752         else
753           r->res_timeout = 0;
754         resolve_count++;
755       }
756
757       r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
758                                  (r->res_argc + 1));
759       r->res_argv_lens = silc_realloc(r->res_argv_lens, 
760                                       sizeof(*r->res_argv_lens) *
761                                       (r->res_argc + 1));
762       r->res_argv_types = silc_realloc(r->res_argv_types, 
763                                        sizeof(*r->res_argv_types) *
764                                        (r->res_argc + 1));
765       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
766       r->res_argv[r->res_argc] = silc_calloc(idp->len, 
767                                              sizeof(**r->res_argv));
768       memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
769       r->res_argv_lens[r->res_argc] = idp->len;
770       r->res_argv_types[r->res_argc] = r->res_argc + 4;
771       r->res_argc++;
772       silc_buffer_free(idp);
773
774       entry->resolve_cmd_ident = r->ident;
775       entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
776       entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
777     }
778   }
779
780   /* Do the resolving */
781   for (i = 0; i < resolve_count; i++) {
782     SilcBuffer res_cmd;
783     unsigned char *attrs_buf;
784     SilcUInt32 attrs_buf_len;
785
786     r = &resolve[i];
787
788     /* If attributes were present put them to this resolving as well */
789     if (attrs) {
790       attrs_buf = silc_argument_get_arg_type(cmd->args, 3, &attrs_buf_len);
791       if (attrs_buf) {
792         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
793                                    (r->res_argc + 1));
794         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
795                                         sizeof(*r->res_argv_lens) *
796                                         (r->res_argc + 1));
797         r->res_argv_types = silc_realloc(r->res_argv_types, 
798                                          sizeof(*r->res_argv_types) *
799                                          (r->res_argc + 1));
800         r->res_argv[r->res_argc] = silc_memdup(attrs_buf, attrs_buf_len);
801         r->res_argv_lens[r->res_argc] = attrs_buf_len;
802         r->res_argv_types[r->res_argc] = 3;
803         r->res_argc++;
804       }
805     }
806
807     /* Send WHOIS command */
808     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
809                                           r->res_argc, r->res_argv, 
810                                           r->res_argv_lens,
811                                           r->res_argv_types, 
812                                           r->ident);
813     silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
814                             cmd->packet->flags, res_cmd->data,
815                             res_cmd->len, FALSE);
816
817     /* Reprocess this packet after received reply */
818     silc_server_command_pending_timed(server, SILC_COMMAND_WHOIS, r->ident,
819                                       silc_server_command_whois,
820                                       silc_server_command_dup(cmd),
821                                       r->res_timeout);
822     cmd->pending = TRUE;
823
824     silc_buffer_free(res_cmd);
825     for (k = 0; k < r->res_argc; k++)
826       silc_free(r->res_argv[k]);
827     silc_free(r->res_argv);
828     silc_free(r->res_argv_lens);
829     silc_free(r->res_argv_types);
830     no_res = FALSE;
831   }
832   silc_free(resolve);
833
834   return no_res;
835 }
836
837 static void
838 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
839                                      SilcClientEntry *clients,
840                                      SilcUInt32 clients_count, 
841                                      ResolveError errors,
842                                      SilcUInt32 errors_count,
843                                      int count, const char *nickname,
844                                      SilcClientID **client_ids)
845 {
846   SilcServer server = cmd->server;
847   char *tmp;
848   int i, k, valid_count = clients_count;
849   SilcUInt32 len;
850   SilcBuffer packet, idp, channels, umode_list = NULL;
851   SilcClientEntry entry;
852   SilcStatus status;
853   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
854   char nh[256], uh[256];
855   unsigned char idle[4], mode[4];
856   unsigned char *fingerprint, fempty[20];
857   SilcSocketConnection hsock;
858
859   if (nickname) {
860     /* Process only valid clients and ignore those that are not registered. 
861        This is checked with nickname only because when resolved client IDs
862        we check that they are registered earlier. */
863     valid_count = 0;
864     for (i = 0; i < clients_count; i++)
865       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
866         valid_count++;
867       else
868         clients[i] = NULL;
869
870     if (!valid_count) {
871       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
872                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
873                                            3, nickname, strlen(nickname));
874       return;
875     }
876   }
877
878   memset(fempty, 0, sizeof(fempty));
879
880   /* Start processing found clients. */
881   status = SILC_STATUS_OK;
882   if (valid_count > 1)
883     status = SILC_STATUS_LIST_START;
884
885   for (i = 0, k = 0; i < clients_count; i++) {
886     entry = clients[i];
887     if (!entry)
888       continue;
889
890     if (k >= 1)
891       status = SILC_STATUS_LIST_ITEM;
892     if (valid_count > 1 && k == valid_count - 1 && !errors_count)
893       status = SILC_STATUS_LIST_END;
894     if (count && k - 1 == count)
895       status = SILC_STATUS_LIST_END;
896
897     /* Send WHOIS reply */
898     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
899     tmp = silc_argument_get_first_arg(cmd->args, NULL);
900     
901     memset(uh, 0, sizeof(uh));
902     memset(nh, 0, sizeof(nh));
903     memset(idle, 0, sizeof(idle));
904     
905     strncat(nh, entry->nickname, strlen(entry->nickname));
906     if (!strchr(entry->nickname, '@')) {
907       strncat(nh, "@", 1);
908       if (entry->servername) {
909         strncat(nh, entry->servername, strlen(entry->servername));
910       } else {
911         len = entry->router ? strlen(entry->router->server_name) :
912           strlen(server->server_name);
913         strncat(nh, entry->router ? entry->router->server_name :
914                 server->server_name, len);
915       }
916     }
917       
918     strncat(uh, entry->username, strlen(entry->username));
919     if (!strchr(entry->username, '@') && entry->connection) {
920       strncat(uh, "@", 1);
921       hsock = (SilcSocketConnection)entry->connection;
922       len = strlen(hsock->hostname);
923       strncat(uh, hsock->hostname, len);
924     }
925
926     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
927       channels = silc_server_get_client_channel_list(server, entry, FALSE, 
928                                                      FALSE, &umode_list);
929     else
930       channels = silc_server_get_client_channel_list(server, entry, TRUE, 
931                                                      TRUE, &umode_list);
932
933     if (memcmp(entry->data.fingerprint, fempty, sizeof(fempty)))
934       fingerprint = entry->data.fingerprint;
935     else
936       fingerprint = NULL;
937       
938     SILC_PUT32_MSB(entry->mode, mode);
939     if (entry->connection)
940       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
941
942     packet = 
943       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
944                                            status, 0, ident, 9, 
945                                            2, idp->data, idp->len,
946                                            3, nh, strlen(nh),
947                                            4, uh, strlen(uh),
948                                            5, entry->userinfo, 
949                                            strlen(entry->userinfo),
950                                            6, channels ? channels->data : NULL,
951                                            channels ? channels->len : 0,
952                                            7, mode, 4,
953                                            8, idle, 4,
954                                            9, fingerprint,
955                                            fingerprint ? 20 : 0,
956                                            10, umode_list ? umode_list->data :
957                                            NULL, umode_list ? umode_list->len :
958                                            0);
959
960     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
961                             0, packet->data, packet->len, FALSE);
962     
963     silc_buffer_free(packet);
964     silc_buffer_free(idp);
965     if (channels)
966       silc_buffer_free(channels);
967     if (umode_list) {
968       silc_buffer_free(umode_list);
969       umode_list = NULL;
970     }
971
972     if (status == SILC_STATUS_LIST_END)
973       break;
974     k++;
975   }
976
977   /* Send error replies */
978   if (status == SILC_STATUS_OK && errors_count > 1)
979     status = SILC_STATUS_LIST_START;
980
981   idp = NULL;
982   for (i = 0, k = 0; i < errors_count; i++) {
983     if (errors[i].id) {
984       idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
985       tmp = idp->data;
986       len = idp->len;
987     } else {
988       tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
989     }
990       
991     if (k >= 1)
992       status = SILC_STATUS_LIST_ITEM;
993     if (errors_count > 1 && k == errors_count - 1)
994       status = SILC_STATUS_LIST_END;
995     if (count && k - 1 == count)
996       status = SILC_STATUS_LIST_END;
997       
998     /* Send error */
999     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1000                                          (status == SILC_STATUS_OK ?
1001                                           errors[i].error : status),
1002                                          (status == SILC_STATUS_OK ?
1003                                           0 : errors[i].error),
1004                                          2, tmp, len);
1005     silc_buffer_free(idp);
1006     idp = NULL;
1007       
1008     if (status == SILC_STATUS_LIST_END)
1009       break;
1010     k++;
1011   }
1012 }
1013
1014 static void 
1015 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
1016 {
1017   SilcServer server = cmd->server;
1018   SilcBuffer tmpbuf;
1019   SilcUInt16 old_ident;
1020
1021   old_ident = silc_command_get_ident(cmd->payload);
1022   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1023   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1024
1025   /* Send WHOIS command to our router */
1026   silc_server_packet_send(server, (SilcSocketConnection)
1027                           SILC_PRIMARY_ROUTE(server),
1028                           SILC_PACKET_COMMAND, cmd->packet->flags,
1029                           tmpbuf->data, tmpbuf->len, TRUE);
1030
1031   /* Reprocess this packet after received reply from router */
1032   silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1033                               silc_command_get_ident(cmd->payload),
1034                               silc_server_command_whois,
1035                               silc_server_command_dup(cmd));
1036   cmd->pending = TRUE;
1037   silc_command_set_ident(cmd->payload, old_ident);
1038   silc_buffer_free(tmpbuf);
1039 }
1040
1041 static int
1042 silc_server_command_whois_process(SilcServerCommandContext cmd)
1043 {
1044   SilcServer server = cmd->server;
1045   char *nick = NULL, *server_name = NULL;
1046   int count = 0;
1047   SilcClientEntry *clients = NULL, entry;
1048   SilcClientID **client_id = NULL;
1049   SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
1050   ResolveError error_client = NULL;
1051   SilcDList attrs = NULL;
1052   int i, ret = 0;
1053   bool check_global = FALSE;
1054
1055   /* Parse the whois request */
1056   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1057                                        &nick, &server_name, &count,
1058                                        &error_client, &error_client_count,
1059                                        &attrs))
1060     return 0;
1061
1062   /* Send the WHOIS request to the router only if it included nickname.
1063      Since nicknames can be expanded into many clients we need to send it
1064      to router.  If the WHOIS included only client ID's we will check them
1065      first locally since we just might have them. */
1066   if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1067       server->server_type == SILC_SERVER && !cmd->pending &&
1068       !server->standalone) {
1069     silc_server_command_whois_send_router(cmd);
1070     ret = -1;
1071     goto out;
1072   }
1073
1074   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1075     check_global = TRUE;
1076   else if (server->server_type != SILC_SERVER)
1077     check_global = TRUE;
1078
1079   /* Get all clients matching that ID or nickname from local list */
1080   if (client_id_count) {
1081     /* Check all Client ID's received in the command packet */
1082     for (i = 0; i < client_id_count; i++) {
1083       entry = silc_idlist_find_client_by_id(server->local_list,
1084                                             client_id[i], TRUE, NULL);
1085       if (!entry && check_global)
1086         entry = silc_idlist_find_client_by_id(server->global_list,
1087                                               client_id[i], TRUE, NULL);
1088       if (entry) {
1089         clients = silc_realloc(clients, sizeof(*clients) *
1090                                (clients_count + 1));
1091         clients[clients_count++] = entry;
1092       } else {
1093         /* If we are normal server and did not send the request first to router
1094            do it now, since we do not have the Client ID information. */
1095         if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1096             server->server_type == SILC_SERVER && !cmd->pending &&
1097             !server->standalone) {
1098           silc_server_command_whois_send_router(cmd);
1099           ret = -1;
1100           goto out;
1101         }
1102
1103         ADD_ERROR(error_client, error_client_count, client_id[i],
1104                   SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1105       }
1106     }
1107   } else if (nick) {
1108     /* Find by nickname */
1109     if (!silc_idlist_get_clients_by_hash(server->local_list,
1110                                          nick, server->md5hash,
1111                                          &clients, &clients_count))
1112       silc_idlist_get_clients_by_nickname(server->local_list,
1113                                           nick, server_name,
1114                                           &clients, &clients_count);
1115     if (check_global) {
1116       if (!silc_idlist_get_clients_by_hash(server->global_list,
1117                                            nick, server->md5hash,
1118                                            &clients, &clients_count))
1119         silc_idlist_get_clients_by_nickname(server->global_list,
1120                                             nick, server_name,
1121                                             &clients, &clients_count);
1122     }
1123   }
1124   
1125   if (!clients && (client_id_count || nick)) {
1126     /* If we are normal server and did not send the request first to router
1127        do it now, since we do not have the information. */
1128     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1129         server->server_type == SILC_SERVER && !cmd->pending &&
1130         !server->standalone) {
1131       silc_server_command_whois_send_router(cmd);
1132       ret = -1;
1133       goto out;
1134     }
1135
1136     /* Such client(s) really does not exist in the SILC network. */
1137     if (!client_id_count)
1138       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1139                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1140                                            3, nick, strlen(nick));
1141     else
1142       silc_server_command_whois_send_reply(cmd, NULL, 0,
1143                                            error_client, error_client_count,
1144                                            0, NULL, NULL);
1145     goto out;
1146   }
1147
1148   /* Router always finds the client entry if it exists in the SILC network.
1149      However, it might be incomplete entry and does not include all the
1150      mandatory fields that WHOIS command reply requires. Check for these and
1151      make query from the server who owns the client if some fields are 
1152      missing. */
1153   if (!silc_server_command_whois_check(cmd, clients, clients_count, attrs)) {
1154     ret = -1;
1155     goto out;
1156   }
1157
1158   /* Send the command reply */
1159   silc_server_command_whois_send_reply(cmd, clients, clients_count,
1160                                        error_client, error_client_count,
1161                                        count, nick, client_id);
1162
1163  out:
1164   if (client_id_count) {
1165     for (i = 0; i < client_id_count; i++)
1166       silc_free(client_id[i]);
1167     silc_free(client_id);
1168   }
1169   silc_free(clients);
1170   silc_free(error_client);
1171   silc_free(nick);
1172   silc_free(server_name);
1173   if (attrs)
1174     silc_attribute_payload_list_free(attrs);
1175
1176   return ret;
1177 }
1178
1179 /* Server side of command WHOIS. Processes user's query and sends found 
1180    results as command replies back to the client. */
1181
1182 SILC_SERVER_CMD_FUNC(whois)
1183 {
1184   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1185   int ret = 0;
1186
1187   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1188
1189   ret = silc_server_command_whois_process(cmd);
1190   silc_server_command_free(cmd);
1191 }
1192
1193 /******************************************************************************
1194
1195                               WHOWAS Functions
1196
1197 ******************************************************************************/
1198
1199 static int
1200 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1201                                  char **nickname,
1202                                  char **server_name,
1203                                  int *count)
1204 {
1205   unsigned char *tmp;
1206   SilcUInt32 len;
1207
1208   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1209   if (!tmp) {
1210     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1211                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 
1212                                           0);
1213     return FALSE;
1214   }
1215
1216   /* Get the nickname@server string and parse it. */
1217   silc_parse_userfqdn(tmp, nickname, server_name);
1218
1219   /* Get the max count of reply messages allowed */
1220   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1221   if (tmp)
1222     SILC_GET32_MSB(*count, tmp);
1223   else
1224     *count = 0;
1225
1226   return TRUE;
1227 }
1228
1229 static char
1230 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1231                                  SilcClientEntry *clients,
1232                                  SilcUInt32 clients_count)
1233 {
1234   SilcServer server = cmd->server;
1235   int i;
1236   SilcClientEntry entry;
1237
1238   for (i = 0; i < clients_count; i++) {
1239     entry = clients[i];
1240
1241     if (!entry->nickname || !entry->username) {
1242       SilcBuffer tmpbuf;
1243       SilcUInt16 old_ident;
1244
1245       if (!entry->router)
1246         continue;
1247       
1248       old_ident = silc_command_get_ident(cmd->payload);
1249       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1250       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1251
1252       /* Send WHOWAS command */
1253       silc_server_packet_send(server, entry->router->connection,
1254                               SILC_PACKET_COMMAND, cmd->packet->flags,
1255                               tmpbuf->data, tmpbuf->len, TRUE);
1256       
1257       /* Reprocess this packet after received reply */
1258       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1259                                   silc_command_get_ident(cmd->payload),
1260                                   silc_server_command_whowas, 
1261                                   silc_server_command_dup(cmd));
1262       cmd->pending = TRUE;
1263       silc_command_set_ident(cmd->payload, old_ident);
1264
1265       silc_buffer_free(tmpbuf);
1266       return FALSE;
1267     }
1268   }
1269
1270   return TRUE;
1271 }
1272
1273 static void
1274 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1275                                       SilcClientEntry *clients,
1276                                       SilcUInt32 clients_count)
1277 {
1278   SilcServer server = cmd->server;
1279   char *tmp;
1280   int i, k, count = 0, len;
1281   SilcBuffer packet, idp;
1282   SilcClientEntry entry = NULL;
1283   SilcStatus status;
1284   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1285   char nh[256], uh[256];
1286   int valid_count;
1287
1288   status = SILC_STATUS_OK;
1289
1290   /* Process only entries that are not registered anymore. */
1291   valid_count = 0;
1292   for (i = 0; i < clients_count; i++) {
1293     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1294       clients[i] = NULL;
1295     else
1296       valid_count++;
1297   }
1298
1299   if (!valid_count) {
1300     /* No valid entries found at all, just send error */
1301     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1302     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1303                                          SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1304                                          3, tmp, tmp ? strlen(tmp) : 0);
1305     return;
1306   }
1307
1308   if (valid_count > 1)
1309     status = SILC_STATUS_LIST_START;
1310
1311   for (i = 0, k = 0; i < clients_count; i++) {
1312     entry = clients[i];
1313     if (!entry)
1314       continue;
1315
1316     if (k >= 1)
1317       status = SILC_STATUS_LIST_ITEM;
1318     if (valid_count > 1 && k == valid_count - 1)
1319       status = SILC_STATUS_LIST_END;
1320     if (count && k - 1 == count)
1321       status = SILC_STATUS_LIST_END;
1322
1323     /* Send WHOWAS reply */
1324     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1325     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1326     memset(uh, 0, sizeof(uh));
1327     memset(nh, 0, sizeof(nh));
1328
1329     strncat(nh, entry->nickname, strlen(entry->nickname));
1330     if (!strchr(entry->nickname, '@')) {
1331       strncat(nh, "@", 1);
1332       if (entry->servername) {
1333         strncat(nh, entry->servername, strlen(entry->servername));
1334       } else {
1335         len = entry->router ? strlen(entry->router->server_name) :
1336           strlen(server->server_name);
1337         strncat(nh, entry->router ? entry->router->server_name :
1338                 server->server_name, len);
1339       }
1340     }
1341       
1342     strncat(uh, entry->username, strlen(entry->username));
1343     if (!strchr(entry->username, '@')) {
1344       strncat(uh, "@", 1);
1345       strcat(uh, "*private*");
1346     }
1347       
1348     packet = 
1349       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1350                                            status, 0, ident, 4, 
1351                                            2, idp->data, idp->len,
1352                                            3, nh, strlen(nh),
1353                                            4, uh, strlen(uh),
1354                                            5, entry->userinfo, 
1355                                            entry->userinfo ? 
1356                                            strlen(entry->userinfo) : 0);
1357     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1358                             0, packet->data, packet->len, FALSE);
1359     
1360     silc_buffer_free(packet);
1361     silc_buffer_free(idp);
1362
1363     if (status == SILC_STATUS_LIST_END)
1364       break;
1365     k++;
1366   }
1367 }
1368
1369 static int
1370 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1371 {
1372   SilcServer server = cmd->server;
1373   char *nick = NULL, *server_name = NULL;
1374   int count = 0;
1375   SilcClientEntry *clients = NULL;
1376   SilcUInt32 clients_count = 0;
1377   int ret = 0;
1378   bool check_global = FALSE;
1379
1380   /* Protocol dictates that we must always send the received WHOWAS request
1381      to our router if we are normal server, so let's do it now unless we
1382      are standalone. We will not send any replies to the client until we
1383      have received reply from the router. */
1384   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1385       server->server_type == SILC_SERVER && !cmd->pending && 
1386       !server->standalone) {
1387     SilcBuffer tmpbuf;
1388     SilcUInt16 old_ident;
1389
1390     old_ident = silc_command_get_ident(cmd->payload);
1391     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1392     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1393
1394     /* Send WHOWAS command to our router */
1395     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1396                             SILC_PACKET_COMMAND, cmd->packet->flags,
1397                             tmpbuf->data, tmpbuf->len, TRUE);
1398
1399     /* Reprocess this packet after received reply from router */
1400     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1401                                 silc_command_get_ident(cmd->payload),
1402                                 silc_server_command_whowas,
1403                                 silc_server_command_dup(cmd));
1404     cmd->pending = TRUE;
1405     silc_command_set_ident(cmd->payload, old_ident);
1406
1407     silc_buffer_free(tmpbuf);
1408     ret = -1;
1409     goto out;
1410   }
1411
1412   /* We are ready to process the command request. Let's search for the
1413      requested client and send reply to the requesting client. */
1414
1415   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1416     check_global = TRUE;
1417   else if (server->server_type != SILC_SERVER)
1418     check_global = TRUE;
1419
1420   /* Parse the whowas request */
1421   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1422     return 0;
1423
1424   /* Get all clients matching that nickname from local list */
1425   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1426                                            nick, server_name,
1427                                            &clients, &clients_count))
1428     silc_idlist_get_clients_by_hash(server->local_list, 
1429                                     nick, server->md5hash,
1430                                     &clients, &clients_count);
1431   
1432   /* Check global list as well */
1433   if (check_global) {
1434     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1435                                              nick, server_name,
1436                                              &clients, &clients_count))
1437       silc_idlist_get_clients_by_hash(server->global_list, 
1438                                       nick, server->md5hash,
1439                                       &clients, &clients_count);
1440   }
1441   
1442   if (!clients) {
1443     /* Such a client really does not exist in the SILC network. */
1444     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1445                                          SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1446                                          3, nick, strlen(nick));
1447     goto out;
1448   }
1449
1450   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1451     ret = -1;
1452     goto out;
1453   }
1454
1455   /* Send the command reply to the client */
1456   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1457
1458  out:
1459   silc_free(clients);
1460   silc_free(nick);
1461   silc_free(server_name);
1462   return ret;
1463 }
1464
1465 /* Server side of command WHOWAS. */
1466
1467 SILC_SERVER_CMD_FUNC(whowas)
1468 {
1469   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1470   int ret = 0;
1471
1472   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1473
1474   ret = silc_server_command_whowas_process(cmd);
1475   silc_server_command_free(cmd);
1476 }
1477
1478 /******************************************************************************
1479
1480                               IDENTIFY Functions
1481
1482 ******************************************************************************/
1483
1484 static void 
1485 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1486 {
1487   SilcServer server = cmd->server;
1488   SilcBuffer tmpbuf;
1489   SilcUInt16 old_ident;
1490
1491   old_ident = silc_command_get_ident(cmd->payload);
1492   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1493   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1494
1495   /* Send IDENTIFY command to our router */
1496   silc_server_packet_send(server, (SilcSocketConnection)
1497                           SILC_PRIMARY_ROUTE(server),
1498                           SILC_PACKET_COMMAND, cmd->packet->flags,
1499                           tmpbuf->data, tmpbuf->len, TRUE);
1500
1501   /* Reprocess this packet after received reply from router */
1502   silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1503                               silc_command_get_ident(cmd->payload),
1504                               silc_server_command_identify,
1505                               silc_server_command_dup(cmd));
1506   cmd->pending = TRUE;
1507   silc_command_set_ident(cmd->payload, old_ident);
1508   silc_buffer_free(tmpbuf);
1509 }
1510
1511 static int
1512 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1513                                    SilcClientEntry **clients,
1514                                    SilcUInt32 *clients_count,
1515                                    SilcServerEntry **servers,
1516                                    SilcUInt32 *servers_count,
1517                                    SilcChannelEntry **channels,
1518                                    SilcUInt32 *channels_count,
1519                                    SilcUInt32 *count,
1520                                    ResolveError *error_id,
1521                                    SilcUInt32 *error_id_count)
1522 {
1523   SilcServer server = cmd->server;
1524   unsigned char *tmp;
1525   SilcUInt32 len;
1526   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1527   SilcIDPayload idp;
1528   bool check_global = FALSE;
1529   void *entry;
1530   int i;
1531
1532   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1533     check_global = TRUE;
1534   else if (server->server_type != SILC_SERVER)
1535     check_global = TRUE;
1536
1537   /* If ID Payload is in the command it must be used instead of names */
1538   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1539   if (!tmp) {
1540     /* No ID, get the names. */
1541
1542     /* If we are normal server and have not resolved information from
1543        router yet, do so now. */
1544     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1545         server->server_type == SILC_SERVER && !cmd->pending && 
1546         !server->standalone) {
1547       silc_server_command_identify_send_router(cmd);
1548       return -1;
1549     }
1550
1551     /* Try to get nickname@server. */
1552     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1553     if (tmp) {
1554       char *nick = NULL;
1555       char *nick_server = NULL;
1556
1557       silc_parse_userfqdn(tmp, &nick, &nick_server);
1558
1559       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1560                                            nick, server->md5hash,
1561                                            clients, clients_count))
1562         silc_idlist_get_clients_by_nickname(server->local_list, 
1563                                             nick, nick_server,
1564                                             clients, clients_count);
1565       if (check_global) {
1566         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1567                                              nick, server->md5hash,
1568                                              clients, clients_count))
1569           silc_idlist_get_clients_by_nickname(server->global_list, 
1570                                               nick, nick_server,
1571                                               clients, clients_count);
1572       }
1573
1574       silc_free(nick);
1575       silc_free(nick_server);
1576
1577       if (!(*clients)) {
1578         /* the nickname does not exist, send error reply */
1579         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1580                                              SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1581                                              3, tmp, strlen(tmp));
1582         return 0;
1583       }
1584     }
1585
1586     /* Try to get server name */
1587     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1588     if (tmp) {
1589       entry = silc_idlist_find_server_by_name(server->local_list,
1590                                               tmp, TRUE, NULL);
1591       if (!entry && check_global)
1592         entry = silc_idlist_find_server_by_name(server->global_list,
1593                                                 tmp, TRUE, NULL);
1594       if (entry) {
1595         *servers = silc_realloc(*servers, sizeof(**servers) * 
1596                                 (*servers_count + 1));
1597         (*servers)[(*servers_count)++] = entry;
1598       }
1599
1600       if (!(*servers)) {
1601         /* the server does not exist, send error reply */
1602         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1603                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1604                                              0, 3, tmp, strlen(tmp));
1605         return 0;
1606       }
1607     }
1608
1609     /* Try to get channel name */
1610     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1611     if (tmp) {
1612       entry = silc_idlist_find_channel_by_name(server->local_list,
1613                                                tmp, NULL);
1614       if (!entry && check_global)
1615         entry = silc_idlist_find_channel_by_name(server->global_list,
1616                                                  tmp, NULL);
1617       if (entry) {
1618         *channels = silc_realloc(*channels, sizeof(**channels) * 
1619                                  (*channels_count + 1));
1620         (*channels)[(*channels_count)++] = entry;
1621       }
1622
1623       if (!(*channels)) {
1624         /* The channel does not exist, send error reply */
1625         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1626                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1627                                              0, 3, tmp, strlen(tmp));
1628         return 0;
1629       }
1630     }
1631
1632     if (!(*clients) && !(*servers) && !(*channels)) {
1633       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1634                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1635                                             0);
1636       return 0;
1637     }
1638   } else {
1639     /* Command includes ID, we must use that.  Also check whether the command
1640        has more than one ID set - take them all. */
1641
1642     /* Take all ID's from the command packet */
1643     for (i = 0; i < argc; i++) {
1644       void *id;
1645
1646       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1647       if (!tmp)
1648         continue;
1649       
1650       idp = silc_id_payload_parse(tmp, len);
1651       if (!idp)
1652         ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1653                   SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1654
1655       id = silc_id_payload_get_id(idp);
1656       switch (silc_id_payload_get_type(idp)) {
1657         
1658       case SILC_ID_CLIENT:
1659         entry = silc_idlist_find_client_by_id(server->local_list, 
1660                                               id, TRUE, NULL);
1661         if (!entry && check_global)
1662           entry = silc_idlist_find_client_by_id(server->global_list, 
1663                                                 id, TRUE, NULL);
1664         if (entry) {
1665           *clients = silc_realloc(*clients, sizeof(**clients) * 
1666                                   (*clients_count + 1));
1667           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1668         } else {
1669           /* If we are normal server and have not resolved information from
1670              router yet, do so now. */
1671           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1672               server->server_type == SILC_SERVER && !cmd->pending && 
1673               !server->standalone) {
1674             silc_server_command_identify_send_router(cmd);
1675             silc_free(*clients);
1676             silc_free(*servers);
1677             silc_free(*channels);
1678             silc_free(*error_id);
1679             return -1;
1680           }
1681
1682           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1683                     SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1684         }
1685
1686         break;
1687         
1688       case SILC_ID_SERVER:
1689         entry = silc_idlist_find_server_by_id(server->local_list, 
1690                                               id, TRUE, NULL);
1691         if (!entry && check_global)
1692           entry = silc_idlist_find_server_by_id(server->global_list, 
1693                                                 id, TRUE, NULL);
1694         if (entry) {
1695           *servers = silc_realloc(*servers, sizeof(**servers) * 
1696                                   (*servers_count + 1));
1697           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1698         } else {
1699           /* If we are normal server and have not resolved information from
1700              router yet, do so now. */
1701           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1702               server->server_type == SILC_SERVER && !cmd->pending && 
1703               !server->standalone) {
1704             silc_server_command_identify_send_router(cmd);
1705             silc_free(*clients);
1706             silc_free(*servers);
1707             silc_free(*channels);
1708             silc_free(*error_id);
1709             return -1;
1710           }
1711
1712           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1713                     SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1714         }
1715         break;
1716         
1717       case SILC_ID_CHANNEL:
1718         entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1719         if (!entry && check_global)
1720           entry = silc_idlist_find_channel_by_id(server->global_list, id,
1721                                                  NULL);
1722         if (entry) {
1723           *channels = silc_realloc(*channels, sizeof(**channels) * 
1724                                    (*channels_count + 1));
1725           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1726         } else {
1727           /* If we are normal server and have not resolved information from
1728              router yet, do so now. */
1729           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1730               server->server_type == SILC_SERVER && !cmd->pending && 
1731               !server->standalone) {
1732             silc_server_command_identify_send_router(cmd);
1733             silc_free(*clients);
1734             silc_free(*servers);
1735             silc_free(*channels);
1736             silc_free(*error_id);
1737             return -1;
1738           }
1739
1740           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1741                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1742         }
1743         break;
1744       }
1745
1746       silc_id_payload_free(idp);
1747       silc_free(id);
1748     }
1749   }
1750
1751   /* Get the max count of reply messages allowed */
1752   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1753   if (tmp)
1754     SILC_GET32_MSB(*count, tmp);
1755   else
1756     *count = 0;
1757
1758   return 1;
1759 }
1760
1761 /* Checks that all mandatory fields in client entry are present. If not
1762    then send WHOIS request to the server who owns the client. We use
1763    WHOIS because we want to get as much information as possible at once. */
1764
1765 static bool
1766 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1767                                           SilcClientEntry *clients,
1768                                           SilcUInt32 clients_count)
1769 {
1770   SilcServer server = cmd->server;
1771   SilcClientEntry entry;
1772   SilcServerResolveContext resolve = NULL, r = NULL;
1773   SilcUInt32 resolve_count = 0;
1774   int i, k;
1775   bool no_res = TRUE;
1776
1777   for (i = 0; i < clients_count; i++) {
1778     entry = clients[i];
1779     if (!entry)
1780       continue;
1781
1782     if (entry->nickname || 
1783         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1784       if (!entry->router)
1785         continue;
1786
1787       /* If we are normal server, and we've not resolved this client from
1788          router and it is global client, we'll check whether it is on some
1789          channel.  If not then we cannot be sure about its validity, and
1790          we'll resolve it from router. */
1791       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1792           entry->connection || silc_hash_table_count(entry->channels))
1793         continue;
1794     }
1795
1796     /* We need to resolve this entry since it is not complete */
1797
1798     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1799       /* The entry is being resolved (and we are not the resolver) so attach
1800          to the command reply and we're done with this one. */
1801       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1802                                   entry->resolve_cmd_ident,
1803                                   silc_server_command_identify,
1804                                   silc_server_command_dup(cmd));
1805       no_res = FALSE;
1806     } else {
1807       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1808         /* We've resolved this and it still is not ready.  We'll return
1809            and are that this will be handled again after it is resolved. */
1810         for (i = 0; i < resolve_count; i++) {
1811           for (k = 0; k < r->res_argc; k++)
1812             silc_free(r->res_argv[k]);
1813           silc_free(r->res_argv);
1814           silc_free(r->res_argv_lens);
1815           silc_free(r->res_argv_types);
1816         }
1817         silc_free(resolve);
1818         return FALSE;
1819       } else {
1820         /* We'll resolve this client */
1821         SilcBuffer idp;
1822
1823         r = NULL;
1824         for (k = 0; k < resolve_count; k++) {
1825           if (resolve[k].sock == entry->router->connection) {
1826             r = &resolve[k];
1827             break;
1828           }
1829         }
1830
1831         if (!r) {
1832           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1833                                  (resolve_count + 1));
1834           r = &resolve[resolve_count];
1835           memset(r, 0, sizeof(*r));
1836           r->sock = entry->router->connection;
1837           r->ident = ++server->cmd_ident;
1838           resolve_count++;
1839         }
1840
1841         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1842                                    (r->res_argc + 1));
1843         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1844                                         sizeof(*r->res_argv_lens) *
1845                                         (r->res_argc + 1));
1846         r->res_argv_types = silc_realloc(r->res_argv_types, 
1847                                          sizeof(*r->res_argv_types) *
1848                                          (r->res_argc + 1));
1849         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1850         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1851                                                sizeof(**r->res_argv));
1852         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1853         r->res_argv_lens[r->res_argc] = idp->len;
1854         r->res_argv_types[r->res_argc] = r->res_argc + 4;
1855         r->res_argc++;
1856         silc_buffer_free(idp);
1857
1858         entry->resolve_cmd_ident = r->ident;
1859         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1860         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1861       }
1862     }
1863   }
1864
1865   /* Do the resolving */
1866   for (i = 0; i < resolve_count; i++) {
1867     SilcBuffer res_cmd;
1868
1869     r = &resolve[i];
1870
1871     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1872        now anyway so make it a good one. */
1873     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1874                                           r->res_argc, r->res_argv, 
1875                                           r->res_argv_lens,
1876                                           r->res_argv_types, 
1877                                           r->ident);
1878     silc_server_packet_send(server, r->sock, SILC_PACKET_COMMAND,
1879                             cmd->packet->flags, res_cmd->data,
1880                             res_cmd->len, FALSE);
1881
1882     /* Reprocess this packet after received reply */
1883     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1884                                 r->ident,
1885                                 silc_server_command_identify,
1886                                 silc_server_command_dup(cmd));
1887     cmd->pending = TRUE;
1888
1889     silc_buffer_free(res_cmd);
1890     for (k = 0; k < r->res_argc; k++)
1891       silc_free(r->res_argv[k]);
1892     silc_free(r->res_argv);
1893     silc_free(r->res_argv_lens);
1894     silc_free(r->res_argv_types);
1895     no_res = FALSE;
1896   }
1897   silc_free(resolve);
1898
1899   return no_res;
1900 }
1901
1902 static void
1903 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1904                                         SilcClientEntry *clients,
1905                                         SilcUInt32 clients_count,
1906                                         SilcServerEntry *servers,
1907                                         SilcUInt32 servers_count,
1908                                         SilcChannelEntry *channels,
1909                                         SilcUInt32 channels_count,
1910                                         ResolveError errors,
1911                                         SilcUInt32 errors_count,
1912                                         int count)
1913 {
1914   SilcServer server = cmd->server;
1915   int i, k, valid_count;
1916   SilcUInt32 len;
1917   SilcBuffer packet, idp;
1918   SilcStatus status;
1919   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1920   char nh[256], uh[256];
1921   SilcSocketConnection hsock;
1922   unsigned char *tmp;
1923
1924   status = SILC_STATUS_OK;
1925
1926   if (clients) {
1927     SilcClientEntry entry;
1928     valid_count = clients_count;
1929
1930     if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1931       /* Process only valid clients and ignore those that are not registered. 
1932          This is checked with nickname only because when resolved client IDs
1933          we check that they are registered earlier. */
1934       valid_count = 0;
1935       for (i = 0; i < clients_count; i++) {
1936         if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1937           valid_count++;
1938         else
1939           clients[i] = NULL;
1940       }
1941
1942       if (!valid_count) {
1943         /* No valid entries found at all, just send error */
1944         tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1945         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1946                                              SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1947                                              3, tmp, tmp ? strlen(tmp) : 0);
1948         return;
1949       }
1950     }
1951
1952     /* Process all valid client entries and send command replies */
1953
1954     if (valid_count > 1)
1955       status = SILC_STATUS_LIST_START;
1956
1957     for (i = 0, k = 0; i < clients_count; i++) {
1958       entry = clients[i];
1959       if (!entry)
1960         continue;
1961
1962       if (k >= 1)
1963         status = SILC_STATUS_LIST_ITEM;
1964       if (valid_count > 1 && k == valid_count - 1 
1965           && !servers_count && !channels_count && !errors_count)
1966         status = SILC_STATUS_LIST_END;
1967       if (count && k - 1 == count)
1968         status = SILC_STATUS_LIST_END;
1969
1970       /* Send IDENTIFY reply */
1971
1972       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1973       memset(uh, 0, sizeof(uh));
1974       memset(nh, 0, sizeof(nh));
1975       strncat(nh, entry->nickname, strlen(entry->nickname));
1976       if (!strchr(entry->nickname, '@')) {
1977         strncat(nh, "@", 1);
1978         if (entry->servername) {
1979           strncat(nh, entry->servername, strlen(entry->servername));
1980         } else {
1981           len = entry->router ? strlen(entry->router->server_name) :
1982             strlen(server->server_name);
1983           strncat(nh, entry->router ? entry->router->server_name :
1984                   server->server_name, len);
1985         }
1986       }
1987
1988       if (!entry->username) {
1989         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1990                                                       status, 0, ident, 2,
1991                                                       2, idp->data, idp->len, 
1992                                                       3, nh, strlen(nh));
1993       } else {
1994         strncat(uh, entry->username, strlen(entry->username));
1995         if (!strchr(entry->username, '@') && entry->connection) {
1996           strncat(uh, "@", 1);
1997           hsock = (SilcSocketConnection)entry->connection;
1998           len = strlen(hsock->hostname);
1999           strncat(uh, hsock->hostname, len);
2000         }
2001         
2002         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2003                                                       status, 0, ident, 3,
2004                                                       2, idp->data, idp->len, 
2005                                                       3, nh, strlen(nh),
2006                                                       4, uh, strlen(uh));
2007       }
2008       
2009       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2010                               0, packet->data, packet->len, FALSE);
2011       
2012       silc_buffer_free(packet);
2013       silc_buffer_free(idp);
2014       
2015       if (status == SILC_STATUS_LIST_END)
2016         break;
2017       k++;
2018     }
2019   }
2020
2021   if (servers) {
2022     SilcServerEntry entry;
2023
2024     if (status == SILC_STATUS_OK && servers_count > 1)
2025       status = SILC_STATUS_LIST_START;
2026
2027     for (i = 0, k = 0; i < servers_count; i++) {
2028       entry = servers[i];
2029       
2030       if (k >= 1)
2031         status = SILC_STATUS_LIST_ITEM;
2032       if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
2033           !errors_count)
2034         status = SILC_STATUS_LIST_END;
2035       if (count && k - 1 == count)
2036         status = SILC_STATUS_LIST_END;
2037       
2038       /* Send IDENTIFY reply */
2039       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2040       packet = 
2041         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2042                                              status, 0, ident, 2,
2043                                              2, idp->data, idp->len, 
2044                                              3, entry->server_name, 
2045                                              entry->server_name ? 
2046                                              strlen(entry->server_name) : 0);
2047       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2048                               0, packet->data, packet->len, FALSE);
2049       
2050       silc_buffer_free(packet);
2051       silc_buffer_free(idp);
2052       
2053       if (status == SILC_STATUS_LIST_END)
2054         break;
2055       k++;
2056     }
2057   }
2058
2059   if (channels) {
2060     SilcChannelEntry entry;
2061
2062     if (status == SILC_STATUS_OK && channels_count > 1)
2063       status = SILC_STATUS_LIST_START;
2064
2065     for (i = 0, k = 0; i < channels_count; i++) {
2066       entry = channels[i];
2067       
2068       if (k >= 1)
2069         status = SILC_STATUS_LIST_ITEM;
2070       if (channels_count > 1 && k == channels_count - 1 && !errors_count)
2071         status = SILC_STATUS_LIST_END;
2072       if (count && k - 1 == count)
2073         status = SILC_STATUS_LIST_END;
2074       
2075       /* Send IDENTIFY reply */
2076       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2077       packet = 
2078         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
2079                                              status, 0, ident, 2,
2080                                              2, idp->data, idp->len, 
2081                                              3, entry->channel_name, 
2082                                              entry->channel_name ? 
2083                                              strlen(entry->channel_name): 0);
2084       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2085                               0, packet->data, packet->len, FALSE);
2086       
2087       silc_buffer_free(packet);
2088       silc_buffer_free(idp);
2089       
2090       if (status == SILC_STATUS_LIST_END)
2091         break;
2092       k++;
2093     }
2094   }
2095
2096   /* Send error replies */
2097   if (errors) {
2098     if (status == SILC_STATUS_OK && errors_count > 1)
2099       status = SILC_STATUS_LIST_START;
2100
2101     idp = NULL;
2102     for (i = 0, k = 0; i < errors_count; i++) {
2103       if (errors[i].id) {
2104         idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
2105         tmp = idp->data;
2106         len = idp->len;
2107       } else {
2108         tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
2109       }
2110       
2111       if (k >= 1)
2112         status = SILC_STATUS_LIST_ITEM;
2113       if (errors_count > 1 && k == errors_count - 1)
2114         status = SILC_STATUS_LIST_END;
2115       if (count && k - 1 == count)
2116         status = SILC_STATUS_LIST_END;
2117       
2118       /* Send error */
2119       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
2120                                            (status == SILC_STATUS_OK ?
2121                                             errors[i].error : status),
2122                                            (status == SILC_STATUS_OK ?
2123                                             0 : errors[i].error),
2124                                            2, tmp, len);
2125       silc_buffer_free(idp);
2126       idp = NULL;
2127       
2128       if (status == SILC_STATUS_LIST_END)
2129         break;
2130       k++;
2131     }
2132   }
2133 }
2134
2135 static int
2136 silc_server_command_identify_process(SilcServerCommandContext cmd)
2137 {
2138   SilcUInt32 count = 0;
2139   int ret = 0;
2140   SilcClientEntry *clients = NULL;
2141   SilcServerEntry *servers = NULL;
2142   SilcChannelEntry *channels = NULL;
2143   SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2144   SilcUInt32 errors_count = 0;
2145   ResolveError errors = NULL;
2146
2147   /* Parse the IDENTIFY request */
2148   ret = silc_server_command_identify_parse(cmd,
2149                                            &clients, &clients_count,
2150                                            &servers, &servers_count,
2151                                            &channels, &channels_count,
2152                                            &count, &errors, &errors_count);
2153   if (ret < 1)
2154     return ret;
2155   ret = 0;
2156
2157   /* Check that all mandatory fields are present and request those data
2158      from the server who owns the client if necessary. */
2159   if (!silc_server_command_identify_check_client(cmd, clients, 
2160                                                  clients_count)) {
2161     ret = -1;
2162     goto out;
2163   }
2164
2165   /* Send the command reply to the client */
2166   silc_server_command_identify_send_reply(cmd, 
2167                                           clients, clients_count,
2168                                           servers, servers_count,
2169                                           channels, channels_count, 
2170                                           errors, errors_count,
2171                                           count);
2172
2173  out:
2174   silc_free(clients);
2175   silc_free(servers);
2176   silc_free(channels);
2177   silc_free(errors);
2178   return ret;
2179 }
2180
2181 SILC_SERVER_CMD_FUNC(identify)
2182 {
2183   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2184   int ret = 0;
2185
2186   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2187
2188   ret = silc_server_command_identify_process(cmd);
2189   silc_server_command_free(cmd);
2190 }
2191
2192 /* Server side of command NICK. Sets nickname for user. Setting
2193    nickname causes generation of a new client ID for the client. The
2194    new client ID is sent to the client after changing the nickname. */
2195
2196 SILC_SERVER_CMD_FUNC(nick)
2197 {
2198   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2199   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2200   SilcServer server = cmd->server;
2201   SilcBuffer packet, nidp, oidp = NULL;
2202   SilcClientID *new_id;
2203   SilcUInt32 nick_len;
2204   char *nick;
2205   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2206   int nickfail = 0;
2207
2208   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2209     goto out;
2210
2211   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2212
2213   /* Check nickname */
2214   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2215   if (nick_len > 128)
2216     nick[128] = '\0';
2217   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2218     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2219                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
2220     goto out;
2221   }
2222
2223   /* Check for same nickname */
2224   if (!strcmp(client->nickname, nick)) {
2225     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2226     goto send_reply;
2227   }
2228
2229   /* Create new Client ID */
2230   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
2231                                    cmd->server->rng, 
2232                                    cmd->server->md5hash, nick,
2233                                    &new_id)) {
2234     nickfail++;
2235     if (nickfail > 9) {
2236       silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2237                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
2238       goto out;
2239     }
2240     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2241   }
2242
2243   /* Send notify about nickname change to our router. We send the new
2244      ID and ask to replace it with the old one. If we are router the
2245      packet is broadcasted. Send NICK_CHANGE notify. */
2246   silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2247                                       SILC_BROADCAST(server), client->id,
2248                                       new_id, nick);
2249
2250   /* Check if anyone is watching the old nickname */
2251   if (server->server_type == SILC_ROUTER)
2252     silc_server_check_watcher_list(server, client, nick,
2253                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
2254
2255   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2256
2257   /* Remove old cache entry */
2258   silc_idcache_del_by_context(server->local_list->clients, client);
2259
2260   silc_free(client->id);
2261   client->id = new_id;
2262
2263   silc_free(client->nickname);
2264   client->nickname = strdup(nick);
2265
2266   /* Update client cache */
2267   silc_idcache_add(server->local_list->clients, client->nickname, 
2268                    client->id, (void *)client, 0, NULL);
2269
2270   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2271
2272   /* Send NICK_CHANGE notify to the client's channels */
2273   silc_server_send_notify_on_channels(server, NULL, client, 
2274                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2275                                       oidp->data, oidp->len, 
2276                                       nidp->data, nidp->len,
2277                                       client->nickname, 
2278                                       strlen(client->nickname));
2279
2280   /* Check if anyone is watching the new nickname */
2281   if (server->server_type == SILC_ROUTER)
2282     silc_server_check_watcher_list(server, client, NULL,
2283                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
2284
2285  send_reply:
2286   /* Send the new Client ID as reply command back to client */
2287   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2288                                                 SILC_STATUS_OK, 0, ident, 2,
2289                                                 2, nidp->data, nidp->len,
2290                                                 3, nick, strlen(nick));
2291   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2292                           0, packet->data, packet->len, FALSE);
2293
2294   silc_buffer_free(packet);
2295   silc_buffer_free(nidp);
2296   if (oidp)
2297     silc_buffer_free(oidp);
2298   
2299  out:
2300   silc_server_command_free(cmd);
2301 }
2302
2303 /* Sends the LIST command reply */
2304
2305 static void
2306 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2307                                     SilcChannelEntry *lch, 
2308                                     SilcUInt32 lch_count,
2309                                     SilcChannelEntry *gch,
2310                                     SilcUInt32 gch_count)
2311 {
2312   int i, k;
2313   SilcBuffer packet, idp;
2314   SilcChannelEntry entry;
2315   SilcStatus status;
2316   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2317   char *topic;
2318   unsigned char usercount[4];
2319   SilcUInt32 users;
2320   int valid_lcount = 0, valid_rcount = 0;
2321
2322   for (i = 0; i < lch_count; i++) {
2323     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2324       lch[i] = NULL;
2325     else
2326       valid_lcount++;
2327   }
2328   for (i = 0; i < gch_count; i++) {
2329     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2330       gch[i] = NULL;
2331     else
2332       valid_rcount++;
2333   }
2334
2335   status = SILC_STATUS_OK;
2336   if ((lch_count + gch_count) > 1)
2337     status = SILC_STATUS_LIST_START;
2338
2339   /* Local list */
2340   for (i = 0, k = 0; i < lch_count; i++) {
2341     entry = lch[i];
2342     if (!entry)
2343       continue;
2344
2345     if (k >= 1)
2346       status = SILC_STATUS_LIST_ITEM;
2347     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2348       status = SILC_STATUS_LIST_END;
2349
2350     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2351
2352     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2353       topic = "*private*";
2354       memset(usercount, 0, sizeof(usercount));
2355     } else {
2356       topic = entry->topic;
2357       users = silc_hash_table_count(entry->user_list);
2358       SILC_PUT32_MSB(users, usercount);
2359     }
2360
2361     /* Send the reply */
2362     packet = 
2363       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2364                                            status, 0, ident, 4,
2365                                            2, idp->data, idp->len,
2366                                            3, entry->channel_name, 
2367                                            strlen(entry->channel_name),
2368                                            4, topic, topic ? strlen(topic) : 0,
2369                                            5, usercount, 4);
2370     silc_server_packet_send(cmd->server, cmd->sock, 
2371                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2372                             packet->len, FALSE);
2373     silc_buffer_free(packet);
2374     silc_buffer_free(idp);
2375     k++;
2376   }
2377
2378   /* Global list */
2379   for (i = 0, k = 0; i < gch_count; i++) {
2380     entry = gch[i];
2381     if (!entry)
2382       continue;
2383
2384     if (k >= 1)
2385       status = SILC_STATUS_LIST_ITEM;
2386     if (valid_rcount > 1 && k == valid_rcount - 1)
2387       status = SILC_STATUS_LIST_END;
2388
2389     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2390
2391     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2392       topic = "*private*";
2393       memset(usercount, 0, sizeof(usercount));
2394     } else {
2395       topic = entry->topic;
2396       users = entry->user_count;
2397       SILC_PUT32_MSB(users, usercount);
2398     }
2399
2400     /* Send the reply */
2401     packet = 
2402       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2403                                            status, 0, ident, 4,
2404                                            2, idp->data, idp->len,
2405                                            3, entry->channel_name, 
2406                                            strlen(entry->channel_name),
2407                                            4, topic, topic ? strlen(topic) : 0,
2408                                            5, usercount, 4);
2409     silc_server_packet_send(cmd->server, cmd->sock, 
2410                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2411                             packet->len, FALSE);
2412     silc_buffer_free(packet);
2413     silc_buffer_free(idp);
2414     k++;
2415   }
2416 }
2417
2418 /* Server side of LIST command. This lists the channel of the requested
2419    server. Secret channels are not listed. */
2420
2421 SILC_SERVER_CMD_FUNC(list)
2422 {
2423   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2424   SilcServer server = cmd->server;
2425   SilcChannelID *channel_id = NULL;
2426   unsigned char *tmp;
2427   SilcUInt32 tmp_len;
2428   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2429   SilcUInt32 lch_count = 0, gch_count = 0;
2430
2431   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2432
2433   /* If we are normal server, send the command to router, since we
2434      want to know all channels in the network. */
2435   if (!cmd->pending && server->server_type == SILC_SERVER && 
2436       !server->standalone) {
2437     SilcBuffer tmpbuf;
2438     SilcUInt16 old_ident;
2439     
2440     old_ident = silc_command_get_ident(cmd->payload);
2441     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2442     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2443     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2444                             SILC_PACKET_COMMAND, cmd->packet->flags,
2445                             tmpbuf->data, tmpbuf->len, TRUE);
2446
2447     /* Reprocess this packet after received reply from router */
2448     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2449                                 silc_command_get_ident(cmd->payload),
2450                                 silc_server_command_list, 
2451                                 silc_server_command_dup(cmd));
2452     cmd->pending = TRUE;
2453     silc_command_set_ident(cmd->payload, old_ident);
2454     silc_buffer_free(tmpbuf);
2455     goto out;
2456   }
2457
2458   /* Get Channel ID */
2459   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2460   if (tmp) {
2461     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2462     if (!channel_id) {
2463       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2464                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2465       goto out;
2466     }
2467   }
2468
2469   /* Get the channels from local list */
2470   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2471                                        &lch_count);
2472   
2473   /* Get the channels from global list */
2474   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2475                                        &gch_count);
2476
2477   /* Send the reply */
2478   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2479                                       gchannels, gch_count);
2480
2481   silc_free(lchannels);
2482   silc_free(gchannels);
2483
2484  out:
2485   silc_server_command_free(cmd);
2486 }
2487
2488 /* Server side of TOPIC command. Sets topic for channel and/or returns
2489    current topic to client. */
2490
2491 SILC_SERVER_CMD_FUNC(topic)
2492 {
2493   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2494   SilcServer server = cmd->server;
2495   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2496   SilcChannelID *channel_id;
2497   SilcChannelEntry channel;
2498   SilcChannelClientEntry chl;
2499   SilcBuffer packet, idp;
2500   unsigned char *tmp;
2501   SilcUInt32 argc, tmp_len;
2502   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2503
2504   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2505     goto out;
2506
2507   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2508
2509   argc = silc_argument_get_arg_num(cmd->args);
2510
2511   /* Get Channel ID */
2512   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2513   if (!tmp) {
2514     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2515                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2516     goto out;
2517   }
2518   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2519   if (!channel_id) {
2520     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2521                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2522     goto out;
2523   }
2524
2525   /* Check whether the channel exists */
2526   channel = silc_idlist_find_channel_by_id(server->local_list, 
2527                                            channel_id, NULL);
2528   if (!channel) {
2529     channel = silc_idlist_find_channel_by_id(server->global_list, 
2530                                              channel_id, NULL);
2531     if (!channel) {
2532       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2533                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2534                                             0);
2535       goto out;
2536     }
2537   }
2538
2539   if (argc > 1) {
2540     /* Get the topic */
2541     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2542     if (!tmp) {
2543       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2544                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2545                                             0);
2546       goto out;
2547     }
2548
2549     if (strlen(tmp) > 256) {
2550       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2551                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2552                                             0);
2553       goto out;
2554     }
2555
2556     /* See whether the client is on channel and has rights to change topic */
2557     if (!silc_server_client_on_channel(client, channel, &chl)) {
2558       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2559                                             SILC_STATUS_ERR_NOT_ON_CHANNEL,
2560                                             0);
2561       goto out;
2562     }
2563
2564     if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2565         !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2566         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2567       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2568                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2569                                             0);
2570       goto out;
2571     }
2572
2573     if (!channel->topic || strcmp(channel->topic, tmp)) {
2574       /* Set the topic for channel */
2575       silc_free(channel->topic);
2576       channel->topic = strdup(tmp);
2577
2578       /* Send TOPIC_SET notify type to the network */
2579       silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2580                                         SILC_BROADCAST(server), channel,
2581                                         client->id, SILC_ID_CLIENT,
2582                                         channel->topic);
2583
2584       /* Send notify about topic change to all clients on the channel */
2585       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2586       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2587                                          SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2588                                          idp->data, idp->len,
2589                                          channel->topic,
2590                                          strlen(channel->topic));
2591       silc_buffer_free(idp);
2592     }
2593   }
2594
2595   /* Send the topic to client as reply packet */
2596   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2597   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2598                                                 SILC_STATUS_OK, 0, ident, 2, 
2599                                                 2, idp->data, idp->len,
2600                                                 3, channel->topic, 
2601                                                 channel->topic ? 
2602                                                 strlen(channel->topic) : 0);
2603   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2604                           0, packet->data, packet->len, FALSE);
2605
2606   silc_buffer_free(packet);
2607   silc_buffer_free(idp);
2608   silc_free(channel_id);
2609
2610  out:
2611   silc_server_command_free(cmd);
2612 }
2613
2614 /* Server side of INVITE command. Invites some client to join some channel. 
2615    This command is also used to manage the invite list of the channel. */
2616
2617 SILC_SERVER_CMD_FUNC(invite)
2618 {
2619   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2620   SilcServer server = cmd->server;
2621   SilcSocketConnection sock = cmd->sock, dest_sock;
2622   SilcChannelClientEntry chl;
2623   SilcClientEntry sender, dest;
2624   SilcClientID *dest_id = NULL;
2625   SilcChannelEntry channel;
2626   SilcChannelID *channel_id = NULL;
2627   SilcIDListData idata;
2628   SilcBuffer idp, idp2, packet;
2629   unsigned char *tmp, *add, *del;
2630   SilcUInt32 len;
2631   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2632
2633   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2634
2635   /* Get Channel ID */
2636   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2637   if (!tmp) {
2638     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2639                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2640     goto out;
2641   }
2642   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2643   if (!channel_id) {
2644     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2645                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2646     goto out;
2647   }
2648
2649   /* Get the channel entry */
2650   channel = silc_idlist_find_channel_by_id(server->local_list, 
2651                                            channel_id, NULL);
2652   if (!channel) {
2653     channel = silc_idlist_find_channel_by_id(server->global_list, 
2654                                              channel_id, NULL);
2655     if (!channel) {
2656       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2657                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2658                                             0);
2659       goto out;
2660     }
2661   }
2662
2663   /* Check whether the sender of this command is on the channel. */
2664   sender = (SilcClientEntry)sock->user_data;
2665   if (!sender || !silc_server_client_on_channel(sender, channel, &chl)) {
2666     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2667                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2668     goto out;
2669   }
2670
2671   /* Check whether the channel is invite-only channel. If yes then the
2672      sender of this command must be at least channel operator. */
2673   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2674       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2675       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2676     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2677                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2678                                           0);
2679     goto out;
2680   }
2681
2682   /* Get destination client ID */
2683   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2684   if (tmp) {
2685     char invite[512];
2686     bool resolve;
2687
2688     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2689     if (!dest_id) {
2690       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2691                                             SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2692       goto out;
2693     }
2694
2695     /* Get the client entry */
2696     dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2697     if (!dest) {
2698       if (server->server_type != SILC_SERVER || !resolve) {
2699         silc_server_command_send_status_reply(
2700                                         cmd, SILC_COMMAND_INVITE,
2701                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2702         goto out;
2703       }
2704       
2705       /* The client info is being resolved. Reprocess this packet after
2706          receiving the reply to the query. */
2707       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2708                                   server->cmd_ident,
2709                                   silc_server_command_invite, 
2710                                   silc_server_command_dup(cmd));
2711       cmd->pending = TRUE;
2712       silc_free(channel_id);
2713       silc_free(dest_id);
2714       goto out;
2715     }
2716
2717     /* Check whether the requested client is already on the channel. */
2718     if (silc_server_client_on_channel(dest, channel, NULL)) {
2719       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2720                                             SILC_STATUS_ERR_USER_ON_CHANNEL,
2721                                             0);
2722       goto out;
2723     }
2724     
2725     /* Get route to the client */
2726     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, 
2727                                              &idata, NULL);
2728     if (!dest_sock) {
2729       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2730                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2731                                             0);
2732       goto out;
2733     }
2734
2735     memset(invite, 0, sizeof(invite));
2736     strncat(invite, dest->nickname, strlen(dest->nickname));
2737     strncat(invite, "!", 1);
2738     strncat(invite, dest->username, strlen(dest->username));
2739     if (!strchr(dest->username, '@')) {
2740       strncat(invite, "@", 1);
2741       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2742     }
2743
2744     len = strlen(invite);
2745     if (!channel->invite_list)
2746       channel->invite_list = silc_calloc(len + 2, 
2747                                          sizeof(*channel->invite_list));
2748     else
2749       channel->invite_list = silc_realloc(channel->invite_list, 
2750                                           sizeof(*channel->invite_list) * 
2751                                           (len + 
2752                                            strlen(channel->invite_list) + 2));
2753     strncat(channel->invite_list, invite, len);
2754     strncat(channel->invite_list, ",", 1);
2755
2756     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2757       /* Send notify to the client that is invited to the channel */
2758       idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2759       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2760       silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2761                                    SILC_ID_CLIENT,
2762                                    SILC_NOTIFY_TYPE_INVITE, 3, 
2763                                    idp->data, idp->len, 
2764                                    channel->channel_name, 
2765                                    strlen(channel->channel_name),
2766                                    idp2->data, idp2->len);
2767       silc_buffer_free(idp);
2768       silc_buffer_free(idp2);
2769     }
2770   }
2771
2772   /* Add the client to the invite list of the channel */
2773   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2774   if (add) {
2775     if (!channel->invite_list)
2776       channel->invite_list = silc_calloc(len + 2, 
2777                                          sizeof(*channel->invite_list));
2778     else
2779       channel->invite_list = silc_realloc(channel->invite_list, 
2780                                           sizeof(*channel->invite_list) * 
2781                                           (len + 
2782                                            strlen(channel->invite_list) + 2));
2783     if (add[len - 1] == ',')
2784       add[len - 1] = '\0';
2785     
2786     strncat(channel->invite_list, add, len);
2787     strncat(channel->invite_list, ",", 1);
2788   }
2789
2790   /* Get the invite to be removed and remove it from the list */
2791   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2792   if (del && channel->invite_list) {
2793     char *start, *end, *n;
2794
2795     if (!strncmp(channel->invite_list, del, 
2796                  strlen(channel->invite_list) - 1)) {
2797       silc_free(channel->invite_list);
2798       channel->invite_list = NULL;
2799     } else {
2800       start = strstr(channel->invite_list, del);
2801       if (start && strlen(start) >= len) {
2802         end = start + len;
2803         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2804         strncat(n, channel->invite_list, start - channel->invite_list);
2805         strncat(n, end + 1, ((channel->invite_list + 
2806                               strlen(channel->invite_list)) - end) - 1);
2807         silc_free(channel->invite_list);
2808         channel->invite_list = n;
2809       }
2810     }
2811   }
2812
2813   /* Send notify to the primary router */
2814   silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2815                                  SILC_BROADCAST(server), channel,
2816                                  sender->id, add, del);
2817
2818   /* Send command reply */
2819   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2820
2821   if (add || del)
2822     packet = 
2823       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2824                                            SILC_STATUS_OK, 0, ident, 2,
2825                                            2, tmp, len,
2826                                            3, channel->invite_list,
2827                                            channel->invite_list ?
2828                                            strlen(channel->invite_list) : 0);
2829   else
2830     packet = 
2831       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2832                                            SILC_STATUS_OK, 0, ident, 1,
2833                                            2, tmp, len);
2834   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2835                           packet->data, packet->len, FALSE);
2836   silc_buffer_free(packet);
2837
2838  out:
2839   silc_free(dest_id);
2840   silc_free(channel_id);
2841   silc_server_command_free(cmd);
2842 }
2843
2844 typedef struct {
2845   SilcSocketConnection sock;
2846   char *signoff;
2847 } *QuitInternal;
2848
2849 /* Quits connection to client. This gets called if client won't
2850    close the connection even when it has issued QUIT command. */
2851
2852 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2853 {
2854   SilcServer server = app_context;
2855   QuitInternal q = (QuitInternal)context;
2856
2857   /* Free all client specific data, such as client entry and entires
2858      on channels this client may be on. */
2859   silc_server_free_client_data(server, q->sock, q->sock->user_data,
2860                                TRUE, q->signoff);
2861   q->sock->user_data = NULL;
2862
2863   /* Close the connection on our side */
2864   silc_server_close_connection(server, q->sock);
2865
2866   silc_socket_free(q->sock);
2867   silc_free(q->signoff);
2868   silc_free(q);
2869 }
2870
2871 /* Quits SILC session. This is the normal way to disconnect client. */
2872  
2873 SILC_SERVER_CMD_FUNC(quit)
2874 {
2875   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2876   SilcServer server = cmd->server;
2877   SilcSocketConnection sock = cmd->sock;
2878   QuitInternal q;
2879   unsigned char *tmp = NULL;
2880   SilcUInt32 len = 0;
2881
2882   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2883
2884   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2885     goto out;
2886
2887   /* Get message */
2888   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2889   if (len > 128)
2890     tmp = NULL;
2891
2892   q = silc_calloc(1, sizeof(*q));
2893   q->sock = silc_socket_dup(sock);
2894   q->signoff = tmp ? strdup(tmp) : NULL;
2895
2896   /* We quit the connection with little timeout */
2897   silc_schedule_task_add(server->schedule, sock->sock,
2898                          silc_server_command_quit_cb, (void *)q,
2899                          0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2900
2901  out:
2902   silc_server_command_free(cmd);
2903 }
2904
2905 /* Server side of command KILL. This command is used by router operator
2906    to remove an client from the SILC Network temporarily. */
2907
2908 SILC_SERVER_CMD_FUNC(kill)
2909 {
2910   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2911   SilcServer server = cmd->server;
2912   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2913   SilcClientEntry remote_client;
2914   SilcClientID *client_id;
2915   unsigned char *tmp, *comment;
2916   SilcUInt32 tmp_len, tmp_len2;
2917   bool local;
2918
2919   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2920
2921   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
2922     goto out;
2923
2924   /* KILL command works only on router */
2925   if (server->server_type != SILC_ROUTER) {
2926     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2927                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2928     goto out;
2929   }
2930
2931   /* Check whether client has the permissions. */
2932   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2933     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2934                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2935     goto out;
2936   }
2937
2938   /* Get the client ID */
2939   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2940   if (!tmp) {
2941     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2942                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2943                                           0);
2944     goto out;
2945   }
2946   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2947   if (!client_id) {
2948     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2949                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2950                                           0);
2951     goto out;
2952   }
2953
2954   /* Get the client entry */
2955   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2956                                                 client_id, TRUE, NULL);
2957   local = TRUE;
2958   if (!remote_client) {
2959     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2960                                                   client_id, TRUE, NULL);
2961     local = FALSE;
2962     if (!remote_client) {
2963       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2964                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2965                                             0);
2966       goto out;
2967     }
2968   }
2969
2970   /* Get comment */
2971   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2972   if (tmp_len2 > 128)
2973     tmp_len2 = 128;
2974
2975   /* Send reply to the sender */
2976   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2977                                         SILC_STATUS_OK, 0);
2978
2979   /* Check if anyone is watching this nickname */
2980   if (server->server_type == SILC_ROUTER)
2981     silc_server_check_watcher_list(server, client, NULL,
2982                                    SILC_NOTIFY_TYPE_KILLED);
2983
2984   /* Now do the killing */
2985   silc_server_kill_client(server, remote_client, comment, client->id,
2986                           SILC_ID_CLIENT);
2987
2988  out:
2989   silc_server_command_free(cmd);
2990 }
2991
2992 /* Server side of command INFO. This sends information about us to 
2993    the client. If client requested specific server we will send the 
2994    command to that server. */
2995
2996 SILC_SERVER_CMD_FUNC(info)
2997 {
2998   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2999   SilcServer server = cmd->server;
3000   SilcBuffer packet, idp;
3001   unsigned char *tmp;
3002   SilcUInt32 tmp_len;
3003   char *dest_server, *server_info = NULL, *server_name;
3004   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3005   SilcServerEntry entry = NULL;
3006   SilcServerID *server_id = NULL;
3007
3008   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
3009
3010   /* Get server name */
3011   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3012
3013   /* Get Server ID */
3014   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3015   if (tmp) {
3016     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3017     if (!server_id) {
3018       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3019                                             SILC_STATUS_ERR_NO_SERVER_ID, 0);
3020       goto out;
3021     }
3022   }
3023
3024   if (server_id) {
3025     /* Check whether we have this server cached */
3026     entry = silc_idlist_find_server_by_id(server->local_list,
3027                                           server_id, TRUE, NULL);
3028     if (!entry) {
3029       entry = silc_idlist_find_server_by_id(server->global_list,
3030                                             server_id, TRUE, NULL);
3031       if (!entry && server->server_type != SILC_SERVER) {
3032         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3033                                               SILC_STATUS_ERR_NO_SUCH_SERVER,
3034                                               0);
3035         goto out;
3036       }
3037     }
3038   }
3039
3040   /* Some buggy servers has sent request to router about themselves. */
3041   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
3042     goto out;
3043
3044   if ((!dest_server && !server_id && !entry) || (entry && 
3045                                                  entry == server->id_entry) ||
3046       (dest_server && !cmd->pending && 
3047        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
3048     /* Send our reply */
3049     char info_string[256];
3050
3051     memset(info_string, 0, sizeof(info_string));
3052     snprintf(info_string, sizeof(info_string), 
3053              "location: %s server: %s admin: %s <%s>",
3054              server->config->server_info->location,
3055              server->config->server_info->server_type,
3056              server->config->server_info->admin,
3057              server->config->server_info->email);
3058
3059     server_info = info_string;
3060     entry = server->id_entry;
3061   } else {
3062     /* Check whether we have this server cached */
3063     if (!entry && dest_server) {
3064       entry = silc_idlist_find_server_by_name(server->global_list,
3065                                               dest_server, TRUE, NULL);
3066       if (!entry) {
3067         entry = silc_idlist_find_server_by_name(server->local_list,
3068                                                 dest_server, TRUE, NULL);
3069       }
3070     }
3071
3072     if (!cmd->pending &&
3073         server->server_type != SILC_SERVER && entry && !entry->server_info) {
3074       /* Send to the server */
3075       SilcBuffer tmpbuf;
3076       SilcUInt16 old_ident;
3077
3078       old_ident = silc_command_get_ident(cmd->payload);
3079       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3080       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3081
3082       silc_server_packet_send(server, entry->connection,
3083                               SILC_PACKET_COMMAND, cmd->packet->flags,
3084                               tmpbuf->data, tmpbuf->len, TRUE);
3085
3086       /* Reprocess this packet after received reply from router */
3087       silc_server_command_pending(server, SILC_COMMAND_INFO, 
3088                                   silc_command_get_ident(cmd->payload),
3089                                   silc_server_command_info,
3090                                   silc_server_command_dup(cmd));
3091       cmd->pending = TRUE;
3092       silc_command_set_ident(cmd->payload, old_ident);
3093       silc_buffer_free(tmpbuf);
3094       goto out;
3095     }
3096
3097     if (!entry && !cmd->pending && !server->standalone) {
3098       /* Send to the primary router */
3099       SilcBuffer tmpbuf;
3100       SilcUInt16 old_ident;
3101
3102       old_ident = silc_command_get_ident(cmd->payload);
3103       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3104       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3105
3106       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3107                               SILC_PACKET_COMMAND, cmd->packet->flags,
3108                               tmpbuf->data, tmpbuf->len, TRUE);
3109
3110       /* Reprocess this packet after received reply from router */
3111       silc_server_command_pending(server, SILC_COMMAND_INFO, 
3112                                   silc_command_get_ident(cmd->payload),
3113                                   silc_server_command_info,
3114                                   silc_server_command_dup(cmd));
3115       cmd->pending = TRUE;
3116       silc_command_set_ident(cmd->payload, old_ident);
3117       silc_buffer_free(tmpbuf);
3118       goto out;
3119     }
3120   }
3121
3122   silc_free(server_id);
3123
3124   if (!entry) {
3125     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3126                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3127     goto out;
3128   }
3129
3130   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3131   if (!server_info)
3132     server_info = entry->server_info;
3133   server_name = entry->server_name;
3134
3135   /* Send the reply */
3136   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3137                                                 SILC_STATUS_OK, 0, ident, 3,
3138                                                 2, idp->data, idp->len,
3139                                                 3, server_name, 
3140                                                 strlen(server_name),
3141                                                 4, server_info, 
3142                                                 server_info ? 
3143                                                 strlen(server_info) : 0);
3144   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3145                           packet->data, packet->len, FALSE);
3146     
3147   silc_buffer_free(packet);
3148   silc_buffer_free(idp);
3149
3150  out:
3151   silc_server_command_free(cmd);
3152 }
3153
3154 /* Server side of command PING. This just replies to the ping. */
3155
3156 SILC_SERVER_CMD_FUNC(ping)
3157 {
3158   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3159   SilcServer server = cmd->server;
3160   SilcServerID *id;
3161   SilcUInt32 len;
3162   unsigned char *tmp;
3163
3164   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3165
3166   /* Get Server ID */
3167   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3168   if (!tmp) {
3169     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3170                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
3171     goto out;
3172   }
3173   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3174   if (!id)
3175     goto out;
3176
3177   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3178     /* Send our reply */
3179     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3180                                           SILC_STATUS_OK, 0);
3181   } else {
3182     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3183                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3184     goto out;
3185   }
3186
3187   silc_free(id);
3188
3189  out:
3190   silc_server_command_free(cmd);
3191 }
3192
3193 /* Server side of command STATS. */
3194
3195 SILC_SERVER_CMD_FUNC(stats)
3196 {
3197   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3198   SilcServer server = cmd->server;
3199   SilcServerID *server_id;
3200   unsigned char *tmp;
3201   SilcUInt32 tmp_len;
3202   SilcBuffer packet, stats;
3203   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3204   SilcUInt32 uptime;
3205
3206   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3207
3208   /* Get Server ID */
3209   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3210   if (!tmp) {
3211     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3212                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
3213     goto out;
3214   }
3215   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3216   if (!server_id)
3217     goto out;
3218
3219   /* The ID must be ours */
3220   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3221     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3222                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3223     silc_free(server_id);
3224     goto out;
3225   }
3226   silc_free(server_id);
3227
3228   /* If we are router then just send everything we got. If we are normal
3229      server then we'll send this to our router to get all the latest
3230      statistical information. */
3231   if (!cmd->pending && server->server_type != SILC_ROUTER && 
3232       !server->standalone) {
3233     /* Send request to our router */
3234     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
3235                                             SILC_ID_SERVER);
3236     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
3237                                             ++server->cmd_ident, 1,
3238                                             1, idp->data, idp->len);
3239     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3240                             SILC_PACKET_COMMAND, 0, packet->data,
3241                             packet->len, FALSE);
3242
3243     /* Reprocess this packet after received reply from router */
3244     silc_server_command_pending(server, SILC_COMMAND_STATS, 
3245                                 server->cmd_ident,
3246                                 silc_server_command_stats,
3247                                 silc_server_command_dup(cmd));
3248     cmd->pending = TRUE;
3249     silc_buffer_free(packet);
3250     silc_buffer_free(idp);
3251     goto out;
3252   }
3253
3254   /* Send our reply to sender */
3255   uptime = time(NULL) - server->starttime;
3256
3257   stats = silc_buffer_alloc_size(60);
3258   silc_buffer_format(stats,
3259                      SILC_STR_UI_INT(server->starttime),
3260                      SILC_STR_UI_INT(uptime),
3261                      SILC_STR_UI_INT(server->stat.my_clients),
3262                      SILC_STR_UI_INT(server->stat.my_channels),
3263                      SILC_STR_UI_INT(server->stat.my_server_ops),
3264                      SILC_STR_UI_INT(server->stat.my_router_ops),
3265                      SILC_STR_UI_INT(server->stat.cell_clients),
3266                      SILC_STR_UI_INT(server->stat.cell_channels),
3267                      SILC_STR_UI_INT(server->stat.cell_servers),
3268                      SILC_STR_UI_INT(server->stat.clients),
3269                      SILC_STR_UI_INT(server->stat.channels),
3270                      SILC_STR_UI_INT(server->stat.servers),
3271                      SILC_STR_UI_INT(server->stat.routers),
3272                      SILC_STR_UI_INT(server->stat.server_ops),
3273                      SILC_STR_UI_INT(server->stat.router_ops),
3274                      SILC_STR_END);
3275
3276   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
3277                                                 SILC_STATUS_OK, 0, ident, 2,
3278                                                 2, tmp, tmp_len,
3279                                                 3, stats->data, stats->len);
3280   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3281                           0, packet->data, packet->len, FALSE);
3282   silc_buffer_free(packet);
3283   silc_buffer_free(stats);
3284
3285  out:
3286   silc_server_command_free(cmd);
3287 }
3288
3289 /* Internal routine to join channel. The channel sent to this function
3290    has been either created or resolved from ID lists. This joins the sent
3291    client to the channel. */
3292
3293 static void silc_server_command_join_channel(SilcServer server, 
3294                                              SilcServerCommandContext cmd,
3295                                              SilcChannelEntry channel,
3296                                              SilcClientID *client_id,
3297                                              bool created,
3298                                              bool create_key,
3299                                              SilcUInt32 umode,
3300                                              const unsigned char *auth,
3301                                              SilcUInt32 auth_len)
3302 {
3303   SilcSocketConnection sock = cmd->sock;
3304   unsigned char *tmp;
3305   SilcUInt32 tmp_len, user_count;
3306   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3307   SilcClientEntry client;
3308   SilcChannelClientEntry chl;
3309   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3310   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3311   char check[512], check2[512];
3312   bool founder = FALSE;
3313   bool resolve;
3314   unsigned char *fkey = NULL;
3315   SilcUInt32 fkey_len = 0;
3316
3317   SILC_LOG_DEBUG(("Joining client to channel"));
3318
3319   if (!channel)
3320     return;
3321
3322   /* Get the client entry */
3323   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3324     client = (SilcClientEntry)sock->user_data;
3325     if (!client)
3326       return;
3327   } else {
3328     client = silc_server_get_client_resolve(server, client_id, FALSE, 
3329                                             &resolve);
3330     if (!client) {
3331       if (cmd->pending)
3332         goto out;
3333
3334       if (!resolve) {
3335         silc_server_command_send_status_reply(
3336                                          cmd, SILC_COMMAND_JOIN,
3337                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3338         goto out;
3339       }
3340
3341       /* The client info is being resolved. Reprocess this packet after
3342          receiving the reply to the query. */
3343       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3344                                   server->cmd_ident,
3345                                   silc_server_command_join, 
3346                                   silc_server_command_dup(cmd));
3347       cmd->pending = TRUE;
3348       goto out;
3349     }
3350
3351     cmd->pending = FALSE;
3352   }
3353
3354   /*
3355    * Check founder auth payload if provided.  If client can gain founder
3356    * privileges it can override various conditions on joining the channel,
3357    * and can have directly the founder mode set on the channel.
3358    */
3359   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3360     SilcIDListData idata = (SilcIDListData)client;
3361     SilcChannelClientEntry chl2;
3362     SilcHashTableList htl;
3363
3364     if (channel->founder_key && idata->public_key &&
3365         silc_pkcs_public_key_compare(channel->founder_key, 
3366                                      idata->public_key)) {
3367       /* Check whether the client is to become founder */
3368       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3369                                 channel->founder_key, 0, server->sha1hash,
3370                                 client->id, SILC_ID_CLIENT)) {
3371
3372         /* There cannot be anyone else as founder on the channel now.  This
3373            client is definitely the founder due to this authentication */
3374         silc_hash_table_list(channel->user_list, &htl);
3375         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3376           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3377             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3378             silc_server_force_cumode_change(server, NULL, channel, chl2,
3379                                             chl2->mode);
3380             break;
3381           }
3382         silc_hash_table_list_reset(&htl);
3383
3384         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3385         founder = TRUE;
3386       }
3387     }
3388   }
3389
3390   /*
3391    * Check channel modes
3392    */
3393
3394   if (!umode) {
3395     memset(check, 0, sizeof(check));
3396     memset(check2, 0, sizeof(check2));
3397     strncat(check, client->nickname, strlen(client->nickname));
3398     strncat(check, "!", 1);
3399     strncat(check, client->username, strlen(client->username));
3400     if (!strchr(client->username, '@')) {
3401       strncat(check, "@", 1);
3402       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3403     }
3404
3405     strncat(check2, client->nickname, strlen(client->nickname));
3406     if (!strchr(client->nickname, '@')) {
3407       strncat(check2, "@", 1);
3408       strncat(check2, server->server_name, strlen(server->server_name));
3409     }
3410     strncat(check2, "!", 1);
3411     strncat(check2, client->username, strlen(client->username));
3412     if (!strchr(client->username, '@')) {
3413       strncat(check2, "@", 1);
3414       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3415     }
3416     
3417     /* Check invite list if channel is invite-only channel */
3418     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3419       if (!channel->invite_list ||
3420           (!silc_string_match(channel->invite_list, check) &&
3421            !silc_string_match(channel->invite_list, check2))) {
3422         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3423                                               SILC_STATUS_ERR_NOT_INVITED, 0);
3424         goto out;
3425       }
3426     }
3427
3428     /* Check ban list if it exists. If the client's nickname, server,
3429        username and/or hostname is in the ban list the access to the
3430        channel is denied. */
3431     if (channel->ban_list) {
3432       if (silc_string_match(channel->ban_list, check) ||
3433           silc_string_match(channel->ban_list, check2)) {
3434         silc_server_command_send_status_reply(
3435                                       cmd, SILC_COMMAND_JOIN,
3436                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3437         goto out;
3438       }
3439     }
3440     
3441     /* Check user count limit if set. */
3442     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3443       if (silc_hash_table_count(channel->user_list) + 1 > 
3444           channel->user_limit) {
3445         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3446                                               SILC_STATUS_ERR_CHANNEL_IS_FULL,
3447                                               0);
3448         goto out;
3449       }
3450     }
3451   }
3452
3453   /* Check the channel passphrase if set. */
3454   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3455     /* Get passphrase */
3456     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3457     if (tmp)
3458       passphrase = silc_memdup(tmp, tmp_len);
3459   
3460     if (!passphrase || !channel->passphrase ||
3461         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3462       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3463                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
3464       goto out;
3465     }
3466   }
3467
3468   /*
3469    * Client is allowed to join to the channel. Make it happen.
3470    */
3471
3472   /* Check whether the client already is on the channel */
3473   if (silc_server_client_on_channel(client, channel, NULL)) {
3474     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3475                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3476     goto out;
3477   }
3478
3479   /* Generate new channel key as protocol dictates */
3480   if (create_key) {
3481     if (!silc_server_create_channel_key(server, channel, 0))
3482       goto out;
3483
3484     /* Send the channel key. This is broadcasted to the channel but is not
3485        sent to the client who is joining to the channel. */
3486     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3487       silc_server_send_channel_key(server, NULL, channel, 
3488                                    server->server_type == SILC_ROUTER ? 
3489                                    FALSE : !server->standalone);
3490   }
3491
3492   /* Join the client to the channel by adding it to channel's user list.
3493      Add also the channel to client entry's channels list for fast cross-
3494      referencing. */
3495   chl = silc_calloc(1, sizeof(*chl));
3496   chl->mode = umode;
3497   chl->client = client;
3498   chl->channel = channel;
3499   silc_hash_table_add(channel->user_list, client, chl);
3500   silc_hash_table_add(client->channels, channel, chl);
3501   channel->user_count++;
3502   channel->disabled = FALSE;
3503
3504   /* Get users on the channel */
3505   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3506                                    &user_count);
3507
3508   /* Encode Client ID Payload of the original client who wants to join */
3509   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3510
3511   /* Encode command reply packet */
3512   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3513   SILC_PUT32_MSB(channel->mode, mode);
3514   SILC_PUT32_MSB(created, tmp2);
3515   SILC_PUT32_MSB(user_count, tmp3);
3516
3517   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3518     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3519     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3520                                                            SILC_ID_CHANNEL), 
3521                                            tmp,
3522                                            strlen(channel->channel_key->
3523                                                   cipher->name),
3524                                            channel->channel_key->cipher->name,
3525                                            channel->key_len / 8, channel->key);
3526     silc_free(tmp);
3527   }
3528
3529   if (channel->founder_key)
3530     fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3531
3532   reply = 
3533     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3534                                          SILC_STATUS_OK, 0, ident, 14,
3535                                          2, channel->channel_name,
3536                                          strlen(channel->channel_name),
3537                                          3, chidp->data, chidp->len,
3538                                          4, clidp->data, clidp->len,
3539                                          5, mode, 4,
3540                                          6, tmp2, 4,
3541                                          7, keyp ? keyp->data : NULL, 
3542                                          keyp ? keyp->len : 0,
3543                                          8, channel->ban_list, 
3544                                          channel->ban_list ?
3545                                          strlen(channel->ban_list) : 0,
3546                                          9, channel->invite_list,
3547                                          channel->invite_list ?
3548                                          strlen(channel->invite_list) : 0,
3549                                          10, channel->topic,
3550                                          channel->topic ?
3551                                          strlen(channel->topic) : 0,
3552                                          11, silc_hmac_get_name(channel->hmac),
3553                                          strlen(silc_hmac_get_name(channel->
3554                                                                    hmac)),
3555                                          12, tmp3, 4,
3556                                          13, user_list->data, user_list->len,
3557                                          14, mode_list->data, 
3558                                          mode_list->len,
3559                                          15, fkey, fkey_len);
3560
3561   /* Send command reply */
3562   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3563                           reply->data, reply->len, FALSE);
3564
3565   /* Send JOIN notify to locally connected clients on the channel. If
3566      we are normal server then router will send or have sent JOIN notify
3567      already. However since we've added the client already to our channel
3568      we'll ignore it (in packet_receive.c) so we must send it here. If
3569      we are router then this will send it to local clients and local
3570      servers. */
3571   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3572   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3573                                      SILC_NOTIFY_TYPE_JOIN, 2,
3574                                      clidp->data, clidp->len,
3575                                      chidp->data, chidp->len);
3576
3577   /* Update statistics */
3578   server->stat.my_chanclients++;
3579   if (server->server_type == SILC_ROUTER) {
3580     server->stat.cell_chanclients++;
3581     server->stat.chanclients++;
3582   }
3583
3584   if (!cmd->pending) {
3585     /* Send JOIN notify packet to our primary router */
3586     silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3587                                  SILC_BROADCAST(server), channel, client->id);
3588
3589     if (keyp)
3590       /* Distribute the channel key to all backup routers. */
3591       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3592                               keyp->data, keyp->len, FALSE, TRUE);
3593
3594     /* If client became founder by providing correct founder auth data
3595        notify the mode change to the channel. */
3596     if (founder) {
3597       SILC_PUT32_MSB(chl->mode, mode);
3598       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3599       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3600                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3601                                          clidp->data, clidp->len,
3602                                          mode, 4, clidp->data, clidp->len,
3603                                          fkey, fkey_len);
3604     }
3605   }
3606
3607   /* Set CUMODE notify type to network */
3608   if (founder)
3609     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3610                                    SILC_BROADCAST(server), channel,
3611                                    chl->mode, client->id, SILC_ID_CLIENT,
3612                                    client->id, channel->founder_key);
3613
3614   silc_buffer_free(reply);
3615   silc_buffer_free(clidp);
3616   silc_buffer_free(chidp);
3617   silc_buffer_free(keyp);
3618   silc_buffer_free(user_list);
3619   silc_buffer_free(mode_list);
3620   silc_free(fkey);
3621
3622  out:
3623   silc_free(passphrase);
3624 }
3625
3626 /* Server side of command JOIN. Joins client into requested channel. If 
3627    the channel does not exist it will be created. */
3628
3629 SILC_SERVER_CMD_FUNC(join)
3630 {
3631   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3632   SilcServer server = cmd->server;
3633   unsigned char *auth;
3634   SilcUInt32 tmp_len, auth_len;
3635   char *tmp, *channel_name = NULL, *cipher, *hmac;
3636   SilcChannelEntry channel;
3637   SilcUInt32 umode = 0;
3638   bool created = FALSE, create_key = TRUE;
3639   SilcClientID *client_id;
3640
3641   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3642
3643   /* Get channel name */
3644   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3645   if (!tmp) {
3646     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3647                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3648                                           0);
3649     goto out;
3650   }
3651   channel_name = tmp;
3652
3653   if (tmp_len > 256)
3654     channel_name[255] = '\0';
3655
3656   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3657     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3658                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
3659     goto out;
3660   }
3661
3662   /* Get Client ID of the client who is joining to the channel */
3663   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3664   if (!tmp) {
3665     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3666                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3667                                           0);
3668     goto out;
3669   }
3670   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3671   if (!client_id) {
3672     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3673                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3674                                           0);
3675     goto out;
3676   }
3677
3678   /* Get cipher, hmac name and auth payload */
3679   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3680   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3681   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3682
3683   /* See if the channel exists */
3684   channel = silc_idlist_find_channel_by_name(server->local_list, 
3685                                              channel_name, NULL);
3686
3687   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3688     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3689     if (!entry) {
3690       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3691                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3692                                             0);
3693       goto out;
3694     }
3695
3696     silc_free(client_id);
3697     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3698
3699     if (!channel || 
3700         (channel->disabled && server->server_type != SILC_ROUTER)) {
3701       /* Channel not found or not valid */
3702
3703       /* If we are standalone server we don't have a router, we just create 
3704          the channel by ourselves (unless it existed). */
3705       if (server->standalone) {
3706         if (!channel) {
3707           channel = silc_server_create_new_channel(server, server->id, cipher, 
3708                                                    hmac, channel_name, TRUE);
3709           if (!channel) {
3710             silc_server_command_send_status_reply(
3711                                   cmd, SILC_COMMAND_JOIN,
3712                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3713                                   0);
3714             silc_free(client_id);
3715             goto out;
3716           }
3717         
3718           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3719           created = TRUE;
3720           create_key = FALSE;
3721         }
3722       } else {
3723
3724         /* The channel does not exist on our server. If we are normal server 
3725            we will send JOIN command to our router which will handle the
3726            joining procedure (either creates the channel if it doesn't exist 
3727            or joins the client to it). */
3728         if (server->server_type != SILC_ROUTER) {
3729           SilcBuffer tmpbuf;
3730           SilcUInt16 old_ident;
3731
3732           /* If this is pending command callback then we've resolved
3733              it and it didn't work, return since we've notified the
3734              client already in the command reply callback. */
3735           if (cmd->pending) {
3736             silc_free(client_id);
3737             goto out;
3738           }
3739           
3740           old_ident = silc_command_get_ident(cmd->payload);
3741           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3742           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3743           
3744           /* Send JOIN command to our router */
3745           silc_server_packet_send(server, (SilcSocketConnection)
3746                                   SILC_PRIMARY_ROUTE(server),
3747                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3748                                   tmpbuf->data, tmpbuf->len, TRUE);
3749           
3750           /* Reprocess this packet after received reply from router */
3751           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3752                                       silc_command_get_ident(cmd->payload),
3753                                       silc_server_command_join,
3754                                       silc_server_command_dup(cmd));
3755           cmd->pending = TRUE;
3756           silc_command_set_ident(cmd->payload, old_ident);
3757           silc_buffer_free(tmpbuf);
3758           silc_free(client_id);
3759           goto out;
3760         }
3761         
3762         /* We are router and the channel does not seem exist so we will check
3763            our global list as well for the channel. */
3764         channel = silc_idlist_find_channel_by_name(server->global_list, 
3765                                                    channel_name, NULL);
3766         if (!channel) {
3767           /* Channel really does not exist, create it */
3768           channel = silc_server_create_new_channel(server, server->id, cipher, 
3769                                                    hmac, channel_name, TRUE);
3770           if (!channel) {
3771             silc_server_command_send_status_reply(
3772                                        cmd, SILC_COMMAND_JOIN,
3773                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3774             silc_free(client_id);
3775             goto out;
3776           }
3777
3778           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3779           created = TRUE;
3780           create_key = FALSE;
3781         }
3782       }
3783     }
3784   } else {
3785     if (!channel) {
3786       /* Channel not found */
3787
3788       /* If the command came from router and we are normal server then
3789          something went wrong with the joining as the channel was not found.
3790          We can't do anything else but ignore this. */
3791       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3792           server->server_type != SILC_ROUTER) {
3793         silc_free(client_id);
3794         goto out;
3795       }
3796       
3797       /* We are router and the channel does not seem exist so we will check
3798          our global list as well for the channel. */
3799       channel = silc_idlist_find_channel_by_name(server->global_list, 
3800                                                  channel_name, NULL);
3801       if (!channel) {
3802         /* Channel really does not exist, create it */
3803         channel = silc_server_create_new_channel(server, server->id, cipher, 
3804                                                  hmac, channel_name, TRUE);
3805         if (!channel) {
3806           silc_server_command_send_status_reply(
3807                                        cmd, SILC_COMMAND_JOIN,
3808                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3809           silc_free(client_id);
3810           goto out;
3811         }
3812
3813         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3814         created = TRUE;
3815         create_key = FALSE;
3816       }
3817     }
3818   }
3819
3820   /* Check whether the channel was created by our router */
3821   if (cmd->pending && context2) {
3822     SilcServerCommandReplyContext reply = context2;
3823
3824     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3825       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3826       SILC_GET32_MSB(created, tmp);
3827       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3828         create_key = FALSE;     /* Router returned the key already */
3829
3830       if (silc_command_get_status(reply->payload, NULL, NULL) &&
3831           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3832         /* Save channel passphrase, if user provided it successfully */
3833         unsigned char *pa;
3834         SilcUInt32 pa_len;
3835         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3836         if (pa) {
3837           silc_free(channel->passphrase);
3838           channel->passphrase = silc_memdup(pa, pa_len);
3839         }
3840       }
3841     }
3842
3843     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3844         !channel->disabled && !silc_hash_table_count(channel->user_list))
3845       created = TRUE;
3846   }
3847
3848   /* If the channel does not have global users and is also empty the client
3849      will be the channel founder and operator. */
3850   if (!channel->disabled &&
3851       !channel->global_users && !silc_hash_table_count(channel->user_list))
3852     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3853
3854   /* Join to the channel */
3855   silc_server_command_join_channel(server, cmd, channel, client_id,
3856                                    created, create_key, umode,
3857                                    auth, auth_len);
3858
3859   silc_free(client_id);
3860
3861  out:
3862   silc_server_command_free(cmd);
3863 }
3864
3865 /* Server side of command MOTD. Sends server's current "message of the
3866    day" to the client. */
3867
3868 SILC_SERVER_CMD_FUNC(motd)
3869 {
3870   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3871   SilcServer server = cmd->server;
3872   SilcBuffer packet, idp;
3873   char *motd, *dest_server;
3874   SilcUInt32 motd_len;
3875   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3876   
3877   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3878
3879   /* Get server name */
3880   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3881   if (!dest_server) {
3882     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3883                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3884     goto out;
3885   }
3886
3887   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3888     /* Send our MOTD */
3889
3890     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3891
3892     if (server->config && server->config->server_info &&
3893         server->config->server_info->motd_file) {
3894       /* Send motd */
3895       motd = silc_file_readfile(server->config->server_info->motd_file,
3896                                 &motd_len);
3897       if (!motd)
3898         goto out;
3899       
3900       motd[motd_len] = 0;
3901       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3902                                                     SILC_STATUS_OK, 0, 
3903                                                     ident, 2,
3904                                                     2, idp, idp->len,
3905                                                     3, motd, motd_len);
3906     } else {
3907       /* No motd */
3908       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3909                                                     SILC_STATUS_OK, 0, 
3910                                                     ident, 1,
3911                                                     2, idp, idp->len);
3912     }
3913
3914     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3915                             packet->data, packet->len, FALSE);
3916     silc_buffer_free(packet);
3917     silc_buffer_free(idp);
3918   } else {
3919     SilcServerEntry entry;
3920
3921     /* Check whether we have this server cached */
3922     entry = silc_idlist_find_server_by_name(server->global_list,
3923                                             dest_server, TRUE, NULL);
3924     if (!entry) {
3925       entry = silc_idlist_find_server_by_name(server->local_list,
3926                                               dest_server, TRUE, NULL);
3927     }
3928
3929     if (server->server_type != SILC_SERVER && !cmd->pending && 
3930         entry && !entry->motd) {
3931       /* Send to the server */
3932       SilcBuffer tmpbuf;
3933       SilcUInt16 old_ident;
3934
3935       old_ident = silc_command_get_ident(cmd->payload);
3936       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3937       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3938
3939       silc_server_packet_send(server, entry->connection,
3940                               SILC_PACKET_COMMAND, cmd->packet->flags,
3941                               tmpbuf->data, tmpbuf->len, TRUE);
3942
3943       /* Reprocess this packet after received reply from router */
3944       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3945                                   silc_command_get_ident(cmd->payload),
3946                                   silc_server_command_motd,
3947                                   silc_server_command_dup(cmd));
3948       cmd->pending = TRUE;
3949       silc_command_set_ident(cmd->payload, old_ident);
3950       silc_buffer_free(tmpbuf);
3951       goto out;
3952     }
3953
3954     if (!entry && !cmd->pending && !server->standalone) {
3955       /* Send to the primary router */
3956       SilcBuffer tmpbuf;
3957       SilcUInt16 old_ident;
3958
3959       old_ident = silc_command_get_ident(cmd->payload);
3960       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3961       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3962
3963       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3964                               SILC_PACKET_COMMAND, cmd->packet->flags,
3965                               tmpbuf->data, tmpbuf->len, TRUE);
3966
3967       /* Reprocess this packet after received reply from router */
3968       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3969                                   silc_command_get_ident(cmd->payload),
3970                                   silc_server_command_motd,
3971                                   silc_server_command_dup(cmd));
3972       cmd->pending = TRUE;
3973       silc_command_set_ident(cmd->payload, old_ident);
3974       silc_buffer_free(tmpbuf);
3975       goto out;
3976     }
3977
3978     if (!entry) {
3979       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3980                                             SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3981       goto out;
3982     }
3983
3984     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3985     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3986                                                   SILC_STATUS_OK, 0, ident, 2,
3987                                                   2, idp, idp->len,
3988                                                   3, entry->motd,
3989                                                   entry->motd ? 
3990                                                   strlen(entry->motd) : 0);
3991     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3992                             packet->data, packet->len, FALSE);
3993     silc_buffer_free(packet);
3994     silc_buffer_free(idp);
3995   }
3996
3997  out:
3998   silc_server_command_free(cmd);
3999 }
4000
4001 /* Server side of command UMODE. Client can use this command to set/unset
4002    user mode. Client actually cannot set itself to be as server/router
4003    operator so this can be used only to unset the modes. */
4004
4005 SILC_SERVER_CMD_FUNC(umode)
4006 {
4007   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4008   SilcServer server = cmd->server;
4009   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4010   SilcBuffer packet;
4011   unsigned char *tmp_mask, m[4];
4012   SilcUInt32 mask = 0;
4013   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4014   bool set_mask = FALSE;
4015
4016   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
4017     goto out;
4018
4019   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
4020
4021   /* Get the client's mode mask */
4022   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4023   if (tmp_mask) {
4024     SILC_GET32_MSB(mask, tmp_mask);
4025     set_mask = TRUE;
4026   }
4027
4028   if (set_mask) {
4029     /* Check that mode changing is allowed. */
4030     if (!silc_server_check_umode_rights(server, client, mask)) {
4031       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4032                                             SILC_STATUS_ERR_PERM_DENIED, 0);
4033       goto out;
4034     }
4035
4036     /* Anonymous mode cannot be set by client */
4037     if (mask & SILC_UMODE_ANONYMOUS) {
4038       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
4039         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4040                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4041         goto out;
4042       }
4043     } else {
4044       if (client->mode & SILC_UMODE_ANONYMOUS) {
4045         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
4046                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4047         goto out;
4048       }
4049     }
4050
4051     /* Update statistics */
4052     if (mask & SILC_UMODE_GONE) {
4053       if (!(client->mode & SILC_UMODE_GONE))
4054         server->stat.my_aways++;
4055     } else {
4056       if (client->mode & SILC_UMODE_GONE)
4057         server->stat.my_aways--;
4058     }
4059
4060     /* Change the mode */
4061     client->mode = mask;
4062
4063     /* Send UMODE change to primary router */
4064     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4065                                   SILC_BROADCAST(server), client->id,
4066                                   client->mode);
4067
4068     /* Check if anyone is watching this nickname */
4069     if (server->server_type == SILC_ROUTER)
4070       silc_server_check_watcher_list(server, client, NULL,
4071                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
4072   }
4073
4074   /* Send command reply to sender */
4075   SILC_PUT32_MSB(client->mode, m);
4076   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
4077                                                 SILC_STATUS_OK, 0, ident, 1,
4078                                                 2, m, sizeof(m));
4079   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4080                           packet->data, packet->len, FALSE);
4081   silc_buffer_free(packet);
4082
4083  out:
4084   silc_server_command_free(cmd);
4085 }
4086
4087 /* Server side command of CMODE. Changes channel mode */
4088
4089 SILC_SERVER_CMD_FUNC(cmode)
4090 {
4091   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4092   SilcServer server = cmd->server;
4093   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4094   SilcIDListData idata = (SilcIDListData)client;
4095   SilcChannelID *channel_id = NULL;
4096   SilcChannelEntry channel;
4097   SilcChannelClientEntry chl;
4098   SilcBuffer packet, cidp;
4099   unsigned char *tmp, *tmp_id, *tmp_mask;
4100   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
4101   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
4102   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4103   bool set_mask = FALSE;
4104   SilcPublicKey founder_key = NULL;
4105   unsigned char *fkey = NULL;
4106   SilcUInt32 fkey_len = 0;
4107
4108   if (!client) {
4109     silc_server_command_free(cmd);
4110     return;
4111   }
4112
4113   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
4114
4115   /* Get Channel ID */
4116   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
4117   if (!tmp_id) {
4118     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4119                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4120     silc_server_command_free(cmd);
4121     return;
4122   }
4123   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
4124   if (!channel_id) {
4125     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4126                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4127     silc_server_command_free(cmd);
4128     return;
4129   }
4130
4131   /* Get channel entry */
4132   channel = silc_idlist_find_channel_by_id(server->local_list, 
4133                                            channel_id, NULL);
4134   if (!channel) {
4135     channel = silc_idlist_find_channel_by_id(server->global_list, 
4136                                              channel_id, NULL);
4137     if (!channel) {
4138       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4139                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4140                                             0);
4141       silc_free(channel_id);
4142       silc_server_command_free(cmd);
4143       return;
4144     }
4145   }
4146   old_mask = channel->mode;
4147
4148   /* Get the channel mode mask */
4149   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4150   if (tmp_mask) {
4151     SILC_GET32_MSB(mode_mask, tmp_mask);
4152     set_mask = TRUE;
4153   }
4154
4155   /* Check whether this client is on the channel */
4156   if (!silc_server_client_on_channel(client, channel, &chl)) {
4157     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4158                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4159     goto out;
4160   }
4161
4162   /* Check that client has rights to change any requested channel modes */
4163   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
4164                                                   mode_mask)) {
4165     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4166     silc_server_command_send_status_reply(
4167                              cmd, SILC_COMMAND_CMODE,
4168                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
4169                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4170                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4171     goto out;
4172   }
4173
4174   /* If mode mask was not sent as argument then merely return the current
4175      mode mask to the sender. */
4176   if (!set_mask) {
4177     unsigned char m[4];
4178     SILC_PUT32_MSB(channel->mode, m);
4179     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4180                                                   SILC_STATUS_OK, 0, ident, 2,
4181                                                   2, tmp_id, tmp_len2,
4182                                                   3, m, sizeof(m));
4183     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4184                             packet->data, packet->len, FALSE);
4185     silc_buffer_free(packet);
4186     goto out;
4187   }
4188
4189   /*
4190    * Check the modes. Modes that requires nothing special operation are
4191    * not checked here.
4192    */
4193
4194   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4195     /* Channel uses private keys to protect traffic. Client(s) has set the
4196        key locally they want to use, server does not know that key. */
4197     /* Nothing interesting to do here */
4198   } else {
4199     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4200       /* The mode is removed and we need to generate and distribute
4201          new channel key. Clients are not using private channel keys
4202          anymore after this. */
4203       
4204       /* Re-generate channel key */
4205       if (!silc_server_create_channel_key(server, channel, 0))
4206         goto out;
4207         
4208       /* Send the channel key. This sends it to our local clients and if
4209          we are normal server to our router as well. */
4210       silc_server_send_channel_key(server, NULL, channel, 
4211                                    server->server_type == SILC_ROUTER ? 
4212                                    FALSE : !server->standalone);
4213         
4214       cipher = channel->channel_key->cipher->name;
4215       hmac = (char *)silc_hmac_get_name(channel->hmac);
4216     }
4217   }
4218
4219   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4220     /* User limit is set on channel */
4221     SilcUInt32 user_limit;
4222       
4223     /* Get user limit */
4224     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4225     if (!tmp) {
4226       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4227         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4228                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4229         goto out;
4230       }
4231     } else {
4232       SILC_GET32_MSB(user_limit, tmp);
4233       channel->user_limit = user_limit;
4234     }
4235   } else {
4236     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4237       /* User limit mode is unset. Remove user limit */
4238       channel->user_limit = 0;
4239   }
4240
4241   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4242     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4243       /* Passphrase has been set to channel */
4244       
4245       /* Get the passphrase */
4246       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4247       if (!tmp) {
4248         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4249                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4250         goto out;
4251       }
4252
4253       /* Save the passphrase */
4254       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4255     }
4256   } else {
4257     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4258       /* Passphrase mode is unset. remove the passphrase */
4259       silc_free(channel->passphrase);
4260       channel->passphrase = NULL;
4261     }
4262   }
4263
4264   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4265     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4266       /* Cipher to use protect the traffic */
4267       SilcCipher newkey, oldkey;
4268
4269       /* Get cipher */
4270       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4271       if (!cipher) {
4272         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4273                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4274         goto out;
4275       }
4276
4277       /* Delete old cipher and allocate the new one */
4278       if (!silc_cipher_alloc(cipher, &newkey)) {
4279         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4280                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4281         goto out;
4282       }
4283
4284       oldkey = channel->channel_key;
4285       channel->channel_key = newkey;
4286
4287       /* Re-generate channel key */
4288       if (!silc_server_create_channel_key(server, channel, 0)) {
4289         /* We don't have new key, revert to old one */
4290         channel->channel_key = oldkey;
4291         goto out;
4292       }
4293
4294       /* Remove old channel key for good */
4295       silc_cipher_free(oldkey);
4296
4297       /* Send the channel key. This sends it to our local clients and if
4298          we are normal server to our router as well. */
4299       silc_server_send_channel_key(server, NULL, channel, 
4300                                    server->server_type == SILC_ROUTER ? 
4301                                    FALSE : !server->standalone);
4302     }
4303   } else {
4304     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4305       /* Cipher mode is unset. Remove the cipher and revert back to 
4306          default cipher */
4307       SilcCipher newkey, oldkey;
4308       cipher = channel->cipher;
4309
4310       /* Delete old cipher and allocate default one */
4311       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4312         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4313                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4314         goto out;
4315       }
4316
4317       oldkey = channel->channel_key;
4318       channel->channel_key = newkey;
4319
4320       /* Re-generate channel key */
4321       if (!silc_server_create_channel_key(server, channel, 0)) {
4322         /* We don't have new key, revert to old one */
4323         channel->channel_key = oldkey;
4324         goto out;
4325       }
4326       
4327       /* Remove old channel key for good */
4328       silc_cipher_free(oldkey);
4329
4330       /* Send the channel key. This sends it to our local clients and if
4331          we are normal server to our router as well. */
4332       silc_server_send_channel_key(server, NULL, channel, 
4333                                    server->server_type == SILC_ROUTER ? 
4334                                    FALSE : !server->standalone);
4335     }
4336   }
4337
4338   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4339     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4340       /* HMAC to use protect the traffic */
4341       unsigned char hash[32];
4342       SilcHmac newhmac;
4343
4344       /* Get hmac */
4345       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4346       if (!hmac) {
4347         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4348                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4349         goto out;
4350       }
4351
4352       /* Delete old hmac and allocate the new one */
4353       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4354         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4355                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4356         goto out;
4357       }
4358
4359       silc_hmac_free(channel->hmac);
4360       channel->hmac = newhmac;
4361
4362       /* Set the HMAC key out of current channel key. The client must do
4363          this locally. */
4364       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4365                      channel->key_len / 8, hash);
4366       silc_hmac_set_key(channel->hmac, hash, 
4367                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4368       memset(hash, 0, sizeof(hash));
4369     }
4370   } else {
4371     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4372       /* Hmac mode is unset. Remove the hmac and revert back to 
4373          default hmac */
4374       SilcHmac newhmac;
4375       unsigned char hash[32];
4376       hmac = channel->hmac_name;
4377
4378       /* Delete old hmac and allocate default one */
4379       silc_hmac_free(channel->hmac);
4380       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4381         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4382                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4383         goto out;
4384       }
4385
4386       silc_hmac_free(channel->hmac);
4387       channel->hmac = newhmac;
4388
4389       /* Set the HMAC key out of current channel key. The client must do
4390          this locally. */
4391       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4392                      channel->key_len / 8, 
4393                      hash);
4394       silc_hmac_set_key(channel->hmac, hash, 
4395                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4396       memset(hash, 0, sizeof(hash));
4397     }
4398   }
4399
4400   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4401     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4402       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4403         /* Set the founder authentication */
4404         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4405         if (!tmp) {
4406           silc_server_command_send_status_reply(
4407                                      cmd, SILC_COMMAND_CMODE,
4408                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4409           goto out;
4410         }
4411
4412         /* Verify the payload before setting the mode */
4413         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
4414                                    idata->public_key, 0, server->sha1hash,
4415                                    client->id, SILC_ID_CLIENT)) {
4416           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4417                                                 SILC_STATUS_ERR_AUTH_FAILED,
4418                                                 0);
4419           goto out;
4420         }
4421
4422         /* Save the public key */
4423         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4424         if (!channel->founder_key) {
4425           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4426                                                 SILC_STATUS_ERR_AUTH_FAILED,
4427                                                 0);
4428           goto out;
4429         }
4430
4431         founder_key = channel->founder_key;
4432         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4433         if (!fkey) {
4434           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4435                                                 SILC_STATUS_ERR_AUTH_FAILED,
4436                                                 0);
4437           silc_pkcs_public_key_free(channel->founder_key);
4438           channel->founder_key = NULL;
4439           goto out;
4440         }
4441       }
4442     }
4443   } else {
4444     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4445       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4446         if (channel->founder_key)
4447           silc_pkcs_public_key_free(channel->founder_key);
4448         channel->founder_key = NULL;
4449       }
4450     }
4451   }
4452
4453   /* Finally, set the mode */
4454   old_mask = channel->mode = mode_mask;
4455
4456   /* Send CMODE_CHANGE notify. */
4457   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4458   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4459                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4460                                      cidp->data, cidp->len, 
4461                                      tmp_mask, 4,
4462                                      cipher, cipher ? strlen(cipher) : 0,
4463                                      hmac, hmac ? strlen(hmac) : 0,
4464                                      passphrase, passphrase ? 
4465                                      strlen(passphrase) : 0,
4466                                      fkey, fkey_len);
4467
4468   /* Set CMODE notify type to network */
4469   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4470                                 SILC_BROADCAST(server), channel,
4471                                 mode_mask, client->id, SILC_ID_CLIENT,
4472                                 cipher, hmac, passphrase, founder_key);
4473
4474   /* Send command reply to sender */
4475   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4476                                                 SILC_STATUS_OK, 0, ident, 2,
4477                                                 2, tmp_id, tmp_len2,
4478                                                 3, tmp_mask, 4);
4479   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4480                           packet->data, packet->len, FALSE);
4481
4482   silc_buffer_free(packet);
4483   silc_buffer_free(cidp);
4484
4485  out:
4486   channel->mode = old_mask;
4487   silc_free(fkey);
4488   silc_free(channel_id);
4489   silc_server_command_free(cmd);
4490 }
4491
4492 /* Server side of CUMODE command. Changes client's mode on a channel. */
4493
4494 SILC_SERVER_CMD_FUNC(cumode)
4495 {
4496   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4497   SilcServer server = cmd->server;
4498   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4499   SilcIDListData idata = (SilcIDListData)client;
4500   SilcChannelID *channel_id;
4501   SilcClientID *client_id;
4502   SilcChannelEntry channel;
4503   SilcClientEntry target_client;
4504   SilcChannelClientEntry chl;
4505   SilcBuffer packet, idp;
4506   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4507   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4508   int notify = FALSE;
4509   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4510   SilcPublicKey founder_key = NULL;
4511   unsigned char *fkey = NULL;
4512   SilcUInt32 fkey_len = 0;
4513
4514   if (!client)
4515     goto out;
4516
4517   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4518
4519   /* Get Channel ID */
4520   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4521   if (!tmp_ch_id) {
4522     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4523                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4524     goto out;
4525   }
4526   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4527   if (!channel_id) {
4528     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4529                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4530     goto out;
4531   }
4532
4533   /* Get channel entry */
4534   channel = silc_idlist_find_channel_by_id(server->local_list, 
4535                                            channel_id, NULL);
4536   if (!channel) {
4537     channel = silc_idlist_find_channel_by_id(server->global_list, 
4538                                              channel_id, NULL);
4539     if (!channel) {
4540       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4541                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4542                                             0);
4543       goto out;
4544     }
4545   }
4546
4547   /* Check whether sender is on the channel */
4548   if (!silc_server_client_on_channel(client, channel, &chl)) {
4549     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4550                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4551     goto out;
4552   }
4553   sender_mask = chl->mode;
4554   
4555   /* Get the target client's channel mode mask */
4556   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4557   if (!tmp_mask) {
4558     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4559                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4560                                           0);
4561     goto out;
4562   }
4563   SILC_GET32_MSB(target_mask, tmp_mask);
4564
4565   /* Get target Client ID */
4566   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4567   if (!tmp_id) {
4568     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4569                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4570     goto out;
4571   }
4572   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4573   if (!client_id) {
4574     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4575                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4576     goto out;
4577   }
4578
4579   /* Get target client's entry */
4580   target_client = silc_idlist_find_client_by_id(server->local_list, 
4581                                                 client_id, TRUE, NULL);
4582   if (!target_client) {
4583     target_client = silc_idlist_find_client_by_id(server->global_list, 
4584                                                   client_id, TRUE, NULL);
4585   }
4586
4587   if (target_client != client &&
4588       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4589       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4590     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4592     goto out;
4593   }
4594
4595   /* Check whether target client is on the channel */
4596   if (target_client != client) {
4597     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4598       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4599                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4600       goto out;
4601     }
4602   }
4603
4604   /* 
4605    * Change the mode 
4606    */
4607
4608   /* If the target client is founder, no one else can change their mode
4609      but themselves. */
4610   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4611     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4612                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4613                                           0);
4614     goto out;
4615   }
4616
4617   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4618     if (target_client != client) {
4619       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4620                                             SILC_STATUS_ERR_NOT_YOU, 0);
4621       goto out;
4622     }
4623
4624     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4625       /* The client tries to claim the founder rights. */
4626       unsigned char *tmp_auth;
4627       SilcUInt32 tmp_auth_len;
4628       SilcChannelClientEntry chl2;
4629       SilcHashTableList htl;
4630
4631       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4632           !channel->founder_key || !idata->public_key ||
4633           !silc_pkcs_public_key_compare(channel->founder_key, 
4634                                         idata->public_key)) {
4635         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4636                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4637         goto out;
4638       }
4639
4640       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4641       if (!tmp_auth) {
4642         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4643                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4644         goto out;
4645       }
4646
4647       /* Verify the authentication payload */
4648       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4649                                  channel->founder_key, 0, server->sha1hash,
4650                                  client->id, SILC_ID_CLIENT)) {
4651         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4652                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4653         goto out;
4654       }
4655
4656       notify = TRUE;
4657       founder_key = channel->founder_key;
4658       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4659       if (!fkey) {
4660         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4661                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4662         goto out;
4663       }
4664
4665       /* There cannot be anyone else as founder on the channel now.  This
4666          client is definitely the founder due to this authentication */
4667       silc_hash_table_list(channel->user_list, &htl);
4668       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4669         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4670           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4671           silc_server_force_cumode_change(server, NULL, channel, chl2,
4672                                           chl2->mode);
4673           break;
4674         }
4675       silc_hash_table_list_reset(&htl);
4676
4677       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4678     }
4679   } else {
4680     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4681       if (target_client == client) {
4682         /* Remove channel founder rights from itself */
4683         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4684         notify = TRUE;
4685       } else {
4686         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4687                                               SILC_STATUS_ERR_NOT_YOU, 0);
4688         goto out;
4689       }
4690     }
4691   }
4692
4693   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4694     /* Promote to operator */
4695     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4696       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) && 
4697           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4698         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4699                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4700                                               0);
4701         goto out;
4702       }
4703
4704       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4705       notify = TRUE;
4706     }
4707   } else {
4708     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4709       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4710           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4711         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,   
4712                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4713                                               0);
4714         goto out;
4715       }
4716       
4717       /* Demote to normal user */
4718       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4719       notify = TRUE;
4720     }
4721   }
4722
4723   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4724     if (target_client != client) {
4725       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4726                                             SILC_STATUS_ERR_NOT_YOU, 0);
4727       goto out;
4728     }
4729
4730     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4731       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4732       notify = TRUE;
4733     }
4734   } else {
4735     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4736       if (target_client != client) {
4737         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4738                                               SILC_STATUS_ERR_NOT_YOU, 0);
4739         goto out;
4740       }
4741
4742       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4743       notify = TRUE;
4744     }
4745   }
4746
4747   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4748     if (target_client != client) {
4749       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4750                                             SILC_STATUS_ERR_NOT_YOU, 0);
4751       goto out;
4752     }
4753
4754     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4755       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4756       notify = TRUE;
4757     }
4758   } else {
4759     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4760       if (target_client != client) {
4761         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4762                                               SILC_STATUS_ERR_NOT_YOU, 0);
4763         goto out;
4764       }
4765
4766       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4767       notify = TRUE;
4768     }
4769   }
4770
4771   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4772     if (target_client != client) {
4773       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4774                                             SILC_STATUS_ERR_NOT_YOU, 0);
4775       goto out;
4776     }
4777
4778     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4779       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4780       notify = TRUE;
4781     }
4782   } else {
4783     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4784       if (target_client != client) {
4785         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4786                                               SILC_STATUS_ERR_NOT_YOU, 0);
4787         goto out;
4788       }
4789
4790       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4791       notify = TRUE;
4792     }
4793   }
4794
4795   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4796     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4797       if (client == target_client) {
4798         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4799                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4800         goto out;
4801       }
4802       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4803       notify = TRUE;
4804     }
4805   } else {
4806     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4807       if (client == target_client) {
4808         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4809                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4810         goto out;
4811       }
4812       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4813       notify = TRUE;
4814     }
4815   }
4816
4817   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4818   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4819
4820   /* Send notify to channel, notify only if mode was actually changed. */
4821   if (notify) {
4822     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4823                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4824                                        idp->data, idp->len,
4825                                        tmp_mask, 4, 
4826                                        tmp_id, tmp_len,
4827                                        fkey, fkey_len);
4828
4829     /* Set CUMODE notify type to network */
4830     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4831                                    SILC_BROADCAST(server), channel,
4832                                    target_mask, client->id, SILC_ID_CLIENT,
4833                                    target_client->id, founder_key);
4834   }
4835
4836   /* Send command reply to sender */
4837   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4838                                                 SILC_STATUS_OK, 0, ident, 3,
4839                                                 2, tmp_mask, 4,
4840                                                 3, tmp_ch_id, tmp_ch_len,
4841                                                 4, tmp_id, tmp_len);
4842   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4843                           packet->data, packet->len, FALSE);
4844     
4845   silc_buffer_free(packet);
4846   silc_free(channel_id);
4847   silc_free(client_id);
4848   silc_buffer_free(idp);
4849
4850  out:
4851   silc_free(fkey);
4852   silc_server_command_free(cmd);
4853 }
4854
4855 /* Server side of KICK command. Kicks client out of channel. */
4856
4857 SILC_SERVER_CMD_FUNC(kick)
4858 {
4859   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4860   SilcServer server = cmd->server;
4861   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4862   SilcClientEntry target_client;
4863   SilcChannelID *channel_id;
4864   SilcClientID *client_id;
4865   SilcChannelEntry channel;
4866   SilcChannelClientEntry chl;
4867   SilcBuffer idp;
4868   SilcUInt32 tmp_len, target_idp_len;
4869   unsigned char *tmp, *comment, *target_idp;
4870
4871   if (!client)
4872     goto out;
4873
4874   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4875
4876   /* Get Channel ID */
4877   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4878   if (!tmp) {
4879     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4880                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4881     goto out;
4882   }
4883   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4884   if (!channel_id) {
4885     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4886                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4887     goto out;
4888   }
4889
4890   /* Get channel entry */
4891   channel = silc_idlist_find_channel_by_id(server->local_list, 
4892                                            channel_id, NULL);
4893   if (!channel) {
4894     channel = silc_idlist_find_channel_by_id(server->local_list, 
4895                                              channel_id, NULL);
4896     if (!channel) {
4897       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4898                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4899                                             0);
4900       goto out;
4901     }
4902   }
4903
4904   /* Check whether sender is on the channel */
4905   if (!silc_server_client_on_channel(client, channel, &chl)) {
4906     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4907                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4908     goto out;
4909   }
4910
4911   /* Check that the kicker is channel operator or channel founder */
4912   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4913       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4914     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4915                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4916     goto out;
4917   }
4918   
4919   /* Get target Client ID */
4920   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4921   if (!target_idp) {
4922     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4923                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4924     goto out;
4925   }
4926   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4927   if (!client_id) {
4928     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4929                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4930     goto out;
4931   }
4932
4933   /* Get target client's entry */
4934   target_client = silc_idlist_find_client_by_id(server->local_list, 
4935                                                 client_id, TRUE, NULL);
4936   if (!target_client) {
4937     target_client = silc_idlist_find_client_by_id(server->global_list, 
4938                                                   client_id, TRUE, NULL);
4939   }
4940
4941   /* Check whether target client is on the channel */
4942   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4943     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4944                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4945                                           0);
4946     goto out;
4947   }
4948
4949   /* Check that the target client is not channel founder. Channel founder
4950      cannot be kicked from the channel. */
4951   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4952     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4953                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4954                                           0);
4955     goto out;
4956   }
4957   
4958   /* Get comment */
4959   tmp_len = 0;
4960   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4961   if (tmp_len > 128)
4962     comment = NULL;
4963
4964   /* Send command reply to sender */
4965   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4966                                         SILC_STATUS_OK, 0);
4967
4968   /* Send KICKED notify to local clients on the channel */
4969   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4970   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4971                                      SILC_NOTIFY_TYPE_KICKED, 3,
4972                                      target_idp, target_idp_len,
4973                                      comment, comment ? strlen(comment) : 0,
4974                                      idp->data, idp->len);
4975   silc_buffer_free(idp);
4976
4977   /* Send KICKED notify to primary route */
4978   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4979                                  SILC_BROADCAST(server), channel,
4980                                  target_client->id, client->id, comment);
4981
4982   /* Remove the client from the channel. If the channel does not exist
4983      after removing the client then the client kicked itself off the channel
4984      and we don't have to send anything after that. */
4985   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4986                                            target_client, FALSE))
4987     goto out;
4988
4989   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4990     /* Re-generate channel key */
4991     if (!silc_server_create_channel_key(server, channel, 0))
4992       goto out;
4993     
4994     /* Send the channel key to the channel. The key of course is not sent
4995        to the client who was kicked off the channel. */
4996     silc_server_send_channel_key(server, target_client->connection, channel, 
4997                                  server->server_type == SILC_ROUTER ? 
4998                                  FALSE : !server->standalone);
4999   }
5000
5001  out:
5002   silc_server_command_free(cmd);
5003 }
5004
5005 /* Server side of OPER command. Client uses this comand to obtain server
5006    operator privileges to this server/router. */
5007
5008 SILC_SERVER_CMD_FUNC(oper)
5009 {
5010   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5011   SilcServer server = cmd->server;
5012   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5013   unsigned char *username, *auth;
5014   SilcUInt32 tmp_len;
5015   SilcServerConfigAdmin *admin;
5016   SilcIDListData idata = (SilcIDListData)client;
5017   bool result = FALSE;
5018   SilcPublicKey cached_key;
5019
5020   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5021     goto out;
5022
5023   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
5024
5025   /* Get the username */
5026   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5027   if (!username) {
5028     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5029                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5030                                           0);
5031     goto out;
5032   }
5033
5034   /* Get the admin configuration */
5035   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5036                                         username, client->nickname);
5037   if (!admin) {
5038     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5039                                           username, client->nickname);
5040     if (!admin) {
5041       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5042                                             SILC_STATUS_ERR_AUTH_FAILED,
5043                                             0);
5044       goto out;
5045     }
5046   }
5047
5048   /* Get the authentication payload */
5049   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5050   if (!auth) {
5051     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5052                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5053                                           0);
5054     goto out;
5055   }
5056
5057   /* Verify the authentication data. If both passphrase and public key
5058      is set then try both of them. */
5059   if (admin->passphrase)
5060     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5061                                    admin->passphrase, admin->passphrase_len,
5062                                    idata->hash, client->id, SILC_ID_CLIENT);
5063   if (!result && admin->publickeys) {
5064     cached_key = silc_server_get_public_key(server, admin->publickeys);
5065     if (!cached_key)
5066       goto out;
5067     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5068                                    cached_key, 0, idata->hash, 
5069                                    client->id, SILC_ID_CLIENT);
5070   }
5071   if (!result) {
5072     /* Authentication failed */
5073     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5074                                           SILC_STATUS_ERR_AUTH_FAILED,
5075                                           0);
5076     goto out;
5077   }
5078
5079   /* Client is now server operator */
5080   client->mode |= SILC_UMODE_SERVER_OPERATOR;
5081
5082   /* Update statistics */
5083   if (SILC_IS_LOCAL(client))
5084     server->stat.my_server_ops++;
5085   if (server->server_type == SILC_ROUTER)
5086     server->stat.server_ops++;
5087
5088   /* Send UMODE change to primary router */
5089   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5090                                 SILC_BROADCAST(server), client->id,
5091                                 client->mode);
5092
5093   /* Check if anyone is watching this nickname */
5094   if (server->server_type == SILC_ROUTER)
5095     silc_server_check_watcher_list(server, client, NULL,
5096                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5097
5098   /* Send reply to the sender */
5099   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5100                                         SILC_STATUS_OK, 0);
5101
5102  out:
5103   silc_server_command_free(cmd);
5104 }
5105
5106 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
5107 {
5108   SilcServer server = app_context;
5109   QuitInternal q = (QuitInternal)context;
5110   SilcClientID *client_id = (SilcClientID *)q->sock;
5111   SilcClientEntry client;
5112   SilcSocketConnection sock;
5113
5114   client = silc_idlist_find_client_by_id(server->local_list, client_id,
5115                                          TRUE, NULL);
5116   if (client && client->connection) {
5117     sock = client->connection;
5118
5119     /* If there is pending outgoing data for the client then purge it
5120        to the network before closing connection. */
5121     silc_server_packet_queue_purge(server, sock);
5122
5123     /* Close the connection on our side */
5124     client->router = NULL;
5125     client->connection = NULL;
5126     sock->user_data = NULL;
5127     silc_server_close_connection(server, sock);
5128   }
5129
5130   silc_free(client_id);
5131   silc_free(q);
5132 }
5133
5134 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
5135 {
5136   SilcServer server = app_context;
5137   QuitInternal q = (QuitInternal)context;
5138   SilcClientID *client_id = (SilcClientID *)q->sock;
5139   SilcClientEntry client;
5140
5141   client = silc_idlist_find_client_by_id(server->local_list, client_id,
5142                                          TRUE, NULL);
5143   if (client && client->mode & SILC_UMODE_DETACHED) {
5144     SILC_LOG_DEBUG(("Detach timeout"));
5145     silc_server_free_client_data(server, NULL, client, TRUE,
5146                                  "Detach timeout");
5147   }
5148
5149   silc_free(client_id);
5150   silc_free(q);
5151 }
5152
5153 /* Server side of DETACH command.  Detached the client from the network
5154    by closing the connection but preserving the session. */
5155
5156 SILC_SERVER_CMD_FUNC(detach)
5157 {
5158   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5159   SilcServer server = cmd->server;
5160   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5161   QuitInternal q;
5162
5163   if (server->config->detach_disabled) {
5164     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5165                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5166     goto out;
5167   }
5168
5169   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5170     goto out;
5171
5172   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5173
5174   /* Remove operator privileges, since the client may resume in some
5175      other server which to it does not have operator privileges. */
5176   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5177   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5178
5179   /* Send the user mode notify to notify that client is detached */
5180   client->mode |= SILC_UMODE_DETACHED;
5181   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5182   client->last_command = 0;
5183   client->fast_command = 0;
5184   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5185                                 SILC_BROADCAST(server), client->id,
5186                                 client->mode);
5187   server->stat.my_detached++;
5188
5189   /* Check if anyone is watching this nickname */
5190   if (server->server_type == SILC_ROUTER)
5191     silc_server_check_watcher_list(server, client, NULL,
5192                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5193
5194   q = silc_calloc(1, sizeof(*q));
5195   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5196   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5197                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5198
5199   if (server->config->detach_timeout) {
5200     q = silc_calloc(1, sizeof(*q));
5201     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5202     silc_schedule_task_add(server->schedule, 0, 
5203                            silc_server_command_detach_timeout,
5204                            q, server->config->detach_timeout * 60,
5205                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5206   }
5207
5208   /* Send reply to the sender */
5209   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5210                                         SILC_STATUS_OK, 0);
5211
5212  out:
5213   silc_server_command_free(cmd);
5214 }
5215
5216 /* Server side of WATCH command. */
5217
5218 SILC_SERVER_CMD_FUNC(watch)
5219 {
5220   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5221   SilcServer server = cmd->server;
5222   char *add_nick, *del_nick;
5223   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5224   char nick[128 + 1];
5225   unsigned char hash[16], *tmp;
5226   SilcClientEntry client;
5227   SilcClientID *client_id = NULL;
5228
5229   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5230
5231   if (server->server_type == SILC_SERVER && !server->standalone) {
5232     if (!cmd->pending) {
5233       /* Send the command to router */
5234       SilcBuffer tmpbuf;
5235       SilcUInt16 old_ident;
5236
5237       old_ident = silc_command_get_ident(cmd->payload);
5238       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5239       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5240
5241       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5242                               SILC_PACKET_COMMAND, cmd->packet->flags,
5243                               tmpbuf->data, tmpbuf->len, TRUE);
5244
5245       /* Reprocess this packet after received reply from router */
5246       silc_server_command_pending(server, SILC_COMMAND_WATCH,
5247                                   silc_command_get_ident(cmd->payload),
5248                                   silc_server_command_watch,
5249                                   silc_server_command_dup(cmd));
5250       cmd->pending = TRUE;
5251       silc_command_set_ident(cmd->payload, old_ident);
5252       silc_buffer_free(tmpbuf);
5253     } else if (context2) {
5254       /* Received reply from router, just send same data to the client. */
5255       SilcServerCommandReplyContext reply = context2;
5256       SilcStatus status;
5257       silc_command_get_status(reply->payload, &status, NULL);
5258       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5259                                             0);
5260     }
5261
5262     goto out;
5263   }
5264
5265   /* We are router and keep the watch list for local cell */
5266
5267   /* Get the client ID */
5268   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5269   if (!tmp) {
5270     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5271                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5272                                           0);
5273     goto out;
5274   }
5275   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5276   if (!client_id) {
5277     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5278                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5279                                           0);
5280     goto out;
5281   }
5282
5283   /* Get the client entry which must be in local list */
5284   client = silc_idlist_find_client_by_id(server->local_list, 
5285                                          client_id, TRUE, NULL);
5286   if (!client) {
5287     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5288                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5289                                           0);
5290     goto out;
5291   }
5292
5293   /* Take nickname */
5294   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5295   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5296   if (!add_nick && !del_nick) {
5297     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5298                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5299                                           0);
5300     goto out;
5301   }
5302
5303   if (add_nick && add_nick_len > 128)
5304     add_nick[128] = '\0';
5305   if (del_nick && del_nick_len > 128)
5306     del_nick[128] = '\0';
5307
5308   memset(nick, 0, sizeof(nick));
5309
5310   /* Add new nickname to be watched in our cell */
5311   if (add_nick) {
5312     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5313       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5314                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5315       goto out;
5316     }
5317
5318     /* Hash the nick, we have the hash saved, not nicks because we can
5319        do one to one mapping to the nick from Client ID hash this way. */
5320     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5321     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5322
5323     /* Check whether this client is already watching this nickname */
5324     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
5325                                         client, NULL)) {
5326       /* Nickname is alredy being watched for this client */
5327       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5328                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
5329                                             0);
5330       goto out;
5331     }
5332
5333     /* Get the nickname from the watcher list and use the same key in
5334        new entries as well.  If key doesn't exist then create it. */
5335     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5336       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5337
5338     /* Add the client to the watcher list with the specified nickname hash. */
5339     silc_hash_table_add(server->watcher_list, tmp, client);
5340   }
5341
5342   /* Delete nickname from watch list */
5343   if (del_nick) {
5344     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5345       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5346                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5347       goto out;
5348     }
5349
5350     /* Hash the nick, we have the hash saved, not nicks because we can
5351        do one to one mapping to the nick from Client ID hash this way. */
5352     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5353     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5354
5355     /* Check that this client is watching for this nickname */
5356     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
5357                                          client, (void **)&tmp)) {
5358       /* Nickname is alredy being watched for this client */
5359       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5360                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5361       goto out;
5362     }
5363
5364     /* Delete the nickname from the watcher list. */
5365     silc_hash_table_del_by_context(server->watcher_list, hash, client);
5366
5367     /* Now check whether there still exists entries with this key, if not
5368        then free the key to not leak memory. */
5369     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5370       silc_free(tmp);
5371   }
5372
5373   /* Distribute the watch list to backup routers too */
5374   if (server->backup) {
5375     SilcBuffer tmpbuf;
5376     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5377     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5378     silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5379                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5380                             FALSE, TRUE);
5381     silc_buffer_free(tmpbuf);
5382   }
5383
5384   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5385                                         SILC_STATUS_OK, 0);
5386
5387  out:
5388   silc_free(client_id);
5389   silc_server_command_free(cmd);
5390 }
5391
5392 /* Server side of SILCOPER command. Client uses this comand to obtain router
5393    operator privileges to this router. */
5394
5395 SILC_SERVER_CMD_FUNC(silcoper)
5396 {
5397   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5398   SilcServer server = cmd->server;
5399   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5400   unsigned char *username, *auth;
5401   SilcUInt32 tmp_len;
5402   SilcServerConfigAdmin *admin;
5403   SilcIDListData idata = (SilcIDListData)client;
5404   bool result = FALSE;
5405   SilcPublicKey cached_key;
5406
5407   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5408     goto out;
5409
5410   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5411
5412   if (server->server_type != SILC_ROUTER) {
5413     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5414                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5415     goto out;
5416   }
5417
5418   /* Get the username */
5419   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5420   if (!username) {
5421     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5422                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5423                                           0);
5424     goto out;
5425   }
5426
5427   /* Get the admin configuration */
5428   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5429                                         username, client->nickname);
5430   if (!admin) {
5431     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5432                                           username, client->nickname);
5433     if (!admin) {
5434       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5435                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
5436       goto out;
5437     }
5438   }
5439
5440   /* Get the authentication payload */
5441   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5442   if (!auth) {
5443     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5444                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5445                                           0);
5446     goto out;
5447   }
5448
5449   /* Verify the authentication data. If both passphrase and public key
5450      is set then try both of them. */
5451   if (admin->passphrase)
5452     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5453                                    admin->passphrase, admin->passphrase_len,
5454                                    idata->hash, client->id, SILC_ID_CLIENT);
5455   if (!result && admin->publickeys) {
5456     cached_key = silc_server_get_public_key(server, admin->publickeys);
5457     if (!cached_key)
5458       goto out;
5459     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5460                                    cached_key, 0, idata->hash, 
5461                                    client->id, SILC_ID_CLIENT);
5462   }
5463   if (!result) {
5464     /* Authentication failed */
5465     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5466                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5467     goto out;
5468   }
5469
5470   /* Client is now router operator */
5471   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5472
5473   /* Update statistics */
5474   if (SILC_IS_LOCAL(client))
5475     server->stat.my_router_ops++;
5476   if (server->server_type == SILC_ROUTER)
5477     server->stat.router_ops++;
5478
5479   /* Send UMODE change to primary router */
5480   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5481                                 SILC_BROADCAST(server), client->id,
5482                                 client->mode);
5483
5484   /* Check if anyone is watching this nickname */
5485   if (server->server_type == SILC_ROUTER)
5486     silc_server_check_watcher_list(server, client, NULL,
5487                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5488
5489   /* Send reply to the sender */
5490   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5491                                         SILC_STATUS_OK, 0);
5492
5493  out:
5494   silc_server_command_free(cmd);
5495 }
5496
5497 /* Server side of command BAN. This is used to manage the ban list of the
5498    channel. To add clients and remove clients from the ban list. */
5499
5500 SILC_SERVER_CMD_FUNC(ban)
5501 {
5502   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5503   SilcServer server = cmd->server;
5504   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5505   SilcBuffer packet;
5506   SilcChannelEntry channel;
5507   SilcChannelClientEntry chl;
5508   SilcChannelID *channel_id = NULL;
5509   unsigned char *id, *add, *del;
5510   SilcUInt32 id_len, tmp_len;
5511   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5512
5513   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
5514     goto out;
5515
5516   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5517
5518   /* Get Channel ID */
5519   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5520   if (id) {
5521     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5522     if (!channel_id) {
5523       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5524                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5525       goto out;
5526     }
5527   }
5528
5529   /* Get channel entry. The server must know about the channel since the
5530      client is expected to be on the channel. */
5531   channel = silc_idlist_find_channel_by_id(server->local_list, 
5532                                            channel_id, NULL);
5533   if (!channel) {
5534     channel = silc_idlist_find_channel_by_id(server->global_list, 
5535                                              channel_id, NULL);
5536     if (!channel) {
5537       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5538                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5539                                             0);
5540       goto out;
5541     }
5542   }
5543
5544   /* Check whether this client is on the channel */
5545   if (!silc_server_client_on_channel(client, channel, &chl)) {
5546     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5547                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5548     goto out;
5549   }
5550
5551   /* The client must be at least channel operator. */
5552   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5553     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5554                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5555     goto out;
5556   }
5557
5558   /* Get the new ban and add it to the ban list */
5559   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5560   if (add) {
5561     if (!channel->ban_list)
5562       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5563     else
5564       channel->ban_list = silc_realloc(channel->ban_list, 
5565                                        sizeof(*channel->ban_list) * 
5566                                        (tmp_len + 
5567                                         strlen(channel->ban_list) + 2));
5568     if (add[tmp_len - 1] == ',')
5569       add[tmp_len - 1] = '\0';
5570
5571     strncat(channel->ban_list, add, tmp_len);
5572     strncat(channel->ban_list, ",", 1);
5573   }
5574
5575   /* Get the ban to be removed and remove it from the list */
5576   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5577   if (del && channel->ban_list) {
5578     char *start, *end, *n;
5579
5580     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5581       silc_free(channel->ban_list);
5582       channel->ban_list = NULL;
5583     } else {
5584       start = strstr(channel->ban_list, del);
5585       if (start && strlen(start) >= tmp_len) {
5586         end = start + tmp_len;
5587         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5588         strncat(n, channel->ban_list, start - channel->ban_list);
5589         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
5590                              end) - 1);
5591         silc_free(channel->ban_list);
5592         channel->ban_list = n;
5593       }
5594     }
5595   }
5596
5597   /* Send the BAN notify type to our primary router. */
5598   if (add || del)
5599     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5600                                 SILC_BROADCAST(server), channel, add, del);
5601
5602   /* Send the reply back to the client */
5603   packet = 
5604     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5605                                          SILC_STATUS_OK, 0, ident, 2,
5606                                          2, id, id_len,
5607                                          3, channel->ban_list, 
5608                                          channel->ban_list ? 
5609                                          strlen(channel->ban_list) -1 : 0);
5610   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5611                           packet->data, packet->len, FALSE);
5612     
5613   silc_buffer_free(packet);
5614
5615  out:
5616   silc_free(channel_id);
5617   silc_server_command_free(cmd);
5618 }
5619
5620 /* Server side command of LEAVE. Removes client from a channel. */
5621
5622 SILC_SERVER_CMD_FUNC(leave)
5623 {
5624   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5625   SilcServer server = cmd->server;
5626   SilcSocketConnection sock = cmd->sock;
5627   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5628   SilcChannelID *id = NULL;
5629   SilcChannelEntry channel;
5630   SilcUInt32 len;
5631   unsigned char *tmp;
5632
5633   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !id_entry)
5634     goto out;
5635
5636   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5637
5638   /* Get Channel ID */
5639   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5640   if (!tmp) {
5641     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5642                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5643     goto out;
5644   }
5645   id = silc_id_payload_parse_id(tmp, len, NULL);
5646   if (!id) {
5647     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5648                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5649     goto out;
5650   }
5651
5652   /* Get channel entry */
5653   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5654   if (!channel) {
5655     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5656     if (!channel) {
5657       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5658                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5659                                             0);
5660       goto out;
5661     }
5662   }
5663
5664   /* Check whether this client is on the channel */
5665   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5666     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5667                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5668     goto out;
5669   }
5670
5671   /* Notify routers that they should remove this client from their list
5672      of clients on the channel. Send LEAVE notify type. */
5673   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5674                                 SILC_BROADCAST(server), channel, id_entry->id);
5675
5676   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5677                                        SILC_STATUS_OK, 0, 2, tmp, len);
5678
5679   /* Remove client from channel */
5680   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5681                                            TRUE))
5682     /* If the channel does not exist anymore we won't send anything */
5683     goto out;
5684
5685   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5686     /* Re-generate channel key */
5687     if (!silc_server_create_channel_key(server, channel, 0))
5688       goto out;
5689
5690     /* Send the channel key */
5691     silc_server_send_channel_key(server, NULL, channel, 
5692                                  server->server_type == SILC_ROUTER ? 
5693                                  FALSE : !server->standalone);
5694   }
5695
5696  out:
5697   silc_free(id);
5698   silc_server_command_free(cmd);
5699 }
5700
5701 /* Server side of command USERS. Resolves clients and their USERS currently
5702    joined on the requested channel. The list of Client ID's and their modes
5703    on the channel is sent back. */
5704
5705 SILC_SERVER_CMD_FUNC(users)
5706 {
5707   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5708   SilcServer server = cmd->server;
5709   SilcChannelEntry channel;
5710   SilcChannelID *id = NULL;
5711   SilcBuffer packet, idp;
5712   unsigned char *channel_id;
5713   SilcUInt32 channel_id_len;
5714   SilcBuffer client_id_list;
5715   SilcBuffer client_mode_list;
5716   unsigned char lc[4];
5717   SilcUInt32 list_count = 0;
5718   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5719   char *channel_name;
5720
5721   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5722
5723   /* Get Channel ID */
5724   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5725
5726   /* Get channel name */
5727   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5728
5729   if (!channel_id && !channel_name) {
5730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5731                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5732     goto out;
5733   }
5734
5735   if (channel_id) {
5736     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5737     if (!id) {
5738       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5739                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5740       goto out;
5741     }
5742   }
5743
5744   /* If we are server and we don't know about this channel we will send
5745      the command to our router. If we know about the channel then we also
5746      have the list of users already. */
5747   if (id)
5748     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5749   else
5750     channel = silc_idlist_find_channel_by_name(server->local_list, 
5751                                                channel_name, NULL);
5752
5753   if (!channel || (!server->standalone && (channel->disabled || 
5754                     !channel->users_resolved))) {
5755     if (server->server_type != SILC_ROUTER && !server->standalone &&
5756         !cmd->pending) {
5757       SilcBuffer tmpbuf;
5758       
5759       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5760       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5761       
5762       /* Send USERS command */
5763       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5764                               SILC_PACKET_COMMAND, cmd->packet->flags,
5765                               tmpbuf->data, tmpbuf->len, TRUE);
5766       
5767       /* Reprocess this packet after received reply */
5768       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5769                                   silc_command_get_ident(cmd->payload),
5770                                   silc_server_command_users,
5771                                   silc_server_command_dup(cmd));
5772       cmd->pending = TRUE;
5773       silc_command_set_ident(cmd->payload, ident);
5774       silc_buffer_free(tmpbuf);
5775       silc_free(id);
5776       goto out;
5777     }
5778
5779     /* Check the global list as well. */
5780     if (id)
5781       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5782     else
5783       channel = silc_idlist_find_channel_by_name(server->global_list, 
5784                                                  channel_name, NULL);
5785     if (!channel) {
5786       /* Channel really does not exist */
5787       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5788                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5789                                             0);
5790       goto out;
5791     }
5792   }
5793
5794   /* If the channel is private or secret do not send anything, unless the
5795      user requesting this command is on the channel or is server */
5796   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5797     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5798         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5799                                           NULL)) {
5800       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5801                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5802                                             0);
5803       goto out;
5804     }
5805   }
5806
5807   /* Get the users list */
5808   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5809                                         &client_mode_list, &list_count)) {
5810     list_count = 0;
5811     client_id_list = NULL;
5812     client_mode_list = NULL;
5813   }
5814
5815   /* List count */
5816   SILC_PUT32_MSB(list_count, lc);
5817
5818   /* Send reply */
5819   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5820   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5821                                                 SILC_STATUS_OK, 0, ident, 4,
5822                                                 2, idp->data, idp->len,
5823                                                 3, lc, 4,
5824                                                 4, client_id_list ? 
5825                                                 client_id_list->data : NULL,
5826                                                 client_id_list ?
5827                                                 client_id_list->len : 0,
5828                                                 5, client_mode_list ?
5829                                                 client_mode_list->data : NULL,
5830                                                 client_mode_list ?
5831                                                 client_mode_list->len : 0);
5832   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5833                           packet->data, packet->len, FALSE);
5834     
5835   silc_buffer_free(idp);
5836   silc_buffer_free(packet);
5837   if (client_id_list)
5838     silc_buffer_free(client_id_list);
5839   if (client_mode_list)
5840     silc_buffer_free(client_mode_list);
5841   silc_free(id);
5842
5843  out:
5844   silc_server_command_free(cmd);
5845 }
5846
5847 /* Server side of command GETKEY. This fetches the client's public key
5848    from the server where to the client is connected. */
5849
5850 SILC_SERVER_CMD_FUNC(getkey)
5851 {
5852   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5853   SilcServer server = cmd->server;
5854   SilcBuffer packet;
5855   SilcClientEntry client;
5856   SilcServerEntry server_entry;
5857   SilcClientID *client_id = NULL;
5858   SilcServerID *server_id = NULL;
5859   SilcIDPayload idp = NULL;
5860   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5861   unsigned char *tmp, *pkdata;
5862   SilcUInt32 tmp_len, pklen;
5863   SilcBuffer pk = NULL;
5864   SilcIdType id_type;
5865   SilcPublicKey public_key;
5866
5867   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5868   if (!tmp) {
5869     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5870                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5871                                           0);
5872     goto out;
5873   }
5874   idp = silc_id_payload_parse(tmp, tmp_len);
5875   if (!idp) {
5876     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5877                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5878                                           0);
5879     goto out;
5880   }
5881
5882   id_type = silc_id_payload_get_type(idp);
5883   if (id_type == SILC_ID_CLIENT) {
5884     client_id = silc_id_payload_get_id(idp);
5885
5886     /* If the client is not found from local list there is no chance it
5887        would be locally connected client so send the command further. */
5888     client = silc_idlist_find_client_by_id(server->local_list, 
5889                                            client_id, TRUE, NULL);
5890     if (!client)
5891       client = silc_idlist_find_client_by_id(server->global_list, 
5892                                              client_id, TRUE, NULL);
5893     
5894     if ((!client && !cmd->pending && !server->standalone) ||
5895         (client && !client->connection && !cmd->pending &&
5896          !(client->mode & SILC_UMODE_DETACHED)) ||
5897         (client && !client->data.public_key && !cmd->pending)) {
5898       SilcBuffer tmpbuf;
5899       SilcUInt16 old_ident;
5900       SilcSocketConnection dest_sock;
5901       
5902       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5903                                                client_id, NULL, NULL);
5904       if (!dest_sock)
5905         goto out;
5906       
5907       old_ident = silc_command_get_ident(cmd->payload);
5908       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5909       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5910       
5911       silc_server_packet_send(server, dest_sock,
5912                               SILC_PACKET_COMMAND, cmd->packet->flags,
5913                               tmpbuf->data, tmpbuf->len, TRUE);
5914       
5915       /* Reprocess this packet after received reply from router */
5916       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5917                                   silc_command_get_ident(cmd->payload),
5918                                   silc_server_command_getkey,
5919                                   silc_server_command_dup(cmd));
5920       cmd->pending = TRUE;
5921       silc_command_set_ident(cmd->payload, old_ident);
5922       silc_buffer_free(tmpbuf);
5923       goto out;
5924     }
5925
5926     if (!client) {
5927       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5928                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5929                                             0);
5930       goto out;
5931     }
5932
5933     /* The client is locally connected, just get the public key and
5934        send it back. If they key does not exist then do not send it, 
5935        send just OK reply */
5936     public_key = client->data.public_key;
5937     if (!public_key) {
5938       pkdata = NULL;
5939       pklen = 0;
5940     } else {
5941       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5942       pk = silc_buffer_alloc(4 + tmp_len);
5943       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5944       silc_buffer_format(pk,
5945                          SILC_STR_UI_SHORT(tmp_len),
5946                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5947                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5948                          SILC_STR_END);
5949       silc_free(tmp);
5950       pkdata = pk->data;
5951       pklen = pk->len;
5952     }
5953   } else if (id_type == SILC_ID_SERVER) {
5954     server_id = silc_id_payload_get_id(idp);
5955
5956     /* If the server is not found from local list there is no chance it
5957        would be locally connected server so send the command further. */
5958     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5959                                                  server_id, TRUE, NULL);
5960     if (!server_entry)
5961       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5962                                                    server_id, TRUE, NULL);
5963     
5964     if (server_entry != server->id_entry &&
5965         ((!server_entry && !cmd->pending && !server->standalone) ||
5966          (server_entry && !server_entry->connection && !cmd->pending &&
5967           !server->standalone) ||
5968          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5969           !server->standalone))) {
5970       SilcBuffer tmpbuf;
5971       SilcUInt16 old_ident;
5972       
5973       old_ident = silc_command_get_ident(cmd->payload);
5974       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5975       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5976       
5977       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5978                               SILC_PACKET_COMMAND, cmd->packet->flags,
5979                               tmpbuf->data, tmpbuf->len, TRUE);
5980       
5981       /* Reprocess this packet after received reply from router */
5982       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5983                                   silc_command_get_ident(cmd->payload),
5984                                   silc_server_command_getkey,
5985                                   silc_server_command_dup(cmd));
5986       cmd->pending = TRUE;
5987       silc_command_set_ident(cmd->payload, old_ident);
5988       silc_buffer_free(tmpbuf);
5989       goto out;
5990     }
5991
5992     if (!server_entry) {
5993       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5994                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5995                                             0);
5996       goto out;
5997     }
5998
5999     /* If they key does not exist then do not send it, send just OK reply */
6000     public_key = (!server_entry->data.public_key ? 
6001                   (server_entry == server->id_entry ? server->public_key :
6002                    NULL) : server_entry->data.public_key);
6003     if (!public_key) {
6004       pkdata = NULL;
6005       pklen = 0;
6006     } else {
6007       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
6008       pk = silc_buffer_alloc(4 + tmp_len);
6009       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
6010       silc_buffer_format(pk,
6011                          SILC_STR_UI_SHORT(tmp_len),
6012                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
6013                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
6014                          SILC_STR_END);
6015       silc_free(tmp);
6016       pkdata = pk->data;
6017       pklen = pk->len;
6018     }
6019   } else {
6020     goto out;
6021   }
6022
6023   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6024   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
6025                                                 SILC_STATUS_OK, 0, ident, 
6026                                                 pkdata ? 2 : 1,
6027                                                 2, tmp, tmp_len,
6028                                                 3, pkdata, pklen);
6029   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
6030                           packet->data, packet->len, FALSE);
6031   silc_buffer_free(packet);
6032
6033   if (pk)
6034     silc_buffer_free(pk);
6035
6036  out:
6037   if (idp)
6038     silc_id_payload_free(idp);
6039   silc_free(client_id);
6040   silc_free(server_id);
6041   silc_server_command_free(cmd);
6042 }
6043
6044
6045 /* Private range commands, specific to this implementation */
6046
6047 /* Server side command of CONNECT. Connects us to the specified remote
6048    server or router. */
6049
6050 SILC_SERVER_CMD_FUNC(connect)
6051 {
6052   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6053   SilcServer server = cmd->server;
6054   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6055   unsigned char *tmp, *host;
6056   SilcUInt32 tmp_len;
6057   SilcUInt32 port = SILC_PORT;
6058
6059   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6060     goto out;
6061
6062   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
6063
6064   /* Check whether client has the permissions. */
6065   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6066       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6067     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6068                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
6069     goto out;
6070   }
6071
6072   if (server->server_type == SILC_ROUTER && 
6073       client->mode & SILC_UMODE_SERVER_OPERATOR) {
6074     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6075                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
6076     goto out;
6077   }
6078
6079   /* Get the remote server */
6080   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6081   if (!host) {
6082     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6083                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6084                                           0);
6085     goto out;
6086   }
6087
6088   /* Get port */
6089   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6090   if (tmp)
6091     SILC_GET32_MSB(port, tmp);
6092
6093   /* Create the connection. It is done with timeout and is async. */
6094   silc_server_create_connection(server, host, port);
6095
6096   /* Send reply to the sender */
6097   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
6098                                         SILC_STATUS_OK, 0);
6099
6100  out:
6101   silc_server_command_free(cmd);
6102 }
6103
6104 /* Server side command of CLOSE. Closes connection to a specified server. */
6105  
6106 SILC_SERVER_CMD_FUNC(close)
6107 {
6108   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6109   SilcServer server = cmd->server;
6110   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6111   SilcServerEntry server_entry;
6112   SilcSocketConnection sock;
6113   unsigned char *tmp;
6114   SilcUInt32 tmp_len;
6115   unsigned char *name;
6116   SilcUInt32 port = SILC_PORT;
6117
6118   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6119     goto out;
6120
6121   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
6122
6123   /* Check whether client has the permissions. */
6124   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6125       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6126     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6127                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
6128                                           0);
6129     goto out;
6130   }
6131
6132   /* Get the remote server */
6133   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
6134   if (!name) {
6135     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6136                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
6137                                           0);
6138     goto out;
6139   }
6140
6141   /* Get port */
6142   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
6143   if (tmp)
6144     SILC_GET32_MSB(port, tmp);
6145
6146   server_entry = silc_idlist_find_server_by_conn(server->local_list,
6147                                                  name, port, FALSE, NULL);
6148   if (!server_entry)
6149     server_entry = silc_idlist_find_server_by_conn(server->global_list,
6150                                                    name, port, FALSE, NULL);
6151   if (!server_entry) {
6152     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6153                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
6154     goto out;
6155   }
6156
6157   if (server_entry == server->id_entry) {
6158     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6159                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
6160     goto out;
6161   }
6162
6163   /* Send reply to the sender */
6164   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6165                                         SILC_STATUS_OK, 0);
6166
6167   /* Close the connection to the server */
6168   sock = (SilcSocketConnection)server_entry->connection;
6169
6170   /* If we shutdown primary router connection manually then don't trigger
6171      any reconnect or backup router connections, by setting the router
6172      to NULL here. */
6173   if (server->router == server_entry) {
6174     server->id_entry->router = NULL;
6175     server->router = NULL;
6176     server->standalone = TRUE;
6177   }
6178   silc_server_free_sock_user_data(server, sock, NULL);
6179   silc_server_close_connection(server, sock);
6180   
6181  out:
6182   silc_server_command_free(cmd);
6183 }
6184
6185 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6186    active connections. */
6187  
6188 SILC_SERVER_CMD_FUNC(shutdown)
6189 {
6190   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6191   SilcServer server = cmd->server;
6192   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6193
6194   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT || !client)
6195     goto out;
6196
6197   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6198
6199   /* Check whether client has the permission. */
6200   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6201       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6202     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6203                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
6204                                           0);
6205     goto out;
6206   }
6207
6208   /* Send reply to the sender */
6209   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6210                                         SILC_STATUS_OK, 0);
6211
6212   /* Then, gracefully, or not, bring the server down. */
6213   silc_server_stop(server);
6214   exit(0);
6215
6216  out:
6217   silc_server_command_free(cmd);
6218 }