updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2000 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      unsigned int arg_type,
38                                      unsigned char *arg,
39                                      unsigned int arg_len);
40 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_users(SilcServer server,
42                                     SilcSocketConnection sock,
43                                     SilcChannelEntry channel,
44                                     int pending);
45
46 /* Server command list. */
47 SilcServerCommand silc_command_list[] =
48 {
49   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
50   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
54   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
56   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
58   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
59   SILC_SERVER_CMD(connect, CONNECT, 
60                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
61   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
63   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
64   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
65   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
67   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
68   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
69   SILC_SERVER_CMD(restart, RESTART, 
70                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
71   SILC_SERVER_CMD(close, CLOSE,
72                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73   SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
74   SILC_SERVER_CMD(silcoper, SILCOPER,
75                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
76   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
77   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
78
79   { NULL, 0 },
80 };
81
82 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max)            \
83 do {                                                                          \
84   unsigned int _argc = silc_argument_get_arg_num(cmd->args);                  \
85                                                                               \
86   SILC_LOG_DEBUG(("Start"));                                                  \
87                                                                               \
88   if (_argc < min) {                                                          \
89     silc_server_command_send_status_reply(cmd, command,                       \
90                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
91     silc_server_command_free(cmd);                                            \
92     return;                                                                   \
93   }                                                                           \
94   if (_argc > max) {                                                          \
95     silc_server_command_send_status_reply(cmd, command,                       \
96                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
97     silc_server_command_free(cmd);                                            \
98     return;                                                                   \
99   }                                                                           \
100 } while(0)
101
102 /* Returns TRUE if the connection is registered. Unregistered connections
103    usually cannot send commands hence the check. */
104
105 static int silc_server_is_registered(SilcServer server,
106                                      SilcSocketConnection sock,
107                                      SilcServerCommandContext cmd,
108                                      SilcCommand command)
109 {
110   SilcIDListData idata = (SilcIDListData)sock->user_data;
111   if (idata->registered)
112     return TRUE;
113
114   silc_server_command_send_status_reply(cmd, command,
115                                         SILC_STATUS_ERR_NOT_REGISTERED);
116   silc_server_command_free(cmd);
117   return FALSE;
118 }
119
120 /* Processes received command packet. */
121
122 void silc_server_command_process(SilcServer server,
123                                  SilcSocketConnection sock,
124                                  SilcPacketContext *packet)
125 {
126   SilcServerCommandContext ctx;
127   SilcServerCommand *cmd;
128
129 #if 0
130   /* XXX allow commands in but do not execute them more than once per
131      two seconds. */
132
133   /* Check whether it is allowed for this connection to execute any
134      command. */
135   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136     time_t curtime;
137     SilcClientEntry client = (SilcClientEntry)sock->user_data;
138
139     if (!client)
140       return;
141
142     /* Allow only one command executed in 2 seconds. */
143     curtime = time(NULL);
144     if (client->last_command && (curtime - client->last_command) < 2)
145       return;
146
147     /* Update access time */
148     client->last_command = curtime;
149   }
150 #endif
151   
152   /* Allocate command context. This must be free'd by the
153      command routine receiving it. */
154   ctx = silc_calloc(1, sizeof(*ctx));
155   ctx->server = server;
156   ctx->sock = sock;
157   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158   
159   /* Parse the command payload in the packet */
160   ctx->payload = silc_command_payload_parse(packet->buffer);
161   if (!ctx->payload) {
162     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
163     silc_buffer_free(packet->buffer);
164     silc_packet_context_free(packet);
165     silc_free(ctx);
166     return;
167   }
168   ctx->args = silc_command_get_args(ctx->payload);
169   
170   /* Execute command. If this fails the packet is dropped. */
171   for (cmd = silc_command_list; cmd->cb; cmd++)
172     if (cmd->cmd == silc_command_get(ctx->payload)) {
173
174       if (!(cmd->flags & SILC_CF_REG)) {
175         cmd->cb(ctx);
176         break;
177       }
178       
179       if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
180         cmd->cb(ctx);
181         break;
182       }
183     }
184
185   if (cmd == NULL) {
186     SILC_LOG_ERROR(("Unknown command, packet dropped"));
187     silc_server_command_free(ctx);
188     return;
189   }
190 }
191
192 /* Add new pending command to be executed when reply to a command has been
193    received. The `reply_cmd' is the command that will call the `callback'
194    with `context' when reply has been received.  If `ident' is non-zero
195    the `callback' will be executed when received reply with command
196    identifier `ident'. */
197
198 void silc_server_command_pending(SilcServer server,
199                                  SilcCommand reply_cmd,
200                                  unsigned short ident,
201                                  SilcCommandCb callback,
202                                  void *context)
203 {
204   SilcServerCommandPending *reply;
205
206   reply = silc_calloc(1, sizeof(*reply));
207   reply->reply_cmd = reply_cmd;
208   reply->ident = ident;
209   reply->context = context;
210   reply->callback = callback;
211   silc_dlist_add(server->pending_commands, reply);
212 }
213
214 /* Deletes pending command by reply command type. */
215
216 void silc_server_command_pending_del(SilcServer server,
217                                      SilcCommand reply_cmd,
218                                      unsigned short ident)
219 {
220   SilcServerCommandPending *r;
221
222   silc_dlist_start(server->pending_commands);
223   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
224     if (r->reply_cmd == reply_cmd && r->ident == ident) {
225       silc_dlist_del(server->pending_commands, r);
226       break;
227     }
228   }
229 }
230
231 /* Checks for pending commands and marks callbacks to be called from
232    the command reply function. Returns TRUE if there were pending command. */
233
234 int silc_server_command_pending_check(SilcServer server,
235                                       SilcServerCommandReplyContext ctx,
236                                       SilcCommand command, 
237                                       unsigned short ident)
238 {
239   SilcServerCommandPending *r;
240
241   silc_dlist_start(server->pending_commands);
242   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
243     if (r->reply_cmd == command && r->ident == ident) {
244       ctx->context = r->context;
245       ctx->callback = r->callback;
246       ctx->ident = ident;
247       return TRUE;
248     }
249   }
250
251   return FALSE;
252 }
253
254 /* Free's the command context allocated before executing the command */
255
256 static void silc_server_command_free(SilcServerCommandContext cmd)
257 {
258   if (cmd) {
259     if (cmd->payload)
260       silc_command_free_payload(cmd->payload);
261     if (cmd->packet)
262       silc_packet_context_free(cmd->packet);
263     silc_free(cmd);
264   }
265 }
266
267 /* Sends simple status message as command reply packet */
268
269 static void 
270 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
271                                       SilcCommand command,
272                                       SilcCommandStatus status)
273 {
274   SilcBuffer buffer;
275
276   SILC_LOG_DEBUG(("Sending command status %d", status));
277
278   buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
279   silc_server_packet_send(cmd->server, cmd->sock,
280                           SILC_PACKET_COMMAND_REPLY, 0, 
281                           buffer->data, buffer->len, FALSE);
282   silc_buffer_free(buffer);
283 }
284
285 /* Sends command status reply with one extra argument. The argument
286    type must be sent as argument. */
287
288 static void 
289 silc_server_command_send_status_data(SilcServerCommandContext cmd,
290                                      SilcCommand command,
291                                      SilcCommandStatus status,
292                                      unsigned int arg_type,
293                                      unsigned char *arg,
294                                      unsigned int arg_len)
295 {
296   SilcBuffer buffer;
297
298   SILC_LOG_DEBUG(("Sending command status %d", status));
299
300   buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
301                                                 arg_type, arg, arg_len);
302   silc_server_packet_send(cmd->server, cmd->sock,
303                           SILC_PACKET_COMMAND_REPLY, 0, 
304                           buffer->data, buffer->len, FALSE);
305   silc_buffer_free(buffer);
306 }
307
308 /******************************************************************************
309
310                               WHOIS Functions
311
312 ******************************************************************************/
313
314 static int
315 silc_server_command_whois_parse(SilcServerCommandContext cmd,
316                                 SilcClientID ***client_id,
317                                 unsigned int *client_id_count,
318                                 char **nickname,
319                                 char **server_name,
320                                 int *count,
321                                 SilcCommand command)
322 {
323   unsigned char *tmp;
324   unsigned int len;
325   unsigned int argc = silc_argument_get_arg_num(cmd->args);
326   int i, k;
327
328   /* If client ID is in the command it must be used instead of nickname */
329   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
330   if (!tmp) {
331     /* No ID, get the nickname@server string and parse it. */
332     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
333     if (tmp) {
334       if (strchr(tmp, '@')) {
335         len = strcspn(tmp, "@");
336         *nickname = silc_calloc(len + 1, sizeof(char));
337         memcpy(*nickname, tmp, len);
338         *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
339         memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
340       } else {
341         *nickname = strdup(tmp);
342       }
343     } else {
344       silc_server_command_send_status_reply(cmd, command,
345                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
346       return FALSE;
347     }
348   } else {
349     /* Command includes ID, we must use that.  Also check whether the command
350        has more than one ID set - take them all. */
351
352     *client_id = silc_calloc(1, sizeof(**client_id));
353     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
354     *client_id_count = 1;
355
356     /* Take all ID's from the command packet */
357     if (argc > 3) {
358       for (k = 1, i = 4; i < argc; i++) {
359         tmp = silc_argument_get_arg_type(cmd->args, i, &len);
360         if (tmp) {
361           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
362                                     (*client_id_count + 1));
363           (*client_id)[k++] = silc_id_payload_parse_id(tmp, len);
364           (*client_id_count)++;
365         }
366       }
367     }
368
369     /* Command includes ID, use that */
370   }
371
372   /* Get the max count of reply messages allowed */
373   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
374   if (tmp)
375     *count = atoi(tmp);
376   else
377     *count = 0;
378
379   return TRUE;
380 }
381
382 static char
383 silc_server_command_whois_check(SilcServerCommandContext cmd,
384                                 SilcClientEntry *clients,
385                                 unsigned int clients_count)
386 {
387   SilcServer server = cmd->server;
388   int i;
389   SilcClientEntry entry;
390
391   for (i = 0; i < clients_count; i++) {
392     entry = clients[i];
393
394     if (!entry->nickname || !entry->username || !entry->userinfo) {
395       SilcBuffer tmpbuf;
396       unsigned short old_ident;
397       
398       old_ident = silc_command_get_ident(cmd->payload);
399       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
400       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
401
402       /* Send WHOIS command */
403       silc_server_packet_send(server, entry->router->connection,
404                               SILC_PACKET_COMMAND, cmd->packet->flags,
405                               tmpbuf->data, tmpbuf->len, TRUE);
406       
407       /* Reprocess this packet after received reply */
408       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
409                                   silc_command_get_ident(cmd->payload),
410                                   silc_server_command_whois, (void *)cmd);
411       cmd->pending = TRUE;
412       
413       silc_command_set_ident(cmd->payload, old_ident);
414
415       silc_buffer_free(tmpbuf);
416       return FALSE;
417     }
418   }
419
420   return TRUE;
421 }
422
423 static void
424 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
425                                      SilcClientEntry *clients,
426                                      unsigned int clients_count)
427 {
428   SilcServer server = cmd->server;
429   char *tmp;
430   int i, count = 0, len;
431   SilcBuffer packet, idp;
432   SilcClientEntry entry;
433   SilcCommandStatus status;
434   unsigned short ident = silc_command_get_ident(cmd->payload);
435
436   status = SILC_STATUS_OK;
437   if (clients_count > 1)
438     status = SILC_STATUS_LIST_START;
439
440   for (i = 0; i < clients_count; i++) {
441     entry = clients[i];
442
443     if (count && i - 1 == count)
444       break;
445
446     if (clients_count > 2)
447       status = SILC_STATUS_LIST_ITEM;
448
449     if (clients_count > 1 && i == clients_count - 1)
450       status = SILC_STATUS_LIST_END;
451
452     /* Send WHOIS reply */
453     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
454     tmp = silc_argument_get_first_arg(cmd->args, NULL);
455     
456     /* XXX */
457     {
458       char nh[256], uh[256];
459       unsigned char idle[4];
460       SilcSocketConnection hsock;
461
462       memset(uh, 0, sizeof(uh));
463       memset(nh, 0, sizeof(nh));
464       
465       strncat(nh, entry->nickname, strlen(entry->nickname));
466       if (!strchr(entry->nickname, '@')) {
467         strncat(nh, "@", 1);
468         len = entry->router ? strlen(entry->router->server_name) :
469           strlen(server->server_name);
470         strncat(nh, entry->router ? entry->router->server_name :
471                 server->server_name, len);
472       }
473       
474       strncat(uh, entry->username, strlen(entry->username));
475       if (!strchr(entry->username, '@')) {
476         strncat(uh, "@", 1);
477         hsock = (SilcSocketConnection)entry->connection;
478         len = strlen(hsock->hostname);
479         strncat(uh, hsock->hostname, len);
480       }
481       
482       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
483       
484       /* XXX */
485       if (entry->userinfo)
486         packet = 
487           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
488                                                status, ident, 5, 
489                                                2, idp->data, idp->len,
490                                                3, nh, strlen(nh),
491                                                4, uh, strlen(uh),
492                                                5, entry->userinfo, 
493                                                strlen(entry->userinfo),
494                                                7, idle, 4);
495       else
496         packet = 
497           silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
498                                                status, ident, 4, 
499                                                2, idp->data, idp->len,
500                                                3, nh, strlen(nh),
501                                                4, uh, strlen(uh),
502                                                7, idle, 4);
503     }
504     
505     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
506                             0, packet->data, packet->len, FALSE);
507     
508     silc_buffer_free(packet);
509     silc_buffer_free(idp);
510   }
511 }
512
513 static int
514 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
515 {
516   SilcServer server = cmd->server;
517   char *nick = NULL, *server_name = NULL;
518   int count = 0, clients_count = 0;
519   SilcClientEntry *clients = NULL, entry;
520   SilcClientID **client_id = NULL;
521   unsigned int client_id_count = 0;
522   int i, ret = 0;
523
524   /* Protocol dictates that we must always send the received WHOIS request
525      to our router if we are normal server, so let's do it now unless we
526      are standalone. We will not send any replies to the client until we
527      have received reply from the router. */
528   if (server->server_type == SILC_SERVER && 
529       !cmd->pending && !server->standalone) {
530     SilcBuffer tmpbuf;
531     unsigned short old_ident;
532
533     old_ident = silc_command_get_ident(cmd->payload);
534     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
535     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
536
537     /* Send WHOIS command to our router */
538     silc_server_packet_send(server, (SilcSocketConnection)
539                             server->router->connection,
540                             SILC_PACKET_COMMAND, cmd->packet->flags,
541                             tmpbuf->data, tmpbuf->len, TRUE);
542
543     /* Reprocess this packet after received reply from router */
544     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
545                                 silc_command_get_ident(cmd->payload),
546                                 silc_server_command_whois, (void *)cmd);
547     cmd->pending = TRUE;
548
549     silc_command_set_ident(cmd->payload, old_ident);
550
551     silc_buffer_free(tmpbuf);
552     ret = -1;
553     goto out;
554   }
555
556   /* We are ready to process the command request. Let's search for the
557      requested client and send reply to the requesting client. */
558
559   /* Parse the whois request */
560   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
561                                        &nick, &server_name, &count,
562                                        SILC_COMMAND_WHOIS))
563     return 0;
564
565   /* Get all clients matching that ID or nickname from local list */
566   if (client_id_count) {
567     /* Check all Client ID's received in the command packet */
568     for (i = 0; i < client_id_count; i++) {
569       entry = silc_idlist_find_client_by_id(server->local_list, 
570                                             client_id[i], NULL);
571       if (entry) {
572         clients = silc_realloc(clients, sizeof(*clients) * 
573                                (clients_count + 1));
574         clients[clients_count++] = entry;
575       }
576     }
577   } else {
578     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
579                                                   nick, server_name,
580                                                   &clients_count);
581   }
582   
583   /* Check global list as well */
584   if (!clients) {
585     if (client_id_count) {
586       /* Check all Client ID's received in the command packet */
587       for (i = 0; i < client_id_count; i++) {
588         entry = silc_idlist_find_client_by_id(server->global_list, 
589                                               client_id[i], NULL);
590         if (entry) {
591           clients = silc_realloc(clients, sizeof(*clients) * 
592                                  (clients_count + 1));
593           clients[clients_count++] = entry;
594         }
595       }
596     } else {
597       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
598                                                     nick, server_name,
599                                                     &clients_count);
600     }
601   }
602   
603   if (!clients) {
604     /* Such client(s) really does not exist in the SILC network. */
605     if (!client_id_count) {
606       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
607                                            SILC_STATUS_ERR_NO_SUCH_NICK,
608                                            3, nick, strlen(nick));
609     } else {
610       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
611       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
612                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
613                                            2, idp->data, idp->len);
614       silc_buffer_free(idp);
615     }
616     goto out;
617   }
618
619   /* Router always finds the client entry if it exists in the SILC network.
620      However, it might be incomplete entry and does not include all the
621      mandatory fields that WHOIS command reply requires. Check for these and
622      make query from the server who owns the client if some fields are 
623      missing. */
624   if (server->server_type == SILC_ROUTER &&
625       !silc_server_command_whois_check(cmd, clients, clients_count)) {
626     ret = -1;
627     goto out;
628   }
629
630   /* Send the command reply to the client */
631   silc_server_command_whois_send_reply(cmd, clients, clients_count);
632
633  out:
634   if (client_id_count) {
635     for (i = 0; i < client_id_count; i++)
636       silc_free(client_id[i]);
637     silc_free(client_id);
638   }
639   if (clients)
640     silc_free(clients);
641   if (nick)
642     silc_free(nick);
643   if (server_name)
644     silc_free(server_name);
645
646   return ret;
647 }
648
649 static int
650 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
651 {
652   SilcServer server = cmd->server;
653   char *nick = NULL, *server_name = NULL;
654   int count = 0, clients_count = 0;
655   SilcClientEntry *clients = NULL, entry;
656   SilcClientID **client_id = NULL;
657   unsigned int client_id_count = 0;
658   int i, ret = 0;
659
660   /* Parse the whois request */
661   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
662                                        &nick, &server_name, &count,
663                                        SILC_COMMAND_WHOIS))
664     return 0;
665
666   /* Process the command request. Let's search for the requested client and
667      send reply to the requesting server. */
668
669   if (client_id_count) {
670     /* Check all Client ID's received in the command packet */
671     for (i = 0; i < client_id_count; i++) {
672       entry = silc_idlist_find_client_by_id(server->local_list, 
673                                             client_id[i], NULL);
674       if (entry) {
675         clients = silc_realloc(clients, sizeof(*clients) * 
676                                (clients_count + 1));
677         clients[clients_count++] = entry;
678       }
679     }
680   } else {
681     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
682                                                   nick, server_name,
683                                                   &clients_count);
684     if (!clients)
685       clients = silc_idlist_get_clients_by_hash(server->local_list, 
686                                                 nick, server->md5hash,
687                                                 &clients_count);
688   }
689   
690   /* If we are router we will check our global list as well. */
691   if (!clients && server->server_type == SILC_ROUTER) {
692     if (client_id_count) {
693       /* Check all Client ID's received in the command packet */
694       for (i = 0; i < client_id_count; i++) {
695         entry = silc_idlist_find_client_by_id(server->global_list, 
696                                               client_id[i], NULL);
697         if (entry) {
698           clients = silc_realloc(clients, sizeof(*clients) * 
699                                  (clients_count + 1));
700           clients[clients_count++] = entry;
701         }
702       }
703     } else {
704       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
705                                                     nick, server_name,
706                                                     &clients_count);
707       if (!clients)
708         clients = silc_idlist_get_clients_by_hash(server->global_list, 
709                                                   nick, server->md5hash,
710                                                   &clients_count);
711     }
712   }
713
714   if (!clients) {
715     /* Such a client really does not exist in the SILC network. */
716     if (!client_id_count) {
717       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
718                                            SILC_STATUS_ERR_NO_SUCH_NICK,
719                                            3, nick, strlen(nick));
720     } else {
721       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
722       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
723                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
724                                            2, idp->data, idp->len);
725       silc_buffer_free(idp);
726     }
727     goto out;
728   }
729
730   /* Router always finds the client entry if it exists in the SILC network.
731      However, it might be incomplete entry and does not include all the
732      mandatory fields that WHOIS command reply requires. Check for these and
733      make query from the server who owns the client if some fields are 
734      missing. */
735   if (server->server_type == SILC_ROUTER &&
736       !silc_server_command_whois_check(cmd, clients, clients_count)) {
737     ret = -1;
738     goto out;
739   }
740
741   /* Send the command reply to the client */
742   silc_server_command_whois_send_reply(cmd, clients, clients_count);
743
744  out:
745   if (client_id_count) {
746     for (i = 0; i < client_id_count; i++)
747       silc_free(client_id[i]);
748     silc_free(client_id);
749   }
750   if (clients)
751     silc_free(clients);
752   if (nick)
753     silc_free(nick);
754   if (server_name)
755     silc_free(server_name);
756
757   return ret;
758 }
759
760 /* Server side of command WHOIS. Processes user's query and sends found 
761    results as command replies back to the client. */
762
763 SILC_SERVER_CMD_FUNC(whois)
764 {
765   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
766   int ret;
767
768   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
769
770   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
771     ret = silc_server_command_whois_from_client(cmd);
772   else
773     ret = silc_server_command_whois_from_server(cmd);
774
775   if (!ret)
776     silc_server_command_free(cmd);
777 }
778
779 SILC_SERVER_CMD_FUNC(whowas)
780 {
781 }
782
783 /******************************************************************************
784
785                               IDENTIFY Functions
786
787 ******************************************************************************/
788
789 /* Checks that all mandatory fields are present. If not then send WHOIS 
790    request to the server who owns the client. We use WHOIS because we want
791    to get as much information as possible at once. */
792
793 static char
794 silc_server_command_identify_check(SilcServerCommandContext cmd,
795                                    SilcClientEntry *clients,
796                                    unsigned int clients_count)
797 {
798   SilcServer server = cmd->server;
799   int i;
800   SilcClientEntry entry;
801
802   for (i = 0; i < clients_count; i++) {
803     entry = clients[i];
804
805     if (!entry->nickname) {
806       SilcBuffer tmpbuf;
807       unsigned short old_ident;
808       
809       old_ident = silc_command_get_ident(cmd->payload);
810       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
811       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
812       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
813       
814       /* Send WHOIS request. We send WHOIS since we're doing the requesting
815          now anyway so make it a good one. */
816       silc_server_packet_send(server, entry->router->connection,
817                               SILC_PACKET_COMMAND, cmd->packet->flags,
818                               tmpbuf->data, tmpbuf->len, TRUE);
819       
820       /* Reprocess this packet after received reply */
821       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
822                                   silc_command_get_ident(cmd->payload),
823                                   silc_server_command_identify, (void *)cmd);
824       cmd->pending = TRUE;
825       
826       /* Put old data back to the Command Payload we just changed */
827       silc_command_set_ident(cmd->payload, old_ident);
828       silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
829
830       silc_buffer_free(tmpbuf);
831       return FALSE;
832     }
833   }
834
835   return TRUE;
836 }
837
838 static void
839 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
840                                         SilcClientEntry *clients,
841                                         unsigned int clients_count)
842 {
843   SilcServer server = cmd->server;
844   char *tmp;
845   int i, count = 0, len;
846   SilcBuffer packet, idp;
847   SilcClientEntry entry;
848   SilcCommandStatus status;
849   unsigned short ident = silc_command_get_ident(cmd->payload);
850
851   status = SILC_STATUS_OK;
852   if (clients_count > 1)
853     status = SILC_STATUS_LIST_START;
854
855   for (i = 0; i < clients_count; i++) {
856     entry = clients[i];
857
858     if (count && i - 1 == count)
859       break;
860
861     if (clients_count > 2)
862       status = SILC_STATUS_LIST_ITEM;
863
864     if (clients_count > 1 && i == clients_count - 1)
865       status = SILC_STATUS_LIST_END;
866
867     /* Send IDENTIFY reply */
868     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
869     tmp = silc_argument_get_first_arg(cmd->args, NULL);
870     
871     /* XXX */
872     {
873       char nh[256], uh[256];
874       SilcSocketConnection hsock;
875
876       memset(uh, 0, sizeof(uh));
877       memset(nh, 0, sizeof(nh));
878       
879       strncat(nh, entry->nickname, strlen(entry->nickname));
880       if (!strchr(entry->nickname, '@')) {
881         strncat(nh, "@", 1);
882         len = entry->router ? strlen(entry->router->server_name) :
883           strlen(server->server_name);
884         strncat(nh, entry->router ? entry->router->server_name :
885                 server->server_name, len);
886       }
887       
888       if (!entry->username) {
889         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
890                                                       SILC_STATUS_OK, ident, 2,
891                                                       2, idp->data, idp->len, 
892                                                       3, nh, strlen(nh));
893       } else {
894         strncat(uh, entry->username, strlen(entry->username));
895         if (!strchr(entry->username, '@')) {
896           strncat(uh, "@", 1);
897           hsock = (SilcSocketConnection)entry->connection;
898           len = strlen(hsock->hostname);
899           strncat(uh, hsock->hostname, len);
900         }
901       
902         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
903                                                       SILC_STATUS_OK, ident, 3,
904                                                       2, idp->data, idp->len, 
905                                                       3, nh, strlen(nh),
906                                                       4, uh, strlen(uh));
907       }
908       
909       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
910                               0, packet->data, packet->len, FALSE);
911       
912       silc_buffer_free(packet);
913       silc_buffer_free(idp);
914     }
915   }
916 }
917
918 static int
919 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
920 {
921   SilcServer server = cmd->server;
922   char *nick = NULL, *server_name = NULL;
923   int count = 0, clients_count = 0; 
924   SilcClientEntry *clients = NULL, entry;
925   SilcClientID **client_id = NULL;
926   unsigned int client_id_count = 0;
927   int i, ret = 0;
928
929   /* Protocol dictates that we must always send the received IDENTIFY request
930      to our router if we are normal server, so let's do it now unless we
931      are standalone. We will not send any replies to the client until we
932      have received reply from the router. */
933   if (server->server_type == SILC_SERVER && 
934       !cmd->pending && !server->standalone) {
935     SilcBuffer tmpbuf;
936     unsigned short old_ident;
937
938     old_ident = silc_command_get_ident(cmd->payload);
939     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
940     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
941
942     /* Send IDENTIFY command to our router */
943     silc_server_packet_send(server, (SilcSocketConnection)
944                             server->router->connection,
945                             SILC_PACKET_COMMAND, cmd->packet->flags,
946                             tmpbuf->data, tmpbuf->len, TRUE);
947
948     /* Reprocess this packet after received reply from router */
949     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
950                                 silc_command_get_ident(cmd->payload),
951                                 silc_server_command_identify, (void *)cmd);
952     cmd->pending = TRUE;
953
954     silc_command_set_ident(cmd->payload, old_ident);
955
956     silc_buffer_free(tmpbuf);
957     ret = -1;
958     goto out;
959   }
960
961   /* We are ready to process the command request. Let's search for the
962      requested client and send reply to the requesting client. */
963
964   /* Parse the IDENTIFY request */
965   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
966                                        &nick, &server_name, &count,
967                                        SILC_COMMAND_IDENTIFY))
968     return 0;
969
970   /* Get all clients matching that ID or nickname from local list */
971   if (client_id_count) { 
972     /* Check all Client ID's received in the command packet */
973     for (i = 0; i < client_id_count; i++) {
974       entry = silc_idlist_find_client_by_id(server->local_list, 
975                                             client_id[i], NULL);
976       if (entry) {
977         clients = silc_realloc(clients, sizeof(*clients) * 
978                                (clients_count + 1));
979         clients[clients_count++] = entry;
980       }
981     }
982   } else {
983     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
984                                                   nick, server_name,
985                                                   &clients_count);
986   }
987   
988   /* Check global list as well */
989   if (!clients) {
990     if (client_id_count) {
991       /* Check all Client ID's received in the command packet */
992       for (i = 0; i < client_id_count; i++) {
993         entry = silc_idlist_find_client_by_id(server->global_list, 
994                                               client_id[i], NULL);
995         if (entry) {
996           clients = silc_realloc(clients, sizeof(*clients) * 
997                                  (clients_count + 1));
998           clients[clients_count++] = entry;
999         }
1000       }
1001     } else {
1002       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1003                                                     nick, server_name,
1004                                                     &clients_count);
1005     }
1006   }
1007   
1008   if (!clients) {
1009     /* Such a client really does not exist in the SILC network. */
1010     if (!client_id_count) {
1011       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1012                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1013                                            3, nick, strlen(nick));
1014     } else {
1015       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1016       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1017                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1018                                            2, idp->data, idp->len);
1019       silc_buffer_free(idp);
1020     }
1021     goto out;
1022   }
1023
1024   /* Check that all mandatory fields are present and request those data
1025      from the server who owns the client if necessary. */
1026   if (!cmd->pending && server->server_type == SILC_ROUTER &&
1027       !silc_server_command_identify_check(cmd, clients, clients_count)) {
1028     ret = -1;
1029     goto out;
1030   }
1031
1032   /* Send the command reply to the client */
1033   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1034
1035  out:
1036   if (client_id_count) {
1037     for (i = 0; i < client_id_count; i++)
1038       silc_free(client_id[i]);
1039     silc_free(client_id);
1040   }
1041   if (clients)
1042     silc_free(clients);
1043   if (nick)
1044     silc_free(nick);
1045   if (server_name)
1046     silc_free(server_name);
1047
1048   return ret;
1049 }
1050
1051 static int
1052 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1053 {
1054   SilcServer server = cmd->server;
1055   char *nick = NULL, *server_name = NULL;
1056   int count = 0, clients_count = 0;
1057   SilcClientEntry *clients = NULL, entry;
1058   SilcClientID **client_id = NULL;
1059   unsigned int client_id_count = 0;
1060   int i, ret = 0;
1061
1062   /* Parse the IDENTIFY request */
1063   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1064                                        &nick, &server_name, &count,
1065                                        SILC_COMMAND_IDENTIFY))
1066     return 0;
1067
1068   /* Process the command request. Let's search for the requested client and
1069      send reply to the requesting server. */
1070
1071   if (client_id_count) {
1072     /* Check all Client ID's received in the command packet */
1073     for (i = 0; i < client_id_count; i++) {
1074       entry = silc_idlist_find_client_by_id(server->local_list, 
1075                                             client_id[i], NULL);
1076       if (entry) {
1077         clients = silc_realloc(clients, sizeof(*clients) * 
1078                                (clients_count + 1));
1079         clients[clients_count++] = entry;
1080       }
1081     }
1082   } else {
1083     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1084                                                   nick, server_name,
1085                                                   &clients_count);
1086     if (!clients)
1087       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1088                                                 nick, server->md5hash,
1089                                                 &clients_count);
1090   }
1091   
1092   /* If we are router we will check our global list as well. */
1093   if (!clients && server->server_type == SILC_ROUTER) {
1094     if (client_id_count) {
1095       /* Check all Client ID's received in the command packet */
1096       for (i = 0; i < client_id_count; i++) {
1097         entry = silc_idlist_find_client_by_id(server->global_list, 
1098                                               client_id[i], NULL);
1099         if (entry) {
1100           clients = silc_realloc(clients, sizeof(*clients) * 
1101                                  (clients_count + 1));
1102           clients[clients_count++] = entry;
1103         }
1104       }
1105     } else {
1106       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1107                                                     nick, server_name,
1108                                                     &clients_count);
1109       if (!clients)
1110         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1111                                                   nick, server->md5hash,
1112                                                   &clients_count);
1113     }
1114   }
1115
1116   if (!clients) {
1117     /* Such a client really does not exist in the SILC network. */
1118     if (!client_id_count) {
1119       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1120                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1121                                            3, nick, strlen(nick));
1122     } else {
1123       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1124       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1125                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1126                                            2, idp->data, idp->len);
1127       silc_buffer_free(idp);
1128     }
1129     goto out;
1130   }
1131
1132   /* Check that all mandatory fields are present and request those data
1133      from the server who owns the client if necessary. */
1134   if (!cmd->pending && server->server_type == SILC_ROUTER &&
1135       !silc_server_command_identify_check(cmd, clients, clients_count)) {
1136     ret = -1;
1137     goto out;
1138   }
1139
1140   /* Send the command reply */
1141   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1142
1143  out:
1144   if (client_id_count) {
1145     for (i = 0; i < client_id_count; i++)
1146       silc_free(client_id[i]);
1147     silc_free(client_id);
1148   }
1149   if (clients)
1150     silc_free(clients);
1151   if (nick)
1152     silc_free(nick);
1153   if (server_name)
1154     silc_free(server_name);
1155
1156   return ret;
1157 }
1158
1159 SILC_SERVER_CMD_FUNC(identify)
1160 {
1161   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1162   int ret;
1163
1164   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1165
1166   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1167     ret = silc_server_command_identify_from_client(cmd);
1168   else
1169     ret = silc_server_command_identify_from_server(cmd);
1170
1171   if (!ret)
1172     silc_server_command_free(cmd);
1173 }
1174
1175 /* Checks string for bad characters and returns TRUE if they are found. */
1176
1177 static int silc_server_command_bad_chars(char *nick)
1178 {
1179   if (strchr(nick, '\\')) return TRUE;
1180   if (strchr(nick, '\"')) return TRUE;
1181   if (strchr(nick, '´')) return TRUE;
1182   if (strchr(nick, '`')) return TRUE;
1183   if (strchr(nick, '\'')) return TRUE;
1184   if (strchr(nick, '*')) return TRUE;
1185   if (strchr(nick, '/')) return TRUE;
1186   if (strchr(nick, '@')) return TRUE;
1187
1188   return FALSE;
1189 }
1190
1191 /* Server side of command NICK. Sets nickname for user. Setting
1192    nickname causes generation of a new client ID for the client. The
1193    new client ID is sent to the client after changing the nickname. */
1194
1195 SILC_SERVER_CMD_FUNC(nick)
1196 {
1197   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1198   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1199   SilcServer server = cmd->server;
1200   SilcBuffer packet, nidp, oidp;
1201   SilcClientID *new_id;
1202   char *nick;
1203
1204   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1205
1206   /* Check nickname */
1207   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1208   if (silc_server_command_bad_chars(nick) == TRUE) {
1209     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1210                                           SILC_STATUS_ERR_BAD_NICKNAME);
1211     goto out;
1212   }
1213
1214   /* Create new Client ID */
1215   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1216                            cmd->server->md5hash, nick,
1217                            &new_id);
1218
1219   /* Send notify about nickname change to our router. We send the new
1220      ID and ask to replace it with the old one. If we are router the
1221      packet is broadcasted. */
1222   if (!cmd->server->standalone)
1223     silc_server_send_replace_id(server, server->router->connection, 
1224                                 server->server_type == SILC_SERVER ? 
1225                                 FALSE : TRUE, client->id,
1226                                 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1227                                 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1228
1229   /* Remove old cache entry */
1230   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
1231                          client->id); 
1232
1233   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1234
1235   /* Free old ID */
1236   if (client->id) {
1237     memset(client->id, 0, SILC_ID_CLIENT_LEN);
1238     silc_free(client->id);
1239   }
1240
1241   /* Save the nickname as this client is our local client */
1242   if (client->nickname)
1243     silc_free(client->nickname);
1244
1245   client->nickname = strdup(nick);
1246   client->id = new_id;
1247
1248   /* Update client cache */
1249   silc_idcache_add(server->local_list->clients, client->nickname, 
1250                    SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1251
1252   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1253
1254   /* Send NICK_CHANGE notify */
1255   silc_server_send_notify_on_channels(server, client, 
1256                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1257                                       oidp->data, oidp->len, 
1258                                       nidp->data, nidp->len);
1259
1260   /* Send the new Client ID as reply command back to client */
1261   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1262                                                 SILC_STATUS_OK, 0, 1, 
1263                                                 2, nidp->data, nidp->len);
1264   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1265                           0, packet->data, packet->len, FALSE);
1266
1267   silc_buffer_free(packet);
1268   silc_buffer_free(nidp);
1269   silc_buffer_free(oidp);
1270   
1271  out:
1272   silc_server_command_free(cmd);
1273 }
1274
1275 SILC_SERVER_CMD_FUNC(list)
1276 {
1277 }
1278
1279 /* Server side of TOPIC command. Sets topic for channel and/or returns
1280    current topic to client. */
1281
1282 SILC_SERVER_CMD_FUNC(topic)
1283 {
1284   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1285   SilcServer server = cmd->server;
1286   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1287   SilcChannelID *channel_id;
1288   SilcChannelEntry channel;
1289   SilcChannelClientEntry chl;
1290   SilcBuffer packet, idp;
1291   unsigned char *tmp;
1292   unsigned int argc, tmp_len;
1293
1294   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1295
1296   argc = silc_argument_get_arg_num(cmd->args);
1297
1298   /* Get Channel ID */
1299   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1300   if (!tmp) {
1301     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1302                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1303     goto out;
1304   }
1305   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1306
1307   /* Check whether the channel exists */
1308   channel = silc_idlist_find_channel_by_id(server->local_list, 
1309                                            channel_id, NULL);
1310   if (!channel) {
1311     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1312                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1313     goto out;
1314   }
1315
1316   if (argc > 1) {
1317     /* Get the topic */
1318     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1319     if (!tmp) {
1320       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1321                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1322       goto out;
1323     }
1324
1325     if (strlen(tmp) > 256) {
1326       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1327                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1328       goto out;
1329     }
1330
1331     /* See whether has rights to change topic */
1332     silc_list_start(channel->user_list);
1333     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1334       if (chl->client == client) {
1335         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1336           silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1337                                                 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1338           goto out;
1339         } else {
1340           break;
1341         }
1342       }
1343     }
1344
1345     /* Set the topic for channel */
1346     if (channel->topic)
1347       silc_free(channel->topic);
1348     channel->topic = strdup(tmp);
1349
1350     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1351
1352     /* Send notify about topic change to all clients on the channel */
1353     silc_server_send_notify_to_channel(server, channel, TRUE,
1354                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1355                                        idp->data, idp->len,
1356                                        channel->topic, strlen(channel->topic));
1357     silc_buffer_free(idp);
1358   }
1359
1360   /* Send the topic to client as reply packet */
1361   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1362   if (channel->topic)
1363     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
1364                                                   SILC_STATUS_OK, 0, 2, 
1365                                                   2, idp->data, idp->len,
1366                                                   3, channel->topic, 
1367                                                   strlen(channel->topic));
1368   else
1369     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
1370                                                   SILC_STATUS_OK, 0, 1, 
1371                                                   2, idp->data, idp->len);
1372   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1373                           0, packet->data, packet->len, FALSE);
1374
1375   silc_buffer_free(packet);
1376   silc_buffer_free(idp);
1377   silc_free(channel_id);
1378
1379  out:
1380   silc_server_command_free(cmd);
1381 }
1382
1383 /* Server side of INVITE command. Invites some client to join some channel. */
1384
1385 SILC_SERVER_CMD_FUNC(invite)
1386 {
1387   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1388   SilcServer server = cmd->server;
1389   SilcSocketConnection sock = cmd->sock, dest_sock;
1390   SilcClientEntry sender, dest;
1391   SilcClientID *dest_id;
1392   SilcChannelEntry channel;
1393   SilcChannelID *channel_id;
1394   SilcBuffer sidp;
1395   unsigned char *tmp;
1396   unsigned int len;
1397
1398   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1399
1400   /* Get destination ID */
1401   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1402   if (!tmp) {
1403     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1404                                           SILC_STATUS_ERR_NO_CLIENT_ID);
1405     goto out;
1406   }
1407   dest_id = silc_id_payload_parse_id(tmp, len);
1408
1409   /* Get Channel ID */
1410   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1411   if (!tmp) {
1412     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1413                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1414     goto out;
1415   }
1416   channel_id = silc_id_payload_parse_id(tmp, len);
1417
1418   /* Check whether the channel exists */
1419   channel = silc_idlist_find_channel_by_id(server->local_list, 
1420                                            channel_id, NULL);
1421   if (!channel) {
1422     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1423                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1424     goto out;
1425   }
1426
1427   /* Check whether the sender of this command is on the channel. */
1428   sender = (SilcClientEntry)sock->user_data;
1429   if (!silc_server_client_on_channel(sender, channel)) {
1430     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1431                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
1432     goto out;
1433   }
1434
1435   /* Check whether the channel is invite-only channel. If yes then the
1436      sender of this command must be at least channel operator. */
1437   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1438     SilcChannelClientEntry chl;
1439
1440     silc_list_start(channel->user_list);
1441     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1442       if (chl->client == sender) {
1443         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1444           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1445                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1446           goto out;
1447         }
1448         break;
1449       }
1450   }
1451
1452   /* Find the connection data for the destination. If it is local we will
1453      send it directly otherwise we will send it to router for routing. */
1454   dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1455   if (dest)
1456     dest_sock = (SilcSocketConnection)dest->connection;
1457   else
1458     dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1459
1460   /* Check whether the requested client is already on the channel. */
1461   /* XXX if we are normal server we don't know about global clients on
1462      the channel thus we must request it (USERS command), check from
1463      local cache as well. */
1464   if (silc_server_client_on_channel(dest, channel)) {
1465     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1466                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1467     goto out;
1468   }
1469
1470   sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1471
1472   /* Send notify to the client that is invited to the channel */
1473   silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1474                                SILC_NOTIFY_TYPE_INVITE, 2, 
1475                                sidp->data, sidp->len, tmp, len);
1476
1477   /* Send command reply */
1478   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1479                                         SILC_STATUS_OK);
1480
1481   silc_buffer_free(sidp);
1482
1483  out:
1484   silc_server_command_free(cmd);
1485 }
1486
1487 /* Quits connection to client. This gets called if client won't
1488    close the connection even when it has issued QUIT command. */
1489
1490 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1491 {
1492   SilcServer server = (SilcServer)context;
1493   SilcSocketConnection sock = server->sockets[fd];
1494
1495   /* Free all client specific data, such as client entry and entires
1496      on channels this client may be on. */
1497   silc_server_free_sock_user_data(server, sock);
1498
1499   /* Close the connection on our side */
1500   silc_server_close_connection(server, sock);
1501 }
1502
1503 /* Quits SILC session. This is the normal way to disconnect client. */
1504  
1505 SILC_SERVER_CMD_FUNC(quit)
1506 {
1507   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1508   SilcServer server = cmd->server;
1509   SilcSocketConnection sock = cmd->sock;
1510
1511   SILC_LOG_DEBUG(("Start"));
1512
1513   /* We quit the connection with little timeout */
1514   silc_task_register(server->timeout_queue, sock->sock,
1515                      silc_server_command_quit_cb, server,
1516                      0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1517
1518   silc_server_command_free(cmd);
1519 }
1520
1521 SILC_SERVER_CMD_FUNC(kill)
1522 {
1523 }
1524
1525 /* Server side of command INFO. This sends information about us to 
1526    the client. If client requested specific server we will send the 
1527    command to that server. */
1528
1529 SILC_SERVER_CMD_FUNC(info)
1530 {
1531   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1532   SilcServer server = cmd->server;
1533   SilcBuffer packet, idp;
1534   char info_string[256], *dest_server;
1535
1536   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1537
1538   /* Get server name */
1539   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1540   if (!dest_server) {
1541     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1542                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1543     goto out;
1544   }
1545
1546   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1547     /* Send our reply */
1548     memset(info_string, 0, sizeof(info_string));
1549     snprintf(info_string, sizeof(info_string), 
1550              "location: %s server: %s admin: %s <%s>",
1551              server->config->admin_info->location,
1552              server->config->admin_info->server_type,
1553              server->config->admin_info->admin_name,
1554              server->config->admin_info->admin_email);
1555
1556     idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1557
1558     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1559                                                   SILC_STATUS_OK, 0, 2,
1560                                                   2, idp->data, idp->len,
1561                                                   3, info_string, 
1562                                                   strlen(info_string));
1563     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
1564                             packet->data, packet->len, FALSE);
1565     
1566     silc_buffer_free(packet);
1567     silc_buffer_free(idp);
1568   } else {
1569     /* Send this command to the requested server */
1570
1571     if (server->server_type == SILC_SERVER && !server->standalone) {
1572
1573     }
1574
1575     if (server->server_type == SILC_ROUTER) {
1576
1577     }
1578   }
1579   
1580  out:
1581   silc_server_command_free(cmd);
1582 }
1583
1584 SILC_SERVER_CMD_FUNC(connect)
1585 {
1586 }
1587
1588 /* Server side of command PING. This just replies to the ping. */
1589
1590 SILC_SERVER_CMD_FUNC(ping)
1591 {
1592   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1593   SilcServer server = cmd->server;
1594   SilcServerID *id;
1595   unsigned int len;
1596   unsigned char *tmp;
1597
1598   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1599
1600   /* Get Server ID */
1601   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1602   if (!tmp) {
1603     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1604                                           SILC_STATUS_ERR_NO_SERVER_ID);
1605     goto out;
1606   }
1607   id = silc_id_str2id(tmp, SILC_ID_SERVER);
1608   if (!id)
1609     goto out;
1610
1611   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1612     /* Send our reply */
1613     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1614                                           SILC_STATUS_OK);
1615   } else {
1616     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1617                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
1618     goto out;
1619   }
1620
1621   silc_free(id);
1622
1623  out:
1624   silc_server_command_free(cmd);
1625 }
1626
1627 SILC_SERVER_CMD_FUNC(oper)
1628 {
1629 }
1630
1631 /* Assembles USERS command and executes it. This is called when client
1632    joins to a channel and we wan't to send USERS command reply to the 
1633    client. */
1634
1635 void silc_server_command_send_users(SilcServer server,
1636                                     SilcSocketConnection sock,
1637                                     SilcChannelEntry channel,
1638                                     int pending)
1639 {
1640   SilcServerCommandContext cmd;
1641   SilcBuffer buffer, idp;
1642   SilcPacketContext *packet = silc_packet_context_alloc();
1643
1644   /* Create USERS command packet and process it. */
1645   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1646   buffer = silc_command_payload_encode_va(SILC_COMMAND_USERS, 0, 1,
1647                                           1, idp->data, idp->len);
1648
1649   packet->buffer = silc_buffer_copy(buffer);
1650   packet->sock = sock;
1651   packet->type = SILC_PACKET_COMMAND;
1652
1653   cmd = silc_calloc(1, sizeof(*cmd));
1654   cmd->payload = silc_command_payload_parse(buffer);
1655   cmd->args = silc_command_get_args(cmd->payload);
1656   cmd->server = server;
1657   cmd->sock = sock;
1658   cmd->packet = silc_packet_context_dup(packet);
1659   cmd->pending = FALSE;
1660
1661   if (pending) {
1662     /* If this function was called from pending command then instead of
1663        processing the command now, register a pending command callback which
1664        will process it after we've received the automatic USERS command 
1665        reply. */
1666     silc_server_command_pending(server, SILC_COMMAND_USERS, 0,
1667                                 silc_server_command_users, (void *)cmd);
1668     cmd->pending = TRUE;
1669     silc_free(buffer);
1670     silc_free(idp);
1671     return;
1672   }
1673
1674   /* Process USERS command. */
1675   silc_server_command_users((void *)cmd);
1676  
1677   silc_free(buffer);
1678   silc_free(idp);
1679   silc_packet_context_free(packet);
1680 }
1681
1682 /* Internal routine to join channel. The channel sent to this function
1683    has been either created or resolved from ID lists. This joins the sent
1684    client to the channel. */
1685
1686 static void silc_server_command_join_channel(SilcServer server, 
1687                                              SilcServerCommandContext cmd,
1688                                              SilcChannelEntry channel,
1689                                              SilcClientID *client_id,
1690                                              int created,
1691                                              unsigned int umode)
1692 {
1693   SilcSocketConnection sock = cmd->sock;
1694   unsigned char *tmp;
1695   unsigned int tmp_len;
1696   unsigned char *passphrase = NULL, mode[4], tmp2[4];
1697   SilcClientEntry client;
1698   SilcChannelClientEntry chl;
1699   SilcBuffer reply, chidp, clidp, keyp;
1700   unsigned short ident = silc_command_get_ident(cmd->payload);
1701
1702   SILC_LOG_DEBUG(("Start"));
1703
1704   if (!channel)
1705     return;
1706
1707   /* Get passphrase */
1708   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1709   if (tmp) {
1710     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1711     memcpy(passphrase, tmp, tmp_len);
1712   }
1713   
1714   /*
1715    * Check channel modes
1716    */
1717
1718   /* Check invite list if channel is invite-only channel */
1719   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1720     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1721       /* Invite list is specified. Check whether client is invited in the
1722          list. If not, then check whether it has been invited otherwise. */
1723
1724     } else {
1725       /* XXX client must be invited to be able to join the channel */
1726     }
1727   }
1728
1729   /* Check ban list if set */
1730   if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1731
1732   }
1733
1734   /* Check the channel passphrase if set. */
1735   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1736     if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1737                               strlen(channel->mode_data.passphrase))) {
1738       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1739                                             SILC_STATUS_ERR_BAD_PASSWORD);
1740       goto out;
1741     }
1742   }
1743
1744   /* Check user count limit if set. */
1745   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1746     if (silc_list_count(channel->user_list) + 1 > 
1747         channel->mode_data.user_limit) {
1748       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1749                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
1750       goto out;
1751     }
1752   }
1753
1754   /*
1755    * Client is allowed to join to the channel. Make it happen.
1756    */
1757
1758   /* Get the client entry */
1759   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1760     client = (SilcClientEntry)sock->user_data;
1761   } else {
1762     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
1763                                            NULL);
1764     if (!client) {
1765       /* XXX actually this is useless since router finds always cell's
1766          local clients from its local lists. */
1767       client = silc_idlist_find_client_by_id(server->global_list, client_id, 
1768                                              NULL);
1769       if (!client)
1770         goto out;
1771     }
1772   }
1773
1774   /* Check whether the client already is on the channel */
1775   if (silc_server_client_on_channel(client, channel)) {
1776     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1777                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
1778     goto out;
1779   }
1780
1781   /* Generate new channel key as protocol dictates */
1782   if (!created || !channel->channel_key)
1783     silc_server_create_channel_key(server, channel, 0);
1784
1785   /* Send the channel key. This is broadcasted to the channel but is not
1786      sent to the client who is joining to the channel. */
1787   silc_server_send_channel_key(server, channel, 
1788                                server->server_type == SILC_ROUTER ? 
1789                                FALSE : server->standalone);
1790
1791   /* Join the client to the channel by adding it to channel's user list.
1792      Add also the channel to client entry's channels list for fast cross-
1793      referencing. */
1794   chl = silc_calloc(1, sizeof(*chl));
1795   chl->mode = umode;
1796   chl->client = client;
1797   chl->channel = channel;
1798   silc_list_add(channel->user_list, chl);
1799   silc_list_add(client->channels, chl);
1800
1801   /* Encode Client ID Payload of the original client who wants to join */
1802   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1803
1804   /* Encode command reply packet */
1805   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1806   SILC_PUT32_MSB(channel->mode, mode);
1807   SILC_PUT32_MSB(created, tmp2);
1808   tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1809   keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
1810                                          SILC_ID_CHANNEL_LEN,
1811                                          channel->channel_key->cipher->name,
1812                                          channel->key_len / 8, channel->key);
1813   silc_free(tmp);
1814   if (!channel->topic) {
1815     reply = 
1816       silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1817                                            SILC_STATUS_OK, ident, 5,
1818                                            2, channel->channel_name,
1819                                            strlen(channel->channel_name),
1820                                            3, chidp->data, chidp->len,
1821                                            4, mode, 4,
1822                                            5, tmp2, 4,
1823                                            6, keyp->data, keyp->len);
1824   } else {
1825     reply = 
1826       silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1827                                            SILC_STATUS_OK, ident, 6, 
1828                                            2, channel->channel_name, 
1829                                            strlen(channel->channel_name),
1830                                            3, chidp->data, chidp->len,
1831                                            4, mode, 4,
1832                                            5, tmp2, 4,
1833                                            6, keyp->data, keyp->len,
1834                                            8, channel->topic, 
1835                                            strlen(channel->topic));
1836   }
1837
1838   /* Send command reply */
1839   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
1840                           reply->data, reply->len, FALSE);
1841
1842   if (!cmd->pending) {
1843     /* Send JOIN notify to locally connected clients on the channel */
1844     silc_server_send_notify_to_channel(server, channel, FALSE,
1845                                        SILC_NOTIFY_TYPE_JOIN, 1,
1846                                        clidp->data, clidp->len);
1847
1848     /* Send NEW_CHANNEL_USER packet to our primary router */
1849     if (!server->standalone)
1850       silc_server_send_new_channel_user(server, server->router->connection,
1851                                         server->server_type == SILC_SERVER ?
1852                                         FALSE : TRUE,
1853                                         channel->id, SILC_ID_CHANNEL_LEN,
1854                                         client->id, SILC_ID_CLIENT_LEN);
1855   }
1856
1857   /* Send USERS command reply to the joined channel so the user sees who
1858      is currently on the channel. */
1859   silc_server_command_send_users(server, sock, channel, cmd->pending);
1860
1861   silc_buffer_free(reply);
1862   silc_buffer_free(clidp);
1863   silc_buffer_free(chidp);
1864   silc_buffer_free(keyp);
1865
1866  out:
1867   if (passphrase)
1868     silc_free(passphrase);
1869 }
1870
1871 /* Server side of command JOIN. Joins client into requested channel. If 
1872    the channel does not exist it will be created. */
1873
1874 SILC_SERVER_CMD_FUNC(join)
1875 {
1876   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1877   SilcServer server = cmd->server;
1878   int tmp_len;
1879   char *tmp, *channel_name = NULL, *cipher = NULL;
1880   SilcChannelEntry channel;
1881   unsigned int umode = 0;
1882   int created = FALSE;
1883   SilcClientID *client_id;
1884
1885   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1886
1887   /* Get channel name */
1888   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1889   if (!tmp) {
1890     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1891                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1892     goto out;
1893   }
1894   channel_name = tmp;
1895
1896   if (silc_server_command_bad_chars(channel_name) == TRUE) {
1897     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1898                                           SILC_STATUS_ERR_BAD_CHANNEL);
1899     silc_free(channel_name);
1900     goto out;
1901   }
1902
1903   /* Get Client ID of the client who is joining to the channel */
1904   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1905   if (!tmp) {
1906     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1907                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1908     goto out;
1909   }
1910   client_id = silc_id_payload_parse_id(tmp, tmp_len);
1911
1912   /* Get cipher name */
1913   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1914
1915   /* See if the channel exists */
1916   channel = silc_idlist_find_channel_by_name(server->local_list, 
1917                                              channel_name, NULL);
1918
1919   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1920     /* If this is coming from client the Client ID in the command packet must
1921        be same as the client's ID. */
1922     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1923       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1924       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1925         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1926                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1927         goto out;
1928       }
1929     }
1930
1931     if (!channel) {
1932       /* Channel not found */
1933
1934       /* If we are standalone server we don't have a router, we just create 
1935          the channel by ourselves. */
1936       if (server->standalone) {
1937         channel = silc_server_create_new_channel(server, server->id, cipher, 
1938                                                  channel_name);
1939         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1940         created = TRUE;
1941
1942       } else {
1943
1944         /* The channel does not exist on our server. If we are normal server 
1945            we will send JOIN command to our router which will handle the
1946            joining procedure (either creates the channel if it doesn't exist 
1947            or joins the client to it). */
1948         if (server->server_type == SILC_SERVER) {
1949           SilcBuffer tmpbuf;
1950           unsigned short old_ident;
1951           
1952           old_ident = silc_command_get_ident(cmd->payload);
1953           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1954           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1955           
1956           /* Send JOIN command to our router */
1957           silc_server_packet_send(server, (SilcSocketConnection)
1958                                   server->router->connection,
1959                                   SILC_PACKET_COMMAND, cmd->packet->flags,
1960                                   tmpbuf->data, tmpbuf->len, TRUE);
1961           
1962           /* Reprocess this packet after received reply from router */
1963           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
1964                                       silc_command_get_ident(cmd->payload),
1965                                       silc_server_command_join, context);
1966           cmd->pending = TRUE;
1967           return;
1968         }
1969         
1970         /* We are router and the channel does not seem exist so we will check
1971            our global list as well for the channel. */
1972         channel = silc_idlist_find_channel_by_name(server->global_list, 
1973                                                    channel_name, NULL);
1974         if (!channel) {
1975           /* Channel really does not exist, create it */
1976           channel = silc_server_create_new_channel(server, server->id, cipher, 
1977                                                    channel_name);
1978           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1979           created = TRUE;
1980         }
1981       }
1982     }
1983   } else {
1984     if (!channel) {
1985       /* Channel not found */
1986
1987       /* If the command came from router and/or we are normal server then
1988          something went wrong with the joining as the channel was not found.
1989          We can't do anything else but ignore this. */
1990       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
1991           server->server_type == SILC_SERVER)
1992         goto out;
1993       
1994       /* We are router and the channel does not seem exist so we will check
1995          our global list as well for the channel. */
1996       channel = silc_idlist_find_channel_by_name(server->global_list, 
1997                                                  channel_name, NULL);
1998       if (!channel) {
1999         /* Channel really does not exist, create it */
2000         channel = silc_server_create_new_channel(server, server->id, cipher, 
2001                                                  channel_name);
2002         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2003         created = TRUE;
2004       }
2005     }
2006   }
2007
2008   /* If the channel does not have global users and is also empty it means the
2009      channel was created globally (by our router) and the client will be the
2010      channel founder and operator. */
2011   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2012     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2013     created = TRUE;             /* Created globally by our router */
2014   }
2015
2016   /* Join to the channel */
2017   silc_server_command_join_channel(server, cmd, channel, client_id,
2018                                    created, umode);
2019
2020   silc_free(client_id);
2021
2022  out:
2023   silc_server_command_free(cmd);
2024 }
2025
2026 /* Server side of command MOTD. Sends server's current "message of the
2027    day" to the client. */
2028
2029 SILC_SERVER_CMD_FUNC(motd)
2030 {
2031   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2032   SilcServer server = cmd->server;
2033   char *motd;
2034   int motd_len;
2035   
2036   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2037
2038   /* XXX show currently only our motd */
2039
2040   if (server->config && server->config->motd && 
2041       server->config->motd->motd_file) {
2042
2043     /* Send motd */
2044     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2045     if (!motd)
2046       goto out;
2047
2048     motd[motd_len] = 0;
2049     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2050                                          SILC_STATUS_OK,
2051                                          2, motd, motd_len);
2052     goto out;
2053   } else {
2054     /* No motd */
2055     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2056                                           SILC_STATUS_OK);
2057   }
2058
2059  out:
2060   silc_server_command_free(cmd);
2061 }
2062
2063 SILC_SERVER_CMD_FUNC(umode)
2064 {
2065 }
2066
2067 /* Checks that client has rights to add or remove channel modes. If any
2068    of the checks fails FALSE is returned. */
2069
2070 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2071                                    SilcChannelClientEntry client,
2072                                    unsigned int mode)
2073 {
2074   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2075   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2076
2077   /* Check whether has rights to change anything */
2078   if (!is_op && !is_fo)
2079     return FALSE;
2080
2081   /* Check whether has rights to change everything */
2082   if (is_op && is_fo)
2083     return TRUE;
2084
2085   /* We know that client is channel operator, check that they are not
2086      changing anything that requires channel founder rights. Rest of the
2087      modes are available automatically for channel operator. */
2088
2089   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2090     if (is_op && !is_fo)
2091       return FALSE;
2092   } else {
2093     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2094       if (is_op && !is_fo)
2095         return FALSE;
2096     }
2097   }
2098   
2099   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2100     if (is_op && !is_fo)
2101       return FALSE;
2102   } else {
2103     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2104       if (is_op && !is_fo)
2105         return FALSE;
2106     }
2107   }
2108
2109   if (mode & SILC_CHANNEL_MODE_CIPHER) {
2110     if (is_op && !is_fo)
2111       return FALSE;
2112   } else {
2113     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2114       if (is_op && !is_fo)
2115         return FALSE;
2116     }
2117   }
2118   
2119   return TRUE;
2120 }
2121
2122 /* Server side command of CMODE. Changes channel mode */
2123
2124 SILC_SERVER_CMD_FUNC(cmode)
2125 {
2126   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2127   SilcServer server = cmd->server;
2128   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2129   SilcChannelID *channel_id;
2130   SilcChannelEntry channel;
2131   SilcChannelClientEntry chl;
2132   SilcBuffer packet, cidp;
2133   unsigned char *tmp, *tmp_id, *tmp_mask;
2134   unsigned int argc, mode_mask, tmp_len, tmp_len2;
2135
2136   SILC_LOG_DEBUG(("Start"));
2137
2138   argc = silc_argument_get_arg_num(cmd->args);
2139   if (argc < 2) {
2140     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2141                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2142     goto out;
2143   }
2144   if (argc > 8) {
2145     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2146                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2147     goto out;
2148   }
2149
2150   /* Get Channel ID */
2151   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2152   if (!tmp_id) {
2153     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2154                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2155     goto out;
2156   }
2157   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2158
2159   /* Get the channel mode mask */
2160   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2161   if (!tmp_mask) {
2162     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2163                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2164     goto out;
2165   }
2166   SILC_GET32_MSB(mode_mask, tmp_mask);
2167
2168   /* Get channel entry */
2169   channel = silc_idlist_find_channel_by_id(server->local_list, 
2170                                            channel_id, NULL);
2171   if (!channel) {
2172     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2173                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2174     goto out;
2175   }
2176
2177   /* Check whether this client is on the channel */
2178   if (!silc_server_client_on_channel(client, channel)) {
2179     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2180                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2181     goto out;
2182   }
2183
2184   /* Get entry to the channel user list */
2185   silc_list_start(channel->user_list);
2186   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2187     if (chl->client == client)
2188       break;
2189
2190   /* Check that client has rights to change any requested channel modes */
2191   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2192     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2193                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2194     goto out;
2195   }
2196
2197   /*
2198    * Check the modes. Modes that requires nothing special operation are
2199    * not checked here.
2200    */
2201
2202   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2203     /* Channel uses private keys to protect traffic. Client(s) has set the
2204        key locally they want to use, server does not know that key. */
2205     /* Nothing interesting to do here now */
2206   } else {
2207     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2208       /* The mode is removed and we need to generate and distribute
2209          new channel key. Clients are not using private channel keys
2210          anymore after this. */
2211
2212       /* XXX Duplicated code, make own function for this!! LEAVE uses this
2213          as well */
2214
2215       /* Re-generate channel key */
2216       silc_server_create_channel_key(server, channel, 0);
2217       
2218       /* Encode channel key payload to be distributed on the channel */
2219       packet = 
2220         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2221                                         strlen(channel->channel_key->
2222                                                cipher->name),
2223                                         channel->channel_key->cipher->name,
2224                                         channel->key_len / 8, channel->key);
2225       
2226       /* If we are normal server then we will send it to our router.  If we
2227          are router we will send it to all local servers that has clients on
2228          the channel */
2229       if (server->server_type == SILC_SERVER) {
2230         if (!server->standalone)
2231           silc_server_packet_send(server, 
2232                                   cmd->server->router->connection,
2233                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2234                                   packet->len, TRUE);
2235       } else {
2236         
2237       }
2238       
2239       /* Send to locally connected clients on the channel */
2240       silc_server_packet_send_local_channel(server, channel, 
2241                                             SILC_PACKET_CHANNEL_KEY, 0,
2242                                             packet->data, packet->len, FALSE);
2243       silc_buffer_free(packet);
2244     }
2245   }
2246   
2247   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2248     /* User limit is set on channel */
2249     unsigned int user_limit;
2250       
2251     /* Get user limit */
2252     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2253     if (!tmp) {
2254       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2255         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2256                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2257         goto out;
2258       }
2259     } else {
2260       SILC_GET32_MSB(user_limit, tmp);
2261       channel->mode_data.user_limit = user_limit;
2262     }
2263   } else {
2264     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2265       /* User limit mode is unset. Remove user limit */
2266       channel->mode_data.user_limit = 0;
2267   }
2268
2269   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2270     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2271       /* Passphrase has been set to channel */
2272       
2273       /* Get the passphrase */
2274       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2275       if (!tmp) {
2276         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2277                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2278         goto out;
2279       }
2280
2281       /* Save the passphrase */
2282       channel->mode_data.passphrase = strdup(tmp);
2283     }
2284   } else {
2285     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2286       /* Passphrase mode is unset. remove the passphrase */
2287       if (channel->mode_data.passphrase) {
2288         silc_free(channel->mode_data.passphrase);
2289         channel->mode_data.passphrase = NULL;
2290       }
2291     }
2292   }
2293
2294   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2295     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2296       /* Ban list is specified for channel */
2297
2298       /* Get ban list */
2299       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2300       if (!tmp) {
2301         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2302                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2303         goto out;
2304       }
2305
2306       /* XXX check that channel founder is not banned */
2307
2308       /* Save the ban list */
2309       channel->mode_data.ban_list = strdup(tmp);
2310     }
2311   } else {
2312     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2313       /* Ban mode is unset. Remove the entire ban list */
2314       if (channel->mode_data.ban_list) {
2315         silc_free(channel->mode_data.ban_list);
2316         channel->mode_data.ban_list = NULL;
2317       }
2318     }
2319   }
2320
2321   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2322     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2323       /* Invite list is specified for channel */
2324
2325       /* Get invite list */
2326       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2327       if (!tmp) {
2328         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2329                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2330         goto out;
2331       }
2332
2333       /* Save the invite linst */
2334       channel->mode_data.invite_list = strdup(tmp);
2335     }
2336   } else {
2337     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2338       /* Invite list mode is unset. Remove the entire invite list */
2339       if (channel->mode_data.invite_list) {
2340         silc_free(channel->mode_data.invite_list);
2341         channel->mode_data.invite_list = NULL;
2342       }
2343     }
2344   }
2345
2346   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2347     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2348       /* Cipher to use protect the traffic */
2349       unsigned int key_len = 128;
2350       char *cp;
2351
2352       /* Get cipher */
2353       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2354       if (!tmp) {
2355         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2356                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2357         goto out;
2358       }
2359
2360       cp = strchr(tmp, ':');
2361       if (cp) {
2362         key_len = atoi(cp);
2363         *cp = '\0';
2364       }
2365
2366       /* XXX Duplicated code, make own function for this!! */
2367     
2368       /* Delete old cipher and allocate the new one */
2369       silc_cipher_free(channel->channel_key);
2370       silc_cipher_alloc(tmp, &channel->channel_key);
2371
2372       key_len /= 8;
2373       if (key_len > 32)
2374         key_len = 32;
2375
2376       /* Re-generate channel key */
2377       silc_server_create_channel_key(server, channel, key_len);
2378     
2379       /* Encode channel key payload to be distributed on the channel */
2380       packet = 
2381         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2382                                         strlen(channel->channel_key->
2383                                                cipher->name),
2384                                         channel->channel_key->cipher->name,
2385                                         channel->key_len / 8, channel->key);
2386     
2387       /* If we are normal server then we will send it to our router.  If we
2388          are router we will send it to all local servers that has clients on
2389          the channel */
2390       if (server->server_type == SILC_SERVER) {
2391         if (!server->standalone)
2392           silc_server_packet_send(server, 
2393                                   cmd->server->router->connection,
2394                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2395                                   packet->len, TRUE);
2396       } else {
2397         
2398       }
2399     
2400       /* Send to locally connected clients on the channel */
2401       silc_server_packet_send_local_channel(server, channel, 
2402                                             SILC_PACKET_CHANNEL_KEY, 0,
2403                                           packet->data, packet->len, FALSE);
2404       silc_buffer_free(packet);
2405     }
2406   } else {
2407     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2408       /* Cipher mode is unset. Remove the cipher and revert back to 
2409          default cipher */
2410
2411       if (channel->mode_data.cipher) {
2412         silc_free(channel->mode_data.cipher);
2413         channel->mode_data.cipher = NULL;
2414         channel->mode_data.key_len = 0;
2415       }
2416
2417       /* Generate new cipher and key for the channel */
2418
2419       /* XXX Duplicated code, make own function for this!! */
2420
2421       /* Delete old cipher and allocate default one */
2422       silc_cipher_free(channel->channel_key);
2423       if (!channel->cipher)
2424         silc_cipher_alloc("twofish", &channel->channel_key);
2425       else
2426         silc_cipher_alloc(channel->cipher, &channel->channel_key);
2427
2428       /* Re-generate channel key */
2429       silc_server_create_channel_key(server, channel, 0);
2430       
2431       /* Encode channel key payload to be distributed on the channel */
2432       packet = 
2433         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2434                                         strlen(channel->channel_key->
2435                                                cipher->name),
2436                                         channel->channel_key->cipher->name,
2437                                         channel->key_len / 8, channel->key);
2438       
2439       /* If we are normal server then we will send it to our router.  If we
2440          are router we will send it to all local servers that has clients on
2441          the channel */
2442       if (server->server_type == SILC_SERVER) {
2443         if (!server->standalone)
2444           silc_server_packet_send(server, 
2445                                   cmd->server->router->connection,
2446                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2447                                   packet->len, TRUE);
2448       } else {
2449         
2450       }
2451       
2452       /* Send to locally connected clients on the channel */
2453       silc_server_packet_send_local_channel(server, channel, 
2454                                             SILC_PACKET_CHANNEL_KEY, 0,
2455                                             packet->data, packet->len, FALSE);
2456       silc_buffer_free(packet);
2457     }
2458   }
2459
2460   /* Finally, set the mode */
2461   channel->mode = mode_mask;
2462
2463   /* Send CMODE_CHANGE notify */
2464   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2465   silc_server_send_notify_to_channel(server, channel, TRUE,
2466                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2467                                      cidp->data, cidp->len, 
2468                                      tmp_mask, tmp_len);
2469   silc_free(cidp);
2470
2471   /* Send command reply to sender */
2472   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2473                                                 SILC_STATUS_OK, 0, 1,
2474                                                 2, tmp_mask, 4);
2475   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2476                           packet->data, packet->len, FALSE);
2477     
2478   silc_buffer_free(packet);
2479   silc_free(channel_id);
2480
2481  out:
2482   silc_server_command_free(cmd);
2483 }
2484
2485 /* Server side of CUMODE command. Changes client's mode on a channel. */
2486
2487 SILC_SERVER_CMD_FUNC(cumode)
2488 {
2489   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2490   SilcServer server = cmd->server;
2491   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2492   SilcChannelID *channel_id;
2493   SilcClientID *client_id;
2494   SilcChannelEntry channel;
2495   SilcClientEntry target_client;
2496   SilcChannelClientEntry chl;
2497   SilcBuffer packet, idp;
2498   unsigned char *tmp_id, *tmp_mask;
2499   unsigned int target_mask, sender_mask, tmp_len;
2500   int notify = FALSE;
2501
2502   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2503
2504   /* Get Channel ID */
2505   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2506   if (!tmp_id) {
2507     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2508                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2509     goto out;
2510   }
2511   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2512
2513   /* Get channel entry */
2514   channel = silc_idlist_find_channel_by_id(server->local_list, 
2515                                            channel_id, NULL);
2516   if (!channel) {
2517     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2518                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2519     goto out;
2520   }
2521
2522   /* Check whether sender is on the channel */
2523   if (!silc_server_client_on_channel(client, channel)) {
2524     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2525                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2526     goto out;
2527   }
2528
2529   /* Check that client has rights to change other's rights */
2530   silc_list_start(channel->user_list);
2531   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2532     if (chl->client == client) {
2533       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2534           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2535         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2536                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2537         goto out;
2538       }
2539
2540       sender_mask = chl->mode;
2541       break;
2542     }
2543   }
2544   
2545   /* Get the target client's channel mode mask */
2546   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2547   if (!tmp_mask) {
2548     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2549                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2550     goto out;
2551   }
2552   SILC_GET32_MSB(target_mask, tmp_mask);
2553
2554   /* Get target Client ID */
2555   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2556   if (!tmp_id) {
2557     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2558                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2559     goto out;
2560   }
2561   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2562
2563   /* Get target client's entry */
2564   target_client = silc_idlist_find_client_by_id(server->local_list, 
2565                                                 client_id, NULL);
2566   if (!target_client) {
2567     /* XXX If target client is not one of mine send to primary route */
2568   }
2569
2570   /* Check whether target client is on the channel */
2571   if (!silc_server_client_on_channel(target_client, channel)) {
2572     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2573                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2574     goto out;
2575   }
2576
2577   /* Get entry to the channel user list */
2578   silc_list_start(channel->user_list);
2579   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2580     if (chl->client == target_client)
2581       break;
2582
2583   /* 
2584    * Change the mode 
2585    */
2586
2587   /* If the target client is founder, no one else can change their mode
2588      but themselves. */
2589   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2590     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2591                                           SILC_STATUS_ERR_NOT_YOU);
2592     goto out;
2593   }
2594
2595   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2596     /* Cannot promote anyone to channel founder */
2597     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2598                                           SILC_STATUS_ERR_NOT_YOU);
2599     goto out;
2600   } else {
2601     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2602       if (target_client == client) {
2603         /* Remove channel founder rights from itself */
2604         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2605         notify = TRUE;
2606       } else {
2607         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2608                                               SILC_STATUS_ERR_NOT_YOU);
2609         goto out;
2610       }
2611     }
2612   }
2613
2614   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2615     /* Promote to operator */
2616     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2617       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2618       notify = TRUE;
2619     }
2620   } else {
2621     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2622       /* Demote to normal user */
2623       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2624       notify = TRUE;
2625     }
2626   }
2627
2628   /* Send notify to channel, notify only if mode was actually changed. */
2629   if (notify) {
2630     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2631     silc_server_send_notify_to_channel(server, channel, TRUE,
2632                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2633                                        idp->data, idp->len,
2634                                        tmp_mask, 4, tmp_id, tmp_len);
2635     silc_buffer_free(idp);
2636   }
2637
2638   /* Send command reply to sender */
2639   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2640                                                 SILC_STATUS_OK, 0, 2,
2641                                                 2, tmp_mask, 4,
2642                                                 3, tmp_id, tmp_len);
2643   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2644                           packet->data, packet->len, FALSE);
2645     
2646   silc_buffer_free(packet);
2647   silc_free(channel_id);
2648   silc_free(client_id);
2649
2650  out:
2651   silc_server_command_free(cmd);
2652 }
2653
2654 /* Server side of KICK command. Kicks client out of channel. */
2655
2656 SILC_SERVER_CMD_FUNC(kick)
2657 {
2658 }
2659
2660 SILC_SERVER_CMD_FUNC(restart)
2661 {
2662 }
2663  
2664 SILC_SERVER_CMD_FUNC(close)
2665 {
2666 }
2667  
2668 SILC_SERVER_CMD_FUNC(die)
2669 {
2670 }
2671  
2672 SILC_SERVER_CMD_FUNC(silcoper)
2673 {
2674 }
2675
2676 /* Server side command of LEAVE. Removes client from a channel. */
2677
2678 SILC_SERVER_CMD_FUNC(leave)
2679 {
2680   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2681   SilcServer server = cmd->server;
2682   SilcSocketConnection sock = cmd->sock;
2683   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2684   SilcChannelID *id;
2685   SilcChannelEntry channel;
2686   SilcBuffer packet;
2687   unsigned int i, len;
2688   unsigned char *tmp;
2689
2690   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2691
2692   /* Get Channel ID */
2693   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2694   if (!tmp) {
2695     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2696                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2697     goto out;
2698   }
2699   id = silc_id_payload_parse_id(tmp, len);
2700
2701   /* Get channel entry */
2702   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2703   if (!channel) {
2704     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2705                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2706     goto out;
2707   }
2708
2709   /* Check whether this client is on the channel */
2710   if (!silc_server_client_on_channel(id_entry, channel)) {
2711     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2712                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2713     goto out;
2714   }
2715
2716   /* Notify routers that they should remove this client from their list
2717      of clients on the channel. */
2718   if (!server->standalone)
2719     silc_server_send_remove_channel_user(server, 
2720                                          server->router->connection,
2721                                          server->server_type == SILC_ROUTER ?
2722                                          TRUE : FALSE, id_entry->id, id);
2723
2724   /* Remove client from channel */
2725   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2726                                           TRUE);
2727   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2728                                         SILC_STATUS_OK);
2729
2730   /* If the channel does not exist anymore we won't send anything */
2731   if (!i)
2732     goto out;
2733
2734   /* Re-generate channel key */
2735   silc_server_create_channel_key(server, channel, 0);
2736
2737   /* Encode channel key payload to be distributed on the channel */
2738   packet = 
2739     silc_channel_key_payload_encode(len, tmp,
2740                                     strlen(channel->channel_key->cipher->name),
2741                                     channel->channel_key->cipher->name,
2742                                     channel->key_len / 8, channel->key);
2743
2744   /* If we are normal server then we will send it to our router.  If we
2745      are router we will send it to all local servers that has clients on
2746      the channel */
2747   if (server->server_type == SILC_SERVER) {
2748     if (!server->standalone)
2749       silc_server_packet_send(server, 
2750                               cmd->server->router->connection,
2751                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2752                               packet->len, TRUE);
2753   } else {
2754
2755   }
2756
2757   /* Send to locally connected clients on the channel */
2758   silc_server_packet_send_local_channel(server, channel, 
2759                                         SILC_PACKET_CHANNEL_KEY, 0,
2760                                         packet->data, packet->len, FALSE);
2761
2762   silc_buffer_free(packet);
2763   silc_free(id);
2764
2765  out:
2766   silc_server_command_free(cmd);
2767 }
2768
2769 /* Server side of command USERS. Resolves clients and their USERS currently
2770    joined on the requested channel. The list of Client ID's and their modes
2771    on the channel is sent back. */
2772
2773 SILC_SERVER_CMD_FUNC(users)
2774 {
2775   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2776   SilcServer server = cmd->server;
2777   SilcChannelEntry channel;
2778   SilcChannelClientEntry chl;
2779   SilcChannelID *id;
2780   SilcBuffer packet;
2781   unsigned char *channel_id;
2782   unsigned int channel_id_len;
2783   SilcBuffer client_id_list;
2784   SilcBuffer client_mode_list;
2785   SilcBuffer idp;
2786   unsigned char lc[4];
2787   unsigned int list_count = 0;
2788   unsigned short ident = silc_command_get_ident(cmd->payload);
2789
2790   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
2791
2792   /* Get Channel ID */
2793   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2794   if (!channel_id) {
2795     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2796                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2797     goto out;
2798   }
2799   id = silc_id_payload_parse_id(channel_id, channel_id_len);
2800
2801   /* If we are server and we don't know about this channel we will send
2802      the command to our router. If we know about the channel then we also
2803      have the list of users already. */
2804   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2805   if (!channel) {
2806     if (server->server_type == SILC_SERVER && !server->standalone &&
2807         !cmd->pending) {
2808       SilcBuffer tmpbuf;
2809       
2810       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2811       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2812       
2813       /* Send USERS command */
2814       silc_server_packet_send(server, server->router->connection,
2815                               SILC_PACKET_COMMAND, cmd->packet->flags,
2816                               tmpbuf->data, tmpbuf->len, TRUE);
2817       
2818       /* Reprocess this packet after received reply */
2819       silc_server_command_pending(server, SILC_COMMAND_USERS, 
2820                                   silc_command_get_ident(cmd->payload),
2821                                   silc_server_command_users, (void *)cmd);
2822       cmd->pending = TRUE;
2823       silc_command_set_ident(cmd->payload, ident);
2824       
2825       silc_buffer_free(tmpbuf);
2826       silc_free(id);
2827       return;
2828     }
2829
2830     /* We are router and we will check the global list as well. */
2831     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2832     if (!channel) {
2833       /* Channel really does not exist */
2834       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2835                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2836       goto out;
2837     }
2838   }
2839
2840   /* Assemble the lists now */
2841
2842   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
2843                                      silc_list_count(channel->user_list));
2844   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2845   client_mode_list = 
2846     silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2847   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2848
2849   silc_list_start(channel->user_list);
2850   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2851     /* Client ID */
2852     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2853     silc_buffer_put(client_id_list, idp->data, idp->len);
2854     silc_buffer_pull(client_id_list, idp->len);
2855     silc_buffer_free(idp);
2856
2857     /* Client's mode on channel */
2858     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2859     silc_buffer_pull(client_mode_list, 4);
2860
2861     list_count++;
2862   }
2863   silc_buffer_push(client_id_list, 
2864                    client_id_list->data - client_id_list->head);
2865   silc_buffer_push(client_mode_list, 
2866                    client_mode_list->data - client_mode_list->head);
2867
2868   /* List count */
2869   SILC_PUT32_MSB(list_count, lc);
2870
2871   /* Send reply */
2872   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2873                                                 SILC_STATUS_OK, 0, 4,
2874                                                 2, channel_id, channel_id_len,
2875                                                 3, lc, 4,
2876                                                 4, client_id_list->data,
2877                                                 client_id_list->len,
2878                                                 5, client_mode_list->data,
2879                                                 client_mode_list->len);
2880   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2881                           packet->data, packet->len, FALSE);
2882     
2883   silc_buffer_free(packet);
2884   silc_buffer_free(client_id_list);
2885   silc_buffer_free(client_mode_list);
2886   silc_free(id);
2887
2888  out:
2889   silc_server_command_free(cmd);
2890 }