Added boolean route argument to to_channel packet sending
[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, TRUE,
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_str2id(tmp, SILC_ID_SERVER);
1128   if (!id)
1129     goto out;
1130
1131   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1132     /* Send our reply */
1133     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1134                                           SILC_STATUS_OK);
1135   } else {
1136     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1137                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1138     goto out;
1139   }
1140
1141   silc_free(id);
1142
1143  out:
1144   silc_server_command_free(cmd);
1145 }
1146
1147 SILC_SERVER_CMD_FUNC(oper)
1148 {
1149 }
1150
1151 typedef struct {
1152   char *channel_name;
1153   char *nickname;
1154   char *username;
1155   char *hostname;
1156   SilcChannelEntry channel;
1157   SilcServer server;
1158   SilcClientEntry client;
1159 } JoinInternalContext;
1160
1161 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1162 {
1163   JoinInternalContext *ctx = (JoinInternalContext *)context;
1164
1165   if (ctx->channel->key && ctx->channel->key_len) {
1166     SilcBuffer clidp;
1167
1168     clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1169
1170     silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1171                                        SILC_NOTIFY_TYPE_JOIN, 1,
1172                                        clidp->data, clidp->len);
1173 #if 0
1174     /* Send NEW_CHANNEL_USER packet to primary route */
1175     silc_server_send_new_channel_user(server, server->router->connection,
1176                                       server->server_type == SILC_SERVER ?
1177                                       FALSE : TRUE,
1178                                       channel->id, SILC_ID_CHANNEL_LEN,
1179                                       client->id, SILC_ID_CLIENT_LEN);
1180 #endif
1181
1182     /* Send NAMES command reply to the joined channel so the user sees who
1183        is currently on the channel. */
1184     silc_server_command_send_names(ctx->server, ctx->client->connection, 
1185                                    ctx->channel);
1186
1187     silc_buffer_free(clidp);
1188     silc_free(ctx);
1189   } else {
1190     silc_task_register(ctx->server->timeout_queue, fd,
1191                        silc_server_command_join_notify, context,
1192                        0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1193   }
1194 }
1195
1196 /* Assembles NAMES command and executes it. This is called when client
1197    joins to a channel and we wan't to send NAMES command reply to the 
1198    client. */
1199
1200 void silc_server_command_send_names(SilcServer server,
1201                                     SilcSocketConnection sock,
1202                                     SilcChannelEntry channel)
1203 {
1204   SilcServerCommandContext cmd;
1205   SilcBuffer buffer, idp;
1206
1207   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1208   buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1209                                           1, idp->data, idp->len);
1210
1211   cmd = silc_calloc(1, sizeof(*cmd));
1212   cmd->payload = silc_command_payload_parse(buffer);
1213   cmd->args = silc_command_get_args(cmd->payload);
1214   cmd->server = server;
1215   cmd->sock = sock;
1216   cmd->pending = FALSE;
1217
1218   silc_server_command_names((void *)cmd);
1219   silc_free(buffer);
1220   silc_free(idp);
1221 }
1222
1223 /* Internal routine to join channel. The channel sent to this function
1224    has been either created or resolved from ID lists. This joins the sent
1225    client to the channel. */
1226
1227 static void
1228 silc_server_command_join_channel(SilcServer server, 
1229                                  SilcServerCommandContext cmd,
1230                                  SilcChannelEntry channel,
1231                                  unsigned int umode)
1232 {
1233   SilcSocketConnection sock = cmd->sock;
1234   unsigned char *tmp;
1235   unsigned int tmp_len;
1236   unsigned char *passphrase = NULL, mode[4];
1237   SilcClientEntry client;
1238   SilcChannelClientEntry chl;
1239   SilcBuffer packet, idp;
1240
1241   if (!channel)
1242     return;
1243
1244   /* Get passphrase */
1245   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1246   if (tmp) {
1247     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1248     memcpy(passphrase, tmp, tmp_len);
1249   }
1250   
1251   /*
1252    * Check channel modes
1253    */
1254
1255   /* Check invite list if channel is invite-only channel */
1256   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1257     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1258       /* Invite list is specified. Check whether client is invited in the
1259          list. If not, then check whether it has been invited otherwise. */
1260
1261     } else {
1262       /* XXX client must be invited to be able to join the channel */
1263     }
1264   }
1265
1266   /* Check ban list if set */
1267   if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1268
1269   }
1270
1271   /* Check the channel passphrase if set. */
1272   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1273     if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1274                               strlen(channel->mode_data.passphrase))) {
1275       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1276                                             SILC_STATUS_ERR_BAD_PASSWORD);
1277       goto out;
1278     }
1279   }
1280
1281   /* Check user count limit if set. */
1282   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1283     if (silc_list_count(channel->user_list) + 1 > 
1284         channel->mode_data.user_limit) {
1285       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1286                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
1287       goto out;
1288     }
1289   }
1290
1291   /*
1292    * Client is allowed to join to the channel. Make it happen.
1293    */
1294
1295   /* If the JOIN request was forwarded to us we will make a bit slower
1296      query to get the client pointer. Otherwise, we get the client pointer
1297      real easy. */
1298   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1299     client = (SilcClientEntry)sock->user_data;
1300   } else {
1301     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1302     client = silc_idlist_find_client_by_id(server->local_list, id);
1303     if (!client) {
1304       /* XXX */
1305       SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1306                       "wanted to join the channel"));
1307       goto out;
1308     }
1309     silc_free(id);
1310   }
1311
1312   /* Check whether the client already is on the channel */
1313   if (silc_server_client_on_channel(client, channel)) {
1314     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1315                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1316     goto out;
1317   }
1318
1319   /* Join the client to the channel by adding it to channel's user list.
1320      Add also the channel to client entry's channels list for fast cross-
1321      referencing. */
1322   chl = silc_calloc(1, sizeof(*chl));
1323   chl->mode = umode;
1324   chl->client = client;
1325   chl->channel = channel;
1326   silc_list_add(channel->user_list, chl);
1327   silc_list_add(client->channels, chl);
1328
1329   /* Notify router about new user on channel. If we are normal server
1330      we send it to our router, if we are router we send it to our
1331      primary route. */
1332   if (!server->standalone) {
1333
1334   }
1335
1336   /* Send command reply to the client. Client receives the Channe ID,
1337      channel mode and possibly other information in this reply packet. */
1338   if (!cmd->pending) {
1339     idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1340     SILC_PUT32_MSB(channel->mode, mode);
1341
1342     if (!channel->topic)
1343       packet = 
1344         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1345                                              SILC_STATUS_OK, 0, 3,
1346                                              2, channel->channel_name,
1347                                              strlen(channel->channel_name),
1348                                              3, idp->data, idp->len,
1349                                              4, mode, 4);
1350     else
1351       packet = 
1352         silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1353                                              SILC_STATUS_OK, 0, 4, 
1354                                              2, channel->channel_name, 
1355                                              strlen(channel->channel_name),
1356                                              3, idp->data, idp->len,
1357                                              4, mode, 4,
1358                                              5, channel->topic, 
1359                                              strlen(channel->topic));
1360
1361     if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1362       void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1363       silc_server_packet_send_dest(cmd->server, cmd->sock, 
1364                                    SILC_PACKET_COMMAND_REPLY, 0,
1365                                    id, cmd->packet->src_id_type,
1366                                    packet->data, packet->len, FALSE);
1367       silc_free(id);
1368     } else
1369       silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1370                               packet->data, packet->len, FALSE);
1371     silc_buffer_free(packet);
1372
1373     /* Send channel key to the client. Client cannot start transmitting
1374        to the channel until we have sent the key. */
1375     tmp_len = strlen(channel->channel_key->cipher->name);
1376     packet = 
1377       silc_channel_key_payload_encode(idp->len, idp->data, 
1378                                       strlen(channel->channel_key->
1379                                              cipher->name),
1380                                       channel->channel_key->cipher->name,
1381                                       channel->key_len / 8, channel->key);
1382     
1383     silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
1384                             packet->data, packet->len, FALSE);
1385
1386     silc_buffer_free(packet);
1387     silc_buffer_free(idp);
1388   }
1389
1390   /* Finally, send notify message to all clients on the channel about
1391      new user on the channel. */
1392   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1393     if (!cmd->pending) {
1394       /* Send JOIN notify to clients */
1395       SilcBuffer clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1396       silc_server_send_notify_to_channel(server, channel, FALSE,
1397                                          SILC_NOTIFY_TYPE_JOIN, 1,
1398                                          clidp->data, clidp->len);
1399       silc_buffer_free(clidp);
1400
1401       /* Send NEW_CHANNEL_USER packet to primary route */
1402       if (!server->standalone)
1403         silc_server_send_new_channel_user(server, server->router->connection,
1404                                           server->server_type == SILC_SERVER ?
1405                                           FALSE : TRUE,
1406                                           channel->id, SILC_ID_CHANNEL_LEN,
1407                                           client->id, SILC_ID_CLIENT_LEN);
1408     } else {
1409       /* This is pending command request. Send the notify after we have
1410          received the key for the channel from the router. */
1411       JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1412       ctx->channel_name = channel->channel_name;
1413       ctx->nickname = client->nickname;
1414       ctx->username = client->username;
1415       ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1416       ctx->channel = channel;
1417       ctx->server = server;
1418       ctx->client = client;
1419       silc_task_register(server->timeout_queue, sock->sock,
1420                          silc_server_command_join_notify, ctx,
1421                          0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1422       goto out;
1423     }
1424
1425     /* Send NAMES command reply to the joined channel so the user sees who
1426        is currently on the channel. */
1427     silc_server_command_send_names(server, sock, channel);
1428   }
1429
1430  out:
1431   if (passphrase)
1432     silc_free(passphrase);
1433 }
1434
1435 /* Server side of command JOIN. Joins client into requested channel. If 
1436    the channel does not exist it will be created. */
1437
1438 SILC_SERVER_CMD_FUNC(join)
1439 {
1440   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1441   SilcServer server = cmd->server;
1442   int argc, tmp_len;
1443   char *tmp, *channel_name = NULL, *cipher = NULL;
1444   SilcChannelEntry channel;
1445   unsigned int umode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1446
1447   SILC_LOG_DEBUG(("Start"));
1448
1449   /* Check number of parameters */
1450   argc = silc_argument_get_arg_num(cmd->args);
1451   if (argc < 1) {
1452     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1453                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1454     goto out;
1455   }
1456   if (argc > 3) {
1457     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1458                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1459     goto out;
1460   }
1461
1462   /* Get channel name */
1463   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1464   if (!tmp) {
1465     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1466                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1467     goto out;
1468   }
1469   channel_name = tmp;
1470
1471   if (silc_server_command_bad_chars(channel_name) == TRUE) {
1472     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1473                                           SILC_STATUS_ERR_BAD_CHANNEL);
1474     silc_free(channel_name);
1475     goto out;
1476   }
1477
1478   /* Get cipher name */
1479   cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1480
1481   /* See if the channel exists */
1482   channel = silc_idlist_find_channel_by_name(server->local_list, channel_name);
1483   if (!channel) {
1484     /* Channel not found */
1485
1486     /* If we are standalone server we don't have a router, we just create 
1487        the channel by ourselves. */
1488     if (server->standalone) {
1489       channel = silc_server_create_new_channel(server, server->id, cipher, 
1490                                                channel_name);
1491     } else {
1492
1493       /* The channel does not exist on our server. We send JOIN command to
1494          our router which will handle the joining procedure (either creates
1495          the channel if it doesn't exist or joins the client to it) - if we
1496          are normal server. */
1497       if (server->server_type == SILC_SERVER) {
1498         SilcBuffer buffer = cmd->packet->buffer;
1499         
1500         /* Forward the original JOIN command to the router */
1501         silc_buffer_push(buffer, buffer->data - buffer->head);
1502         silc_server_packet_forward(server, (SilcSocketConnection)
1503                                    server->router->connection,
1504                                    buffer->data, buffer->len, TRUE);
1505         
1506         /* Add the command to be pending. It will be re-executed after
1507            router has replied back to us. */
1508         cmd->pending = TRUE;
1509         silc_server_command_pending(server, SILC_COMMAND_JOIN, 0,
1510                                     silc_server_command_join, context);
1511         return;
1512       }
1513       
1514       /* We are router and the channel does not seem exist so we will check
1515          our global list as well for the channel. */
1516       channel = silc_idlist_find_channel_by_name(server->global_list, 
1517                                                  channel_name);
1518       if (!channel) {
1519         /* Channel really does not exist, create it */
1520         channel = silc_server_create_new_channel(server, server->id, cipher, 
1521                                                  channel_name);
1522         umode |= SILC_CHANNEL_UMODE_CHANOP;
1523         umode |= SILC_CHANNEL_UMODE_CHANFO;
1524       }
1525     }
1526   }
1527
1528   /* Join to the channel */
1529   silc_server_command_join_channel(server, cmd, channel, umode);
1530
1531  out:
1532   silc_server_command_free(cmd);
1533 }
1534
1535 /* Server side of command MOTD. Sends server's current "message of the
1536    day" to the client. */
1537
1538 SILC_SERVER_CMD_FUNC(motd)
1539 {
1540   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1541   SilcServer server = cmd->server;
1542   unsigned int argc;
1543   char *motd;
1544   int motd_len;
1545   
1546   SILC_LOG_DEBUG(("Start"));
1547
1548   argc = silc_argument_get_arg_num(cmd->args);
1549   if (argc < 1) {
1550     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1551                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1552     goto out;
1553   }
1554   if (argc > 2) {
1555     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1556                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1557     goto out;
1558   }
1559
1560   /* XXX show currently only our motd */
1561
1562   if (server->config && server->config->motd && 
1563       server->config->motd->motd_file) {
1564
1565     /* Send motd */
1566     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
1567     if (!motd)
1568       goto out;
1569
1570     motd[motd_len] = 0;
1571     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
1572                                          SILC_STATUS_OK,
1573                                          2, motd, motd_len);
1574     goto out;
1575   } else {
1576     /* No motd */
1577     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
1578                                           SILC_STATUS_OK);
1579   }
1580
1581  out:
1582   silc_server_command_free(cmd);
1583 }
1584
1585 SILC_SERVER_CMD_FUNC(umode)
1586 {
1587 }
1588
1589 /* Checks that client has rights to add or remove channel modes. If any
1590    of the checks fails FALSE is returned. */
1591
1592 int silc_server_check_cmode_rights(SilcChannelEntry channel,
1593                                    SilcChannelClientEntry client,
1594                                    unsigned int mode)
1595 {
1596   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
1597   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
1598
1599   /* Check whether has rights to change anything */
1600   if (!is_op && !is_fo)
1601     return FALSE;
1602
1603   /* Check whether has rights to change everything */
1604   if (is_op && is_fo)
1605     return TRUE;
1606
1607   /* We know that client is channel operator, check that they are not
1608      changing anything that requires channel founder rights. Rest of the
1609      modes are available automatically for channel operator. */
1610
1611   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
1612     if (is_op && !is_fo)
1613       return FALSE;
1614   } else {
1615     if (channel->mode & SILC_CHANNEL_MODE_PRIVATE) {
1616       if (is_op && !is_fo)
1617         return FALSE;
1618     }
1619   }
1620   
1621   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1622     if (is_op && !is_fo)
1623       return FALSE;
1624   } else {
1625     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1626       if (is_op && !is_fo)
1627         return FALSE;
1628     }
1629   }
1630
1631   if (mode & SILC_CHANNEL_MODE_CIPHER) {
1632     if (is_op && !is_fo)
1633       return FALSE;
1634   } else {
1635     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1636       if (is_op && !is_fo)
1637         return FALSE;
1638     }
1639   }
1640   
1641   return TRUE;
1642 }
1643
1644 /* Server side command of CMODE. Changes channel mode */
1645
1646 SILC_SERVER_CMD_FUNC(cmode)
1647 {
1648   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1649   SilcServer server = cmd->server;
1650   SilcSocketConnection sock = cmd->sock;
1651   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1652   SilcChannelID *channel_id;
1653   SilcClientID *client_id;
1654   SilcChannelEntry channel;
1655   SilcChannelClientEntry chl;
1656   SilcBuffer packet, cidp;
1657   unsigned char *tmp, *tmp_id, *tmp_mask;
1658   unsigned int argc, mode_mask, tmp_len, tmp_len2;
1659   int i;
1660
1661   SILC_LOG_DEBUG(("Start"));
1662
1663   argc = silc_argument_get_arg_num(cmd->args);
1664   if (argc < 2) {
1665     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1666                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1667     goto out;
1668   }
1669   if (argc > 8) {
1670     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1671                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1672     goto out;
1673   }
1674
1675   /* Get Channel ID */
1676   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
1677   if (!tmp_id) {
1678     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1679                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1680     goto out;
1681   }
1682   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
1683
1684   /* Get the channel mode mask */
1685   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1686   if (!tmp_mask) {
1687     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1688                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1689     goto out;
1690   }
1691   SILC_GET32_MSB(mode_mask, tmp_mask);
1692
1693   /* Get channel entry */
1694   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
1695   if (!channel) {
1696     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1697                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1698     goto out;
1699   }
1700
1701   /* Check whether this client is on the channel */
1702   if (!silc_server_client_on_channel(client, channel)) {
1703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1704                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1705     goto out;
1706   }
1707
1708   /* Get entry to the channel user list */
1709   silc_list_start(channel->user_list);
1710   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1711     if (chl->client == client)
1712       break;
1713
1714   /* Check that client has rights to change any requested channel modes */
1715   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
1716     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1717                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1718     goto out;
1719   }
1720
1721   /*
1722    * Check the modes. Modes that requires nothing special operation are
1723    * not checked here.
1724    */
1725
1726   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
1727     /* Channel uses private keys to protect traffic. Client(s) has set the
1728        key locally they want to use, server does not know that key. */
1729     /* Nothing interesting to do here now */
1730   } else {
1731     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
1732       /* The mode is removed and we need to generate and distribute
1733          new channel key. Clients are not using private channel keys
1734          anymore after this. */
1735       unsigned int key_len;
1736       unsigned char channel_key[32];
1737
1738       /* XXX Duplicated code, make own function for this!! LEAVE uses this
1739          as well */
1740
1741       /* Re-generate channel key */
1742       key_len = channel->key_len / 8;
1743       for (i = 0; i < key_len; i++)
1744         channel_key[i] = silc_rng_get_byte(server->rng);
1745       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1746                                             channel_key, key_len);
1747       memset(channel->key, 0, key_len);
1748       silc_free(channel->key);
1749       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1750       memcpy(channel->key, channel_key, key_len);
1751       memset(channel_key, 0, sizeof(channel_key));
1752       
1753       /* Encode channel key payload to be distributed on the channel */
1754       packet = 
1755         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1756                                         strlen(channel->channel_key->
1757                                                cipher->name),
1758                                         channel->channel_key->cipher->name,
1759                                         key_len, channel->key);
1760       
1761       /* If we are normal server then we will send it to our router.  If we
1762          are router we will send it to all local servers that has clients on
1763          the channel */
1764       if (server->server_type == SILC_SERVER) {
1765         if (!server->standalone)
1766           silc_server_packet_send(server, 
1767                                   cmd->server->router->connection,
1768                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1769                                   packet->len, TRUE);
1770       } else {
1771         
1772       }
1773       
1774       /* Send to locally connected clients on the channel */
1775       silc_server_packet_send_local_channel(server, channel, 
1776                                             SILC_PACKET_CHANNEL_KEY, 0,
1777                                             packet->data, packet->len, FALSE);
1778       silc_buffer_free(packet);
1779     }
1780   }
1781   
1782   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
1783     /* User limit is set on channel */
1784     unsigned int user_limit;
1785       
1786     /* Get user limit */
1787     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1788     if (!tmp) {
1789       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
1790         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1791                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1792         goto out;
1793       }
1794     } else {
1795       SILC_GET32_MSB(user_limit, tmp);
1796       channel->mode_data.user_limit = user_limit;
1797     }
1798   } else {
1799     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
1800       /* User limit mode is unset. Remove user limit */
1801       channel->mode_data.user_limit = 0;
1802   }
1803
1804   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
1805     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
1806       /* Passphrase has been set to channel */
1807       
1808       /* Get the passphrase */
1809       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1810       if (!tmp) {
1811         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1812                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1813         goto out;
1814       }
1815
1816       /* Save the passphrase */
1817       channel->mode_data.passphrase = strdup(tmp);
1818     }
1819   } else {
1820     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1821       /* Passphrase mode is unset. remove the passphrase */
1822       if (channel->mode_data.passphrase) {
1823         silc_free(channel->mode_data.passphrase);
1824         channel->mode_data.passphrase = NULL;
1825       }
1826     }
1827   }
1828
1829   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
1830     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
1831       /* Ban list is specified for channel */
1832
1833       /* Get ban list */
1834       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
1835       if (!tmp) {
1836         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1837                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1838         goto out;
1839       }
1840
1841       /* XXX check that channel founder is not banned */
1842
1843       /* Save the ban list */
1844       channel->mode_data.ban_list = strdup(tmp);
1845     }
1846   } else {
1847     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1848       /* Ban mode is unset. Remove the entire ban list */
1849       if (channel->mode_data.ban_list) {
1850         silc_free(channel->mode_data.ban_list);
1851         channel->mode_data.ban_list = NULL;
1852       }
1853     }
1854   }
1855
1856   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
1857     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
1858       /* Invite list is specified for channel */
1859
1860       /* Get invite list */
1861       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
1862       if (!tmp) {
1863         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1864                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1865         goto out;
1866       }
1867
1868       /* Save the invite linst */
1869       channel->mode_data.invite_list = strdup(tmp);
1870     }
1871   } else {
1872     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1873       /* Invite list mode is unset. Remove the entire invite list */
1874       if (channel->mode_data.invite_list) {
1875         silc_free(channel->mode_data.invite_list);
1876         channel->mode_data.invite_list = NULL;
1877       }
1878     }
1879   }
1880
1881   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
1882     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
1883       /* Cipher to use protect the traffic */
1884       unsigned int key_len = 128;
1885       unsigned char channel_key[32];
1886       char *cp;
1887
1888       /* Get cipher */
1889       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
1890       if (!tmp) {
1891         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
1892                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1893         goto out;
1894       }
1895
1896       cp = strchr(tmp, ':');
1897       if (cp) {
1898         key_len = atoi(cp);
1899         *cp = '\0';
1900       }
1901
1902       /* XXX Duplicated code, make own function for this!! */
1903     
1904       /* Delete old cipher and allocate the new one */
1905       silc_cipher_free(channel->channel_key);
1906       silc_cipher_alloc(tmp, &channel->channel_key);
1907
1908       /* Re-generate channel key */
1909       key_len /= 8;
1910       if (key_len > sizeof(channel_key))
1911         key_len = sizeof(channel_key);
1912
1913       for (i = 0; i < key_len; i++)
1914         channel_key[i] = silc_rng_get_byte(server->rng);
1915       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1916                                             channel_key, key_len);
1917       memset(channel->key, 0, key_len);
1918       silc_free(channel->key);
1919       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1920       memcpy(channel->key, channel_key, key_len);
1921       memset(channel_key, 0, sizeof(channel_key));
1922     
1923       /* Encode channel key payload to be distributed on the channel */
1924       packet = 
1925         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1926                                         strlen(channel->channel_key->
1927                                                cipher->name),
1928                                         channel->channel_key->cipher->name,
1929                                         key_len, channel->key);
1930     
1931       /* If we are normal server then we will send it to our router.  If we
1932          are router we will send it to all local servers that has clients on
1933          the channel */
1934       if (server->server_type == SILC_SERVER) {
1935         if (!server->standalone)
1936           silc_server_packet_send(server, 
1937                                   cmd->server->router->connection,
1938                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1939                                   packet->len, TRUE);
1940       } else {
1941         
1942       }
1943     
1944       /* Send to locally connected clients on the channel */
1945       silc_server_packet_send_local_channel(server, channel, 
1946                                             SILC_PACKET_CHANNEL_KEY, 0,
1947                                           packet->data, packet->len, FALSE);
1948       silc_buffer_free(packet);
1949     }
1950   } else {
1951     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
1952       /* Cipher mode is unset. Remove the cipher and revert back to 
1953          default cipher */
1954       unsigned int key_len;
1955       unsigned char channel_key[32];
1956
1957       if (channel->mode_data.cipher) {
1958         silc_free(channel->mode_data.cipher);
1959         channel->mode_data.cipher = NULL;
1960         channel->mode_data.key_len = 0;
1961       }
1962
1963       /* Generate new cipher and key for the channel */
1964
1965       /* XXX Duplicated code, make own function for this!! */
1966
1967       /* Delete old cipher and allocate default one */
1968       silc_cipher_free(channel->channel_key);
1969       if (!channel->cipher)
1970         silc_cipher_alloc("twofish", &channel->channel_key);
1971       else
1972         silc_cipher_alloc(channel->cipher, &channel->channel_key);
1973
1974       /* Re-generate channel key */
1975       key_len = channel->key_len / 8;
1976       for (i = 0; i < key_len; i++)
1977         channel_key[i] = silc_rng_get_byte(server->rng);
1978       channel->channel_key->cipher->set_key(channel->channel_key->context, 
1979                                             channel_key, key_len);
1980       memset(channel->key, 0, key_len);
1981       silc_free(channel->key);
1982       channel->key = silc_calloc(key_len, sizeof(*channel->key));
1983       memcpy(channel->key, channel_key, key_len);
1984       memset(channel_key, 0, sizeof(channel_key));
1985       
1986       /* Encode channel key payload to be distributed on the channel */
1987       packet = 
1988         silc_channel_key_payload_encode(tmp_len2, tmp_id,
1989                                         strlen(channel->channel_key->
1990                                                cipher->name),
1991                                         channel->channel_key->cipher->name,
1992                                         key_len, channel->key);
1993       
1994       /* If we are normal server then we will send it to our router.  If we
1995          are router we will send it to all local servers that has clients on
1996          the channel */
1997       if (server->server_type == SILC_SERVER) {
1998         if (!server->standalone)
1999           silc_server_packet_send(server, 
2000                                   cmd->server->router->connection,
2001                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2002                                   packet->len, TRUE);
2003       } else {
2004         
2005       }
2006       
2007       /* Send to locally connected clients on the channel */
2008       silc_server_packet_send_local_channel(server, channel, 
2009                                             SILC_PACKET_CHANNEL_KEY, 0,
2010                                             packet->data, packet->len, FALSE);
2011       silc_buffer_free(packet);
2012     }
2013   }
2014
2015   /* Finally, set the mode */
2016   channel->mode = mode_mask;
2017
2018   /* Send CMODE_CHANGE notify */
2019   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2020   silc_server_send_notify_to_channel(server, channel, TRUE,
2021                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2022                                      cidp->data, cidp->len, 
2023                                      tmp_mask, tmp_len);
2024   silc_free(cidp);
2025
2026   /* Send command reply to sender */
2027   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2028                                                 SILC_STATUS_OK, 0, 1,
2029                                                 2, tmp_mask, 4);
2030   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2031                           packet->data, packet->len, FALSE);
2032     
2033   silc_buffer_free(packet);
2034   silc_free(channel_id);
2035
2036  out:
2037   silc_server_command_free(cmd);
2038 }
2039
2040 /* Server side of CUMODE command. Changes client's mode on a channel. */
2041
2042 SILC_SERVER_CMD_FUNC(cumode)
2043 {
2044   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2045   SilcServer server = cmd->server;
2046   SilcSocketConnection sock = cmd->sock;
2047   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2048   SilcChannelID *channel_id;
2049   SilcClientID *client_id;
2050   SilcChannelEntry channel;
2051   SilcClientEntry target_client;
2052   SilcChannelClientEntry chl;
2053   SilcBuffer packet, idp;
2054   unsigned char *tmp, *tmp_id, *tmp_mask;
2055   unsigned int argc, target_mask, sender_mask, tmp_len;
2056   int i, notify = FALSE;
2057
2058   SILC_LOG_DEBUG(("Start"));
2059
2060   argc = silc_argument_get_arg_num(cmd->args);
2061   if (argc < 3) {
2062     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2063                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2064     goto out;
2065   }
2066   if (argc > 3) {
2067     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2068                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2069     goto out;
2070   }
2071
2072   /* Get Channel ID */
2073   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2074   if (!tmp_id) {
2075     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2076                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2077     goto out;
2078   }
2079   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2080
2081   /* Get channel entry */
2082   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
2083   if (!channel) {
2084     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2085                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2086     goto out;
2087   }
2088
2089   /* Check whether sender is on the channel */
2090   if (!silc_server_client_on_channel(client, channel)) {
2091     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2092                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2093     goto out;
2094   }
2095
2096   /* Check that client has rights to change other's rights */
2097   silc_list_start(channel->user_list);
2098   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2099     if (chl->client == client) {
2100       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2101           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2102         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2103                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2104         goto out;
2105       }
2106
2107       sender_mask = chl->mode;
2108       break;
2109     }
2110   }
2111   
2112   /* Get the target client's channel mode mask */
2113   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2114   if (!tmp_mask) {
2115     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2116                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2117     goto out;
2118   }
2119   SILC_GET32_MSB(target_mask, tmp_mask);
2120
2121   /* Get target Client ID */
2122   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2123   if (!tmp_id) {
2124     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2125                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2126     goto out;
2127   }
2128   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2129
2130   /* Get target client's entry */
2131   target_client = silc_idlist_find_client_by_id(server->local_list, client_id);
2132   if (!target_client) {
2133     /* XXX If target client is not one of mine send to primary route */
2134   }
2135
2136   /* Check whether target client is on the channel */
2137   if (!silc_server_client_on_channel(target_client, channel)) {
2138     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2139                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2140     goto out;
2141   }
2142
2143   /* Get entry to the channel user list */
2144   silc_list_start(channel->user_list);
2145   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2146     if (chl->client == target_client)
2147       break;
2148
2149   /* 
2150    * Change the mode 
2151    */
2152
2153   /* If the target client is founder, no one else can change their mode
2154      but themselves. */
2155   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2156     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2157                                           SILC_STATUS_ERR_NOT_YOU);
2158     goto out;
2159   }
2160
2161   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2162     /* Cannot promote anyone to channel founder */
2163     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2164                                           SILC_STATUS_ERR_NOT_YOU);
2165     goto out;
2166   } else {
2167     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2168       if (target_client == client) {
2169         /* Remove channel founder rights from itself */
2170         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2171         notify = TRUE;
2172       } else {
2173         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2174                                               SILC_STATUS_ERR_NOT_YOU);
2175         goto out;
2176       }
2177     }
2178   }
2179
2180   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2181     /* Promote to operator */
2182     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2183       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2184       notify = TRUE;
2185     }
2186   } else {
2187     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2188       /* Demote to normal user */
2189       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2190       notify = TRUE;
2191     }
2192   }
2193
2194   /* Send notify to channel, notify only if mode was actually changed. */
2195   if (notify) {
2196     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2197     silc_server_send_notify_to_channel(server, channel, TRUE,
2198                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2199                                        idp->data, idp->len,
2200                                        tmp_mask, 4, tmp_id, tmp_len);
2201     silc_buffer_free(idp);
2202   }
2203
2204   /* Send command reply to sender */
2205   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2206                                                 SILC_STATUS_OK, 0, 2,
2207                                                 2, tmp_mask, 4,
2208                                                 3, tmp_id, tmp_len);
2209   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2210                           packet->data, packet->len, FALSE);
2211     
2212   silc_buffer_free(packet);
2213   silc_free(channel_id);
2214   silc_free(client_id);
2215
2216  out:
2217   silc_server_command_free(cmd);
2218 }
2219
2220 /* Server side of KICK command. Kicks client out of channel. */
2221
2222 SILC_SERVER_CMD_FUNC(kick)
2223 {
2224   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2225   SilcServer server = cmd->server;
2226   SilcSocketConnection sock = cmd->sock;
2227   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2228
2229 }
2230
2231 SILC_SERVER_CMD_FUNC(restart)
2232 {
2233 }
2234  
2235 SILC_SERVER_CMD_FUNC(close)
2236 {
2237 }
2238  
2239 SILC_SERVER_CMD_FUNC(die)
2240 {
2241 }
2242  
2243 SILC_SERVER_CMD_FUNC(silcoper)
2244 {
2245 }
2246
2247 /* Server side command of LEAVE. Removes client from a channel. */
2248
2249 SILC_SERVER_CMD_FUNC(leave)
2250 {
2251   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2252   SilcServer server = cmd->server;
2253   SilcSocketConnection sock = cmd->sock;
2254   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2255   SilcChannelID *id;
2256   SilcChannelEntry channel;
2257   SilcBuffer packet;
2258   unsigned int i, argc, key_len, len;
2259   unsigned char *tmp, channel_key[32];
2260
2261   SILC_LOG_DEBUG(("Start"));
2262
2263   argc = silc_argument_get_arg_num(cmd->args);
2264   if (argc < 1) {
2265     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2266                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2267     goto out;
2268   }
2269   if (argc > 2) {
2270     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2271                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2272     goto out;
2273   }
2274
2275   /* Get Channel ID */
2276   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2277   if (!tmp) {
2278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2279                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2280     goto out;
2281   }
2282   id = silc_id_payload_parse_id(tmp, len);
2283
2284   /* Get channel entry */
2285   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2286   if (!channel) {
2287     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2288                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2289     goto out;
2290   }
2291
2292   /* Check whether this client is on the channel */
2293   if (!silc_server_client_on_channel(id_entry, channel)) {
2294     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2295                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2296     goto out;
2297   }
2298
2299   /* Notify routers that they should remove this client from their list
2300      of clients on the channel. */
2301   if (!server->standalone)
2302     silc_server_send_remove_channel_user(server, 
2303                                          server->router->connection,
2304                                          server->server_type == SILC_ROUTER ?
2305                                          TRUE : FALSE, id_entry->id, id);
2306
2307   /* Remove client from channel */
2308   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2309                                           TRUE);
2310   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2311                                         SILC_STATUS_OK);
2312
2313   /* If the channel does not exist anymore we won't send anything */
2314   if (!i)
2315     goto out;
2316
2317   /* Re-generate channel key */
2318   key_len = channel->key_len / 8;
2319   for (i = 0; i < key_len; i++)
2320     channel_key[i] = silc_rng_get_byte(server->rng);
2321   channel->channel_key->cipher->set_key(channel->channel_key->context, 
2322                                         channel_key, key_len);
2323   memset(channel->key, 0, key_len);
2324   silc_free(channel->key);
2325   channel->key = silc_calloc(key_len, sizeof(*channel->key));
2326   memcpy(channel->key, channel_key, key_len);
2327   memset(channel_key, 0, sizeof(channel_key));
2328
2329   /* Encode channel key payload to be distributed on the channel */
2330   packet = 
2331     silc_channel_key_payload_encode(len, tmp,
2332                                     strlen(channel->channel_key->cipher->name),
2333                                     channel->channel_key->cipher->name,
2334                                     key_len, channel->key);
2335
2336   /* If we are normal server then we will send it to our router.  If we
2337      are router we will send it to all local servers that has clients on
2338      the channel */
2339   if (server->server_type == SILC_SERVER) {
2340     if (!server->standalone)
2341       silc_server_packet_send(server, 
2342                               cmd->server->router->connection,
2343                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2344                               packet->len, TRUE);
2345   } else {
2346
2347   }
2348
2349   /* Send to locally connected clients on the channel */
2350   silc_server_packet_send_local_channel(server, channel, 
2351                                         SILC_PACKET_CHANNEL_KEY, 0,
2352                                         packet->data, packet->len, FALSE);
2353
2354   silc_buffer_free(packet);
2355   silc_free(id);
2356
2357  out:
2358   silc_server_command_free(cmd);
2359 }
2360
2361 /* Server side of command NAMES. Resolves clients and their names currently
2362    joined on the requested channel. The name list is sent back to the
2363    client. */
2364
2365 SILC_SERVER_CMD_FUNC(names)
2366 {
2367   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2368   SilcServer server = cmd->server;
2369   SilcChannelEntry channel;
2370   SilcChannelClientEntry chl;
2371   SilcChannelID *id;
2372   SilcBuffer packet;
2373   unsigned int i, len, len2, tmp_len, argc;
2374   unsigned char *tmp;
2375   char *name_list = NULL, *n;
2376   SilcBuffer client_id_list;
2377   SilcBuffer client_mode_list;
2378
2379   SILC_LOG_DEBUG(("Start"));
2380
2381   argc = silc_argument_get_arg_num(cmd->args);
2382   if (argc < 1) {
2383     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2384                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2385     goto out;
2386   }
2387   if (argc > 2) {
2388     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2389                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2390     goto out;
2391   }
2392
2393   /* Get Channel ID */
2394   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2395   if (!tmp) {
2396     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2397                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2398     goto out;
2399   }
2400   id = silc_id_payload_parse_id(tmp, tmp_len);
2401
2402   /* Check whether the channel exists. If we are normal server and the
2403      channel does not exist we will send this same command to our router
2404      which will know if the channel exists. */
2405   channel = silc_idlist_find_channel_by_id(server->local_list, id);
2406   if (!channel) {
2407     if (server->server_type == SILC_SERVER && !server->standalone) {
2408       /* XXX Send names command */
2409
2410       cmd->pending = TRUE;
2411       silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2412                                   silc_server_command_names, context);
2413       return;
2414     }
2415
2416     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2417                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2418     goto out;
2419   }
2420
2421   /* Assemble the name list now */
2422   name_list = NULL;
2423   len = 0;
2424   silc_list_start(channel->user_list);
2425   i = 0;
2426   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2427     n = chl->client->nickname;
2428     if (n) {
2429       len2 = strlen(n);
2430       len += len2;
2431       name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2432       memcpy(name_list + (len - len2), n, len2);
2433       name_list[len] = 0;
2434
2435       if (i == silc_list_count(channel->user_list) - 1)
2436         break;
2437       memcpy(name_list + len, ",", 1);
2438       len++;
2439       i++;
2440     }
2441   }
2442   if (!name_list)
2443     name_list = "";
2444
2445   /* Assemble the Client ID list now */
2446   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
2447                                      silc_list_count(channel->user_list));
2448   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2449   silc_list_start(channel->user_list);
2450   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2451     SilcBuffer idp;
2452
2453     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2454     silc_buffer_format(client_id_list,
2455                        SILC_STR_UI_XNSTRING(idp->data, idp->len),
2456                        SILC_STR_END);
2457     silc_buffer_pull(client_id_list, idp->len);
2458     silc_buffer_free(idp);
2459   }
2460   silc_buffer_push(client_id_list, 
2461                    client_id_list->data - client_id_list->head);
2462
2463   /* Assemble mode list */
2464   client_mode_list = silc_buffer_alloc(4 * 
2465                                        silc_list_count(channel->user_list));
2466   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2467   silc_list_start(channel->user_list);
2468   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2469     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2470     silc_buffer_pull(client_mode_list, 4);
2471   }
2472   silc_buffer_push(client_mode_list, 
2473                    client_mode_list->data - client_mode_list->head);
2474
2475   /* Send reply */
2476   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2477                                                 SILC_STATUS_OK, 0, 4,
2478                                                 2, tmp, tmp_len,
2479                                                 3, name_list, 
2480                                                 strlen(name_list),
2481                                                 4, client_id_list->data,
2482                                                 client_id_list->len,
2483                                                 5, client_mode_list->data,
2484                                                 client_mode_list->len);
2485   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2486                           packet->data, packet->len, FALSE);
2487     
2488   silc_buffer_free(packet);
2489   silc_free(name_list);
2490   silc_buffer_free(client_id_list);
2491   silc_buffer_free(client_mode_list);
2492   silc_free(id);
2493
2494  out:
2495   silc_server_command_free(cmd);
2496 }