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