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