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