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