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