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