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