Do not send send_remove_id if standalone server.
[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   if (!client_id)
1918     goto out;
1919
1920   /* Get cipher name */
1921   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1922
1923   /* See if the channel exists */
1924   channel = silc_idlist_find_channel_by_name(server->local_list, 
1925                                              channel_name, NULL);
1926
1927   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1928     /* If this is coming from client the Client ID in the command packet must
1929        be same as the client's ID. */
1930     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1931       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1932       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1933         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1934                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1935         goto out;
1936       }
1937     }
1938
1939     if (!channel) {
1940       /* Channel not found */
1941
1942       /* If we are standalone server we don't have a router, we just create 
1943          the channel by ourselves. */
1944       if (server->standalone) {
1945         channel = silc_server_create_new_channel(server, server->id, cipher, 
1946                                                  channel_name);
1947         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1948         created = TRUE;
1949
1950       } else {
1951
1952         /* The channel does not exist on our server. If we are normal server 
1953            we will send JOIN command to our router which will handle the
1954            joining procedure (either creates the channel if it doesn't exist 
1955            or joins the client to it). */
1956         if (server->server_type == SILC_SERVER) {
1957           SilcBuffer tmpbuf;
1958           unsigned short old_ident;
1959           
1960           old_ident = silc_command_get_ident(cmd->payload);
1961           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1962           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1963           
1964           /* Send JOIN command to our router */
1965           silc_server_packet_send(server, (SilcSocketConnection)
1966                                   server->router->connection,
1967                                   SILC_PACKET_COMMAND, cmd->packet->flags,
1968                                   tmpbuf->data, tmpbuf->len, TRUE);
1969           
1970           /* Reprocess this packet after received reply from router */
1971           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
1972                                       silc_command_get_ident(cmd->payload),
1973                                       silc_server_command_join, context);
1974           cmd->pending = TRUE;
1975           return;
1976         }
1977         
1978         /* We are router and the channel does not seem exist so we will check
1979            our global list as well for the channel. */
1980         channel = silc_idlist_find_channel_by_name(server->global_list, 
1981                                                    channel_name, NULL);
1982         if (!channel) {
1983           /* Channel really does not exist, create it */
1984           channel = silc_server_create_new_channel(server, server->id, cipher, 
1985                                                    channel_name);
1986           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1987           created = TRUE;
1988         }
1989       }
1990     }
1991   } else {
1992     if (!channel) {
1993       /* Channel not found */
1994
1995       /* If the command came from router and/or we are normal server then
1996          something went wrong with the joining as the channel was not found.
1997          We can't do anything else but ignore this. */
1998       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
1999           server->server_type == SILC_SERVER)
2000         goto out;
2001       
2002       /* We are router and the channel does not seem exist so we will check
2003          our global list as well for the channel. */
2004       channel = silc_idlist_find_channel_by_name(server->global_list, 
2005                                                  channel_name, NULL);
2006       if (!channel) {
2007         /* Channel really does not exist, create it */
2008         channel = silc_server_create_new_channel(server, server->id, cipher, 
2009                                                  channel_name);
2010         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2011         created = TRUE;
2012       }
2013     }
2014   }
2015
2016   /* If the channel does not have global users and is also empty it means the
2017      channel was created globally (by our router) and the client will be the
2018      channel founder and operator. */
2019   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2020     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2021     created = TRUE;             /* Created globally by our router */
2022   }
2023
2024   /* Join to the channel */
2025   silc_server_command_join_channel(server, cmd, channel, client_id,
2026                                    created, umode);
2027
2028   silc_free(client_id);
2029
2030  out:
2031   silc_server_command_free(cmd);
2032 }
2033
2034 /* Server side of command MOTD. Sends server's current "message of the
2035    day" to the client. */
2036
2037 SILC_SERVER_CMD_FUNC(motd)
2038 {
2039   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2040   SilcServer server = cmd->server;
2041   char *motd;
2042   int motd_len;
2043   
2044   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2045
2046   /* XXX show currently only our motd */
2047
2048   if (server->config && server->config->motd && 
2049       server->config->motd->motd_file) {
2050
2051     /* Send motd */
2052     motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2053     if (!motd)
2054       goto out;
2055
2056     motd[motd_len] = 0;
2057     silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2058                                          SILC_STATUS_OK,
2059                                          2, motd, motd_len);
2060     goto out;
2061   } else {
2062     /* No motd */
2063     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2064                                           SILC_STATUS_OK);
2065   }
2066
2067  out:
2068   silc_server_command_free(cmd);
2069 }
2070
2071 SILC_SERVER_CMD_FUNC(umode)
2072 {
2073 }
2074
2075 /* Checks that client has rights to add or remove channel modes. If any
2076    of the checks fails FALSE is returned. */
2077
2078 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2079                                    SilcChannelClientEntry client,
2080                                    unsigned int mode)
2081 {
2082   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2083   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2084
2085   /* Check whether has rights to change anything */
2086   if (!is_op && !is_fo)
2087     return FALSE;
2088
2089   /* Check whether has rights to change everything */
2090   if (is_op && is_fo)
2091     return TRUE;
2092
2093   /* We know that client is channel operator, check that they are not
2094      changing anything that requires channel founder rights. Rest of the
2095      modes are available automatically for channel operator. */
2096
2097   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2098     if (is_op && !is_fo)
2099       return FALSE;
2100   } else {
2101     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2102       if (is_op && !is_fo)
2103         return FALSE;
2104     }
2105   }
2106   
2107   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2108     if (is_op && !is_fo)
2109       return FALSE;
2110   } else {
2111     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2112       if (is_op && !is_fo)
2113         return FALSE;
2114     }
2115   }
2116
2117   if (mode & SILC_CHANNEL_MODE_CIPHER) {
2118     if (is_op && !is_fo)
2119       return FALSE;
2120   } else {
2121     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2122       if (is_op && !is_fo)
2123         return FALSE;
2124     }
2125   }
2126   
2127   return TRUE;
2128 }
2129
2130 /* Server side command of CMODE. Changes channel mode */
2131
2132 SILC_SERVER_CMD_FUNC(cmode)
2133 {
2134   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2135   SilcServer server = cmd->server;
2136   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2137   SilcChannelID *channel_id;
2138   SilcChannelEntry channel;
2139   SilcChannelClientEntry chl;
2140   SilcBuffer packet, cidp;
2141   unsigned char *tmp, *tmp_id, *tmp_mask;
2142   unsigned int argc, mode_mask, tmp_len, tmp_len2;
2143
2144   SILC_LOG_DEBUG(("Start"));
2145
2146   argc = silc_argument_get_arg_num(cmd->args);
2147   if (argc < 2) {
2148     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2149                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2150     goto out;
2151   }
2152   if (argc > 8) {
2153     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2154                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
2155     goto out;
2156   }
2157
2158   /* Get Channel ID */
2159   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2160   if (!tmp_id) {
2161     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2162                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2163     goto out;
2164   }
2165   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2166
2167   /* Get the channel mode mask */
2168   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2169   if (!tmp_mask) {
2170     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2171                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2172     goto out;
2173   }
2174   SILC_GET32_MSB(mode_mask, tmp_mask);
2175
2176   /* Get channel entry */
2177   channel = silc_idlist_find_channel_by_id(server->local_list, 
2178                                            channel_id, NULL);
2179   if (!channel) {
2180     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2181                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2182     goto out;
2183   }
2184
2185   /* Check whether this client is on the channel */
2186   if (!silc_server_client_on_channel(client, channel)) {
2187     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2188                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2189     goto out;
2190   }
2191
2192   /* Get entry to the channel user list */
2193   silc_list_start(channel->user_list);
2194   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2195     if (chl->client == client)
2196       break;
2197
2198   /* Check that client has rights to change any requested channel modes */
2199   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2200     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2201                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2202     goto out;
2203   }
2204
2205   /*
2206    * Check the modes. Modes that requires nothing special operation are
2207    * not checked here.
2208    */
2209
2210   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2211     /* Channel uses private keys to protect traffic. Client(s) has set the
2212        key locally they want to use, server does not know that key. */
2213     /* Nothing interesting to do here now */
2214   } else {
2215     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2216       /* The mode is removed and we need to generate and distribute
2217          new channel key. Clients are not using private channel keys
2218          anymore after this. */
2219
2220       /* XXX Duplicated code, make own function for this!! LEAVE uses this
2221          as well */
2222
2223       /* Re-generate channel key */
2224       silc_server_create_channel_key(server, channel, 0);
2225       
2226       /* Encode channel key payload to be distributed on the channel */
2227       packet = 
2228         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2229                                         strlen(channel->channel_key->
2230                                                cipher->name),
2231                                         channel->channel_key->cipher->name,
2232                                         channel->key_len / 8, channel->key);
2233       
2234       /* If we are normal server then we will send it to our router.  If we
2235          are router we will send it to all local servers that has clients on
2236          the channel */
2237       if (server->server_type == SILC_SERVER) {
2238         if (!server->standalone)
2239           silc_server_packet_send(server, 
2240                                   cmd->server->router->connection,
2241                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2242                                   packet->len, TRUE);
2243       } else {
2244         
2245       }
2246       
2247       /* Send to locally connected clients on the channel */
2248       silc_server_packet_send_local_channel(server, channel, 
2249                                             SILC_PACKET_CHANNEL_KEY, 0,
2250                                             packet->data, packet->len, FALSE);
2251       silc_buffer_free(packet);
2252     }
2253   }
2254   
2255   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2256     /* User limit is set on channel */
2257     unsigned int user_limit;
2258       
2259     /* Get user limit */
2260     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2261     if (!tmp) {
2262       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2263         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2264                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2265         goto out;
2266       }
2267     } else {
2268       SILC_GET32_MSB(user_limit, tmp);
2269       channel->mode_data.user_limit = user_limit;
2270     }
2271   } else {
2272     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2273       /* User limit mode is unset. Remove user limit */
2274       channel->mode_data.user_limit = 0;
2275   }
2276
2277   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2278     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2279       /* Passphrase has been set to channel */
2280       
2281       /* Get the passphrase */
2282       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2283       if (!tmp) {
2284         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2285                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2286         goto out;
2287       }
2288
2289       /* Save the passphrase */
2290       channel->mode_data.passphrase = strdup(tmp);
2291     }
2292   } else {
2293     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2294       /* Passphrase mode is unset. remove the passphrase */
2295       if (channel->mode_data.passphrase) {
2296         silc_free(channel->mode_data.passphrase);
2297         channel->mode_data.passphrase = NULL;
2298       }
2299     }
2300   }
2301
2302   if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2303     if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2304       /* Ban list is specified for channel */
2305
2306       /* Get ban list */
2307       tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2308       if (!tmp) {
2309         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2310                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2311         goto out;
2312       }
2313
2314       /* XXX check that channel founder is not banned */
2315
2316       /* Save the ban list */
2317       channel->mode_data.ban_list = strdup(tmp);
2318     }
2319   } else {
2320     if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2321       /* Ban mode is unset. Remove the entire ban list */
2322       if (channel->mode_data.ban_list) {
2323         silc_free(channel->mode_data.ban_list);
2324         channel->mode_data.ban_list = NULL;
2325       }
2326     }
2327   }
2328
2329   if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2330     if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2331       /* Invite list is specified for channel */
2332
2333       /* Get invite list */
2334       tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2335       if (!tmp) {
2336         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2337                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2338         goto out;
2339       }
2340
2341       /* Save the invite linst */
2342       channel->mode_data.invite_list = strdup(tmp);
2343     }
2344   } else {
2345     if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2346       /* Invite list mode is unset. Remove the entire invite list */
2347       if (channel->mode_data.invite_list) {
2348         silc_free(channel->mode_data.invite_list);
2349         channel->mode_data.invite_list = NULL;
2350       }
2351     }
2352   }
2353
2354   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2355     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2356       /* Cipher to use protect the traffic */
2357       unsigned int key_len = 128;
2358       char *cp;
2359
2360       /* Get cipher */
2361       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2362       if (!tmp) {
2363         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2364                                               SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2365         goto out;
2366       }
2367
2368       cp = strchr(tmp, ':');
2369       if (cp) {
2370         key_len = atoi(cp);
2371         *cp = '\0';
2372       }
2373
2374       /* XXX Duplicated code, make own function for this!! */
2375     
2376       /* Delete old cipher and allocate the new one */
2377       silc_cipher_free(channel->channel_key);
2378       silc_cipher_alloc(tmp, &channel->channel_key);
2379
2380       key_len /= 8;
2381       if (key_len > 32)
2382         key_len = 32;
2383
2384       /* Re-generate channel key */
2385       silc_server_create_channel_key(server, channel, key_len);
2386     
2387       /* Encode channel key payload to be distributed on the channel */
2388       packet = 
2389         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2390                                         strlen(channel->channel_key->
2391                                                cipher->name),
2392                                         channel->channel_key->cipher->name,
2393                                         channel->key_len / 8, channel->key);
2394     
2395       /* If we are normal server then we will send it to our router.  If we
2396          are router we will send it to all local servers that has clients on
2397          the channel */
2398       if (server->server_type == SILC_SERVER) {
2399         if (!server->standalone)
2400           silc_server_packet_send(server, 
2401                                   cmd->server->router->connection,
2402                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2403                                   packet->len, TRUE);
2404       } else {
2405         
2406       }
2407     
2408       /* Send to locally connected clients on the channel */
2409       silc_server_packet_send_local_channel(server, channel, 
2410                                             SILC_PACKET_CHANNEL_KEY, 0,
2411                                           packet->data, packet->len, FALSE);
2412       silc_buffer_free(packet);
2413     }
2414   } else {
2415     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2416       /* Cipher mode is unset. Remove the cipher and revert back to 
2417          default cipher */
2418
2419       if (channel->mode_data.cipher) {
2420         silc_free(channel->mode_data.cipher);
2421         channel->mode_data.cipher = NULL;
2422         channel->mode_data.key_len = 0;
2423       }
2424
2425       /* Generate new cipher and key for the channel */
2426
2427       /* XXX Duplicated code, make own function for this!! */
2428
2429       /* Delete old cipher and allocate default one */
2430       silc_cipher_free(channel->channel_key);
2431       if (!channel->cipher)
2432         silc_cipher_alloc("twofish", &channel->channel_key);
2433       else
2434         silc_cipher_alloc(channel->cipher, &channel->channel_key);
2435
2436       /* Re-generate channel key */
2437       silc_server_create_channel_key(server, channel, 0);
2438       
2439       /* Encode channel key payload to be distributed on the channel */
2440       packet = 
2441         silc_channel_key_payload_encode(tmp_len2, tmp_id,
2442                                         strlen(channel->channel_key->
2443                                                cipher->name),
2444                                         channel->channel_key->cipher->name,
2445                                         channel->key_len / 8, channel->key);
2446       
2447       /* If we are normal server then we will send it to our router.  If we
2448          are router we will send it to all local servers that has clients on
2449          the channel */
2450       if (server->server_type == SILC_SERVER) {
2451         if (!server->standalone)
2452           silc_server_packet_send(server, 
2453                                   cmd->server->router->connection,
2454                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2455                                   packet->len, TRUE);
2456       } else {
2457         
2458       }
2459       
2460       /* Send to locally connected clients on the channel */
2461       silc_server_packet_send_local_channel(server, channel, 
2462                                             SILC_PACKET_CHANNEL_KEY, 0,
2463                                             packet->data, packet->len, FALSE);
2464       silc_buffer_free(packet);
2465     }
2466   }
2467
2468   /* Finally, set the mode */
2469   channel->mode = mode_mask;
2470
2471   /* Send CMODE_CHANGE notify */
2472   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2473   silc_server_send_notify_to_channel(server, channel, TRUE,
2474                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2475                                      cidp->data, cidp->len, 
2476                                      tmp_mask, tmp_len);
2477   silc_free(cidp);
2478
2479   /* Send command reply to sender */
2480   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2481                                                 SILC_STATUS_OK, 0, 1,
2482                                                 2, tmp_mask, 4);
2483   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2484                           packet->data, packet->len, FALSE);
2485     
2486   silc_buffer_free(packet);
2487   silc_free(channel_id);
2488
2489  out:
2490   silc_server_command_free(cmd);
2491 }
2492
2493 /* Server side of CUMODE command. Changes client's mode on a channel. */
2494
2495 SILC_SERVER_CMD_FUNC(cumode)
2496 {
2497   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2498   SilcServer server = cmd->server;
2499   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2500   SilcChannelID *channel_id;
2501   SilcClientID *client_id;
2502   SilcChannelEntry channel;
2503   SilcClientEntry target_client;
2504   SilcChannelClientEntry chl;
2505   SilcBuffer packet, idp;
2506   unsigned char *tmp_id, *tmp_mask;
2507   unsigned int target_mask, sender_mask, tmp_len;
2508   int notify = FALSE;
2509
2510   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2511
2512   /* Get Channel ID */
2513   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2514   if (!tmp_id) {
2515     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2516                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2517     goto out;
2518   }
2519   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2520
2521   /* Get channel entry */
2522   channel = silc_idlist_find_channel_by_id(server->local_list, 
2523                                            channel_id, NULL);
2524   if (!channel) {
2525     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2526                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2527     goto out;
2528   }
2529
2530   /* Check whether sender is on the channel */
2531   if (!silc_server_client_on_channel(client, channel)) {
2532     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2533                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2534     goto out;
2535   }
2536
2537   /* Check that client has rights to change other's rights */
2538   silc_list_start(channel->user_list);
2539   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2540     if (chl->client == client) {
2541       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2542           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2543         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2544                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2545         goto out;
2546       }
2547
2548       sender_mask = chl->mode;
2549       break;
2550     }
2551   }
2552   
2553   /* Get the target client's channel mode mask */
2554   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2555   if (!tmp_mask) {
2556     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2557                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2558     goto out;
2559   }
2560   SILC_GET32_MSB(target_mask, tmp_mask);
2561
2562   /* Get target Client ID */
2563   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2564   if (!tmp_id) {
2565     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2566                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2567     goto out;
2568   }
2569   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2570
2571   /* Get target client's entry */
2572   target_client = silc_idlist_find_client_by_id(server->local_list, 
2573                                                 client_id, NULL);
2574   if (!target_client) {
2575     /* XXX If target client is not one of mine send to primary route */
2576   }
2577
2578   /* Check whether target client is on the channel */
2579   if (!silc_server_client_on_channel(target_client, channel)) {
2580     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2581                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2582     goto out;
2583   }
2584
2585   /* Get entry to the channel user list */
2586   silc_list_start(channel->user_list);
2587   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2588     if (chl->client == target_client)
2589       break;
2590
2591   /* 
2592    * Change the mode 
2593    */
2594
2595   /* If the target client is founder, no one else can change their mode
2596      but themselves. */
2597   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2598     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2599                                           SILC_STATUS_ERR_NOT_YOU);
2600     goto out;
2601   }
2602
2603   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2604     /* Cannot promote anyone to channel founder */
2605     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2606                                           SILC_STATUS_ERR_NOT_YOU);
2607     goto out;
2608   } else {
2609     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2610       if (target_client == client) {
2611         /* Remove channel founder rights from itself */
2612         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2613         notify = TRUE;
2614       } else {
2615         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2616                                               SILC_STATUS_ERR_NOT_YOU);
2617         goto out;
2618       }
2619     }
2620   }
2621
2622   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2623     /* Promote to operator */
2624     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2625       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2626       notify = TRUE;
2627     }
2628   } else {
2629     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2630       /* Demote to normal user */
2631       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2632       notify = TRUE;
2633     }
2634   }
2635
2636   /* Send notify to channel, notify only if mode was actually changed. */
2637   if (notify) {
2638     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2639     silc_server_send_notify_to_channel(server, channel, TRUE,
2640                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2641                                        idp->data, idp->len,
2642                                        tmp_mask, 4, tmp_id, tmp_len);
2643     silc_buffer_free(idp);
2644   }
2645
2646   /* Send command reply to sender */
2647   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2648                                                 SILC_STATUS_OK, 0, 2,
2649                                                 2, tmp_mask, 4,
2650                                                 3, tmp_id, tmp_len);
2651   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2652                           packet->data, packet->len, FALSE);
2653     
2654   silc_buffer_free(packet);
2655   silc_free(channel_id);
2656   silc_free(client_id);
2657
2658  out:
2659   silc_server_command_free(cmd);
2660 }
2661
2662 /* Server side of KICK command. Kicks client out of channel. */
2663
2664 SILC_SERVER_CMD_FUNC(kick)
2665 {
2666 }
2667
2668 SILC_SERVER_CMD_FUNC(restart)
2669 {
2670 }
2671  
2672 SILC_SERVER_CMD_FUNC(close)
2673 {
2674 }
2675  
2676 SILC_SERVER_CMD_FUNC(die)
2677 {
2678 }
2679  
2680 SILC_SERVER_CMD_FUNC(silcoper)
2681 {
2682 }
2683
2684 /* Server side command of LEAVE. Removes client from a channel. */
2685
2686 SILC_SERVER_CMD_FUNC(leave)
2687 {
2688   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2689   SilcServer server = cmd->server;
2690   SilcSocketConnection sock = cmd->sock;
2691   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2692   SilcChannelID *id;
2693   SilcChannelEntry channel;
2694   SilcBuffer packet;
2695   unsigned int i, len;
2696   unsigned char *tmp;
2697
2698   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2699
2700   /* Get Channel ID */
2701   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2702   if (!tmp) {
2703     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2704                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2705     goto out;
2706   }
2707   id = silc_id_payload_parse_id(tmp, len);
2708
2709   /* Get channel entry */
2710   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2711   if (!channel) {
2712     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2713                                           SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2714     goto out;
2715   }
2716
2717   /* Check whether this client is on the channel */
2718   if (!silc_server_client_on_channel(id_entry, channel)) {
2719     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2720                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2721     goto out;
2722   }
2723
2724   /* Notify routers that they should remove this client from their list
2725      of clients on the channel. */
2726   if (!server->standalone)
2727     silc_server_send_remove_channel_user(server, 
2728                                          server->router->connection,
2729                                          server->server_type == SILC_ROUTER ?
2730                                          TRUE : FALSE, id_entry->id, id);
2731
2732   /* Remove client from channel */
2733   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2734                                           TRUE);
2735   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2736                                         SILC_STATUS_OK);
2737
2738   /* If the channel does not exist anymore we won't send anything */
2739   if (!i)
2740     goto out;
2741
2742   /* Re-generate channel key */
2743   silc_server_create_channel_key(server, channel, 0);
2744
2745   /* Encode channel key payload to be distributed on the channel */
2746   packet = 
2747     silc_channel_key_payload_encode(len, tmp,
2748                                     strlen(channel->channel_key->cipher->name),
2749                                     channel->channel_key->cipher->name,
2750                                     channel->key_len / 8, channel->key);
2751
2752   /* If we are normal server then we will send it to our router.  If we
2753      are router we will send it to all local servers that has clients on
2754      the channel */
2755   if (server->server_type == SILC_SERVER) {
2756     if (!server->standalone)
2757       silc_server_packet_send(server, 
2758                               cmd->server->router->connection,
2759                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2760                               packet->len, TRUE);
2761   } else {
2762
2763   }
2764
2765   /* Send to locally connected clients on the channel */
2766   silc_server_packet_send_local_channel(server, channel, 
2767                                         SILC_PACKET_CHANNEL_KEY, 0,
2768                                         packet->data, packet->len, FALSE);
2769
2770   silc_buffer_free(packet);
2771   silc_free(id);
2772
2773  out:
2774   silc_server_command_free(cmd);
2775 }
2776
2777 /* Server side of command USERS. Resolves clients and their USERS currently
2778    joined on the requested channel. The list of Client ID's and their modes
2779    on the channel is sent back. */
2780
2781 SILC_SERVER_CMD_FUNC(users)
2782 {
2783   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2784   SilcServer server = cmd->server;
2785   SilcChannelEntry channel;
2786   SilcChannelClientEntry chl;
2787   SilcChannelID *id;
2788   SilcBuffer packet;
2789   unsigned char *channel_id;
2790   unsigned int channel_id_len;
2791   SilcBuffer client_id_list;
2792   SilcBuffer client_mode_list;
2793   SilcBuffer idp;
2794   unsigned char lc[4];
2795   unsigned int list_count = 0;
2796   unsigned short ident = silc_command_get_ident(cmd->payload);
2797
2798   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 2);
2799
2800   /* Get Channel ID */
2801   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
2802   if (!channel_id) {
2803     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2804                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2805     goto out;
2806   }
2807   id = silc_id_payload_parse_id(channel_id, channel_id_len);
2808
2809   /* If we are server and we don't know about this channel we will send
2810      the command to our router. If we know about the channel then we also
2811      have the list of users already. */
2812   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2813   if (!channel) {
2814     if (server->server_type == SILC_SERVER && !server->standalone &&
2815         !cmd->pending) {
2816       SilcBuffer tmpbuf;
2817       
2818       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2819       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2820       
2821       /* Send USERS command */
2822       silc_server_packet_send(server, server->router->connection,
2823                               SILC_PACKET_COMMAND, cmd->packet->flags,
2824                               tmpbuf->data, tmpbuf->len, TRUE);
2825       
2826       /* Reprocess this packet after received reply */
2827       silc_server_command_pending(server, SILC_COMMAND_USERS, 
2828                                   silc_command_get_ident(cmd->payload),
2829                                   silc_server_command_users, (void *)cmd);
2830       cmd->pending = TRUE;
2831       silc_command_set_ident(cmd->payload, ident);
2832       
2833       silc_buffer_free(tmpbuf);
2834       silc_free(id);
2835       return;
2836     }
2837
2838     /* We are router and we will check the global list as well. */
2839     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
2840     if (!channel) {
2841       /* Channel really does not exist */
2842       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
2843                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2844       goto out;
2845     }
2846   }
2847
2848   /* Assemble the lists now */
2849
2850   client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) * 
2851                                      silc_list_count(channel->user_list));
2852   silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2853   client_mode_list = 
2854     silc_buffer_alloc(4 * silc_list_count(channel->user_list));
2855   silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2856
2857   silc_list_start(channel->user_list);
2858   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2859     /* Client ID */
2860     idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2861     silc_buffer_put(client_id_list, idp->data, idp->len);
2862     silc_buffer_pull(client_id_list, idp->len);
2863     silc_buffer_free(idp);
2864
2865     /* Client's mode on channel */
2866     SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2867     silc_buffer_pull(client_mode_list, 4);
2868
2869     list_count++;
2870   }
2871   silc_buffer_push(client_id_list, 
2872                    client_id_list->data - client_id_list->head);
2873   silc_buffer_push(client_mode_list, 
2874                    client_mode_list->data - client_mode_list->head);
2875
2876   /* List count */
2877   SILC_PUT32_MSB(list_count, lc);
2878
2879   /* Send reply */
2880   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
2881                                                 SILC_STATUS_OK, 0, 4,
2882                                                 2, channel_id, channel_id_len,
2883                                                 3, lc, 4,
2884                                                 4, client_id_list->data,
2885                                                 client_id_list->len,
2886                                                 5, client_mode_list->data,
2887                                                 client_mode_list->len);
2888   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2889                           packet->data, packet->len, FALSE);
2890     
2891   silc_buffer_free(packet);
2892   silc_buffer_free(client_id_list);
2893   silc_buffer_free(client_mode_list);
2894   silc_free(id);
2895
2896  out:
2897   silc_server_command_free(cmd);
2898 }