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