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