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