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