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