updates.
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
6
7   Copyright (C) 1997 - 2001 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; either version 2 of the License, or
12   (at your option) any later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18
19 */
20 /* $Id$ */
21
22 #include "serverincludes.h"
23 #include "server_internal.h"
24
25 static int silc_server_is_registered(SilcServer server,
26                                      SilcSocketConnection sock,
27                                      SilcServerCommandContext cmd,
28                                      SilcCommand command);
29 static void 
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
31                                       SilcCommand command,
32                                       SilcCommandStatus status);
33 static void 
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
35                                      SilcCommand command,
36                                      SilcCommandStatus status,
37                                      unsigned int arg_type,
38                                      unsigned char *arg,
39                                      unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
41
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
44 {
45   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
46   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
47   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
48   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
49   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
50   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
51   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
54   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
55   SILC_SERVER_CMD(connect, CONNECT, 
56                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
59   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
60   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
63   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
65   SILC_SERVER_CMD(restart, RESTART, 
66                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
67   SILC_SERVER_CMD(close, CLOSE,
68                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
69   SILC_SERVER_CMD(shutdown, SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
70                   SILC_CF_OPER),
71   SILC_SERVER_CMD(silcoper, SILCOPER,
72                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
73   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
74   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
75   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
76
77   { NULL, 0 },
78 };
79
80 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max)            \
81 do {                                                                          \
82   unsigned int _argc = silc_argument_get_arg_num(cmd->args);                  \
83                                                                               \
84   SILC_LOG_DEBUG(("Start"));                                                  \
85                                                                               \
86   if (_argc < min) {                                                          \
87     silc_server_command_send_status_reply(cmd, command,                       \
88                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
89     silc_server_command_free(cmd);                                            \
90     return;                                                                   \
91   }                                                                           \
92   if (_argc > max) {                                                          \
93     silc_server_command_send_status_reply(cmd, command,                       \
94                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);   \
95     silc_server_command_free(cmd);                                            \
96     return;                                                                   \
97   }                                                                           \
98 } while(0)
99
100 /* Returns TRUE if the connection is registered. Unregistered connections
101    usually cannot send commands hence the check. */
102
103 static int silc_server_is_registered(SilcServer server,
104                                      SilcSocketConnection sock,
105                                      SilcServerCommandContext cmd,
106                                      SilcCommand command)
107 {
108   SilcIDListData idata = (SilcIDListData)sock->user_data;
109   if (idata->registered)
110     return TRUE;
111
112   silc_server_command_send_status_reply(cmd, command,
113                                         SILC_STATUS_ERR_NOT_REGISTERED);
114   silc_server_command_free(cmd);
115   return FALSE;
116 }
117
118 /* Internal context to hold data when executed command with timeout. */
119 typedef struct {
120   SilcServerCommandContext ctx;
121   SilcServerCommand *cmd;
122 } *SilcServerCommandTimeout;
123
124 /* Timeout callback to process commands with timeout for client. Client's
125    commands are always executed with timeout. */
126
127 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
128 {
129   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
130   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
131
132   /* Update access time */
133   client->last_command = time(NULL);
134
135   if (!(timeout->cmd->flags & SILC_CF_REG))
136     timeout->cmd->cb(timeout->ctx);
137   else if (silc_server_is_registered(timeout->ctx->server, 
138                                      timeout->ctx->sock, 
139                                      timeout->ctx, 
140                                      timeout->cmd->cmd))
141     timeout->cmd->cb(timeout->ctx);
142
143   silc_free(timeout);
144 }
145
146 /* Processes received command packet. */
147
148 void silc_server_command_process(SilcServer server,
149                                  SilcSocketConnection sock,
150                                  SilcPacketContext *packet)
151 {
152   SilcServerCommandContext ctx;
153   SilcServerCommand *cmd;
154   SilcCommand command;
155
156   /* Allocate command context. This must be free'd by the
157      command routine receiving it. */
158   ctx = silc_server_command_alloc();
159   ctx->server = server;
160   ctx->sock = silc_socket_dup(sock);
161   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
162   
163   /* Parse the command payload in the packet */
164   ctx->payload = silc_command_payload_parse(packet->buffer);
165   if (!ctx->payload) {
166     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
167     silc_buffer_free(packet->buffer);
168     silc_packet_context_free(packet);
169     silc_socket_free(ctx->sock);
170     silc_free(ctx);
171     return;
172   }
173   ctx->args = silc_command_get_args(ctx->payload);
174
175   /* Get the command */
176   command = silc_command_get(ctx->payload);
177   for (cmd = silc_command_list; cmd->cb; cmd++)
178     if (cmd->cmd == command)
179       break;
180
181   if (cmd == NULL) {
182     silc_server_command_send_status_reply(ctx, command,
183                                           SILC_STATUS_ERR_UNKNOWN_COMMAND);
184     silc_server_command_free(ctx);
185     return;
186   }
187
188   /* Execute client's commands always with timeout.  Normally they are
189      executed with zero (0) timeout but if client is sending command more
190      frequently than once in 2 seconds, then the timeout may be 0 to 2
191      seconds. */
192   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
193     SilcClientEntry client = (SilcClientEntry)sock->user_data;
194     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
195     int fast;
196
197     timeout->ctx = ctx;
198     timeout->cmd = cmd;
199
200     if (client->last_command && (time(NULL) - client->last_command) < 2) {
201       client->fast_command++;
202       fast = FALSE;
203     } else {
204       client->fast_command = ((client->fast_command - 1) <= 0 ? 0 : 
205                               client->fast_command--);
206       fast = TRUE;
207     }
208
209     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
210                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
211       silc_task_register(server->timeout_queue, sock->sock, 
212                          silc_server_command_process_timeout,
213                          (void *)timeout, 
214                          2 - (time(NULL) - client->last_command), 0,
215                          SILC_TASK_TIMEOUT,
216                          SILC_TASK_PRI_NORMAL);
217     else
218       silc_task_register(server->timeout_queue, sock->sock, 
219                          silc_server_command_process_timeout,
220                          (void *)timeout, 
221                          0, 1,
222                          SILC_TASK_TIMEOUT,
223                          SILC_TASK_PRI_NORMAL);
224     return;
225   }
226
227   /* Execute for server */
228
229   if (!(cmd->flags & SILC_CF_REG))
230     cmd->cb(ctx);
231   else if (silc_server_is_registered(server, sock, ctx, cmd->cmd))
232     cmd->cb(ctx);
233 }
234
235 /* Allocate Command Context */
236
237 SilcServerCommandContext silc_server_command_alloc()
238 {
239   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
240   ctx->users++;
241   return ctx;
242 }
243
244 /* Free's the command context allocated before executing the command */
245
246 void silc_server_command_free(SilcServerCommandContext ctx)
247 {
248   ctx->users--;
249   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
250                   ctx->users));
251   if (ctx->users < 1) {
252     if (ctx->payload)
253       silc_command_free_payload(ctx->payload);
254     if (ctx->packet)
255       silc_packet_context_free(ctx->packet);
256     if (ctx->sock)
257       silc_socket_free(ctx->sock); /* Decrease reference counter */
258     silc_free(ctx);
259   }
260 }
261
262 /* Duplicate Command Context by adding reference counter. The context won't
263    be free'd untill it hits zero. */
264
265 SilcServerCommandContext 
266 silc_server_command_dup(SilcServerCommandContext ctx)
267 {
268   ctx->users++;
269   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
270                   ctx->users));
271   return ctx;
272 }
273
274 /* Add new pending command to be executed when reply to a command has been
275    received. The `reply_cmd' is the command that will call the `callback'
276    with `context' when reply has been received.  If `ident' is non-zero
277    the `callback' will be executed when received reply with command
278    identifier `ident'. */
279
280 void silc_server_command_pending(SilcServer server,
281                                  SilcCommand reply_cmd,
282                                  unsigned short ident,
283                                  SilcServerPendingDestructor destructor,
284                                  SilcCommandCb callback,
285                                  void *context)
286 {
287   SilcServerCommandPending *reply;
288
289   reply = silc_calloc(1, sizeof(*reply));
290   reply->reply_cmd = reply_cmd;
291   reply->ident = ident;
292   reply->context = context;
293   reply->callback = callback;
294   reply->destructor = destructor;
295   silc_dlist_add(server->pending_commands, reply);
296 }
297
298 /* Deletes pending command by reply command type. */
299
300 void silc_server_command_pending_del(SilcServer server,
301                                      SilcCommand reply_cmd,
302                                      unsigned short ident)
303 {
304   SilcServerCommandPending *r;
305
306   silc_dlist_start(server->pending_commands);
307   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
308     if (r->reply_cmd == reply_cmd && r->ident == ident) {
309       silc_dlist_del(server->pending_commands, r);
310       break;
311     }
312   }
313 }
314
315 /* Checks for pending commands and marks callbacks to be called from
316    the command reply function. Returns TRUE if there were pending command. */
317
318 int silc_server_command_pending_check(SilcServer server,
319                                       SilcServerCommandReplyContext ctx,
320                                       SilcCommand command, 
321                                       unsigned short ident)
322 {
323   SilcServerCommandPending *r;
324
325   silc_dlist_start(server->pending_commands);
326   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
327     if (r->reply_cmd == command && r->ident == ident) {
328       ctx->context = r->context;
329       ctx->callback = r->callback;
330       ctx->destructor = r->destructor;
331       ctx->ident = ident;
332       return TRUE;
333     }
334   }
335
336   return FALSE;
337 }
338
339 /* Destructor function for pending callbacks. This is called when using
340    pending commands to free the context given for the pending command. */
341
342 static void silc_server_command_destructor(void *context)
343 {
344   silc_server_command_free((SilcServerCommandContext)context);
345 }
346
347 /* Sends simple status message as command reply packet */
348
349 static void 
350 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
351                                       SilcCommand command,
352                                       SilcCommandStatus status)
353 {
354   SilcBuffer buffer;
355
356   SILC_LOG_DEBUG(("Sending command status %d", status));
357
358   buffer = 
359     silc_command_reply_payload_encode_va(command, status, 
360                                          silc_command_get_ident(cmd->payload),
361                                          0);
362   silc_server_packet_send(cmd->server, cmd->sock,
363                           SILC_PACKET_COMMAND_REPLY, 0, 
364                           buffer->data, buffer->len, FALSE);
365   silc_buffer_free(buffer);
366 }
367
368 /* Sends command status reply with one extra argument. The argument
369    type must be sent as argument. */
370
371 static void 
372 silc_server_command_send_status_data(SilcServerCommandContext cmd,
373                                      SilcCommand command,
374                                      SilcCommandStatus status,
375                                      unsigned int arg_type,
376                                      unsigned char *arg,
377                                      unsigned int arg_len)
378 {
379   SilcBuffer buffer;
380
381   SILC_LOG_DEBUG(("Sending command status %d", status));
382
383   buffer = 
384     silc_command_reply_payload_encode_va(command, status, 
385                                          silc_command_get_ident(cmd->payload),
386                                          1, arg_type, arg, arg_len);
387   silc_server_packet_send(cmd->server, cmd->sock,
388                           SILC_PACKET_COMMAND_REPLY, 0, 
389                           buffer->data, buffer->len, FALSE);
390   silc_buffer_free(buffer);
391 }
392
393 /******************************************************************************
394
395                               WHOIS Functions
396
397 ******************************************************************************/
398
399 static int
400 silc_server_command_whois_parse(SilcServerCommandContext cmd,
401                                 SilcClientID ***client_id,
402                                 unsigned int *client_id_count,
403                                 char **nickname,
404                                 char **server_name,
405                                 int *count,
406                                 SilcCommand command)
407 {
408   unsigned char *tmp;
409   unsigned int len;
410   unsigned int argc = silc_argument_get_arg_num(cmd->args);
411   int i, k;
412
413   /* If client ID is in the command it must be used instead of nickname */
414   tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
415   if (!tmp) {
416     /* No ID, get the nickname@server string and parse it. */
417     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
418     if (tmp) {
419       if (strchr(tmp, '@')) {
420         len = strcspn(tmp, "@");
421         *nickname = silc_calloc(len + 1, sizeof(char));
422         memcpy(*nickname, tmp, len);
423         *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
424         memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
425       } else {
426         *nickname = strdup(tmp);
427       }
428     } else {
429       silc_server_command_send_status_reply(cmd, command,
430                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
431       return FALSE;
432     }
433   } else {
434     /* Command includes ID, we must use that.  Also check whether the command
435        has more than one ID set - take them all. */
436
437     *client_id = silc_calloc(1, sizeof(**client_id));
438     (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
439     if ((*client_id)[0] == NULL) {
440       silc_free(*client_id);
441       return FALSE;
442     }
443     *client_id_count = 1;
444
445     /* Take all ID's from the command packet */
446     if (argc > 1) {
447       for (k = 1, i = 1; i < argc; i++) {
448         tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
449         if (tmp) {
450           *client_id = silc_realloc(*client_id, sizeof(**client_id) *
451                                     (*client_id_count + 1));
452           (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
453           if ((*client_id)[k] == NULL) {
454             /* Cleanup all and fail */
455             for (i = 0; i < *client_id_count; i++)
456               silc_free((*client_id)[i]);
457             silc_free(*client_id);
458             return FALSE;
459           }
460           (*client_id_count)++;
461           k++;
462         }
463       }
464     }
465
466     /* Command includes ID, use that */
467   }
468
469   /* Get the max count of reply messages allowed */
470   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
471   if (tmp)
472     *count = atoi(tmp);
473   else
474     *count = 0;
475
476   return TRUE;
477 }
478
479 static char
480 silc_server_command_whois_check(SilcServerCommandContext cmd,
481                                 SilcClientEntry *clients,
482                                 unsigned int clients_count)
483 {
484   SilcServer server = cmd->server;
485   int i;
486   SilcClientEntry entry;
487
488   for (i = 0; i < clients_count; i++) {
489     entry = clients[i];
490
491     if (entry->data.registered == FALSE)
492       continue;
493
494     if (!entry->nickname || !entry->username || !entry->userinfo) {
495       SilcBuffer tmpbuf;
496       unsigned short old_ident;
497
498       if (!entry->router)
499         continue;
500       
501       old_ident = silc_command_get_ident(cmd->payload);
502       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
503       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
504
505       /* Send WHOIS command */
506       silc_server_packet_send(server, entry->router->connection,
507                               SILC_PACKET_COMMAND, cmd->packet->flags,
508                               tmpbuf->data, tmpbuf->len, TRUE);
509       
510       /* Reprocess this packet after received reply */
511       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
512                                   silc_command_get_ident(cmd->payload),
513                                   silc_server_command_destructor,
514                                   silc_server_command_whois, 
515                                   silc_server_command_dup(cmd));
516       cmd->pending = TRUE;
517       
518       silc_command_set_ident(cmd->payload, old_ident);
519
520       silc_buffer_free(tmpbuf);
521       return FALSE;
522     }
523   }
524
525   return TRUE;
526 }
527
528 static void
529 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
530                                      SilcClientEntry *clients,
531                                      unsigned int clients_count)
532 {
533   SilcServer server = cmd->server;
534   char *tmp;
535   int i, count = 0, len;
536   SilcBuffer packet, idp, channels;
537   SilcClientEntry entry;
538   SilcCommandStatus status;
539   unsigned short ident = silc_command_get_ident(cmd->payload);
540   char nh[128], uh[128];
541   unsigned char idle[4], mode[4];
542   SilcSocketConnection hsock;
543
544   status = SILC_STATUS_OK;
545   if (clients_count > 1)
546     status = SILC_STATUS_LIST_START;
547
548   for (i = 0; i < clients_count; i++) {
549     entry = clients[i];
550
551     if (entry->data.registered == FALSE) {
552       if (clients_count == 1) {
553         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
554         silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
555                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
556                                              2, idp->data, idp->len);
557         silc_buffer_free(idp);
558       }
559       continue;
560     }
561
562     if (count && i - 1 == count)
563       break;
564
565     if (i >= 1)
566       status = SILC_STATUS_LIST_ITEM;
567
568     if (clients_count > 1 && i == clients_count - 1)
569       status = SILC_STATUS_LIST_END;
570
571     /* Sanity check, however these should never fail. However, as
572        this sanity check has been added here they have failed. */
573     if (!entry->nickname || !entry->username || !entry->userinfo)
574       continue;
575       
576     /* Send WHOIS reply */
577     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
578     tmp = silc_argument_get_first_arg(cmd->args, NULL);
579     
580     memset(uh, 0, sizeof(uh));
581     memset(nh, 0, sizeof(nh));
582     memset(idle, 0, sizeof(idle));
583     
584     strncat(nh, entry->nickname, strlen(entry->nickname));
585     if (!strchr(entry->nickname, '@')) {
586       strncat(nh, "@", 1);
587       len = entry->router ? strlen(entry->router->server_name) :
588         strlen(server->server_name);
589       strncat(nh, entry->router ? entry->router->server_name :
590               server->server_name, len);
591     }
592       
593     strncat(uh, entry->username, strlen(entry->username));
594     if (!strchr(entry->username, '@')) {
595       strncat(uh, "@", 1);
596       hsock = (SilcSocketConnection)entry->connection;
597       len = strlen(hsock->hostname);
598       strncat(uh, hsock->hostname, len);
599     }
600
601     channels = silc_server_get_client_channel_list(server, entry);
602       
603     SILC_PUT32_MSB(entry->mode, mode);
604
605     if (entry->connection) {
606       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
607     }
608
609     if (channels)
610       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
611                                                     status, ident, 7, 
612                                                     2, idp->data, idp->len,
613                                                     3, nh, strlen(nh),
614                                                     4, uh, strlen(uh),
615                                                     5, entry->userinfo, 
616                                                     strlen(entry->userinfo),
617                                                     6, channels->data,
618                                                     channels->len,
619                                                     7, mode, 4,
620                                                     8, idle, 4);
621     else
622       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
623                                                     status, ident, 6, 
624                                                     2, idp->data, idp->len,
625                                                     3, nh, strlen(nh),
626                                                     4, uh, strlen(uh),
627                                                     5, entry->userinfo, 
628                                                     strlen(entry->userinfo),
629                                                     7, mode, 4,
630                                                     8, idle, 4);
631     
632     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
633                             0, packet->data, packet->len, FALSE);
634     
635     silc_buffer_free(packet);
636     silc_buffer_free(idp);
637     if (channels)
638       silc_buffer_free(channels);
639   }
640 }
641
642 static int
643 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
644 {
645   SilcServer server = cmd->server;
646   char *nick = NULL, *server_name = NULL;
647   int count = 0, clients_count = 0;
648   SilcClientEntry *clients = NULL, entry;
649   SilcClientID **client_id = NULL;
650   unsigned int client_id_count = 0;
651   int i, ret = 0;
652
653   /* Protocol dictates that we must always send the received WHOIS request
654      to our router if we are normal server, so let's do it now unless we
655      are standalone. We will not send any replies to the client until we
656      have received reply from the router. */
657   if (server->server_type == SILC_SERVER && !cmd->pending && 
658       !server->standalone) {
659     SilcBuffer tmpbuf;
660     unsigned short old_ident;
661
662     old_ident = silc_command_get_ident(cmd->payload);
663     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
664     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
665
666     /* Send WHOIS command to our router */
667     silc_server_packet_send(server, (SilcSocketConnection)
668                             server->router->connection,
669                             SILC_PACKET_COMMAND, cmd->packet->flags,
670                             tmpbuf->data, tmpbuf->len, TRUE);
671
672     /* Reprocess this packet after received reply from router */
673     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
674                                 silc_command_get_ident(cmd->payload),
675                                 silc_server_command_destructor,
676                                 silc_server_command_whois,
677                                 silc_server_command_dup(cmd));
678     cmd->pending = TRUE;
679
680     silc_command_set_ident(cmd->payload, old_ident);
681
682     silc_buffer_free(tmpbuf);
683     ret = -1;
684     goto out;
685   }
686
687   /* We are ready to process the command request. Let's search for the
688      requested client and send reply to the requesting client. */
689
690   /* Parse the whois request */
691   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
692                                        &nick, &server_name, &count,
693                                        SILC_COMMAND_WHOIS))
694     return 0;
695
696   /* Get all clients matching that ID or nickname from local list */
697   if (client_id_count) {
698     /* Check all Client ID's received in the command packet */
699     for (i = 0; i < client_id_count; i++) {
700       entry = silc_idlist_find_client_by_id(server->local_list, 
701                                             client_id[i], NULL);
702       if (entry) {
703         clients = silc_realloc(clients, sizeof(*clients) * 
704                                (clients_count + 1));
705         clients[clients_count++] = entry;
706       }
707     }
708   } else {
709     clients = silc_idlist_get_clients_by_hash(server->local_list, 
710                                               nick, server->md5hash,
711                                               &clients_count);
712     if (!clients)
713       clients = silc_idlist_get_clients_by_nickname(server->local_list, 
714                                                     nick, server_name,
715                                                     &clients_count);
716   }
717   
718   /* Check global list as well */
719   if (!clients) {
720     if (client_id_count) {
721       /* Check all Client ID's received in the command packet */
722       for (i = 0; i < client_id_count; i++) {
723         entry = silc_idlist_find_client_by_id(server->global_list, 
724                                               client_id[i], NULL);
725         if (entry) {
726           clients = silc_realloc(clients, sizeof(*clients) * 
727                                  (clients_count + 1));
728           clients[clients_count++] = entry;
729         }
730       }
731     } else {
732       clients = silc_idlist_get_clients_by_hash(server->global_list, 
733                                                 nick, server->md5hash,
734                                                 &clients_count);
735       if (!clients)
736         clients = silc_idlist_get_clients_by_nickname(server->global_list, 
737                                                       nick, server_name,
738                                                       &clients_count);
739     }
740   }
741   
742   if (!clients) {
743     /* Such client(s) really does not exist in the SILC network. */
744     if (!client_id_count) {
745       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
746                                            SILC_STATUS_ERR_NO_SUCH_NICK,
747                                            3, nick, strlen(nick));
748     } else {
749       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
750       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
751                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
752                                            2, idp->data, idp->len);
753       silc_buffer_free(idp);
754     }
755     goto out;
756   }
757
758   /* Router always finds the client entry if it exists in the SILC network.
759      However, it might be incomplete entry and does not include all the
760      mandatory fields that WHOIS command reply requires. Check for these and
761      make query from the server who owns the client if some fields are 
762      missing. */
763   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
764     ret = -1;
765     goto out;
766   }
767
768   /* Send the command reply to the client */
769   silc_server_command_whois_send_reply(cmd, clients, clients_count);
770
771  out:
772   if (client_id_count) {
773     for (i = 0; i < client_id_count; i++)
774       silc_free(client_id[i]);
775     silc_free(client_id);
776   }
777   if (clients)
778     silc_free(clients);
779   if (nick)
780     silc_free(nick);
781   if (server_name)
782     silc_free(server_name);
783
784   return ret;
785 }
786
787 static int
788 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
789 {
790   SilcServer server = cmd->server;
791   char *nick = NULL, *server_name = NULL;
792   int count = 0, clients_count = 0;
793   SilcClientEntry *clients = NULL, entry;
794   SilcClientID **client_id = NULL;
795   unsigned int client_id_count = 0;
796   int i, ret = 0;
797
798   /* Parse the whois request */
799   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
800                                        &nick, &server_name, &count,
801                                        SILC_COMMAND_WHOIS))
802     return 0;
803
804   /* Process the command request. Let's search for the requested client and
805      send reply to the requesting server. */
806
807   if (client_id_count) {
808     /* Check all Client ID's received in the command packet */
809     for (i = 0; i < client_id_count; i++) {
810       entry = silc_idlist_find_client_by_id(server->local_list, 
811                                             client_id[i], NULL);
812       if (entry) {
813         clients = silc_realloc(clients, sizeof(*clients) * 
814                                (clients_count + 1));
815         clients[clients_count++] = entry;
816       }
817     }
818   } else {
819     clients = silc_idlist_get_clients_by_hash(server->local_list, 
820                                               nick, server->md5hash,
821                                               &clients_count);
822     if (!clients)
823       clients = silc_idlist_get_clients_by_nickname(server->local_list, 
824                                                     nick, server_name,
825                                                     &clients_count);
826   }
827   
828   /* If we are router we will check our global list as well. */
829   if (!clients && server->server_type == SILC_ROUTER) {
830     if (client_id_count) {
831       /* Check all Client ID's received in the command packet */
832       for (i = 0; i < client_id_count; i++) {
833         entry = silc_idlist_find_client_by_id(server->global_list, 
834                                               client_id[i], NULL);
835         if (entry) {
836           clients = silc_realloc(clients, sizeof(*clients) * 
837                                  (clients_count + 1));
838           clients[clients_count++] = entry;
839         }
840       }
841     } else {
842       clients = silc_idlist_get_clients_by_hash(server->global_list, 
843                                                 nick, server->md5hash,
844                                                 &clients_count);
845       if (!clients)
846         clients = silc_idlist_get_clients_by_nickname(server->global_list, 
847                                                       nick, server_name,
848                                                       &clients_count);
849     }
850   }
851
852   if (!clients) {
853     /* Such a client really does not exist in the SILC network. */
854     if (!client_id_count) {
855       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
856                                            SILC_STATUS_ERR_NO_SUCH_NICK,
857                                            3, nick, strlen(nick));
858     } else {
859       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
860       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
861                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
862                                            2, idp->data, idp->len);
863       silc_buffer_free(idp);
864     }
865     goto out;
866   }
867
868   /* Router always finds the client entry if it exists in the SILC network.
869      However, it might be incomplete entry and does not include all the
870      mandatory fields that WHOIS command reply requires. Check for these and
871      make query from the server who owns the client if some fields are 
872      missing. */
873   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
874     ret = -1;
875     goto out;
876   }
877
878   /* Send the command reply to the client */
879   silc_server_command_whois_send_reply(cmd, clients, clients_count);
880
881  out:
882   if (client_id_count) {
883     for (i = 0; i < client_id_count; i++)
884       silc_free(client_id[i]);
885     silc_free(client_id);
886   }
887   if (clients)
888     silc_free(clients);
889   if (nick)
890     silc_free(nick);
891   if (server_name)
892     silc_free(server_name);
893
894   return ret;
895 }
896
897 /* Server side of command WHOIS. Processes user's query and sends found 
898    results as command replies back to the client. */
899
900 SILC_SERVER_CMD_FUNC(whois)
901 {
902   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
903   int ret = 0;
904
905   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
906
907   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
908     ret = silc_server_command_whois_from_client(cmd);
909   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
910            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
911     ret = silc_server_command_whois_from_server(cmd);
912
913   if (!ret)
914     silc_server_command_free(cmd);
915 }
916
917 /******************************************************************************
918
919                               WHOWAS Functions
920
921 ******************************************************************************/
922
923 static int
924 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
925                                  char **nickname,
926                                  char **server_name,
927                                  int *count)
928 {
929   unsigned char *tmp;
930   unsigned int len;
931
932   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
933   if (!tmp) {
934     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
935                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
936     return FALSE;
937   }
938
939   /* Get the nickname@server string and parse it. */
940   if (strchr(tmp, '@')) {
941     len = strcspn(tmp, "@");
942     *nickname = silc_calloc(len + 1, sizeof(char));
943     memcpy(*nickname, tmp, len);
944     *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
945     memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
946   } else {
947     *nickname = strdup(tmp);
948   }
949   /* Get the max count of reply messages allowed */
950   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
951   if (tmp)
952     *count = atoi(tmp);
953   else
954     *count = 0;
955
956   return TRUE;
957 }
958
959 static char
960 silc_server_command_whowas_check(SilcServerCommandContext cmd,
961                                  SilcClientEntry *clients,
962                                  unsigned int clients_count)
963 {
964   SilcServer server = cmd->server;
965   int i;
966   SilcClientEntry entry;
967
968   for (i = 0; i < clients_count; i++) {
969     entry = clients[i];
970
971     if (!entry->nickname || !entry->username) {
972       SilcBuffer tmpbuf;
973       unsigned short old_ident;
974
975       if (!entry->router)
976         continue;
977       
978       old_ident = silc_command_get_ident(cmd->payload);
979       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
980       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
981
982       /* Send WHOWAS command */
983       silc_server_packet_send(server, entry->router->connection,
984                               SILC_PACKET_COMMAND, cmd->packet->flags,
985                               tmpbuf->data, tmpbuf->len, TRUE);
986       
987       /* Reprocess this packet after received reply */
988       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
989                                   silc_command_get_ident(cmd->payload),
990                                   silc_server_command_destructor,
991                                   silc_server_command_whowas, 
992                                   silc_server_command_dup(cmd));
993       cmd->pending = TRUE;
994       
995       silc_command_set_ident(cmd->payload, old_ident);
996
997       silc_buffer_free(tmpbuf);
998       return FALSE;
999     }
1000   }
1001
1002   return TRUE;
1003 }
1004
1005 static void
1006 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1007                                       SilcClientEntry *clients,
1008                                       unsigned int clients_count)
1009 {
1010   SilcServer server = cmd->server;
1011   char *tmp;
1012   int i, count = 0, len;
1013   SilcBuffer packet, idp;
1014   SilcClientEntry entry = NULL;
1015   SilcCommandStatus status;
1016   unsigned short ident = silc_command_get_ident(cmd->payload);
1017   char found = FALSE;
1018   char nh[256], uh[256];
1019
1020   status = SILC_STATUS_OK;
1021   if (clients_count > 1)
1022     status = SILC_STATUS_LIST_START;
1023
1024   for (i = 0; i < clients_count; i++) {
1025     entry = clients[i];
1026
1027     /* We will take only clients that are not valid anymore. They are the
1028        ones that are not registered anymore but still have a ID. They
1029        have disconnected us, and thus valid for WHOWAS. */
1030     if (entry->data.registered == TRUE)
1031       continue;
1032     if (entry->id == NULL)
1033       continue;
1034
1035     if (count && i - 1 == count)
1036       break;
1037
1038     found = TRUE;
1039
1040     if (clients_count > 2)
1041       status = SILC_STATUS_LIST_ITEM;
1042
1043     if (clients_count > 1 && i == clients_count - 1)
1044       status = SILC_STATUS_LIST_END;
1045
1046     /* Sanity check, however these should never fail. However, as
1047        this sanity check has been added here they have failed. */
1048     if (!entry->nickname || !entry->username)
1049       continue;
1050       
1051     /* Send WHOWAS reply */
1052     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1053     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1054     
1055     memset(uh, 0, sizeof(uh));
1056     memset(nh, 0, sizeof(nh));
1057
1058     strncat(nh, entry->nickname, strlen(entry->nickname));
1059     if (!strchr(entry->nickname, '@')) {
1060       strncat(nh, "@", 1);
1061       len = entry->router ? strlen(entry->router->server_name) :
1062         strlen(server->server_name);
1063       strncat(nh, entry->router ? entry->router->server_name :
1064               server->server_name, len);
1065     }
1066       
1067     strncat(uh, entry->username, strlen(entry->username));
1068     if (!strchr(entry->username, '@')) {
1069       strncat(uh, "@", 1);
1070       strcat(uh, "*private*");
1071     }
1072       
1073     if (entry->userinfo)
1074       packet = 
1075         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1076                                              status, ident, 4, 
1077                                              2, idp->data, idp->len,
1078                                              3, nh, strlen(nh),
1079                                              4, uh, strlen(uh),
1080                                              5, entry->userinfo, 
1081                                              strlen(entry->userinfo));
1082     else
1083       packet = 
1084         silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1085                                              status, ident, 3, 
1086                                              2, idp->data, idp->len,
1087                                              3, nh, strlen(nh),
1088                                              4, uh, strlen(uh));
1089
1090     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1091                             0, packet->data, packet->len, FALSE);
1092     
1093     silc_buffer_free(packet);
1094     silc_buffer_free(idp);
1095   }
1096
1097   if (found == FALSE && entry)
1098     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1099                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1100                                          3, entry->nickname, 
1101                                          strlen(entry->nickname));
1102 }
1103
1104 static int
1105 silc_server_command_whowas_from_client(SilcServerCommandContext cmd)
1106 {
1107   SilcServer server = cmd->server;
1108   char *nick = NULL, *server_name = NULL;
1109   int count = 0, clients_count = 0;
1110   SilcClientEntry *clients = NULL;
1111   int ret = 0;
1112
1113   /* Protocol dictates that we must always send the received WHOWAS request
1114      to our router if we are normal server, so let's do it now unless we
1115      are standalone. We will not send any replies to the client until we
1116      have received reply from the router. */
1117   if (server->server_type == SILC_SERVER && 
1118       !cmd->pending && !server->standalone) {
1119     SilcBuffer tmpbuf;
1120     unsigned short old_ident;
1121
1122     old_ident = silc_command_get_ident(cmd->payload);
1123     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1124     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1125
1126     /* Send WHOWAS command to our router */
1127     silc_server_packet_send(server, (SilcSocketConnection)
1128                             server->router->connection,
1129                             SILC_PACKET_COMMAND, cmd->packet->flags,
1130                             tmpbuf->data, tmpbuf->len, TRUE);
1131
1132     /* Reprocess this packet after received reply from router */
1133     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1134                                 silc_command_get_ident(cmd->payload),
1135                                 silc_server_command_destructor,
1136                                 silc_server_command_whowas,
1137                                 silc_server_command_dup(cmd));
1138     cmd->pending = TRUE;
1139
1140     silc_command_set_ident(cmd->payload, old_ident);
1141
1142     silc_buffer_free(tmpbuf);
1143     ret = -1;
1144     goto out;
1145   }
1146
1147   /* We are ready to process the command request. Let's search for the
1148      requested client and send reply to the requesting client. */
1149
1150   /* Parse the whowas request */
1151   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1152     return 0;
1153
1154   /* Get all clients matching that nickname from local list */
1155   clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1156                                                 nick, server_name,
1157                                                 &clients_count);
1158   if (!clients)
1159     clients = silc_idlist_get_clients_by_hash(server->local_list, 
1160                                               nick, server->md5hash,
1161                                               &clients_count);
1162   
1163   /* Check global list as well */
1164   if (!clients) {
1165     clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1166                                                   nick, server_name,
1167                                                   &clients_count);
1168     if (!clients)
1169       clients = silc_idlist_get_clients_by_hash(server->global_list, 
1170                                                 nick, server->md5hash,
1171                                                 &clients_count);
1172   }
1173   
1174   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1175     ret = -1;
1176     goto out;
1177   }
1178
1179   /* Send the command reply to the client */
1180   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1181
1182  out:
1183   if (clients)
1184     silc_free(clients);
1185   if (nick)
1186     silc_free(nick);
1187   if (server_name)
1188     silc_free(server_name);
1189
1190   return ret;
1191 }
1192
1193 static int
1194 silc_server_command_whowas_from_server(SilcServerCommandContext cmd)
1195 {
1196   SilcServer server = cmd->server;
1197   char *nick = NULL, *server_name = NULL;
1198   int count = 0, clients_count = 0;
1199   SilcClientEntry *clients = NULL;
1200   int ret = 0;
1201
1202   /* Parse the whowas request */
1203   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1204     return 0;
1205
1206   /* Process the command request. Let's search for the requested client and
1207      send reply to the requesting server. */
1208
1209   clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1210                                                 nick, server_name,
1211                                                 &clients_count);
1212   if (!clients)
1213     clients = silc_idlist_get_clients_by_hash(server->local_list, 
1214                                               nick, server->md5hash,
1215                                               &clients_count);
1216   
1217   /* If we are router we will check our global list as well. */
1218   if (!clients && server->server_type == SILC_ROUTER) {
1219     clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1220                                                   nick, server_name,
1221                                                   &clients_count);
1222     if (!clients)
1223       clients = silc_idlist_get_clients_by_hash(server->global_list, 
1224                                                 nick, server->md5hash,
1225                                                 &clients_count);
1226   }
1227
1228   if (!clients) {
1229     /* Such a client really does not exist in the SILC network. */
1230     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1231                                          SILC_STATUS_ERR_NO_SUCH_NICK,
1232                                          3, nick, strlen(nick));
1233     goto out;
1234   }
1235
1236   /* Send the command reply to the client */
1237   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1238
1239  out:
1240   if (clients)
1241     silc_free(clients);
1242   if (nick)
1243     silc_free(nick);
1244   if (server_name)
1245     silc_free(server_name);
1246
1247   return ret;
1248 }
1249
1250 /* Server side of command WHOWAS. */
1251
1252 SILC_SERVER_CMD_FUNC(whowas)
1253 {
1254   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1255   int ret = 0;
1256
1257   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1258
1259   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1260     ret = silc_server_command_whowas_from_client(cmd);
1261   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
1262            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1263     ret = silc_server_command_whowas_from_server(cmd);
1264
1265   if (!ret)
1266     silc_server_command_free(cmd);
1267 }
1268
1269 /******************************************************************************
1270
1271                               IDENTIFY Functions
1272
1273 ******************************************************************************/
1274
1275 /* Checks that all mandatory fields are present. If not then send WHOIS 
1276    request to the server who owns the client. We use WHOIS because we want
1277    to get as much information as possible at once. */
1278
1279 static char
1280 silc_server_command_identify_check(SilcServerCommandContext cmd,
1281                                    SilcClientEntry *clients,
1282                                    unsigned int clients_count)
1283 {
1284   SilcServer server = cmd->server;
1285   int i;
1286   SilcClientEntry entry;
1287
1288   for (i = 0; i < clients_count; i++) {
1289     entry = clients[i];
1290
1291     if (entry->data.registered == FALSE)
1292       continue;
1293
1294     if (!entry->nickname) {
1295       SilcBuffer tmpbuf;
1296       unsigned short old_ident;
1297       
1298       if (!entry->router)
1299         continue;
1300       
1301       old_ident = silc_command_get_ident(cmd->payload);
1302       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1303       silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
1304       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1305       
1306       /* Send WHOIS request. We send WHOIS since we're doing the requesting
1307          now anyway so make it a good one. */
1308       silc_server_packet_send(server, entry->router->connection,
1309                               SILC_PACKET_COMMAND, cmd->packet->flags,
1310                               tmpbuf->data, tmpbuf->len, TRUE);
1311       
1312       /* Reprocess this packet after received reply */
1313       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1314                                   silc_command_get_ident(cmd->payload),
1315                                   silc_server_command_destructor,
1316                                   silc_server_command_identify,
1317                                   silc_server_command_dup(cmd));
1318
1319       cmd->pending = TRUE;
1320       
1321       /* Put old data back to the Command Payload we just changed */
1322       silc_command_set_ident(cmd->payload, old_ident);
1323       silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
1324
1325       silc_buffer_free(tmpbuf);
1326       return FALSE;
1327     }
1328   }
1329
1330   return TRUE;
1331 }
1332
1333 static void
1334 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1335                                         SilcClientEntry *clients,
1336                                         unsigned int clients_count)
1337 {
1338   SilcServer server = cmd->server;
1339   char *tmp;
1340   int i, count = 0, len;
1341   SilcBuffer packet, idp;
1342   SilcClientEntry entry;
1343   SilcCommandStatus status;
1344   unsigned short ident = silc_command_get_ident(cmd->payload);
1345
1346   status = SILC_STATUS_OK;
1347   if (clients_count > 1)
1348     status = SILC_STATUS_LIST_START;
1349
1350   for (i = 0; i < clients_count; i++) {
1351     entry = clients[i];
1352
1353     if (entry->data.registered == FALSE) {
1354       if (clients_count == 1) {
1355         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1356         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1357                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1358                                              2, idp->data, idp->len);
1359         silc_buffer_free(idp);
1360       }
1361       continue;
1362     }
1363
1364     if (count && i - 1 == count)
1365       break;
1366
1367     if (i >= 1)
1368       status = SILC_STATUS_LIST_ITEM;
1369
1370     if (clients_count > 1 && i == clients_count - 1)
1371       status = SILC_STATUS_LIST_END;
1372
1373     /* Send IDENTIFY reply */
1374     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1375     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1376     
1377     /* XXX */
1378     {
1379       char nh[256], uh[256];
1380       SilcSocketConnection hsock;
1381
1382       memset(uh, 0, sizeof(uh));
1383       memset(nh, 0, sizeof(nh));
1384       
1385       strncat(nh, entry->nickname, strlen(entry->nickname));
1386       if (!strchr(entry->nickname, '@')) {
1387         strncat(nh, "@", 1);
1388         len = entry->router ? strlen(entry->router->server_name) :
1389           strlen(server->server_name);
1390         strncat(nh, entry->router ? entry->router->server_name :
1391                 server->server_name, len);
1392       }
1393       
1394       if (!entry->username) {
1395         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1396                                                       status, ident, 2,
1397                                                       2, idp->data, idp->len, 
1398                                                       3, nh, strlen(nh));
1399       } else {
1400         strncat(uh, entry->username, strlen(entry->username));
1401         if (!strchr(entry->username, '@')) {
1402           strncat(uh, "@", 1);
1403           hsock = (SilcSocketConnection)entry->connection;
1404           len = strlen(hsock->hostname);
1405           strncat(uh, hsock->hostname, len);
1406         }
1407       
1408         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1409                                                       status, ident, 3,
1410                                                       2, idp->data, idp->len, 
1411                                                       3, nh, strlen(nh),
1412                                                       4, uh, strlen(uh));
1413       }
1414       
1415       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1416                               0, packet->data, packet->len, FALSE);
1417       
1418       silc_buffer_free(packet);
1419       silc_buffer_free(idp);
1420     }
1421   }
1422 }
1423
1424 static int
1425 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1426 {
1427   SilcServer server = cmd->server;
1428   char *nick = NULL, *server_name = NULL;
1429   int count = 0, clients_count = 0; 
1430   SilcClientEntry *clients = NULL, entry;
1431   SilcClientID **client_id = NULL;
1432   unsigned int client_id_count = 0;
1433   int i, ret = 0;
1434
1435   /* Protocol dictates that we must always send the received IDENTIFY request
1436      to our router if we are normal server, so let's do it now unless we
1437      are standalone. We will not send any replies to the client until we
1438      have received reply from the router. */
1439   if (server->server_type == SILC_SERVER && 
1440       !cmd->pending && !server->standalone) {
1441     SilcBuffer tmpbuf;
1442     unsigned short old_ident;
1443
1444     old_ident = silc_command_get_ident(cmd->payload);
1445     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1446     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1447
1448     /* Send IDENTIFY command to our router */
1449     silc_server_packet_send(server, (SilcSocketConnection)
1450                             server->router->connection,
1451                             SILC_PACKET_COMMAND, cmd->packet->flags,
1452                             tmpbuf->data, tmpbuf->len, TRUE);
1453
1454     /* Reprocess this packet after received reply from router */
1455     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1456                                 silc_command_get_ident(cmd->payload),
1457                                 silc_server_command_destructor,
1458                                 silc_server_command_identify,
1459                                 silc_server_command_dup(cmd));
1460     cmd->pending = TRUE;
1461
1462     silc_command_set_ident(cmd->payload, old_ident);
1463
1464     silc_buffer_free(tmpbuf);
1465     ret = -1;
1466     goto out;
1467   }
1468
1469   /* We are ready to process the command request. Let's search for the
1470      requested client and send reply to the requesting client. */
1471
1472   /* Parse the IDENTIFY request */
1473   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1474                                        &nick, &server_name, &count,
1475                                        SILC_COMMAND_IDENTIFY))
1476     return 0;
1477
1478   /* Get all clients matching that ID or nickname from local list */
1479   if (client_id_count) { 
1480     /* Check all Client ID's received in the command packet */
1481     for (i = 0; i < client_id_count; i++) {
1482       entry = silc_idlist_find_client_by_id(server->local_list, 
1483                                             client_id[i], NULL);
1484       if (entry) {
1485         clients = silc_realloc(clients, sizeof(*clients) * 
1486                                (clients_count + 1));
1487         clients[clients_count++] = entry;
1488       }
1489     }
1490   } else {
1491     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1492                                                   nick, server_name,
1493                                                   &clients_count);
1494     if (!clients)
1495       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1496                                                 nick, server->md5hash,
1497                                                 &clients_count);
1498   }
1499   
1500   /* Check global list as well */
1501   if (!clients) {
1502     if (client_id_count) {
1503       /* Check all Client ID's received in the command packet */
1504       for (i = 0; i < client_id_count; i++) {
1505         entry = silc_idlist_find_client_by_id(server->global_list, 
1506                                               client_id[i], NULL);
1507         if (entry) {
1508           clients = silc_realloc(clients, sizeof(*clients) * 
1509                                  (clients_count + 1));
1510           clients[clients_count++] = entry;
1511         }
1512       }
1513     } else {
1514       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1515                                                     nick, server_name,
1516                                                     &clients_count);
1517       if (!clients)
1518         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1519                                                   nick, server->md5hash,
1520                                                   &clients_count);
1521     }
1522   }
1523   
1524   if (!clients) {
1525     /* Such a client really does not exist in the SILC network. */
1526     if (!client_id_count) {
1527       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1528                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1529                                            3, nick, strlen(nick));
1530     } else {
1531       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1532       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1533                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1534                                            2, idp->data, idp->len);
1535       silc_buffer_free(idp);
1536     }
1537     goto out;
1538   }
1539
1540   /* Check that all mandatory fields are present and request those data
1541      from the server who owns the client if necessary. */
1542   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1543     ret = -1;
1544     goto out;
1545   }
1546
1547   /* Send the command reply to the client */
1548   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1549
1550  out:
1551   if (client_id_count) {
1552     for (i = 0; i < client_id_count; i++)
1553       silc_free(client_id[i]);
1554     silc_free(client_id);
1555   }
1556   if (clients)
1557     silc_free(clients);
1558   if (nick)
1559     silc_free(nick);
1560   if (server_name)
1561     silc_free(server_name);
1562
1563   return ret;
1564 }
1565
1566 static int
1567 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1568 {
1569   SilcServer server = cmd->server;
1570   char *nick = NULL, *server_name = NULL;
1571   int count = 0, clients_count = 0;
1572   SilcClientEntry *clients = NULL, entry;
1573   SilcClientID **client_id = NULL;
1574   unsigned int client_id_count = 0;
1575   int i, ret = 0;
1576
1577   /* Parse the IDENTIFY request */
1578   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1579                                        &nick, &server_name, &count,
1580                                        SILC_COMMAND_IDENTIFY))
1581     return 0;
1582
1583   /* Process the command request. Let's search for the requested client and
1584      send reply to the requesting server. */
1585
1586   if (client_id_count) {
1587     /* Check all Client ID's received in the command packet */
1588     for (i = 0; i < client_id_count; i++) {
1589       entry = silc_idlist_find_client_by_id(server->local_list, 
1590                                             client_id[i], NULL);
1591       if (entry) {
1592         clients = silc_realloc(clients, sizeof(*clients) * 
1593                                (clients_count + 1));
1594         clients[clients_count++] = entry;
1595       }
1596     }
1597   } else {
1598     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1599                                                   nick, server_name,
1600                                                   &clients_count);
1601     if (!clients)
1602       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1603                                                 nick, server->md5hash,
1604                                                 &clients_count);
1605   }
1606   
1607   /* If we are router we will check our global list as well. */
1608   if (!clients && server->server_type == SILC_ROUTER) {
1609     if (client_id_count) {
1610       /* Check all Client ID's received in the command packet */
1611       for (i = 0; i < client_id_count; i++) {
1612         entry = silc_idlist_find_client_by_id(server->global_list, 
1613                                               client_id[i], NULL);
1614         if (entry) {
1615           clients = silc_realloc(clients, sizeof(*clients) * 
1616                                  (clients_count + 1));
1617           clients[clients_count++] = entry;
1618         }
1619       }
1620     } else {
1621       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1622                                                     nick, server_name,
1623                                                     &clients_count);
1624       if (!clients)
1625         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1626                                                   nick, server->md5hash,
1627                                                   &clients_count);
1628     }
1629   }
1630
1631   if (!clients) {
1632     /* Such a client really does not exist in the SILC network. */
1633     if (!client_id_count) {
1634       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1635                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1636                                            3, nick, strlen(nick));
1637     } else {
1638       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1639       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1640                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1641                                            2, idp->data, idp->len);
1642       silc_buffer_free(idp);
1643     }
1644     goto out;
1645   }
1646
1647   /* Check that all mandatory fields are present and request those data
1648      from the server who owns the client if necessary. */
1649   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1650     ret = -1;
1651     goto out;
1652   }
1653
1654   /* Send the command reply */
1655   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1656
1657  out:
1658   if (client_id_count) {
1659     for (i = 0; i < client_id_count; i++)
1660       silc_free(client_id[i]);
1661     silc_free(client_id);
1662   }
1663   if (clients)
1664     silc_free(clients);
1665   if (nick)
1666     silc_free(nick);
1667   if (server_name)
1668     silc_free(server_name);
1669
1670   return ret;
1671 }
1672
1673 SILC_SERVER_CMD_FUNC(identify)
1674 {
1675   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1676   int ret = 0;
1677
1678   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1679
1680   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1681     ret = silc_server_command_identify_from_client(cmd);
1682   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1683            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1684     ret = silc_server_command_identify_from_server(cmd);
1685
1686   if (!ret)
1687     silc_server_command_free(cmd);
1688 }
1689
1690 /* Checks string for bad characters and returns TRUE if they are found. */
1691
1692 static int silc_server_command_bad_chars(char *nick)
1693 {
1694   if (strchr(nick, '\\')) return TRUE;
1695   if (strchr(nick, '\"')) return TRUE;
1696   if (strchr(nick, '´')) return TRUE;
1697   if (strchr(nick, '`')) return TRUE;
1698   if (strchr(nick, '\'')) return TRUE;
1699   if (strchr(nick, '*')) return TRUE;
1700   if (strchr(nick, '/')) return TRUE;
1701   if (strchr(nick, '@')) return TRUE;
1702
1703   return FALSE;
1704 }
1705
1706 /* Server side of command NICK. Sets nickname for user. Setting
1707    nickname causes generation of a new client ID for the client. The
1708    new client ID is sent to the client after changing the nickname. */
1709
1710 SILC_SERVER_CMD_FUNC(nick)
1711 {
1712   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1713   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1714   SilcServer server = cmd->server;
1715   SilcBuffer packet, nidp, oidp;
1716   SilcClientID *new_id;
1717   char *nick;
1718   unsigned short ident = silc_command_get_ident(cmd->payload);
1719
1720   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1721     goto out;
1722
1723   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1724
1725   /* Check nickname */
1726   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1727   if (silc_server_command_bad_chars(nick) == TRUE) {
1728     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1729                                           SILC_STATUS_ERR_BAD_NICKNAME);
1730     goto out;
1731   }
1732
1733   if (strlen(nick) > 128)
1734     nick[127] = '\0';
1735
1736   /* Create new Client ID */
1737   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1738                            cmd->server->md5hash, nick,
1739                            &new_id);
1740
1741   /* Send notify about nickname change to our router. We send the new
1742      ID and ask to replace it with the old one. If we are router the
1743      packet is broadcasted. Send NICK_CHANGE notify. */
1744   if (!server->standalone)
1745     silc_server_send_notify_nick_change(server, server->router->connection, 
1746                                         server->server_type == SILC_SERVER ? 
1747                                         FALSE : TRUE, client->id,
1748                                         new_id, SILC_ID_CLIENT_LEN);
1749
1750   /* Remove old cache entry */
1751   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
1752                          client->id); 
1753
1754   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1755
1756   /* Free old ID */
1757   if (client->id) {
1758     memset(client->id, 0, SILC_ID_CLIENT_LEN);
1759     silc_free(client->id);
1760   }
1761
1762   /* Save the nickname as this client is our local client */
1763   if (client->nickname)
1764     silc_free(client->nickname);
1765
1766   client->nickname = strdup(nick);
1767   client->id = new_id;
1768
1769   /* Update client cache */
1770   silc_idcache_add(server->local_list->clients, client->nickname, 
1771                    strlen(client->nickname), SILC_ID_CLIENT, client->id, 
1772                    (void *)client, TRUE, FALSE);
1773
1774   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1775
1776   /* Send NICK_CHANGE notify to the client's channels */
1777   silc_server_send_notify_on_channels(server, NULL, client, 
1778                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1779                                       oidp->data, oidp->len, 
1780                                       nidp->data, nidp->len);
1781
1782   /* Send the new Client ID as reply command back to client */
1783   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1784                                                 SILC_STATUS_OK, ident, 1, 
1785                                                 2, nidp->data, nidp->len);
1786   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1787                           0, packet->data, packet->len, FALSE);
1788
1789   silc_buffer_free(packet);
1790   silc_buffer_free(nidp);
1791   silc_buffer_free(oidp);
1792   
1793  out:
1794   silc_server_command_free(cmd);
1795 }
1796
1797 /* Sends the LIST command reply */
1798
1799 static void
1800 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1801                                     SilcChannelEntry *lch, 
1802                                     unsigned int lch_count,
1803                                     SilcChannelEntry *gch,
1804                                     unsigned int gch_count)
1805 {
1806   int i;
1807   SilcBuffer packet, idp;
1808   SilcChannelEntry entry;
1809   SilcCommandStatus status;
1810   unsigned short ident = silc_command_get_ident(cmd->payload);
1811   char *topic;
1812   unsigned char usercount[4];
1813   unsigned int users;
1814
1815   for (i = 0; i < lch_count; i++)
1816     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1817       lch[i] = NULL;
1818   for (i = 0; i < gch_count; i++)
1819     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1820       gch[i] = NULL;
1821
1822   status = SILC_STATUS_OK;
1823   if ((lch_count + gch_count) > 1)
1824     status = SILC_STATUS_LIST_START;
1825
1826   /* Local list */
1827   for (i = 0; i < lch_count; i++) {
1828     entry = lch[i];
1829
1830     if (!entry)
1831       continue;
1832
1833     if (i >= 1)
1834       status = SILC_STATUS_LIST_ITEM;
1835
1836     if (i == lch_count - 1 && gch_count)
1837       break;
1838     if (lch_count > 1 && i == lch_count - 1)
1839       status = SILC_STATUS_LIST_END;
1840
1841     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1842
1843     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1844       topic = "*private*";
1845       memset(usercount, 0, sizeof(usercount));
1846     } else {
1847       topic = entry->topic;
1848       users = silc_list_count(entry->user_list);
1849       SILC_PUT32_MSB(users, usercount);
1850     }
1851
1852     /* Send the reply */
1853     if (topic)
1854       packet = 
1855         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1856                                              status, ident, 4, 
1857                                              2, idp->data, idp->len,
1858                                              3, entry->channel_name, 
1859                                              strlen(entry->channel_name),
1860                                              4, topic, strlen(topic),
1861                                              5, usercount, 4);
1862     else
1863       packet = 
1864         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1865                                              status, ident, 3, 
1866                                              2, idp->data, idp->len,
1867                                              3, entry->channel_name, 
1868                                              strlen(entry->channel_name),
1869                                              5, usercount, 4);
1870     silc_server_packet_send(cmd->server, cmd->sock, 
1871                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1872                             packet->len, FALSE);
1873     silc_buffer_free(packet);
1874     silc_buffer_free(idp);
1875   }
1876
1877   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1878
1879   /* Global list */
1880   for (i = 0; i < gch_count; i++) {
1881     entry = gch[i];
1882
1883     if (!entry)
1884       continue;
1885
1886     if (i >= 1)
1887       status = SILC_STATUS_LIST_ITEM;
1888
1889     if (gch_count > 1 && i == lch_count - 1)
1890       status = SILC_STATUS_LIST_END;
1891
1892     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1893
1894     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1895       topic = "*private*";
1896       memset(usercount, 0, sizeof(usercount));
1897     } else {
1898       topic = entry->topic;
1899       users = silc_list_count(entry->user_list);
1900       SILC_PUT32_MSB(users, usercount);
1901     }
1902
1903     /* Send the reply */
1904     if (topic)
1905       packet = 
1906         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1907                                              status, ident, 4, 
1908                                              2, idp->data, idp->len,
1909                                              3, entry->channel_name, 
1910                                              strlen(entry->channel_name),
1911                                              4, topic, strlen(topic),
1912                                              5, usercount, 4);
1913     else
1914       packet = 
1915         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1916                                              status, ident, 3, 
1917                                              2, idp->data, idp->len,
1918                                              3, entry->channel_name, 
1919                                              strlen(entry->channel_name),
1920                                              5, usercount, 4);
1921     silc_server_packet_send(cmd->server, cmd->sock, 
1922                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1923                             packet->len, FALSE);
1924     silc_buffer_free(packet);
1925     silc_buffer_free(idp);
1926   }
1927 }
1928
1929 /* Server side of LIST command. This lists the channel of the requested
1930    server. Secret channels are not listed. */
1931
1932 SILC_SERVER_CMD_FUNC(list)
1933 {
1934   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1935   SilcServer server = cmd->server;
1936   SilcChannelID *channel_id = NULL;
1937   unsigned char *tmp;
1938   unsigned int tmp_len;
1939   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1940   unsigned int lch_count = 0, gch_count = 0;
1941
1942   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1943
1944   /* Get Channel ID */
1945   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1946   if (tmp) {
1947     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1948     if (!channel_id) {
1949       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1950                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
1951       goto out;
1952     }
1953   }
1954
1955   /* Get the channels from local list */
1956   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1957                                        &lch_count);
1958   
1959   /* Get the channels from global list if we are router */
1960   if (server->server_type == SILC_ROUTER) 
1961     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1962                                          &gch_count);
1963
1964   /* Send the reply */
1965   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
1966                                       gchannels, gch_count);
1967
1968  out:
1969   silc_server_command_free(cmd);
1970 }
1971
1972 /* Server side of TOPIC command. Sets topic for channel and/or returns
1973    current topic to client. */
1974
1975 SILC_SERVER_CMD_FUNC(topic)
1976 {
1977   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1978   SilcServer server = cmd->server;
1979   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1980   SilcChannelID *channel_id;
1981   SilcChannelEntry channel;
1982   SilcChannelClientEntry chl;
1983   SilcBuffer packet, idp;
1984   unsigned char *tmp;
1985   unsigned int argc, tmp_len;
1986   unsigned short ident = silc_command_get_ident(cmd->payload);
1987
1988   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1989
1990   argc = silc_argument_get_arg_num(cmd->args);
1991
1992   /* Get Channel ID */
1993   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1994   if (!tmp) {
1995     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1996                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1997     goto out;
1998   }
1999   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2000   if (!channel_id) {
2001     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2002                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2003     goto out;
2004   }
2005
2006   /* Check whether the channel exists */
2007   channel = silc_idlist_find_channel_by_id(server->local_list, 
2008                                            channel_id, NULL);
2009   if (!channel) {
2010     channel = silc_idlist_find_channel_by_id(server->global_list, 
2011                                              channel_id, NULL);
2012     if (!channel) {
2013       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2014                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2015       goto out;
2016     }
2017   }
2018
2019   if (argc > 1) {
2020     /* Get the topic */
2021     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2022     if (!tmp) {
2023       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2024                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2025       goto out;
2026     }
2027
2028     if (strlen(tmp) > 256) {
2029       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2030                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2031       goto out;
2032     }
2033
2034     /* See whether has rights to change topic */
2035     silc_list_start(channel->user_list);
2036     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2037       if (chl->client == client)
2038         break;
2039
2040     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2041       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2042         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2043                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2044         goto out;
2045       }
2046     }
2047
2048     /* Set the topic for channel */
2049     if (channel->topic)
2050       silc_free(channel->topic);
2051     channel->topic = strdup(tmp);
2052
2053     /* Send TOPIC_SET notify type to the network */
2054     if (!server->standalone)
2055       silc_server_send_notify_topic_set(server, server->router->connection,
2056                                         server->server_type == SILC_ROUTER ?
2057                                         TRUE : FALSE, channel, client->id,
2058                                         SILC_ID_CLIENT_LEN, channel->topic);
2059
2060     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2061
2062     /* Send notify about topic change to all clients on the channel */
2063     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2064                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2065                                        idp->data, idp->len,
2066                                        channel->topic, strlen(channel->topic));
2067     silc_buffer_free(idp);
2068   }
2069
2070   /* Send the topic to client as reply packet */
2071   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2072   if (channel->topic)
2073     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2074                                                   SILC_STATUS_OK, ident, 2, 
2075                                                   2, idp->data, idp->len,
2076                                                   3, channel->topic, 
2077                                                   strlen(channel->topic));
2078   else
2079     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2080                                                   SILC_STATUS_OK, ident, 1, 
2081                                                   2, idp->data, idp->len);
2082   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2083                           0, packet->data, packet->len, FALSE);
2084
2085   silc_buffer_free(packet);
2086   silc_buffer_free(idp);
2087   silc_free(channel_id);
2088
2089  out:
2090   silc_server_command_free(cmd);
2091 }
2092
2093 /* Server side of INVITE command. Invites some client to join some channel. 
2094    This command is also used to manage the invite list of the channel. */
2095
2096 SILC_SERVER_CMD_FUNC(invite)
2097 {
2098   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2099   SilcServer server = cmd->server;
2100   SilcSocketConnection sock = cmd->sock, dest_sock;
2101   SilcChannelClientEntry chl;
2102   SilcClientEntry sender, dest;
2103   SilcClientID *dest_id = NULL;
2104   SilcChannelEntry channel;
2105   SilcChannelID *channel_id = NULL;
2106   SilcIDListData idata;
2107   SilcBuffer idp;
2108   unsigned char *tmp, *add, *del;
2109   unsigned int len;
2110
2111   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
2112
2113   /* Get Channel ID */
2114   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2115   if (!tmp) {
2116     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2117                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2118     goto out;
2119   }
2120   channel_id = silc_id_payload_parse_id(tmp, len);
2121   if (!channel_id) {
2122     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2123                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2124     goto out;
2125   }
2126
2127   /* Get the channel entry */
2128   channel = silc_idlist_find_channel_by_id(server->local_list, 
2129                                            channel_id, NULL);
2130   if (!channel) {
2131     channel = silc_idlist_find_channel_by_id(server->global_list, 
2132                                              channel_id, NULL);
2133     if (!channel) {
2134       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2135                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2136       goto out;
2137     }
2138   }
2139
2140   /* Check whether the sender of this command is on the channel. */
2141   sender = (SilcClientEntry)sock->user_data;
2142   if (!silc_server_client_on_channel(sender, channel)) {
2143     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2144                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2145     goto out;
2146   }
2147
2148   /* Check whether the channel is invite-only channel. If yes then the
2149      sender of this command must be at least channel operator. */
2150   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2151     silc_list_start(channel->user_list);
2152     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2153       if (chl->client == sender) {
2154         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2155           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2156                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2157           goto out;
2158         }
2159         break;
2160       }
2161   }
2162
2163   /* Get destination client ID */
2164   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2165   if (tmp) {
2166     char invite[512];
2167
2168     dest_id = silc_id_payload_parse_id(tmp, len);
2169     if (!dest_id) {
2170       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2171                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2172       goto out;
2173     }
2174
2175     /* Get the client entry */
2176     dest = silc_server_get_client_resolve(server, dest_id);
2177     if (!dest) {
2178       if (server->server_type == SILC_ROUTER) {
2179         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2180                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2181         goto out;
2182       }
2183       
2184       /* The client info is being resolved. Reprocess this packet after
2185          receiving the reply to the query. */
2186       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2187                                   server->cmd_ident,
2188                                   silc_server_command_destructor,
2189                                   silc_server_command_invite, 
2190                                   silc_server_command_dup(cmd));
2191       cmd->pending = TRUE;
2192       silc_free(channel_id);
2193       silc_free(dest_id);
2194       return;
2195     }
2196
2197     /* Check whether the requested client is already on the channel. */
2198     if (silc_server_client_on_channel(dest, channel)) {
2199       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2200                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2201       goto out;
2202     }
2203     
2204     /* Get route to the client */
2205     dest_sock = silc_server_get_client_route(server, tmp, len, &idata);
2206
2207     strncat(invite, dest->nickname, strlen(dest->nickname));
2208     if (!strchr(dest->nickname, '@')) {
2209       strncat(invite, "@", 1);
2210       strncat(invite, server->server_name, strlen(server->server_name));
2211     }
2212     strncat(invite, "!", 1);
2213     strncat(invite, dest->username, strlen(dest->username));
2214     if (!strchr(dest->username, '@')) {
2215       strncat(invite, "@", 1);
2216       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2217     }
2218
2219     len = strlen(invite);
2220     if (!channel->invite_list)
2221       channel->invite_list = silc_calloc(len + 2, 
2222                                          sizeof(*channel->invite_list));
2223     else
2224       channel->invite_list = silc_realloc(channel->ban_list, 
2225                                           sizeof(*channel->invite_list) * 
2226                                           (len + 
2227                                            strlen(channel->invite_list) + 2));
2228     strncat(channel->invite_list, invite, len);
2229     strncat(channel->invite_list, ",", 1);
2230
2231     /* Send notify to the client that is invited to the channel */
2232     idp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2233     tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2234     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2235                                  SILC_ID_CLIENT,
2236                                  SILC_NOTIFY_TYPE_INVITE, 2, 
2237                                  idp->data, idp->len, tmp, len);
2238     silc_buffer_free(idp);
2239   }
2240
2241   /* Add the client to the invite list of the channel */
2242   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2243   if (add && strlen(add) == len) {
2244     if (!channel->invite_list)
2245       channel->invite_list = silc_calloc(len + 2, 
2246                                          sizeof(*channel->invite_list));
2247     else
2248       channel->invite_list = silc_realloc(channel->ban_list, 
2249                                           sizeof(*channel->invite_list) * 
2250                                           (len + 
2251                                            strlen(channel->invite_list) + 2));
2252     if (add[len - 1] == ',')
2253       add[len - 1] = '\0';
2254     
2255     strncat(channel->invite_list, add, len);
2256     strncat(channel->invite_list, ",", 1);
2257   }
2258
2259   /* Get the invite to be removed and remove it from the list */
2260   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2261   if (del && channel->invite_list) {
2262     char *start, *end, *n;
2263
2264     if (!strncmp(channel->invite_list, del, 
2265                  strlen(channel->invite_list) - 1)) {
2266       silc_free(channel->invite_list);
2267       channel->invite_list = NULL;
2268       goto out0;
2269     }
2270
2271     start = strstr(channel->invite_list, del);
2272     if (start && strlen(start) >= len) {
2273       end = start + len;
2274       n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2275       strncat(n, channel->invite_list, start - channel->invite_list);
2276       strncat(n, end + 1, ((channel->invite_list + 
2277                             strlen(channel->invite_list)) - end) - 1);
2278       silc_free(channel->invite_list);
2279       channel->invite_list = n;
2280     }
2281   }
2282
2283  out0:
2284
2285   idp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2286
2287   /* Send notify to the primary router */
2288
2289
2290   /* Send command reply */
2291   silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2292                                         SILC_STATUS_OK);
2293
2294   silc_buffer_free(idp);
2295
2296  out:
2297   if (dest_id)
2298     silc_free(dest_id);
2299   if (channel_id)
2300     silc_free(channel_id);
2301   silc_server_command_free(cmd);
2302 }
2303
2304 typedef struct {
2305   SilcServer server;
2306   SilcSocketConnection sock;
2307   char *signoff;
2308 } *QuitInternal;
2309
2310 /* Quits connection to client. This gets called if client won't
2311    close the connection even when it has issued QUIT command. */
2312
2313 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2314 {
2315   QuitInternal q = (QuitInternal)context;
2316
2317   /* Free all client specific data, such as client entry and entires
2318      on channels this client may be on. */
2319   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2320                                TRUE, q->signoff);
2321   q->sock->user_data = NULL;
2322
2323   /* Close the connection on our side */
2324   silc_server_close_connection(q->server, q->sock);
2325
2326   silc_free(q->signoff);
2327   silc_free(q);
2328 }
2329
2330 /* Quits SILC session. This is the normal way to disconnect client. */
2331  
2332 SILC_SERVER_CMD_FUNC(quit)
2333 {
2334   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2335   SilcServer server = cmd->server;
2336   SilcSocketConnection sock = cmd->sock;
2337   QuitInternal q;
2338   unsigned char *tmp = NULL;
2339   unsigned int len = 0;
2340
2341   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2342
2343   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2344     goto out;
2345
2346   /* Get destination ID */
2347   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2348   if (len > 128)
2349     tmp = NULL;
2350
2351   q = silc_calloc(1, sizeof(*q));
2352   q->server = server;
2353   q->sock = sock;
2354   q->signoff = tmp ? strdup(tmp) : NULL;
2355
2356   /* We quit the connection with little timeout */
2357   silc_task_register(server->timeout_queue, sock->sock,
2358                      silc_server_command_quit_cb, (void *)q,
2359                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2360
2361  out:
2362   silc_server_command_free(cmd);
2363 }
2364
2365 /* Server side of command KILL. This command is used by router operator
2366    to remove an client from the SILC Network temporarily. */
2367
2368 SILC_SERVER_CMD_FUNC(kill)
2369 {
2370   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2371   SilcServer server = cmd->server;
2372   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2373   SilcClientEntry remote_client;
2374   SilcClientID *client_id;
2375   unsigned char *tmp, *comment;
2376   unsigned int tmp_len, tmp_len2;
2377
2378   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2379
2380   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2381     goto out;
2382
2383   /* KILL command works only on router */
2384   if (server->server_type != SILC_ROUTER) {
2385     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2386                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2387     goto out;
2388   }
2389
2390   /* Check whether client has the permissions. */
2391   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2392     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2393                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2394     goto out;
2395   }
2396
2397   /* Get the client ID */
2398   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2399   if (!tmp) {
2400     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2401                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2402     goto out;
2403   }
2404   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2405   if (!client_id) {
2406     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2407                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2408     goto out;
2409   }
2410
2411   /* Get the client entry */
2412   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2413                                                 client_id, NULL);
2414   if (!remote_client) {
2415     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2416                                                   client_id, NULL);
2417     if (!remote_client) {
2418       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2419                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2420       goto out;
2421     }
2422   }
2423
2424   /* Get comment */
2425   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2426   if (tmp_len2 > 128)
2427     comment = NULL;
2428
2429   /* Send reply to the sender */
2430   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2431                                         SILC_STATUS_OK);
2432
2433   /* Send the KILL notify packets. First send it to the channel, then
2434      to our primary router and then directly to the client who is being
2435      killed right now. */
2436
2437   /* Send KILLED notify to the channels. It is not sent to the client
2438      as it will be sent differently destined directly to the client and not
2439      to the channel. */
2440   silc_server_send_notify_on_channels(server, remote_client, 
2441                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2442                                       comment ? 2 : 1,
2443                                       tmp, tmp_len,
2444                                       comment, comment ? tmp_len2 : 0);
2445
2446   /* Send KILLED notify to primary route */
2447   if (!server->standalone)
2448     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2449                                    remote_client->id, SILC_ID_CLIENT_LEN,
2450                                    comment);
2451
2452   /* Send KILLED notify to the client directly */
2453   silc_server_send_notify_killed(server, remote_client->connection ? 
2454                                  remote_client->connection : 
2455                                  remote_client->router->connection, FALSE,
2456                                  remote_client->id, SILC_ID_CLIENT_LEN,
2457                                  comment);
2458
2459   /* Remove the client from all channels. This generates new keys to the
2460      channels as well. */
2461   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2462                                    NULL, TRUE);
2463
2464   /* Remove the client entry, If it is locally connected then we will also
2465      disconnect the client here */
2466   if (remote_client->data.registered && remote_client->connection) {
2467     /* Remove locally conneted client */
2468     SilcSocketConnection sock = remote_client->connection;
2469     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2470     silc_server_close_connection(server, sock);
2471   } else {
2472     /* Remove remote client */
2473     if (!silc_idlist_del_client(server->global_list, remote_client))
2474       silc_idlist_del_client(server->local_list, remote_client);
2475   }
2476
2477  out:
2478   silc_server_command_free(cmd);
2479 }
2480
2481 /* Server side of command INFO. This sends information about us to 
2482    the client. If client requested specific server we will send the 
2483    command to that server. */
2484
2485 SILC_SERVER_CMD_FUNC(info)
2486 {
2487   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2488   SilcServer server = cmd->server;
2489   SilcBuffer packet, idp;
2490   char *dest_server, *server_info = NULL, *server_name;
2491   unsigned short ident = silc_command_get_ident(cmd->payload);
2492   SilcServerEntry entry = NULL;
2493
2494   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2495
2496   /* Get server name */
2497   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2498   if (!dest_server) {
2499     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2500                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2501     goto out;
2502   }
2503
2504   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2505     /* Send our reply */
2506     char info_string[256];
2507
2508     memset(info_string, 0, sizeof(info_string));
2509     snprintf(info_string, sizeof(info_string), 
2510              "location: %s server: %s admin: %s <%s>",
2511              server->config->admin_info->location,
2512              server->config->admin_info->server_type,
2513              server->config->admin_info->admin_name,
2514              server->config->admin_info->admin_email);
2515
2516     server_info = info_string;
2517     entry = server->id_entry;
2518   } else {
2519     /* Check whether we have this server cached */
2520     entry = silc_idlist_find_server_by_name(server->global_list,
2521                                             dest_server, NULL);
2522     if (!entry) {
2523       entry = silc_idlist_find_server_by_name(server->local_list,
2524                                               dest_server, NULL);
2525     }
2526
2527     if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2528       /* Send to the server */
2529       SilcBuffer tmpbuf;
2530       unsigned short old_ident;
2531
2532       old_ident = silc_command_get_ident(cmd->payload);
2533       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2534       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2535
2536       silc_server_packet_send(server, entry->connection,
2537                               SILC_PACKET_COMMAND, cmd->packet->flags,
2538                               tmpbuf->data, tmpbuf->len, TRUE);
2539
2540       /* Reprocess this packet after received reply from router */
2541       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2542                                   silc_command_get_ident(cmd->payload),
2543                                   silc_server_command_destructor,
2544                                   silc_server_command_info,
2545                                   silc_server_command_dup(cmd));
2546       cmd->pending = TRUE;
2547       silc_command_set_ident(cmd->payload, old_ident);
2548       silc_buffer_free(tmpbuf);
2549       return;
2550     }
2551
2552     if (!entry && !cmd->pending && !server->standalone) {
2553       /* Send to the primary router */
2554       SilcBuffer tmpbuf;
2555       unsigned short old_ident;
2556
2557       old_ident = silc_command_get_ident(cmd->payload);
2558       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2559       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2560
2561       silc_server_packet_send(server, server->router->connection,
2562                               SILC_PACKET_COMMAND, cmd->packet->flags,
2563                               tmpbuf->data, tmpbuf->len, TRUE);
2564
2565       /* Reprocess this packet after received reply from router */
2566       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2567                                   silc_command_get_ident(cmd->payload),
2568                                   silc_server_command_destructor,
2569                                   silc_server_command_info,
2570                                   silc_server_command_dup(cmd));
2571       cmd->pending = TRUE;
2572       silc_command_set_ident(cmd->payload, old_ident);
2573       silc_buffer_free(tmpbuf);
2574       return;
2575     }
2576   }
2577
2578   if (!entry) {
2579     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2580                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2581     goto out;
2582   }
2583
2584   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2585   if (!server_info)
2586     server_info = entry->server_info;
2587   server_name = dest_server;
2588
2589   /* Send the reply */
2590   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2591                                                 SILC_STATUS_OK, ident, 3,
2592                                                 2, idp->data, idp->len,
2593                                                 3, server_name, 
2594                                                 strlen(server_name),
2595                                                 4, server_info, 
2596                                                 strlen(server_info));
2597   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2598                           packet->data, packet->len, FALSE);
2599     
2600   silc_buffer_free(packet);
2601   silc_buffer_free(idp);
2602
2603  out:
2604   silc_server_command_free(cmd);
2605 }
2606
2607 /* Server side of command PING. This just replies to the ping. */
2608
2609 SILC_SERVER_CMD_FUNC(ping)
2610 {
2611   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2612   SilcServer server = cmd->server;
2613   SilcServerID *id;
2614   unsigned int len;
2615   unsigned char *tmp;
2616
2617   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2618
2619   /* Get Server ID */
2620   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2621   if (!tmp) {
2622     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2623                                           SILC_STATUS_ERR_NO_SERVER_ID);
2624     goto out;
2625   }
2626   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2627   if (!id)
2628     goto out;
2629
2630   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2631     /* Send our reply */
2632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2633                                           SILC_STATUS_OK);
2634   } else {
2635     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2636                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2637     goto out;
2638   }
2639
2640   silc_free(id);
2641
2642  out:
2643   silc_server_command_free(cmd);
2644 }
2645
2646 /* Internal routine to join channel. The channel sent to this function
2647    has been either created or resolved from ID lists. This joins the sent
2648    client to the channel. */
2649
2650 static void silc_server_command_join_channel(SilcServer server, 
2651                                              SilcServerCommandContext cmd,
2652                                              SilcChannelEntry channel,
2653                                              SilcClientID *client_id,
2654                                              int created,
2655                                              unsigned int umode)
2656 {
2657   SilcSocketConnection sock = cmd->sock;
2658   unsigned char *tmp;
2659   unsigned int tmp_len, user_count;
2660   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2661   SilcClientEntry client;
2662   SilcChannelClientEntry chl;
2663   SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
2664   unsigned short ident = silc_command_get_ident(cmd->payload);
2665   char check[512];
2666
2667   SILC_LOG_DEBUG(("Start"));
2668
2669   if (!channel)
2670     return;
2671
2672   /* Get the client entry */
2673   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2674     client = (SilcClientEntry)sock->user_data;
2675   } else {
2676     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2677                                            NULL);
2678     if (!client)
2679       goto out;
2680   }
2681
2682   /*
2683    * Check channel modes
2684    */
2685
2686   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2687     strncat(check, client->nickname, strlen(client->nickname));
2688     if (!strchr(client->nickname, '@')) {
2689       strncat(check, "@", 1);
2690       strncat(check, server->server_name, strlen(server->server_name));
2691     }
2692     strncat(check, "!", 1);
2693     strncat(check, client->username, strlen(client->username));
2694     if (!strchr(client->username, '@')) {
2695       strncat(check, "@", 1);
2696       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2697     }
2698   }
2699
2700   /* Check invite list if channel is invite-only channel */
2701   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
2702       channel->mode & SILC_CHANNEL_MODE_INVITE && channel->invite_list) {
2703     if (!silc_string_match(channel->invite_list, check)) {
2704       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2705                                             SILC_STATUS_ERR_NOT_INVITED);
2706       goto out;
2707     }
2708   }
2709
2710   /* Check ban list if it exists. If the client's nickname, server,
2711      username and/or hostname is in the ban list the access to the
2712      channel is denied. */
2713   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2714     if (silc_string_match(channel->ban_list, check)) {
2715       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2716                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2717       goto out;
2718     }
2719   }
2720
2721   /* Get passphrase */
2722   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2723   if (tmp) {
2724     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2725     memcpy(passphrase, tmp, tmp_len);
2726   }
2727   
2728   /* Check the channel passphrase if set. */
2729   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2730     if (!passphrase || memcmp(channel->passphrase, passphrase,
2731                               strlen(channel->passphrase))) {
2732       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2733                                             SILC_STATUS_ERR_BAD_PASSWORD);
2734       goto out;
2735     }
2736   }
2737
2738   /* Check user count limit if set. */
2739   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2740     if (silc_list_count(channel->user_list) + 1 > 
2741         channel->user_limit) {
2742       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2743                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2744       goto out;
2745     }
2746   }
2747
2748   /*
2749    * Client is allowed to join to the channel. Make it happen.
2750    */
2751
2752   /* Check whether the client already is on the channel */
2753   if (silc_server_client_on_channel(client, channel)) {
2754     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2755                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2756     goto out;
2757   }
2758
2759   /* Generate new channel key as protocol dictates */
2760   if ((!created && silc_list_count(channel->user_list) > 0) || 
2761       !channel->channel_key)
2762     silc_server_create_channel_key(server, channel, 0);
2763
2764   /* Send the channel key. This is broadcasted to the channel but is not
2765      sent to the client who is joining to the channel. */
2766   silc_server_send_channel_key(server, NULL, channel, 
2767                                server->server_type == SILC_ROUTER ? 
2768                                FALSE : !server->standalone);
2769
2770   /* Join the client to the channel by adding it to channel's user list.
2771      Add also the channel to client entry's channels list for fast cross-
2772      referencing. */
2773   chl = silc_calloc(1, sizeof(*chl));
2774   chl->mode = umode;
2775   chl->client = client;
2776   chl->channel = channel;
2777   silc_list_add(channel->user_list, chl);
2778   silc_list_add(client->channels, chl);
2779
2780   /* Get users on the channel */
2781   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2782                                    &user_count);
2783
2784   /* Encode Client ID Payload of the original client who wants to join */
2785   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2786
2787   /* Encode command reply packet */
2788   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2789   SILC_PUT32_MSB(channel->mode, mode);
2790   SILC_PUT32_MSB(created, tmp2);
2791   SILC_PUT32_MSB(user_count, tmp3);
2792   tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2793   keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2794                                          strlen(channel->channel_key->
2795                                                 cipher->name),
2796                                          channel->channel_key->cipher->name,
2797                                          channel->key_len / 8, channel->key);
2798   silc_free(tmp);
2799   reply = 
2800     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2801                                          SILC_STATUS_OK, ident, 13,
2802                                          2, channel->channel_name,
2803                                          strlen(channel->channel_name),
2804                                          3, chidp->data, chidp->len,
2805                                          4, clidp->data, clidp->len,
2806                                          5, mode, 4,
2807                                          6, tmp2, 4,
2808                                          7, keyp->data, keyp->len,
2809                                          8, channel->ban_list, 
2810                                          channel->ban_list ?
2811                                          strlen(channel->ban_list) : 0,
2812                                          9, channel->invite_list,
2813                                          channel->invite_list ?
2814                                          strlen(channel->invite_list) : 0,
2815                                          10, channel->topic,
2816                                          channel->topic ?
2817                                          strlen(channel->topic) : 0,
2818                                          11, channel->hmac->hmac->name,
2819                                          strlen(channel->hmac->hmac->name),
2820                                          12, tmp3, 4,
2821                                          13, user_list->data, user_list->len,
2822                                          14, mode_list->data, 
2823                                          mode_list->len);
2824
2825   /* Send command reply */
2826   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2827                           reply->data, reply->len, FALSE);
2828
2829   if (!cmd->pending) {
2830     /* Send JOIN notify to locally connected clients on the channel */
2831     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2832                                        SILC_NOTIFY_TYPE_JOIN, 2,
2833                                        clidp->data, clidp->len,
2834                                        chidp->data, chidp->len);
2835
2836     /* Send JOIN notify packet to our primary router */
2837     if (!server->standalone)
2838       silc_server_send_notify_join(server, server->router->connection,
2839                                    server->server_type == SILC_ROUTER ?
2840                                    TRUE : FALSE, channel, client->id,
2841                                    SILC_ID_CLIENT_LEN);
2842   }
2843
2844   silc_buffer_free(reply);
2845   silc_buffer_free(clidp);
2846   silc_buffer_free(chidp);
2847   silc_buffer_free(keyp);
2848   silc_buffer_free(user_list);
2849   silc_buffer_free(mode_list);
2850
2851  out:
2852   if (passphrase)
2853     silc_free(passphrase);
2854 }
2855
2856 /* Server side of command JOIN. Joins client into requested channel. If 
2857    the channel does not exist it will be created. */
2858
2859 SILC_SERVER_CMD_FUNC(join)
2860 {
2861   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2862   SilcServer server = cmd->server;
2863   int tmp_len;
2864   char *tmp, *channel_name = NULL, *cipher, *hmac;
2865   SilcChannelEntry channel;
2866   unsigned int umode = 0;
2867   int created = FALSE;
2868   SilcClientID *client_id;
2869
2870   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2871
2872   /* Get channel name */
2873   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2874   if (!tmp) {
2875     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2876                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2877     goto out;
2878   }
2879   channel_name = tmp;
2880
2881   if (strlen(channel_name) > 256)
2882     channel_name[255] = '\0';
2883
2884   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2885     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2886                                           SILC_STATUS_ERR_BAD_CHANNEL);
2887     silc_free(channel_name);
2888     goto out;
2889   }
2890
2891   /* Get Client ID of the client who is joining to the channel */
2892   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2893   if (!tmp) {
2894     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2895                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2896     goto out;
2897   }
2898   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2899   if (!client_id) {
2900     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2901                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2902     goto out;
2903   }
2904
2905   /* Get cipher and hmac name */
2906   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2907   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2908
2909   /* See if the channel exists */
2910   channel = silc_idlist_find_channel_by_name(server->local_list, 
2911                                              channel_name, NULL);
2912
2913   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2914     /* If this is coming from client the Client ID in the command packet must
2915        be same as the client's ID. */
2916     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2917       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2918       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2919         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2920                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2921         goto out;
2922       }
2923     }
2924
2925     if (!channel) {
2926       /* Channel not found */
2927
2928       /* If we are standalone server we don't have a router, we just create 
2929          the channel by ourselves. */
2930       if (server->standalone) {
2931         channel = silc_server_create_new_channel(server, server->id, cipher, 
2932                                                  hmac, channel_name, TRUE);
2933         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2934         created = TRUE;
2935
2936       } else {
2937
2938         /* The channel does not exist on our server. If we are normal server 
2939            we will send JOIN command to our router which will handle the
2940            joining procedure (either creates the channel if it doesn't exist 
2941            or joins the client to it). */
2942         if (server->server_type == SILC_SERVER) {
2943           SilcBuffer tmpbuf;
2944           unsigned short old_ident;
2945           
2946           old_ident = silc_command_get_ident(cmd->payload);
2947           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2948           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2949           
2950           /* Send JOIN command to our router */
2951           silc_server_packet_send(server, (SilcSocketConnection)
2952                                   server->router->connection,
2953                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2954                                   tmpbuf->data, tmpbuf->len, TRUE);
2955           
2956           /* Reprocess this packet after received reply from router */
2957           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2958                                       silc_command_get_ident(cmd->payload),
2959                                       silc_server_command_destructor,
2960                                       silc_server_command_join,
2961                                       silc_server_command_dup(cmd));
2962           cmd->pending = TRUE;
2963           return;
2964         }
2965         
2966         /* We are router and the channel does not seem exist so we will check
2967            our global list as well for the channel. */
2968         channel = silc_idlist_find_channel_by_name(server->global_list, 
2969                                                    channel_name, NULL);
2970         if (!channel) {
2971           /* Channel really does not exist, create it */
2972           channel = silc_server_create_new_channel(server, server->id, cipher, 
2973                                                    hmac, channel_name, TRUE);
2974           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2975           created = TRUE;
2976         }
2977       }
2978     }
2979   } else {
2980     if (!channel) {
2981       /* Channel not found */
2982
2983       /* If the command came from router and/or we are normal server then
2984          something went wrong with the joining as the channel was not found.
2985          We can't do anything else but ignore this. */
2986       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2987           server->server_type == SILC_SERVER)
2988         goto out;
2989       
2990       /* We are router and the channel does not seem exist so we will check
2991          our global list as well for the channel. */
2992       channel = silc_idlist_find_channel_by_name(server->global_list, 
2993                                                  channel_name, NULL);
2994       if (!channel) {
2995         /* Channel really does not exist, create it */
2996         channel = silc_server_create_new_channel(server, server->id, cipher, 
2997                                                  hmac, channel_name, TRUE);
2998         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2999         created = TRUE;
3000       }
3001     }
3002   }
3003
3004   /* If the channel does not have global users and is also empty it means the
3005      channel was created globally (by our router) and the client will be the
3006      channel founder and operator. */
3007   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3008     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3009     created = TRUE;             /* Created globally by our router */
3010   }
3011
3012   /* Join to the channel */
3013   silc_server_command_join_channel(server, cmd, channel, client_id,
3014                                    created, umode);
3015
3016   silc_free(client_id);
3017
3018  out:
3019   silc_server_command_free(cmd);
3020 }
3021
3022 /* Server side of command MOTD. Sends server's current "message of the
3023    day" to the client. */
3024
3025 SILC_SERVER_CMD_FUNC(motd)
3026 {
3027   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3028   SilcServer server = cmd->server;
3029   SilcBuffer packet, idp;
3030   char *motd, *dest_server;
3031   int motd_len;
3032   unsigned short ident = silc_command_get_ident(cmd->payload);
3033   
3034   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3035
3036   /* Get server name */
3037   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3038   if (!dest_server) {
3039     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3040                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3041     goto out;
3042   }
3043
3044   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3045     /* Send our MOTD */
3046
3047     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3048
3049     if (server->config && server->config->motd && 
3050         server->config->motd->motd_file) {
3051       /* Send motd */
3052       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3053       if (!motd)
3054         goto out;
3055       
3056       motd[motd_len] = 0;
3057       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3058                                                     SILC_STATUS_OK, ident, 2,
3059                                                     2, idp, idp->len,
3060                                                     3, motd, motd_len);
3061       goto out;
3062     } else {
3063       /* No motd */
3064       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3065                                                     SILC_STATUS_OK, ident, 1,
3066                                                     2, idp, idp->len);
3067     }
3068
3069     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3070                             packet->data, packet->len, FALSE);
3071     silc_buffer_free(packet);
3072     silc_buffer_free(idp);
3073   } else {
3074     SilcServerEntry entry;
3075
3076     /* Check whether we have this server cached */
3077     entry = silc_idlist_find_server_by_name(server->global_list,
3078                                             dest_server, NULL);
3079     if (!entry) {
3080       entry = silc_idlist_find_server_by_name(server->local_list,
3081                                               dest_server, NULL);
3082     }
3083
3084     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3085         entry && !entry->motd) {
3086       /* Send to the server */
3087       SilcBuffer tmpbuf;
3088       unsigned short old_ident;
3089
3090       old_ident = silc_command_get_ident(cmd->payload);
3091       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3092       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3093
3094       silc_server_packet_send(server, entry->connection,
3095                               SILC_PACKET_COMMAND, cmd->packet->flags,
3096                               tmpbuf->data, tmpbuf->len, TRUE);
3097
3098       /* Reprocess this packet after received reply from router */
3099       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3100                                   silc_command_get_ident(cmd->payload),
3101                                   silc_server_command_destructor,
3102                                   silc_server_command_motd,
3103                                   silc_server_command_dup(cmd));
3104       cmd->pending = TRUE;
3105       silc_command_set_ident(cmd->payload, old_ident);
3106       silc_buffer_free(tmpbuf);
3107       return;
3108     }
3109
3110     if (!entry && !cmd->pending && !server->standalone) {
3111       /* Send to the primary router */
3112       SilcBuffer tmpbuf;
3113       unsigned short old_ident;
3114
3115       old_ident = silc_command_get_ident(cmd->payload);
3116       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3117       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3118
3119       silc_server_packet_send(server, server->router->connection,
3120                               SILC_PACKET_COMMAND, cmd->packet->flags,
3121                               tmpbuf->data, tmpbuf->len, TRUE);
3122
3123       /* Reprocess this packet after received reply from router */
3124       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3125                                   silc_command_get_ident(cmd->payload),
3126                                   silc_server_command_destructor,
3127                                   silc_server_command_motd,
3128                                   silc_server_command_dup(cmd));
3129       cmd->pending = TRUE;
3130       silc_command_set_ident(cmd->payload, old_ident);
3131       silc_buffer_free(tmpbuf);
3132       return;
3133     }
3134
3135     if (!entry) {
3136       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3137                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3138       goto out;
3139     }
3140
3141     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3142
3143     if (entry->motd)
3144       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3145                                                     SILC_STATUS_OK, ident, 2,
3146                                                     2, idp, idp->len,
3147                                                     3, entry->motd,
3148                                                     strlen(entry->motd));
3149     else
3150       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3151                                                     SILC_STATUS_OK, ident, 1,
3152                                                     2, idp, idp->len);
3153
3154     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3155                             packet->data, packet->len, FALSE);
3156     silc_buffer_free(packet);
3157     silc_buffer_free(idp);
3158   }
3159
3160  out:
3161   silc_server_command_free(cmd);
3162 }
3163
3164 /* Server side of command UMODE. Client can use this command to set/unset
3165    user mode. Client actually cannot set itself to be as server/router
3166    operator so this can be used only to unset the modes. */
3167
3168 SILC_SERVER_CMD_FUNC(umode)
3169 {
3170   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3171   SilcServer server = cmd->server;
3172   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3173   SilcBuffer packet;
3174   unsigned char *tmp_mask;
3175   unsigned int mask;
3176   unsigned short ident = silc_command_get_ident(cmd->payload);
3177
3178   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3179     goto out;
3180
3181   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3182
3183   /* Get the client's mode mask */
3184   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3185   if (!tmp_mask) {
3186     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3187                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3188     goto out;
3189   }
3190   SILC_GET32_MSB(mask, tmp_mask);
3191
3192   /* 
3193    * Change the mode 
3194    */
3195
3196   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3197     /* Cannot operator mode */
3198     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3199                                           SILC_STATUS_ERR_PERM_DENIED);
3200     goto out;
3201   } else {
3202     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3203       /* Remove the server operator rights */
3204       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3205   }
3206
3207   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3208     /* Cannot operator mode */
3209     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3210                                           SILC_STATUS_ERR_PERM_DENIED);
3211     goto out;
3212   } else {
3213     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3214       /* Remove the router operator rights */
3215       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3216   }
3217
3218   /* Send UMODE change to primary router */
3219   if (!server->standalone)
3220     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3221                                   client->id, SILC_ID_CLIENT_LEN,
3222                                   client->mode);
3223
3224   /* Send command reply to sender */
3225   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3226                                                 SILC_STATUS_OK, ident, 1,
3227                                                 2, tmp_mask, 4);
3228   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3229                           packet->data, packet->len, FALSE);
3230   silc_buffer_free(packet);
3231
3232  out:
3233   silc_server_command_free(cmd);
3234 }
3235
3236 /* Checks that client has rights to add or remove channel modes. If any
3237    of the checks fails FALSE is returned. */
3238
3239 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3240                                    SilcChannelClientEntry client,
3241                                    unsigned int mode)
3242 {
3243   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3244   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3245
3246   /* Check whether has rights to change anything */
3247   if (!is_op && !is_fo)
3248     return FALSE;
3249
3250   /* Check whether has rights to change everything */
3251   if (is_op && is_fo)
3252     return TRUE;
3253
3254   /* We know that client is channel operator, check that they are not
3255      changing anything that requires channel founder rights. Rest of the
3256      modes are available automatically for channel operator. */
3257
3258   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3259     if (is_op && !is_fo)
3260       return FALSE;
3261   } else {
3262     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3263       if (is_op && !is_fo)
3264         return FALSE;
3265     }
3266   }
3267   
3268   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3269     if (is_op && !is_fo)
3270       return FALSE;
3271   } else {
3272     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3273       if (is_op && !is_fo)
3274         return FALSE;
3275     }
3276   }
3277
3278   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3279     if (is_op && !is_fo)
3280       return FALSE;
3281   } else {
3282     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3283       if (is_op && !is_fo)
3284         return FALSE;
3285     }
3286   }
3287   
3288   return TRUE;
3289 }
3290
3291 /* Server side command of CMODE. Changes channel mode */
3292
3293 SILC_SERVER_CMD_FUNC(cmode)
3294 {
3295   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3296   SilcServer server = cmd->server;
3297   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3298   SilcChannelID *channel_id;
3299   SilcChannelEntry channel;
3300   SilcChannelClientEntry chl;
3301   SilcBuffer packet, cidp;
3302   unsigned char *tmp, *tmp_id, *tmp_mask;
3303   unsigned int argc, mode_mask, tmp_len, tmp_len2;
3304   unsigned short ident = silc_command_get_ident(cmd->payload);
3305
3306   SILC_LOG_DEBUG(("Start"));
3307
3308   argc = silc_argument_get_arg_num(cmd->args);
3309   if (argc < 2) {
3310     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3311                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3312     goto out;
3313   }
3314   if (argc > 8) {
3315     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3316                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
3317     goto out;
3318   }
3319
3320   /* Get Channel ID */
3321   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3322   if (!tmp_id) {
3323     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3324                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3325     goto out;
3326   }
3327   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3328   if (!channel_id) {
3329     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3330                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3331     goto out;
3332   }
3333
3334   /* Get the channel mode mask */
3335   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3336   if (!tmp_mask) {
3337     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3338                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3339     goto out;
3340   }
3341   SILC_GET32_MSB(mode_mask, tmp_mask);
3342
3343   /* Get channel entry */
3344   channel = silc_idlist_find_channel_by_id(server->local_list, 
3345                                            channel_id, NULL);
3346   if (!channel) {
3347     channel = silc_idlist_find_channel_by_id(server->global_list, 
3348                                              channel_id, NULL);
3349     if (!channel) {
3350       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3351                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3352       goto out;
3353     }
3354   }
3355
3356   /* Check whether this client is on the channel */
3357   if (!silc_server_client_on_channel(client, channel)) {
3358     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3359                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3360     goto out;
3361   }
3362
3363   /* Get entry to the channel user list */
3364   silc_list_start(channel->user_list);
3365   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3366     if (chl->client == client)
3367       break;
3368
3369   /* Check that client has rights to change any requested channel modes */
3370   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3371     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3372                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3373     goto out;
3374   }
3375
3376   /*
3377    * Check the modes. Modes that requires nothing special operation are
3378    * not checked here.
3379    */
3380
3381   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3382     /* Channel uses private keys to protect traffic. Client(s) has set the
3383        key locally they want to use, server does not know that key. */
3384     /* Nothing interesting to do here now */
3385   } else {
3386     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3387       /* The mode is removed and we need to generate and distribute
3388          new channel key. Clients are not using private channel keys
3389          anymore after this. */
3390
3391       /* XXX Duplicated code, make own function for this!! LEAVE uses this
3392          as well */
3393
3394       /* Re-generate channel key */
3395       silc_server_create_channel_key(server, channel, 0);
3396       
3397       /* Encode channel key payload to be distributed on the channel */
3398       packet = 
3399         silc_channel_key_payload_encode(tmp_len2, tmp_id,
3400                                         strlen(channel->channel_key->
3401                                                cipher->name),
3402                                         channel->channel_key->cipher->name,
3403                                         channel->key_len / 8, channel->key);
3404       
3405       /* If we are normal server then we will send it to our router.  If we
3406          are router we will send it to all local servers that has clients on
3407          the channel */
3408       if (server->server_type == SILC_SERVER) {
3409         if (!server->standalone)
3410           silc_server_packet_send(server, 
3411                                   cmd->server->router->connection,
3412                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3413                                   packet->len, TRUE);
3414       } else {
3415         
3416       }
3417       
3418       /* Send to locally connected clients on the channel */
3419       silc_server_packet_send_local_channel(server, channel, 
3420                                             SILC_PACKET_CHANNEL_KEY, 0,
3421                                             packet->data, packet->len, FALSE);
3422       silc_buffer_free(packet);
3423     }
3424   }
3425   
3426   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3427     /* User limit is set on channel */
3428     unsigned int user_limit;
3429       
3430     /* Get user limit */
3431     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3432     if (!tmp) {
3433       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3434         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3435                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3436         goto out;
3437       }
3438     } else {
3439       SILC_GET32_MSB(user_limit, tmp);
3440       channel->user_limit = user_limit;
3441     }
3442   } else {
3443     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3444       /* User limit mode is unset. Remove user limit */
3445       channel->user_limit = 0;
3446   }
3447
3448   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3449     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3450       /* Passphrase has been set to channel */
3451       
3452       /* Get the passphrase */
3453       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3454       if (!tmp) {
3455         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3456                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3457         goto out;
3458       }
3459
3460       /* Save the passphrase */
3461       channel->passphrase = strdup(tmp);
3462     }
3463   } else {
3464     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3465       /* Passphrase mode is unset. remove the passphrase */
3466       if (channel->passphrase) {
3467         silc_free(channel->passphrase);
3468         channel->passphrase = NULL;
3469       }
3470     }
3471   }
3472
3473   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3474     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3475       /* Cipher to use protect the traffic */
3476       unsigned int key_len;
3477
3478       /* Get cipher */
3479       tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
3480       if (!tmp) {
3481         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3482                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3483         goto out;
3484       }
3485
3486       /* XXX Duplicated code, make own function for this!! */
3487     
3488       /* Delete old cipher and allocate the new one */
3489       silc_cipher_free(channel->channel_key);
3490       if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
3491         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3492                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3493         goto out;
3494       }
3495       key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
3496
3497       /* Re-generate channel key */
3498       silc_server_create_channel_key(server, channel, key_len);
3499     
3500       /* Encode channel key payload to be distributed on the channel */
3501       packet = 
3502         silc_channel_key_payload_encode(tmp_len2, tmp_id,
3503                                         strlen(channel->channel_key->
3504                                                cipher->name),
3505                                         channel->channel_key->cipher->name,
3506                                         channel->key_len / 8, channel->key);
3507     
3508       /* If we are normal server then we will send it to our router.  If we
3509          are router we will send it to all local servers that has clients on
3510          the channel */
3511       if (server->server_type == SILC_SERVER) {
3512         if (!server->standalone)
3513           silc_server_packet_send(server, 
3514                                   cmd->server->router->connection,
3515                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3516                                   packet->len, TRUE);
3517       } else {
3518         
3519       }
3520     
3521       /* Send to locally connected clients on the channel */
3522       silc_server_packet_send_local_channel(server, channel, 
3523                                             SILC_PACKET_CHANNEL_KEY, 0,
3524                                           packet->data, packet->len, FALSE);
3525       silc_buffer_free(packet);
3526     }
3527   } else {
3528     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3529       /* Cipher mode is unset. Remove the cipher and revert back to 
3530          default cipher */
3531       char *cipher = channel->channel_key->cipher->name;
3532
3533       /* Generate new cipher and key for the channel */
3534
3535       /* XXX Duplicated code, make own function for this!! */
3536
3537       /* Delete old cipher and allocate default one */
3538       silc_cipher_free(channel->channel_key);
3539       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3540         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3541                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3542         goto out;
3543       }
3544
3545       /* Re-generate channel key */
3546       silc_server_create_channel_key(server, channel, 0);
3547       
3548       /* Encode channel key payload to be distributed on the channel */
3549       packet = 
3550         silc_channel_key_payload_encode(tmp_len2, tmp_id,
3551                                         strlen(channel->channel_key->
3552                                                cipher->name),
3553                                         channel->channel_key->cipher->name,
3554                                         channel->key_len / 8, channel->key);
3555       
3556       /* If we are normal server then we will send it to our router.  If we
3557          are router we will send it to all local servers that has clients on
3558          the channel */
3559       if (server->server_type == SILC_SERVER) {
3560         if (!server->standalone)
3561           silc_server_packet_send(server, 
3562                                   cmd->server->router->connection,
3563                                   SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3564                                   packet->len, TRUE);
3565       } else {
3566         
3567       }
3568       
3569       /* Send to locally connected clients on the channel */
3570       silc_server_packet_send_local_channel(server, channel, 
3571                                             SILC_PACKET_CHANNEL_KEY, 0,
3572                                             packet->data, packet->len, FALSE);
3573       silc_buffer_free(packet);
3574     }
3575   }
3576
3577   /* Finally, set the mode */
3578   channel->mode = mode_mask;
3579
3580   /* Send CMODE_CHANGE notify */
3581   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3582   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3583                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
3584                                      cidp->data, cidp->len, 
3585                                      tmp_mask, tmp_len);
3586
3587   /* Set CMODE notify type to network */
3588   if (!server->standalone)
3589     silc_server_send_notify_cmode(server, server->router->connection,
3590                                   server->server_type == SILC_ROUTER ? 
3591                                   TRUE : FALSE, channel,
3592                                   mode_mask, client->id, SILC_ID_CLIENT_LEN);
3593
3594   /* Send command reply to sender */
3595   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3596                                                 SILC_STATUS_OK, ident, 1,
3597                                                 2, tmp_mask, 4);
3598   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3599                           packet->data, packet->len, FALSE);
3600     
3601   silc_buffer_free(packet);
3602   silc_free(channel_id);
3603   silc_free(cidp);
3604
3605  out:
3606   silc_server_command_free(cmd);
3607 }
3608
3609 /* Server side of CUMODE command. Changes client's mode on a channel. */
3610
3611 SILC_SERVER_CMD_FUNC(cumode)
3612 {
3613   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3614   SilcServer server = cmd->server;
3615   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3616   SilcChannelID *channel_id;
3617   SilcClientID *client_id;
3618   SilcChannelEntry channel;
3619   SilcClientEntry target_client;
3620   SilcChannelClientEntry chl;
3621   SilcBuffer packet, idp;
3622   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3623   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3624   int notify = FALSE;
3625   unsigned short ident = silc_command_get_ident(cmd->payload);
3626
3627   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3628
3629   /* Get Channel ID */
3630   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3631   if (!tmp_ch_id) {
3632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3633                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3634     goto out;
3635   }
3636   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3637   if (!channel_id) {
3638     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3639                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3640     goto out;
3641   }
3642
3643   /* Get channel entry */
3644   channel = silc_idlist_find_channel_by_id(server->local_list, 
3645                                            channel_id, NULL);
3646   if (!channel) {
3647     channel = silc_idlist_find_channel_by_id(server->global_list, 
3648                                              channel_id, NULL);
3649     if (!channel) {
3650       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3651                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3652       goto out;
3653     }
3654   }
3655
3656   /* Check whether sender is on the channel */
3657   if (!silc_server_client_on_channel(client, channel)) {
3658     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3659                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3660     goto out;
3661   }
3662
3663   /* Check that client has rights to change other's rights */
3664   silc_list_start(channel->user_list);
3665   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3666     if (chl->client == client) {
3667       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3668           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3669         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3670                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3671         goto out;
3672       }
3673
3674       sender_mask = chl->mode;
3675       break;
3676     }
3677   }
3678   
3679   /* Get the target client's channel mode mask */
3680   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3681   if (!tmp_mask) {
3682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3683                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3684     goto out;
3685   }
3686   SILC_GET32_MSB(target_mask, tmp_mask);
3687
3688   /* Get target Client ID */
3689   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3690   if (!tmp_id) {
3691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3692                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3693     goto out;
3694   }
3695   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3696   if (!client_id) {
3697     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3698                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3699     goto out;
3700   }
3701
3702   /* Get target client's entry */
3703   target_client = silc_idlist_find_client_by_id(server->local_list, 
3704                                                 client_id, NULL);
3705   if (!target_client) {
3706     target_client = silc_idlist_find_client_by_id(server->global_list, 
3707                                                   client_id, NULL);
3708   }
3709
3710   /* Check whether target client is on the channel */
3711   if (!silc_server_client_on_channel(target_client, channel)) {
3712     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3713                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3714     goto out;
3715   }
3716
3717   /* Get entry to the channel user list */
3718   silc_list_start(channel->user_list);
3719   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3720     if (chl->client == target_client)
3721       break;
3722
3723   /* 
3724    * Change the mode 
3725    */
3726
3727   /* If the target client is founder, no one else can change their mode
3728      but themselves. */
3729   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3731                                           SILC_STATUS_ERR_NOT_YOU);
3732     goto out;
3733   }
3734
3735   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3736     /* Cannot promote anyone to channel founder */
3737     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3738                                           SILC_STATUS_ERR_NOT_YOU);
3739     goto out;
3740   } else {
3741     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3742       if (target_client == client) {
3743         /* Remove channel founder rights from itself */
3744         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3745         notify = TRUE;
3746       } else {
3747         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3748                                               SILC_STATUS_ERR_NOT_YOU);
3749         goto out;
3750       }
3751     }
3752   }
3753
3754   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3755     /* Promote to operator */
3756     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3757       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3758       notify = TRUE;
3759     }
3760   } else {
3761     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3762       /* Demote to normal user */
3763       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3764       notify = TRUE;
3765     }
3766   }
3767
3768   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3769
3770   /* Send notify to channel, notify only if mode was actually changed. */
3771   if (notify) {
3772     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3773                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3774                                        idp->data, idp->len,
3775                                        tmp_mask, 4, 
3776                                        tmp_id, tmp_len);
3777
3778     /* Set CUMODE notify type to network */
3779     if (!server->standalone)
3780       silc_server_send_notify_cumode(server, server->router->connection,
3781                                      server->server_type == SILC_ROUTER ? 
3782                                      TRUE : FALSE, channel,
3783                                      target_mask, client->id, 
3784                                      SILC_ID_CLIENT_LEN,
3785                                      target_client->id, 
3786                                      SILC_ID_CLIENT_LEN);
3787   }
3788
3789   /* Send command reply to sender */
3790   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3791                                                 SILC_STATUS_OK, ident, 2,
3792                                                 2, tmp_mask, 4,
3793                                                 3, tmp_id, tmp_len);
3794   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3795                           packet->data, packet->len, FALSE);
3796     
3797   silc_buffer_free(packet);
3798   silc_free(channel_id);
3799   silc_free(client_id);
3800   silc_buffer_free(idp);
3801
3802  out:
3803   silc_server_command_free(cmd);
3804 }
3805
3806 /* Server side of KICK command. Kicks client out of channel. */
3807
3808 SILC_SERVER_CMD_FUNC(kick)
3809 {
3810   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3811   SilcServer server = cmd->server;
3812   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3813   SilcClientEntry target_client;
3814   SilcChannelID *channel_id;
3815   SilcClientID *client_id;
3816   SilcChannelEntry channel;
3817   SilcChannelClientEntry chl;
3818   SilcBuffer idp;
3819   unsigned int tmp_len;
3820   unsigned char *tmp, *comment;
3821
3822   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3823
3824   /* Get Channel ID */
3825   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3826   if (!tmp) {
3827     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3828                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3829     goto out;
3830   }
3831   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3832   if (!channel_id) {
3833     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3834                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3835     goto out;
3836   }
3837
3838   /* Get channel entry */
3839   channel = silc_idlist_find_channel_by_id(server->local_list, 
3840                                            channel_id, NULL);
3841   if (!channel) {
3842     channel = silc_idlist_find_channel_by_id(server->local_list, 
3843                                              channel_id, NULL);
3844     if (!channel) {
3845       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3846                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3847       goto out;
3848     }
3849   }
3850
3851   /* Check whether sender is on the channel */
3852   if (!silc_server_client_on_channel(client, channel)) {
3853     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3854                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3855     goto out;
3856   }
3857
3858   /* Check that the kicker is channel operator or channel founder */
3859   silc_list_start(channel->user_list);
3860   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3861     if (chl->client == client) {
3862       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3863         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3864                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3865         goto out;
3866       }
3867       break;
3868     }
3869   }
3870   
3871   /* Get target Client ID */
3872   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3873   if (!tmp) {
3874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3875                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3876     goto out;
3877   }
3878   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3879   if (!client_id) {
3880     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3881                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3882     goto out;
3883   }
3884
3885   /* Get target client's entry */
3886   target_client = silc_idlist_find_client_by_id(server->local_list, 
3887                                                 client_id, NULL);
3888   if (!target_client) {
3889     target_client = silc_idlist_find_client_by_id(server->global_list, 
3890                                                   client_id, NULL);
3891   }
3892
3893   /* Check that the target client is not channel founder. Channel founder
3894      cannot be kicked from the channel. */
3895   silc_list_start(channel->user_list);
3896   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3897     if (chl->client == target_client) {
3898       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3899         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3900                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3901         goto out;
3902       }
3903       break;
3904     }
3905   }
3906   
3907   /* Check whether target client is on the channel */
3908   if (!silc_server_client_on_channel(target_client, channel)) {
3909     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3910                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3911     goto out;
3912   }
3913
3914   /* Get comment */
3915   tmp_len = 0;
3916   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3917   if (tmp_len > 128)
3918     comment = NULL;
3919
3920   /* Send command reply to sender */
3921   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
3922                                         SILC_STATUS_OK);
3923
3924   /* Send KICKED notify to local clients on the channel */
3925   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3926   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3927                                      SILC_NOTIFY_TYPE_KICKED, 
3928                                      comment ? 2 : 1,
3929                                      idp->data, idp->len,
3930                                      comment, comment ? strlen(comment) : 0);
3931   silc_buffer_free(idp);
3932
3933   /* Remove the client from the channel. If the channel does not exist
3934      after removing the client then the client kicked itself off the channel
3935      and we don't have to send anything after that. */
3936   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
3937                                            target_client, FALSE))
3938     goto out;
3939
3940   /* Send KICKED notify to primary route */
3941   if (!server->standalone)
3942     silc_server_send_notify_kicked(server, server->router->connection,
3943                                    server->server_type == SILC_ROUTER ?
3944                                    TRUE : FALSE, channel,
3945                                    target_client->id, SILC_ID_CLIENT_LEN,
3946                                    comment);
3947
3948   /* Re-generate channel key */
3949   silc_server_create_channel_key(server, channel, 0);
3950
3951   /* Send the channel key to the channel. The key of course is not sent
3952      to the client who was kicked off the channel. */
3953   silc_server_send_channel_key(server, target_client->connection, channel, 
3954                                server->server_type == SILC_ROUTER ? 
3955                                FALSE : !server->standalone);
3956
3957  out:
3958   silc_server_command_free(cmd);
3959 }
3960
3961 /* Server side of OPER command. Client uses this comand to obtain server
3962    operator privileges to this server/router. */
3963
3964 SILC_SERVER_CMD_FUNC(oper)
3965 {
3966   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3967   SilcServer server = cmd->server;
3968   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3969   unsigned char *username, *auth;
3970   unsigned int tmp_len;
3971   SilcServerConfigSectionAdminConnection *admin;
3972   SilcIDListData idata = (SilcIDListData)client;
3973
3974   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3975
3976   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3977     goto out;
3978
3979   /* Get the username */
3980   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3981   if (!username) {
3982     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3983                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3984     goto out;
3985   }
3986
3987   /* Get the admin configuration */
3988   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3989                                         username, client->nickname);
3990   if (!admin) {
3991     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3992                                           username, client->nickname);
3993     if (!admin) {
3994       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3995                                             SILC_STATUS_ERR_AUTH_FAILED);
3996       goto out;
3997     }
3998   }
3999
4000   /* Get the authentication payload */
4001   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4002   if (!auth) {
4003     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4004                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4005     goto out;
4006   }
4007
4008   /* Verify the authentication data */
4009   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4010                              admin->auth_data, admin->auth_data_len,
4011                              idata->hash, client->id, SILC_ID_CLIENT)) {
4012     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4013                                           SILC_STATUS_ERR_AUTH_FAILED);
4014     goto out;
4015   }
4016
4017   /* Client is now server operator */
4018   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4019
4020   /* Send UMODE change to primary router */
4021   if (!server->standalone)
4022     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4023                                   client->id, SILC_ID_CLIENT_LEN,
4024                                   client->mode);
4025
4026   /* Send reply to the sender */
4027   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4028                                         SILC_STATUS_OK);
4029
4030  out:
4031   silc_server_command_free(cmd);
4032 }
4033
4034 /* Server side of SILCOPER command. Client uses this comand to obtain router
4035    operator privileges to this router. */
4036
4037 SILC_SERVER_CMD_FUNC(silcoper)
4038 {
4039   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4040   SilcServer server = cmd->server;
4041   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4042   unsigned char *username, *auth;
4043   unsigned int tmp_len;
4044   SilcServerConfigSectionAdminConnection *admin;
4045   SilcIDListData idata = (SilcIDListData)client;
4046
4047   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4048
4049   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4050     goto out;
4051
4052   /* Get the username */
4053   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4054   if (!username) {
4055     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4056                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4057     goto out;
4058   }
4059
4060   /* Get the admin configuration */
4061   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4062                                         username, client->nickname);
4063   if (!admin) {
4064     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4065                                           username, client->nickname);
4066     if (!admin) {
4067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4068                                             SILC_STATUS_ERR_AUTH_FAILED);
4069       goto out;
4070     }
4071   }
4072
4073   /* Get the authentication payload */
4074   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4075   if (!auth) {
4076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4077                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4078     goto out;
4079   }
4080
4081   /* Verify the authentication data */
4082   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4083                              admin->auth_data, admin->auth_data_len,
4084                              idata->hash, client->id, SILC_ID_CLIENT)) {
4085     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4086                                           SILC_STATUS_ERR_AUTH_FAILED);
4087     goto out;
4088   }
4089
4090   /* Client is now router operator */
4091   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4092
4093   /* Send UMODE change to primary router */
4094   if (!server->standalone)
4095     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4096                                   client->id, SILC_ID_CLIENT_LEN,
4097                                   client->mode);
4098
4099   /* Send reply to the sender */
4100   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4101                                         SILC_STATUS_OK);
4102
4103  out:
4104   silc_server_command_free(cmd);
4105 }
4106
4107 /* Server side command of CONNECT. Connects us to the specified remote
4108    server or router. */
4109
4110 SILC_SERVER_CMD_FUNC(connect)
4111 {
4112   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4113   SilcServer server = cmd->server;
4114   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4115   unsigned char *tmp, *host;
4116   unsigned int tmp_len;
4117   unsigned int port = SILC_PORT;
4118
4119   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4120
4121   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4122     goto out;
4123
4124   /* Check whether client has the permissions. */
4125   if (client->mode == SILC_UMODE_NONE) {
4126     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4127                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4128     goto out;
4129   }
4130
4131   if (server->server_type == SILC_ROUTER && 
4132       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4133     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4134                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4135     goto out;
4136   }
4137
4138   /* Get the remote server */
4139   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4140   if (!host) {
4141     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4142                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4143     goto out;
4144   }
4145
4146   /* Get port */
4147   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4148   if (tmp)
4149     SILC_GET32_MSB(port, tmp);
4150
4151   /* Create the connection. It is done with timeout and is async. */
4152   silc_server_create_connection(server, host, port);
4153
4154   /* Send reply to the sender */
4155   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4156                                         SILC_STATUS_OK);
4157
4158  out:
4159   silc_server_command_free(cmd);
4160 }
4161
4162 SILC_SERVER_CMD_FUNC(restart)
4163 {
4164 }
4165
4166 /* Server side command of CLOSE. Closes connection to a specified server. */
4167  
4168 SILC_SERVER_CMD_FUNC(close)
4169 {
4170   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4171   SilcServer server = cmd->server;
4172   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4173   SilcServerEntry server_entry;
4174   SilcSocketConnection sock;
4175   unsigned char *tmp;
4176   unsigned int tmp_len;
4177   unsigned char *name;
4178   unsigned int port = SILC_PORT;
4179
4180   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4181
4182   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4183     goto out;
4184
4185   /* Check whether client has the permissions. */
4186   if (client->mode == SILC_UMODE_NONE) {
4187     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4188                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4189     goto out;
4190   }
4191
4192   /* Get the remote server */
4193   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4194   if (!name) {
4195     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4196                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4197     goto out;
4198   }
4199
4200   /* Get port */
4201   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4202   if (tmp)
4203     SILC_GET32_MSB(port, tmp);
4204
4205   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4206                                                  name, port, NULL);
4207   if (!server_entry) {
4208     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4209                                           SILC_STATUS_ERR_NO_SERVER_ID);
4210     goto out;
4211   }
4212
4213   /* Send reply to the sender */
4214   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4215                                         SILC_STATUS_OK);
4216
4217   /* Close the connection to the server */
4218   sock = (SilcSocketConnection)server_entry->connection;
4219   silc_server_free_sock_user_data(server, sock);
4220   silc_server_close_connection(server, sock);
4221   
4222  out:
4223   silc_server_command_free(cmd);
4224 }
4225
4226 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4227    active connections. */
4228  
4229 SILC_SERVER_CMD_FUNC(shutdown)
4230 {
4231   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4232   SilcServer server = cmd->server;
4233   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4234
4235   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4236
4237   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4238     goto out;
4239
4240   /* Check whether client has the permission. */
4241   if (client->mode == SILC_UMODE_NONE) {
4242     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4243                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4244     goto out;
4245   }
4246
4247   /* Send reply to the sender */
4248   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4249                                         SILC_STATUS_OK);
4250
4251   /* Then, gracefully, or not, bring the server down. */
4252   silc_server_stop(server);
4253   exit(0);
4254
4255  out:
4256   silc_server_command_free(cmd);
4257 }
4258  
4259 /* Server side command of LEAVE. Removes client from a channel. */
4260
4261 SILC_SERVER_CMD_FUNC(leave)
4262 {
4263   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4264   SilcServer server = cmd->server;
4265   SilcSocketConnection sock = cmd->sock;
4266   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4267   SilcChannelID *id;
4268   SilcChannelEntry channel;
4269   SilcBuffer packet;
4270   unsigned int i, len;
4271   unsigned char *tmp;
4272
4273   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4274
4275   /* Get Channel ID */
4276   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4277   if (!tmp) {
4278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4279                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4280     goto out;
4281   }
4282   id = silc_id_payload_parse_id(tmp, len);
4283   if (!id) {
4284     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4285                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4286     goto out;
4287   }
4288
4289   /* Get channel entry */
4290   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4291   if (!channel) {
4292     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4293     if (!channel) {
4294       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4295                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4296       goto out;
4297     }
4298   }
4299
4300   /* Check whether this client is on the channel */
4301   if (!silc_server_client_on_channel(id_entry, channel)) {
4302     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4303                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4304     goto out;
4305   }
4306
4307   /* Notify routers that they should remove this client from their list
4308      of clients on the channel. Send LEAVE notify type. */
4309   if (!server->standalone)
4310     silc_server_send_notify_leave(server, server->router->connection,
4311                                   server->server_type == SILC_ROUTER ?
4312                                   TRUE : FALSE, channel, id_entry->id,
4313                                   SILC_ID_CLIENT_LEN);
4314
4315   /* Remove client from channel */
4316   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4317                                           TRUE);
4318   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4319                                         SILC_STATUS_OK);
4320
4321   /* If the channel does not exist anymore we won't send anything */
4322   if (!i)
4323     goto out;
4324
4325   /* Re-generate channel key */
4326   silc_server_create_channel_key(server, channel, 0);
4327
4328   /* Encode channel key payload to be distributed on the channel */
4329   packet = 
4330     silc_channel_key_payload_encode(len, tmp,
4331                                     strlen(channel->channel_key->cipher->name),
4332                                     channel->channel_key->cipher->name,
4333                                     channel->key_len / 8, channel->key);
4334
4335   /* If we are normal server then we will send it to our router.  If we
4336      are router we will send it to all local servers that has clients on
4337      the channel */
4338   if (server->server_type == SILC_SERVER) {
4339     if (!server->standalone)
4340       silc_server_packet_send(server, 
4341                               cmd->server->router->connection,
4342                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4343                               packet->len, FALSE);
4344   } else {
4345
4346   }
4347
4348   /* Send to locally connected clients on the channel */
4349   silc_server_packet_send_local_channel(server, channel, 
4350                                         SILC_PACKET_CHANNEL_KEY, 0,
4351                                         packet->data, packet->len, FALSE);
4352
4353   silc_buffer_free(packet);
4354   silc_free(id);
4355
4356  out:
4357   silc_server_command_free(cmd);
4358 }
4359
4360 /* Server side of command USERS. Resolves clients and their USERS currently
4361    joined on the requested channel. The list of Client ID's and their modes
4362    on the channel is sent back. */
4363
4364 SILC_SERVER_CMD_FUNC(users)
4365 {
4366   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4367   SilcServer server = cmd->server;
4368   SilcChannelEntry channel;
4369   SilcChannelID *id;
4370   SilcBuffer packet;
4371   unsigned char *channel_id;
4372   unsigned int channel_id_len;
4373   SilcBuffer client_id_list;
4374   SilcBuffer client_mode_list;
4375   unsigned char lc[4];
4376   unsigned int list_count = 0;
4377   unsigned short ident = silc_command_get_ident(cmd->payload);
4378
4379   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4380
4381   /* Get Channel ID */
4382   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4383   if (!channel_id) {
4384     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4385                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4386     goto out;
4387   }
4388   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4389   if (!id) {
4390     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4391                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4392     goto out;
4393   }
4394
4395   /* If we are server and we don't know about this channel we will send
4396      the command to our router. If we know about the channel then we also
4397      have the list of users already. */
4398   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4399   if (!channel) {
4400     if (server->server_type == SILC_SERVER && !server->standalone &&
4401         !cmd->pending) {
4402       SilcBuffer tmpbuf;
4403       
4404       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4405       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4406       
4407       /* Send USERS command */
4408       silc_server_packet_send(server, server->router->connection,
4409                               SILC_PACKET_COMMAND, cmd->packet->flags,
4410                               tmpbuf->data, tmpbuf->len, TRUE);
4411       
4412       /* Reprocess this packet after received reply */
4413       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4414                                   silc_command_get_ident(cmd->payload),
4415                                   silc_server_command_destructor,
4416                                   silc_server_command_users,
4417                                   silc_server_command_dup(cmd));
4418       cmd->pending = TRUE;
4419       silc_command_set_ident(cmd->payload, ident);
4420       
4421       silc_buffer_free(tmpbuf);
4422       silc_free(id);
4423       return;
4424     }
4425
4426     /* We are router and we will check the global list as well. */
4427     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4428     if (!channel) {
4429       /* Channel really does not exist */
4430       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4431                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4432       goto out;
4433     }
4434   }
4435
4436   /* Get the users list */
4437   silc_server_get_users_on_channel(server, channel, &client_id_list,
4438                                    &client_mode_list, &list_count);
4439
4440   /* List count */
4441   SILC_PUT32_MSB(list_count, lc);
4442
4443   /* Send reply */
4444   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4445                                                 SILC_STATUS_OK, ident, 4,
4446                                                 2, channel_id, channel_id_len,
4447                                                 3, lc, 4,
4448                                                 4, client_id_list->data,
4449                                                 client_id_list->len,
4450                                                 5, client_mode_list->data,
4451                                                 client_mode_list->len);
4452   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4453                           packet->data, packet->len, FALSE);
4454     
4455   silc_buffer_free(packet);
4456   silc_buffer_free(client_id_list);
4457   silc_buffer_free(client_mode_list);
4458   silc_free(id);
4459
4460  out:
4461   silc_server_command_free(cmd);
4462 }
4463
4464 /* Server side of command BAN. This is used to manage the ban list of the
4465    channel. To add clients and remove clients from the ban list. */
4466
4467 SILC_SERVER_CMD_FUNC(ban)
4468 {
4469   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4470   SilcServer server = cmd->server;
4471   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4472   SilcBuffer packet;
4473   SilcChannelEntry channel;
4474   SilcChannelClientEntry chl;
4475   SilcChannelID *channel_id = NULL;
4476   unsigned char *id, *add, *del;
4477   unsigned int id_len, tmp_len;
4478   unsigned short ident = silc_command_get_ident(cmd->payload);
4479
4480   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4481     goto out;
4482
4483   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4484
4485   /* Get Channel ID */
4486   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4487   if (id) {
4488     channel_id = silc_id_payload_parse_id(id, id_len);
4489     if (!channel_id) {
4490       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4491                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4492       goto out;
4493     }
4494   }
4495
4496   /* Get channel entry. The server must know about the channel since the
4497      client is expected to be on the channel. */
4498   channel = silc_idlist_find_channel_by_id(server->local_list, 
4499                                            channel_id, NULL);
4500   if (!channel) {
4501     channel = silc_idlist_find_channel_by_id(server->global_list, 
4502                                              channel_id, NULL);
4503     if (!channel) {
4504       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4505                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4506       goto out;
4507     }
4508   }
4509
4510   /* Check whether this client is on the channel */
4511   if (!silc_server_client_on_channel(client, channel)) {
4512     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4513                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4514     goto out;
4515   }
4516
4517   /* Get entry to the channel user list */
4518   silc_list_start(channel->user_list);
4519   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4520     if (chl->client == client)
4521       break;
4522
4523   /* The client must be at least channel operator. */
4524   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4525     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4526                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4527     goto out;
4528   }
4529
4530   /* Get the new ban and add it to the ban list */
4531   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4532   if (add && strlen(add) == tmp_len) {
4533     if (!channel->ban_list)
4534       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4535     else
4536       channel->ban_list = silc_realloc(channel->ban_list, 
4537                                        sizeof(*channel->ban_list) * 
4538                                        (tmp_len + 
4539                                         strlen(channel->ban_list) + 2));
4540     if (add[tmp_len - 1] == ',')
4541       add[tmp_len - 1] = '\0';
4542
4543     strncat(channel->ban_list, add, tmp_len);
4544     strncat(channel->ban_list, ",", 1);
4545   }
4546
4547   /* Get the ban to be removed and remove it from the list */
4548   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4549   if (del && channel->ban_list) {
4550     char *start, *end, *n;
4551
4552     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4553       silc_free(channel->ban_list);
4554       channel->ban_list = NULL;
4555       goto out0;
4556     }
4557
4558     start = strstr(channel->ban_list, del);
4559     if (start && strlen(start) >= tmp_len) {
4560       end = start + tmp_len;
4561       n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4562       strncat(n, channel->ban_list, start - channel->ban_list);
4563       strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4564                            end) - 1);
4565       silc_free(channel->ban_list);
4566       channel->ban_list = n;
4567     }
4568   }
4569
4570  out0:
4571
4572   /* Send the BAN notify type to our primary router. */
4573   if (!server->standalone && (add || del))
4574     silc_server_send_notify_ban(server, server->router->connection,
4575                                 server->server_type == SILC_ROUTER ?
4576                                 TRUE : FALSE, channel, add, del);
4577
4578   /* Send the reply back to the client */
4579   if (channel->ban_list)
4580     packet = 
4581       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4582                                            SILC_STATUS_OK, ident, 2,
4583                                            2, id, id_len,
4584                                            3, channel->ban_list, 
4585                                            strlen(channel->ban_list) - 1);
4586   else
4587     packet = 
4588       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4589                                            SILC_STATUS_OK, ident, 1,
4590                                            2, id, id_len);
4591
4592   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4593                           packet->data, packet->len, FALSE);
4594     
4595   silc_buffer_free(packet);
4596
4597  out:
4598   if (channel_id)
4599     silc_free(channel_id);
4600   silc_server_command_free(cmd);
4601 }