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