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