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