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