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