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