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