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
3178   SILC_LOG_DEBUG(("Start"));
3179
3180   if (!channel)
3181     return;
3182
3183   /* Get the client entry */
3184   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3185     client = (SilcClientEntry)sock->user_data;
3186   } else {
3187     client = silc_server_get_client_resolve(server, client_id, FALSE, 
3188                                             &resolve);
3189     if (!client) {
3190       if (cmd->pending)
3191         goto out;
3192
3193       if (!resolve) {
3194         silc_server_command_send_status_reply(
3195                                          cmd, SILC_COMMAND_JOIN,
3196                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3197         goto out;
3198       }
3199
3200       /* The client info is being resolved. Reprocess this packet after
3201          receiving the reply to the query. */
3202       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3203                                   server->cmd_ident,
3204                                   silc_server_command_join, 
3205                                   silc_server_command_dup(cmd));
3206       cmd->pending = TRUE;
3207       goto out;
3208     }
3209
3210     cmd->pending = FALSE;
3211   }
3212
3213   /*
3214    * Check founder auth payload if provided.  If client can gain founder
3215    * privileges it can override various conditions on joining the channel,
3216    * and can have directly the founder mode set on the channel.
3217    */
3218   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3219     SilcIDListData idata = (SilcIDListData)client;
3220
3221     if (channel->founder_key && idata->public_key &&
3222         silc_pkcs_public_key_compare(channel->founder_key, 
3223                                      idata->public_key)) {
3224       /* Check whether the client is to become founder */
3225       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3226                                 channel->founder_key, 0, server->sha1hash,
3227                                 client->id, SILC_ID_CLIENT)) {
3228         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3229         founder = TRUE;
3230       }
3231     }
3232   }
3233
3234   /*
3235    * Check channel modes
3236    */
3237
3238   if (!umode) {
3239     memset(check, 0, sizeof(check));
3240     memset(check2, 0, sizeof(check2));
3241     strncat(check, client->nickname, strlen(client->nickname));
3242     strncat(check, "!", 1);
3243     strncat(check, client->username, strlen(client->username));
3244     if (!strchr(client->username, '@')) {
3245       strncat(check, "@", 1);
3246       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3247     }
3248
3249     strncat(check2, client->nickname, strlen(client->nickname));
3250     if (!strchr(client->nickname, '@')) {
3251       strncat(check2, "@", 1);
3252       strncat(check2, server->server_name, strlen(server->server_name));
3253     }
3254     strncat(check2, "!", 1);
3255     strncat(check2, client->username, strlen(client->username));
3256     if (!strchr(client->username, '@')) {
3257       strncat(check2, "@", 1);
3258       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3259     }
3260     
3261     /* Check invite list if channel is invite-only channel */
3262     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3263       if (!channel->invite_list ||
3264           (!silc_string_match(channel->invite_list, check) &&
3265            !silc_string_match(channel->invite_list, check2))) {
3266         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3267                                               SILC_STATUS_ERR_NOT_INVITED, 0);
3268         goto out;
3269       }
3270     }
3271
3272     /* Check ban list if it exists. If the client's nickname, server,
3273        username and/or hostname is in the ban list the access to the
3274        channel is denied. */
3275     if (channel->ban_list) {
3276       if (silc_string_match(channel->ban_list, check) ||
3277           silc_string_match(channel->ban_list, check2)) {
3278         silc_server_command_send_status_reply(
3279                                       cmd, SILC_COMMAND_JOIN,
3280                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3281         goto out;
3282       }
3283     }
3284     
3285     /* Check user count limit if set. */
3286     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3287       if (silc_hash_table_count(channel->user_list) + 1 > 
3288           channel->user_limit) {
3289         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3290                                               SILC_STATUS_ERR_CHANNEL_IS_FULL,
3291                                               0);
3292         goto out;
3293       }
3294     }
3295   }
3296
3297   /* Check the channel passphrase if set. */
3298   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3299     /* Get passphrase */
3300     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3301     if (tmp)
3302       passphrase = silc_memdup(tmp, tmp_len);
3303   
3304     if (!passphrase || !channel->passphrase ||
3305         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3306       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3307                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
3308       goto out;
3309     }
3310   }
3311
3312   /*
3313    * Client is allowed to join to the channel. Make it happen.
3314    */
3315
3316   /* Check whether the client already is on the channel */
3317   if (silc_server_client_on_channel(client, channel, NULL)) {
3318     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3319                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3320     goto out;
3321   }
3322
3323   /* Generate new channel key as protocol dictates */
3324   if (create_key) {
3325     if (!silc_server_create_channel_key(server, channel, 0))
3326       goto out;
3327
3328     /* Send the channel key. This is broadcasted to the channel but is not
3329        sent to the client who is joining to the channel. */
3330     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3331       silc_server_send_channel_key(server, NULL, channel, 
3332                                    server->server_type == SILC_ROUTER ? 
3333                                    FALSE : !server->standalone);
3334   }
3335
3336   /* Join the client to the channel by adding it to channel's user list.
3337      Add also the channel to client entry's channels list for fast cross-
3338      referencing. */
3339   chl = silc_calloc(1, sizeof(*chl));
3340   chl->mode = umode;
3341   chl->client = client;
3342   chl->channel = channel;
3343   silc_hash_table_add(channel->user_list, client, chl);
3344   silc_hash_table_add(client->channels, channel, chl);
3345   channel->user_count++;
3346   channel->disabled = FALSE;
3347
3348   /* Get users on the channel */
3349   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3350                                    &user_count);
3351
3352   /* Encode Client ID Payload of the original client who wants to join */
3353   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3354
3355   /* Encode command reply packet */
3356   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3357   SILC_PUT32_MSB(channel->mode, mode);
3358   SILC_PUT32_MSB(created, tmp2);
3359   SILC_PUT32_MSB(user_count, tmp3);
3360
3361   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3362     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3363     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3364                                                            SILC_ID_CHANNEL), 
3365                                            tmp,
3366                                            strlen(channel->channel_key->
3367                                                   cipher->name),
3368                                            channel->channel_key->cipher->name,
3369                                            channel->key_len / 8, channel->key);
3370     silc_free(tmp);
3371   }
3372
3373   reply = 
3374     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3375                                          SILC_STATUS_OK, 0, ident, 13,
3376                                          2, channel->channel_name,
3377                                          strlen(channel->channel_name),
3378                                          3, chidp->data, chidp->len,
3379                                          4, clidp->data, clidp->len,
3380                                          5, mode, 4,
3381                                          6, tmp2, 4,
3382                                          7, keyp ? keyp->data : NULL, 
3383                                          keyp ? keyp->len : 0,
3384                                          8, channel->ban_list, 
3385                                          channel->ban_list ?
3386                                          strlen(channel->ban_list) : 0,
3387                                          9, channel->invite_list,
3388                                          channel->invite_list ?
3389                                          strlen(channel->invite_list) : 0,
3390                                          10, channel->topic,
3391                                          channel->topic ?
3392                                          strlen(channel->topic) : 0,
3393                                          11, silc_hmac_get_name(channel->hmac),
3394                                          strlen(silc_hmac_get_name(channel->
3395                                                                    hmac)),
3396                                          12, tmp3, 4,
3397                                          13, user_list->data, user_list->len,
3398                                          14, mode_list->data, 
3399                                          mode_list->len);
3400
3401   /* Send command reply */
3402   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3403                           reply->data, reply->len, FALSE);
3404
3405   /* Send JOIN notify to locally connected clients on the channel. If
3406      we are normal server then router will send or have sent JOIN notify
3407      already. However since we've added the client already to our channel
3408      we'll ignore it (in packet_receive.c) so we must send it here. If
3409      we are router then this will send it to local clients and local
3410      servers. */
3411   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3412                                      SILC_NOTIFY_TYPE_JOIN, 2,
3413                                      clidp->data, clidp->len,
3414                                      chidp->data, chidp->len);
3415
3416   if (!cmd->pending) {
3417     /* Send JOIN notify packet to our primary router */
3418     if (!server->standalone)
3419       silc_server_send_notify_join(server, server->router->connection,
3420                                    server->server_type == SILC_ROUTER ?
3421                                    TRUE : FALSE, channel, client->id);
3422
3423     if (keyp)
3424       /* Distribute the channel key to all backup routers. */
3425       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3426                               keyp->data, keyp->len, FALSE, TRUE);
3427
3428     /* If client became founder by providing correct founder auth data
3429        notify the mode change to the channel. */
3430     if (founder) {
3431       SILC_PUT32_MSB(chl->mode, mode);
3432       tmp = silc_pkcs_public_key_encode(channel->founder_key, &tmp_len);
3433       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3434                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3435                                          clidp->data, clidp->len,
3436                                          mode, 4, clidp->data, clidp->len,
3437                                          tmp, tmp_len);
3438       silc_free(tmp);
3439       
3440       /* Set CUMODE notify type to network */
3441       if (!server->standalone)
3442         silc_server_send_notify_cumode(server, server->router->connection,
3443                                        server->server_type == SILC_ROUTER ? 
3444                                        TRUE : FALSE, channel,
3445                                        chl->mode, client->id, SILC_ID_CLIENT,
3446                                        client->id, channel->founder_key);
3447     }
3448   }
3449
3450   silc_buffer_free(reply);
3451   silc_buffer_free(clidp);
3452   silc_buffer_free(chidp);
3453   silc_buffer_free(keyp);
3454   silc_buffer_free(user_list);
3455   silc_buffer_free(mode_list);
3456
3457  out:
3458   silc_free(passphrase);
3459 }
3460
3461 /* Server side of command JOIN. Joins client into requested channel. If 
3462    the channel does not exist it will be created. */
3463
3464 SILC_SERVER_CMD_FUNC(join)
3465 {
3466   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3467   SilcServer server = cmd->server;
3468   unsigned char *auth;
3469   SilcUInt32 tmp_len, auth_len;
3470   char *tmp, *channel_name = NULL, *cipher, *hmac;
3471   SilcChannelEntry channel;
3472   SilcUInt32 umode = 0;
3473   bool created = FALSE, create_key = TRUE;
3474   SilcClientID *client_id;
3475
3476   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3477
3478   /* Get channel name */
3479   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3480   if (!tmp) {
3481     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3482                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3483                                           0);
3484     goto out;
3485   }
3486   channel_name = tmp;
3487
3488   if (tmp_len > 256)
3489     channel_name[255] = '\0';
3490
3491   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3492     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3493                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
3494     goto out;
3495   }
3496
3497   /* Get Client ID of the client who is joining to the channel */
3498   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3499   if (!tmp) {
3500     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3501                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3502                                           0);
3503     goto out;
3504   }
3505   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3506   if (!client_id) {
3507     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3508                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3509                                           0);
3510     goto out;
3511   }
3512
3513   /* Get cipher, hmac name and auth payload */
3514   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3515   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3516   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3517
3518   /* See if the channel exists */
3519   channel = silc_idlist_find_channel_by_name(server->local_list, 
3520                                              channel_name, NULL);
3521
3522   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3523     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3524     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3525
3526     if (!channel || 
3527         (channel->disabled && server->server_type != SILC_ROUTER)) {
3528       /* Channel not found */
3529
3530       /* If we are standalone server we don't have a router, we just create 
3531          the channel by ourselves. */
3532       if (server->standalone) {
3533         channel = silc_server_create_new_channel(server, server->id, cipher, 
3534                                                  hmac, channel_name, TRUE);
3535         if (!channel) {
3536           silc_server_command_send_status_reply(
3537                                          cmd, SILC_COMMAND_JOIN,
3538                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3539                                          0);
3540           goto out;
3541         }
3542         
3543         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3544         created = TRUE;
3545         create_key = FALSE;
3546         
3547       } else {
3548
3549         /* The channel does not exist on our server. If we are normal server 
3550            we will send JOIN command to our router which will handle the
3551            joining procedure (either creates the channel if it doesn't exist 
3552            or joins the client to it). */
3553         if (server->server_type != SILC_ROUTER) {
3554           SilcBuffer tmpbuf;
3555           SilcUInt16 old_ident;
3556
3557           /* If this is pending command callback then we've resolved
3558              it and it didn't work, return since we've notified the
3559              client already in the command reply callback. */
3560           if (cmd->pending)
3561             goto out;
3562           
3563           old_ident = silc_command_get_ident(cmd->payload);
3564           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3565           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3566           
3567           /* Send JOIN command to our router */
3568           silc_server_packet_send(server, (SilcSocketConnection)
3569                                   server->router->connection,
3570                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3571                                   tmpbuf->data, tmpbuf->len, TRUE);
3572           
3573           /* Reprocess this packet after received reply from router */
3574           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3575                                       silc_command_get_ident(cmd->payload),
3576                                       silc_server_command_join,
3577                                       silc_server_command_dup(cmd));
3578           cmd->pending = TRUE;
3579           silc_command_set_ident(cmd->payload, old_ident);
3580           silc_buffer_free(tmpbuf);
3581           goto out;
3582         }
3583         
3584         /* We are router and the channel does not seem exist so we will check
3585            our global list as well for the channel. */
3586         channel = silc_idlist_find_channel_by_name(server->global_list, 
3587                                                    channel_name, NULL);
3588         if (!channel) {
3589           /* Channel really does not exist, create it */
3590           channel = silc_server_create_new_channel(server, server->id, cipher, 
3591                                                    hmac, channel_name, TRUE);
3592           if (!channel) {
3593             silc_server_command_send_status_reply(
3594                                        cmd, SILC_COMMAND_JOIN,
3595                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3596             goto out;
3597           }
3598
3599           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3600           created = TRUE;
3601           create_key = FALSE;
3602         }
3603       }
3604     }
3605   } else {
3606     if (!channel) {
3607       /* Channel not found */
3608
3609       /* If the command came from router and we are normal server then
3610          something went wrong with the joining as the channel was not found.
3611          We can't do anything else but ignore this. */
3612       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3613           server->server_type != SILC_ROUTER)
3614         goto out;
3615       
3616       /* We are router and the channel does not seem exist so we will check
3617          our global list as well for the channel. */
3618       channel = silc_idlist_find_channel_by_name(server->global_list, 
3619                                                  channel_name, NULL);
3620       if (!channel) {
3621         /* Channel really does not exist, create it */
3622         channel = silc_server_create_new_channel(server, server->id, cipher, 
3623                                                  hmac, channel_name, TRUE);
3624         if (!channel) {
3625           silc_server_command_send_status_reply(
3626                                        cmd, SILC_COMMAND_JOIN,
3627                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3628           goto out;
3629         }
3630
3631         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3632         created = TRUE;
3633         create_key = FALSE;
3634       }
3635     }
3636   }
3637
3638   /* Check whether the channel was created by our router */
3639   if (cmd->pending && context2) {
3640     SilcServerCommandReplyContext reply = context2;
3641
3642     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3643       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3644       SILC_GET32_MSB(created, tmp);
3645       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3646         create_key = FALSE;     /* Router returned the key already */
3647     }
3648
3649     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3650         !silc_hash_table_count(channel->user_list))
3651       created = TRUE;
3652   }
3653
3654   /* If the channel does not have global users and is also empty the client
3655      will be the channel founder and operator. */
3656   if (!channel->disabled &&
3657       !channel->global_users && !silc_hash_table_count(channel->user_list))
3658     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3659
3660   /* Join to the channel */
3661   silc_server_command_join_channel(server, cmd, channel, client_id,
3662                                    created, create_key, umode,
3663                                    auth, auth_len);
3664
3665   silc_free(client_id);
3666
3667  out:
3668   silc_server_command_free(cmd);
3669 }
3670
3671 /* Server side of command MOTD. Sends server's current "message of the
3672    day" to the client. */
3673
3674 SILC_SERVER_CMD_FUNC(motd)
3675 {
3676   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3677   SilcServer server = cmd->server;
3678   SilcBuffer packet, idp;
3679   char *motd, *dest_server;
3680   SilcUInt32 motd_len;
3681   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3682   
3683   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3684
3685   /* Get server name */
3686   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3687   if (!dest_server) {
3688     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3689                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3690     goto out;
3691   }
3692
3693   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3694     /* Send our MOTD */
3695
3696     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3697
3698     if (server->config && server->config->server_info &&
3699         server->config->server_info->motd_file) {
3700       /* Send motd */
3701       motd = silc_file_readfile(server->config->server_info->motd_file, &motd_len);
3702       if (!motd)
3703         goto out;
3704       
3705       motd[motd_len] = 0;
3706       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3707                                                     SILC_STATUS_OK, 0, 
3708                                                     ident, 2,
3709                                                     2, idp, idp->len,
3710                                                     3, motd, motd_len);
3711     } else {
3712       /* No motd */
3713       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3714                                                     SILC_STATUS_OK, 0, 
3715                                                     ident, 1,
3716                                                     2, idp, idp->len);
3717     }
3718
3719     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3720                             packet->data, packet->len, FALSE);
3721     silc_buffer_free(packet);
3722     silc_buffer_free(idp);
3723   } else {
3724     SilcServerEntry entry;
3725
3726     /* Check whether we have this server cached */
3727     entry = silc_idlist_find_server_by_name(server->global_list,
3728                                             dest_server, TRUE, NULL);
3729     if (!entry) {
3730       entry = silc_idlist_find_server_by_name(server->local_list,
3731                                               dest_server, TRUE, NULL);
3732     }
3733
3734     if (server->server_type != SILC_SERVER && !cmd->pending && 
3735         entry && !entry->motd) {
3736       /* Send to the server */
3737       SilcBuffer tmpbuf;
3738       SilcUInt16 old_ident;
3739
3740       old_ident = silc_command_get_ident(cmd->payload);
3741       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3742       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3743
3744       silc_server_packet_send(server, entry->connection,
3745                               SILC_PACKET_COMMAND, cmd->packet->flags,
3746                               tmpbuf->data, tmpbuf->len, TRUE);
3747
3748       /* Reprocess this packet after received reply from router */
3749       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3750                                   silc_command_get_ident(cmd->payload),
3751                                   silc_server_command_motd,
3752                                   silc_server_command_dup(cmd));
3753       cmd->pending = TRUE;
3754       silc_command_set_ident(cmd->payload, old_ident);
3755       silc_buffer_free(tmpbuf);
3756       goto out;
3757     }
3758
3759     if (!entry && !cmd->pending && !server->standalone) {
3760       /* Send to the primary router */
3761       SilcBuffer tmpbuf;
3762       SilcUInt16 old_ident;
3763
3764       old_ident = silc_command_get_ident(cmd->payload);
3765       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3766       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3767
3768       silc_server_packet_send(server, server->router->connection,
3769                               SILC_PACKET_COMMAND, cmd->packet->flags,
3770                               tmpbuf->data, tmpbuf->len, TRUE);
3771
3772       /* Reprocess this packet after received reply from router */
3773       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3774                                   silc_command_get_ident(cmd->payload),
3775                                   silc_server_command_motd,
3776                                   silc_server_command_dup(cmd));
3777       cmd->pending = TRUE;
3778       silc_command_set_ident(cmd->payload, old_ident);
3779       silc_buffer_free(tmpbuf);
3780       goto out;
3781     }
3782
3783     if (!entry) {
3784       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3785                                             SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3786       goto out;
3787     }
3788
3789     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3790     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3791                                                   SILC_STATUS_OK, 0, ident, 2,
3792                                                   2, idp, idp->len,
3793                                                   3, entry->motd,
3794                                                   entry->motd ? 
3795                                                   strlen(entry->motd) : 0);
3796     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3797                             packet->data, packet->len, FALSE);
3798     silc_buffer_free(packet);
3799     silc_buffer_free(idp);
3800   }
3801
3802  out:
3803   silc_server_command_free(cmd);
3804 }
3805
3806 /* Server side of command UMODE. Client can use this command to set/unset
3807    user mode. Client actually cannot set itself to be as server/router
3808    operator so this can be used only to unset the modes. */
3809
3810 SILC_SERVER_CMD_FUNC(umode)
3811 {
3812   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3813   SilcServer server = cmd->server;
3814   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3815   SilcBuffer packet;
3816   unsigned char *tmp_mask, m[4];
3817   SilcUInt32 mask = 0;
3818   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3819   bool set_mask = FALSE;
3820
3821   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3822     goto out;
3823
3824   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3825
3826   /* Get the client's mode mask */
3827   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3828   if (tmp_mask) {
3829     SILC_GET32_MSB(mask, tmp_mask);
3830     set_mask = TRUE;
3831   }
3832
3833   if (set_mask) {
3834     /* Check that mode changing is allowed. */
3835     if (!silc_server_check_umode_rights(server, client, mask)) {
3836       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3837                                             SILC_STATUS_ERR_PERM_DENIED, 0);
3838       goto out;
3839     }
3840
3841     /* Anonymous mode cannot be set by client */
3842     if (mask & SILC_UMODE_ANONYMOUS) {
3843       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3844         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3845                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3846         goto out;
3847       }
3848     } else {
3849       if (client->mode & SILC_UMODE_ANONYMOUS) {
3850         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3851                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3852         goto out;
3853       }
3854     }
3855
3856     /* Change the mode */
3857     client->mode = mask;
3858
3859     /* Send UMODE change to primary router */
3860     if (!server->standalone)
3861       silc_server_send_notify_umode(server, server->router->connection, TRUE,
3862                                     client->id, client->mode);
3863
3864     /* Check if anyone is watching this nickname */
3865     if (server->server_type == SILC_ROUTER)
3866       silc_server_check_watcher_list(server, client, NULL,
3867                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
3868   }
3869
3870   /* Send command reply to sender */
3871   SILC_PUT32_MSB(client->mode, m);
3872   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3873                                                 SILC_STATUS_OK, 0, ident, 1,
3874                                                 2, m, sizeof(m));
3875   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3876                           packet->data, packet->len, FALSE);
3877   silc_buffer_free(packet);
3878
3879  out:
3880   silc_server_command_free(cmd);
3881 }
3882
3883 /* Server side command of CMODE. Changes channel mode */
3884
3885 SILC_SERVER_CMD_FUNC(cmode)
3886 {
3887   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3888   SilcServer server = cmd->server;
3889   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3890   SilcIDListData idata = (SilcIDListData)client;
3891   SilcChannelID *channel_id = NULL;
3892   SilcChannelEntry channel;
3893   SilcChannelClientEntry chl;
3894   SilcBuffer packet, cidp;
3895   unsigned char *tmp, *tmp_id, *tmp_mask;
3896   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3897   SilcUInt32 mode_mask = 0, tmp_len, tmp_len2;
3898   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3899   bool set_mask = FALSE;
3900   SilcPublicKey founder_key = NULL;
3901   unsigned char *fkey = NULL;
3902   SilcUInt32 fkey_len = 0;
3903
3904   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3905
3906   /* Get Channel ID */
3907   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3908   if (!tmp_id) {
3909     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3910                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3911     goto out;
3912   }
3913   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3914   if (!channel_id) {
3915     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3916                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3917     goto out;
3918   }
3919
3920   /* Get the channel mode mask */
3921   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3922   if (tmp_mask) {
3923     SILC_GET32_MSB(mode_mask, tmp_mask);
3924     set_mask = TRUE;
3925   }
3926
3927   /* Get channel entry */
3928   channel = silc_idlist_find_channel_by_id(server->local_list, 
3929                                            channel_id, NULL);
3930   if (!channel) {
3931     channel = silc_idlist_find_channel_by_id(server->global_list, 
3932                                              channel_id, NULL);
3933     if (!channel) {
3934       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3935                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3936                                             0);
3937       goto out;
3938     }
3939   }
3940
3941   /* Check whether this client is on the channel */
3942   if (!silc_server_client_on_channel(client, channel, &chl)) {
3943     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3944                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
3945     goto out;
3946   }
3947
3948   /* Check that client has rights to change any requested channel modes */
3949   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
3950                                                   mode_mask)) {
3951     silc_server_command_send_status_reply(
3952                              cmd, SILC_COMMAND_CMODE,
3953                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
3954                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
3955                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
3956     goto out;
3957   }
3958
3959   /* If mode mask was not sent as argument then merely return the current
3960      mode mask to the sender. */
3961   if (!set_mask) {
3962     unsigned char m[4];
3963     SILC_PUT32_MSB(channel->mode, m);
3964     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3965                                                   SILC_STATUS_OK, 0, ident, 2,
3966                                                   2, tmp_id, tmp_len2,
3967                                                   3, m, sizeof(m));
3968     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3969                             packet->data, packet->len, FALSE);
3970     silc_buffer_free(packet);
3971     goto out;
3972   }
3973
3974   /*
3975    * Check the modes. Modes that requires nothing special operation are
3976    * not checked here.
3977    */
3978
3979   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3980     /* Channel uses private keys to protect traffic. Client(s) has set the
3981        key locally they want to use, server does not know that key. */
3982     /* Nothing interesting to do here */
3983   } else {
3984     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3985       /* The mode is removed and we need to generate and distribute
3986          new channel key. Clients are not using private channel keys
3987          anymore after this. */
3988       
3989       /* Re-generate channel key */
3990       if (!silc_server_create_channel_key(server, channel, 0))
3991         goto out;
3992         
3993       /* Send the channel key. This sends it to our local clients and if
3994          we are normal server to our router as well. */
3995       silc_server_send_channel_key(server, NULL, channel, 
3996                                    server->server_type == SILC_ROUTER ? 
3997                                    FALSE : !server->standalone);
3998         
3999       cipher = channel->channel_key->cipher->name;
4000       hmac = (char *)silc_hmac_get_name(channel->hmac);
4001     }
4002   }
4003
4004   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4005     /* User limit is set on channel */
4006     SilcUInt32 user_limit;
4007       
4008     /* Get user limit */
4009     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4010     if (!tmp) {
4011       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4012         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4013                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4014         goto out;
4015       }
4016     } else {
4017       SILC_GET32_MSB(user_limit, tmp);
4018       channel->user_limit = user_limit;
4019     }
4020   } else {
4021     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4022       /* User limit mode is unset. Remove user limit */
4023       channel->user_limit = 0;
4024   }
4025
4026   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4027     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4028       /* Passphrase has been set to channel */
4029       
4030       /* Get the passphrase */
4031       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4032       if (!tmp) {
4033         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4034                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4035         goto out;
4036       }
4037
4038       /* Save the passphrase */
4039       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4040     }
4041   } else {
4042     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4043       /* Passphrase mode is unset. remove the passphrase */
4044       silc_free(channel->passphrase);
4045       channel->passphrase = NULL;
4046     }
4047   }
4048
4049   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4050     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4051       /* Cipher to use protect the traffic */
4052       SilcCipher newkey, oldkey;
4053
4054       /* Get cipher */
4055       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4056       if (!cipher) {
4057         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4058                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4059         goto out;
4060       }
4061
4062       /* Delete old cipher and allocate the new one */
4063       if (!silc_cipher_alloc(cipher, &newkey)) {
4064         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4065                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4066         goto out;
4067       }
4068
4069       oldkey = channel->channel_key;
4070       channel->channel_key = newkey;
4071
4072       /* Re-generate channel key */
4073       if (!silc_server_create_channel_key(server, channel, 0)) {
4074         /* We don't have new key, revert to old one */
4075         channel->channel_key = oldkey;
4076         goto out;
4077       }
4078
4079       /* Remove old channel key for good */
4080       silc_cipher_free(oldkey);
4081
4082       /* Send the channel key. This sends it to our local clients and if
4083          we are normal server to our router as well. */
4084       silc_server_send_channel_key(server, NULL, channel, 
4085                                    server->server_type == SILC_ROUTER ? 
4086                                    FALSE : !server->standalone);
4087     }
4088   } else {
4089     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4090       /* Cipher mode is unset. Remove the cipher and revert back to 
4091          default cipher */
4092       SilcCipher newkey, oldkey;
4093       cipher = channel->cipher;
4094
4095       /* Delete old cipher and allocate default one */
4096       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4097         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4098                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4099         goto out;
4100       }
4101
4102       oldkey = channel->channel_key;
4103       channel->channel_key = newkey;
4104
4105       /* Re-generate channel key */
4106       if (!silc_server_create_channel_key(server, channel, 0)) {
4107         /* We don't have new key, revert to old one */
4108         channel->channel_key = oldkey;
4109         goto out;
4110       }
4111       
4112       /* Remove old channel key for good */
4113       silc_cipher_free(oldkey);
4114
4115       /* Send the channel key. This sends it to our local clients and if
4116          we are normal server to our router as well. */
4117       silc_server_send_channel_key(server, NULL, channel, 
4118                                    server->server_type == SILC_ROUTER ? 
4119                                    FALSE : !server->standalone);
4120     }
4121   }
4122
4123   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4124     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4125       /* HMAC to use protect the traffic */
4126       unsigned char hash[32];
4127       SilcHmac newhmac;
4128
4129       /* Get hmac */
4130       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4131       if (!hmac) {
4132         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4133                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4134         goto out;
4135       }
4136
4137       /* Delete old hmac and allocate the new one */
4138       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4139         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4140                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4141         goto out;
4142       }
4143
4144       silc_hmac_free(channel->hmac);
4145       channel->hmac = newhmac;
4146
4147       /* Set the HMAC key out of current channel key. The client must do
4148          this locally. */
4149       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4150                      channel->key_len / 8, hash);
4151       silc_hmac_set_key(channel->hmac, hash, 
4152                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4153       memset(hash, 0, sizeof(hash));
4154     }
4155   } else {
4156     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4157       /* Hmac mode is unset. Remove the hmac and revert back to 
4158          default hmac */
4159       SilcHmac newhmac;
4160       unsigned char hash[32];
4161       hmac = channel->hmac_name;
4162
4163       /* Delete old hmac and allocate default one */
4164       silc_hmac_free(channel->hmac);
4165       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4166         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4167                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4168         goto out;
4169       }
4170
4171       silc_hmac_free(channel->hmac);
4172       channel->hmac = newhmac;
4173
4174       /* Set the HMAC key out of current channel key. The client must do
4175          this locally. */
4176       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4177                      channel->key_len / 8, 
4178                      hash);
4179       silc_hmac_set_key(channel->hmac, hash, 
4180                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4181       memset(hash, 0, sizeof(hash));
4182     }
4183   }
4184
4185   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4186     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4187       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4188         /* Set the founder authentication */
4189         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4190         if (!tmp) {
4191           silc_server_command_send_status_reply(
4192                                      cmd, SILC_COMMAND_CMODE,
4193                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4194           goto out;
4195         }
4196
4197         /* Verify the payload before setting the mode */
4198         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
4199                                    idata->public_key, 0, server->sha1hash,
4200                                    client->id, SILC_ID_CLIENT)) {
4201           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4202                                                 SILC_STATUS_ERR_AUTH_FAILED,
4203                                                 0);
4204           goto out;
4205         }
4206
4207         /* Save the public key */
4208         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4209         if (!channel->founder_key) {
4210           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4211                                                 SILC_STATUS_ERR_AUTH_FAILED,
4212                                                 0);
4213           goto out;
4214         }
4215
4216         founder_key = channel->founder_key;
4217         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4218         if (!fkey) {
4219           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4220                                                 SILC_STATUS_ERR_AUTH_FAILED,
4221                                                 0);
4222           goto out;
4223         }
4224       }
4225     }
4226   } else {
4227     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4228       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4229         if (channel->founder_key)
4230           silc_pkcs_public_key_free(channel->founder_key);
4231         channel->founder_key = NULL;
4232       }
4233     }
4234   }
4235
4236   /* Finally, set the mode */
4237   channel->mode = mode_mask;
4238
4239   /* Send CMODE_CHANGE notify. */
4240   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4241   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4242                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4243                                      cidp->data, cidp->len, 
4244                                      tmp_mask, 4,
4245                                      cipher, cipher ? strlen(cipher) : 0,
4246                                      hmac, hmac ? strlen(hmac) : 0,
4247                                      passphrase, passphrase ? 
4248                                      strlen(passphrase) : 0,
4249                                      fkey, fkey_len);
4250
4251   /* Set CMODE notify type to network */
4252   if (!server->standalone)
4253     silc_server_send_notify_cmode(server, server->router->connection,
4254                                   server->server_type == SILC_ROUTER ? 
4255                                   TRUE : FALSE, channel,
4256                                   mode_mask, client->id, SILC_ID_CLIENT,
4257                                   cipher, hmac, passphrase, founder_key);
4258
4259   /* Send command reply to sender */
4260   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4261                                                 SILC_STATUS_OK, 0, ident, 2,
4262                                                 2, tmp_id, tmp_len2,
4263                                                 3, tmp_mask, 4);
4264   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4265                           packet->data, packet->len, FALSE);
4266     
4267   silc_buffer_free(packet);
4268   silc_buffer_free(cidp);
4269
4270  out:
4271   silc_free(fkey);
4272   silc_free(channel_id);
4273   silc_server_command_free(cmd);
4274 }
4275
4276 /* Server side of CUMODE command. Changes client's mode on a channel. */
4277
4278 SILC_SERVER_CMD_FUNC(cumode)
4279 {
4280   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4281   SilcServer server = cmd->server;
4282   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4283   SilcIDListData idata = (SilcIDListData)client;
4284   SilcChannelID *channel_id;
4285   SilcClientID *client_id;
4286   SilcChannelEntry channel;
4287   SilcClientEntry target_client;
4288   SilcChannelClientEntry chl;
4289   SilcBuffer packet, idp;
4290   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4291   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4292   int notify = FALSE;
4293   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4294   SilcPublicKey founder_key = NULL;
4295   unsigned char *fkey = NULL;
4296   SilcUInt32 fkey_len = 0;
4297
4298   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4299
4300   /* Get Channel ID */
4301   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4302   if (!tmp_ch_id) {
4303     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4304                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4305     goto out;
4306   }
4307   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4308   if (!channel_id) {
4309     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4310                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4311     goto out;
4312   }
4313
4314   /* Get channel entry */
4315   channel = silc_idlist_find_channel_by_id(server->local_list, 
4316                                            channel_id, NULL);
4317   if (!channel) {
4318     channel = silc_idlist_find_channel_by_id(server->global_list, 
4319                                              channel_id, NULL);
4320     if (!channel) {
4321       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4322                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4323                                             0);
4324       goto out;
4325     }
4326   }
4327
4328   /* Check whether sender is on the channel */
4329   if (!silc_server_client_on_channel(client, channel, &chl)) {
4330     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4331                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4332     goto out;
4333   }
4334   sender_mask = chl->mode;
4335   
4336   /* Get the target client's channel mode mask */
4337   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4338   if (!tmp_mask) {
4339     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4340                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4341                                           0);
4342     goto out;
4343   }
4344   SILC_GET32_MSB(target_mask, tmp_mask);
4345
4346   /* Get target Client ID */
4347   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4348   if (!tmp_id) {
4349     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4350                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4351     goto out;
4352   }
4353   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4354   if (!client_id) {
4355     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4356                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4357     goto out;
4358   }
4359
4360   /* Get target client's entry */
4361   target_client = silc_idlist_find_client_by_id(server->local_list, 
4362                                                 client_id, TRUE, NULL);
4363   if (!target_client) {
4364     target_client = silc_idlist_find_client_by_id(server->global_list, 
4365                                                   client_id, TRUE, NULL);
4366   }
4367
4368   if (target_client != client &&
4369       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4370       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4371     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4372                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4373     goto out;
4374   }
4375
4376   /* Check whether target client is on the channel */
4377   if (target_client != client) {
4378     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4379       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4380                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4381       goto out;
4382     }
4383   }
4384
4385   /* 
4386    * Change the mode 
4387    */
4388
4389   /* If the target client is founder, no one else can change their mode
4390      but themselves. */
4391   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4392     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4393                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4394                                           0);
4395     goto out;
4396   }
4397
4398   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4399     if (target_client != client) {
4400       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4401                                             SILC_STATUS_ERR_NOT_YOU, 0);
4402       goto out;
4403     }
4404
4405     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4406       /* The client tries to claim the founder rights. */
4407       unsigned char *tmp_auth;
4408       SilcUInt32 tmp_auth_len;
4409
4410       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4411           !channel->founder_key || !idata->public_key ||
4412           !silc_pkcs_public_key_compare(channel->founder_key, 
4413                                         idata->public_key)) {
4414         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4415                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4416         goto out;
4417       }
4418
4419       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4420       if (!tmp_auth) {
4421         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4423         goto out;
4424       }
4425
4426       /* Verify the authentication payload */
4427       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4428                                  channel->founder_key, 0, server->sha1hash,
4429                                  client->id, SILC_ID_CLIENT)) {
4430         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4431                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4432         goto out;
4433       }
4434
4435       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4436       notify = TRUE;
4437       founder_key = channel->founder_key;
4438       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4439       if (!fkey) {
4440         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4441                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4442         goto out;
4443       }
4444     }
4445   } else {
4446     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4447       if (target_client == client) {
4448         /* Remove channel founder rights from itself */
4449         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4450         notify = TRUE;
4451       } else {
4452         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4453                                               SILC_STATUS_ERR_NOT_YOU, 0);
4454         goto out;
4455       }
4456     }
4457   }
4458
4459   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4460     /* Promote to operator */
4461     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4462       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4463           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4464         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4465                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4466                                               0);
4467         goto out;
4468       }
4469
4470       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4471       notify = TRUE;
4472     }
4473   } else {
4474     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4475       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4476           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4477         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4478                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4479                                               0);
4480         goto out;
4481       }
4482
4483       /* Demote to normal user */
4484       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4485       notify = TRUE;
4486     }
4487   }
4488
4489   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4490     if (target_client != client) {
4491       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4492                                             SILC_STATUS_ERR_NOT_YOU, 0);
4493       goto out;
4494     }
4495
4496     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4497       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4498       notify = TRUE;
4499     }
4500   } else {
4501     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4502       if (target_client != client) {
4503         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4504                                               SILC_STATUS_ERR_NOT_YOU, 0);
4505         goto out;
4506       }
4507
4508       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4509       notify = TRUE;
4510     }
4511   }
4512
4513   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4514     if (target_client != client) {
4515       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4516                                             SILC_STATUS_ERR_NOT_YOU, 0);
4517       goto out;
4518     }
4519
4520     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4521       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4522       notify = TRUE;
4523     }
4524   } else {
4525     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4526       if (target_client != client) {
4527         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4528                                               SILC_STATUS_ERR_NOT_YOU, 0);
4529         goto out;
4530       }
4531
4532       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4533       notify = TRUE;
4534     }
4535   }
4536
4537   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4538     if (target_client != client) {
4539       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4540                                             SILC_STATUS_ERR_NOT_YOU, 0);
4541       goto out;
4542     }
4543
4544     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4545       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4546       notify = TRUE;
4547     }
4548   } else {
4549     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4550       if (target_client != client) {
4551         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4552                                               SILC_STATUS_ERR_NOT_YOU, 0);
4553         goto out;
4554       }
4555
4556       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4557       notify = TRUE;
4558     }
4559   }
4560
4561   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4562   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4563
4564   /* Send notify to channel, notify only if mode was actually changed. */
4565   if (notify) {
4566     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4567                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4568                                        idp->data, idp->len,
4569                                        tmp_mask, 4, 
4570                                        tmp_id, tmp_len,
4571                                        fkey, fkey_len);
4572
4573     /* Set CUMODE notify type to network */
4574     if (!server->standalone)
4575       silc_server_send_notify_cumode(server, server->router->connection,
4576                                      server->server_type == SILC_ROUTER ? 
4577                                      TRUE : FALSE, channel,
4578                                      target_mask, client->id, 
4579                                      SILC_ID_CLIENT,
4580                                      target_client->id, founder_key);
4581   }
4582
4583   /* Send command reply to sender */
4584   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4585                                                 SILC_STATUS_OK, 0, ident, 3,
4586                                                 2, tmp_mask, 4,
4587                                                 3, tmp_ch_id, tmp_ch_len,
4588                                                 4, tmp_id, tmp_len);
4589   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4590                           packet->data, packet->len, FALSE);
4591     
4592   silc_buffer_free(packet);
4593   silc_free(channel_id);
4594   silc_free(client_id);
4595   silc_buffer_free(idp);
4596
4597  out:
4598   silc_free(fkey);
4599   silc_server_command_free(cmd);
4600 }
4601
4602 /* Server side of KICK command. Kicks client out of channel. */
4603
4604 SILC_SERVER_CMD_FUNC(kick)
4605 {
4606   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4607   SilcServer server = cmd->server;
4608   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4609   SilcClientEntry target_client;
4610   SilcChannelID *channel_id;
4611   SilcClientID *client_id;
4612   SilcChannelEntry channel;
4613   SilcChannelClientEntry chl;
4614   SilcBuffer idp;
4615   SilcUInt32 tmp_len, target_idp_len;
4616   unsigned char *tmp, *comment, *target_idp;
4617
4618   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4619
4620   /* Get Channel ID */
4621   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4622   if (!tmp) {
4623     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4624                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4625     goto out;
4626   }
4627   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4628   if (!channel_id) {
4629     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4630                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4631     goto out;
4632   }
4633
4634   /* Get channel entry */
4635   channel = silc_idlist_find_channel_by_id(server->local_list, 
4636                                            channel_id, NULL);
4637   if (!channel) {
4638     channel = silc_idlist_find_channel_by_id(server->local_list, 
4639                                              channel_id, NULL);
4640     if (!channel) {
4641       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4642                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4643                                             0);
4644       goto out;
4645     }
4646   }
4647
4648   /* Check whether sender is on the channel */
4649   if (!silc_server_client_on_channel(client, channel, &chl)) {
4650     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4651                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4652     goto out;
4653   }
4654
4655   /* Check that the kicker is channel operator or channel founder */
4656   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4657       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4658     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4659                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4660     goto out;
4661   }
4662   
4663   /* Get target Client ID */
4664   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4665   if (!target_idp) {
4666     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4667                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4668     goto out;
4669   }
4670   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4671   if (!client_id) {
4672     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4673                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4674     goto out;
4675   }
4676
4677   /* Get target client's entry */
4678   target_client = silc_idlist_find_client_by_id(server->local_list, 
4679                                                 client_id, TRUE, NULL);
4680   if (!target_client) {
4681     target_client = silc_idlist_find_client_by_id(server->global_list, 
4682                                                   client_id, TRUE, NULL);
4683   }
4684
4685   /* Check whether target client is on the channel */
4686   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4688                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4689                                           0);
4690     goto out;
4691   }
4692
4693   /* Check that the target client is not channel founder. Channel founder
4694      cannot be kicked from the channel. */
4695   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4696     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4697                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4698                                           0);
4699     goto out;
4700   }
4701   
4702   /* Get comment */
4703   tmp_len = 0;
4704   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4705   if (tmp_len > 128)
4706     comment = NULL;
4707
4708   /* Send command reply to sender */
4709   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4710                                         SILC_STATUS_OK, 0);
4711
4712   /* Send KICKED notify to local clients on the channel */
4713   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4714   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4715                                      SILC_NOTIFY_TYPE_KICKED, 3,
4716                                      target_idp, target_idp_len,
4717                                      comment, comment ? strlen(comment) : 0,
4718                                      idp->data, idp->len);
4719   silc_buffer_free(idp);
4720
4721   /* Remove the client from the channel. If the channel does not exist
4722      after removing the client then the client kicked itself off the channel
4723      and we don't have to send anything after that. */
4724   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4725                                            target_client, FALSE))
4726     goto out;
4727
4728   /* Send KICKED notify to primary route */
4729   if (!server->standalone)
4730     silc_server_send_notify_kicked(server, server->router->connection,
4731                                    server->server_type == SILC_ROUTER ?
4732                                    TRUE : FALSE, channel,
4733                                    target_client->id, client->id, comment);
4734
4735   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4736     /* Re-generate channel key */
4737     if (!silc_server_create_channel_key(server, channel, 0))
4738       goto out;
4739     
4740     /* Send the channel key to the channel. The key of course is not sent
4741        to the client who was kicked off the channel. */
4742     silc_server_send_channel_key(server, target_client->connection, channel, 
4743                                  server->server_type == SILC_ROUTER ? 
4744                                  FALSE : !server->standalone);
4745   }
4746
4747  out:
4748   silc_server_command_free(cmd);
4749 }
4750
4751 /* Server side of OPER command. Client uses this comand to obtain server
4752    operator privileges to this server/router. */
4753
4754 SILC_SERVER_CMD_FUNC(oper)
4755 {
4756   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4757   SilcServer server = cmd->server;
4758   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4759   unsigned char *username, *auth;
4760   SilcUInt32 tmp_len;
4761   SilcServerConfigAdmin *admin;
4762   SilcIDListData idata = (SilcIDListData)client;
4763   bool result = FALSE;
4764   SilcPublicKey cached_key;
4765
4766   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4767
4768   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4769     goto out;
4770
4771   /* Get the username */
4772   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4773   if (!username) {
4774     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4775                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4776                                           0);
4777     goto out;
4778   }
4779
4780   /* Get the admin configuration */
4781   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4782                                         username, client->nickname);
4783   if (!admin) {
4784     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4785                                           username, client->nickname);
4786     if (!admin) {
4787       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4788                                             SILC_STATUS_ERR_AUTH_FAILED,
4789                                             0);
4790       goto out;
4791     }
4792   }
4793
4794   /* Get the authentication payload */
4795   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4796   if (!auth) {
4797     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4798                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4799                                           0);
4800     goto out;
4801   }
4802
4803   /* Verify the authentication data. If both passphrase and public key
4804      is set then try both of them. */
4805   if (admin->passphrase)
4806     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4807                                    admin->passphrase, admin->passphrase_len,
4808                                    idata->hash, client->id, SILC_ID_CLIENT);
4809   if (!result && admin->publickeys) {
4810     cached_key = silc_server_get_public_key(server, admin->publickeys);
4811     if (!cached_key)
4812       goto out;
4813     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4814                                    cached_key, 0, idata->hash, 
4815                                    client->id, SILC_ID_CLIENT);
4816   }
4817   if (!result) {
4818     /* Authentication failed */
4819     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4820                                           SILC_STATUS_ERR_AUTH_FAILED,
4821                                           0);
4822     goto out;
4823   }
4824
4825   /* Client is now server operator */
4826   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4827
4828   /* Update statistics */
4829   if (client->connection)
4830     server->stat.my_server_ops++;
4831   if (server->server_type == SILC_ROUTER)
4832     server->stat.server_ops++;
4833
4834   /* Send UMODE change to primary router */
4835   if (!server->standalone)
4836     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4837                                   client->id, client->mode);
4838
4839   /* Check if anyone is watching this nickname */
4840   if (server->server_type == SILC_ROUTER)
4841     silc_server_check_watcher_list(server, client, NULL,
4842                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4843
4844   /* Send reply to the sender */
4845   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4846                                         SILC_STATUS_OK, 0);
4847
4848  out:
4849   silc_server_command_free(cmd);
4850 }
4851
4852 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4853 {
4854   QuitInternal q = (QuitInternal)context;
4855   SilcClientEntry client = (SilcClientEntry)q->sock->user_data;
4856
4857   /* If there is pending outgoing data for the client then purge it
4858      to the network before closing connection. */
4859   silc_server_packet_queue_purge(q->server, q->sock);
4860
4861   /* Close the connection on our side */
4862   client->router = NULL;
4863   client->connection = NULL;
4864   q->sock->user_data = NULL;
4865   silc_server_close_connection(q->server, q->sock);
4866
4867   silc_free(q);
4868 }
4869
4870 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4871 {
4872   QuitInternal q = (QuitInternal)context;
4873   SilcClientEntry client = (SilcClientEntry)q->sock;
4874
4875   SILC_LOG_DEBUG(("Start"));
4876
4877   if (client->mode & SILC_UMODE_DETACHED)
4878     silc_server_free_client_data(q->server, NULL, client, TRUE,
4879                                  "Detach timeout");
4880   silc_free(q);
4881 }
4882
4883 /* Server side of DETACH command.  Detached the client from the network
4884    by closing the connection but preserving the session. */
4885
4886 SILC_SERVER_CMD_FUNC(detach)
4887 {
4888   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4889   SilcServer server = cmd->server;
4890   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4891   QuitInternal q;
4892
4893   if (server->config->detach_disabled) {
4894     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4895                                           SILC_STATUS_ERR_UNKNOWN_COMMAND,
4896                                           0);
4897     goto out;
4898   }
4899
4900   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4901     goto out;
4902
4903   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
4904
4905   /* Send the user mode notify to notify that client is detached */
4906   client->mode |= SILC_UMODE_DETACHED;
4907   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
4908   client->last_command = 0;
4909   client->fast_command = 0;
4910   if (!server->standalone)
4911     silc_server_send_notify_umode(server, server->router->connection,
4912                                   server->server_type == SILC_SERVER ?
4913                                   FALSE : TRUE, client->id, client->mode);
4914
4915   /* Check if anyone is watching this nickname */
4916   if (server->server_type == SILC_ROUTER)
4917     silc_server_check_watcher_list(server, client, NULL,
4918                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4919
4920   q = silc_calloc(1, sizeof(*q));
4921   q->server = server;
4922   q->sock = cmd->sock;
4923   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
4924                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4925
4926   if (server->config->detach_timeout) {
4927     q = silc_calloc(1, sizeof(*q));
4928     q->server = server;
4929     q->sock = (void *)client;
4930     silc_schedule_task_add(server->schedule, 0, 
4931                            silc_server_command_detach_timeout,
4932                            q, server->config->detach_timeout * 60,
4933                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
4934   }
4935
4936   /* Send reply to the sender */
4937   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
4938                                         SILC_STATUS_OK, 0);
4939
4940  out:
4941   silc_server_command_free(cmd);
4942 }
4943
4944 /* Server side of WATCH command. */
4945
4946 SILC_SERVER_CMD_FUNC(watch)
4947 {
4948   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4949   SilcServer server = cmd->server;
4950   char *add_nick, *del_nick;
4951   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
4952   char nick[128 + 1];
4953   unsigned char hash[16], *tmp;
4954   SilcClientEntry client;
4955   SilcClientID *client_id = NULL;
4956
4957   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
4958
4959   if (server->server_type == SILC_SERVER && !server->standalone) {
4960     if (!cmd->pending) {
4961       /* Send the command to router */
4962       SilcBuffer tmpbuf;
4963       SilcUInt16 old_ident;
4964
4965       old_ident = silc_command_get_ident(cmd->payload);
4966       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
4967       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4968
4969       silc_server_packet_send(server, server->router->connection,
4970                               SILC_PACKET_COMMAND, cmd->packet->flags,
4971                               tmpbuf->data, tmpbuf->len, TRUE);
4972
4973       /* Reprocess this packet after received reply from router */
4974       silc_server_command_pending(server, SILC_COMMAND_WATCH,
4975                                   silc_command_get_ident(cmd->payload),
4976                                   silc_server_command_watch,
4977                                   silc_server_command_dup(cmd));
4978       cmd->pending = TRUE;
4979       silc_command_set_ident(cmd->payload, old_ident);
4980       silc_buffer_free(tmpbuf);
4981     } else if (context2) {
4982       /* Received reply from router, just send same data to the client. */
4983       SilcServerCommandReplyContext reply = context2;
4984       SilcStatus status;
4985       silc_command_get_status(reply->payload, &status, NULL);
4986       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
4987                                             0);
4988     }
4989
4990     goto out;
4991   }
4992
4993   /* We are router and keep the watch list for local cell */
4994
4995   /* Get the client ID */
4996   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4997   if (!tmp) {
4998     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
4999                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5000                                           0);
5001     goto out;
5002   }
5003   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5004   if (!client_id) {
5005     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5006                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5007                                           0);
5008     goto out;
5009   }
5010
5011   /* Get the client entry which must be in local list */
5012   client = silc_idlist_find_client_by_id(server->local_list, 
5013                                          client_id, TRUE, NULL);
5014   if (!client) {
5015     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5016                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5017                                           0);
5018     goto out;
5019   }
5020
5021   /* Take nickname */
5022   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5023   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5024   if (!add_nick && !del_nick) {
5025     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5026                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5027                                           0);
5028     goto out;
5029   }
5030
5031   if (add_nick && add_nick_len > 128)
5032     add_nick[128] = '\0';
5033   if (del_nick && del_nick_len > 128)
5034     del_nick[128] = '\0';
5035
5036   memset(nick, 0, sizeof(nick));
5037
5038   /* Add new nickname to be watched in our cell */
5039   if (add_nick) {
5040     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5041       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5042                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5043       goto out;
5044     }
5045
5046     /* Hash the nick, we have the hash saved, not nicks because we can
5047        do one to one mapping to the nick from Client ID hash this way. */
5048     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5049     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5050
5051     /* Check whether this client is already watching this nickname */
5052     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
5053                                         client, NULL)) {
5054       /* Nickname is alredy being watched for this client */
5055       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5056                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
5057                                             0);
5058       goto out;
5059     }
5060
5061     /* Get the nickname from the watcher list and use the same key in
5062        new entries as well.  If key doesn't exist then create it. */
5063     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5064       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5065
5066     /* Add the client to the watcher list with the specified nickname hash. */
5067     silc_hash_table_add(server->watcher_list, tmp, client);
5068   }
5069
5070   /* Delete nickname from watch list */
5071   if (del_nick) {
5072     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5073       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5074                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5075       goto out;
5076     }
5077
5078     /* Hash the nick, we have the hash saved, not nicks because we can
5079        do one to one mapping to the nick from Client ID hash this way. */
5080     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5081     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5082
5083     /* Check that this client is watching for this nickname */
5084     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
5085                                          client, (void **)&tmp)) {
5086       /* Nickname is alredy being watched for this client */
5087       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5088                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5089       goto out;
5090     }
5091
5092     /* Delete the nickname from the watcher list. */
5093     silc_hash_table_del_by_context(server->watcher_list, hash, client);
5094
5095     /* Now check whether there still exists entries with this key, if not
5096        then free the key to not leak memory. */
5097     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5098       silc_free(tmp);
5099   }
5100
5101   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5102                                         SILC_STATUS_OK, 0);
5103
5104  out:
5105   silc_free(client_id);
5106   silc_server_command_free(cmd);
5107 }
5108
5109 /* Server side of SILCOPER command. Client uses this comand to obtain router
5110    operator privileges to this router. */
5111
5112 SILC_SERVER_CMD_FUNC(silcoper)
5113 {
5114   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5115   SilcServer server = cmd->server;
5116   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5117   unsigned char *username, *auth;
5118   SilcUInt32 tmp_len;
5119   SilcServerConfigAdmin *admin;
5120   SilcIDListData idata = (SilcIDListData)client;
5121   bool result = FALSE;
5122   SilcPublicKey cached_key;
5123
5124   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5125
5126   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5127     goto out;
5128
5129   if (server->server_type != SILC_ROUTER) {
5130     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5131                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5132     goto out;
5133   }
5134
5135   /* Get the username */
5136   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5137   if (!username) {
5138     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5139                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5140                                           0);
5141     goto out;
5142   }
5143
5144   /* Get the admin configuration */
5145   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5146                                         username, client->nickname);
5147   if (!admin) {
5148     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5149                                           username, client->nickname);
5150     if (!admin) {
5151       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5152                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
5153       goto out;
5154     }
5155   }
5156
5157   /* Get the authentication payload */
5158   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5159   if (!auth) {
5160     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5161                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5162                                           0);
5163     goto out;
5164   }
5165
5166   /* Verify the authentication data. If both passphrase and public key
5167      is set then try both of them. */
5168   if (admin->passphrase)
5169     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5170                                    admin->passphrase, admin->passphrase_len,
5171                                    idata->hash, client->id, SILC_ID_CLIENT);
5172   if (!result && admin->publickeys) {
5173     cached_key = silc_server_get_public_key(server, admin->publickeys);
5174     if (!cached_key)
5175       goto out;
5176     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5177                                    cached_key, 0, idata->hash, 
5178                                    client->id, SILC_ID_CLIENT);
5179   }
5180   if (!result) {
5181     /* Authentication failed */
5182     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5183                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5184     goto out;
5185   }
5186
5187   /* Client is now router operator */
5188   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5189
5190   /* Update statistics */
5191   if (client->connection)
5192     server->stat.my_router_ops++;
5193   if (server->server_type == SILC_ROUTER)
5194     server->stat.router_ops++;
5195
5196   /* Send UMODE change to primary router */
5197   if (!server->standalone)
5198     silc_server_send_notify_umode(server, server->router->connection, TRUE,
5199                                   client->id, client->mode);
5200
5201   /* Check if anyone is watching this nickname */
5202   if (server->server_type == SILC_ROUTER)
5203     silc_server_check_watcher_list(server, client, NULL,
5204                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5205
5206   /* Send reply to the sender */
5207   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5208                                         SILC_STATUS_OK, 0);
5209
5210  out:
5211   silc_server_command_free(cmd);
5212 }
5213
5214 /* Server side of command BAN. This is used to manage the ban list of the
5215    channel. To add clients and remove clients from the ban list. */
5216
5217 SILC_SERVER_CMD_FUNC(ban)
5218 {
5219   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5220   SilcServer server = cmd->server;
5221   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5222   SilcBuffer packet;
5223   SilcChannelEntry channel;
5224   SilcChannelClientEntry chl;
5225   SilcChannelID *channel_id = NULL;
5226   unsigned char *id, *add, *del;
5227   SilcUInt32 id_len, tmp_len;
5228   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5229
5230   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5231     goto out;
5232
5233   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5234
5235   /* Get Channel ID */
5236   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5237   if (id) {
5238     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5239     if (!channel_id) {
5240       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5241                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5242       goto out;
5243     }
5244   }
5245
5246   /* Get channel entry. The server must know about the channel since the
5247      client is expected to be on the channel. */
5248   channel = silc_idlist_find_channel_by_id(server->local_list, 
5249                                            channel_id, NULL);
5250   if (!channel) {
5251     channel = silc_idlist_find_channel_by_id(server->global_list, 
5252                                              channel_id, NULL);
5253     if (!channel) {
5254       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5255                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5256                                             0);
5257       goto out;
5258     }
5259   }
5260
5261   /* Check whether this client is on the channel */
5262   if (!silc_server_client_on_channel(client, channel, &chl)) {
5263     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5264                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5265     goto out;
5266   }
5267
5268   /* The client must be at least channel operator. */
5269   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5270     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5271                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5272     goto out;
5273   }
5274
5275   /* Get the new ban and add it to the ban list */
5276   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5277   if (add) {
5278     if (!channel->ban_list)
5279       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5280     else
5281       channel->ban_list = silc_realloc(channel->ban_list, 
5282                                        sizeof(*channel->ban_list) * 
5283                                        (tmp_len + 
5284                                         strlen(channel->ban_list) + 2));
5285     if (add[tmp_len - 1] == ',')
5286       add[tmp_len - 1] = '\0';
5287
5288     strncat(channel->ban_list, add, tmp_len);
5289     strncat(channel->ban_list, ",", 1);
5290   }
5291
5292   /* Get the ban to be removed and remove it from the list */
5293   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5294   if (del && channel->ban_list) {
5295     char *start, *end, *n;
5296
5297     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5298       silc_free(channel->ban_list);
5299       channel->ban_list = NULL;
5300     } else {
5301       start = strstr(channel->ban_list, del);
5302       if (start && strlen(start) >= tmp_len) {
5303         end = start + tmp_len;
5304         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5305         strncat(n, channel->ban_list, start - channel->ban_list);
5306         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
5307                              end) - 1);
5308         silc_free(channel->ban_list);
5309         channel->ban_list = n;
5310       }
5311     }
5312   }
5313
5314   /* Send the BAN notify type to our primary router. */
5315   if (!server->standalone && (add || del))
5316     silc_server_send_notify_ban(server, server->router->connection,
5317                                 server->server_type == SILC_ROUTER ?
5318                                 TRUE : FALSE, channel, add, del);
5319
5320   /* Send the reply back to the client */
5321   packet = 
5322     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5323                                          SILC_STATUS_OK, 0, ident, 2,
5324                                          2, id, id_len,
5325                                          3, channel->ban_list, 
5326                                          channel->ban_list ? 
5327                                          strlen(channel->ban_list) -1 : 0);
5328   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5329                           packet->data, packet->len, FALSE);
5330     
5331   silc_buffer_free(packet);
5332
5333  out:
5334   silc_free(channel_id);
5335   silc_server_command_free(cmd);
5336 }
5337
5338 /* Server side command of LEAVE. Removes client from a channel. */
5339
5340 SILC_SERVER_CMD_FUNC(leave)
5341 {
5342   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5343   SilcServer server = cmd->server;
5344   SilcSocketConnection sock = cmd->sock;
5345   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5346   SilcChannelID *id = NULL;
5347   SilcChannelEntry channel;
5348   SilcUInt32 len;
5349   unsigned char *tmp;
5350
5351   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5352
5353   /* Get Channel ID */
5354   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5355   if (!tmp) {
5356     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5357                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5358     goto out;
5359   }
5360   id = silc_id_payload_parse_id(tmp, len, NULL);
5361   if (!id) {
5362     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5363                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5364     goto out;
5365   }
5366
5367   /* Get channel entry */
5368   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5369   if (!channel) {
5370     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5371     if (!channel) {
5372       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5373                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5374                                             0);
5375       goto out;
5376     }
5377   }
5378
5379   /* Check whether this client is on the channel */
5380   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5381     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5382                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5383     goto out;
5384   }
5385
5386   /* Notify routers that they should remove this client from their list
5387      of clients on the channel. Send LEAVE notify type. */
5388   if (!server->standalone)
5389     silc_server_send_notify_leave(server, server->router->connection,
5390                                   server->server_type == SILC_ROUTER ?
5391                                   TRUE : FALSE, channel, id_entry->id);
5392
5393   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5394                                        SILC_STATUS_OK, 0, 2, tmp, len);
5395
5396   /* Remove client from channel */
5397   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5398                                            TRUE))
5399     /* If the channel does not exist anymore we won't send anything */
5400     goto out;
5401
5402   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5403     /* Re-generate channel key */
5404     if (!silc_server_create_channel_key(server, channel, 0))
5405       goto out;
5406
5407     /* Send the channel key */
5408     silc_server_send_channel_key(server, NULL, channel, 
5409                                  server->server_type == SILC_ROUTER ? 
5410                                  FALSE : !server->standalone);
5411   }
5412
5413  out:
5414   silc_free(id);
5415   silc_server_command_free(cmd);
5416 }
5417
5418 /* Server side of command USERS. Resolves clients and their USERS currently
5419    joined on the requested channel. The list of Client ID's and their modes
5420    on the channel is sent back. */
5421
5422 SILC_SERVER_CMD_FUNC(users)
5423 {
5424   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5425   SilcServer server = cmd->server;
5426   SilcChannelEntry channel;
5427   SilcChannelID *id = NULL;
5428   SilcBuffer packet, idp;
5429   unsigned char *channel_id;
5430   SilcUInt32 channel_id_len;
5431   SilcBuffer client_id_list;
5432   SilcBuffer client_mode_list;
5433   unsigned char lc[4];
5434   SilcUInt32 list_count = 0;
5435   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5436   char *channel_name;
5437
5438   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5439
5440   /* Get Channel ID */
5441   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5442
5443   /* Get channel name */
5444   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5445
5446   if (!channel_id && !channel_name) {
5447     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5448                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5449     goto out;
5450   }
5451
5452   if (channel_id) {
5453     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5454     if (!id) {
5455       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5456                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5457       goto out;
5458     }
5459   }
5460
5461   /* If we are server and we don't know about this channel we will send
5462      the command to our router. If we know about the channel then we also
5463      have the list of users already. */
5464   if (id)
5465     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5466   else
5467     channel = silc_idlist_find_channel_by_name(server->local_list, 
5468                                                channel_name, NULL);
5469
5470   if (!channel || channel->disabled || !channel->users_resolved) {
5471     if (server->server_type != SILC_ROUTER && !server->standalone &&
5472         !cmd->pending) {
5473       SilcBuffer tmpbuf;
5474       
5475       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5476       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5477       
5478       /* Send USERS command */
5479       silc_server_packet_send(server, server->router->connection,
5480                               SILC_PACKET_COMMAND, cmd->packet->flags,
5481                               tmpbuf->data, tmpbuf->len, TRUE);
5482       
5483       /* Reprocess this packet after received reply */
5484       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5485                                   silc_command_get_ident(cmd->payload),
5486                                   silc_server_command_users,
5487                                   silc_server_command_dup(cmd));
5488       cmd->pending = TRUE;
5489       silc_command_set_ident(cmd->payload, ident);
5490       silc_buffer_free(tmpbuf);
5491       silc_free(id);
5492       goto out;
5493     }
5494
5495     /* Check the global list as well. */
5496     if (id)
5497       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5498     else
5499       channel = silc_idlist_find_channel_by_name(server->global_list, 
5500                                                  channel_name, NULL);
5501     if (!channel) {
5502       /* Channel really does not exist */
5503       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5504                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5505                                             0);
5506       goto out;
5507     }
5508   }
5509
5510   /* If the channel is private or secret do not send anything, unless the
5511      user requesting this command is on the channel or is server */
5512   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5513     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5514         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5515                                           NULL)) {
5516       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5517                                             SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5518       goto out;
5519     }
5520   }
5521
5522   /* Get the users list */
5523   silc_server_get_users_on_channel(server, channel, &client_id_list,
5524                                    &client_mode_list, &list_count);
5525
5526   /* List count */
5527   SILC_PUT32_MSB(list_count, lc);
5528
5529   /* Send reply */
5530   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5531   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5532                                                 SILC_STATUS_OK, 0, ident, 4,
5533                                                 2, idp->data, idp->len,
5534                                                 3, lc, 4,
5535                                                 4, client_id_list->data,
5536                                                 client_id_list->len,
5537                                                 5, client_mode_list->data,
5538                                                 client_mode_list->len);
5539   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5540                           packet->data, packet->len, FALSE);
5541     
5542   silc_buffer_free(idp);
5543   silc_buffer_free(packet);
5544   silc_buffer_free(client_id_list);
5545   silc_buffer_free(client_mode_list);
5546   silc_free(id);
5547
5548  out:
5549   silc_server_command_free(cmd);
5550 }
5551
5552 /* Server side of command GETKEY. This fetches the client's public key
5553    from the server where to the client is connected. */
5554
5555 SILC_SERVER_CMD_FUNC(getkey)
5556 {
5557   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5558   SilcServer server = cmd->server;
5559   SilcBuffer packet;
5560   SilcClientEntry client;
5561   SilcServerEntry server_entry;
5562   SilcClientID *client_id = NULL;
5563   SilcServerID *server_id = NULL;
5564   SilcIDPayload idp = NULL;
5565   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5566   unsigned char *tmp, *pkdata;
5567   SilcUInt32 tmp_len, pklen;
5568   SilcBuffer pk = NULL;
5569   SilcIdType id_type;
5570   SilcPublicKey public_key;
5571
5572   SILC_LOG_DEBUG(("Start"));
5573
5574   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5575   if (!tmp) {
5576     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5577                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5578                                           0);
5579     goto out;
5580   }
5581   idp = silc_id_payload_parse(tmp, tmp_len);
5582   if (!idp) {
5583     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5584                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5585                                           0);
5586     goto out;
5587   }
5588
5589   id_type = silc_id_payload_get_type(idp);
5590   if (id_type == SILC_ID_CLIENT) {
5591     client_id = silc_id_payload_get_id(idp);
5592
5593     /* If the client is not found from local list there is no chance it
5594        would be locally connected client so send the command further. */
5595     client = silc_idlist_find_client_by_id(server->local_list, 
5596                                            client_id, TRUE, NULL);
5597     if (!client)
5598       client = silc_idlist_find_client_by_id(server->global_list, 
5599                                              client_id, TRUE, NULL);
5600     
5601     if ((!client && !cmd->pending && !server->standalone) ||
5602         (client && !client->connection && !cmd->pending &&
5603          !(client->mode & SILC_UMODE_DETACHED)) ||
5604         (client && !client->data.public_key && !cmd->pending)) {
5605       SilcBuffer tmpbuf;
5606       SilcUInt16 old_ident;
5607       SilcSocketConnection dest_sock;
5608       
5609       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5610                                                client_id, NULL, NULL);
5611       if (!dest_sock)
5612         goto out;
5613       
5614       old_ident = silc_command_get_ident(cmd->payload);
5615       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5616       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5617       
5618       silc_server_packet_send(server, dest_sock,
5619                               SILC_PACKET_COMMAND, cmd->packet->flags,
5620                               tmpbuf->data, tmpbuf->len, TRUE);
5621       
5622       /* Reprocess this packet after received reply from router */
5623       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5624                                   silc_command_get_ident(cmd->payload),
5625                                   silc_server_command_getkey,
5626                                   silc_server_command_dup(cmd));
5627       cmd->pending = TRUE;
5628       silc_command_set_ident(cmd->payload, old_ident);
5629       silc_buffer_free(tmpbuf);
5630       goto out;
5631     }
5632
5633     if (!client) {
5634       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5635                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5636                                             0);
5637       goto out;
5638     }
5639
5640     /* The client is locally connected, just get the public key and
5641        send it back. If they key does not exist then do not send it, 
5642        send just OK reply */
5643     public_key = client->data.public_key;
5644     if (!public_key) {
5645       pkdata = NULL;
5646       pklen = 0;
5647     } else {
5648       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5649       pk = silc_buffer_alloc(4 + tmp_len);
5650       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5651       silc_buffer_format(pk,
5652                          SILC_STR_UI_SHORT(tmp_len),
5653                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5654                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5655                          SILC_STR_END);
5656       silc_free(tmp);
5657       pkdata = pk->data;
5658       pklen = pk->len;
5659     }
5660   } else if (id_type == SILC_ID_SERVER) {
5661     server_id = silc_id_payload_get_id(idp);
5662
5663     /* If the server is not found from local list there is no chance it
5664        would be locally connected server so send the command further. */
5665     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5666                                                  server_id, TRUE, NULL);
5667     if (!server_entry)
5668       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5669                                                    server_id, TRUE, NULL);
5670     
5671     if (server_entry != server->id_entry &&
5672         ((!server_entry && !cmd->pending && !server->standalone) ||
5673          (server_entry && !server_entry->connection && !cmd->pending &&
5674           !server->standalone) ||
5675          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5676           !server->standalone))) {
5677       SilcBuffer tmpbuf;
5678       SilcUInt16 old_ident;
5679       
5680       old_ident = silc_command_get_ident(cmd->payload);
5681       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5682       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5683       
5684       silc_server_packet_send(server, server->router->connection,
5685                               SILC_PACKET_COMMAND, cmd->packet->flags,
5686                               tmpbuf->data, tmpbuf->len, TRUE);
5687       
5688       /* Reprocess this packet after received reply from router */
5689       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5690                                   silc_command_get_ident(cmd->payload),
5691                                   silc_server_command_getkey,
5692                                   silc_server_command_dup(cmd));
5693       cmd->pending = TRUE;
5694       silc_command_set_ident(cmd->payload, old_ident);
5695       silc_buffer_free(tmpbuf);
5696       goto out;
5697     }
5698
5699     if (!server_entry) {
5700       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5701                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5702                                             0);
5703       goto out;
5704     }
5705
5706     /* If they key does not exist then do not send it, send just OK reply */
5707     public_key = (!server_entry->data.public_key ? 
5708                   (server_entry == server->id_entry ? server->public_key :
5709                    NULL) : server_entry->data.public_key);
5710     if (!public_key) {
5711       pkdata = NULL;
5712       pklen = 0;
5713     } else {
5714       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5715       pk = silc_buffer_alloc(4 + tmp_len);
5716       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5717       silc_buffer_format(pk,
5718                          SILC_STR_UI_SHORT(tmp_len),
5719                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5720                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5721                          SILC_STR_END);
5722       silc_free(tmp);
5723       pkdata = pk->data;
5724       pklen = pk->len;
5725     }
5726   } else {
5727     goto out;
5728   }
5729
5730   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5731   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5732                                                 SILC_STATUS_OK, 0, ident, 
5733                                                 pkdata ? 2 : 1,
5734                                                 2, tmp, tmp_len,
5735                                                 3, pkdata, pklen);
5736   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5737                           packet->data, packet->len, FALSE);
5738   silc_buffer_free(packet);
5739
5740   if (pk)
5741     silc_buffer_free(pk);
5742
5743  out:
5744   if (idp)
5745     silc_id_payload_free(idp);
5746   silc_free(client_id);
5747   silc_free(server_id);
5748   silc_server_command_free(cmd);
5749 }
5750
5751
5752 /* Private range commands, specific to this implementation */
5753
5754 /* Server side command of CONNECT. Connects us to the specified remote
5755    server or router. */
5756
5757 SILC_SERVER_CMD_FUNC(connect)
5758 {
5759   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5760   SilcServer server = cmd->server;
5761   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5762   unsigned char *tmp, *host;
5763   SilcUInt32 tmp_len;
5764   SilcUInt32 port = SILC_PORT;
5765
5766   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5767
5768   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5769     goto out;
5770
5771   /* Check whether client has the permissions. */
5772   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5773       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5774     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5775                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5776     goto out;
5777   }
5778
5779   if (server->server_type == SILC_ROUTER && 
5780       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5781     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5782                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5783     goto out;
5784   }
5785
5786   /* Get the remote server */
5787   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5788   if (!host) {
5789     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5790                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5791                                           0);
5792     goto out;
5793   }
5794
5795   /* Get port */
5796   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5797   if (tmp)
5798     SILC_GET32_MSB(port, tmp);
5799
5800   /* Create the connection. It is done with timeout and is async. */
5801   silc_server_create_connection(server, host, port);
5802
5803   /* Send reply to the sender */
5804   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5805                                         SILC_STATUS_OK, 0);
5806
5807  out:
5808   silc_server_command_free(cmd);
5809 }
5810
5811 /* Server side command of CLOSE. Closes connection to a specified server. */
5812  
5813 SILC_SERVER_CMD_FUNC(close)
5814 {
5815   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5816   SilcServer server = cmd->server;
5817   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5818   SilcServerEntry server_entry;
5819   SilcSocketConnection sock;
5820   unsigned char *tmp;
5821   SilcUInt32 tmp_len;
5822   unsigned char *name;
5823   SilcUInt32 port = SILC_PORT;
5824
5825   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5826
5827   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5828     goto out;
5829
5830   /* Check whether client has the permissions. */
5831   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5832       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5833     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5834                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5835                                           0);
5836     goto out;
5837   }
5838
5839   /* Get the remote server */
5840   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5841   if (!name) {
5842     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5843                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5844                                           0);
5845     goto out;
5846   }
5847
5848   /* Get port */
5849   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5850   if (tmp)
5851     SILC_GET32_MSB(port, tmp);
5852
5853   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5854                                                  name, port, FALSE, NULL);
5855   if (!server_entry)
5856     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5857                                                    name, port, FALSE, NULL);
5858   if (!server_entry) {
5859     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5860                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
5861     goto out;
5862   }
5863
5864   /* Send reply to the sender */
5865   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5866                                         SILC_STATUS_OK, 0);
5867
5868   /* Close the connection to the server */
5869   sock = (SilcSocketConnection)server_entry->connection;
5870
5871   /* If we shutdown primary router connection manually then don't trigger
5872      any reconnect or backup router connections, by setting the router
5873      to NULL here. */
5874   if (server->router == server_entry) {
5875     server->id_entry->router = NULL;
5876     server->router = NULL;
5877     server->standalone = TRUE;
5878   }
5879   silc_server_free_sock_user_data(server, sock, NULL);
5880   silc_server_close_connection(server, sock);
5881   
5882  out:
5883   silc_server_command_free(cmd);
5884 }
5885
5886 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
5887    active connections. */
5888  
5889 SILC_SERVER_CMD_FUNC(shutdown)
5890 {
5891   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5892   SilcServer server = cmd->server;
5893   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5894
5895   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
5896
5897   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5898     goto out;
5899
5900   /* Check whether client has the permission. */
5901   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5902       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5903     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5904                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5905                                           0);
5906     goto out;
5907   }
5908
5909   /* Send reply to the sender */
5910   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
5911                                         SILC_STATUS_OK, 0);
5912
5913   /* Then, gracefully, or not, bring the server down. */
5914   silc_server_stop(server);
5915   exit(0);
5916
5917  out:
5918   silc_server_command_free(cmd);
5919 }