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