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