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