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                                            9, 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, *hmac;
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 and hmac name */
2024   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2025   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2026
2027   /* See if the channel exists */
2028   channel = silc_idlist_find_channel_by_name(server->local_list, 
2029                                              channel_name, NULL);
2030
2031   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2032     /* If this is coming from client the Client ID in the command packet must
2033        be same as the client's ID. */
2034     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2035       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2036       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2037         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2038                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2039         goto out;
2040       }
2041     }
2042
2043     if (!channel) {
2044       /* Channel not found */
2045
2046       /* If we are standalone server we don't have a router, we just create 
2047          the channel by ourselves. */
2048       if (server->standalone) {
2049         channel = silc_server_create_new_channel(server, server->id, cipher, 
2050                                                  hmac, channel_name, TRUE);
2051         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2052         created = TRUE;
2053
2054       } else {
2055
2056         /* The channel does not exist on our server. If we are normal server 
2057            we will send JOIN command to our router which will handle the
2058            joining procedure (either creates the channel if it doesn't exist 
2059            or joins the client to it). */
2060         if (server->server_type == SILC_SERVER) {
2061           SilcBuffer tmpbuf;
2062           unsigned short old_ident;
2063           
2064           old_ident = silc_command_get_ident(cmd->payload);
2065           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2066           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2067           
2068           /* Send JOIN command to our router */
2069           silc_server_packet_send(server, (SilcSocketConnection)
2070                                   server->router->connection,
2071                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2072                                   tmpbuf->data, tmpbuf->len, TRUE);
2073           
2074           /* Reprocess this packet after received reply from router */
2075           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2076                                       silc_command_get_ident(cmd->payload),
2077                                       silc_server_command_destructor,
2078                                       silc_server_command_join,
2079                                       silc_server_command_dup(cmd));
2080           cmd->pending = TRUE;
2081           return;
2082         }
2083         
2084         /* We are router and the channel does not seem exist so we will check
2085            our global list as well for the channel. */
2086         channel = silc_idlist_find_channel_by_name(server->global_list, 
2087                                                    channel_name, NULL);
2088         if (!channel) {
2089           /* Channel really does not exist, create it */
2090           channel = silc_server_create_new_channel(server, server->id, cipher, 
2091                                                    hmac, channel_name, TRUE);
2092           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2093           created = TRUE;
2094         }
2095       }
2096     }
2097   } else {
2098     if (!channel) {
2099       /* Channel not found */
2100
2101       /* If the command came from router and/or we are normal server then
2102          something went wrong with the joining as the channel was not found.
2103          We can't do anything else but ignore this. */
2104       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2105           server->server_type == SILC_SERVER)
2106         goto out;
2107       
2108       /* We are router and the channel does not seem exist so we will check
2109          our global list as well for the channel. */
2110       channel = silc_idlist_find_channel_by_name(server->global_list, 
2111                                                  channel_name, NULL);
2112       if (!channel) {
2113         /* Channel really does not exist, create it */
2114         channel = silc_server_create_new_channel(server, server->id, cipher, 
2115                                                  hmac, channel_name, TRUE);
2116         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2117         created = TRUE;
2118       }
2119     }
2120   }
2121
2122   /* If the channel does not have global users and is also empty it means the
2123      channel was created globally (by our router) and the client will be the
2124      channel founder and operator. */
2125   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2126     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2127     created = TRUE;             /* Created globally by our router */
2128   }
2129
2130   /* Join to the channel */
2131   silc_server_command_join_channel(server, cmd, channel, client_id,
2132                                    created, umode);
2133
2134   silc_free(client_id);
2135
2136  out:
2137   silc_server_command_free(cmd);
2138 }
2139
2140 /* Server side of command MOTD. Sends server's current "message of the
2141    day" to the client. */
2142
2143 SILC_SERVER_CMD_FUNC(motd)
2144 {
2145   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2146   SilcServer server = cmd->server;
2147   char *motd;
2148   int motd_len;
2149   
2150   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2151
2152   /* XXX show currently only our motd */
2153
2154   if (server->config && server->config->motd && 
2155       server->config->motd->motd_file) {
2156
2157     /* Send motd */
2158     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2159     if (!motd)
2160       goto out;
2161
2162     motd[motd_len] = 0;
2163     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2164                                          SILC_STATUS_OK,
2165                                          2, motd, motd_len);
2166     goto out;
2167   } else {
2168     /* No motd */
2169     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2170                                           SILC_STATUS_OK);
2171   }
2172
2173  out:
2174   silc_server_command_free(cmd);
2175 }
2176
2177 SILC_SERVER_CMD_FUNC(umode)
2178 {
2179 }
2180
2181 /* Checks that client has rights to add or remove channel modes. If any
2182    of the checks fails FALSE is returned. */
2183
2184 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2185                                    SilcChannelClientEntry client,
2186                                    unsigned int mode)
2187 {
2188   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2189   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2190
2191   /* Check whether has rights to change anything */
2192   if (!is_op && !is_fo)
2193     return FALSE;
2194
2195   /* Check whether has rights to change everything */
2196   if (is_op && is_fo)
2197     return TRUE;
2198
2199   /* We know that client is channel operator, check that they are not
2200      changing anything that requires channel founder rights. Rest of the
2201      modes are available automatically for channel operator. */
2202
2203   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2204     if (is_op && !is_fo)
2205       return FALSE;
2206   } else {
2207     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2208       if (is_op && !is_fo)
2209         return FALSE;
2210     }
2211   }
2212   
2213   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2214     if (is_op && !is_fo)
2215       return FALSE;
2216   } else {
2217     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2218       if (is_op && !is_fo)
2219         return FALSE;
2220     }
2221   }
2222
2223   if (mode & SILC_CHANNEL_MODE_CIPHER) {
2224     if (is_op && !is_fo)
2225       return FALSE;
2226   } else {
2227     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2228       if (is_op && !is_fo)
2229         return FALSE;
2230     }
2231   }
2232   
2233   return TRUE;
2234 }
2235
2236 /* Server side command of CMODE. Changes channel mode */
2237
2238 SILC_SERVER_CMD_FUNC(cmode)
2239 {
2240   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2241   SilcServer server = cmd->server;
2242   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2243   SilcChannelID *channel_id;
2244   SilcChannelEntry channel;
2245   SilcChannelClientEntry chl;
2246   SilcBuffer packet, cidp;
2247   unsigned char *tmp, *tmp_id, *tmp_mask;
2248   unsigned int argc, mode_mask, tmp_len, tmp_len2;
2249
2250   SILC_LOG_DEBUG(("Start"));
2251
2252   argc = silc_argument_get_arg_num(cmd->args);
2253   if (argc < 2) {
2254     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2255                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2256     goto out;
2257   }
2258   if (argc > 8) {
2259     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2260                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2261     goto out;
2262   }
2263
2264   /* Get Channel ID */
2265   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2266   if (!tmp_id) {
2267     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2268                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2269     goto out;
2270   }
2271   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2272   if (!channel_id) {
2273     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2274                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2275     goto out;
2276   }
2277
2278   /* Get the channel mode mask */
2279   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2280   if (!tmp_mask) {
2281     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2282                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2283     goto out;
2284   }
2285   SILC_GET32_MSB(mode_mask, tmp_mask);
2286
2287   /* Get channel entry */
2288   channel = silc_idlist_find_channel_by_id(server->local_list, 
2289                                            channel_id, NULL);
2290   if (!channel) {
2291     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2292                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2293     goto out;
2294   }
2295
2296   /* Check whether this client is on the channel */
2297   if (!silc_server_client_on_channel(client, channel)) {
2298     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2299                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2300     goto out;
2301   }
2302
2303   /* Get entry to the channel user list */
2304   silc_list_start(channel->user_list);
2305   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2306     if (chl->client == client)
2307       break;
2308
2309   /* Check that client has rights to change any requested channel modes */
2310   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2311     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2312                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2313     goto out;
2314   }
2315
2316   /*
2317    * Check the modes. Modes that requires nothing special operation are
2318    * not checked here.
2319    */
2320
2321   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2322     /* Channel uses private keys to protect traffic. Client(s) has set the
2323        key locally they want to use, server does not know that key. */
2324     /* Nothing interesting to do here now */
2325   } else {
2326     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2327       /* The mode is removed and we need to generate and distribute
2328          new channel key. Clients are not using private channel keys
2329          anymore after this. */
2330
2331       /* XXX Duplicated code, make own function for this!! LEAVE uses this
2332          as well */
2333
2334       /* Re-generate channel key */
2335       silc_server_create_channel_key(server, channel, 0);
2336       
2337       /* Encode channel key payload to be distributed on the channel */
2338       packet = 
2339         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2340                                         strlen(channel->channel_key->
2341                                                cipher->name),
2342                                         channel->channel_key->cipher->name,
2343                                         channel->key_len / 8, channel->key);
2344       
2345       /* If we are normal server then we will send it to our router.  If we
2346          are router we will send it to all local servers that has clients on
2347          the channel */
2348       if (server->server_type == SILC_SERVER) {
2349         if (!server->standalone)
2350           silc_server_packet_send(server, 
2351                                   cmd->server->router->connection,
2352                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2353                                   packet->len, TRUE);
2354       } else {
2355         
2356       }
2357       
2358       /* Send to locally connected clients on the channel */
2359       silc_server_packet_send_local_channel(server, channel, 
2360                                             SILC_PACKET_CHANNEL_KEY, 0,
2361                                             packet->data, packet->len, FALSE);
2362       silc_buffer_free(packet);
2363     }
2364   }
2365   
2366   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2367     /* User limit is set on channel */
2368     unsigned int user_limit;
2369       
2370     /* Get user limit */
2371     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2372     if (!tmp) {
2373       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2374         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2375                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2376         goto out;
2377       }
2378     } else {
2379       SILC_GET32_MSB(user_limit, tmp);
2380       channel->mode_data.user_limit = user_limit;
2381     }
2382   } else {
2383     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2384       /* User limit mode is unset. Remove user limit */
2385       channel->mode_data.user_limit = 0;
2386   }
2387
2388   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2389     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2390       /* Passphrase has been set to channel */
2391       
2392       /* Get the passphrase */
2393       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2394       if (!tmp) {
2395         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2396                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2397         goto out;
2398       }
2399
2400       /* Save the passphrase */
2401       channel->mode_data.passphrase = strdup(tmp);
2402     }
2403   } else {
2404     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2405       /* Passphrase mode is unset. remove the passphrase */
2406       if (channel->mode_data.passphrase) {
2407         silc_free(channel->mode_data.passphrase);
2408         channel->mode_data.passphrase = NULL;
2409       }
2410     }
2411   }
2412
2413   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2414     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2415       /* Ban list is specified for channel */
2416
2417       /* Get ban list */
2418       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2419       if (!tmp) {
2420         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2421                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2422         goto out;
2423       }
2424
2425       /* XXX check that channel founder is not banned */
2426
2427       /* Save the ban list */
2428       channel->mode_data.ban_list = strdup(tmp);
2429     }
2430   } else {
2431     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2432       /* Ban mode is unset. Remove the entire ban list */
2433       if (channel->mode_data.ban_list) {
2434         silc_free(channel->mode_data.ban_list);
2435         channel->mode_data.ban_list = NULL;
2436       }
2437     }
2438   }
2439
2440   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2441     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2442       /* Invite list is specified for channel */
2443
2444       /* Get invite list */
2445       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2446       if (!tmp) {
2447         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2448                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2449         goto out;
2450       }
2451
2452       /* Save the invite linst */
2453       channel->mode_data.invite_list = strdup(tmp);
2454     }
2455   } else {
2456     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2457       /* Invite list mode is unset. Remove the entire invite list */
2458       if (channel->mode_data.invite_list) {
2459         silc_free(channel->mode_data.invite_list);
2460         channel->mode_data.invite_list = NULL;
2461       }
2462     }
2463   }
2464
2465   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2466     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2467       /* Cipher to use protect the traffic */
2468       unsigned int key_len;
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       /* XXX Duplicated code, make own function for this!! */
2479     
2480       /* Delete old cipher and allocate the new one */
2481       silc_cipher_free(channel->channel_key);
2482       if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2483         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2484                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2485         goto out;
2486       }
2487       key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2488
2489       /* Re-generate channel key */
2490       silc_server_create_channel_key(server, channel, key_len);
2491     
2492       /* Encode channel key payload to be distributed on the channel */
2493       packet = 
2494         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2495                                         strlen(channel->channel_key->
2496                                                cipher->name),
2497                                         channel->channel_key->cipher->name,
2498                                         channel->key_len / 8, channel->key);
2499     
2500       /* If we are normal server then we will send it to our router.  If we
2501          are router we will send it to all local servers that has clients on
2502          the channel */
2503       if (server->server_type == SILC_SERVER) {
2504         if (!server->standalone)
2505           silc_server_packet_send(server, 
2506                                   cmd->server->router->connection,
2507                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2508                                   packet->len, TRUE);
2509       } else {
2510         
2511       }
2512     
2513       /* Send to locally connected clients on the channel */
2514       silc_server_packet_send_local_channel(server, channel, 
2515                                             SILC_PACKET_CHANNEL_KEY, 0,
2516                                           packet->data, packet->len, FALSE);
2517       silc_buffer_free(packet);
2518     }
2519   } else {
2520     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2521       /* Cipher mode is unset. Remove the cipher and revert back to 
2522          default cipher */
2523
2524       if (channel->mode_data.cipher) {
2525         silc_free(channel->mode_data.cipher);
2526         channel->mode_data.cipher = NULL;
2527         channel->mode_data.key_len = 0;
2528       }
2529
2530       /* Generate new cipher and key for the channel */
2531
2532       /* XXX Duplicated code, make own function for this!! */
2533
2534       /* Delete old cipher and allocate default one */
2535       silc_cipher_free(channel->channel_key);
2536       if (!channel->cipher)
2537         silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2538       else {
2539         if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2540           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2541                                   SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2542           goto out;
2543         }
2544       }
2545
2546       /* Re-generate channel key */
2547       silc_server_create_channel_key(server, channel, 0);
2548       
2549       /* Encode channel key payload to be distributed on the channel */
2550       packet = 
2551         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2552                                         strlen(channel->channel_key->
2553                                                cipher->name),
2554                                         channel->channel_key->cipher->name,
2555                                         channel->key_len / 8, channel->key);
2556       
2557       /* If we are normal server then we will send it to our router.  If we
2558          are router we will send it to all local servers that has clients on
2559          the channel */
2560       if (server->server_type == SILC_SERVER) {
2561         if (!server->standalone)
2562           silc_server_packet_send(server, 
2563                                   cmd->server->router->connection,
2564                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2565                                   packet->len, TRUE);
2566       } else {
2567         
2568       }
2569       
2570       /* Send to locally connected clients on the channel */
2571       silc_server_packet_send_local_channel(server, channel, 
2572                                             SILC_PACKET_CHANNEL_KEY, 0,
2573                                             packet->data, packet->len, FALSE);
2574       silc_buffer_free(packet);
2575     }
2576   }
2577
2578   /* Finally, set the mode */
2579   channel->mode = mode_mask;
2580
2581   /* Send CMODE_CHANGE notify */
2582   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2583   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2584                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2585                                      cidp->data, cidp->len, 
2586                                      tmp_mask, tmp_len);
2587
2588   /* Set CMODE notify type to network */
2589   if (!server->standalone)
2590     silc_server_send_notify_cmode(server, server->router->connection,
2591                                   server->server_type == SILC_ROUTER ? 
2592                                   TRUE : FALSE, channel,
2593                                   mode_mask, client->id, SILC_ID_CLIENT_LEN);
2594
2595   /* Send command reply to sender */
2596   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2597                                                 SILC_STATUS_OK, 0, 1,
2598                                                 2, tmp_mask, 4);
2599   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2600                           packet->data, packet->len, FALSE);
2601     
2602   silc_buffer_free(packet);
2603   silc_free(channel_id);
2604   silc_free(cidp);
2605
2606  out:
2607   silc_server_command_free(cmd);
2608 }
2609
2610 /* Server side of CUMODE command. Changes client's mode on a channel. */
2611
2612 SILC_SERVER_CMD_FUNC(cumode)
2613 {
2614   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2615   SilcServer server = cmd->server;
2616   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2617   SilcChannelID *channel_id;
2618   SilcClientID *client_id;
2619   SilcChannelEntry channel;
2620   SilcClientEntry target_client;
2621   SilcChannelClientEntry chl;
2622   SilcBuffer packet, idp;
2623   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2624   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2625   int notify = FALSE;
2626
2627   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2628
2629   /* Get Channel ID */
2630   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2631   if (!tmp_ch_id) {
2632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2633                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2634     goto out;
2635   }
2636   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2637   if (!channel_id) {
2638     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2639                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2640     goto out;
2641   }
2642
2643   /* Get channel entry */
2644   channel = silc_idlist_find_channel_by_id(server->local_list, 
2645                                            channel_id, NULL);
2646   if (!channel) {
2647     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2648                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2649     goto out;
2650   }
2651
2652   /* Check whether sender is on the channel */
2653   if (!silc_server_client_on_channel(client, channel)) {
2654     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2655                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2656     goto out;
2657   }
2658
2659   /* Check that client has rights to change other's rights */
2660   silc_list_start(channel->user_list);
2661   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2662     if (chl->client == client) {
2663       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2664           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2665         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2666                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2667         goto out;
2668       }
2669
2670       sender_mask = chl->mode;
2671       break;
2672     }
2673   }
2674   
2675   /* Get the target client's channel mode mask */
2676   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2677   if (!tmp_mask) {
2678     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2679                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2680     goto out;
2681   }
2682   SILC_GET32_MSB(target_mask, tmp_mask);
2683
2684   /* Get target Client ID */
2685   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2686   if (!tmp_id) {
2687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2688                                           SILC_STATUS_ERR_NO_CLIENT_ID);
2689     goto out;
2690   }
2691   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2692   if (!client_id) {
2693     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2694                                           SILC_STATUS_ERR_NO_CLIENT_ID);
2695     goto out;
2696   }
2697
2698   /* Get target client's entry */
2699   target_client = silc_idlist_find_client_by_id(server->local_list, 
2700                                                 client_id, NULL);
2701   if (!target_client) {
2702     target_client = silc_idlist_find_client_by_id(server->global_list, 
2703                                                   client_id, NULL);
2704   }
2705
2706   /* Check whether target client is on the channel */
2707   if (!silc_server_client_on_channel(target_client, channel)) {
2708     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2709                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2710     goto out;
2711   }
2712
2713   /* Get entry to the channel user list */
2714   silc_list_start(channel->user_list);
2715   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2716     if (chl->client == target_client)
2717       break;
2718
2719   /* 
2720    * Change the mode 
2721    */
2722
2723   /* If the target client is founder, no one else can change their mode
2724      but themselves. */
2725   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2726     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2727                                           SILC_STATUS_ERR_NOT_YOU);
2728     goto out;
2729   }
2730
2731   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2732     /* Cannot promote anyone to channel founder */
2733     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2734                                           SILC_STATUS_ERR_NOT_YOU);
2735     goto out;
2736   } else {
2737     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2738       if (target_client == client) {
2739         /* Remove channel founder rights from itself */
2740         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2741         notify = TRUE;
2742       } else {
2743         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2744                                               SILC_STATUS_ERR_NOT_YOU);
2745         goto out;
2746       }
2747     }
2748   }
2749
2750   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2751     /* Promote to operator */
2752     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2753       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2754       notify = TRUE;
2755     }
2756   } else {
2757     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2758       /* Demote to normal user */
2759       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2760       notify = TRUE;
2761     }
2762   }
2763
2764   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2765
2766   /* Send notify to channel, notify only if mode was actually changed. */
2767   if (notify) {
2768     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2769                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2770                                        idp->data, idp->len,
2771                                        tmp_mask, 4, 
2772                                        tmp_id, tmp_len);
2773
2774     /* Set CUMODE notify type to network */
2775     if (!server->standalone)
2776       silc_server_send_notify_cumode(server, server->router->connection,
2777                                      server->server_type == SILC_ROUTER ? 
2778                                      TRUE : FALSE, channel,
2779                                      target_mask, client->id, 
2780                                      SILC_ID_CLIENT_LEN,
2781                                      target_client->id, 
2782                                      SILC_ID_CLIENT_LEN);
2783   }
2784
2785   /* Send command reply to sender */
2786   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2787                                                 SILC_STATUS_OK, 0, 2,
2788                                                 2, tmp_mask, 4,
2789                                                 3, tmp_id, tmp_len);
2790   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2791                           packet->data, packet->len, FALSE);
2792     
2793   silc_buffer_free(packet);
2794   silc_free(channel_id);
2795   silc_free(client_id);
2796   silc_buffer_free(idp);
2797
2798  out:
2799   silc_server_command_free(cmd);
2800 }
2801
2802 /* Server side of KICK command. Kicks client out of channel. */
2803
2804 SILC_SERVER_CMD_FUNC(kick)
2805 {
2806   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2807   SilcServer server = cmd->server;
2808   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2809   SilcClientEntry target_client;
2810   SilcChannelID *channel_id;
2811   SilcClientID *client_id;
2812   SilcChannelEntry channel;
2813   SilcChannelClientEntry chl;
2814   SilcBuffer idp;
2815   unsigned int tmp_len;
2816   unsigned char *tmp, *comment;
2817
2818   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2819
2820   /* Get Channel ID */
2821   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2822   if (!tmp) {
2823     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2824                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2825     goto out;
2826   }
2827   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2828   if (!channel_id) {
2829     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2830                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2831     goto out;
2832   }
2833
2834   /* Get channel entry */
2835   channel = silc_idlist_find_channel_by_id(server->local_list, 
2836                                            channel_id, NULL);
2837   if (!channel) {
2838     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2839                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2840     goto out;
2841   }
2842
2843   /* Check whether sender is on the channel */
2844   if (!silc_server_client_on_channel(client, channel)) {
2845     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2846                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2847     goto out;
2848   }
2849
2850   /* Check that the kicker is channel operator or channel founder */
2851   silc_list_start(channel->user_list);
2852   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2853     if (chl->client == client) {
2854       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2855         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2856                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2857         goto out;
2858       }
2859       break;
2860     }
2861   }
2862   
2863   /* Get target Client ID */
2864   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2865   if (!tmp) {
2866     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2867                                           SILC_STATUS_ERR_NO_CLIENT_ID);
2868     goto out;
2869   }
2870   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2871   if (!client_id) {
2872     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2873                                           SILC_STATUS_ERR_NO_CLIENT_ID);
2874     goto out;
2875   }
2876
2877   /* Get target client's entry */
2878   target_client = silc_idlist_find_client_by_id(server->local_list, 
2879                                                 client_id, NULL);
2880   if (!target_client) {
2881     target_client = silc_idlist_find_client_by_id(server->global_list, 
2882                                                   client_id, NULL);
2883   }
2884
2885   /* Check that the target client is not channel founder. Channel founder
2886      cannot be kicked from the channel. */
2887   silc_list_start(channel->user_list);
2888   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2889     if (chl->client == target_client) {
2890       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2891         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2892                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2893         goto out;
2894       }
2895       break;
2896     }
2897   }
2898   
2899   /* Check whether target client is on the channel */
2900   if (!silc_server_client_on_channel(target_client, channel)) {
2901     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2902                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2903     goto out;
2904   }
2905
2906   /* Get comment */
2907   tmp_len = 0;
2908   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2909   if (tmp_len > 128)
2910     comment = NULL;
2911
2912   /* Send command reply to sender */
2913   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
2914                                         SILC_STATUS_OK);
2915
2916   /* Send KICKED notify to local clients on the channel */
2917   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2918   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2919                                      SILC_NOTIFY_TYPE_KICKED, 
2920                                      comment ? 2 : 1,
2921                                      idp->data, idp->len,
2922                                      comment, comment ? strlen(comment) : 0);
2923   silc_buffer_free(idp);
2924
2925   /* Remove the client from the channel. If the channel does not exist
2926      after removing the client then the client kicked itself of the channel
2927      and we don't have to send anything after that. */
2928   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
2929                                            target_client, FALSE))
2930     goto out;
2931
2932   /* Send KICKED notify to primary route */
2933   if (!server->standalone)
2934     silc_server_send_notify_kicked(server, server->router->connection,
2935                                    server->server_type == SILC_ROUTER ?
2936                                    TRUE : FALSE, channel,
2937                                    target_client->id, SILC_ID_CLIENT_LEN,
2938                                    comment);
2939
2940   /* Re-generate channel key */
2941   silc_server_create_channel_key(server, channel, 0);
2942
2943   /* Send the channel key to the channel. The key of course is not sent
2944      to the client who joined the channel. */
2945   silc_server_send_channel_key(server, target_client->connection, channel, 
2946                                server->server_type == SILC_ROUTER ? 
2947                                FALSE : !server->standalone);
2948
2949  out:
2950   silc_server_command_free(cmd);
2951 }
2952
2953 SILC_SERVER_CMD_FUNC(oper)
2954 {
2955 }
2956
2957 SILC_SERVER_CMD_FUNC(silcoper)
2958 {
2959 }
2960
2961 /* Server side command of CONNECT. Connects us to the specified remote
2962    server or router. */
2963
2964 SILC_SERVER_CMD_FUNC(connect)
2965 {
2966   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2967   SilcServer server = cmd->server;
2968   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2969   unsigned char *tmp;
2970   unsigned int tmp_len;
2971   unsigned int port = SILC_PORT;
2972
2973   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
2974
2975   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2976     goto out;
2977
2978   /* Check whether client has the permissions. */
2979   if (client->mode == SILC_UMODE_NONE) {
2980     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2981                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
2982     goto out;
2983   }
2984
2985   if (server->server_type == SILC_ROUTER && 
2986       client->mode & SILC_UMODE_SERVER_OPERATOR) {
2987     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2988                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2989     goto out;
2990   }
2991
2992   /* Get the remote server */
2993   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2994   if (!tmp) {
2995     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
2996                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2997     goto out;
2998   }
2999
3000   /* Get port */
3001   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3002   if (tmp)
3003     SILC_GET32_MSB(port, tmp);
3004
3005   /* Create the connection. It is done with timeout and is async. */
3006   silc_server_create_connection(server, tmp, port);
3007
3008   /* Send reply to the sender */
3009   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3010                                         SILC_STATUS_OK);
3011
3012  out:
3013   silc_server_command_free(cmd);
3014 }
3015
3016 SILC_SERVER_CMD_FUNC(restart)
3017 {
3018 }
3019
3020 /* Server side command of CLOSE. Closes connection to a specified server. */
3021  
3022 SILC_SERVER_CMD_FUNC(close)
3023 {
3024   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3025   SilcServer server = cmd->server;
3026   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3027   SilcServerEntry server_entry;
3028   unsigned char *tmp;
3029   unsigned int tmp_len;
3030   unsigned char *name;
3031   unsigned int port = SILC_PORT;
3032
3033   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3034
3035   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3036     goto out;
3037
3038   /* Check whether client has the permissions. */
3039   if (client->mode == SILC_UMODE_NONE) {
3040     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3041                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
3042     goto out;
3043   }
3044
3045   /* Get the remote server */
3046   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3047   if (!name) {
3048     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3049                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3050     goto out;
3051   }
3052
3053   /* Get port */
3054   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3055   if (tmp)
3056     SILC_GET32_MSB(port, tmp);
3057
3058   server_entry = silc_idlist_find_server_by_conn(server->local_list,
3059                                                  name, port, NULL);
3060   if (!server_entry) {
3061     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3062                                           SILC_STATUS_ERR_NO_SERVER_ID);
3063     goto out;
3064   }
3065
3066   /* Close the connection to the server */
3067   silc_server_free_sock_user_data(server, server_entry->connection);
3068   silc_server_disconnect_remote(server, server_entry->connection,
3069                                 "Server closed connection: "
3070                                 "Closed by operator");
3071   
3072   /* Send reply to the sender */
3073   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3074                                         SILC_STATUS_OK);
3075
3076  out:
3077   silc_server_command_free(cmd);
3078 }
3079
3080 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3081    active connections. */
3082  
3083 SILC_SERVER_CMD_FUNC(shutdown)
3084 {
3085   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3086   SilcServer server = cmd->server;
3087   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3088
3089   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3090
3091   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3092     goto out;
3093
3094   /* Check whether client has the permission. */
3095   if (client->mode == SILC_UMODE_NONE) {
3096     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3097                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
3098     goto out;
3099   }
3100
3101   /* Then, gracefully, or not, bring the server down. */
3102   silc_server_stop(server);
3103
3104   /* Send reply to the sender */
3105   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3106                                         SILC_STATUS_OK);
3107
3108  out:
3109   silc_server_command_free(cmd);
3110 }
3111  
3112 /* Server side command of LEAVE. Removes client from a channel. */
3113
3114 SILC_SERVER_CMD_FUNC(leave)
3115 {
3116   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3117   SilcServer server = cmd->server;
3118   SilcSocketConnection sock = cmd->sock;
3119   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3120   SilcChannelID *id;
3121   SilcChannelEntry channel;
3122   SilcBuffer packet;
3123   unsigned int i, len;
3124   unsigned char *tmp;
3125
3126   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3127
3128   /* Get Channel ID */
3129   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3130   if (!tmp) {
3131     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3132                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3133     goto out;
3134   }
3135   id = silc_id_payload_parse_id(tmp, len);
3136   if (!id) {
3137     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3138                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3139     goto out;
3140   }
3141
3142   /* Get channel entry */
3143   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3144   if (!channel) {
3145     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3146                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3147     goto out;
3148   }
3149
3150   /* Check whether this client is on the channel */
3151   if (!silc_server_client_on_channel(id_entry, channel)) {
3152     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3153                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3154     goto out;
3155   }
3156
3157   /* Notify routers that they should remove this client from their list
3158      of clients on the channel. Send LEAVE notify type. */
3159   if (!server->standalone)
3160     silc_server_send_notify_leave(server, server->router->connection,
3161                                   server->server_type == SILC_ROUTER ?
3162                                   TRUE : FALSE, channel, id_entry->id,
3163                                   SILC_ID_CLIENT_LEN);
3164
3165   /* Remove client from channel */
3166   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3167                                           TRUE);
3168   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3169                                         SILC_STATUS_OK);
3170
3171   /* If the channel does not exist anymore we won't send anything */
3172   if (!i)
3173     goto out;
3174
3175   /* Re-generate channel key */
3176   silc_server_create_channel_key(server, channel, 0);
3177
3178   /* Encode channel key payload to be distributed on the channel */
3179   packet = 
3180     silc_channel_key_payload_encode(len, tmp,
3181                                     strlen(channel->channel_key->cipher->name),
3182                                     channel->channel_key->cipher->name,
3183                                     channel->key_len / 8, channel->key);
3184
3185   /* If we are normal server then we will send it to our router.  If we
3186      are router we will send it to all local servers that has clients on
3187      the channel */
3188   if (server->server_type == SILC_SERVER) {
3189     if (!server->standalone)
3190       silc_server_packet_send(server, 
3191                               cmd->server->router->connection,
3192                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3193                               packet->len, FALSE);
3194   } else {
3195
3196   }
3197
3198   /* Send to locally connected clients on the channel */
3199   silc_server_packet_send_local_channel(server, channel, 
3200                                         SILC_PACKET_CHANNEL_KEY, 0,
3201                                         packet->data, packet->len, FALSE);
3202
3203   silc_buffer_free(packet);
3204   silc_free(id);
3205
3206  out:
3207   silc_server_command_free(cmd);
3208 }
3209
3210 /* Server side of command USERS. Resolves clients and their USERS currently
3211    joined on the requested channel. The list of Client ID's and their modes
3212    on the channel is sent back. */
3213
3214 SILC_SERVER_CMD_FUNC(users)
3215 {
3216   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3217   SilcServer server = cmd->server;
3218   SilcChannelEntry channel;
3219   SilcChannelClientEntry chl;
3220   SilcChannelID *id;
3221   SilcBuffer packet;
3222   unsigned char *channel_id;
3223   unsigned int channel_id_len;
3224   SilcBuffer client_id_list;
3225   SilcBuffer client_mode_list;
3226   SilcBuffer idp;
3227   unsigned char lc[4];
3228   unsigned int list_count = 0;
3229   unsigned short ident = silc_command_get_ident(cmd->payload);
3230
3231   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3232
3233   /* Get Channel ID */
3234   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3235   if (!channel_id) {
3236     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3237                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3238     goto out;
3239   }
3240   id = silc_id_payload_parse_id(channel_id, channel_id_len);
3241   if (!id) {
3242     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3243                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3244     goto out;
3245   }
3246
3247   /* If we are server and we don't know about this channel we will send
3248      the command to our router. If we know about the channel then we also
3249      have the list of users already. */
3250   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3251   if (!channel) {
3252     if (server->server_type == SILC_SERVER && !server->standalone &&
3253         !cmd->pending) {
3254       SilcBuffer tmpbuf;
3255       
3256       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3257       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3258       
3259       /* Send USERS command */
3260       silc_server_packet_send(server, server->router->connection,
3261                               SILC_PACKET_COMMAND, cmd->packet->flags,
3262                               tmpbuf->data, tmpbuf->len, TRUE);
3263       
3264       /* Reprocess this packet after received reply */
3265       silc_server_command_pending(server, SILC_COMMAND_USERS, 
3266                                   silc_command_get_ident(cmd->payload),
3267                                   silc_server_command_destructor,
3268                                   silc_server_command_users,
3269                                   silc_server_command_dup(cmd));
3270       cmd->pending = TRUE;
3271       silc_command_set_ident(cmd->payload, ident);
3272       
3273       silc_buffer_free(tmpbuf);
3274       silc_free(id);
3275       return;
3276     }
3277
3278     /* We are router and we will check the global list as well. */
3279     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3280     if (!channel) {
3281       /* Channel really does not exist */
3282       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3283                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3284       goto out;
3285     }
3286   }
3287
3288   /* Assemble the lists now */
3289
3290   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
3291                                      silc_list_count(channel->user_list));
3292   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
3293   client_mode_list = 
3294     silc_buffer_alloc(4 * silc_list_count(channel->user_list));
3295   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
3296
3297   silc_list_start(channel->user_list);
3298   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3299     /* Client ID */
3300     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
3301     silc_buffer_put(client_id_list, idp->data, idp->len);
3302     silc_buffer_pull(client_id_list, idp->len);
3303     silc_buffer_free(idp);
3304
3305     /* Client's mode on channel */
3306     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
3307     silc_buffer_pull(client_mode_list, 4);
3308
3309     list_count++;
3310   }
3311   silc_buffer_push(client_id_list, 
3312                    client_id_list->data - client_id_list->head);
3313   silc_buffer_push(client_mode_list, 
3314                    client_mode_list->data - client_mode_list->head);
3315
3316   /* List count */
3317   SILC_PUT32_MSB(list_count, lc);
3318
3319   /* Send reply */
3320   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3321                                                 SILC_STATUS_OK, 0, 4,
3322                                                 2, channel_id, channel_id_len,
3323                                                 3, lc, 4,
3324                                                 4, client_id_list->data,
3325                                                 client_id_list->len,
3326                                                 5, client_mode_list->data,
3327                                                 client_mode_list->len);
3328   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3329                           packet->data, packet->len, FALSE);
3330     
3331   silc_buffer_free(packet);
3332   silc_buffer_free(client_id_list);
3333   silc_buffer_free(client_mode_list);
3334   silc_free(id);
3335
3336  out:
3337   silc_server_command_free(cmd);
3338 }