Added KILL command.
[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                                      unsigned int arg_type,
38                                      unsigned char *arg,
39                                      unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
41
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
44 {
45   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(connect, CONNECT, 
56                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65   SILC_SERVER_CMD(restart, RESTART, 
66                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67   SILC_SERVER_CMD(close, CLOSE,
68                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
70                   SILC_CF_OPER),
71   SILC_SERVER_CMD(silcoper, SILCOPER,
72                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75
76   { NULL, 0 },
77 };
78
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max)            \
80 do {                                                                          \
81   unsigned int _argc = silc_argument_get_arg_num(cmd->args);                  \
82                                                                               \
83   SILC_LOG_DEBUG(("Start"));                                                  \
84                                                                               \
85   if (_argc < min) {                                                          \
86     silc_server_command_send_status_reply(cmd, command,                       \
87                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88     silc_server_command_free(cmd);                                            \
89     return;                                                                   \
90   }                                                                           \
91   if (_argc > max) {                                                          \
92     silc_server_command_send_status_reply(cmd, command,                       \
93                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
94     silc_server_command_free(cmd);                                            \
95     return;                                                                   \
96   }                                                                           \
97 } while(0)
98
99 /* Returns TRUE if the connection is registered. Unregistered connections
100    usually cannot send commands hence the check. */
101
102 static int silc_server_is_registered(SilcServer server,
103                                      SilcSocketConnection sock,
104                                      SilcServerCommandContext cmd,
105                                      SilcCommand command)
106 {
107   SilcIDListData idata = (SilcIDListData)sock->user_data;
108   if (idata->registered)
109     return TRUE;
110
111   silc_server_command_send_status_reply(cmd, command,
112                                         SILC_STATUS_ERR_NOT_REGISTERED);
113   silc_server_command_free(cmd);
114   return FALSE;
115 }
116
117 /* Internal context to hold data when executed command with timeout. */
118 typedef struct {
119   SilcServerCommandContext ctx;
120   SilcServerCommand *cmd;
121 } *SilcServerCommandTimeout;
122
123 /* Timeout callback to process commands with timeout for client. Client's
124    commands are always executed with timeout. */
125
126 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
127 {
128   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
129   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
130
131   /* Update access time */
132   client->last_command = time(NULL);
133
134   if (!(timeout->cmd->flags & SILC_CF_REG))
135     timeout->cmd->cb(timeout->ctx);
136   else if (silc_server_is_registered(timeout->ctx->server, 
137                                      timeout->ctx->sock, 
138                                      timeout->ctx, 
139                                      timeout->cmd->cmd))
140     timeout->cmd->cb(timeout->ctx);
141
142   silc_free(timeout);
143 }
144
145 /* Processes received command packet. */
146
147 void silc_server_command_process(SilcServer server,
148                                  SilcSocketConnection sock,
149                                  SilcPacketContext *packet)
150 {
151   SilcServerCommandContext ctx;
152   SilcServerCommand *cmd;
153
154   /* Allocate command context. This must be free'd by the
155      command routine receiving it. */
156   ctx = silc_server_command_alloc();
157   ctx->server = server;
158   ctx->sock = silc_socket_dup(sock);
159   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
160   
161   /* Parse the command payload in the packet */
162   ctx->payload = silc_command_payload_parse(packet->buffer);
163   if (!ctx->payload) {
164     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
165     silc_buffer_free(packet->buffer);
166     silc_packet_context_free(packet);
167     silc_socket_free(ctx->sock);
168     silc_free(ctx);
169     return;
170   }
171   ctx->args = silc_command_get_args(ctx->payload);
172   
173   /* Get the command */
174   for (cmd = silc_command_list; cmd->cb; cmd++)
175     if (cmd->cmd == silc_command_get(ctx->payload))
176       break;
177
178   if (cmd == NULL) {
179     SILC_LOG_ERROR(("Unknown command, packet dropped"));
180     silc_server_command_free(ctx);
181     return;
182   }
183
184   /* Execute client's commands always with timeout.  Normally they are
185      executed with zero (0) timeout but if client is sending command more
186      frequently than once in 2 seconds, then the timeout may be 0 to 2
187      seconds. */
188   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
189     SilcClientEntry client = (SilcClientEntry)sock->user_data;
190     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
191     int fast;
192
193     timeout->ctx = ctx;
194     timeout->cmd = cmd;
195
196     if (client->last_command && (time(NULL) - client->last_command) < 2) {
197       client->fast_command++;
198       fast = FALSE;
199     } else {
200       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
201                               client->fast_command--);
202       fast = TRUE;
203     }
204
205     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
206                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
207       silc_task_register(server->timeout_queue, sock->sock, 
208                          silc_server_command_process_timeout,
209                          (void *)timeout, 
210                          2 - (time(NULL) - client->last_command), 0,
211                          SILC_TASK_TIMEOUT,
212                          SILC_TASK_PRI_NORMAL);
213     else
214       silc_task_register(server->timeout_queue, sock->sock, 
215                          silc_server_command_process_timeout,
216                          (void *)timeout, 
217                          0, 1,
218                          SILC_TASK_TIMEOUT,
219                          SILC_TASK_PRI_NORMAL);
220     return;
221   }
222
223   /* Execute for server */
224
225   if (!(cmd->flags & SILC_CF_REG))
226     cmd->cb(ctx);
227   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
228     cmd->cb(ctx);
229 }
230
231 /* Allocate Command Context */
232
233 SilcServerCommandContext silc_server_command_alloc()
234 {
235   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
236   ctx->users++;
237   return ctx;
238 }
239
240 /* Free's the command context allocated before executing the command */
241
242 void silc_server_command_free(SilcServerCommandContext ctx)
243 {
244   ctx->users--;
245   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
246                   ctx->users));
247   if (ctx->users < 1) {
248     if (ctx->payload)
249       silc_command_free_payload(ctx->payload);
250     if (ctx->packet)
251       silc_packet_context_free(ctx->packet);
252     if (ctx->sock)
253       silc_socket_free(ctx->sock); /* Decrease reference counter */
254     silc_free(ctx);
255   }
256 }
257
258 /* Duplicate Command Context by adding reference counter. The context won't
259    be free'd untill it hits zero. */
260
261 SilcServerCommandContext 
262 silc_server_command_dup(SilcServerCommandContext ctx)
263 {
264   ctx->users++;
265   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
266                   ctx->users));
267   return ctx;
268 }
269
270 /* Add new pending command to be executed when reply to a command has been
271    received. The `reply_cmd' is the command that will call the `callback'
272    with `context' when reply has been received.  If `ident' is non-zero
273    the `callback' will be executed when received reply with command
274    identifier `ident'. */
275
276 void silc_server_command_pending(SilcServer server,
277                                  SilcCommand reply_cmd,
278                                  unsigned short ident,
279                                  SilcServerPendingDestructor destructor,
280                                  SilcCommandCb callback,
281                                  void *context)
282 {
283   SilcServerCommandPending *reply;
284
285   reply = silc_calloc(1, sizeof(*reply));
286   reply->reply_cmd = reply_cmd;
287   reply->ident = ident;
288   reply->context = context;
289   reply->callback = callback;
290   reply->destructor = destructor;
291   silc_dlist_add(server->pending_commands, reply);
292 }
293
294 /* Deletes pending command by reply command type. */
295
296 void silc_server_command_pending_del(SilcServer server,
297                                      SilcCommand reply_cmd,
298                                      unsigned short ident)
299 {
300   SilcServerCommandPending *r;
301
302   silc_dlist_start(server->pending_commands);
303   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
304     if (r->reply_cmd == reply_cmd && r->ident == ident) {
305       silc_dlist_del(server->pending_commands, r);
306       break;
307     }
308   }
309 }
310
311 /* Checks for pending commands and marks callbacks to be called from
312    the command reply function. Returns TRUE if there were pending command. */
313
314 int silc_server_command_pending_check(SilcServer server,
315                                       SilcServerCommandReplyContext ctx,
316                                       SilcCommand command, 
317                                       unsigned short ident)
318 {
319   SilcServerCommandPending *r;
320
321   silc_dlist_start(server->pending_commands);
322   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
323     if (r->reply_cmd == command && r->ident == ident) {
324       ctx->context = r->context;
325       ctx->callback = r->callback;
326       ctx->destructor = r->destructor;
327       ctx->ident = ident;
328       return TRUE;
329     }
330   }
331
332   return FALSE;
333 }
334
335 /* Destructor function for pending callbacks. This is called when using
336    pending commands to free the context given for the pending command. */
337
338 static void silc_server_command_destructor(void *context)
339 {
340   silc_server_command_free((SilcServerCommandContext)context);
341 }
342
343 /* Sends simple status message as command reply packet */
344
345 static void 
346 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
347                                       SilcCommand command,
348                                       SilcCommandStatus status)
349 {
350   SilcBuffer buffer;
351
352   SILC_LOG_DEBUG(("Sending command status %d", status));
353
354   buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
355   silc_server_packet_send(cmd->server, cmd->sock,
356                           SILC_PACKET_COMMAND_REPLY, 0, 
357                           buffer->data, buffer->len, FALSE);
358   silc_buffer_free(buffer);
359 }
360
361 /* Sends command status reply with one extra argument. The argument
362    type must be sent as argument. */
363
364 static void 
365 silc_server_command_send_status_data(SilcServerCommandContext cmd,
366                                      SilcCommand command,
367                                      SilcCommandStatus status,
368                                      unsigned int arg_type,
369                                      unsigned char *arg,
370                                      unsigned int arg_len)
371 {
372   SilcBuffer buffer;
373
374   SILC_LOG_DEBUG(("Sending command status %d", status));
375
376   buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
377                                                 arg_type, arg, arg_len);
378   silc_server_packet_send(cmd->server, cmd->sock,
379                           SILC_PACKET_COMMAND_REPLY, 0, 
380                           buffer->data, buffer->len, FALSE);
381   silc_buffer_free(buffer);
382 }
383
384 /******************************************************************************
385
386                               WHOIS Functions
387
388 ******************************************************************************/
389
390 static int
391 silc_server_command_whois_parse(SilcServerCommandContext cmd,
392                                 SilcClientID ***client_id,
393                                 unsigned int *client_id_count,
394                                 char **nickname,
395                                 char **server_name,
396                                 int *count,
397                                 SilcCommand command)
398 {
399   unsigned char *tmp;
400   unsigned int len;
401   unsigned int argc = silc_argument_get_arg_num(cmd->args);
402   int i, k;
403
404   /* If client ID is in the command it must be used instead of nickname */
405   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
406   if (!tmp) {
407     /* No ID, get the nickname@server string and parse it. */
408     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
409     if (tmp) {
410       if (strchr(tmp, '@')) {
411         len = strcspn(tmp, "@");
412         *nickname = silc_calloc(len + 1, sizeof(char));
413         memcpy(*nickname, tmp, len);
414         *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
415         memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
416       } else {
417         *nickname = strdup(tmp);
418       }
419     } else {
420       silc_server_command_send_status_reply(cmd, command,
421                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
422       return FALSE;
423     }
424   } else {
425     /* Command includes ID, we must use that.  Also check whether the command
426        has more than one ID set - take them all. */
427
428     *client_id = silc_calloc(1, sizeof(**client_id));
429     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
430     if ((*client_id)[0] == NULL) {
431       silc_free(*client_id);
432       return FALSE;
433     }
434     *client_id_count = 1;
435
436     /* Take all ID's from the command packet */
437     if (argc > 1) {
438       for (k = 1, i = 1; i < argc; i++) {
439         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
440         if (tmp) {
441           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
442                                     (*client_id_count + 1));
443           (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
444           if ((*client_id)[k] == NULL) {
445             /* Cleanup all and fail */
446             for (i = 0; i < *client_id_count; i++)
447               silc_free((*client_id)[i]);
448             silc_free(*client_id);
449             return FALSE;
450           }
451           (*client_id_count)++;
452           k++;
453         }
454       }
455     }
456
457     /* Command includes ID, use that */
458   }
459
460   /* Get the max count of reply messages allowed */
461   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
462   if (tmp)
463     *count = atoi(tmp);
464   else
465     *count = 0;
466
467   return TRUE;
468 }
469
470 static char
471 silc_server_command_whois_check(SilcServerCommandContext cmd,
472                                 SilcClientEntry *clients,
473                                 unsigned int clients_count)
474 {
475   SilcServer server = cmd->server;
476   int i;
477   SilcClientEntry entry;
478
479   for (i = 0; i < clients_count; i++) {
480     entry = clients[i];
481
482     if (!entry->nickname || !entry->username) {
483       SilcBuffer tmpbuf;
484       unsigned short old_ident;
485
486       if (!entry->router)
487         continue;
488       
489       old_ident = silc_command_get_ident(cmd->payload);
490       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
491       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
492
493       /* Send WHOIS command */
494       silc_server_packet_send(server, entry->router->connection,
495                               SILC_PACKET_COMMAND, cmd->packet->flags,
496                               tmpbuf->data, tmpbuf->len, TRUE);
497       
498       /* Reprocess this packet after received reply */
499       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
500                                   silc_command_get_ident(cmd->payload),
501                                   silc_server_command_destructor,
502                                   silc_server_command_whois, 
503                                   silc_server_command_dup(cmd));
504       cmd->pending = TRUE;
505       
506       silc_command_set_ident(cmd->payload, old_ident);
507
508       silc_buffer_free(tmpbuf);
509       return FALSE;
510     }
511   }
512
513   return TRUE;
514 }
515
516 static void
517 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
518                                      SilcClientEntry *clients,
519                                      unsigned int clients_count)
520 {
521   SilcServer server = cmd->server;
522   char *tmp;
523   int i, count = 0, len;
524   SilcBuffer packet, idp;
525   SilcClientEntry entry;
526   SilcCommandStatus status;
527   unsigned short ident = silc_command_get_ident(cmd->payload);
528
529   status = SILC_STATUS_OK;
530   if (clients_count > 1)
531     status = SILC_STATUS_LIST_START;
532
533   for (i = 0; i < clients_count; i++) {
534     entry = clients[i];
535
536     if (entry->connection && entry->data.registered == FALSE) {
537       if (clients_count == 1)
538         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
539                                              SILC_STATUS_ERR_NO_SUCH_NICK,
540                                              3, entry->nickname, 
541                                              strlen(entry->nickname));
542       continue;
543     }
544
545     if (count && i - 1 == count)
546       break;
547
548     if (clients_count > 2)
549       status = SILC_STATUS_LIST_ITEM;
550
551     if (clients_count > 1 && i == clients_count - 1)
552       status = SILC_STATUS_LIST_END;
553
554     /* Sanity check, however these should never fail. However, as
555        this sanity check has been added here they have failed. */
556     if (!entry->nickname || !entry->username)
557       continue;
558       
559     /* Send WHOIS reply */
560     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
561     tmp = silc_argument_get_first_arg(cmd->args, NULL);
562     
563     {
564       char nh[256], uh[256];
565       unsigned char idle[4];
566       SilcSocketConnection hsock;
567
568       memset(uh, 0, sizeof(uh));
569       memset(nh, 0, sizeof(nh));
570
571       strncat(nh, entry->nickname, strlen(entry->nickname));
572       if (!strchr(entry->nickname, '@')) {
573         strncat(nh, "@", 1);
574         len = entry->router ? strlen(entry->router->server_name) :
575           strlen(server->server_name);
576         strncat(nh, entry->router ? entry->router->server_name :
577                 server->server_name, len);
578       }
579       
580       strncat(uh, entry->username, strlen(entry->username));
581       if (!strchr(entry->username, '@')) {
582         strncat(uh, "@", 1);
583         hsock = (SilcSocketConnection)entry->connection;
584         len = strlen(hsock->hostname);
585         strncat(uh, hsock->hostname, len);
586       }
587       
588       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
589       
590       packet = 
591         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
592                                              status, ident, 5, 
593                                              2, idp->data, idp->len,
594                                              3, nh, strlen(nh),
595                                              4, uh, strlen(uh),
596                                              5, entry->userinfo, 
597                                              strlen(entry->userinfo),
598                                              7, idle, 4);
599     }
600     
601     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
602                             0, packet->data, packet->len, FALSE);
603     
604     silc_buffer_free(packet);
605     silc_buffer_free(idp);
606   }
607 }
608
609 static int
610 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
611 {
612   SilcServer server = cmd->server;
613   char *nick = NULL, *server_name = NULL;
614   int count = 0, clients_count = 0;
615   SilcClientEntry *clients = NULL, entry;
616   SilcClientID **client_id = NULL;
617   unsigned int client_id_count = 0;
618   int i, ret = 0;
619
620   /* Protocol dictates that we must always send the received WHOIS request
621      to our router if we are normal server, so let's do it now unless we
622      are standalone. We will not send any replies to the client until we
623      have received reply from the router. */
624   if (server->server_type == SILC_SERVER && 
625       !cmd->pending && !server->standalone) {
626     SilcBuffer tmpbuf;
627     unsigned short old_ident;
628
629     old_ident = silc_command_get_ident(cmd->payload);
630     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
631     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
632
633     /* Send WHOIS command to our router */
634     silc_server_packet_send(server, (SilcSocketConnection)
635                             server->router->connection,
636                             SILC_PACKET_COMMAND, cmd->packet->flags,
637                             tmpbuf->data, tmpbuf->len, TRUE);
638
639     /* Reprocess this packet after received reply from router */
640     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
641                                 silc_command_get_ident(cmd->payload),
642                                 silc_server_command_destructor,
643                                 silc_server_command_whois,
644                                 silc_server_command_dup(cmd));
645     cmd->pending = TRUE;
646
647     silc_command_set_ident(cmd->payload, old_ident);
648
649     silc_buffer_free(tmpbuf);
650     ret = -1;
651     goto out;
652   }
653
654   /* We are ready to process the command request. Let's search for the
655      requested client and send reply to the requesting client. */
656
657   /* Parse the whois request */
658   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
659                                        &nick, &server_name, &count,
660                                        SILC_COMMAND_WHOIS))
661     return 0;
662
663   /* Get all clients matching that ID or nickname from local list */
664   if (client_id_count) {
665     /* Check all Client ID's received in the command packet */
666     for (i = 0; i < client_id_count; i++) {
667       entry = silc_idlist_find_client_by_id(server->local_list, 
668                                             client_id[i], NULL);
669       if (entry) {
670         clients = silc_realloc(clients, sizeof(*clients) * 
671                                (clients_count + 1));
672         clients[clients_count++] = entry;
673       }
674     }
675   } else {
676     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
677                                                   nick, server_name,
678                                                   &clients_count);
679     if (!clients)
680       clients = silc_idlist_get_clients_by_hash(server->local_list, 
681                                                 nick, server->md5hash,
682                                                 &clients_count);
683   }
684   
685   /* Check global list as well */
686   if (!clients) {
687     if (client_id_count) {
688       /* Check all Client ID's received in the command packet */
689       for (i = 0; i < client_id_count; i++) {
690         entry = silc_idlist_find_client_by_id(server->global_list, 
691                                               client_id[i], NULL);
692         if (entry) {
693           clients = silc_realloc(clients, sizeof(*clients) * 
694                                  (clients_count + 1));
695           clients[clients_count++] = entry;
696         }
697       }
698     } else {
699       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
700                                                     nick, server_name,
701                                                     &clients_count);
702       if (!clients)
703         clients = silc_idlist_get_clients_by_hash(server->global_list, 
704                                                   nick, server->md5hash,
705                                                   &clients_count);
706     }
707   }
708   
709   if (!clients) {
710     /* Such client(s) really does not exist in the SILC network. */
711     if (!client_id_count) {
712       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
713                                            SILC_STATUS_ERR_NO_SUCH_NICK,
714                                            3, nick, strlen(nick));
715     } else {
716       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
717       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
718                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
719                                            2, idp->data, idp->len);
720       silc_buffer_free(idp);
721     }
722     goto out;
723   }
724
725   /* Router always finds the client entry if it exists in the SILC network.
726      However, it might be incomplete entry and does not include all the
727      mandatory fields that WHOIS command reply requires. Check for these and
728      make query from the server who owns the client if some fields are 
729      missing. */
730   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
731     ret = -1;
732     goto out;
733   }
734
735   /* Send the command reply to the client */
736   silc_server_command_whois_send_reply(cmd, clients, clients_count);
737
738  out:
739   if (client_id_count) {
740     for (i = 0; i < client_id_count; i++)
741       silc_free(client_id[i]);
742     silc_free(client_id);
743   }
744   if (clients)
745     silc_free(clients);
746   if (nick)
747     silc_free(nick);
748   if (server_name)
749     silc_free(server_name);
750
751   return ret;
752 }
753
754 static int
755 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
756 {
757   SilcServer server = cmd->server;
758   char *nick = NULL, *server_name = NULL;
759   int count = 0, clients_count = 0;
760   SilcClientEntry *clients = NULL, entry;
761   SilcClientID **client_id = NULL;
762   unsigned int client_id_count = 0;
763   int i, ret = 0;
764
765   /* Parse the whois request */
766   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
767                                        &nick, &server_name, &count,
768                                        SILC_COMMAND_WHOIS))
769     return 0;
770
771   /* Process the command request. Let's search for the requested client and
772      send reply to the requesting server. */
773
774   if (client_id_count) {
775     /* Check all Client ID's received in the command packet */
776     for (i = 0; i < client_id_count; i++) {
777       entry = silc_idlist_find_client_by_id(server->local_list, 
778                                             client_id[i], NULL);
779       if (entry) {
780         clients = silc_realloc(clients, sizeof(*clients) * 
781                                (clients_count + 1));
782         clients[clients_count++] = entry;
783       }
784     }
785   } else {
786     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
787                                                   nick, server_name,
788                                                   &clients_count);
789     if (!clients)
790       clients = silc_idlist_get_clients_by_hash(server->local_list, 
791                                                 nick, server->md5hash,
792                                                 &clients_count);
793   }
794   
795   /* If we are router we will check our global list as well. */
796   if (!clients && server->server_type == SILC_ROUTER) {
797     if (client_id_count) {
798       /* Check all Client ID's received in the command packet */
799       for (i = 0; i < client_id_count; i++) {
800         entry = silc_idlist_find_client_by_id(server->global_list, 
801                                               client_id[i], NULL);
802         if (entry) {
803           clients = silc_realloc(clients, sizeof(*clients) * 
804                                  (clients_count + 1));
805           clients[clients_count++] = entry;
806         }
807       }
808     } else {
809       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
810                                                     nick, server_name,
811                                                     &clients_count);
812       if (!clients)
813         clients = silc_idlist_get_clients_by_hash(server->global_list, 
814                                                   nick, server->md5hash,
815                                                   &clients_count);
816     }
817   }
818
819   if (!clients) {
820     /* Such a client really does not exist in the SILC network. */
821     if (!client_id_count) {
822       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
823                                            SILC_STATUS_ERR_NO_SUCH_NICK,
824                                            3, nick, strlen(nick));
825     } else {
826       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
827       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
828                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
829                                            2, idp->data, idp->len);
830       silc_buffer_free(idp);
831     }
832     goto out;
833   }
834
835   /* Router always finds the client entry if it exists in the SILC network.
836      However, it might be incomplete entry and does not include all the
837      mandatory fields that WHOIS command reply requires. Check for these and
838      make query from the server who owns the client if some fields are 
839      missing. */
840   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
841     ret = -1;
842     goto out;
843   }
844
845   /* Send the command reply to the client */
846   silc_server_command_whois_send_reply(cmd, clients, clients_count);
847
848  out:
849   if (client_id_count) {
850     for (i = 0; i < client_id_count; i++)
851       silc_free(client_id[i]);
852     silc_free(client_id);
853   }
854   if (clients)
855     silc_free(clients);
856   if (nick)
857     silc_free(nick);
858   if (server_name)
859     silc_free(server_name);
860
861   return ret;
862 }
863
864 /* Server side of command WHOIS. Processes user's query and sends found 
865    results as command replies back to the client. */
866
867 SILC_SERVER_CMD_FUNC(whois)
868 {
869   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
870   int ret = 0;
871
872   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
873
874   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
875     ret = silc_server_command_whois_from_client(cmd);
876   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
877            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
878     ret = silc_server_command_whois_from_server(cmd);
879
880   if (!ret)
881     silc_server_command_free(cmd);
882 }
883
884 /******************************************************************************
885
886                               WHOWAS Functions
887
888 ******************************************************************************/
889
890 static int
891 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
892                                  char **nickname,
893                                  char **server_name,
894                                  int *count)
895 {
896   unsigned char *tmp;
897   unsigned int len;
898
899   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
900   if (!tmp) {
901     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
902                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
903     return FALSE;
904   }
905
906   /* Get the nickname@server string and parse it. */
907   if (strchr(tmp, '@')) {
908     len = strcspn(tmp, "@");
909     *nickname = silc_calloc(len + 1, sizeof(char));
910     memcpy(*nickname, tmp, len);
911     *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
912     memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
913   } else {
914     *nickname = strdup(tmp);
915   }
916   /* Get the max count of reply messages allowed */
917   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
918   if (tmp)
919     *count = atoi(tmp);
920   else
921     *count = 0;
922
923   return TRUE;
924 }
925
926 static void
927 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
928                                       SilcClientEntry *clients,
929                                       unsigned int clients_count)
930 {
931   SilcServer server = cmd->server;
932   char *tmp;
933   int i, count = 0, len;
934   SilcBuffer packet, idp;
935   SilcClientEntry entry = NULL;
936   SilcCommandStatus status;
937   unsigned short ident = silc_command_get_ident(cmd->payload);
938   char found = FALSE;
939
940   status = SILC_STATUS_OK;
941   if (clients_count > 1)
942     status = SILC_STATUS_LIST_START;
943
944   for (i = 0; i < clients_count; i++) {
945     entry = clients[i];
946
947     /* We will take only clients that are not valid anymore. They are the
948        ones that are not registered anymore but still have a ID. They
949        have disconnected us, and thus valid for WHOWAS. */
950     if (entry->data.registered == TRUE)
951       continue;
952     if (entry->id == NULL)
953       continue;
954
955     if (count && i - 1 == count)
956       break;
957
958     found = TRUE;
959
960     if (clients_count > 2)
961       status = SILC_STATUS_LIST_ITEM;
962
963     if (clients_count > 1 && i == clients_count - 1)
964       status = SILC_STATUS_LIST_END;
965
966     /* Sanity check, however these should never fail. However, as
967        this sanity check has been added here they have failed. */
968     if (!entry->nickname || !entry->username)
969       continue;
970       
971     /* Send WHOWAS reply */
972     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
973     tmp = silc_argument_get_first_arg(cmd->args, NULL);
974     
975     {
976       char nh[256], uh[256];
977
978       memset(uh, 0, sizeof(uh));
979       memset(nh, 0, sizeof(nh));
980
981       strncat(nh, entry->nickname, strlen(entry->nickname));
982       if (!strchr(entry->nickname, '@')) {
983         strncat(nh, "@", 1);
984         len = entry->router ? strlen(entry->router->server_name) :
985           strlen(server->server_name);
986         strncat(nh, entry->router ? entry->router->server_name :
987                 server->server_name, len);
988       }
989       
990       strncat(uh, entry->username, strlen(entry->username));
991       if (!strchr(entry->username, '@')) {
992         strncat(uh, "@", 1);
993         strcat(uh, "*private*");
994       }
995       
996       packet = 
997         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
998                                              status, ident, 4, 
999                                              2, idp->data, idp->len,
1000                                              3, nh, strlen(nh),
1001                                              4, uh, strlen(uh),
1002                                              5, entry->userinfo, 
1003                                              strlen(entry->userinfo));
1004     }
1005     
1006     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1007                             0, packet->data, packet->len, FALSE);
1008     
1009     silc_buffer_free(packet);
1010     silc_buffer_free(idp);
1011   }
1012
1013   if (found == FALSE && entry)
1014     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1015                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1016                                          3, entry->nickname, 
1017                                          strlen(entry->nickname));
1018 }
1019
1020 static int
1021 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1022 {
1023   SilcServer server = cmd->server;
1024   char *nick = NULL, *server_name = NULL;
1025   int count = 0, clients_count = 0;
1026   SilcClientEntry *clients = NULL;
1027   int ret = 0;
1028
1029   /* Protocol dictates that we must always send the received WHOWAS request
1030      to our router if we are normal server, so let's do it now unless we
1031      are standalone. We will not send any replies to the client until we
1032      have received reply from the router. */
1033   if (server->server_type == SILC_SERVER && 
1034       !cmd->pending && !server->standalone) {
1035     SilcBuffer tmpbuf;
1036     unsigned short old_ident;
1037
1038     old_ident = silc_command_get_ident(cmd->payload);
1039     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1040     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1041
1042     /* Send WHOWAS command to our router */
1043     silc_server_packet_send(server, (SilcSocketConnection)
1044                             server->router->connection,
1045                             SILC_PACKET_COMMAND, cmd->packet->flags,
1046                             tmpbuf->data, tmpbuf->len, TRUE);
1047
1048     /* Reprocess this packet after received reply from router */
1049     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1050                                 silc_command_get_ident(cmd->payload),
1051                                 silc_server_command_destructor,
1052                                 silc_server_command_whois,
1053                                 silc_server_command_dup(cmd));
1054     cmd->pending = TRUE;
1055
1056     silc_command_set_ident(cmd->payload, old_ident);
1057
1058     silc_buffer_free(tmpbuf);
1059     ret = -1;
1060     goto out;
1061   }
1062
1063   /* We are ready to process the command request. Let's search for the
1064      requested client and send reply to the requesting client. */
1065
1066   /* Parse the whowas request */
1067   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1068     return 0;
1069
1070   /* Get all clients matching that nickname from local list */
1071   clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1072                                                 nick, server_name,
1073                                                 &clients_count);
1074   if (!clients)
1075     clients = silc_idlist_get_clients_by_hash(server->local_list, 
1076                                               nick, server->md5hash,
1077                                               &clients_count);
1078   
1079   /* Check global list as well */
1080   if (!clients) {
1081     clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1082                                                   nick, server_name,
1083                                                   &clients_count);
1084     if (!clients)
1085       clients = silc_idlist_get_clients_by_hash(server->global_list, 
1086                                                 nick, server->md5hash,
1087                                                 &clients_count);
1088   }
1089   
1090   if (!clients) {
1091     /* Such client(s) really does not exist in the SILC network. */
1092     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1093                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1094                                          3, nick, strlen(nick));
1095     goto out;
1096   }
1097
1098   /* Send the command reply to the client */
1099   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1100
1101  out:
1102   if (clients)
1103     silc_free(clients);
1104   if (nick)
1105     silc_free(nick);
1106   if (server_name)
1107     silc_free(server_name);
1108
1109   return ret;
1110 }
1111
1112 static int
1113 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1114 {
1115   SilcServer server = cmd->server;
1116   char *nick = NULL, *server_name = NULL;
1117   int count = 0, clients_count = 0;
1118   SilcClientEntry *clients = NULL;
1119   int ret = 0;
1120
1121   /* Parse the whowas request */
1122   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1123     return 0;
1124
1125   /* Process the command request. Let's search for the requested client and
1126      send reply to the requesting server. */
1127
1128   clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1129                                                 nick, server_name,
1130                                                 &clients_count);
1131   if (!clients)
1132     clients = silc_idlist_get_clients_by_hash(server->local_list, 
1133                                               nick, server->md5hash,
1134                                               &clients_count);
1135   
1136   /* If we are router we will check our global list as well. */
1137   if (!clients && server->server_type == SILC_ROUTER) {
1138     clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1139                                                   nick, server_name,
1140                                                   &clients_count);
1141     if (!clients)
1142       clients = silc_idlist_get_clients_by_hash(server->global_list, 
1143                                                 nick, server->md5hash,
1144                                                 &clients_count);
1145   }
1146
1147   if (!clients) {
1148     /* Such a client really does not exist in the SILC network. */
1149     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1150                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1151                                          3, nick, strlen(nick));
1152     goto out;
1153   }
1154
1155   /* Send the command reply to the client */
1156   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1157
1158  out:
1159   if (clients)
1160     silc_free(clients);
1161   if (nick)
1162     silc_free(nick);
1163   if (server_name)
1164     silc_free(server_name);
1165
1166   return ret;
1167 }
1168
1169 /* Server side of command WHOWAS. */
1170
1171 SILC_SERVER_CMD_FUNC(whowas)
1172 {
1173   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1174   int ret = 0;
1175
1176   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1177
1178   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1179     ret = silc_server_command_whowas_from_client(cmd);
1180   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1181            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1182     ret = silc_server_command_whowas_from_server(cmd);
1183
1184   if (!ret)
1185     silc_server_command_free(cmd);
1186 }
1187
1188 /******************************************************************************
1189
1190                               IDENTIFY Functions
1191
1192 ******************************************************************************/
1193
1194 /* Checks that all mandatory fields are present. If not then send WHOIS 
1195    request to the server who owns the client. We use WHOIS because we want
1196    to get as much information as possible at once. */
1197
1198 static char
1199 silc_server_command_identify_check(SilcServerCommandContext cmd,
1200                                    SilcClientEntry *clients,
1201                                    unsigned int clients_count)
1202 {
1203   SilcServer server = cmd->server;
1204   int i;
1205   SilcClientEntry entry;
1206
1207   for (i = 0; i < clients_count; i++) {
1208     entry = clients[i];
1209
1210     if (!entry->nickname) {
1211       SilcBuffer tmpbuf;
1212       unsigned short old_ident;
1213       
1214       if (!entry->router)
1215         continue;
1216       
1217       old_ident = silc_command_get_ident(cmd->payload);
1218       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1219       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1220       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1221       
1222       /* Send WHOIS request. We send WHOIS since we're doing the requesting
1223          now anyway so make it a good one. */
1224       silc_server_packet_send(server, entry->router->connection,
1225                               SILC_PACKET_COMMAND, cmd->packet->flags,
1226                               tmpbuf->data, tmpbuf->len, TRUE);
1227       
1228       /* Reprocess this packet after received reply */
1229       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1230                                   silc_command_get_ident(cmd->payload),
1231                                   silc_server_command_destructor,
1232                                   silc_server_command_identify,
1233                                   silc_server_command_dup(cmd));
1234
1235       cmd->pending = TRUE;
1236       
1237       /* Put old data back to the Command Payload we just changed */
1238       silc_command_set_ident(cmd->payload, old_ident);
1239       silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1240
1241       silc_buffer_free(tmpbuf);
1242       return FALSE;
1243     }
1244   }
1245
1246   return TRUE;
1247 }
1248
1249 static void
1250 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1251                                         SilcClientEntry *clients,
1252                                         unsigned int clients_count)
1253 {
1254   SilcServer server = cmd->server;
1255   char *tmp;
1256   int i, count = 0, len;
1257   SilcBuffer packet, idp;
1258   SilcClientEntry entry;
1259   SilcCommandStatus status;
1260   unsigned short ident = silc_command_get_ident(cmd->payload);
1261
1262   status = SILC_STATUS_OK;
1263   if (clients_count > 1)
1264     status = SILC_STATUS_LIST_START;
1265
1266   for (i = 0; i < clients_count; i++) {
1267     entry = clients[i];
1268
1269     if (entry->connection && entry->data.registered == FALSE) {
1270       if (clients_count == 1)
1271         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1272                                              SILC_STATUS_ERR_NO_SUCH_NICK,
1273                                              3, entry->nickname, 
1274                                              strlen(entry->nickname));
1275       continue;
1276     }
1277
1278     if (count && i - 1 == count)
1279       break;
1280
1281     if (clients_count > 2)
1282       status = SILC_STATUS_LIST_ITEM;
1283
1284     if (clients_count > 1 && i == clients_count - 1)
1285       status = SILC_STATUS_LIST_END;
1286
1287     /* Send IDENTIFY reply */
1288     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1289     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1290     
1291     /* XXX */
1292     {
1293       char nh[256], uh[256];
1294       SilcSocketConnection hsock;
1295
1296       memset(uh, 0, sizeof(uh));
1297       memset(nh, 0, sizeof(nh));
1298       
1299       strncat(nh, entry->nickname, strlen(entry->nickname));
1300       if (!strchr(entry->nickname, '@')) {
1301         strncat(nh, "@", 1);
1302         len = entry->router ? strlen(entry->router->server_name) :
1303           strlen(server->server_name);
1304         strncat(nh, entry->router ? entry->router->server_name :
1305                 server->server_name, len);
1306       }
1307       
1308       if (!entry->username) {
1309         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1310                                                       status, ident, 2,
1311                                                       2, idp->data, idp->len, 
1312                                                       3, nh, strlen(nh));
1313       } else {
1314         strncat(uh, entry->username, strlen(entry->username));
1315         if (!strchr(entry->username, '@')) {
1316           strncat(uh, "@", 1);
1317           hsock = (SilcSocketConnection)entry->connection;
1318           len = strlen(hsock->hostname);
1319           strncat(uh, hsock->hostname, len);
1320         }
1321       
1322         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1323                                                       status, ident, 3,
1324                                                       2, idp->data, idp->len, 
1325                                                       3, nh, strlen(nh),
1326                                                       4, uh, strlen(uh));
1327       }
1328       
1329       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1330                               0, packet->data, packet->len, FALSE);
1331       
1332       silc_buffer_free(packet);
1333       silc_buffer_free(idp);
1334     }
1335   }
1336 }
1337
1338 static int
1339 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1340 {
1341   SilcServer server = cmd->server;
1342   char *nick = NULL, *server_name = NULL;
1343   int count = 0, clients_count = 0; 
1344   SilcClientEntry *clients = NULL, entry;
1345   SilcClientID **client_id = NULL;
1346   unsigned int client_id_count = 0;
1347   int i, ret = 0;
1348
1349   /* Protocol dictates that we must always send the received IDENTIFY request
1350      to our router if we are normal server, so let's do it now unless we
1351      are standalone. We will not send any replies to the client until we
1352      have received reply from the router. */
1353   if (server->server_type == SILC_SERVER && 
1354       !cmd->pending && !server->standalone) {
1355     SilcBuffer tmpbuf;
1356     unsigned short old_ident;
1357
1358     old_ident = silc_command_get_ident(cmd->payload);
1359     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1360     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1361
1362     /* Send IDENTIFY command to our router */
1363     silc_server_packet_send(server, (SilcSocketConnection)
1364                             server->router->connection,
1365                             SILC_PACKET_COMMAND, cmd->packet->flags,
1366                             tmpbuf->data, tmpbuf->len, TRUE);
1367
1368     /* Reprocess this packet after received reply from router */
1369     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1370                                 silc_command_get_ident(cmd->payload),
1371                                 silc_server_command_destructor,
1372                                 silc_server_command_identify,
1373                                 silc_server_command_dup(cmd));
1374     cmd->pending = TRUE;
1375
1376     silc_command_set_ident(cmd->payload, old_ident);
1377
1378     silc_buffer_free(tmpbuf);
1379     ret = -1;
1380     goto out;
1381   }
1382
1383   /* We are ready to process the command request. Let's search for the
1384      requested client and send reply to the requesting client. */
1385
1386   /* Parse the IDENTIFY request */
1387   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1388                                        &nick, &server_name, &count,
1389                                        SILC_COMMAND_IDENTIFY))
1390     return 0;
1391
1392   /* Get all clients matching that ID or nickname from local list */
1393   if (client_id_count) { 
1394     /* Check all Client ID's received in the command packet */
1395     for (i = 0; i < client_id_count; i++) {
1396       entry = silc_idlist_find_client_by_id(server->local_list, 
1397                                             client_id[i], NULL);
1398       if (entry) {
1399         clients = silc_realloc(clients, sizeof(*clients) * 
1400                                (clients_count + 1));
1401         clients[clients_count++] = entry;
1402       }
1403     }
1404   } else {
1405     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1406                                                   nick, server_name,
1407                                                   &clients_count);
1408     if (!clients)
1409       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1410                                                 nick, server->md5hash,
1411                                                 &clients_count);
1412   }
1413   
1414   /* Check global list as well */
1415   if (!clients) {
1416     if (client_id_count) {
1417       /* Check all Client ID's received in the command packet */
1418       for (i = 0; i < client_id_count; i++) {
1419         entry = silc_idlist_find_client_by_id(server->global_list, 
1420                                               client_id[i], NULL);
1421         if (entry) {
1422           clients = silc_realloc(clients, sizeof(*clients) * 
1423                                  (clients_count + 1));
1424           clients[clients_count++] = entry;
1425         }
1426       }
1427     } else {
1428       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1429                                                     nick, server_name,
1430                                                     &clients_count);
1431       if (!clients)
1432         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1433                                                   nick, server->md5hash,
1434                                                   &clients_count);
1435     }
1436   }
1437   
1438   if (!clients) {
1439     /* Such a client really does not exist in the SILC network. */
1440     if (!client_id_count) {
1441       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1442                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1443                                            3, nick, strlen(nick));
1444     } else {
1445       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1446       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1447                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1448                                            2, idp->data, idp->len);
1449       silc_buffer_free(idp);
1450     }
1451     goto out;
1452   }
1453
1454   /* Check that all mandatory fields are present and request those data
1455      from the server who owns the client if necessary. */
1456   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1457     ret = -1;
1458     goto out;
1459   }
1460
1461   /* Send the command reply to the client */
1462   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1463
1464  out:
1465   if (client_id_count) {
1466     for (i = 0; i < client_id_count; i++)
1467       silc_free(client_id[i]);
1468     silc_free(client_id);
1469   }
1470   if (clients)
1471     silc_free(clients);
1472   if (nick)
1473     silc_free(nick);
1474   if (server_name)
1475     silc_free(server_name);
1476
1477   return ret;
1478 }
1479
1480 static int
1481 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1482 {
1483   SilcServer server = cmd->server;
1484   char *nick = NULL, *server_name = NULL;
1485   int count = 0, clients_count = 0;
1486   SilcClientEntry *clients = NULL, entry;
1487   SilcClientID **client_id = NULL;
1488   unsigned int client_id_count = 0;
1489   int i, ret = 0;
1490
1491   /* Parse the IDENTIFY request */
1492   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1493                                        &nick, &server_name, &count,
1494                                        SILC_COMMAND_IDENTIFY))
1495     return 0;
1496
1497   /* Process the command request. Let's search for the requested client and
1498      send reply to the requesting server. */
1499
1500   if (client_id_count) {
1501     /* Check all Client ID's received in the command packet */
1502     for (i = 0; i < client_id_count; i++) {
1503       entry = silc_idlist_find_client_by_id(server->local_list, 
1504                                             client_id[i], NULL);
1505       if (entry) {
1506         clients = silc_realloc(clients, sizeof(*clients) * 
1507                                (clients_count + 1));
1508         clients[clients_count++] = entry;
1509       }
1510     }
1511   } else {
1512     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1513                                                   nick, server_name,
1514                                                   &clients_count);
1515     if (!clients)
1516       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1517                                                 nick, server->md5hash,
1518                                                 &clients_count);
1519   }
1520   
1521   /* If we are router we will check our global list as well. */
1522   if (!clients && server->server_type == SILC_ROUTER) {
1523     if (client_id_count) {
1524       /* Check all Client ID's received in the command packet */
1525       for (i = 0; i < client_id_count; i++) {
1526         entry = silc_idlist_find_client_by_id(server->global_list, 
1527                                               client_id[i], NULL);
1528         if (entry) {
1529           clients = silc_realloc(clients, sizeof(*clients) * 
1530                                  (clients_count + 1));
1531           clients[clients_count++] = entry;
1532         }
1533       }
1534     } else {
1535       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1536                                                     nick, server_name,
1537                                                     &clients_count);
1538       if (!clients)
1539         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1540                                                   nick, server->md5hash,
1541                                                   &clients_count);
1542     }
1543   }
1544
1545   if (!clients) {
1546     /* Such a client really does not exist in the SILC network. */
1547     if (!client_id_count) {
1548       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1549                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1550                                            3, nick, strlen(nick));
1551     } else {
1552       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1553       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1554                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1555                                            2, idp->data, idp->len);
1556       silc_buffer_free(idp);
1557     }
1558     goto out;
1559   }
1560
1561   /* Check that all mandatory fields are present and request those data
1562      from the server who owns the client if necessary. */
1563   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1564     ret = -1;
1565     goto out;
1566   }
1567
1568   /* Send the command reply */
1569   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1570
1571  out:
1572   if (client_id_count) {
1573     for (i = 0; i < client_id_count; i++)
1574       silc_free(client_id[i]);
1575     silc_free(client_id);
1576   }
1577   if (clients)
1578     silc_free(clients);
1579   if (nick)
1580     silc_free(nick);
1581   if (server_name)
1582     silc_free(server_name);
1583
1584   return ret;
1585 }
1586
1587 SILC_SERVER_CMD_FUNC(identify)
1588 {
1589   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1590   int ret = 0;
1591
1592   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1593
1594   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1595     ret = silc_server_command_identify_from_client(cmd);
1596   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1597            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1598     ret = silc_server_command_identify_from_server(cmd);
1599
1600   if (!ret)
1601     silc_server_command_free(cmd);
1602 }
1603
1604 /* Checks string for bad characters and returns TRUE if they are found. */
1605
1606 static int silc_server_command_bad_chars(char *nick)
1607 {
1608   if (strchr(nick, '\\')) return TRUE;
1609   if (strchr(nick, '\"')) return TRUE;
1610   if (strchr(nick, '´')) return TRUE;
1611   if (strchr(nick, '`')) return TRUE;
1612   if (strchr(nick, '\'')) return TRUE;
1613   if (strchr(nick, '*')) return TRUE;
1614   if (strchr(nick, '/')) return TRUE;
1615   if (strchr(nick, '@')) return TRUE;
1616
1617   return FALSE;
1618 }
1619
1620 /* Server side of command NICK. Sets nickname for user. Setting
1621    nickname causes generation of a new client ID for the client. The
1622    new client ID is sent to the client after changing the nickname. */
1623
1624 SILC_SERVER_CMD_FUNC(nick)
1625 {
1626   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1627   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1628   SilcServer server = cmd->server;
1629   SilcBuffer packet, nidp, oidp;
1630   SilcClientID *new_id;
1631   char *nick;
1632
1633   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1634     goto out;
1635
1636   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1637
1638   /* Check nickname */
1639   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1640   if (silc_server_command_bad_chars(nick) == TRUE) {
1641     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1642                                           SILC_STATUS_ERR_BAD_NICKNAME);
1643     goto out;
1644   }
1645
1646   if (strlen(nick) > 128)
1647     nick[127] = '\0';
1648
1649   /* Create new Client ID */
1650   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1651                            cmd->server->md5hash, nick,
1652                            &new_id);
1653
1654   /* Send notify about nickname change to our router. We send the new
1655      ID and ask to replace it with the old one. If we are router the
1656      packet is broadcasted. Send NICK_CHANGE notify. */
1657   if (!server->standalone)
1658     silc_server_send_notify_nick_change(server, server->router->connection, 
1659                                         server->server_type == SILC_SERVER ? 
1660                                         FALSE : TRUE, client->id,
1661                                         new_id, SILC_ID_CLIENT_LEN);
1662
1663   /* Remove old cache entry */
1664   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
1665                          client->id); 
1666
1667   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1668
1669   /* Free old ID */
1670   if (client->id) {
1671     memset(client->id, 0, SILC_ID_CLIENT_LEN);
1672     silc_free(client->id);
1673   }
1674
1675   /* Save the nickname as this client is our local client */
1676   if (client->nickname)
1677     silc_free(client->nickname);
1678
1679   client->nickname = strdup(nick);
1680   client->id = new_id;
1681
1682   /* Update client cache */
1683   silc_idcache_add(server->local_list->clients, client->nickname, 
1684                    SILC_ID_CLIENT, client->id, (void *)client, TRUE, FALSE);
1685
1686   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1687
1688   /* Send NICK_CHANGE notify to the client's channels */
1689   silc_server_send_notify_on_channels(server, NULL, client, 
1690                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1691                                       oidp->data, oidp->len, 
1692                                       nidp->data, nidp->len);
1693
1694   /* Send the new Client ID as reply command back to client */
1695   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1696                                                 SILC_STATUS_OK, 0, 1, 
1697                                                 2, nidp->data, nidp->len);
1698   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1699                           0, packet->data, packet->len, FALSE);
1700
1701   silc_buffer_free(packet);
1702   silc_buffer_free(nidp);
1703   silc_buffer_free(oidp);
1704   
1705  out:
1706   silc_server_command_free(cmd);
1707 }
1708
1709 SILC_SERVER_CMD_FUNC(list)
1710 {
1711 }
1712
1713 /* Server side of TOPIC command. Sets topic for channel and/or returns
1714    current topic to client. */
1715
1716 SILC_SERVER_CMD_FUNC(topic)
1717 {
1718   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1719   SilcServer server = cmd->server;
1720   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1721   SilcChannelID *channel_id;
1722   SilcChannelEntry channel;
1723   SilcChannelClientEntry chl;
1724   SilcBuffer packet, idp;
1725   unsigned char *tmp;
1726   unsigned int argc, tmp_len;
1727
1728   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1729
1730   argc = silc_argument_get_arg_num(cmd->args);
1731
1732   /* Get Channel ID */
1733   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1734   if (!tmp) {
1735     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1736                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1737     goto out;
1738   }
1739   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1740   if (!channel_id) {
1741     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1742                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1743     goto out;
1744   }
1745
1746   /* Check whether the channel exists */
1747   channel = silc_idlist_find_channel_by_id(server->local_list, 
1748                                            channel_id, NULL);
1749   if (!channel) {
1750     channel = silc_idlist_find_channel_by_id(server->global_list, 
1751                                              channel_id, NULL);
1752     if (!channel) {
1753       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1754                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1755       goto out;
1756     }
1757   }
1758
1759   if (argc > 1) {
1760     /* Get the topic */
1761     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1762     if (!tmp) {
1763       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1764                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1765       goto out;
1766     }
1767
1768     if (strlen(tmp) > 256) {
1769       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1770                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1771       goto out;
1772     }
1773
1774     /* See whether has rights to change topic */
1775     silc_list_start(channel->user_list);
1776     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1777       if (chl->client == client)
1778         break;
1779
1780     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1781       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1782         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1783                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1784         goto out;
1785       }
1786     }
1787
1788     /* Set the topic for channel */
1789     if (channel->topic)
1790       silc_free(channel->topic);
1791     channel->topic = strdup(tmp);
1792
1793     /* Send TOPIC_SET notify type to the network */
1794     if (!server->standalone)
1795       silc_server_send_notify_topic_set(server, server->router->connection,
1796                                         server->server_type == SILC_ROUTER ?
1797                                         TRUE : FALSE, channel, client->id,
1798                                         SILC_ID_CLIENT_LEN, channel->topic);
1799
1800     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1801
1802     /* Send notify about topic change to all clients on the channel */
1803     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1804                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1805                                        idp->data, idp->len,
1806                                        channel->topic, strlen(channel->topic));
1807     silc_buffer_free(idp);
1808   }
1809
1810   /* Send the topic to client as reply packet */
1811   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1812   if (channel->topic)
1813     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
1814                                                   SILC_STATUS_OK, 0, 2, 
1815                                                   2, idp->data, idp->len,
1816                                                   3, channel->topic, 
1817                                                   strlen(channel->topic));
1818   else
1819     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
1820                                                   SILC_STATUS_OK, 0, 1, 
1821                                                   2, idp->data, idp->len);
1822   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1823                           0, packet->data, packet->len, FALSE);
1824
1825   silc_buffer_free(packet);
1826   silc_buffer_free(idp);
1827   silc_free(channel_id);
1828
1829  out:
1830   silc_server_command_free(cmd);
1831 }
1832
1833 /* Server side of INVITE command. Invites some client to join some channel. */
1834
1835 SILC_SERVER_CMD_FUNC(invite)
1836 {
1837   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1838   SilcServer server = cmd->server;
1839   SilcSocketConnection sock = cmd->sock, dest_sock;
1840   SilcClientEntry sender, dest;
1841   SilcClientID *dest_id;
1842   SilcChannelEntry channel;
1843   SilcChannelID *channel_id;
1844   SilcBuffer sidp;
1845   unsigned char *tmp;
1846   unsigned int len;
1847
1848   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1849
1850   /* Get destination ID */
1851   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1852   if (!tmp) {
1853     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1854                                           SILC_STATUS_ERR_NO_CLIENT_ID);
1855     goto out;
1856   }
1857   dest_id = silc_id_payload_parse_id(tmp, len);
1858   if (!dest_id) {
1859     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1860                                           SILC_STATUS_ERR_NO_CLIENT_ID);
1861     goto out;
1862   }
1863
1864   /* Get Channel ID */
1865   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1866   if (!tmp) {
1867     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1868                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1869     goto out;
1870   }
1871   channel_id = silc_id_payload_parse_id(tmp, len);
1872   if (!channel_id) {
1873     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1874                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1875     goto out;
1876   }
1877
1878   /* Check whether the channel exists */
1879   channel = silc_idlist_find_channel_by_id(server->local_list, 
1880                                            channel_id, NULL);
1881   if (!channel) {
1882     channel = silc_idlist_find_channel_by_id(server->global_list, 
1883                                              channel_id, NULL);
1884     if (!channel) {
1885       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1886                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1887       goto out;
1888     }
1889   }
1890
1891   /* Check whether the sender of this command is on the channel. */
1892   sender = (SilcClientEntry)sock->user_data;
1893   if (!silc_server_client_on_channel(sender, channel)) {
1894     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1895                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1896     goto out;
1897   }
1898
1899   /* Check whether the channel is invite-only channel. If yes then the
1900      sender of this command must be at least channel operator. */
1901   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1902     SilcChannelClientEntry chl;
1903
1904     silc_list_start(channel->user_list);
1905     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1906       if (chl->client == sender) {
1907         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1908           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1909                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1910           goto out;
1911         }
1912         break;
1913       }
1914   }
1915
1916   /* Find the connection data for the destination. If it is local we will
1917      send it directly otherwise we will send it to router for routing. */
1918   dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1919   if (dest)
1920     dest_sock = (SilcSocketConnection)dest->connection;
1921   else
1922     dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1923
1924   /* Check whether the requested client is already on the channel. */
1925   /* XXX if we are normal server we don't know about global clients on
1926      the channel thus we must request it (USERS command), check from
1927      local cache as well. */
1928   if (silc_server_client_on_channel(dest, channel)) {
1929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1930                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1931     goto out;
1932   }
1933
1934   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1935
1936   /* Send notify to the client that is invited to the channel */
1937   silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
1938                                SILC_ID_CLIENT,
1939                                SILC_NOTIFY_TYPE_INVITE, 2, 
1940                                sidp->data, sidp->len, tmp, len);
1941
1942   /* Send command reply */
1943   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1944                                         SILC_STATUS_OK);
1945
1946   silc_buffer_free(sidp);
1947
1948  out:
1949   silc_server_command_free(cmd);
1950 }
1951
1952 typedef struct {
1953   SilcServer server;
1954   SilcSocketConnection sock;
1955   char *signoff;
1956 } *QuitInternal;
1957
1958 /* Quits connection to client. This gets called if client won't
1959    close the connection even when it has issued QUIT command. */
1960
1961 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1962 {
1963   QuitInternal q = (QuitInternal)context;
1964
1965   /* Free all client specific data, such as client entry and entires
1966      on channels this client may be on. */
1967   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1968                                TRUE, q->signoff);
1969   q->sock->user_data = NULL;
1970
1971   /* Close the connection on our side */
1972   silc_server_close_connection(q->server, q->sock);
1973
1974   silc_free(q->signoff);
1975   silc_free(q);
1976 }
1977
1978 /* Quits SILC session. This is the normal way to disconnect client. */
1979  
1980 SILC_SERVER_CMD_FUNC(quit)
1981 {
1982   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1983   SilcServer server = cmd->server;
1984   SilcSocketConnection sock = cmd->sock;
1985   QuitInternal q;
1986   unsigned char *tmp = NULL;
1987   unsigned int len = 0;
1988
1989   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1990
1991   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1992     goto out;
1993
1994   /* Get destination ID */
1995   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1996   if (len > 128)
1997     tmp = NULL;
1998
1999   q = silc_calloc(1, sizeof(*q));
2000   q->server = server;
2001   q->sock = sock;
2002   q->signoff = tmp ? strdup(tmp) : NULL;
2003
2004   /* We quit the connection with little timeout */
2005   silc_task_register(server->timeout_queue, sock->sock,
2006                      silc_server_command_quit_cb, (void *)q,
2007                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2008
2009  out:
2010   silc_server_command_free(cmd);
2011 }
2012
2013 /* Server side of command KILL. This command is used by router operator
2014    to remove an client from the SILC Network temporarily. */
2015
2016 SILC_SERVER_CMD_FUNC(kill)
2017 {
2018   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2019   SilcServer server = cmd->server;
2020   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2021   SilcClientEntry remote_client;
2022   SilcClientID *client_id;
2023   unsigned char *tmp, *comment;
2024   unsigned int tmp_len, tmp_len2;
2025
2026   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2027
2028   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2029     goto out;
2030
2031   /* KILL command works only on router */
2032   if (server->server_type != SILC_ROUTER) {
2033     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2034                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2035     goto out;
2036   }
2037
2038   /* Check whether client has the permissions. */
2039   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2040     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2041                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2042     goto out;
2043   }
2044
2045   /* Get the client ID */
2046   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2047   if (!tmp) {
2048     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2049                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2050     goto out;
2051   }
2052   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2053   if (!client_id) {
2054     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2055                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2056     goto out;
2057   }
2058
2059   /* Get the client entry */
2060   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2061                                                 client_id, NULL);
2062   if (!remote_client) {
2063     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2064                                                   client_id, NULL);
2065     if (!remote_client) {
2066       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2067                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2068       goto out;
2069     }
2070   }
2071
2072   /* Get comment */
2073   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2074   if (tmp_len2 > 128)
2075     comment = NULL;
2076
2077   /* Send reply to the sender */
2078   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2079                                         SILC_STATUS_OK);
2080
2081   /* Send the KILL notify packets. First send it to the channel, then
2082      to our primary router and then directly to the client who is being
2083      killed right now. */
2084
2085   /* Send KILLED notify to the channels. It is not sent to the client
2086      as it will be sent differently destined directly to the client and not
2087      to the channel. */
2088   silc_server_send_notify_on_channels(server, remote_client, 
2089                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2090                                       comment ? 2 : 1,
2091                                       tmp, tmp_len,
2092                                       comment, comment ? tmp_len2 : 0);
2093
2094   /* Send KILLED notify to primary route */
2095   if (!server->standalone)
2096     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2097                                    remote_client->id, SILC_ID_CLIENT_LEN,
2098                                    comment);
2099
2100   /* Send KILLED notify to the client directly */
2101   silc_server_send_notify_killed(server, remote_client->connection ? 
2102                                  remote_client->connection : 
2103                                  remote_client->router->connection, FALSE,
2104                                  remote_client->id, SILC_ID_CLIENT_LEN,
2105                                  comment);
2106
2107   /* Remove the client from all channels. This generates new keys to the
2108      channels as well. */
2109   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2110                                    NULL, TRUE);
2111
2112   /* Remove the client entry, If it is locally connected then we will also
2113      disconnect the client here */
2114   if (remote_client->data.registered && remote_client->connection) {
2115     /* Remove locally conneted client */
2116     SilcSocketConnection sock = remote_client->connection;
2117     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2118     silc_server_close_connection(server, sock);
2119   } else {
2120     /* Remove remote client */
2121     if (!silc_idlist_del_client(server->global_list, remote_client))
2122       silc_idlist_del_client(server->local_list, remote_client);
2123   }
2124
2125  out:
2126   silc_server_command_free(cmd);
2127 }
2128
2129 /* Server side of command INFO. This sends information about us to 
2130    the client. If client requested specific server we will send the 
2131    command to that server. */
2132
2133 SILC_SERVER_CMD_FUNC(info)
2134 {
2135   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2136   SilcServer server = cmd->server;
2137   SilcBuffer packet, idp;
2138   char info_string[256], *dest_server;
2139
2140   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2141
2142   /* Get server name */
2143   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2144   if (!dest_server) {
2145     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2146                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2147     goto out;
2148   }
2149
2150   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2151     /* Send our reply */
2152     memset(info_string, 0, sizeof(info_string));
2153     snprintf(info_string, sizeof(info_string), 
2154              "location: %s server: %s admin: %s <%s>",
2155              server->config->admin_info->location,
2156              server->config->admin_info->server_type,
2157              server->config->admin_info->admin_name,
2158              server->config->admin_info->admin_email);
2159
2160     idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
2161
2162     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2163                                                   SILC_STATUS_OK, 0, 2,
2164                                                   2, idp->data, idp->len,
2165                                                   3, info_string, 
2166                                                   strlen(info_string));
2167     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2168                             packet->data, packet->len, FALSE);
2169     
2170     silc_buffer_free(packet);
2171     silc_buffer_free(idp);
2172   } else {
2173     /* Send this command to the requested server */
2174
2175     if (server->server_type == SILC_SERVER && !server->standalone) {
2176
2177     }
2178
2179     if (server->server_type == SILC_ROUTER) {
2180
2181     }
2182   }
2183   
2184  out:
2185   silc_server_command_free(cmd);
2186 }
2187
2188 /* Server side of command PING. This just replies to the ping. */
2189
2190 SILC_SERVER_CMD_FUNC(ping)
2191 {
2192   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2193   SilcServer server = cmd->server;
2194   SilcServerID *id;
2195   unsigned int len;
2196   unsigned char *tmp;
2197
2198   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2199
2200   /* Get Server ID */
2201   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2202   if (!tmp) {
2203     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2204                                           SILC_STATUS_ERR_NO_SERVER_ID);
2205     goto out;
2206   }
2207   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2208   if (!id)
2209     goto out;
2210
2211   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2212     /* Send our reply */
2213     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2214                                           SILC_STATUS_OK);
2215   } else {
2216     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2217                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2218     goto out;
2219   }
2220
2221   silc_free(id);
2222
2223  out:
2224   silc_server_command_free(cmd);
2225 }
2226
2227 /* Internal routine to join channel. The channel sent to this function
2228    has been either created or resolved from ID lists. This joins the sent
2229    client to the channel. */
2230
2231 static void silc_server_command_join_channel(SilcServer server, 
2232                                              SilcServerCommandContext cmd,
2233                                              SilcChannelEntry channel,
2234                                              SilcClientID *client_id,
2235                                              int created,
2236                                              unsigned int umode)
2237 {
2238   SilcSocketConnection sock = cmd->sock;
2239   unsigned char *tmp;
2240   unsigned int tmp_len, user_count;
2241   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2242   SilcClientEntry client;
2243   SilcChannelClientEntry chl;
2244   SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2245   unsigned short ident = silc_command_get_ident(cmd->payload);
2246
2247   SILC_LOG_DEBUG(("Start"));
2248
2249   if (!channel)
2250     return;
2251
2252   /* Get passphrase */
2253   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2254   if (tmp) {
2255     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2256     memcpy(passphrase, tmp, tmp_len);
2257   }
2258   
2259   /*
2260    * Check channel modes
2261    */
2262
2263   /* Check invite list if channel is invite-only channel */
2264   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2265     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2266       /* Invite list is specified. Check whether client is invited in the
2267          list. If not, then check whether it has been invited otherwise. */
2268
2269     } else {
2270       /* XXX client must be invited to be able to join the channel */
2271     }
2272   }
2273
2274   /* Check ban list if set */
2275   if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2276
2277   }
2278
2279   /* Check the channel passphrase if set. */
2280   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2281     if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
2282                               strlen(channel->mode_data.passphrase))) {
2283       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2284                                             SILC_STATUS_ERR_BAD_PASSWORD);
2285       goto out;
2286     }
2287   }
2288
2289   /* Check user count limit if set. */
2290   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2291     if (silc_list_count(channel->user_list) + 1 > 
2292         channel->mode_data.user_limit) {
2293       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2294                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2295       goto out;
2296     }
2297   }
2298
2299   /*
2300    * Client is allowed to join to the channel. Make it happen.
2301    */
2302
2303   /* Get the client entry */
2304   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2305     client = (SilcClientEntry)sock->user_data;
2306   } else {
2307     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2308                                            NULL);
2309     if (!client) {
2310       /* XXX actually this is useless since router finds always cell's
2311          local clients from its local lists. */
2312       client = silc_idlist_find_client_by_id(server->global_list, client_id, 
2313                                              NULL);
2314       if (!client)
2315         goto out;
2316     }
2317   }
2318
2319   /* Check whether the client already is on the channel */
2320   if (silc_server_client_on_channel(client, channel)) {
2321     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2322                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2323     goto out;
2324   }
2325
2326   /* Generate new channel key as protocol dictates */
2327   if ((!created && silc_list_count(channel->user_list) > 0) || 
2328       !channel->channel_key)
2329     silc_server_create_channel_key(server, channel, 0);
2330
2331   /* Send the channel key. This is broadcasted to the channel but is not
2332      sent to the client who is joining to the channel. */
2333   silc_server_send_channel_key(server, NULL, channel, 
2334                                server->server_type == SILC_ROUTER ? 
2335                                FALSE : !server->standalone);
2336
2337   /* Join the client to the channel by adding it to channel's user list.
2338      Add also the channel to client entry's channels list for fast cross-
2339      referencing. */
2340   chl = silc_calloc(1, sizeof(*chl));
2341   chl->mode = umode;
2342   chl->client = client;
2343   chl->channel = channel;
2344   silc_list_add(channel->user_list, chl);
2345   silc_list_add(client->channels, chl);
2346
2347   /* Get users on the channel */
2348   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2349                                    &user_count);
2350
2351   /* Encode Client ID Payload of the original client who wants to join */
2352   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2353
2354   /* Encode command reply packet */
2355   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2356   SILC_PUT32_MSB(channel->mode, mode);
2357   SILC_PUT32_MSB(created, tmp2);
2358   SILC_PUT32_MSB(user_count, tmp3);
2359   tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2360   keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2361                                          strlen(channel->channel_key->
2362                                                 cipher->name),
2363                                          channel->channel_key->cipher->name,
2364                                          channel->key_len / 8, channel->key);
2365   silc_free(tmp);
2366   if (!channel->topic) {
2367     reply = 
2368       silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2369                                            SILC_STATUS_OK, ident, 9,
2370                                            2, channel->channel_name,
2371                                            strlen(channel->channel_name),
2372                                            3, chidp->data, chidp->len,
2373                                            4, clidp->data, clidp->len,
2374                                            5, mode, 4,
2375                                            6, tmp2, 4,
2376                                            7, keyp->data, keyp->len,
2377                                            12, tmp3, 4,
2378                                            13, user_list->data, user_list->len,
2379                                            14, mode_list->data, 
2380                                            mode_list->len);
2381   } else {
2382     reply = 
2383       silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2384                                            SILC_STATUS_OK, ident, 10, 
2385                                            2, channel->channel_name, 
2386                                            strlen(channel->channel_name),
2387                                            3, chidp->data, chidp->len,
2388                                            4, clidp->data, clidp->len,
2389                                            5, mode, 4,
2390                                            6, tmp2, 4,
2391                                            7, keyp->data, keyp->len,
2392                                            10, channel->topic, 
2393                                            strlen(channel->topic),
2394                                            12, tmp3, 4,
2395                                            13, user_list->data, user_list->len,
2396                                            14, mode_list->data, 
2397                                            mode_list->len);
2398   }
2399
2400   /* Send command reply */
2401   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2402                           reply->data, reply->len, FALSE);
2403
2404   if (!cmd->pending) {
2405     /* Send JOIN notify to locally connected clients on the channel */
2406     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2407                                        SILC_NOTIFY_TYPE_JOIN, 2,
2408                                        clidp->data, clidp->len,
2409                                        chidp->data, chidp->len);
2410
2411     /* Send JOIN notify packet to our primary router */
2412     if (!server->standalone)
2413       silc_server_send_notify_join(server, server->router->connection,
2414                                    server->server_type == SILC_ROUTER ?
2415                                    TRUE : FALSE, channel, client->id,
2416                                    SILC_ID_CLIENT_LEN);
2417   }
2418
2419   silc_buffer_free(reply);
2420   silc_buffer_free(clidp);
2421   silc_buffer_free(chidp);
2422   silc_buffer_free(keyp);
2423   silc_buffer_free(user_list);
2424   silc_buffer_free(mode_list);
2425
2426  out:
2427   if (passphrase)
2428     silc_free(passphrase);
2429 }
2430
2431 /* Server side of command JOIN. Joins client into requested channel. If 
2432    the channel does not exist it will be created. */
2433
2434 SILC_SERVER_CMD_FUNC(join)
2435 {
2436   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2437   SilcServer server = cmd->server;
2438   int tmp_len;
2439   char *tmp, *channel_name = NULL, *cipher, *hmac;
2440   SilcChannelEntry channel;
2441   unsigned int umode = 0;
2442   int created = FALSE;
2443   SilcClientID *client_id;
2444
2445   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2446
2447   /* Get channel name */
2448   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2449   if (!tmp) {
2450     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2451                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2452     goto out;
2453   }
2454   channel_name = tmp;
2455
2456   if (strlen(channel_name) > 256)
2457     channel_name[255] = '\0';
2458
2459   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2460     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2461                                           SILC_STATUS_ERR_BAD_CHANNEL);
2462     silc_free(channel_name);
2463     goto out;
2464   }
2465
2466   /* Get Client ID of the client who is joining to the channel */
2467   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2468   if (!tmp) {
2469     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2470                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2471     goto out;
2472   }
2473   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2474   if (!client_id) {
2475     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2476                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2477     goto out;
2478   }
2479
2480   /* Get cipher and hmac name */
2481   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2482   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2483
2484   /* See if the channel exists */
2485   channel = silc_idlist_find_channel_by_name(server->local_list, 
2486                                              channel_name, NULL);
2487
2488   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2489     /* If this is coming from client the Client ID in the command packet must
2490        be same as the client's ID. */
2491     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2492       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2493       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2494         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2495                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2496         goto out;
2497       }
2498     }
2499
2500     if (!channel) {
2501       /* Channel not found */
2502
2503       /* If we are standalone server we don't have a router, we just create 
2504          the channel by ourselves. */
2505       if (server->standalone) {
2506         channel = silc_server_create_new_channel(server, server->id, cipher, 
2507                                                  hmac, channel_name, TRUE);
2508         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2509         created = TRUE;
2510
2511       } else {
2512
2513         /* The channel does not exist on our server. If we are normal server 
2514            we will send JOIN command to our router which will handle the
2515            joining procedure (either creates the channel if it doesn't exist 
2516            or joins the client to it). */
2517         if (server->server_type == SILC_SERVER) {
2518           SilcBuffer tmpbuf;
2519           unsigned short old_ident;
2520           
2521           old_ident = silc_command_get_ident(cmd->payload);
2522           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2523           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2524           
2525           /* Send JOIN command to our router */
2526           silc_server_packet_send(server, (SilcSocketConnection)
2527                                   server->router->connection,
2528                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2529                                   tmpbuf->data, tmpbuf->len, TRUE);
2530           
2531           /* Reprocess this packet after received reply from router */
2532           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2533                                       silc_command_get_ident(cmd->payload),
2534                                       silc_server_command_destructor,
2535                                       silc_server_command_join,
2536                                       silc_server_command_dup(cmd));
2537           cmd->pending = TRUE;
2538           return;
2539         }
2540         
2541         /* We are router and the channel does not seem exist so we will check
2542            our global list as well for the channel. */
2543         channel = silc_idlist_find_channel_by_name(server->global_list, 
2544                                                    channel_name, NULL);
2545         if (!channel) {
2546           /* Channel really does not exist, create it */
2547           channel = silc_server_create_new_channel(server, server->id, cipher, 
2548                                                    hmac, channel_name, TRUE);
2549           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2550           created = TRUE;
2551         }
2552       }
2553     }
2554   } else {
2555     if (!channel) {
2556       /* Channel not found */
2557
2558       /* If the command came from router and/or we are normal server then
2559          something went wrong with the joining as the channel was not found.
2560          We can't do anything else but ignore this. */
2561       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2562           server->server_type == SILC_SERVER)
2563         goto out;
2564       
2565       /* We are router and the channel does not seem exist so we will check
2566          our global list as well for the channel. */
2567       channel = silc_idlist_find_channel_by_name(server->global_list, 
2568                                                  channel_name, NULL);
2569       if (!channel) {
2570         /* Channel really does not exist, create it */
2571         channel = silc_server_create_new_channel(server, server->id, cipher, 
2572                                                  hmac, channel_name, TRUE);
2573         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2574         created = TRUE;
2575       }
2576     }
2577   }
2578
2579   /* If the channel does not have global users and is also empty it means the
2580      channel was created globally (by our router) and the client will be the
2581      channel founder and operator. */
2582   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2583     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2584     created = TRUE;             /* Created globally by our router */
2585   }
2586
2587   /* Join to the channel */
2588   silc_server_command_join_channel(server, cmd, channel, client_id,
2589                                    created, umode);
2590
2591   silc_free(client_id);
2592
2593  out:
2594   silc_server_command_free(cmd);
2595 }
2596
2597 /* Server side of command MOTD. Sends server's current "message of the
2598    day" to the client. */
2599
2600 SILC_SERVER_CMD_FUNC(motd)
2601 {
2602   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2603   SilcServer server = cmd->server;
2604   char *motd;
2605   int motd_len;
2606   
2607   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2608
2609   /* XXX show currently only our motd */
2610
2611   if (server->config && server->config->motd && 
2612       server->config->motd->motd_file) {
2613
2614     /* Send motd */
2615     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2616     if (!motd)
2617       goto out;
2618
2619     motd[motd_len] = 0;
2620     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2621                                          SILC_STATUS_OK,
2622                                          2, motd, motd_len);
2623     goto out;
2624   } else {
2625     /* No motd */
2626     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2627                                           SILC_STATUS_OK);
2628   }
2629
2630  out:
2631   silc_server_command_free(cmd);
2632 }
2633
2634 SILC_SERVER_CMD_FUNC(umode)
2635 {
2636 }
2637
2638 /* Checks that client has rights to add or remove channel modes. If any
2639    of the checks fails FALSE is returned. */
2640
2641 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2642                                    SilcChannelClientEntry client,
2643                                    unsigned int mode)
2644 {
2645   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2646   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2647
2648   /* Check whether has rights to change anything */
2649   if (!is_op && !is_fo)
2650     return FALSE;
2651
2652   /* Check whether has rights to change everything */
2653   if (is_op && is_fo)
2654     return TRUE;
2655
2656   /* We know that client is channel operator, check that they are not
2657      changing anything that requires channel founder rights. Rest of the
2658      modes are available automatically for channel operator. */
2659
2660   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2661     if (is_op && !is_fo)
2662       return FALSE;
2663   } else {
2664     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2665       if (is_op && !is_fo)
2666         return FALSE;
2667     }
2668   }
2669   
2670   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2671     if (is_op && !is_fo)
2672       return FALSE;
2673   } else {
2674     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2675       if (is_op && !is_fo)
2676         return FALSE;
2677     }
2678   }
2679
2680   if (mode & SILC_CHANNEL_MODE_CIPHER) {
2681     if (is_op && !is_fo)
2682       return FALSE;
2683   } else {
2684     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2685       if (is_op && !is_fo)
2686         return FALSE;
2687     }
2688   }
2689   
2690   return TRUE;
2691 }
2692
2693 /* Server side command of CMODE. Changes channel mode */
2694
2695 SILC_SERVER_CMD_FUNC(cmode)
2696 {
2697   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2698   SilcServer server = cmd->server;
2699   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2700   SilcChannelID *channel_id;
2701   SilcChannelEntry channel;
2702   SilcChannelClientEntry chl;
2703   SilcBuffer packet, cidp;
2704   unsigned char *tmp, *tmp_id, *tmp_mask;
2705   unsigned int argc, mode_mask, tmp_len, tmp_len2;
2706
2707   SILC_LOG_DEBUG(("Start"));
2708
2709   argc = silc_argument_get_arg_num(cmd->args);
2710   if (argc < 2) {
2711     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2712                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2713     goto out;
2714   }
2715   if (argc > 8) {
2716     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2717                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2718     goto out;
2719   }
2720
2721   /* Get Channel ID */
2722   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2723   if (!tmp_id) {
2724     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2725                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2726     goto out;
2727   }
2728   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2729   if (!channel_id) {
2730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2731                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2732     goto out;
2733   }
2734
2735   /* Get the channel mode mask */
2736   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2737   if (!tmp_mask) {
2738     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2739                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2740     goto out;
2741   }
2742   SILC_GET32_MSB(mode_mask, tmp_mask);
2743
2744   /* Get channel entry */
2745   channel = silc_idlist_find_channel_by_id(server->local_list, 
2746                                            channel_id, NULL);
2747   if (!channel) {
2748     channel = silc_idlist_find_channel_by_id(server->global_list, 
2749                                              channel_id, NULL);
2750     if (!channel) {
2751       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2752                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2753       goto out;
2754     }
2755   }
2756
2757   /* Check whether this client is on the channel */
2758   if (!silc_server_client_on_channel(client, channel)) {
2759     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2760                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2761     goto out;
2762   }
2763
2764   /* Get entry to the channel user list */
2765   silc_list_start(channel->user_list);
2766   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2767     if (chl->client == client)
2768       break;
2769
2770   /* Check that client has rights to change any requested channel modes */
2771   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2772     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2773                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2774     goto out;
2775   }
2776
2777   /*
2778    * Check the modes. Modes that requires nothing special operation are
2779    * not checked here.
2780    */
2781
2782   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2783     /* Channel uses private keys to protect traffic. Client(s) has set the
2784        key locally they want to use, server does not know that key. */
2785     /* Nothing interesting to do here now */
2786   } else {
2787     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2788       /* The mode is removed and we need to generate and distribute
2789          new channel key. Clients are not using private channel keys
2790          anymore after this. */
2791
2792       /* XXX Duplicated code, make own function for this!! LEAVE uses this
2793          as well */
2794
2795       /* Re-generate channel key */
2796       silc_server_create_channel_key(server, channel, 0);
2797       
2798       /* Encode channel key payload to be distributed on the channel */
2799       packet = 
2800         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2801                                         strlen(channel->channel_key->
2802                                                cipher->name),
2803                                         channel->channel_key->cipher->name,
2804                                         channel->key_len / 8, channel->key);
2805       
2806       /* If we are normal server then we will send it to our router.  If we
2807          are router we will send it to all local servers that has clients on
2808          the channel */
2809       if (server->server_type == SILC_SERVER) {
2810         if (!server->standalone)
2811           silc_server_packet_send(server, 
2812                                   cmd->server->router->connection,
2813                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2814                                   packet->len, TRUE);
2815       } else {
2816         
2817       }
2818       
2819       /* Send to locally connected clients on the channel */
2820       silc_server_packet_send_local_channel(server, channel, 
2821                                             SILC_PACKET_CHANNEL_KEY, 0,
2822                                             packet->data, packet->len, FALSE);
2823       silc_buffer_free(packet);
2824     }
2825   }
2826   
2827   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2828     /* User limit is set on channel */
2829     unsigned int user_limit;
2830       
2831     /* Get user limit */
2832     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2833     if (!tmp) {
2834       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2835         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2836                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2837         goto out;
2838       }
2839     } else {
2840       SILC_GET32_MSB(user_limit, tmp);
2841       channel->mode_data.user_limit = user_limit;
2842     }
2843   } else {
2844     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2845       /* User limit mode is unset. Remove user limit */
2846       channel->mode_data.user_limit = 0;
2847   }
2848
2849   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2850     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2851       /* Passphrase has been set to channel */
2852       
2853       /* Get the passphrase */
2854       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2855       if (!tmp) {
2856         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2857                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2858         goto out;
2859       }
2860
2861       /* Save the passphrase */
2862       channel->mode_data.passphrase = strdup(tmp);
2863     }
2864   } else {
2865     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2866       /* Passphrase mode is unset. remove the passphrase */
2867       if (channel->mode_data.passphrase) {
2868         silc_free(channel->mode_data.passphrase);
2869         channel->mode_data.passphrase = NULL;
2870       }
2871     }
2872   }
2873
2874   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2875     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2876       /* Ban list is specified for channel */
2877
2878       /* Get ban list */
2879       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2880       if (!tmp) {
2881         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2882                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2883         goto out;
2884       }
2885
2886       /* XXX check that channel founder is not banned */
2887
2888       /* Save the ban list */
2889       channel->mode_data.ban_list = strdup(tmp);
2890     }
2891   } else {
2892     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2893       /* Ban mode is unset. Remove the entire ban list */
2894       if (channel->mode_data.ban_list) {
2895         silc_free(channel->mode_data.ban_list);
2896         channel->mode_data.ban_list = NULL;
2897       }
2898     }
2899   }
2900
2901   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2902     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2903       /* Invite list is specified for channel */
2904
2905       /* Get invite list */
2906       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2907       if (!tmp) {
2908         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2909                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2910         goto out;
2911       }
2912
2913       /* Save the invite linst */
2914       channel->mode_data.invite_list = strdup(tmp);
2915     }
2916   } else {
2917     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2918       /* Invite list mode is unset. Remove the entire invite list */
2919       if (channel->mode_data.invite_list) {
2920         silc_free(channel->mode_data.invite_list);
2921         channel->mode_data.invite_list = NULL;
2922       }
2923     }
2924   }
2925
2926   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2927     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2928       /* Cipher to use protect the traffic */
2929       unsigned int key_len;
2930
2931       /* Get cipher */
2932       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2933       if (!tmp) {
2934         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2935                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2936         goto out;
2937       }
2938
2939       /* XXX Duplicated code, make own function for this!! */
2940     
2941       /* Delete old cipher and allocate the new one */
2942       silc_cipher_free(channel->channel_key);
2943       if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2944         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2945                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2946         goto out;
2947       }
2948       key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2949
2950       /* Re-generate channel key */
2951       silc_server_create_channel_key(server, channel, key_len);
2952     
2953       /* Encode channel key payload to be distributed on the channel */
2954       packet = 
2955         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2956                                         strlen(channel->channel_key->
2957                                                cipher->name),
2958                                         channel->channel_key->cipher->name,
2959                                         channel->key_len / 8, channel->key);
2960     
2961       /* If we are normal server then we will send it to our router.  If we
2962          are router we will send it to all local servers that has clients on
2963          the channel */
2964       if (server->server_type == SILC_SERVER) {
2965         if (!server->standalone)
2966           silc_server_packet_send(server, 
2967                                   cmd->server->router->connection,
2968                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2969                                   packet->len, TRUE);
2970       } else {
2971         
2972       }
2973     
2974       /* Send to locally connected clients on the channel */
2975       silc_server_packet_send_local_channel(server, channel, 
2976                                             SILC_PACKET_CHANNEL_KEY, 0,
2977                                           packet->data, packet->len, FALSE);
2978       silc_buffer_free(packet);
2979     }
2980   } else {
2981     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2982       /* Cipher mode is unset. Remove the cipher and revert back to 
2983          default cipher */
2984
2985       if (channel->mode_data.cipher) {
2986         silc_free(channel->mode_data.cipher);
2987         channel->mode_data.cipher = NULL;
2988         channel->mode_data.key_len = 0;
2989       }
2990
2991       /* Generate new cipher and key for the channel */
2992
2993       /* XXX Duplicated code, make own function for this!! */
2994
2995       /* Delete old cipher and allocate default one */
2996       silc_cipher_free(channel->channel_key);
2997       if (!channel->cipher)
2998         silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2999       else {
3000         if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
3001           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3002                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3003           goto out;
3004         }
3005       }
3006
3007       /* Re-generate channel key */
3008       silc_server_create_channel_key(server, channel, 0);
3009       
3010       /* Encode channel key payload to be distributed on the channel */
3011       packet = 
3012         silc_channel_key_payload_encode(tmp_len2, tmp_id,
3013                                         strlen(channel->channel_key->
3014                                                cipher->name),
3015                                         channel->channel_key->cipher->name,
3016                                         channel->key_len / 8, channel->key);
3017       
3018       /* If we are normal server then we will send it to our router.  If we
3019          are router we will send it to all local servers that has clients on
3020          the channel */
3021       if (server->server_type == SILC_SERVER) {
3022         if (!server->standalone)
3023           silc_server_packet_send(server, 
3024                                   cmd->server->router->connection,
3025                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3026                                   packet->len, TRUE);
3027       } else {
3028         
3029       }
3030       
3031       /* Send to locally connected clients on the channel */
3032       silc_server_packet_send_local_channel(server, channel, 
3033                                             SILC_PACKET_CHANNEL_KEY, 0,
3034                                             packet->data, packet->len, FALSE);
3035       silc_buffer_free(packet);
3036     }
3037   }
3038
3039   /* Finally, set the mode */
3040   channel->mode = mode_mask;
3041
3042   /* Send CMODE_CHANGE notify */
3043   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3044   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3045                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3046                                      cidp->data, cidp->len, 
3047                                      tmp_mask, tmp_len);
3048
3049   /* Set CMODE notify type to network */
3050   if (!server->standalone)
3051     silc_server_send_notify_cmode(server, server->router->connection,
3052                                   server->server_type == SILC_ROUTER ? 
3053                                   TRUE : FALSE, channel,
3054                                   mode_mask, client->id, SILC_ID_CLIENT_LEN);
3055
3056   /* Send command reply to sender */
3057   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3058                                                 SILC_STATUS_OK, 0, 1,
3059                                                 2, tmp_mask, 4);
3060   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3061                           packet->data, packet->len, FALSE);
3062     
3063   silc_buffer_free(packet);
3064   silc_free(channel_id);
3065   silc_free(cidp);
3066
3067  out:
3068   silc_server_command_free(cmd);
3069 }
3070
3071 /* Server side of CUMODE command. Changes client's mode on a channel. */
3072
3073 SILC_SERVER_CMD_FUNC(cumode)
3074 {
3075   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3076   SilcServer server = cmd->server;
3077   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3078   SilcChannelID *channel_id;
3079   SilcClientID *client_id;
3080   SilcChannelEntry channel;
3081   SilcClientEntry target_client;
3082   SilcChannelClientEntry chl;
3083   SilcBuffer packet, idp;
3084   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3085   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3086   int notify = FALSE;
3087
3088   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3089
3090   /* Get Channel ID */
3091   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3092   if (!tmp_ch_id) {
3093     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3094                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3095     goto out;
3096   }
3097   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3098   if (!channel_id) {
3099     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3100                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3101     goto out;
3102   }
3103
3104   /* Get channel entry */
3105   channel = silc_idlist_find_channel_by_id(server->local_list, 
3106                                            channel_id, NULL);
3107   if (!channel) {
3108     channel = silc_idlist_find_channel_by_id(server->global_list, 
3109                                              channel_id, NULL);
3110     if (!channel) {
3111       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3112                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3113       goto out;
3114     }
3115   }
3116
3117   /* Check whether sender is on the channel */
3118   if (!silc_server_client_on_channel(client, channel)) {
3119     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3120                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3121     goto out;
3122   }
3123
3124   /* Check that client has rights to change other's rights */
3125   silc_list_start(channel->user_list);
3126   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3127     if (chl->client == client) {
3128       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3129           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3130         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3131                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3132         goto out;
3133       }
3134
3135       sender_mask = chl->mode;
3136       break;
3137     }
3138   }
3139   
3140   /* Get the target client's channel mode mask */
3141   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3142   if (!tmp_mask) {
3143     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3144                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3145     goto out;
3146   }
3147   SILC_GET32_MSB(target_mask, tmp_mask);
3148
3149   /* Get target Client ID */
3150   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3151   if (!tmp_id) {
3152     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3153                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3154     goto out;
3155   }
3156   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3157   if (!client_id) {
3158     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3159                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3160     goto out;
3161   }
3162
3163   /* Get target client's entry */
3164   target_client = silc_idlist_find_client_by_id(server->local_list, 
3165                                                 client_id, NULL);
3166   if (!target_client) {
3167     target_client = silc_idlist_find_client_by_id(server->global_list, 
3168                                                   client_id, NULL);
3169   }
3170
3171   /* Check whether target client is on the channel */
3172   if (!silc_server_client_on_channel(target_client, channel)) {
3173     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3174                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3175     goto out;
3176   }
3177
3178   /* Get entry to the channel user list */
3179   silc_list_start(channel->user_list);
3180   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3181     if (chl->client == target_client)
3182       break;
3183
3184   /* 
3185    * Change the mode 
3186    */
3187
3188   /* If the target client is founder, no one else can change their mode
3189      but themselves. */
3190   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3191     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3192                                           SILC_STATUS_ERR_NOT_YOU);
3193     goto out;
3194   }
3195
3196   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3197     /* Cannot promote anyone to channel founder */
3198     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3199                                           SILC_STATUS_ERR_NOT_YOU);
3200     goto out;
3201   } else {
3202     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3203       if (target_client == client) {
3204         /* Remove channel founder rights from itself */
3205         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3206         notify = TRUE;
3207       } else {
3208         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3209                                               SILC_STATUS_ERR_NOT_YOU);
3210         goto out;
3211       }
3212     }
3213   }
3214
3215   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3216     /* Promote to operator */
3217     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3218       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3219       notify = TRUE;
3220     }
3221   } else {
3222     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3223       /* Demote to normal user */
3224       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3225       notify = TRUE;
3226     }
3227   }
3228
3229   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3230
3231   /* Send notify to channel, notify only if mode was actually changed. */
3232   if (notify) {
3233     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3234                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3235                                        idp->data, idp->len,
3236                                        tmp_mask, 4, 
3237                                        tmp_id, tmp_len);
3238
3239     /* Set CUMODE notify type to network */
3240     if (!server->standalone)
3241       silc_server_send_notify_cumode(server, server->router->connection,
3242                                      server->server_type == SILC_ROUTER ? 
3243                                      TRUE : FALSE, channel,
3244                                      target_mask, client->id, 
3245                                      SILC_ID_CLIENT_LEN,
3246                                      target_client->id, 
3247                                      SILC_ID_CLIENT_LEN);
3248   }
3249
3250   /* Send command reply to sender */
3251   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3252                                                 SILC_STATUS_OK, 0, 2,
3253                                                 2, tmp_mask, 4,
3254                                                 3, tmp_id, tmp_len);
3255   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3256                           packet->data, packet->len, FALSE);
3257     
3258   silc_buffer_free(packet);
3259   silc_free(channel_id);
3260   silc_free(client_id);
3261   silc_buffer_free(idp);
3262
3263  out:
3264   silc_server_command_free(cmd);
3265 }
3266
3267 /* Server side of KICK command. Kicks client out of channel. */
3268
3269 SILC_SERVER_CMD_FUNC(kick)
3270 {
3271   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3272   SilcServer server = cmd->server;
3273   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3274   SilcClientEntry target_client;
3275   SilcChannelID *channel_id;
3276   SilcClientID *client_id;
3277   SilcChannelEntry channel;
3278   SilcChannelClientEntry chl;
3279   SilcBuffer idp;
3280   unsigned int tmp_len;
3281   unsigned char *tmp, *comment;
3282
3283   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3284
3285   /* Get Channel ID */
3286   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3287   if (!tmp) {
3288     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3289                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3290     goto out;
3291   }
3292   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3293   if (!channel_id) {
3294     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3295                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3296     goto out;
3297   }
3298
3299   /* Get channel entry */
3300   channel = silc_idlist_find_channel_by_id(server->local_list, 
3301                                            channel_id, NULL);
3302   if (!channel) {
3303     channel = silc_idlist_find_channel_by_id(server->local_list, 
3304                                              channel_id, NULL);
3305     if (!channel) {
3306       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3307                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3308       goto out;
3309     }
3310   }
3311
3312   /* Check whether sender is on the channel */
3313   if (!silc_server_client_on_channel(client, channel)) {
3314     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3315                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3316     goto out;
3317   }
3318
3319   /* Check that the kicker is channel operator or channel founder */
3320   silc_list_start(channel->user_list);
3321   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3322     if (chl->client == client) {
3323       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3324         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3325                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3326         goto out;
3327       }
3328       break;
3329     }
3330   }
3331   
3332   /* Get target Client ID */
3333   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3334   if (!tmp) {
3335     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3336                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3337     goto out;
3338   }
3339   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3340   if (!client_id) {
3341     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3342                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3343     goto out;
3344   }
3345
3346   /* Get target client's entry */
3347   target_client = silc_idlist_find_client_by_id(server->local_list, 
3348                                                 client_id, NULL);
3349   if (!target_client) {
3350     target_client = silc_idlist_find_client_by_id(server->global_list, 
3351                                                   client_id, NULL);
3352   }
3353
3354   /* Check that the target client is not channel founder. Channel founder
3355      cannot be kicked from the channel. */
3356   silc_list_start(channel->user_list);
3357   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3358     if (chl->client == target_client) {
3359       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3360         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3361                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3362         goto out;
3363       }
3364       break;
3365     }
3366   }
3367   
3368   /* Check whether target client is on the channel */
3369   if (!silc_server_client_on_channel(target_client, channel)) {
3370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3371                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3372     goto out;
3373   }
3374
3375   /* Get comment */
3376   tmp_len = 0;
3377   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3378   if (tmp_len > 128)
3379     comment = NULL;
3380
3381   /* Send command reply to sender */
3382   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
3383                                         SILC_STATUS_OK);
3384
3385   /* Send KICKED notify to local clients on the channel */
3386   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3387   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3388                                      SILC_NOTIFY_TYPE_KICKED, 
3389                                      comment ? 2 : 1,
3390                                      idp->data, idp->len,
3391                                      comment, comment ? strlen(comment) : 0);
3392   silc_buffer_free(idp);
3393
3394   /* Remove the client from the channel. If the channel does not exist
3395      after removing the client then the client kicked itself off the channel
3396      and we don't have to send anything after that. */
3397   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
3398                                            target_client, FALSE))
3399     goto out;
3400
3401   /* Send KICKED notify to primary route */
3402   if (!server->standalone)
3403     silc_server_send_notify_kicked(server, server->router->connection,
3404                                    server->server_type == SILC_ROUTER ?
3405                                    TRUE : FALSE, channel,
3406                                    target_client->id, SILC_ID_CLIENT_LEN,
3407                                    comment);
3408
3409   /* Re-generate channel key */
3410   silc_server_create_channel_key(server, channel, 0);
3411
3412   /* Send the channel key to the channel. The key of course is not sent
3413      to the client who was kicked off the channel. */
3414   silc_server_send_channel_key(server, target_client->connection, channel, 
3415                                server->server_type == SILC_ROUTER ? 
3416                                FALSE : !server->standalone);
3417
3418  out:
3419   silc_server_command_free(cmd);
3420 }
3421
3422 /* Server side of OPER command. Client uses this comand to obtain server
3423    operator privileges to this server/router. */
3424
3425 SILC_SERVER_CMD_FUNC(oper)
3426 {
3427   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3428   SilcServer server = cmd->server;
3429   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3430   unsigned char *username, *auth;
3431   unsigned int tmp_len;
3432   SilcServerConfigSectionAdminConnection *admin;
3433   SilcIDListData idata = (SilcIDListData)client;
3434
3435   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3436
3437   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3438     goto out;
3439
3440   /* Get the username */
3441   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3442   if (!username) {
3443     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3444                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3445     goto out;
3446   }
3447
3448   /* Get the admin configuration */
3449   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3450                                         username, client->nickname);
3451   if (!admin) {
3452     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3453                                           username, client->nickname);
3454     if (!admin) {
3455       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3456                                             SILC_STATUS_ERR_AUTH_FAILED);
3457       goto out;
3458     }
3459   }
3460
3461   /* Get the authentication payload */
3462   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3463   if (!auth) {
3464     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3465                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3466     goto out;
3467   }
3468
3469   /* Verify the authentication data */
3470   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
3471                              admin->auth_data, admin->auth_data_len,
3472                              idata->hash, client->id, SILC_ID_CLIENT)) {
3473     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3474                                           SILC_STATUS_ERR_AUTH_FAILED);
3475     goto out;
3476   }
3477
3478   /* Client is now server operator */
3479   client->mode |= SILC_UMODE_SERVER_OPERATOR;
3480
3481   /* Send reply to the sender */
3482   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3483                                         SILC_STATUS_OK);
3484
3485  out:
3486   silc_server_command_free(cmd);
3487 }
3488
3489 /* Server side of SILCOPER command. Client uses this comand to obtain router
3490    operator privileges to this router. */
3491
3492 SILC_SERVER_CMD_FUNC(silcoper)
3493 {
3494   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3495   SilcServer server = cmd->server;
3496   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3497   unsigned char *username, *auth;
3498   unsigned int tmp_len;
3499   SilcServerConfigSectionAdminConnection *admin;
3500   SilcIDListData idata = (SilcIDListData)client;
3501
3502   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
3503
3504   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3505     goto out;
3506
3507   /* Get the username */
3508   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3509   if (!username) {
3510     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3511                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3512     goto out;
3513   }
3514
3515   /* Get the admin configuration */
3516   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3517                                         username, client->nickname);
3518   if (!admin) {
3519     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3520                                           username, client->nickname);
3521     if (!admin) {
3522       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3523                                             SILC_STATUS_ERR_AUTH_FAILED);
3524       goto out;
3525     }
3526   }
3527
3528   /* Get the authentication payload */
3529   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3530   if (!auth) {
3531     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3532                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3533     goto out;
3534   }
3535
3536   /* Verify the authentication data */
3537   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
3538                              admin->auth_data, admin->auth_data_len,
3539                              idata->hash, client->id, SILC_ID_CLIENT)) {
3540     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3541                                           SILC_STATUS_ERR_AUTH_FAILED);
3542     goto out;
3543   }
3544
3545   /* Client is now router operator */
3546   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
3547
3548   /* Send reply to the sender */
3549   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
3550                                         SILC_STATUS_OK);
3551
3552  out:
3553   silc_server_command_free(cmd);
3554 }
3555
3556 /* Server side command of CONNECT. Connects us to the specified remote
3557    server or router. */
3558
3559 SILC_SERVER_CMD_FUNC(connect)
3560 {
3561   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3562   SilcServer server = cmd->server;
3563   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3564   unsigned char *tmp, *host;
3565   unsigned int tmp_len;
3566   unsigned int port = SILC_PORT;
3567
3568   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3569
3570   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3571     goto out;
3572
3573   /* Check whether client has the permissions. */
3574   if (client->mode == SILC_UMODE_NONE) {
3575     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3576                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
3577     goto out;
3578   }
3579
3580   if (server->server_type == SILC_ROUTER && 
3581       client->mode & SILC_UMODE_SERVER_OPERATOR) {
3582     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3583                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
3584     goto out;
3585   }
3586
3587   /* Get the remote server */
3588   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3589   if (!host) {
3590     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3591                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3592     goto out;
3593   }
3594
3595   /* Get port */
3596   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3597   if (tmp)
3598     SILC_GET32_MSB(port, tmp);
3599
3600   /* Create the connection. It is done with timeout and is async. */
3601   silc_server_create_connection(server, host, port);
3602
3603   /* Send reply to the sender */
3604   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3605                                         SILC_STATUS_OK);
3606
3607  out:
3608   silc_server_command_free(cmd);
3609 }
3610
3611 SILC_SERVER_CMD_FUNC(restart)
3612 {
3613 }
3614
3615 /* Server side command of CLOSE. Closes connection to a specified server. */
3616  
3617 SILC_SERVER_CMD_FUNC(close)
3618 {
3619   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3620   SilcServer server = cmd->server;
3621   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3622   SilcServerEntry server_entry;
3623   SilcSocketConnection sock;
3624   unsigned char *tmp;
3625   unsigned int tmp_len;
3626   unsigned char *name;
3627   unsigned int port = SILC_PORT;
3628
3629   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3630
3631   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3632     goto out;
3633
3634   /* Check whether client has the permissions. */
3635   if (client->mode == SILC_UMODE_NONE) {
3636     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3637                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
3638     goto out;
3639   }
3640
3641   /* Get the remote server */
3642   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3643   if (!name) {
3644     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3645                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3646     goto out;
3647   }
3648
3649   /* Get port */
3650   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3651   if (tmp)
3652     SILC_GET32_MSB(port, tmp);
3653
3654   server_entry = silc_idlist_find_server_by_conn(server->local_list,
3655                                                  name, port, NULL);
3656   if (!server_entry) {
3657     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3658                                           SILC_STATUS_ERR_NO_SERVER_ID);
3659     goto out;
3660   }
3661
3662   /* Send reply to the sender */
3663   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3664                                         SILC_STATUS_OK);
3665
3666   /* Close the connection to the server */
3667   sock = (SilcSocketConnection)server_entry->connection;
3668   silc_server_free_sock_user_data(server, sock);
3669   silc_server_close_connection(server, sock);
3670   
3671  out:
3672   silc_server_command_free(cmd);
3673 }
3674
3675 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3676    active connections. */
3677  
3678 SILC_SERVER_CMD_FUNC(shutdown)
3679 {
3680   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3681   SilcServer server = cmd->server;
3682   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3683
3684   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3685
3686   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3687     goto out;
3688
3689   /* Check whether client has the permission. */
3690   if (client->mode == SILC_UMODE_NONE) {
3691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3692                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
3693     goto out;
3694   }
3695
3696   /* Send reply to the sender */
3697   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3698                                         SILC_STATUS_OK);
3699
3700   /* Then, gracefully, or not, bring the server down. */
3701   silc_server_stop(server);
3702   exit(0);
3703
3704  out:
3705   silc_server_command_free(cmd);
3706 }
3707  
3708 /* Server side command of LEAVE. Removes client from a channel. */
3709
3710 SILC_SERVER_CMD_FUNC(leave)
3711 {
3712   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3713   SilcServer server = cmd->server;
3714   SilcSocketConnection sock = cmd->sock;
3715   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3716   SilcChannelID *id;
3717   SilcChannelEntry channel;
3718   SilcBuffer packet;
3719   unsigned int i, len;
3720   unsigned char *tmp;
3721
3722   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3723
3724   /* Get Channel ID */
3725   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3726   if (!tmp) {
3727     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3728                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3729     goto out;
3730   }
3731   id = silc_id_payload_parse_id(tmp, len);
3732   if (!id) {
3733     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3734                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3735     goto out;
3736   }
3737
3738   /* Get channel entry */
3739   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3740   if (!channel) {
3741     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3742     if (!channel) {
3743       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3744                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3745       goto out;
3746     }
3747   }
3748
3749   /* Check whether this client is on the channel */
3750   if (!silc_server_client_on_channel(id_entry, channel)) {
3751     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3752                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3753     goto out;
3754   }
3755
3756   /* Notify routers that they should remove this client from their list
3757      of clients on the channel. Send LEAVE notify type. */
3758   if (!server->standalone)
3759     silc_server_send_notify_leave(server, server->router->connection,
3760                                   server->server_type == SILC_ROUTER ?
3761                                   TRUE : FALSE, channel, id_entry->id,
3762                                   SILC_ID_CLIENT_LEN);
3763
3764   /* Remove client from channel */
3765   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3766                                           TRUE);
3767   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3768                                         SILC_STATUS_OK);
3769
3770   /* If the channel does not exist anymore we won't send anything */
3771   if (!i)
3772     goto out;
3773
3774   /* Re-generate channel key */
3775   silc_server_create_channel_key(server, channel, 0);
3776
3777   /* Encode channel key payload to be distributed on the channel */
3778   packet = 
3779     silc_channel_key_payload_encode(len, tmp,
3780                                     strlen(channel->channel_key->cipher->name),
3781                                     channel->channel_key->cipher->name,
3782                                     channel->key_len / 8, channel->key);
3783
3784   /* If we are normal server then we will send it to our router.  If we
3785      are router we will send it to all local servers that has clients on
3786      the channel */
3787   if (server->server_type == SILC_SERVER) {
3788     if (!server->standalone)
3789       silc_server_packet_send(server, 
3790                               cmd->server->router->connection,
3791                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3792                               packet->len, FALSE);
3793   } else {
3794
3795   }
3796
3797   /* Send to locally connected clients on the channel */
3798   silc_server_packet_send_local_channel(server, channel, 
3799                                         SILC_PACKET_CHANNEL_KEY, 0,
3800                                         packet->data, packet->len, FALSE);
3801
3802   silc_buffer_free(packet);
3803   silc_free(id);
3804
3805  out:
3806   silc_server_command_free(cmd);
3807 }
3808
3809 /* Server side of command USERS. Resolves clients and their USERS currently
3810    joined on the requested channel. The list of Client ID's and their modes
3811    on the channel is sent back. */
3812
3813 SILC_SERVER_CMD_FUNC(users)
3814 {
3815   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3816   SilcServer server = cmd->server;
3817   SilcChannelEntry channel;
3818   SilcChannelID *id;
3819   SilcBuffer packet;
3820   unsigned char *channel_id;
3821   unsigned int channel_id_len;
3822   SilcBuffer client_id_list;
3823   SilcBuffer client_mode_list;
3824   unsigned char lc[4];
3825   unsigned int list_count = 0;
3826   unsigned short ident = silc_command_get_ident(cmd->payload);
3827
3828   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3829
3830   /* Get Channel ID */
3831   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3832   if (!channel_id) {
3833     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3834                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3835     goto out;
3836   }
3837   id = silc_id_payload_parse_id(channel_id, channel_id_len);
3838   if (!id) {
3839     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3840                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3841     goto out;
3842   }
3843
3844   /* If we are server and we don't know about this channel we will send
3845      the command to our router. If we know about the channel then we also
3846      have the list of users already. */
3847   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3848   if (!channel) {
3849     if (server->server_type == SILC_SERVER && !server->standalone &&
3850         !cmd->pending) {
3851       SilcBuffer tmpbuf;
3852       
3853       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3854       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3855       
3856       /* Send USERS command */
3857       silc_server_packet_send(server, server->router->connection,
3858                               SILC_PACKET_COMMAND, cmd->packet->flags,
3859                               tmpbuf->data, tmpbuf->len, TRUE);
3860       
3861       /* Reprocess this packet after received reply */
3862       silc_server_command_pending(server, SILC_COMMAND_USERS, 
3863                                   silc_command_get_ident(cmd->payload),
3864                                   silc_server_command_destructor,
3865                                   silc_server_command_users,
3866                                   silc_server_command_dup(cmd));
3867       cmd->pending = TRUE;
3868       silc_command_set_ident(cmd->payload, ident);
3869       
3870       silc_buffer_free(tmpbuf);
3871       silc_free(id);
3872       return;
3873     }
3874
3875     /* We are router and we will check the global list as well. */
3876     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3877     if (!channel) {
3878       /* Channel really does not exist */
3879       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3880                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3881       goto out;
3882     }
3883   }
3884
3885   /* Get the users list */
3886   silc_server_get_users_on_channel(server, channel, &client_id_list,
3887                                    &client_mode_list, &list_count);
3888
3889   /* List count */
3890   SILC_PUT32_MSB(list_count, lc);
3891
3892   /* Send reply */
3893   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3894                                                 SILC_STATUS_OK, ident, 4,
3895                                                 2, channel_id, channel_id_len,
3896                                                 3, lc, 4,
3897                                                 4, client_id_list->data,
3898                                                 client_id_list->len,
3899                                                 5, client_mode_list->data,
3900                                                 client_mode_list->len);
3901   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3902                           packet->data, packet->len, FALSE);
3903     
3904   silc_buffer_free(packet);
3905   silc_buffer_free(client_id_list);
3906   silc_buffer_free(client_mode_list);
3907   silc_free(id);
3908
3909  out:
3910   silc_server_command_free(cmd);
3911 }