Fixed silc_server_packet_broadcast to sen correct broadcast
[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 - 2000 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 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_names(SilcServer server,
42                                     SilcSocketConnection sock,
43                                     SilcChannelEntry channel);
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(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73   SILC_SERVER_CMD(silcoper, SILCOPER,
74                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76   SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
77
78   { NULL, 0 },
79 };
80
81 /* Returns TRUE if the connection is registered. Unregistered connections
82    usually cannot send commands hence the check. */
83
84 static int silc_server_is_registered(SilcServer server,
85                                      SilcSocketConnection sock,
86                                      SilcServerCommandContext cmd,
87                                      SilcCommand command)
88 {
89   SilcIDListData idata = (SilcIDListData)sock->user_data;
90   if (idata->registered)
91     return TRUE;
92
93   silc_server_command_send_status_reply(cmd, command,
94                                         SILC_STATUS_ERR_NOT_REGISTERED);
95   silc_server_command_free(cmd);
96   return FALSE;
97 }
98
99 /* Processes received command packet. */
100
101 void silc_server_command_process(SilcServer server,
102                                  SilcSocketConnection sock,
103                                  SilcPacketContext *packet)
104 {
105   SilcServerCommandContext ctx;
106   SilcServerCommand *cmd;
107
108 #if 0
109   /* XXX allow commands in but do not execute them more than once per
110      two seconds. */
111
112   /* Check whether it is allowed for this connection to execute any
113      command. */
114   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
115     time_t curtime;
116     SilcClientEntry client = (SilcClientEntry)sock->user_data;
117
118     if (!client)
119       return;
120
121     /* Allow only one command executed in 2 seconds. */
122     curtime = time(NULL);
123     if (client->last_command && (curtime - client->last_command) < 2)
124       return;
125
126     /* Update access time */
127     client->last_command = curtime;
128   }
129 #endif
130   
131   /* Allocate command context. This must be free'd by the
132      command routine receiving it. */
133   ctx = silc_calloc(1, sizeof(*ctx));
134   ctx->server = server;
135   ctx->sock = sock;
136   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
137   
138   /* Parse the command payload in the packet */
139   ctx->payload = silc_command_payload_parse(packet->buffer);
140   if (!ctx->payload) {
141     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
142     silc_buffer_free(packet->buffer);
143     silc_packet_context_free(packet);
144     silc_free(ctx);
145     return;
146   }
147   ctx->args = silc_command_get_args(ctx->payload);
148   
149   /* Execute command. If this fails the packet is dropped. */
150   for (cmd = silc_command_list; cmd->cb; cmd++)
151     if (cmd->cmd == silc_command_get(ctx->payload)) {
152
153       if (!(cmd->flags & SILC_CF_REG)) {
154         cmd->cb(ctx);
155         break;
156       }
157       
158       if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
159         cmd->cb(ctx);
160         break;
161       }
162     }
163
164   if (cmd == NULL) {
165     SILC_LOG_ERROR(("Unknown command, packet dropped"));
166     silc_server_command_free(ctx);
167     return;
168   }
169 }
170
171 /* Add new pending command to be executed when reply to a command has been
172    received. The `reply_cmd' is the command that will call the `callback'
173    with `context' when reply has been received.  If `ident' is non-zero
174    the `callback' will be executed when received reply with command
175    identifier `ident'. */
176
177 void silc_server_command_pending(SilcServer server,
178                                  SilcCommand reply_cmd,
179                                  unsigned short ident,
180                                  SilcCommandCb callback,
181                                  void *context)
182 {
183   SilcServerCommandPending *reply;
184
185   reply = silc_calloc(1, sizeof(*reply));
186   reply->reply_cmd = reply_cmd;
187   reply->ident = ident;
188   reply->context = context;
189   reply->callback = callback;
190   silc_dlist_add(server->pending_commands, reply);
191 }
192
193 /* Deletes pending command by reply command type. */
194
195 void silc_server_command_pending_del(SilcServer server,
196                                      SilcCommand reply_cmd,
197                                      unsigned short ident)
198 {
199   SilcServerCommandPending *r;
200
201   silc_dlist_start(server->pending_commands);
202   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
203     if (r->reply_cmd == reply_cmd && r->ident == ident) {
204       silc_dlist_del(server->pending_commands, r);
205       break;
206     }
207   }
208 }
209
210 /* Checks for pending commands and marks callbacks to be called from
211    the command reply function. Returns TRUE if there were pending command. */
212
213 int silc_server_command_pending_check(SilcServer server,
214                                       SilcServerCommandReplyContext ctx,
215                                       SilcCommand command, 
216                                       unsigned short ident)
217 {
218   SilcServerCommandPending *r;
219
220   silc_dlist_start(server->pending_commands);
221   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
222     if (r->reply_cmd == command && r->ident == ident) {
223       ctx->context = r->context;
224       ctx->callback = r->callback;
225       ctx->ident = ident;
226       return TRUE;
227     }
228   }
229
230   return FALSE;
231 }
232
233 /* Free's the command context allocated before executing the command */
234
235 static void silc_server_command_free(SilcServerCommandContext cmd)
236 {
237   if (cmd) {
238     if (cmd->payload)
239       silc_command_free_payload(cmd->payload);
240     if (cmd->packet)
241       silc_packet_context_free(cmd->packet);
242     silc_free(cmd);
243   }
244 }
245
246 /* Sends simple status message as command reply packet */
247
248 static void 
249 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
250                                       SilcCommand command,
251                                       SilcCommandStatus status)
252 {
253   SilcBuffer buffer;
254
255   SILC_LOG_DEBUG(("Sending command status %d", status));
256
257   buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
258   silc_server_packet_send(cmd->server, cmd->sock,
259                           SILC_PACKET_COMMAND_REPLY, 0, 
260                           buffer->data, buffer->len, FALSE);
261   silc_buffer_free(buffer);
262 }
263
264 /* Sends command status reply with one extra argument. The argument
265    type must be sent as argument. */
266
267 static void 
268 silc_server_command_send_status_data(SilcServerCommandContext cmd,
269                                      SilcCommand command,
270                                      SilcCommandStatus status,
271                                      unsigned int arg_type,
272                                      unsigned char *arg,
273                                      unsigned int arg_len)
274 {
275   SilcBuffer buffer;
276
277   SILC_LOG_DEBUG(("Sending command status %d", status));
278
279   buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
280                                                 arg_type, arg, arg_len);
281   silc_server_packet_send(cmd->server, cmd->sock,
282                           SILC_PACKET_COMMAND_REPLY, 0, 
283                           buffer->data, buffer->len, FALSE);
284   silc_buffer_free(buffer);
285 }
286
287 /* Server side of command WHOIS. Processes user's query and sends found 
288    results as command replies back to the client. */
289
290 SILC_SERVER_CMD_FUNC(whois)
291 {
292   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
293   SilcServer server = cmd->server;
294   char *tmp, *nick = NULL, *server_name = NULL;
295   unsigned int i, argc, count = 0, len, clients_count;
296   int use_id = FALSE;
297   SilcClientID *client_id = NULL;
298   SilcBuffer packet, idp;
299   SilcClientEntry *clients = NULL, entry;
300   SilcCommandStatus status;
301
302   SILC_LOG_DEBUG(("Start"));
303
304   argc = silc_argument_get_arg_num(cmd->args);
305   if (argc < 1) {
306     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
307                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
308     goto out;
309   }
310   if (argc > 3) {
311     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
312                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
313     goto out;
314   }
315
316   /* If client ID is in the command it must be used instead of nickname */
317   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
318   if (!tmp) {
319
320     /* No ID, get the nickname@server string and parse it. */
321     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
322     if (tmp) {
323       if (strchr(tmp, '@')) {
324         len = strcspn(tmp, "@");
325         nick = silc_calloc(len + 1, sizeof(char));
326         memcpy(nick, tmp, len);
327         server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
328         memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
329       } else {
330         nick = strdup(tmp);
331       }
332     } else {
333       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
334                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
335       goto out;
336     }
337   } else {
338     /* Command includes ID, use that */
339     client_id = silc_id_payload_parse_id(tmp, len);
340     use_id = TRUE;
341   }
342
343   /* Get the max count of reply messages allowed */
344   if (argc == 3) {
345     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
346     if (!tmp) {
347       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
348                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
349       if (nick)
350         silc_free(nick);
351       if (server_name)
352         silc_free(server_name);
353       goto out;
354     }
355     count = atoi(tmp);
356   }
357
358   /* Protocol dictates that we must always send the received WHOIS request
359      to our router if we are normal server, so let's do it now unless we
360      are standalone. We will not send any replies to the client until we
361      have received reply from the router. */
362   if (!server->standalone) {
363     SilcBuffer tmpbuf;
364
365     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
366     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
367
368     /* Send WHOIS command to our router */
369     silc_server_packet_send(server, (SilcSocketConnection)
370                             server->router->connection,
371                             SILC_PACKET_COMMAND, cmd->packet->flags,
372                             tmpbuf->data, tmpbuf->len, TRUE);
373     return;
374   } else {
375     /* We are standalone, let's just do local search and send reply to
376        requesting client. */
377
378     /* Get all clients matching that nickname */
379     if (!use_id) {
380       clients = silc_idlist_get_clients_by_nickname(server->local_list, 
381                                                     nick, server_name,
382                                                     &clients_count);
383     } else {
384       entry = silc_idlist_find_client_by_id(server->local_list, client_id);
385       if (entry) {
386         clients = silc_calloc(1, sizeof(*clients));
387         clients[0] = entry;
388         clients_count = 1;
389       }
390     }
391     
392     /* If we are router then we will check our global list as well. */
393     if (server->server_type == SILC_ROUTER) {
394       entry =
395         silc_idlist_find_client_by_nickname(server->global_list,
396                                             nick, server_name);
397       if (!entry) {
398         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
399                                              SILC_STATUS_ERR_NO_SUCH_NICK,
400                                              3, tmp, strlen(tmp));
401         goto out;
402       }
403       goto ok;
404     }
405       
406 #if 0
407     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
408                                          SILC_STATUS_ERR_NO_SUCH_NICK,
409                                          3, tmp, strlen(tmp));
410     goto out;
411 #endif
412   }
413
414   /* We are standalone and will send reply to client */
415  ok:
416  
417   status = SILC_STATUS_OK;
418   if (clients_count > 1)
419     status = SILC_STATUS_LIST_START;
420
421   for (i = 0; i < clients_count; i++) {
422     entry = clients[i];
423
424     if (count && i - 1 == count)
425       break;
426
427     if (clients_count > 2)
428       status = SILC_STATUS_LIST_ITEM;
429
430     if (clients_count > 1 && i == clients_count - 1)
431       status = SILC_STATUS_LIST_END;
432
433     /* Send WHOIS reply */
434     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
435     tmp = silc_argument_get_first_arg(cmd->args, NULL);
436     
437     /* XXX */
438     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
439       char nh[256], uh[256];
440       unsigned char idle[4];
441       SilcSocketConnection hsock;
442
443       memset(uh, 0, sizeof(uh));
444       memset(nh, 0, sizeof(nh));
445       
446       strncat(nh, entry->nickname, strlen(entry->nickname));
447       strncat(nh, "@", 1);
448       len = entry->router ? strlen(entry->router->server_name) :
449         strlen(server->server_name);
450       strncat(nh, entry->router ? entry->router->server_name :
451               server->server_name, len);
452       
453       strncat(uh, entry->username, strlen(entry->username));
454       strncat(uh, "@", 1);
455       hsock = (SilcSocketConnection)entry->connection;
456       len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
457       strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
458       
459       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
460       
461       /* XXX */
462       if (entry->userinfo)
463         packet = 
464           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
465                                                status, 0, 5, 
466                                                2, idp->data, idp->len,
467                                                3, nh, strlen(nh),
468                                                4, uh, strlen(uh),
469                                                5, entry->userinfo, 
470                                                strlen(entry->userinfo),
471                                                7, idle, 4);
472       else
473         packet = 
474           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
475                                                status, 0, 4, 
476                                                2, idp->data, idp->len,
477                                                3, nh, strlen(nh),
478                                                4, uh, strlen(uh),
479                                                7, idle, 4);
480       
481     } else {
482       /* XXX */
483       packet = 
484         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS, 
485                                              status, 0, 3, 
486                                              2, idp->data, idp->len,
487                                              3, entry->nickname, 
488                                              strlen(entry->nickname),
489                                              4, tmp, strlen(tmp)); /* XXX */
490     }
491     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
492                             0, packet->data, packet->len, FALSE);
493     
494     silc_buffer_free(packet);
495     silc_buffer_free(idp);
496   }
497
498   silc_free(clients);
499
500   if (client_id)
501     silc_free(client_id);
502
503  out:
504   silc_server_command_free(cmd);
505 }
506
507 SILC_SERVER_CMD_FUNC(whowas)
508 {
509 }
510
511 SILC_SERVER_CMD_FUNC(identify)
512 {
513   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
514   SilcServer server = cmd->server;
515   char *tmp, *nick = NULL, *server_name = NULL;
516   unsigned int argc, count = 0, len;
517   int use_id = FALSE;
518   SilcClientID *client_id = NULL;
519   SilcClientEntry entry;
520   SilcBuffer packet, idp;
521
522   SILC_LOG_DEBUG(("Start"));
523
524   argc = silc_argument_get_arg_num(cmd->args);
525   if (argc < 1) {
526     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
527                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
528     goto out;
529   }
530   if (argc > 3) {
531     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
532                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
533     goto out;
534   }
535
536   /* If client ID is in the command it must be used instead of nickname */
537   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
538   if (!tmp) {
539
540     /* Get the nickname@server string and parse it. */
541     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
542     if (tmp) {
543       if (strchr(tmp, '@')) {
544         len = strcspn(tmp, "@");
545         nick = silc_calloc(len + 1, sizeof(char));
546         memcpy(nick, tmp, len);
547         server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
548         memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
549       } else {
550         nick = strdup(tmp);
551       }
552     } else {
553       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
554                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
555       goto out;
556     }
557   } else {
558     /* Command includes ID, use that */
559     client_id = silc_id_payload_parse_id(tmp, len);
560     use_id = TRUE;
561   }
562
563   /* Get the max count of reply messages allowed */
564   if (argc == 3) {
565     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
566     if (!tmp) {
567       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
568                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
569       goto out;
570     }
571     count = atoi(tmp);
572   }
573
574   /* Find client */
575   if (!use_id) {
576     entry = silc_idlist_find_client_by_nickname(server->local_list,
577                                                 nick, NULL);
578     if (!entry)
579       entry = silc_idlist_find_client_by_hash(server->global_list,
580                                               nick, server->md5hash);
581   } else {
582     entry = silc_idlist_find_client_by_id(server->local_list, client_id);
583   }
584
585   /* If client was not found and if we are normal server and are connected
586      to a router we will make global query from the router. */
587   if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
588       !cmd->pending) {
589     SilcBuffer buffer = cmd->packet->buffer;
590     
591     SILC_LOG_DEBUG(("Requesting identify from router"));
592     
593     /* Send IDENTIFY command to our router */
594     silc_buffer_push(buffer, buffer->data - buffer->head);
595     silc_server_packet_forward(server, (SilcSocketConnection)
596                                server->router->connection,
597                                buffer->data, buffer->len, TRUE);
598     return;
599   }
600
601   /* If we are router we have checked our local list by nickname and our
602      global list by hash so far. It is possible that the client is still not
603      found and we'll check it from local list by hash. */
604   if (!entry && server->server_type == SILC_ROUTER)
605     entry = silc_idlist_find_client_by_hash(server->local_list,
606                                             nick, server->md5hash);
607
608   if (!entry) {
609     /* The client definitely does not exist */
610     silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
611                                          SILC_STATUS_ERR_NO_SUCH_NICK,
612                                          3, tmp, strlen(tmp));
613     goto out;
614   }
615
616   /* Send IDENTIFY reply */
617   idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
618   tmp = silc_argument_get_first_arg(cmd->args, NULL);
619   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
620                                                 SILC_STATUS_OK, 0, 2,
621                                                 2, idp->data, idp->len, 
622                                                 3, nick, strlen(nick));
623   if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
624     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
625     silc_server_packet_send_dest(server, cmd->sock, 
626                                  SILC_PACKET_COMMAND_REPLY, 0,
627                                  id, cmd->packet->src_id_type,
628                                  packet->data, packet->len, FALSE);
629     silc_free(id);
630   } else {
631     silc_server_packet_send(server, cmd->sock, 
632                             SILC_PACKET_COMMAND_REPLY, 0, 
633                             packet->data, packet->len, FALSE);
634   }
635
636   silc_buffer_free(packet);
637   silc_buffer_free(idp);
638   if (client_id)
639     silc_free(client_id);
640
641  out:
642   if (nick)
643     silc_free(nick);
644   if (server_name)
645     silc_free(server_name);
646   silc_server_command_free(cmd);
647 }
648
649 /* Checks string for bad characters and returns TRUE if they are found. */
650
651 static int silc_server_command_bad_chars(char *nick)
652 {
653   if (strchr(nick, '\\')) return TRUE;
654   if (strchr(nick, '\"')) return TRUE;
655   if (strchr(nick, '´')) return TRUE;
656   if (strchr(nick, '`')) return TRUE;
657   if (strchr(nick, '\'')) return TRUE;
658   if (strchr(nick, '*')) return TRUE;
659   if (strchr(nick, '/')) return TRUE;
660   if (strchr(nick, '@')) return TRUE;
661
662   return FALSE;
663 }
664
665 /* Server side of command NICK. Sets nickname for user. Setting
666    nickname causes generation of a new client ID for the client. The
667    new client ID is sent to the client after changing the nickname. */
668
669 SILC_SERVER_CMD_FUNC(nick)
670 {
671   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
672   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
673   SilcServer server = cmd->server;
674   SilcBuffer packet, nidp, oidp;
675   SilcClientID *new_id;
676   char *nick;
677
678   SILC_LOG_DEBUG(("Start"));
679
680   /* Check number of arguments */
681   if (silc_argument_get_arg_num(cmd->args) < 1) {
682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
684     goto out;
685   }
686
687   /* Check nickname */
688   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
689   if (silc_server_command_bad_chars(nick) == TRUE) {
690     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
691                                           SILC_STATUS_ERR_BAD_NICKNAME);
692     goto out;
693   }
694
695   /* Create new Client ID */
696   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
697                            cmd->server->md5hash, nick,
698                            &new_id);
699
700   /* Send notify about nickname change to our router. We send the new
701      ID and ask to replace it with the old one. If we are router the
702      packet is broadcasted. */
703   if (!cmd->server->standalone)
704     silc_server_send_replace_id(server, server->router->connection, 
705                                 server->server_type == SILC_SERVER ? 
706                                 FALSE : TRUE, client->id,
707                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
708                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
709
710   /* Remove old cache entry */
711   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
712                          client->id); 
713
714   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
715
716   /* Free old ID */
717   if (client->id) {
718     memset(client->id, 0, SILC_ID_CLIENT_LEN);
719     silc_free(client->id);
720   }
721
722   /* Save the nickname as this client is our local client */
723   if (client->nickname)
724     silc_free(client->nickname);
725
726   client->nickname = strdup(nick);
727   client->id = new_id;
728
729   /* Update client cache */
730   silc_idcache_add(server->local_list->clients, client->nickname, 
731                    SILC_ID_CLIENT, client->id, (void *)client, TRUE);
732
733   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
734
735   /* Send NICK_CHANGE notify */
736   silc_server_send_notify_on_channels(server, client, 
737                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
738                                       oidp->data, oidp->len, 
739                                       nidp->data, nidp->len);
740
741   /* Send the new Client ID as reply command back to client */
742   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
743                                                 SILC_STATUS_OK, 0, 1, 
744                                                 2, nidp->data, nidp->len);
745   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
746                           0, packet->data, packet->len, FALSE);
747
748   silc_buffer_free(packet);
749   silc_buffer_free(nidp);
750   silc_buffer_free(oidp);
751   
752  out:
753   silc_server_command_free(cmd);
754 }
755
756 SILC_SERVER_CMD_FUNC(list)
757 {
758 }
759
760 /* Server side of TOPIC command. Sets topic for channel and/or returns
761    current topic to client. */
762
763 SILC_SERVER_CMD_FUNC(topic)
764 {
765   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766   SilcServer server = cmd->server;
767   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
768   SilcChannelID *channel_id;
769   SilcChannelEntry channel;
770   SilcChannelClientEntry chl;
771   SilcBuffer packet, idp;
772   unsigned char *tmp;
773   unsigned int argc, tmp_len;
774
775   /* Check number of arguments */
776   argc = silc_argument_get_arg_num(cmd->args);
777   if (argc < 1) {
778     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
779                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
780     goto out;
781   }
782   if (argc > 2) {
783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
784                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
785     goto out;
786   }
787
788   /* Get Channel ID */
789   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
790   if (!tmp) {
791     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
792                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
793     goto out;
794   }
795   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
796
797   /* Check whether the channel exists */
798   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
799   if (!channel) {
800     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
801                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
802     goto out;
803   }
804
805   if (argc > 1) {
806     /* Get the topic */
807     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
808     if (!tmp) {
809       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
810                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
811       goto out;
812     }
813
814     if (strlen(tmp) > 256) {
815       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
816                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
817       goto out;
818     }
819
820     /* See whether has rights to change topic */
821     silc_list_start(channel->user_list);
822     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
823       if (chl->client == client) {
824         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
825           silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
826                                                 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
827           goto out;
828         } else {
829           break;
830         }
831       }
832     }
833
834     /* Set the topic for channel */
835     if (channel->topic)
836       silc_free(channel->topic);
837     channel->topic = strdup(tmp);
838
839     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
840
841     /* Send notify about topic change to all clients on the channel */
842     silc_server_send_notify_to_channel(server, channel,
843                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
844                                        idp->data, idp->len,
845                                        channel->topic, strlen(channel->topic));
846     silc_buffer_free(idp);
847   }
848
849   /* Send the topic to client as reply packet */
850   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
851   if (channel->topic)
852     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
853                                                   SILC_STATUS_OK, 0, 2, 
854                                                   2, idp->data, idp->len,
855                                                   3, channel->topic, 
856                                                   strlen(channel->topic));
857   else
858     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
859                                                   SILC_STATUS_OK, 0, 1, 
860                                                   2, idp->data, idp->len);
861   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
862                           0, packet->data, packet->len, FALSE);
863
864   silc_buffer_free(packet);
865   silc_buffer_free(idp);
866   silc_free(channel_id);
867
868  out:
869   silc_server_command_free(cmd);
870 }
871
872 /* Server side of INVITE command. Invites some client to join some channel. */
873
874 SILC_SERVER_CMD_FUNC(invite)
875 {
876   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
877   SilcServer server = cmd->server;
878   SilcSocketConnection sock = cmd->sock, dest_sock;
879   SilcClientEntry sender, dest;
880   SilcClientID *dest_id;
881   SilcChannelEntry channel;
882   SilcChannelID *channel_id;
883   SilcBuffer sidp;
884   unsigned char *tmp;
885   unsigned int argc, len;
886
887   /* Check number of arguments */
888   argc = silc_argument_get_arg_num(cmd->args);
889   if (argc < 1) {
890     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
891                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
892     goto out;
893   }
894   if (argc > 2) {
895     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
896                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
897     goto out;
898   }
899
900   /* Get destination ID */
901   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
902   if (!tmp) {
903     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
904                                           SILC_STATUS_ERR_NO_CLIENT_ID);
905     goto out;
906   }
907   dest_id = silc_id_payload_parse_id(tmp, len);
908
909   /* Get Channel ID */
910   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
911   if (!tmp) {
912     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
913                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
914     goto out;
915   }
916   channel_id = silc_id_payload_parse_id(tmp, len);
917
918   /* Check whether the channel exists */
919   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
920   if (!channel) {
921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
922                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
923     goto out;
924   }
925
926   /* Check whether the sender of this command is on the channel. */
927   sender = (SilcClientEntry)sock->user_data;
928   if (!silc_server_client_on_channel(sender, channel)) {
929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
930                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
931     goto out;
932   }
933
934   /* Check whether the channel is invite-only channel. If yes then the
935      sender of this command must be at least channel operator. */
936   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
937     SilcChannelClientEntry chl;
938
939     silc_list_start(channel->user_list);
940     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
941       if (chl->client == sender) {
942         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
943           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
944                                                 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
945           goto out;
946         }
947         break;
948       }
949   }
950
951   /* Find the connection data for the destination. If it is local we will
952      send it directly otherwise we will send it to router for routing. */
953   dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
954   if (dest)
955     dest_sock = (SilcSocketConnection)dest->connection;
956   else
957     dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
958
959   /* Check whether the requested client is already on the channel. */
960   /* XXX if we are normal server we don't know about global clients on
961      the channel thus we must request it (NAMES command), check from
962      local cache as well. */
963   if (silc_server_client_on_channel(dest, channel)) {
964     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
965                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
966     goto out;
967   }
968
969   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
970
971   /* Send notify to the client that is invited to the channel */
972   silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
973                                SILC_NOTIFY_TYPE_INVITE, 2, 
974                                sidp->data, sidp->len, tmp, len);
975
976   /* Send command reply */
977   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
978                                         SILC_STATUS_OK);
979
980   silc_buffer_free(sidp);
981
982  out:
983   silc_server_command_free(cmd);
984 }
985
986 /* Quits connection to client. This gets called if client won't
987    close the connection even when it has issued QUIT command. */
988
989 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
990 {
991   SilcServer server = (SilcServer)context;
992   SilcSocketConnection sock = server->sockets[fd];
993
994   /* Free all client specific data, such as client entry and entires
995      on channels this client may be on. */
996   silc_server_free_sock_user_data(server, sock);
997
998   /* Close the connection on our side */
999   silc_server_close_connection(server, sock);
1000 }
1001
1002 /* Quits SILC session. This is the normal way to disconnect client. */
1003  
1004 SILC_SERVER_CMD_FUNC(quit)
1005 {
1006   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1007   SilcServer server = cmd->server;
1008   SilcSocketConnection sock = cmd->sock;
1009
1010   SILC_LOG_DEBUG(("Start"));
1011
1012   /* We quit the connection with little timeout */
1013   silc_task_register(server->timeout_queue, sock->sock,
1014                      silc_server_command_quit_cb, server,
1015                      0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1016
1017   silc_server_command_free(cmd);
1018 }
1019
1020 SILC_SERVER_CMD_FUNC(kill)
1021 {
1022 }
1023
1024 /* Server side of command INFO. This sends information about us to 
1025    the client. If client requested specific server we will send the 
1026    command to that server. */
1027
1028 SILC_SERVER_CMD_FUNC(info)
1029 {
1030   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1031   SilcServer server = cmd->server;
1032   SilcBuffer packet, idp;
1033   unsigned int argc;
1034   char info_string[256], *dest_server;
1035
1036   argc = silc_argument_get_arg_num(cmd->args);
1037   if (argc < 1) {
1038     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1039                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1040     goto out;
1041   }
1042   if (argc > 1) {
1043     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1044                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1045     goto out;
1046   }
1047
1048   /* Get server name */
1049   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1050   if (!dest_server) {
1051     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1052                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1053     goto out;
1054   }
1055
1056   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1057     /* Send our reply */
1058     memset(info_string, 0, sizeof(info_string));
1059     snprintf(info_string, sizeof(info_string), 
1060              "location: %s server: %s admin: %s <%s>",
1061              server->config->admin_info->location,
1062              server->config->admin_info->server_type,
1063              server->config->admin_info->admin_name,
1064              server->config->admin_info->admin_email);
1065
1066     idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1067
1068     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1069                                                   SILC_STATUS_OK, 0, 2,
1070                                                   2, idp->data, idp->len,
1071                                                   3, info_string, 
1072                                                   strlen(info_string));
1073     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1074                             packet->data, packet->len, FALSE);
1075     
1076     silc_buffer_free(packet);
1077     silc_buffer_free(idp);
1078   } else {
1079     /* Send this command to the requested server */
1080
1081     if (server->server_type == SILC_SERVER && !server->standalone) {
1082
1083     }
1084
1085     if (server->server_type == SILC_ROUTER) {
1086
1087     }
1088   }
1089   
1090  out:
1091   silc_server_command_free(cmd);
1092 }
1093
1094 SILC_SERVER_CMD_FUNC(connect)
1095 {
1096 }
1097
1098 /* Server side of command PING. This just replies to the ping. */
1099
1100 SILC_SERVER_CMD_FUNC(ping)
1101 {
1102   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1103   SilcServer server = cmd->server;
1104   SilcServerID *id;
1105   unsigned int argc, len;
1106   unsigned char *tmp;
1107
1108   argc = silc_argument_get_arg_num(cmd->args);
1109   if (argc < 1) {
1110     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1111                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1112     goto out;
1113   }
1114   if (argc > 2) {
1115     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1116                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1117     goto out;
1118   }
1119
1120   /* Get Server ID */
1121   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1122   if (!tmp) {
1123     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1124                                           SILC_STATUS_ERR_NO_SERVER_ID);
1125     goto out;
1126   }
1127   id = silc_id_payload_parse_id(tmp, len);
1128
1129   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1130     /* Send our reply */
1131     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1132                                           SILC_STATUS_OK);
1133   } else {
1134     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1135                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1136     goto out;
1137   }
1138
1139   silc_free(id);
1140
1141  out:
1142   silc_server_command_free(cmd);
1143 }
1144
1145 SILC_SERVER_CMD_FUNC(oper)
1146 {
1147 }
1148
1149 typedef struct {
1150   char *channel_name;
1151   char *nickname;
1152   char *username;
1153   char *hostname;
1154   SilcChannelEntry channel;
1155   SilcServer server;
1156   SilcClientEntry client;
1157 } JoinInternalContext;
1158
1159 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1160 {
1161   JoinInternalContext *ctx = (JoinInternalContext *)context;
1162
1163   if (ctx->channel->key && ctx->channel->key_len) {
1164     SilcBuffer clidp;
1165
1166     clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1167
1168     silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1169                                        SILC_NOTIFY_TYPE_JOIN, 1,
1170                                        clidp->data, clidp->len);
1171
1172     /* Send NAMES command reply to the joined channel so the user sees who
1173        is currently on the channel. */
1174     silc_server_command_send_names(ctx->server, ctx->client->connection, 
1175                                    ctx->channel);
1176
1177     silc_buffer_free(clidp);
1178     silc_free(ctx);
1179   } else {
1180     silc_task_register(ctx->server->timeout_queue, fd,
1181                        silc_server_command_join_notify, context,
1182                        0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1183   }
1184 }
1185
1186 /* Assembles NAMES command and executes it. This is called when client
1187    joins to a channel and we wan't to send NAMES command reply to the 
1188    client. */
1189
1190 void silc_server_command_send_names(SilcServer server,
1191                                     SilcSocketConnection sock,
1192                                     SilcChannelEntry channel)
1193 {
1194   SilcServerCommandContext cmd;
1195   SilcBuffer buffer, idp;
1196
1197   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1198   buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1199                                           1, idp->data, idp->len);
1200
1201   cmd = silc_calloc(1, sizeof(*cmd));
1202   cmd->payload = silc_command_payload_parse(buffer);
1203   cmd->args = silc_command_get_args(cmd->payload);
1204   cmd->server = server;
1205   cmd->sock = sock;
1206   cmd->pending = FALSE;
1207
1208   silc_server_command_names((void *)cmd);
1209   silc_free(buffer);
1210   silc_free(idp);
1211 }
1212
1213 /* Internal routine to join channel. The channel sent to this function
1214    has been either created or resolved from ID lists. This joins the sent
1215    client to the channel. */
1216
1217 static void
1218 silc_server_command_join_channel(SilcServer server, 
1219                                  SilcServerCommandContext cmd,
1220                                  SilcChannelEntry channel,
1221                                  unsigned int umode)
1222 {
1223   SilcSocketConnection sock = cmd->sock;
1224   unsigned char *tmp;
1225   unsigned int tmp_len;
1226   unsigned char *passphrase = NULL, mode[4];
1227   SilcClientEntry client;
1228   SilcChannelClientEntry chl;
1229   SilcBuffer packet, idp;
1230
1231   if (!channel)
1232     return;
1233
1234   /* Get passphrase */
1235   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1236   if (tmp) {
1237     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1238     memcpy(passphrase, tmp, tmp_len);
1239   }
1240   
1241   /*
1242    * Check channel modes
1243    */
1244
1245   /* Check invite list if channel is invite-only channel */
1246   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1247     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1248       /* Invite list is specified. Check whether client is invited in the
1249          list. If not, then check whether it has been invited otherwise. */
1250
1251     } else {
1252       /* XXX client must be invited to be able to join the channel */
1253     }
1254   }
1255
1256   /* Check ban list if set */
1257   if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1258
1259   }
1260
1261   /* Check the channel passphrase if set. */
1262   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1263     if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1264                               strlen(channel->mode_data.passphrase))) {
1265       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1266                                             SILC_STATUS_ERR_BAD_PASSWORD);
1267       goto out;
1268     }
1269   }
1270
1271   /* Check user count limit if set. */
1272   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1273     if (silc_list_count(channel->user_list) + 1 > 
1274         channel->mode_data.user_limit) {
1275       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1276                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
1277       goto out;
1278     }
1279   }
1280
1281   /*
1282    * Client is allowed to join to the channel. Make it happen.
1283    */
1284
1285   /* If the JOIN request was forwarded to us we will make a bit slower
1286      query to get the client pointer. Otherwise, we get the client pointer
1287      real easy. */
1288   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1289     client = (SilcClientEntry)sock->user_data;
1290   } else {
1291     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1292     client = silc_idlist_find_client_by_id(server->local_list, id);
1293     if (!client) {
1294       /* XXX */
1295       SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1296                       "wanted to join the channel"));
1297       goto out;
1298     }
1299     silc_free(id);
1300   }
1301
1302   /* Check whether the client already is on the channel */
1303   if (silc_server_client_on_channel(client, channel)) {
1304     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1305                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1306     goto out;
1307   }
1308
1309   /* Join the client to the channel by adding it to channel's user list.
1310      Add also the channel to client entry's channels list for fast cross-
1311      referencing. */
1312   chl = silc_calloc(1, sizeof(*chl));
1313   chl->mode = umode;
1314   chl->client = client;
1315   chl->channel = channel;
1316   silc_list_add(channel->user_list, chl);
1317   silc_list_add(client->channels, chl);
1318
1319   /* Notify router about new user on channel. If we are normal server
1320      we send it to our router, if we are router we send it to our
1321      primary route. */
1322   if (!server->standalone) {
1323
1324   }
1325
1326   /* Send command reply to the client. Client receives the Channe ID,
1327      channel mode and possibly other information in this reply packet. */
1328   if (!cmd->pending) {
1329     idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1330     SILC_PUT32_MSB(channel->mode, mode);
1331
1332     if (!channel->topic)
1333       packet = 
1334         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1335                                              SILC_STATUS_OK, 0, 3,
1336                                              2, channel->channel_name,
1337                                              strlen(channel->channel_name),
1338                                              3, idp->data, idp->len,
1339                                              4, mode, 4);
1340     else
1341       packet = 
1342         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1343                                              SILC_STATUS_OK, 0, 4, 
1344                                              2, channel->channel_name, 
1345                                              strlen(channel->channel_name),
1346                                              3, idp->data, idp->len,
1347                                              4, mode, 4,
1348                                              5, channel->topic, 
1349                                              strlen(channel->topic));
1350
1351     if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1352       void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1353       silc_server_packet_send_dest(cmd->server, cmd->sock, 
1354                                    SILC_PACKET_COMMAND_REPLY, 0,
1355                                    id, cmd->packet->src_id_type,
1356                                    packet->data, packet->len, FALSE);
1357       silc_free(id);
1358     } else
1359       silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1360                               packet->data, packet->len, FALSE);
1361     silc_buffer_free(packet);
1362
1363     /* Send channel key to the client. Client cannot start transmitting
1364        to the channel until we have sent the key. */
1365     tmp_len = strlen(channel->channel_key->cipher->name);
1366     packet = 
1367       silc_channel_key_payload_encode(idp->len, idp->data, 
1368                                       strlen(channel->channel_key->
1369                                              cipher->name),
1370                                       channel->channel_key->cipher->name,
1371                                       channel->key_len / 8, channel->key);
1372     
1373     silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
1374                             packet->data, packet->len, FALSE);
1375
1376     silc_buffer_free(packet);
1377     silc_buffer_free(idp);
1378   }
1379
1380   /* Finally, send notify message to all clients on the channel about
1381      new user on the channel. */
1382   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1383     if (!cmd->pending) {
1384       SilcBuffer clidp;
1385
1386       clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1387       
1388       silc_server_send_notify_to_channel(server, channel,
1389                                          SILC_NOTIFY_TYPE_JOIN, 1,
1390                                          clidp->data, clidp->len);
1391       
1392       silc_buffer_free(clidp);
1393     } else {
1394       /* This is pending command request. Send the notify after we have
1395          received the key for the channel from the router. */
1396       JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1397       ctx->channel_name = channel->channel_name;
1398       ctx->nickname = client->nickname;
1399       ctx->username = client->username;
1400       ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1401       ctx->channel = channel;
1402       ctx->server = server;
1403       ctx->client = client;
1404       silc_task_register(server->timeout_queue, sock->sock,
1405                          silc_server_command_join_notify, ctx,
1406                          0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1407       goto out;
1408     }
1409
1410     /* Send NAMES command reply to the joined channel so the user sees who
1411        is currently on the channel. */
1412     silc_server_command_send_names(server, sock, channel);
1413   }
1414
1415  out:
1416   if (passphrase)
1417     silc_free(passphrase);
1418 }
1419
1420 /* Server side of command JOIN. Joins client into requested channel. If 
1421    the channel does not exist it will be created. */
1422
1423 SILC_SERVER_CMD_FUNC(join)
1424 {
1425   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1426   SilcServer server = cmd->server;
1427   int argc, tmp_len;
1428   char *tmp, *channel_name = NULL, *cipher = NULL;
1429   SilcChannelEntry channel;
1430   unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1431
1432   SILC_LOG_DEBUG(("Start"));
1433
1434   /* Check number of parameters */
1435   argc = silc_argument_get_arg_num(cmd->args);
1436   if (argc < 1) {
1437     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1438                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1439     goto out;
1440   }
1441   if (argc > 3) {
1442     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1443                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1444     goto out;
1445   }
1446
1447   /* Get channel name */
1448   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1449   if (!tmp) {
1450     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1451                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1452     goto out;
1453   }
1454   channel_name = tmp;
1455
1456   if (silc_server_command_bad_chars(channel_name) == TRUE) {
1457     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1458                                           SILC_STATUS_ERR_BAD_CHANNEL);
1459     silc_free(channel_name);
1460     goto out;
1461   }
1462
1463   /* Get cipher name */
1464   cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1465
1466   /* See if the channel exists */
1467   channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1468   if (!channel) {
1469     /* Channel not found */
1470
1471     /* If we are standalone server we don't have a router, we just create 
1472        the channel by ourselves. */
1473     if (server->standalone) {
1474       channel = silc_server_new_channel(server, server->id, cipher, 
1475                                         channel_name);
1476     } else {
1477
1478       /* The channel does not exist on our server. We send JOIN command to
1479          our router which will handle the joining procedure (either creates
1480          the channel if it doesn't exist or joins the client to it) - if we
1481          are normal server. */
1482       if (server->server_type == SILC_SERVER) {
1483         SilcBuffer buffer = cmd->packet->buffer;
1484         
1485         /* Forward the original JOIN command to the router */
1486         silc_buffer_push(buffer, buffer->data - buffer->head);
1487         silc_server_packet_forward(server, (SilcSocketConnection)
1488                                    server->router->connection,
1489                                    buffer->data, buffer->len, TRUE);
1490         
1491         /* Add the command to be pending. It will be re-executed after
1492            router has replied back to us. */
1493         cmd->pending = TRUE;
1494         silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
1495                                     silc_server_command_join, context);
1496         return;
1497       }
1498       
1499       /* We are router and the channel does not seem exist so we will check
1500          our global list as well for the channel. */
1501       channel = silc_idlist_find_channel_by_name(server->global_list, 
1502                                                  channel_name);
1503       if (!channel) {
1504         /* Channel really does not exist, create it */
1505         channel = silc_server_new_channel(server, server->id, cipher, 
1506                                           channel_name);
1507         umode |= SILC_CHANNEL_UMODE_CHANOP;
1508         umode |= SILC_CHANNEL_UMODE_CHANFO;
1509       }
1510     }
1511   }
1512
1513   /* Join to the channel */
1514   silc_server_command_join_channel(server, cmd, channel, umode);
1515
1516  out:
1517   silc_server_command_free(cmd);
1518 }
1519
1520 /* Server side of command MOTD. Sends server's current "message of the
1521    day" to the client. */
1522
1523 SILC_SERVER_CMD_FUNC(motd)
1524 {
1525   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1526   SilcServer server = cmd->server;
1527   unsigned int argc;
1528   char *motd;
1529   int motd_len;
1530   
1531   SILC_LOG_DEBUG(("Start"));
1532
1533   argc = silc_argument_get_arg_num(cmd->args);
1534   if (argc < 1) {
1535     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1536                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1537     goto out;
1538   }
1539   if (argc > 2) {
1540     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1541                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1542     goto out;
1543   }
1544
1545   /* XXX show currently only our motd */
1546
1547   if (server->config && server->config->motd && 
1548       server->config->motd->motd_file) {
1549
1550     /* Send motd */
1551     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1552     if (!motd)
1553       goto out;
1554
1555     motd[motd_len] = 0;
1556     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1557                                          SILC_STATUS_OK,
1558                                          2, motd, motd_len);
1559     goto out;
1560   } else {
1561     /* No motd */
1562     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1563                                           SILC_STATUS_OK);
1564   }
1565
1566  out:
1567   silc_server_command_free(cmd);
1568 }
1569
1570 SILC_SERVER_CMD_FUNC(umode)
1571 {
1572 }
1573
1574 /* Checks that client has rights to add or remove channel modes. If any
1575    of the checks fails FALSE is returned. */
1576
1577 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1578                                    SilcChannelClientEntry client,
1579                                    unsigned int mode)
1580 {
1581   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1582   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1583
1584   /* Check whether has rights to change anything */
1585   if (!is_op && !is_fo)
1586     return FALSE;
1587
1588   /* Check whether has rights to change everything */
1589   if (is_op && is_fo)
1590     return TRUE;
1591
1592   /* We know that client is channel operator, check that they are not
1593      changing anything that requires channel founder rights. Rest of the
1594      modes are available automatically for channel operator. */
1595
1596   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1597     if (is_op && !is_fo)
1598       return FALSE;
1599   } else {
1600     if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1601       if (is_op && !is_fo)
1602         return FALSE;
1603     }
1604   }
1605   
1606   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1607     if (is_op && !is_fo)
1608       return FALSE;
1609   } else {
1610     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1611       if (is_op && !is_fo)
1612         return FALSE;
1613     }
1614   }
1615
1616   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1617     if (is_op && !is_fo)
1618       return FALSE;
1619   } else {
1620     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1621       if (is_op && !is_fo)
1622         return FALSE;
1623     }
1624   }
1625   
1626   return TRUE;
1627 }
1628
1629 /* Server side command of CMODE. Changes channel mode */
1630
1631 SILC_SERVER_CMD_FUNC(cmode)
1632 {
1633   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1634   SilcServer server = cmd->server;
1635   SilcSocketConnection sock = cmd->sock;
1636   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1637   SilcChannelID *channel_id;
1638   SilcClientID *client_id;
1639   SilcChannelEntry channel;
1640   SilcChannelClientEntry chl;
1641   SilcBuffer packet, cidp;
1642   unsigned char *tmp, *tmp_id, *tmp_mask;
1643   unsigned int argc, mode_mask, tmp_len, tmp_len2;
1644   int i;
1645
1646   SILC_LOG_DEBUG(("Start"));
1647
1648   argc = silc_argument_get_arg_num(cmd->args);
1649   if (argc < 2) {
1650     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1651                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1652     goto out;
1653   }
1654   if (argc > 8) {
1655     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1656                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1657     goto out;
1658   }
1659
1660   /* Get Channel ID */
1661   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1662   if (!tmp_id) {
1663     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1664                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1665     goto out;
1666   }
1667   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1668
1669   /* Get the channel mode mask */
1670   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1671   if (!tmp_mask) {
1672     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1673                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1674     goto out;
1675   }
1676   SILC_GET32_MSB(mode_mask, tmp_mask);
1677
1678   /* Get channel entry */
1679   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1680   if (!channel) {
1681     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1682                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1683     goto out;
1684   }
1685
1686   /* Check whether this client is on the channel */
1687   if (!silc_server_client_on_channel(client, channel)) {
1688     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1689                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1690     goto out;
1691   }
1692
1693   /* Get entry to the channel user list */
1694   silc_list_start(channel->user_list);
1695   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1696     if (chl->client == client)
1697       break;
1698
1699   /* Check that client has rights to change any requested channel modes */
1700   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1701     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1702                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1703     goto out;
1704   }
1705
1706   /*
1707    * Check the modes. Modes that requires nothing special operation are
1708    * not checked here.
1709    */
1710
1711   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1712     /* Channel uses private keys to protect traffic. Client(s) has set the
1713        key locally they want to use, server does not know that key. */
1714     /* Nothing interesting to do here now */
1715   } else {
1716     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1717       /* The mode is removed and we need to generate and distribute
1718          new channel key. Clients are not using private channel keys
1719          anymore after this. */
1720       unsigned int key_len;
1721       unsigned char channel_key[32];
1722
1723       /* XXX Duplicated code, make own function for this!! LEAVE uses this
1724          as well */
1725
1726       /* Re-generate channel key */
1727       key_len = channel->key_len / 8;
1728       for (i = 0; i < key_len; i++)
1729         channel_key[i] = silc_rng_get_byte(server->rng);
1730       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1731                                             channel_key, key_len);
1732       memset(channel->key, 0, key_len);
1733       silc_free(channel->key);
1734       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1735       memcpy(channel->key, channel_key, key_len);
1736       memset(channel_key, 0, sizeof(channel_key));
1737       
1738       /* Encode channel key payload to be distributed on the channel */
1739       packet = 
1740         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1741                                         strlen(channel->channel_key->
1742                                                cipher->name),
1743                                         channel->channel_key->cipher->name,
1744                                         key_len, channel->key);
1745       
1746       /* If we are normal server then we will send it to our router.  If we
1747          are router we will send it to all local servers that has clients on
1748          the channel */
1749       if (server->server_type == SILC_SERVER) {
1750         if (!server->standalone)
1751           silc_server_packet_send(server, 
1752                                   cmd->server->router->connection,
1753                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1754                                   packet->len, TRUE);
1755       } else {
1756         
1757       }
1758       
1759       /* Send to locally connected clients on the channel */
1760       silc_server_packet_send_local_channel(server, channel, 
1761                                             SILC_PACKET_CHANNEL_KEY, 0,
1762                                             packet->data, packet->len, FALSE);
1763       silc_buffer_free(packet);
1764     }
1765   }
1766   
1767   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1768     /* User limit is set on channel */
1769     unsigned int user_limit;
1770       
1771     /* Get user limit */
1772     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1773     if (!tmp) {
1774       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1775         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1776                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1777         goto out;
1778       }
1779     } else {
1780       SILC_GET32_MSB(user_limit, tmp);
1781       channel->mode_data.user_limit = user_limit;
1782     }
1783   } else {
1784     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1785       /* User limit mode is unset. Remove user limit */
1786       channel->mode_data.user_limit = 0;
1787   }
1788
1789   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1790     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1791       /* Passphrase has been set to channel */
1792       
1793       /* Get the passphrase */
1794       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1795       if (!tmp) {
1796         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1797                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1798         goto out;
1799       }
1800
1801       /* Save the passphrase */
1802       channel->mode_data.passphrase = strdup(tmp);
1803     }
1804   } else {
1805     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1806       /* Passphrase mode is unset. remove the passphrase */
1807       if (channel->mode_data.passphrase) {
1808         silc_free(channel->mode_data.passphrase);
1809         channel->mode_data.passphrase = NULL;
1810       }
1811     }
1812   }
1813
1814   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1815     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1816       /* Ban list is specified for channel */
1817
1818       /* Get ban list */
1819       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1820       if (!tmp) {
1821         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1822                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1823         goto out;
1824       }
1825
1826       /* XXX check that channel founder is not banned */
1827
1828       /* Save the ban list */
1829       channel->mode_data.ban_list = strdup(tmp);
1830     }
1831   } else {
1832     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1833       /* Ban mode is unset. Remove the entire ban list */
1834       if (channel->mode_data.ban_list) {
1835         silc_free(channel->mode_data.ban_list);
1836         channel->mode_data.ban_list = NULL;
1837       }
1838     }
1839   }
1840
1841   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1842     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1843       /* Invite list is specified for channel */
1844
1845       /* Get invite list */
1846       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1847       if (!tmp) {
1848         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1849                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1850         goto out;
1851       }
1852
1853       /* Save the invite linst */
1854       channel->mode_data.invite_list = strdup(tmp);
1855     }
1856   } else {
1857     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1858       /* Invite list mode is unset. Remove the entire invite list */
1859       if (channel->mode_data.invite_list) {
1860         silc_free(channel->mode_data.invite_list);
1861         channel->mode_data.invite_list = NULL;
1862       }
1863     }
1864   }
1865
1866   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1867     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1868       /* Cipher to use protect the traffic */
1869       unsigned int key_len = 128;
1870       unsigned char channel_key[32];
1871       char *cp;
1872
1873       /* Get cipher */
1874       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1875       if (!tmp) {
1876         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1877                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1878         goto out;
1879       }
1880
1881       cp = strchr(tmp, ':');
1882       if (cp) {
1883         key_len = atoi(cp);
1884         *cp = '\0';
1885       }
1886
1887       /* XXX Duplicated code, make own function for this!! */
1888     
1889       /* Delete old cipher and allocate the new one */
1890       silc_cipher_free(channel->channel_key);
1891       silc_cipher_alloc(tmp, &channel->channel_key);
1892
1893       /* Re-generate channel key */
1894       key_len /= 8;
1895       if (key_len > sizeof(channel_key))
1896         key_len = sizeof(channel_key);
1897
1898       for (i = 0; i < key_len; i++)
1899         channel_key[i] = silc_rng_get_byte(server->rng);
1900       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1901                                             channel_key, key_len);
1902       memset(channel->key, 0, key_len);
1903       silc_free(channel->key);
1904       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1905       memcpy(channel->key, channel_key, key_len);
1906       memset(channel_key, 0, sizeof(channel_key));
1907     
1908       /* Encode channel key payload to be distributed on the channel */
1909       packet = 
1910         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1911                                         strlen(channel->channel_key->
1912                                                cipher->name),
1913                                         channel->channel_key->cipher->name,
1914                                         key_len, channel->key);
1915     
1916       /* If we are normal server then we will send it to our router.  If we
1917          are router we will send it to all local servers that has clients on
1918          the channel */
1919       if (server->server_type == SILC_SERVER) {
1920         if (!server->standalone)
1921           silc_server_packet_send(server, 
1922                                   cmd->server->router->connection,
1923                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1924                                   packet->len, TRUE);
1925       } else {
1926         
1927       }
1928     
1929       /* Send to locally connected clients on the channel */
1930       silc_server_packet_send_local_channel(server, channel, 
1931                                             SILC_PACKET_CHANNEL_KEY, 0,
1932                                           packet->data, packet->len, FALSE);
1933       silc_buffer_free(packet);
1934     }
1935   } else {
1936     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1937       /* Cipher mode is unset. Remove the cipher and revert back to 
1938          default cipher */
1939       unsigned int key_len;
1940       unsigned char channel_key[32];
1941
1942       if (channel->mode_data.cipher) {
1943         silc_free(channel->mode_data.cipher);
1944         channel->mode_data.cipher = NULL;
1945         channel->mode_data.key_len = 0;
1946       }
1947
1948       /* Generate new cipher and key for the channel */
1949
1950       /* XXX Duplicated code, make own function for this!! */
1951
1952       /* Delete old cipher and allocate default one */
1953       silc_cipher_free(channel->channel_key);
1954       if (!channel->cipher)
1955         silc_cipher_alloc("twofish", &channel->channel_key);
1956       else
1957         silc_cipher_alloc(channel->cipher, &channel->channel_key);
1958
1959       /* Re-generate channel key */
1960       key_len = channel->key_len / 8;
1961       for (i = 0; i < key_len; i++)
1962         channel_key[i] = silc_rng_get_byte(server->rng);
1963       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1964                                             channel_key, key_len);
1965       memset(channel->key, 0, key_len);
1966       silc_free(channel->key);
1967       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1968       memcpy(channel->key, channel_key, key_len);
1969       memset(channel_key, 0, sizeof(channel_key));
1970       
1971       /* Encode channel key payload to be distributed on the channel */
1972       packet = 
1973         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1974                                         strlen(channel->channel_key->
1975                                                cipher->name),
1976                                         channel->channel_key->cipher->name,
1977                                         key_len, channel->key);
1978       
1979       /* If we are normal server then we will send it to our router.  If we
1980          are router we will send it to all local servers that has clients on
1981          the channel */
1982       if (server->server_type == SILC_SERVER) {
1983         if (!server->standalone)
1984           silc_server_packet_send(server, 
1985                                   cmd->server->router->connection,
1986                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1987                                   packet->len, TRUE);
1988       } else {
1989         
1990       }
1991       
1992       /* Send to locally connected clients on the channel */
1993       silc_server_packet_send_local_channel(server, channel, 
1994                                             SILC_PACKET_CHANNEL_KEY, 0,
1995                                             packet->data, packet->len, FALSE);
1996       silc_buffer_free(packet);
1997     }
1998   }
1999
2000   /* Finally, set the mode */
2001   channel->mode = mode_mask;
2002
2003   /* Send CMODE_CHANGE notify */
2004   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2005   silc_server_send_notify_to_channel(server, channel, 
2006                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2007                                      cidp->data, cidp->len, 
2008                                      tmp_mask, tmp_len);
2009   silc_free(cidp);
2010
2011   /* Send command reply to sender */
2012   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2013                                                 SILC_STATUS_OK, 0, 1,
2014                                                 2, tmp_mask, 4);
2015   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2016                           packet->data, packet->len, FALSE);
2017     
2018   silc_buffer_free(packet);
2019   silc_free(channel_id);
2020
2021  out:
2022   silc_server_command_free(cmd);
2023 }
2024
2025 /* Server side of CUMODE command. Changes client's mode on a channel. */
2026
2027 SILC_SERVER_CMD_FUNC(cumode)
2028 {
2029   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2030   SilcServer server = cmd->server;
2031   SilcSocketConnection sock = cmd->sock;
2032   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2033   SilcChannelID *channel_id;
2034   SilcClientID *client_id;
2035   SilcChannelEntry channel;
2036   SilcClientEntry target_client;
2037   SilcChannelClientEntry chl;
2038   SilcBuffer packet, idp;
2039   unsigned char *tmp, *tmp_id, *tmp_mask;
2040   unsigned int argc, target_mask, sender_mask, tmp_len;
2041   int i, notify = FALSE;
2042
2043   SILC_LOG_DEBUG(("Start"));
2044
2045   argc = silc_argument_get_arg_num(cmd->args);
2046   if (argc < 3) {
2047     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2048                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2049     goto out;
2050   }
2051   if (argc > 3) {
2052     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2053                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2054     goto out;
2055   }
2056
2057   /* Get Channel ID */
2058   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2059   if (!tmp_id) {
2060     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2061                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2062     goto out;
2063   }
2064   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2065
2066   /* Get channel entry */
2067   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2068   if (!channel) {
2069     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2070                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2071     goto out;
2072   }
2073
2074   /* Check whether sender is on the channel */
2075   if (!silc_server_client_on_channel(client, channel)) {
2076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2077                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2078     goto out;
2079   }
2080
2081   /* Check that client has rights to change other's rights */
2082   silc_list_start(channel->user_list);
2083   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2084     if (chl->client == client) {
2085       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2086           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2087         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2088                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2089         goto out;
2090       }
2091
2092       sender_mask = chl->mode;
2093       break;
2094     }
2095   }
2096   
2097   /* Get the target client's channel mode mask */
2098   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2099   if (!tmp_mask) {
2100     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2101                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2102     goto out;
2103   }
2104   SILC_GET32_MSB(target_mask, tmp_mask);
2105
2106   /* Get target Client ID */
2107   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2108   if (!tmp_id) {
2109     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2110                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2111     goto out;
2112   }
2113   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2114
2115   /* Get target client's entry */
2116   target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2117   if (!client) {
2118     /* XXX If target client is not one of mine send to primary route */
2119   }
2120
2121   /* Check whether target client is on the channel */
2122   if (!silc_server_client_on_channel(target_client, channel)) {
2123     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2124                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2125     goto out;
2126   }
2127
2128   /* Get entry to the channel user list */
2129   silc_list_start(channel->user_list);
2130   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2131     if (chl->client == target_client)
2132       break;
2133
2134   /* 
2135    * Change the mode 
2136    */
2137
2138   /* If the target client is founder, no one else can change their mode
2139      but themselves. */
2140   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2141     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2142                                           SILC_STATUS_ERR_NOT_YOU);
2143     goto out;
2144   }
2145
2146   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2147     /* Cannot promote anyone to channel founder */
2148     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2149                                           SILC_STATUS_ERR_NOT_YOU);
2150     goto out;
2151   } else {
2152     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2153       if (target_client == client) {
2154         /* Remove channel founder rights from itself */
2155         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2156         notify = TRUE;
2157       } else {
2158         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2159                                               SILC_STATUS_ERR_NOT_YOU);
2160         goto out;
2161       }
2162     }
2163   }
2164
2165   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2166     /* Promote to operator */
2167     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2168       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2169       notify = TRUE;
2170     }
2171   } else {
2172     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2173       /* Demote to normal user */
2174       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2175       notify = TRUE;
2176     }
2177   }
2178
2179   /* Send notify to channel, notify only if mode was actually changed. */
2180   if (notify) {
2181     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2182     silc_server_send_notify_to_channel(server, channel,
2183                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2184                                        idp->data, idp->len,
2185                                        tmp_mask, 4, tmp_id, tmp_len);
2186     silc_buffer_free(idp);
2187   }
2188
2189   /* Send command reply to sender */
2190   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2191                                                 SILC_STATUS_OK, 0, 2,
2192                                                 2, tmp_mask, 4,
2193                                                 3, tmp_id, tmp_len);
2194   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2195                           packet->data, packet->len, FALSE);
2196     
2197   silc_buffer_free(packet);
2198   silc_free(channel_id);
2199   silc_free(client_id);
2200
2201  out:
2202   silc_server_command_free(cmd);
2203 }
2204
2205 /* Server side of KICK command. Kicks client out of channel. */
2206
2207 SILC_SERVER_CMD_FUNC(kick)
2208 {
2209   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2210   SilcServer server = cmd->server;
2211   SilcSocketConnection sock = cmd->sock;
2212   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2213
2214 }
2215
2216 SILC_SERVER_CMD_FUNC(restart)
2217 {
2218 }
2219  
2220 SILC_SERVER_CMD_FUNC(close)
2221 {
2222 }
2223  
2224 SILC_SERVER_CMD_FUNC(die)
2225 {
2226 }
2227  
2228 SILC_SERVER_CMD_FUNC(silcoper)
2229 {
2230 }
2231
2232 /* Server side command of LEAVE. Removes client from a channel. */
2233
2234 SILC_SERVER_CMD_FUNC(leave)
2235 {
2236   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2237   SilcServer server = cmd->server;
2238   SilcSocketConnection sock = cmd->sock;
2239   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2240   SilcChannelID *id;
2241   SilcChannelEntry channel;
2242   SilcBuffer packet;
2243   unsigned int i, argc, key_len, len;
2244   unsigned char *tmp, channel_key[32];
2245
2246   SILC_LOG_DEBUG(("Start"));
2247
2248   argc = silc_argument_get_arg_num(cmd->args);
2249   if (argc < 1) {
2250     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2251                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2252     goto out;
2253   }
2254   if (argc > 2) {
2255     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2256                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2257     goto out;
2258   }
2259
2260   /* Get Channel ID */
2261   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2262   if (!tmp) {
2263     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2264                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2265     goto out;
2266   }
2267   id = silc_id_payload_parse_id(tmp, len);
2268
2269   /* Get channel entry */
2270   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2271   if (!channel) {
2272     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2273                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2274     goto out;
2275   }
2276
2277   /* Check whether this client is on the channel */
2278   if (!silc_server_client_on_channel(id_entry, channel)) {
2279     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2280                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2281     goto out;
2282   }
2283
2284   /* Notify routers that they should remove this client from their list
2285      of clients on the channel. */
2286   if (!server->standalone)
2287     silc_server_send_remove_channel_user(server, 
2288                                          server->router->connection,
2289                                          server->server_type == SILC_ROUTER ?
2290                                          TRUE : FALSE, id_entry->id, id);
2291
2292   /* Remove client from channel */
2293   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2294                                           TRUE);
2295   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2296                                         SILC_STATUS_OK);
2297
2298   /* If the channel does not exist anymore we won't send anything */
2299   if (!i)
2300     goto out;
2301
2302   /* Re-generate channel key */
2303   key_len = channel->key_len / 8;
2304   for (i = 0; i < key_len; i++)
2305     channel_key[i] = silc_rng_get_byte(server->rng);
2306   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2307                                         channel_key, key_len);
2308   memset(channel->key, 0, key_len);
2309   silc_free(channel->key);
2310   channel->key = silc_calloc(key_len, sizeof(*channel->key));
2311   memcpy(channel->key, channel_key, key_len);
2312   memset(channel_key, 0, sizeof(channel_key));
2313
2314   /* Encode channel key payload to be distributed on the channel */
2315   packet = 
2316     silc_channel_key_payload_encode(len, tmp,
2317                                     strlen(channel->channel_key->cipher->name),
2318                                     channel->channel_key->cipher->name,
2319                                     key_len, channel->key);
2320
2321   /* If we are normal server then we will send it to our router.  If we
2322      are router we will send it to all local servers that has clients on
2323      the channel */
2324   if (server->server_type == SILC_SERVER) {
2325     if (!server->standalone)
2326       silc_server_packet_send(server, 
2327                               cmd->server->router->connection,
2328                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2329                               packet->len, TRUE);
2330   } else {
2331
2332   }
2333
2334   /* Send to locally connected clients on the channel */
2335   silc_server_packet_send_local_channel(server, channel, 
2336                                         SILC_PACKET_CHANNEL_KEY, 0,
2337                                         packet->data, packet->len, FALSE);
2338
2339   silc_buffer_free(packet);
2340   silc_free(id);
2341
2342  out:
2343   silc_server_command_free(cmd);
2344 }
2345
2346 /* Server side of command NAMES. Resolves clients and their names currently
2347    joined on the requested channel. The name list is sent back to the
2348    client. */
2349
2350 SILC_SERVER_CMD_FUNC(names)
2351 {
2352   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2353   SilcServer server = cmd->server;
2354   SilcChannelEntry channel;
2355   SilcChannelClientEntry chl;
2356   SilcChannelID *id;
2357   SilcBuffer packet;
2358   unsigned int i, len, len2, tmp_len, argc;
2359   unsigned char *tmp;
2360   char *name_list = NULL, *n;
2361   SilcBuffer client_id_list;
2362   SilcBuffer client_mode_list;
2363
2364   SILC_LOG_DEBUG(("Start"));
2365
2366   argc = silc_argument_get_arg_num(cmd->args);
2367   if (argc < 1) {
2368     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2369                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2370     goto out;
2371   }
2372   if (argc > 2) {
2373     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2374                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2375     goto out;
2376   }
2377
2378   /* Get Channel ID */
2379   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2380   if (!tmp) {
2381     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2382                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2383     goto out;
2384   }
2385   id = silc_id_payload_parse_id(tmp, tmp_len);
2386
2387   /* Check whether the channel exists. If we are normal server and the
2388      channel does not exist we will send this same command to our router
2389      which will know if the channel exists. */
2390   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2391   if (!channel) {
2392     if (server->server_type == SILC_SERVER && !server->standalone) {
2393       /* XXX Send names command */
2394
2395       cmd->pending = TRUE;
2396       silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2397                                   silc_server_command_names, context);
2398       return;
2399     }
2400
2401     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2402                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2403     goto out;
2404   }
2405
2406   /* Assemble the name list now */
2407   name_list = NULL;
2408   len = 0;
2409   silc_list_start(channel->user_list);
2410   i = 0;
2411   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2412     n = chl->client->nickname;
2413     if (n) {
2414       len2 = strlen(n);
2415       len += len2;
2416       name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2417       memcpy(name_list + (len - len2), n, len2);
2418       name_list[len] = 0;
2419
2420       if (i == silc_list_count(channel->user_list) - 1)
2421         break;
2422       memcpy(name_list + len, ",", 1);
2423       len++;
2424       i++;
2425     }
2426   }
2427   if (!name_list)
2428     name_list = "";
2429
2430   /* Assemble the Client ID list now */
2431   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
2432                                      silc_list_count(channel->user_list));
2433   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2434   silc_list_start(channel->user_list);
2435   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2436     SilcBuffer idp;
2437
2438     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2439     silc_buffer_format(client_id_list,
2440                        SILC_STR_UI_XNSTRING(idp->data, idp->len),
2441                        SILC_STR_END);
2442     silc_buffer_pull(client_id_list, idp->len);
2443     silc_buffer_free(idp);
2444   }
2445   silc_buffer_push(client_id_list, 
2446                    client_id_list->data - client_id_list->head);
2447
2448   /* Assemble mode list */
2449   client_mode_list = silc_buffer_alloc(4 * 
2450                                        silc_list_count(channel->user_list));
2451   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2452   silc_list_start(channel->user_list);
2453   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2454     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2455     silc_buffer_pull(client_mode_list, 4);
2456   }
2457   silc_buffer_push(client_mode_list, 
2458                    client_mode_list->data - client_mode_list->head);
2459
2460   /* Send reply */
2461   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2462                                                 SILC_STATUS_OK, 0, 4,
2463                                                 2, tmp, tmp_len,
2464                                                 3, name_list, 
2465                                                 strlen(name_list),
2466                                                 4, client_id_list->data,
2467                                                 client_id_list->len,
2468                                                 5, client_mode_list->data,
2469                                                 client_mode_list->len);
2470   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2471                           packet->data, packet->len, FALSE);
2472     
2473   silc_buffer_free(packet);
2474   silc_free(name_list);
2475   silc_buffer_free(client_id_list);
2476   silc_buffer_free(client_mode_list);
2477   silc_free(id);
2478
2479  out:
2480   silc_server_command_free(cmd);
2481 }