Added support for notify type sending in notify payload.
[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 /*
21  * $Id$
22  * $Log$
23  * Revision 1.14  2000/09/29 07:13:04  priikone
24  *      Added support for notify type sending in notify payload.
25  *      Removed Log headers from the file.
26  *      Enabled debug messages by default for server.
27  *
28  * Revision 1.13  2000/08/21 14:21:21  priikone
29  *      Fixed channel joining and channel message sending inside a
30  *      SILC cell. Added silc_server_send_remove_channel_user and
31  *      silc_server_remove_channel_user functions.
32  *
33  * Revision 1.12  2000/07/26 07:05:11  priikone
34  *      Fixed the server to server (server to router actually) connections
35  *      and made the private message work inside a cell. Added functin
36  *      silc_server_replace_id.
37  *
38  * Revision 1.11  2000/07/19 07:08:09  priikone
39  *      Added version detection support to SKE.
40  *
41  * Revision 1.10  2000/07/17 11:47:30  priikone
42  *      Added command lagging support. Added idle counting support.
43  *
44  * Revision 1.9  2000/07/12 05:59:41  priikone
45  *      Major rewrite of ID Cache system. Support added for the new
46  *      ID cache system. Major rewrite of ID List stuff on server.  All
47  *      SilcXXXList's are now called SilcXXXEntry's and they are pointers
48  *      by default. A lot rewritten ID list functions.
49  *
50  * Revision 1.8  2000/07/10 05:42:59  priikone
51  *      Removed command packet processing from server.c and added it to
52  *      command.c.
53  *      Implemented INFO command. Added support for testing that
54  *      connections are registered before executing commands.
55  *
56  * Revision 1.7  2000/07/07 06:55:24  priikone
57  *      Do not allow client to join twice on same channel.
58  *
59  * Revision 1.6  2000/07/06 10:20:59  priikone
60  *      Cipher name in joining is not mandatory, removed check.
61  *
62  * Revision 1.5  2000/07/06 07:16:43  priikone
63  *      Fixed a wrong way of sending command replies. The fixed way
64  *      does comply with the protocol.
65  *
66  * Revision 1.4  2000/07/05 06:13:38  priikone
67  *      Added PING, INVITE and NAMES command.
68  *
69  * Revision 1.3  2000/07/03 05:52:22  priikone
70  *      Implemented LEAVE command.
71  *
72  * Revision 1.2  2000/06/28 05:06:38  priikone
73  *      Shorter timeout for channel joining notify.
74  *
75  * Revision 1.1.1.1  2000/06/27 11:36:56  priikone
76  *      Imported from internal CVS/Added Log headers.
77  *
78  *
79  */
80
81 #include "serverincludes.h"
82 #include "server_internal.h"
83
84 static int silc_server_is_registered(SilcServer server,
85                                      SilcSocketConnection sock,
86                                      SilcServerCommandContext cmd,
87                                      SilcCommand command);
88 static void 
89 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
90                                       SilcCommand command,
91                                       SilcCommandStatus status);
92 static void 
93 silc_server_command_send_status_data(SilcServerCommandContext cmd,
94                                      SilcCommand command,
95                                      SilcCommandStatus status,
96                                      unsigned int arg_type,
97                                      unsigned char *arg,
98                                      unsigned int arg_len);
99 static void silc_server_command_free(SilcServerCommandContext cmd);
100
101 /* Server command list. */
102 SilcServerCommand silc_command_list[] =
103 {
104   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
105   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
106   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
107   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
108   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
109   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
110   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
111   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
112   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
113   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
114   SILC_SERVER_CMD(connect, CONNECT, 
115                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
116   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
117   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
118   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
119   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
120   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
121   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
122   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
123   SILC_SERVER_CMD(restart, RESTART, 
124                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
125   SILC_SERVER_CMD(close, CLOSE,
126                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
127   SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
128   SILC_SERVER_CMD(silcoper, SILCOPER,
129                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
130   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
131   SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
132
133   { NULL, 0 },
134 };
135
136 /* List of pending commands. */
137 SilcServerCommandPending *silc_command_pending = NULL;
138
139 /* Returns TRUE if the connection is registered. Unregistered connections
140    usually cannot send commands hence the check. */
141
142 static int silc_server_is_registered(SilcServer server,
143                                      SilcSocketConnection sock,
144                                      SilcServerCommandContext cmd,
145                                      SilcCommand command)
146 {
147   switch(sock->type) {
148   case SILC_SOCKET_TYPE_CLIENT:
149     {
150       SilcClientEntry client = (SilcClientEntry)sock->user_data;
151       if (client->registered)
152         return TRUE;
153       break;
154     }
155   case SILC_SOCKET_TYPE_SERVER:
156   case SILC_SOCKET_TYPE_ROUTER:
157     {
158       SilcServerEntry serv = (SilcServerEntry)sock->user_data;
159       if (serv->registered)
160         return TRUE;
161       break;
162     }
163   default:
164     break;
165   }
166
167   silc_server_command_send_status_reply(cmd, command,
168                                         SILC_STATUS_ERR_NOT_REGISTERED);
169   silc_server_command_free(cmd);
170   return FALSE;
171 }
172
173 /* Processes received command packet. */
174
175 void silc_server_command_process(SilcServer server,
176                                  SilcSocketConnection sock,
177                                  SilcPacketContext *packet)
178 {
179   SilcServerCommandContext ctx;
180   SilcServerCommand *cmd;
181
182   /* Check whether it is allowed for this connection to execute any
183      command. */
184   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
185     time_t curtime;
186     SilcClientEntry client = (SilcClientEntry)sock->user_data;
187
188     if (!client)
189       goto out;
190
191     /* Allow only one command executed in 2 seconds. */
192     curtime = time(NULL);
193     if (client->last_command && (curtime - client->last_command) < 2)
194       goto out;
195
196     /* Update access time */
197     client->last_command = curtime;
198   }
199   
200   /* Allocate command context. This must be free'd by the
201      command routine receiving it. */
202   ctx = silc_calloc(1, sizeof(*ctx));
203   ctx->server = server;
204   ctx->sock = sock;
205   ctx->packet = packet; /* Save original packet */
206   
207   /* Parse the command payload in the packet */
208   ctx->payload = silc_command_parse_payload(packet->buffer);
209   if (!ctx->payload) {
210     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
211     silc_buffer_free(packet->buffer);
212     silc_free(ctx);
213     return;
214   }
215   
216   /* Execute command. If this fails the packet is dropped. */
217   for (cmd = silc_command_list; cmd->cb; cmd++)
218     if (cmd->cmd == silc_command_get(ctx->payload)) {
219
220       if (!(cmd->flags & SILC_CF_REG)) {
221         cmd->cb(ctx);
222         break;
223       }
224       
225       if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
226         cmd->cb(ctx);
227         break;
228       }
229     }
230
231   if (cmd == NULL) {
232     SILC_LOG_ERROR(("Unknown command, packet dropped"));
233     silc_free(ctx);
234     goto out;
235   }
236
237  out:
238   silc_buffer_free(packet->buffer);
239 }
240
241 /* Add new pending command to the list of pending commands. Currently
242    pending commands are executed from command replies, thus we can
243    execute any command after receiving some specific command reply.
244
245    The argument `reply_cmd' is the command reply from where the callback
246    function is to be called, thus, it IS NOT the command to be executed. */
247
248 void silc_server_command_pending(SilcCommand reply_cmd,
249                                  SilcCommandCb callback,
250                                  void *context)
251 {
252   SilcServerCommandPending *reply, *r;
253
254   reply = silc_calloc(1, sizeof(*reply));
255   reply->reply_cmd = reply_cmd;
256   reply->context = context;
257   reply->callback = callback;
258
259   if (silc_command_pending == NULL) {
260     silc_command_pending = reply;
261     return;
262   }
263
264   for (r = silc_command_pending; r; r = r->next) {
265     if (r->next == NULL) {
266       r->next = reply;
267       break;
268     }
269   }
270 }
271
272 /* Deletes pending command by reply command type. */
273
274 void silc_server_command_pending_del(SilcCommand reply_cmd)
275 {
276   SilcServerCommandPending *r, *tmp;
277   
278   if (silc_command_pending) {
279     if (silc_command_pending->reply_cmd == reply_cmd) {
280       silc_free(silc_command_pending);
281       silc_command_pending = NULL;
282       return;
283     }
284
285     for (r = silc_command_pending; r; r = r->next) {
286       if (r->next && r->next->reply_cmd == reply_cmd) {
287         tmp = r->next;
288         r->next = r->next->next;
289         silc_free(tmp);
290         break;
291       }
292     }
293   }
294 }
295
296 /* Free's the command context allocated before executing the command */
297
298 static void silc_server_command_free(SilcServerCommandContext cmd)
299 {
300   if (cmd) {
301     silc_command_free_payload(cmd->payload);
302     silc_free(cmd);
303   }
304 }
305
306 #define SILC_COMMAND_STATUS_DATA(x) \
307   (
308
309 /* Sends simple status message as command reply packet */
310
311 static void 
312 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
313                                       SilcCommand command,
314                                       SilcCommandStatus status)
315 {
316   SilcBuffer buffer;
317
318   SILC_LOG_DEBUG(("Sending command status %d", status));
319
320   buffer = silc_command_encode_reply_payload_va(command, status, 0);
321   silc_server_packet_send(cmd->server, cmd->sock,
322                           SILC_PACKET_COMMAND_REPLY, 0, 
323                           buffer->data, buffer->len, FALSE);
324   silc_buffer_free(buffer);
325 }
326
327 /* Sends command status reply with one extra argument. The argument
328    type must be sent as argument. */
329
330 static void 
331 silc_server_command_send_status_data(SilcServerCommandContext cmd,
332                                      SilcCommand command,
333                                      SilcCommandStatus status,
334                                      unsigned int arg_type,
335                                      unsigned char *arg,
336                                      unsigned int arg_len)
337 {
338   SilcBuffer buffer;
339
340   SILC_LOG_DEBUG(("Sending command status %d", status));
341
342   buffer = silc_command_encode_reply_payload_va(command, status, 1,
343                                                 arg_type, arg, arg_len);
344   silc_server_packet_send(cmd->server, cmd->sock,
345                           SILC_PACKET_COMMAND_REPLY, 0, 
346                           buffer->data, buffer->len, FALSE);
347   silc_buffer_free(buffer);
348 }
349
350 /* Server side of command WHOIS. Processes user's query and sends found 
351    results as command replies back to the client. */
352
353 SILC_SERVER_CMD_FUNC(whois)
354 {
355   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
356   SilcServer server = cmd->server;
357   char *tmp, *nick = NULL, *server_name = NULL;
358   unsigned int argc, count = 0, len;
359   SilcClientEntry entry;
360   SilcBuffer packet;
361   unsigned char *id_string;
362
363   SILC_LOG_DEBUG(("Start"));
364
365   argc = silc_command_get_arg_num(cmd->payload);
366   if (argc < 1) {
367     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
368                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
369     goto out;
370   }
371   if (argc > 2) {
372     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
373                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
374     goto out;
375   }
376
377   /* Get the nickname@server string and parse it. */
378   tmp = silc_command_get_first_arg(cmd->payload, NULL);
379   if (tmp) {
380     if (strchr(tmp, '@')) {
381       len = strcspn(tmp, "@");
382       nick = silc_calloc(len + 1, sizeof(char));
383       memcpy(nick, tmp, len);
384       server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
385       memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
386     } else {
387       nick = strdup(tmp);
388     }
389   } else {
390     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
391                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
392     goto out;
393   }
394
395   /* Get the max count of reply messages allowed */
396   if (argc == 2) {
397     tmp = silc_command_get_next_arg(cmd->payload, NULL);
398     if (!tmp) {
399       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
400                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
401       if (nick)
402         silc_free(nick);
403       if (server_name)
404         silc_free(server_name);
405       goto out;
406     }
407     count = atoi(tmp);
408   }
409
410   /* Then, make the query from our local client list */
411   entry = silc_idlist_find_client_by_nickname(server->local_list, 
412                                               nick, server_name);
413   if (!entry) {
414
415     /* If we are normal server and are connected to a router we will
416        make global query from the router. */
417     if (server->server_type == SILC_SERVER && !server->standalone) {
418
419       goto ok;
420     }
421     
422     /* If we are router then we will check our global list as well. */
423     if (server->server_type == SILC_ROUTER) {
424       entry =
425         silc_idlist_find_client_by_nickname(server->global_list,
426                                             nick, server_name);
427       if (!entry) {
428         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
429                                              SILC_STATUS_ERR_NO_SUCH_NICK,
430                                              3, tmp, strlen(tmp));
431         goto out;
432       }
433       goto ok;
434     }
435
436     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
437                                          SILC_STATUS_ERR_NO_SUCH_NICK,
438                                          3, tmp, strlen(tmp));
439     goto out;
440   }
441
442  ok:
443   /* XXX, works only for local server info */
444
445   /* Send WHOIS reply */
446   id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
447   tmp = silc_command_get_first_arg(cmd->payload, NULL);
448
449   /* XXX */
450   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
451     char nh[256], uh[256];
452     unsigned char idle[4];
453     SilcSocketConnection hsock;
454
455     memset(uh, 0, sizeof(uh));
456     memset(nh, 0, sizeof(nh));
457
458     strncat(nh, entry->nickname, strlen(entry->nickname));
459     strncat(nh, "@", 1);
460     len = entry->router ? strlen(entry->router->server_name) :
461       strlen(server->server_name);
462     strncat(nh, entry->router ? entry->router->server_name :
463             server->server_name, len);
464
465     strncat(uh, entry->username, strlen(entry->username));
466     strncat(uh, "@", 1);
467     hsock = (SilcSocketConnection)entry->connection;
468     len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
469     strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
470
471     SILC_PUT32_MSB((time(NULL) - entry->last_receive), idle);
472
473     /* XXX */
474     if (entry->userinfo)
475       packet = 
476         silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
477                                              SILC_STATUS_OK, 5, 
478                                              2, id_string, SILC_ID_CLIENT_LEN,
479                                              3, nh, strlen(nh),
480                                              4, uh, strlen(uh),
481                                              5, entry->userinfo, 
482                                              strlen(entry->userinfo),
483                                              7, idle, 4);
484     else
485       packet = 
486         silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS,
487                                              SILC_STATUS_OK, 4, 
488                                              2, id_string, SILC_ID_CLIENT_LEN,
489                                              3, nh, strlen(nh),
490                                              4, uh, strlen(uh),
491                                              7, idle, 4);
492
493   } else {
494     /* XXX */
495     packet = 
496       silc_command_encode_reply_payload_va(SILC_COMMAND_WHOIS, 
497                                            SILC_STATUS_OK, 3, 
498                                            2, id_string, SILC_ID_CLIENT_LEN,
499                                            3, entry->nickname, 
500                                            strlen(entry->nickname),
501                                            4, tmp, strlen(tmp)); /* XXX */
502   }
503   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
504                           0, packet->data, packet->len, FALSE);
505
506   silc_free(id_string);
507   silc_buffer_free(packet);
508
509  out:
510   silc_server_command_free(cmd);
511 }
512
513 SILC_SERVER_CMD_FUNC(whowas)
514 {
515 }
516
517 SILC_SERVER_CMD_FUNC(identify)
518 {
519   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
520   SilcServer server = cmd->server;
521   char *tmp, *nick = NULL, *server_name = NULL;
522   unsigned int argc, count = 0, len;
523   SilcClientEntry entry;
524   SilcBuffer packet;
525   unsigned char *id_string;
526
527   SILC_LOG_DEBUG(("Start"));
528
529   argc = silc_command_get_arg_num(cmd->payload);
530   if (argc < 1) {
531     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
532                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
533     goto out;
534   }
535   if (argc > 2) {
536     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
537                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
538     goto out;
539   }
540
541   /* Get the nickname@server string and parse it. */
542   tmp = silc_command_get_first_arg(cmd->payload, NULL);
543   if (tmp) {
544     if (strchr(tmp, '@')) {
545       len = strcspn(tmp, "@");
546       nick = silc_calloc(len + 1, sizeof(char));
547       memcpy(nick, tmp, len);
548       server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
549       memcpy(server_name, tmp + len + 1, strlen(tmp) - len - 1);
550     } else {
551       nick = strdup(tmp);
552     }
553   } else {
554     silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
555                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
556     goto out;
557   }
558
559   /* Get the max count of reply messages allowed */
560   if (argc == 2) {
561     tmp = silc_command_get_next_arg(cmd->payload, NULL);
562     if (!tmp) {
563       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
564                                             SILC_STATUS_ERR_TOO_MANY_PARAMS);
565       goto out;
566     }
567     count = atoi(tmp);
568   }
569
570   /* Find client */
571   entry = silc_idlist_find_client_by_nickname(server->local_list,
572                                               nick, NULL);
573   if (!entry)
574     entry = silc_idlist_find_client_by_hash(server->global_list,
575                                             nick, server->md5hash);
576
577   /* If client was not found and if we are normal server and are connected
578      to a router we will make global query from the router. */
579   if (!entry && server->server_type == SILC_SERVER && !server->standalone &&
580       !cmd->pending) {
581     SilcBuffer buffer = cmd->packet->buffer;
582     
583     SILC_LOG_DEBUG(("Requesting identify from router"));
584     
585     /* Send IDENTIFY command to our router */
586     silc_buffer_push(buffer, buffer->data - buffer->head);
587     silc_server_packet_forward(server, (SilcSocketConnection)
588                                server->id_entry->router->connection,
589                                buffer->data, buffer->len, TRUE);
590     return;
591   }
592
593   /* If we are router we have checked our local list by nickname and our
594      global list by hash so far. It is possible that the client is still not
595      found and we'll check it from local list by hash. */
596   if (!entry && server->server_type == SILC_ROUTER)
597     entry = silc_idlist_find_client_by_hash(server->local_list,
598                                             nick, server->md5hash);
599
600   if (!entry) {
601     /* The client definitely does not exist */
602     silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
603                                          SILC_STATUS_ERR_NO_SUCH_NICK,
604                                          3, tmp, strlen(tmp));
605     goto out;
606   }
607
608   /* Send IDENTIFY reply */
609   id_string = silc_id_id2str(entry->id, SILC_ID_CLIENT);
610   tmp = silc_command_get_first_arg(cmd->payload, NULL);
611   packet = silc_command_encode_reply_payload_va(SILC_COMMAND_IDENTIFY,
612                                                 SILC_STATUS_OK, 2,
613                                                 2, id_string, 
614                                                 SILC_ID_CLIENT_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_free(id_string);
630   silc_buffer_free(packet);
631
632  out:
633   if (nick)
634     silc_free(nick);
635   if (server_name)
636     silc_free(server_name);
637   silc_server_command_free(cmd);
638 }
639
640 /* Checks string for bad characters and returns TRUE if they are found. */
641
642 static int silc_server_command_bad_chars(char *nick)
643 {
644   if (strchr(nick, '\\')) return TRUE;
645   if (strchr(nick, '\"')) return TRUE;
646   if (strchr(nick, '´')) return TRUE;
647   if (strchr(nick, '`')) return TRUE;
648   if (strchr(nick, '\'')) return TRUE;
649   if (strchr(nick, '*')) return TRUE;
650   if (strchr(nick, '/')) return TRUE;
651   if (strchr(nick, '@')) return TRUE;
652
653   return FALSE;
654 }
655
656 /* Server side of command NICK. Sets nickname for user. Setting
657    nickname causes generation of a new client ID for the client. The
658    new client ID is sent to the client after changing the nickname. */
659
660 SILC_SERVER_CMD_FUNC(nick)
661 {
662   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
663   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
664   SilcServer server = cmd->server;
665   SilcBuffer packet;
666   SilcClientID *new_id;
667   char *id_string;
668   char *nick;
669
670   SILC_LOG_DEBUG(("Start"));
671
672   /* Check number of arguments */
673   if (silc_command_get_arg_num(cmd->payload) < 1) {
674     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
675                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
676     goto out;
677   }
678
679   /* Check nickname */
680   nick = silc_command_get_arg_type(cmd->payload, 1, NULL);
681   if (silc_server_command_bad_chars(nick) == TRUE) {
682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
683                                           SILC_STATUS_ERR_BAD_NICKNAME);
684     goto out;
685   }
686
687   /* Create new Client ID */
688   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
689                            cmd->server->md5hash, nick,
690                            &new_id);
691
692   /* Send notify about nickname change to our router. We send the new
693      ID and ask to replace it with the old one. */
694   if (cmd->server->server_type == SILC_SERVER && !cmd->server->standalone)
695     silc_server_send_replace_id(server, server->id_entry->router->connection, 
696                                 FALSE, id_entry->id,
697                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
698                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
699
700   /* If we are router we have to distribute the new Client ID to all 
701      routers in SILC. */
702   if (cmd->server->server_type == SILC_ROUTER && !cmd->server->standalone)
703     silc_server_send_replace_id(server, server->id_entry->router->connection,  
704                                 TRUE, id_entry->id,
705                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
706                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
707
708   /* Remove old cache entry */
709   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
710                          id_entry->id); 
711   
712   /* Free old ID */
713   if (id_entry->id) {
714     memset(id_entry->id, 0, SILC_ID_CLIENT_LEN);
715     silc_free(id_entry->id);
716   }
717
718   /* Save the nickname as this client is our local client */
719   if (id_entry->nickname)
720     silc_free(id_entry->nickname);
721
722   id_entry->nickname = strdup(nick);
723   id_entry->id = new_id;
724
725   /* Update client cache */
726   silc_idcache_add(server->local_list->clients, id_entry->nickname, 
727                    SILC_ID_CLIENT, id_entry->id, (void *)id_entry, TRUE);
728
729   /* Send the new Client ID as reply command back to client */
730   id_string = silc_id_id2str(id_entry->id, SILC_ID_CLIENT);
731   packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NICK, 
732                                                 SILC_STATUS_OK, 1, 
733                                                 2, id_string, 
734                                                 SILC_ID_CLIENT_LEN);
735   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
736                           0, packet->data, packet->len, FALSE);
737
738   silc_free(id_string);
739   silc_buffer_free(packet);
740
741  out:
742   silc_server_command_free(cmd);
743 }
744
745 SILC_SERVER_CMD_FUNC(list)
746 {
747 }
748
749 SILC_SERVER_CMD_FUNC(topic)
750 {
751 }
752
753 /* Server side of INVITE command. Invites some client to join some channel. */
754
755 SILC_SERVER_CMD_FUNC(invite)
756 {
757   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
758   SilcServer server = cmd->server;
759   SilcSocketConnection sock = cmd->sock, dest_sock;
760   SilcClientEntry sender, dest;
761   SilcClientID *dest_id;
762   SilcChannelEntry channel;
763   SilcChannelID *channel_id;
764   unsigned int argc, len;
765   unsigned char *id_string;
766
767   /* Check number of arguments */
768   argc = silc_command_get_arg_num(cmd->payload);
769   if (argc < 1) {
770     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
771                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
772     goto out;
773   }
774   if (argc > 2) {
775     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
776                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
777     goto out;
778   }
779
780   /* Get destination ID */
781   id_string = silc_command_get_arg_type(cmd->payload, 1, &len);
782   if (!id_string) {
783     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
784                                           SILC_STATUS_ERR_NO_CLIENT_ID);
785     goto out;
786   }
787   dest_id = silc_id_str2id(id_string, SILC_ID_CLIENT);
788
789   /* Get Channel ID */
790   id_string = silc_command_get_arg_type(cmd->payload, 2, &len);
791   if (!id_string) {
792     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
793                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
794     goto out;
795   }
796   channel_id = silc_id_str2id(id_string, SILC_ID_CHANNEL);
797
798   /* Check whether the channel exists */
799   channel = silc_idlist_find_channel_by_id(server->local_list, channel_id);
800   if (!channel) {
801     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
802                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
803     goto out;
804   }
805
806   /* Check whether the sender of this command is on the channel. */
807   sender = (SilcClientEntry )sock->user_data;
808   if (!silc_server_client_on_channel(sender, channel)) {
809     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
810                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
811     goto out;
812   }
813
814   /* Check whether the channel is invite-only channel. If yes then the
815      sender of this command must be at least channel operator. */
816   /* XXX */
817
818   /* Find the connection data for the destination. If it is local we will
819      send it directly otherwise we will send it to router for routing. */
820   dest = silc_idlist_find_client_by_id(server->local_list, dest_id);
821   if (dest)
822     dest_sock = (SilcSocketConnection)dest->connection;
823   else
824     dest_sock = silc_server_get_route(server, dest_id, SILC_ID_CLIENT);
825
826   /* Check whether the requested client is already on the channel. */
827   /* XXX if we are normal server we don't know about global clients on
828      the channel thus we must request it (NAMES command), check from
829      local cache as well. */
830   if (silc_server_client_on_channel(dest, channel)) {
831     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
832                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
833     goto out;
834   }
835
836   /* Send notify to the client that is invited to the channel */
837   silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
838                                SILC_NOTIFY_TYPE_INVITE,
839                                "%s invites you to channel %s",
840                                sender->nickname, channel->channel_name);
841
842   /* Send command reply */
843   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
844                                         SILC_STATUS_OK);
845
846  out:
847   silc_server_command_free(cmd);
848 }
849
850 /* Quits connection to client. This gets called if client won't
851    close the connection even when it has issued QUIT command. */
852
853 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
854 {
855   SilcServer server = (SilcServer)context;
856   SilcSocketConnection sock = server->sockets[fd];
857
858   /* Free all client specific data, such as client entry and entires
859      on channels this client may be on. */
860   silc_server_free_sock_user_data(server, sock);
861
862   /* Close the connection on our side */
863   silc_server_close_connection(server, sock);
864 }
865
866 /* Quits SILC session. This is the normal way to disconnect client. */
867  
868 SILC_SERVER_CMD_FUNC(quit)
869 {
870   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
871   SilcServer server = cmd->server;
872   SilcSocketConnection sock = cmd->sock;
873
874   SILC_LOG_DEBUG(("Start"));
875
876   /* We quit the connection with little timeout */
877   silc_task_register(server->timeout_queue, sock->sock,
878                      silc_server_command_quit_cb, server,
879                      0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
880
881   silc_server_command_free(cmd);
882 }
883
884 SILC_SERVER_CMD_FUNC(kill)
885 {
886 }
887
888 /* Server side of command INFO. This sends information about us to 
889    the client. If client requested specific server we will send the 
890    command to that server. */
891
892 SILC_SERVER_CMD_FUNC(info)
893 {
894   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
895   SilcServer server = cmd->server;
896   SilcBuffer packet;
897   unsigned int argc;
898   unsigned char *id_string;
899   char info_string[256], *dest_server;
900
901   argc = silc_command_get_arg_num(cmd->payload);
902   if (argc < 1) {
903     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
904                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
905     goto out;
906   }
907   if (argc > 1) {
908     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
909                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
910     goto out;
911   }
912
913   /* Get server name */
914   dest_server = silc_command_get_arg_type(cmd->payload, 1, NULL);
915   if (!dest_server) {
916     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
917                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
918     goto out;
919   }
920
921   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
922     /* Send our reply */
923     memset(info_string, 0, sizeof(info_string));
924     snprintf(info_string, sizeof(info_string), 
925              "location: %s server: %s admin: %s <%s>",
926              server->config->admin_info->location,
927              server->config->admin_info->server_type,
928              server->config->admin_info->admin_name,
929              server->config->admin_info->admin_email);
930
931     id_string = silc_id_id2str(server->id, SILC_ID_SERVER);
932
933     packet = 
934       silc_command_encode_reply_payload_va(SILC_COMMAND_INFO,
935                                            SILC_STATUS_OK, 2,
936                                            2, id_string, SILC_ID_SERVER_LEN,
937                                            3, info_string, 
938                                            strlen(info_string));
939     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
940                             packet->data, packet->len, FALSE);
941     
942     silc_free(id_string);
943     silc_buffer_free(packet);
944   } else {
945     /* Send this command to the requested server */
946
947     if (server->server_type == SILC_SERVER && !server->standalone) {
948
949     }
950
951     if (server->server_type == SILC_ROUTER) {
952
953     }
954   }
955   
956  out:
957   silc_server_command_free(cmd);
958 }
959
960 SILC_SERVER_CMD_FUNC(connect)
961 {
962 }
963
964 /* Server side of command PING. This just replies to the ping. */
965
966 SILC_SERVER_CMD_FUNC(ping)
967 {
968   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
969   SilcServer server = cmd->server;
970   SilcServerID *id;
971   unsigned int argc;
972   unsigned char *id_string;
973
974   argc = silc_command_get_arg_num(cmd->payload);
975   if (argc < 1) {
976     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
977                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
978     goto out;
979   }
980   if (argc > 2) {
981     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
982                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
983     goto out;
984   }
985
986   /* Get Server ID */
987   id_string = silc_command_get_arg_type(cmd->payload, 1, NULL);
988   if (!id_string) {
989     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
990                                           SILC_STATUS_ERR_NO_SERVER_ID);
991     goto out;
992   }
993   id = silc_id_str2id(id_string, SILC_ID_SERVER);
994
995   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
996     /* Send our reply */
997     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
998                                           SILC_STATUS_OK);
999   } else {
1000     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1001                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1002     goto out;
1003   }
1004
1005   silc_free(id);
1006
1007  out:
1008   silc_server_command_free(cmd);
1009 }
1010
1011 SILC_SERVER_CMD_FUNC(oper)
1012 {
1013 }
1014
1015 typedef struct {
1016   char *channel_name;
1017   char *nickname;
1018   char *username;
1019   char *hostname;
1020   SilcChannelEntry channel;
1021   SilcServer server;
1022 } JoinInternalContext;
1023
1024 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1025 {
1026   JoinInternalContext *ctx = (JoinInternalContext *)context;
1027
1028   if (ctx->channel->key && ctx->channel->key_len) {
1029     silc_server_send_notify_to_channel(ctx->server, ctx->channel,
1030                                        SILC_NOTIFY_TYPE_JOIN,
1031                                        "%s (%s@%s) has joined channel %s",
1032                                        ctx->nickname, ctx->username,
1033                                        ctx->hostname, ctx->channel_name);
1034     silc_free(ctx);
1035   } else {
1036     silc_task_register(ctx->server->timeout_queue, fd,
1037                        silc_server_command_join_notify, context,
1038                        0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1039   }
1040 }
1041
1042 /* Assembles NAMES command and executes it. This is called when client
1043    joins to a channel and we wan't to send NAMES command reply to the 
1044    client. */
1045
1046 void silc_server_command_send_names(SilcServer server,
1047                                     SilcSocketConnection sock,
1048                                     SilcChannelEntry channel)
1049 {
1050   SilcServerCommandContext cmd;
1051   SilcBuffer buffer;
1052   unsigned char *id_string;
1053
1054   id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1055   buffer = silc_command_encode_payload_va(SILC_COMMAND_NAMES, 1,
1056                                           1, id_string, SILC_ID_CHANNEL_LEN);
1057
1058   cmd = silc_calloc(1, sizeof(*cmd));
1059   cmd->payload = silc_command_parse_payload(buffer);
1060   cmd->server = server;
1061   cmd->sock = sock;
1062   cmd->pending = FALSE;
1063
1064   silc_server_command_names((void *)cmd);
1065   silc_free(id_string);
1066   silc_free(buffer);
1067 }
1068
1069 /* Server side of command JOIN. Joins client into requested channel. If 
1070    the channel does not exist it will be created. */
1071
1072 SILC_SERVER_CMD_FUNC(join)
1073 {
1074   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1075   SilcServer server = cmd->server;
1076   SilcSocketConnection sock = cmd->sock;
1077   SilcBuffer buffer = cmd->packet->buffer;
1078   int argc, i, tmp_len;
1079   char *tmp, *channel_name = NULL, *cipher = NULL, *id_string = NULL;
1080   unsigned char *passphrase, mode[4];
1081   SilcChannelEntry channel;
1082   SilcServerID *router_id;
1083   SilcBuffer packet;
1084   SilcClientEntry client;
1085
1086   SILC_LOG_DEBUG(("Start"));
1087
1088   /* Check number of parameters */
1089   argc = silc_command_get_arg_num(cmd->payload);
1090   if (argc < 1) {
1091     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1092                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1093     goto out;
1094   }
1095   if (argc > 3) {
1096     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1097                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1098     goto out;
1099   }
1100
1101   /* Get channel name */
1102   tmp = silc_command_get_arg_type(cmd->payload, 1, &tmp_len);
1103   channel_name = silc_calloc(tmp_len + 1, sizeof(*channel_name));
1104   memcpy(channel_name, tmp, tmp_len);
1105   if (silc_server_command_bad_chars(tmp) == TRUE) {
1106     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1107                                           SILC_STATUS_ERR_BAD_CHANNEL);
1108     silc_free(channel_name);
1109     goto out;
1110   }
1111
1112   /* Get passphrase */
1113   tmp = silc_command_get_arg_type(cmd->payload, 2, &tmp_len);
1114   if (tmp) {
1115     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1116     memcpy(passphrase, tmp, tmp_len);
1117   }
1118   
1119   /* Get cipher name */
1120   cipher = silc_command_get_arg_type(cmd->payload, 3, NULL);
1121
1122   /* See if the channel exists */
1123   channel = 
1124     silc_idlist_find_channel_by_name(server->local_list, channel_name);
1125   if (!channel) {
1126     /* Channel not found */
1127
1128     /* If we are standalone server we don't have a router, we just create 
1129        the channel by  ourselves. */
1130     if (server->standalone) {
1131       router_id = server->id;
1132       channel = silc_server_new_channel(server, router_id, 
1133                                         cipher, channel_name);
1134       if (!channel)
1135         goto out;
1136
1137       goto join_channel;
1138     }
1139
1140     /* No channel ID found, the channel does not exist on our server.
1141        We send JOIN command to our router which will handle the joining
1142        procedure (either creates the channel if it doesn't exist or
1143        joins the client to it) - if we are normal server. */
1144     if (server->server_type == SILC_SERVER) {
1145
1146       /* Forward the original JOIN command to the router */
1147       silc_buffer_push(buffer, buffer->data - buffer->head);
1148       silc_server_packet_forward(server, (SilcSocketConnection)
1149                                  server->id_entry->router->connection,
1150                                  buffer->data, buffer->len, TRUE);
1151       
1152       /* Add the command to be pending. It will be re-executed after
1153          router has replied back to us. */
1154       cmd->pending = TRUE;
1155       silc_server_command_pending(SILC_COMMAND_JOIN, 
1156                                   silc_server_command_join, context);
1157       return;
1158     }
1159   }
1160
1161   /* If we are router and the channel does not exist we will check our
1162      global list for the channel. */
1163   if (!channel && server->server_type == SILC_ROUTER) {
1164
1165     /* Notify all routers about the new channel in SILC network. */
1166     if (!server->standalone) {
1167 #if 0
1168       silc_server_send_new_id(server, server->id_entry->router->connection, 
1169                               TRUE,
1170                               xxx, SILC_ID_CHANNEL, SILC_ID_CHANNEL_LEN);
1171 #endif
1172     }
1173
1174   }
1175
1176  join_channel:
1177
1178   /* If the JOIN request was forwarded to us we will make a bit slower
1179      query to get the client pointer. Otherwise, we get the client pointer
1180      real easy. */
1181   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1182     client = (SilcClientEntry)sock->user_data;
1183   } else {
1184     void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1185     client = silc_idlist_find_client_by_id(server->local_list, id);
1186     if (!client) {
1187       /* XXX */
1188       goto out;
1189     }
1190     silc_free(id);
1191   }
1192
1193   /* Check whether the client already is on the channel */
1194   if (silc_server_client_on_channel(client, channel)) {
1195     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1196                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1197     silc_free(channel_name);
1198     goto out;
1199   }
1200
1201   /* Join the client to the channel */
1202   i = channel->user_list_count;
1203   channel->user_list = silc_realloc(channel->user_list, 
1204                                     sizeof(*channel->user_list) * (i + 1));
1205   channel->user_list[i].mode = SILC_CHANNEL_UMODE_NONE;
1206   channel->user_list[i].client = client;
1207   channel->user_list_count++;
1208
1209   /* Add the channel to client's channel list */
1210   i = client->channel_count;
1211   client->channel = silc_realloc(client->channel, 
1212                                  sizeof(*client->channel) * (i + 1));
1213   client->channel[i] = channel;
1214   client->channel_count++;
1215
1216   /* Notify router about new user on channel. If we are normal server
1217      we send it to our router, if we are router we send it to our
1218      primary route. */
1219   if (!server->standalone) {
1220
1221   }
1222
1223   /* Send command reply to the client. Client receives the Channe ID,
1224      channel mode and possibly other information in this reply packet. */
1225   if (!cmd->pending) {
1226     id_string = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1227     SILC_PUT32_MSB(channel->mode, mode);
1228
1229     if (!channel->topic)
1230       packet = 
1231         silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1232                                              SILC_STATUS_OK, 3,
1233                                              2, channel_name, 
1234                                              strlen(channel_name),
1235                                              3, id_string, SILC_ID_CHANNEL_LEN,
1236                                              4, mode, 4);
1237     else
1238       packet = 
1239         silc_command_encode_reply_payload_va(SILC_COMMAND_JOIN,
1240                                              SILC_STATUS_OK, 4, 
1241                                              2, channel_name, 
1242                                              strlen(channel_name),
1243                                              3, id_string, SILC_ID_CHANNEL_LEN,
1244                                              4, mode, 4,
1245                                              5, channel->topic, 
1246                                              strlen(channel->topic));
1247
1248     if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1249       void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1250       silc_server_packet_send_dest(cmd->server, cmd->sock, 
1251                                    SILC_PACKET_COMMAND_REPLY, 0,
1252                                    id, cmd->packet->src_id_type,
1253                                    packet->data, packet->len, FALSE);
1254       silc_free(id);
1255     } else
1256       silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1257                               packet->data, packet->len, FALSE);
1258     
1259     silc_buffer_free(packet);
1260   }
1261
1262   /* Send channel key to the client. Client cannot start transmitting
1263      to the channel until we have sent the key. */
1264   if (!cmd->pending) {
1265     tmp_len = strlen(channel->channel_key->cipher->name);
1266     packet = 
1267       silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN, 
1268                                       id_string, tmp_len, 
1269                                       channel->channel_key->cipher->name,
1270                                       channel->key_len / 8, channel->key);
1271     
1272     silc_server_packet_send(server, sock, SILC_PACKET_CHANNEL_KEY, 0, 
1273                             packet->data, packet->len, FALSE);
1274     silc_buffer_free(packet);
1275   }
1276
1277   if (id_string)
1278     silc_free(id_string);
1279
1280   /* Finally, send notify message to all clients on the channel about
1281      new user on the channel. */
1282   if (!(cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED)) {
1283     if (!cmd->pending) {
1284       silc_server_send_notify_to_channel(server, channel,
1285                                          SILC_NOTIFY_TYPE_JOIN,
1286                                          "%s (%s@%s) has joined channel %s",
1287                                          client->nickname, client->username,
1288                                          sock->hostname ? sock->hostname :
1289                                          sock->ip, channel_name);
1290     } else {
1291       /* This is pending command request. Send the notify after we have
1292          received the key for the channel from the router. */
1293       JoinInternalContext *ctx = silc_calloc(1, sizeof(*ctx));
1294       ctx->channel_name = channel_name;
1295       ctx->nickname = client->nickname;
1296       ctx->username = client->username;
1297       ctx->hostname = sock->hostname ? sock->hostname : sock->ip;
1298       ctx->channel = channel;
1299       ctx->server = server;
1300       silc_task_register(server->timeout_queue, sock->sock,
1301                          silc_server_command_join_notify, ctx,
1302                          0, 10000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1303     }
1304   }
1305
1306   /* Send NAMES command reply to the joined channel so the user sees who
1307      is currently on the channel. */
1308   silc_server_command_send_names(server, sock, channel);
1309
1310  out:
1311   silc_server_command_free(cmd);
1312 }
1313
1314 /* Server side of command MOTD. Sends servers current "message of the
1315    day" to the client. */
1316
1317 SILC_SERVER_CMD_FUNC(motd)
1318 {
1319
1320   SILC_LOG_DEBUG(("Start"));
1321
1322 }
1323
1324 SILC_SERVER_CMD_FUNC(umode)
1325 {
1326 }
1327
1328 SILC_SERVER_CMD_FUNC(cmode)
1329 {
1330 }
1331
1332 SILC_SERVER_CMD_FUNC(kick)
1333 {
1334 }
1335
1336 SILC_SERVER_CMD_FUNC(restart)
1337 {
1338 }
1339  
1340 SILC_SERVER_CMD_FUNC(close)
1341 {
1342 }
1343  
1344 SILC_SERVER_CMD_FUNC(die)
1345 {
1346 }
1347  
1348 SILC_SERVER_CMD_FUNC(silcoper)
1349 {
1350 }
1351
1352 /* Server side command of LEAVE. Removes client from a channel. */
1353
1354 SILC_SERVER_CMD_FUNC(leave)
1355 {
1356   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1357   SilcServer server = cmd->server;
1358   SilcSocketConnection sock = cmd->sock;
1359   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
1360   SilcChannelID *id;
1361   SilcChannelEntry channel;
1362   SilcBuffer packet;
1363   unsigned int i, argc, key_len;
1364   unsigned char *tmp, channel_key[32];
1365
1366   SILC_LOG_DEBUG(("Start"));
1367
1368   argc = silc_command_get_arg_num(cmd->payload);
1369   if (argc < 1) {
1370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1371                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1372     goto out;
1373   }
1374   if (argc > 2) {
1375     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1376                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1377     goto out;
1378   }
1379
1380   /* Get Channel ID */
1381   tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1382   if (!tmp) {
1383     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1384                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1385     goto out;
1386   }
1387   id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1388
1389   /* Get channel entry */
1390   channel = silc_idlist_find_channel_by_id(server->local_list, id);
1391   if (!channel) {
1392     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1393                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1394     goto out;
1395   }
1396
1397   /* Check whether this client is on the channel */
1398   if (!silc_server_client_on_channel(id_entry, channel)) {
1399     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1400                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1401     goto out;
1402   }
1403
1404   /* Notify routers that they should remove this client from their list
1405      of clients on the channel. */
1406   if (!server->standalone)
1407     silc_server_send_remove_channel_user(server, 
1408                                          server->id_entry->router->connection,
1409                                          server->server_type == SILC_ROUTER ?
1410                                          TRUE : FALSE, id_entry->id, id);
1411
1412   /* Remove client from channel */
1413   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
1414                                           TRUE);
1415   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1416                                         SILC_STATUS_OK);
1417
1418   /* If the channel does not exist anymore we won't send anything */
1419   if (!i)
1420     goto out;
1421
1422   /* Re-generate channel key */
1423   key_len = channel->key_len / 8;
1424   for (i = 0; i < key_len; i++)
1425     channel_key[i] = silc_rng_get_byte(server->rng);
1426   channel->channel_key->cipher->set_key(channel->channel_key->context, 
1427                                         channel_key, key_len);
1428   memset(channel->key, 0, key_len);
1429   silc_free(channel->key);
1430   channel->key = silc_calloc(key_len, sizeof(*channel->key));
1431   memcpy(channel->key, channel_key, key_len);
1432   memset(channel_key, 0, sizeof(channel_key));
1433
1434   /* Encode channel key payload to be distributed on the channel */
1435   packet = 
1436     silc_channel_key_encode_payload(SILC_ID_CHANNEL_LEN, tmp,
1437                                     strlen(channel->channel_key->cipher->name),
1438                                     channel->channel_key->cipher->name,
1439                                     key_len, channel->key);
1440
1441   /* If we are normal server then we will send it to our router.  If we
1442      are router we will send it to all local servers that has clients on
1443      the channel */
1444   if (server->server_type == SILC_SERVER) {
1445     if (!server->standalone)
1446       silc_server_packet_send(server, 
1447                               cmd->server->id_entry->router->connection,
1448                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
1449                               packet->len, TRUE);
1450   } else {
1451
1452   }
1453
1454   /* Send to locally connected clients on the channel */
1455   silc_server_packet_send_local_channel(server, channel, 
1456                                         SILC_PACKET_CHANNEL_KEY, 0,
1457                                         packet->data, packet->len, FALSE);
1458
1459   silc_buffer_free(packet);
1460   silc_free(id);
1461
1462  out:
1463   silc_server_command_free(cmd);
1464 }
1465
1466 /* Server side of command NAMES. Resolves clients and their names currently
1467    joined on the requested channel. The name list is sent back to the
1468    client. */
1469
1470 SILC_SERVER_CMD_FUNC(names)
1471 {
1472   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1473   SilcServer server = cmd->server;
1474   SilcChannelEntry channel;
1475   SilcChannelID *id;
1476   SilcBuffer packet;
1477   unsigned int i, len, len2, argc;
1478   unsigned char *tmp;
1479   char *name_list = NULL, *n;
1480   SilcBuffer client_id_list;
1481
1482   SILC_LOG_DEBUG(("Start"));
1483
1484   argc = silc_command_get_arg_num(cmd->payload);
1485   if (argc < 1) {
1486     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1487                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1488     goto out;
1489   }
1490   if (argc > 2) {
1491     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
1492                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
1493     goto out;
1494   }
1495
1496   /* Get Channel ID */
1497   tmp = silc_command_get_arg_type(cmd->payload, 1, NULL);
1498   if (!tmp) {
1499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1500                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1501     goto out;
1502   }
1503   id = silc_id_str2id(tmp, SILC_ID_CHANNEL);
1504
1505   /* Check whether the channel exists. If we are normal server and the
1506      channel does not exist we will send this same command to our router
1507      which will know if the channel exists. */
1508   channel = silc_idlist_find_channel_by_id(server->local_list, id);
1509   if (!channel) {
1510     if (server->server_type == SILC_SERVER && !server->standalone) {
1511       /* XXX Send names command */
1512
1513       cmd->pending = TRUE;
1514       silc_server_command_pending(SILC_COMMAND_NAMES, 
1515                                   silc_server_command_names, context);
1516       return;
1517     }
1518
1519     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1520                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1521     goto out;
1522   }
1523
1524   /* Assemble the name list now */
1525   name_list = NULL;
1526   len = 0;
1527   for (i = 0; i < channel->user_list_count; i++) {
1528     if (!channel->user_list[i].client)
1529       continue;
1530
1531     n = channel->user_list[i].client->nickname;
1532     if (n) {
1533       len2 = strlen(n);
1534       len += len2;
1535       name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
1536       memcpy(name_list + (len - len2), n, len2);
1537       name_list[len] = 0;
1538
1539       if (i == channel->user_list_count - 1)
1540         break;
1541       memcpy(name_list + len, ",", 1);
1542       len++;
1543     }
1544   }
1545   if (!name_list)
1546     name_list = "";
1547
1548   /* Assemble the Client ID list now */
1549   client_id_list = silc_buffer_alloc(SILC_ID_CLIENT_LEN * 
1550                                      channel->user_list_count);
1551   silc_buffer_pull_tail(client_id_list, (SILC_ID_CLIENT_LEN *
1552                                          channel->user_list_count));
1553   for (i = 0; i < channel->user_list_count; i++) {
1554     unsigned char *id_string;
1555
1556     if (!channel->user_list[i].client)
1557       continue;
1558
1559     id_string = silc_id_id2str(channel->user_list[i].client->id,
1560                                SILC_ID_CLIENT);
1561     silc_buffer_format(client_id_list,
1562                        SILC_STR_UI_XNSTRING(id_string, SILC_ID_CLIENT_LEN),
1563                        SILC_STR_END);
1564     silc_buffer_pull(client_id_list, SILC_ID_CLIENT_LEN);
1565     silc_free(id_string);
1566   }
1567   silc_buffer_push(client_id_list, 
1568                    client_id_list->data - client_id_list->head);
1569
1570   /* Send reply */
1571   packet = silc_command_encode_reply_payload_va(SILC_COMMAND_NAMES,
1572                                                 SILC_STATUS_OK, 3,
1573                                                 2, tmp, SILC_ID_CHANNEL_LEN,
1574                                                 3, name_list, 
1575                                                 strlen(name_list),
1576                                                 4, client_id_list->data,
1577                                                 client_id_list->len);
1578   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1579                           packet->data, packet->len, FALSE);
1580     
1581   silc_buffer_free(packet);
1582   silc_free(name_list);
1583   silc_buffer_free(client_id_list);
1584   silc_free(id);
1585
1586  out:
1587   silc_server_command_free(cmd);
1588 }