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