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