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   char nh[256], uh[256];
1346   SilcSocketConnection hsock;
1347
1348   status = SILC_STATUS_OK;
1349   if (clients_count > 1)
1350     status = SILC_STATUS_LIST_START;
1351
1352   for (i = 0; i < clients_count; i++) {
1353     entry = clients[i];
1354
1355     if (entry->data.registered == FALSE) {
1356       if (clients_count == 1) {
1357         SilcBuffer idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1358         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1359                                              SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1360                                              2, idp->data, idp->len);
1361         silc_buffer_free(idp);
1362       }
1363       continue;
1364     }
1365
1366     if (count && i - 1 == count)
1367       break;
1368
1369     if (i >= 1)
1370       status = SILC_STATUS_LIST_ITEM;
1371
1372     if (clients_count > 1 && i == clients_count - 1)
1373       status = SILC_STATUS_LIST_END;
1374
1375     /* Send IDENTIFY reply */
1376     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1377     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1378     
1379     memset(uh, 0, sizeof(uh));
1380     memset(nh, 0, sizeof(nh));
1381       
1382     strncat(nh, entry->nickname, strlen(entry->nickname));
1383     if (!strchr(entry->nickname, '@')) {
1384       strncat(nh, "@", 1);
1385       len = entry->router ? strlen(entry->router->server_name) :
1386         strlen(server->server_name);
1387       strncat(nh, entry->router ? entry->router->server_name :
1388               server->server_name, len);
1389     }
1390       
1391     if (!entry->username) {
1392       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1393                                                     status, ident, 2,
1394                                                     2, idp->data, idp->len, 
1395                                                     3, nh, strlen(nh));
1396     } else {
1397       strncat(uh, entry->username, strlen(entry->username));
1398       if (!strchr(entry->username, '@')) {
1399         strncat(uh, "@", 1);
1400         hsock = (SilcSocketConnection)entry->connection;
1401         len = strlen(hsock->hostname);
1402         strncat(uh, hsock->hostname, len);
1403       }
1404       
1405       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1406                                                     status, ident, 3,
1407                                                     2, idp->data, idp->len, 
1408                                                     3, nh, strlen(nh),
1409                                                     4, uh, strlen(uh));
1410     }
1411       
1412     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1413                             0, packet->data, packet->len, FALSE);
1414     
1415     silc_buffer_free(packet);
1416     silc_buffer_free(idp);
1417   }
1418 }
1419
1420 static int
1421 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1422 {
1423   SilcServer server = cmd->server;
1424   char *nick = NULL, *server_name = NULL;
1425   int count = 0, clients_count = 0; 
1426   SilcClientEntry *clients = NULL, entry;
1427   SilcClientID **client_id = NULL;
1428   unsigned int client_id_count = 0;
1429   int i, ret = 0;
1430
1431   /* Protocol dictates that we must always send the received IDENTIFY request
1432      to our router if we are normal server, so let's do it now unless we
1433      are standalone. We will not send any replies to the client until we
1434      have received reply from the router. */
1435   if (server->server_type == SILC_SERVER && 
1436       !cmd->pending && !server->standalone) {
1437     SilcBuffer tmpbuf;
1438     unsigned short old_ident;
1439
1440     old_ident = silc_command_get_ident(cmd->payload);
1441     silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1442     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1443
1444     /* Send IDENTIFY command to our router */
1445     silc_server_packet_send(server, (SilcSocketConnection)
1446                             server->router->connection,
1447                             SILC_PACKET_COMMAND, cmd->packet->flags,
1448                             tmpbuf->data, tmpbuf->len, TRUE);
1449
1450     /* Reprocess this packet after received reply from router */
1451     silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1452                                 silc_command_get_ident(cmd->payload),
1453                                 silc_server_command_destructor,
1454                                 silc_server_command_identify,
1455                                 silc_server_command_dup(cmd));
1456     cmd->pending = TRUE;
1457
1458     silc_command_set_ident(cmd->payload, old_ident);
1459
1460     silc_buffer_free(tmpbuf);
1461     ret = -1;
1462     goto out;
1463   }
1464
1465   /* We are ready to process the command request. Let's search for the
1466      requested client and send reply to the requesting client. */
1467
1468   /* Parse the IDENTIFY request */
1469   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1470                                        &nick, &server_name, &count,
1471                                        SILC_COMMAND_IDENTIFY))
1472     return 0;
1473
1474   /* Get all clients matching that ID or nickname from local list */
1475   if (client_id_count) { 
1476     /* Check all Client ID's received in the command packet */
1477     for (i = 0; i < client_id_count; i++) {
1478       entry = silc_idlist_find_client_by_id(server->local_list, 
1479                                             client_id[i], NULL);
1480       if (entry) {
1481         clients = silc_realloc(clients, sizeof(*clients) * 
1482                                (clients_count + 1));
1483         clients[clients_count++] = entry;
1484       }
1485     }
1486   } else {
1487     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1488                                                   nick, server_name,
1489                                                   &clients_count);
1490     if (!clients)
1491       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1492                                                 nick, server->md5hash,
1493                                                 &clients_count);
1494   }
1495   
1496   /* Check global list as well */
1497   if (!clients) {
1498     if (client_id_count) {
1499       /* Check all Client ID's received in the command packet */
1500       for (i = 0; i < client_id_count; i++) {
1501         entry = silc_idlist_find_client_by_id(server->global_list, 
1502                                               client_id[i], NULL);
1503         if (entry) {
1504           clients = silc_realloc(clients, sizeof(*clients) * 
1505                                  (clients_count + 1));
1506           clients[clients_count++] = entry;
1507         }
1508       }
1509     } else {
1510       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1511                                                     nick, server_name,
1512                                                     &clients_count);
1513       if (!clients)
1514         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1515                                                   nick, server->md5hash,
1516                                                   &clients_count);
1517     }
1518   }
1519   
1520   if (!clients) {
1521     /* Such a client really does not exist in the SILC network. */
1522     if (!client_id_count) {
1523       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1524                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1525                                            3, nick, strlen(nick));
1526     } else {
1527       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1528       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1529                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1530                                            2, idp->data, idp->len);
1531       silc_buffer_free(idp);
1532     }
1533     goto out;
1534   }
1535
1536   /* Check that all mandatory fields are present and request those data
1537      from the server who owns the client if necessary. */
1538   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1539     ret = -1;
1540     goto out;
1541   }
1542
1543   /* Send the command reply to the client */
1544   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1545
1546  out:
1547   if (client_id_count) {
1548     for (i = 0; i < client_id_count; i++)
1549       silc_free(client_id[i]);
1550     silc_free(client_id);
1551   }
1552   if (clients)
1553     silc_free(clients);
1554   if (nick)
1555     silc_free(nick);
1556   if (server_name)
1557     silc_free(server_name);
1558
1559   return ret;
1560 }
1561
1562 static int
1563 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1564 {
1565   SilcServer server = cmd->server;
1566   char *nick = NULL, *server_name = NULL;
1567   int count = 0, clients_count = 0;
1568   SilcClientEntry *clients = NULL, entry;
1569   SilcClientID **client_id = NULL;
1570   unsigned int client_id_count = 0;
1571   int i, ret = 0;
1572
1573   /* Parse the IDENTIFY request */
1574   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1575                                        &nick, &server_name, &count,
1576                                        SILC_COMMAND_IDENTIFY))
1577     return 0;
1578
1579   /* Process the command request. Let's search for the requested client and
1580      send reply to the requesting server. */
1581
1582   if (client_id_count) {
1583     /* Check all Client ID's received in the command packet */
1584     for (i = 0; i < client_id_count; i++) {
1585       entry = silc_idlist_find_client_by_id(server->local_list, 
1586                                             client_id[i], NULL);
1587       if (entry) {
1588         clients = silc_realloc(clients, sizeof(*clients) * 
1589                                (clients_count + 1));
1590         clients[clients_count++] = entry;
1591       }
1592     }
1593   } else {
1594     clients = silc_idlist_get_clients_by_nickname(server->local_list, 
1595                                                   nick, server_name,
1596                                                   &clients_count);
1597     if (!clients)
1598       clients = silc_idlist_get_clients_by_hash(server->local_list, 
1599                                                 nick, server->md5hash,
1600                                                 &clients_count);
1601   }
1602   
1603   /* If we are router we will check our global list as well. */
1604   if (!clients && server->server_type == SILC_ROUTER) {
1605     if (client_id_count) {
1606       /* Check all Client ID's received in the command packet */
1607       for (i = 0; i < client_id_count; i++) {
1608         entry = silc_idlist_find_client_by_id(server->global_list, 
1609                                               client_id[i], NULL);
1610         if (entry) {
1611           clients = silc_realloc(clients, sizeof(*clients) * 
1612                                  (clients_count + 1));
1613           clients[clients_count++] = entry;
1614         }
1615       }
1616     } else {
1617       clients = silc_idlist_get_clients_by_nickname(server->global_list, 
1618                                                     nick, server_name,
1619                                                     &clients_count);
1620       if (!clients)
1621         clients = silc_idlist_get_clients_by_hash(server->global_list, 
1622                                                   nick, server->md5hash,
1623                                                   &clients_count);
1624     }
1625   }
1626
1627   if (!clients) {
1628     /* Such a client really does not exist in the SILC network. */
1629     if (!client_id_count) {
1630       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1631                                            SILC_STATUS_ERR_NO_SUCH_NICK,
1632                                            3, nick, strlen(nick));
1633     } else {
1634       SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1635       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1636                                            SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1637                                            2, idp->data, idp->len);
1638       silc_buffer_free(idp);
1639     }
1640     goto out;
1641   }
1642
1643   /* Check that all mandatory fields are present and request those data
1644      from the server who owns the client if necessary. */
1645   if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1646     ret = -1;
1647     goto out;
1648   }
1649
1650   /* Send the command reply */
1651   silc_server_command_identify_send_reply(cmd, clients, clients_count);
1652
1653  out:
1654   if (client_id_count) {
1655     for (i = 0; i < client_id_count; i++)
1656       silc_free(client_id[i]);
1657     silc_free(client_id);
1658   }
1659   if (clients)
1660     silc_free(clients);
1661   if (nick)
1662     silc_free(nick);
1663   if (server_name)
1664     silc_free(server_name);
1665
1666   return ret;
1667 }
1668
1669 SILC_SERVER_CMD_FUNC(identify)
1670 {
1671   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1672   int ret = 0;
1673
1674   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1675
1676   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1677     ret = silc_server_command_identify_from_client(cmd);
1678   else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1679            (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1680     ret = silc_server_command_identify_from_server(cmd);
1681
1682   if (!ret)
1683     silc_server_command_free(cmd);
1684 }
1685
1686 /* Checks string for bad characters and returns TRUE if they are found. */
1687
1688 static int silc_server_command_bad_chars(char *nick)
1689 {
1690   if (strchr(nick, '\\')) return TRUE;
1691   if (strchr(nick, '\"')) return TRUE;
1692   if (strchr(nick, '´')) return TRUE;
1693   if (strchr(nick, '`')) return TRUE;
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
1699   return FALSE;
1700 }
1701
1702 /* Server side of command NICK. Sets nickname for user. Setting
1703    nickname causes generation of a new client ID for the client. The
1704    new client ID is sent to the client after changing the nickname. */
1705
1706 SILC_SERVER_CMD_FUNC(nick)
1707 {
1708   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1709   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1710   SilcServer server = cmd->server;
1711   SilcBuffer packet, nidp, oidp;
1712   SilcClientID *new_id;
1713   char *nick;
1714   unsigned short ident = silc_command_get_ident(cmd->payload);
1715
1716   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1717     goto out;
1718
1719   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1720
1721   /* Check nickname */
1722   nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1723   if (silc_server_command_bad_chars(nick) == TRUE) {
1724     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1725                                           SILC_STATUS_ERR_BAD_NICKNAME);
1726     goto out;
1727   }
1728
1729   if (strlen(nick) > 128)
1730     nick[127] = '\0';
1731
1732   /* Create new Client ID */
1733   silc_id_create_client_id(cmd->server->id, cmd->server->rng, 
1734                            cmd->server->md5hash, nick,
1735                            &new_id);
1736
1737   /* Send notify about nickname change to our router. We send the new
1738      ID and ask to replace it with the old one. If we are router the
1739      packet is broadcasted. Send NICK_CHANGE notify. */
1740   if (!server->standalone)
1741     silc_server_send_notify_nick_change(server, server->router->connection, 
1742                                         server->server_type == SILC_SERVER ? 
1743                                         FALSE : TRUE, client->id,
1744                                         new_id, SILC_ID_CLIENT_LEN);
1745
1746   /* Remove old cache entry */
1747   silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT, 
1748                          client->id); 
1749
1750   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1751
1752   /* Free old ID */
1753   if (client->id) {
1754     memset(client->id, 0, SILC_ID_CLIENT_LEN);
1755     silc_free(client->id);
1756   }
1757
1758   /* Save the nickname as this client is our local client */
1759   if (client->nickname)
1760     silc_free(client->nickname);
1761
1762   client->nickname = strdup(nick);
1763   client->id = new_id;
1764
1765   /* Update client cache */
1766   silc_idcache_add(server->local_list->clients, client->nickname, 
1767                    strlen(client->nickname), SILC_ID_CLIENT, client->id, 
1768                    (void *)client, TRUE, FALSE);
1769
1770   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1771
1772   /* Send NICK_CHANGE notify to the client's channels */
1773   silc_server_send_notify_on_channels(server, NULL, client, 
1774                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1775                                       oidp->data, oidp->len, 
1776                                       nidp->data, nidp->len);
1777
1778   /* Send the new Client ID as reply command back to client */
1779   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
1780                                                 SILC_STATUS_OK, ident, 1, 
1781                                                 2, nidp->data, nidp->len);
1782   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1783                           0, packet->data, packet->len, FALSE);
1784
1785   silc_buffer_free(packet);
1786   silc_buffer_free(nidp);
1787   silc_buffer_free(oidp);
1788   
1789  out:
1790   silc_server_command_free(cmd);
1791 }
1792
1793 /* Sends the LIST command reply */
1794
1795 static void
1796 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
1797                                     SilcChannelEntry *lch, 
1798                                     unsigned int lch_count,
1799                                     SilcChannelEntry *gch,
1800                                     unsigned int gch_count)
1801 {
1802   int i;
1803   SilcBuffer packet, idp;
1804   SilcChannelEntry entry;
1805   SilcCommandStatus status;
1806   unsigned short ident = silc_command_get_ident(cmd->payload);
1807   char *topic;
1808   unsigned char usercount[4];
1809   unsigned int users;
1810
1811   for (i = 0; i < lch_count; i++)
1812     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1813       lch[i] = NULL;
1814   for (i = 0; i < gch_count; i++)
1815     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
1816       gch[i] = NULL;
1817
1818   status = SILC_STATUS_OK;
1819   if ((lch_count + gch_count) > 1)
1820     status = SILC_STATUS_LIST_START;
1821
1822   /* Local list */
1823   for (i = 0; i < lch_count; i++) {
1824     entry = lch[i];
1825
1826     if (!entry)
1827       continue;
1828
1829     if (i >= 1)
1830       status = SILC_STATUS_LIST_ITEM;
1831
1832     if (i == lch_count - 1 && gch_count)
1833       break;
1834     if (lch_count > 1 && i == lch_count - 1)
1835       status = SILC_STATUS_LIST_END;
1836
1837     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1838
1839     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1840       topic = "*private*";
1841       memset(usercount, 0, sizeof(usercount));
1842     } else {
1843       topic = entry->topic;
1844       users = silc_list_count(entry->user_list);
1845       SILC_PUT32_MSB(users, usercount);
1846     }
1847
1848     /* Send the reply */
1849     if (topic)
1850       packet = 
1851         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1852                                              status, ident, 4, 
1853                                              2, idp->data, idp->len,
1854                                              3, entry->channel_name, 
1855                                              strlen(entry->channel_name),
1856                                              4, topic, strlen(topic),
1857                                              5, usercount, 4);
1858     else
1859       packet = 
1860         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1861                                              status, ident, 3, 
1862                                              2, idp->data, idp->len,
1863                                              3, entry->channel_name, 
1864                                              strlen(entry->channel_name),
1865                                              5, usercount, 4);
1866     silc_server_packet_send(cmd->server, cmd->sock, 
1867                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1868                             packet->len, FALSE);
1869     silc_buffer_free(packet);
1870     silc_buffer_free(idp);
1871   }
1872
1873   status = i ? SILC_STATUS_LIST_ITEM : SILC_STATUS_OK;
1874
1875   /* Global list */
1876   for (i = 0; i < gch_count; i++) {
1877     entry = gch[i];
1878
1879     if (!entry)
1880       continue;
1881
1882     if (i >= 1)
1883       status = SILC_STATUS_LIST_ITEM;
1884
1885     if (gch_count > 1 && i == lch_count - 1)
1886       status = SILC_STATUS_LIST_END;
1887
1888     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1889
1890     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
1891       topic = "*private*";
1892       memset(usercount, 0, sizeof(usercount));
1893     } else {
1894       topic = entry->topic;
1895       users = silc_list_count(entry->user_list);
1896       SILC_PUT32_MSB(users, usercount);
1897     }
1898
1899     /* Send the reply */
1900     if (topic)
1901       packet = 
1902         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1903                                              status, ident, 4, 
1904                                              2, idp->data, idp->len,
1905                                              3, entry->channel_name, 
1906                                              strlen(entry->channel_name),
1907                                              4, topic, strlen(topic),
1908                                              5, usercount, 4);
1909     else
1910       packet = 
1911         silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
1912                                              status, ident, 3, 
1913                                              2, idp->data, idp->len,
1914                                              3, entry->channel_name, 
1915                                              strlen(entry->channel_name),
1916                                              5, usercount, 4);
1917     silc_server_packet_send(cmd->server, cmd->sock, 
1918                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
1919                             packet->len, FALSE);
1920     silc_buffer_free(packet);
1921     silc_buffer_free(idp);
1922   }
1923 }
1924
1925 /* Server side of LIST command. This lists the channel of the requested
1926    server. Secret channels are not listed. */
1927
1928 SILC_SERVER_CMD_FUNC(list)
1929 {
1930   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1931   SilcServer server = cmd->server;
1932   SilcChannelID *channel_id = NULL;
1933   unsigned char *tmp;
1934   unsigned int tmp_len;
1935   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
1936   unsigned int lch_count = 0, gch_count = 0;
1937
1938   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LIST, cmd, 0, 2);
1939
1940   /* Get Channel ID */
1941   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1942   if (tmp) {
1943     channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1944     if (!channel_id) {
1945       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
1946                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
1947       goto out;
1948     }
1949   }
1950
1951   /* Get the channels from local list */
1952   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
1953                                        &lch_count);
1954   
1955   /* Get the channels from global list if we are router */
1956   if (server->server_type == SILC_ROUTER) 
1957     gchannels = silc_idlist_get_channels(server->global_list, channel_id,
1958                                          &gch_count);
1959
1960   /* Send the reply */
1961   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
1962                                       gchannels, gch_count);
1963
1964  out:
1965   silc_server_command_free(cmd);
1966 }
1967
1968 /* Server side of TOPIC command. Sets topic for channel and/or returns
1969    current topic to client. */
1970
1971 SILC_SERVER_CMD_FUNC(topic)
1972 {
1973   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1974   SilcServer server = cmd->server;
1975   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1976   SilcChannelID *channel_id;
1977   SilcChannelEntry channel;
1978   SilcChannelClientEntry chl;
1979   SilcBuffer packet, idp;
1980   unsigned char *tmp;
1981   unsigned int argc, tmp_len;
1982   unsigned short ident = silc_command_get_ident(cmd->payload);
1983
1984   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1985
1986   argc = silc_argument_get_arg_num(cmd->args);
1987
1988   /* Get Channel ID */
1989   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1990   if (!tmp) {
1991     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1992                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1993     goto out;
1994   }
1995   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1996   if (!channel_id) {
1997     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1998                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
1999     goto out;
2000   }
2001
2002   /* Check whether the channel exists */
2003   channel = silc_idlist_find_channel_by_id(server->local_list, 
2004                                            channel_id, NULL);
2005   if (!channel) {
2006     channel = silc_idlist_find_channel_by_id(server->global_list, 
2007                                              channel_id, NULL);
2008     if (!channel) {
2009       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2010                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2011       goto out;
2012     }
2013   }
2014
2015   if (argc > 1) {
2016     /* Get the topic */
2017     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2018     if (!tmp) {
2019       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2020                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2021       goto out;
2022     }
2023
2024     if (strlen(tmp) > 256) {
2025       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2026                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2027       goto out;
2028     }
2029
2030     /* See whether has rights to change topic */
2031     silc_list_start(channel->user_list);
2032     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2033       if (chl->client == client)
2034         break;
2035
2036     if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2037       if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
2038         silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2039                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2040         goto out;
2041       }
2042     }
2043
2044     /* Set the topic for channel */
2045     if (channel->topic)
2046       silc_free(channel->topic);
2047     channel->topic = strdup(tmp);
2048
2049     /* Send TOPIC_SET notify type to the network */
2050     if (!server->standalone)
2051       silc_server_send_notify_topic_set(server, server->router->connection,
2052                                         server->server_type == SILC_ROUTER ?
2053                                         TRUE : FALSE, channel, client->id,
2054                                         SILC_ID_CLIENT_LEN, channel->topic);
2055
2056     idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2057
2058     /* Send notify about topic change to all clients on the channel */
2059     silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
2060                                        SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2061                                        idp->data, idp->len,
2062                                        channel->topic, strlen(channel->topic));
2063     silc_buffer_free(idp);
2064   }
2065
2066   /* Send the topic to client as reply packet */
2067   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2068   if (channel->topic)
2069     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2070                                                   SILC_STATUS_OK, ident, 2, 
2071                                                   2, idp->data, idp->len,
2072                                                   3, channel->topic, 
2073                                                   strlen(channel->topic));
2074   else
2075     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2076                                                   SILC_STATUS_OK, ident, 1, 
2077                                                   2, idp->data, idp->len);
2078   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2079                           0, packet->data, packet->len, FALSE);
2080
2081   silc_buffer_free(packet);
2082   silc_buffer_free(idp);
2083   silc_free(channel_id);
2084
2085  out:
2086   silc_server_command_free(cmd);
2087 }
2088
2089 /* Server side of INVITE command. Invites some client to join some channel. 
2090    This command is also used to manage the invite list of the channel. */
2091
2092 SILC_SERVER_CMD_FUNC(invite)
2093 {
2094   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2095   SilcServer server = cmd->server;
2096   SilcSocketConnection sock = cmd->sock, dest_sock;
2097   SilcChannelClientEntry chl;
2098   SilcClientEntry sender, dest;
2099   SilcClientID *dest_id = NULL;
2100   SilcChannelEntry channel;
2101   SilcChannelID *channel_id = NULL;
2102   SilcIDListData idata;
2103   SilcBuffer idp, idp2, packet;
2104   unsigned char *tmp, *add, *del;
2105   unsigned int len;
2106   unsigned short ident = silc_command_get_ident(cmd->payload);
2107
2108   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 4);
2109
2110   /* Get Channel ID */
2111   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2112   if (!tmp) {
2113     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2114                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2115     goto out;
2116   }
2117   channel_id = silc_id_payload_parse_id(tmp, len);
2118   if (!channel_id) {
2119     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2120                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
2121     goto out;
2122   }
2123
2124   /* Get the channel entry */
2125   channel = silc_idlist_find_channel_by_id(server->local_list, 
2126                                            channel_id, NULL);
2127   if (!channel) {
2128     channel = silc_idlist_find_channel_by_id(server->global_list, 
2129                                              channel_id, NULL);
2130     if (!channel) {
2131       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2132                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2133       goto out;
2134     }
2135   }
2136
2137   /* Check whether the sender of this command is on the channel. */
2138   sender = (SilcClientEntry)sock->user_data;
2139   if (!silc_server_client_on_channel(sender, channel)) {
2140     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2141                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
2142     goto out;
2143   }
2144
2145   /* Check whether the channel is invite-only channel. If yes then the
2146      sender of this command must be at least channel operator. */
2147   if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
2148     silc_list_start(channel->user_list);
2149     while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2150       if (chl->client == sender) {
2151         if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2152           silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2153                                         SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2154           goto out;
2155         }
2156         break;
2157       }
2158   }
2159
2160   /* Get destination client ID */
2161   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2162   if (tmp) {
2163     char invite[512];
2164
2165     dest_id = silc_id_payload_parse_id(tmp, len);
2166     if (!dest_id) {
2167       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2168                                             SILC_STATUS_ERR_NO_CLIENT_ID);
2169       goto out;
2170     }
2171
2172     /* Get the client entry */
2173     dest = silc_server_get_client_resolve(server, dest_id);
2174     if (!dest) {
2175       if (server->server_type == SILC_ROUTER) {
2176         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2177                                      SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2178         goto out;
2179       }
2180       
2181       /* The client info is being resolved. Reprocess this packet after
2182          receiving the reply to the query. */
2183       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2184                                   server->cmd_ident,
2185                                   silc_server_command_destructor,
2186                                   silc_server_command_invite, 
2187                                   silc_server_command_dup(cmd));
2188       cmd->pending = TRUE;
2189       silc_free(channel_id);
2190       silc_free(dest_id);
2191       return;
2192     }
2193
2194     /* Check whether the requested client is already on the channel. */
2195     if (silc_server_client_on_channel(dest, channel)) {
2196       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2197                                             SILC_STATUS_ERR_USER_ON_CHANNEL);
2198       goto out;
2199     }
2200     
2201     /* Get route to the client */
2202     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, &idata);
2203
2204     memset(invite, 0, sizeof(invite));
2205     strncat(invite, dest->nickname, strlen(dest->nickname));
2206     strncat(invite, "!", 1);
2207     strncat(invite, dest->username, strlen(dest->username));
2208     if (!strchr(dest->username, '@')) {
2209       strncat(invite, "@", 1);
2210       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2211     }
2212
2213     len = strlen(invite);
2214     if (!channel->invite_list)
2215       channel->invite_list = silc_calloc(len + 2, 
2216                                          sizeof(*channel->invite_list));
2217     else
2218       channel->invite_list = silc_realloc(channel->invite_list, 
2219                                           sizeof(*channel->invite_list) * 
2220                                           (len + 
2221                                            strlen(channel->invite_list) + 2));
2222     strncat(channel->invite_list, invite, len);
2223     strncat(channel->invite_list, ",", 1);
2224
2225     /* Send notify to the client that is invited to the channel */
2226     idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2227     idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2228     silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2229                                  SILC_ID_CLIENT,
2230                                  SILC_NOTIFY_TYPE_INVITE, 3, 
2231                                  idp->data, idp->len, 
2232                                  channel->channel_name, 
2233                                  strlen(channel->channel_name),
2234                                  idp2->data, idp2->len);
2235     silc_buffer_free(idp);
2236     silc_buffer_free(idp2);
2237   }
2238
2239   /* Add the client to the invite list of the channel */
2240   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2241   if (add) {
2242     if (!channel->invite_list)
2243       channel->invite_list = silc_calloc(len + 2, 
2244                                          sizeof(*channel->invite_list));
2245     else
2246       channel->invite_list = silc_realloc(channel->invite_list, 
2247                                           sizeof(*channel->invite_list) * 
2248                                           (len + 
2249                                            strlen(channel->invite_list) + 2));
2250     if (add[len - 1] == ',')
2251       add[len - 1] = '\0';
2252     
2253     strncat(channel->invite_list, add, len);
2254     strncat(channel->invite_list, ",", 1);
2255   }
2256
2257   /* Get the invite to be removed and remove it from the list */
2258   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2259   if (del && channel->invite_list) {
2260     char *start, *end, *n;
2261
2262     if (!strncmp(channel->invite_list, del, 
2263                  strlen(channel->invite_list) - 1)) {
2264       silc_free(channel->invite_list);
2265       channel->invite_list = NULL;
2266     } else {
2267       start = strstr(channel->invite_list, del);
2268       if (start && strlen(start) >= len) {
2269         end = start + len;
2270         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2271         strncat(n, channel->invite_list, start - channel->invite_list);
2272         strncat(n, end + 1, ((channel->invite_list + 
2273                               strlen(channel->invite_list)) - end) - 1);
2274         silc_free(channel->invite_list);
2275         channel->invite_list = n;
2276       }
2277     }
2278   }
2279
2280   /* Send notify to the primary router */
2281   if (!server->standalone)
2282     silc_server_send_notify_invite(server, server->router->connection,
2283                                    server->server_type == SILC_ROUTER ?
2284                                    TRUE : FALSE, channel,
2285                                    sender->id, SILC_ID_CLIENT_LEN,
2286                                    add, del);
2287
2288   /* Send command reply */
2289   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2290   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2291                                                 SILC_STATUS_OK, ident, 2,
2292                                                 2, tmp, len,
2293                                                 3, channel->invite_list,
2294                                                 channel->invite_list ?
2295                                                 strlen(channel->invite_list) :
2296                                                 0);
2297   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2298                           packet->data, packet->len, FALSE);
2299   silc_buffer_free(packet);
2300
2301  out:
2302   if (dest_id)
2303     silc_free(dest_id);
2304   if (channel_id)
2305     silc_free(channel_id);
2306   silc_server_command_free(cmd);
2307 }
2308
2309 typedef struct {
2310   SilcServer server;
2311   SilcSocketConnection sock;
2312   char *signoff;
2313 } *QuitInternal;
2314
2315 /* Quits connection to client. This gets called if client won't
2316    close the connection even when it has issued QUIT command. */
2317
2318 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2319 {
2320   QuitInternal q = (QuitInternal)context;
2321
2322   /* Free all client specific data, such as client entry and entires
2323      on channels this client may be on. */
2324   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2325                                TRUE, q->signoff);
2326   q->sock->user_data = NULL;
2327
2328   /* Close the connection on our side */
2329   silc_server_close_connection(q->server, q->sock);
2330
2331   silc_free(q->signoff);
2332   silc_free(q);
2333 }
2334
2335 /* Quits SILC session. This is the normal way to disconnect client. */
2336  
2337 SILC_SERVER_CMD_FUNC(quit)
2338 {
2339   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2340   SilcServer server = cmd->server;
2341   SilcSocketConnection sock = cmd->sock;
2342   QuitInternal q;
2343   unsigned char *tmp = NULL;
2344   unsigned int len = 0;
2345
2346   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
2347
2348   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2349     goto out;
2350
2351   /* Get destination ID */
2352   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2353   if (len > 128)
2354     tmp = NULL;
2355
2356   q = silc_calloc(1, sizeof(*q));
2357   q->server = server;
2358   q->sock = sock;
2359   q->signoff = tmp ? strdup(tmp) : NULL;
2360
2361   /* We quit the connection with little timeout */
2362   silc_task_register(server->timeout_queue, sock->sock,
2363                      silc_server_command_quit_cb, (void *)q,
2364                      0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2365
2366  out:
2367   silc_server_command_free(cmd);
2368 }
2369
2370 /* Server side of command KILL. This command is used by router operator
2371    to remove an client from the SILC Network temporarily. */
2372
2373 SILC_SERVER_CMD_FUNC(kill)
2374 {
2375   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2376   SilcServer server = cmd->server;
2377   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2378   SilcClientEntry remote_client;
2379   SilcClientID *client_id;
2380   unsigned char *tmp, *comment;
2381   unsigned int tmp_len, tmp_len2;
2382
2383   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_KILL, cmd, 1, 2);
2384
2385   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2386     goto out;
2387
2388   /* KILL command works only on router */
2389   if (server->server_type != SILC_ROUTER) {
2390     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2391                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2392     goto out;
2393   }
2394
2395   /* Check whether client has the permissions. */
2396   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2397     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2398                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
2399     goto out;
2400   }
2401
2402   /* Get the client ID */
2403   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2404   if (!tmp) {
2405     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2406                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2407     goto out;
2408   }
2409   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2410   if (!client_id) {
2411     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2412                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2413     goto out;
2414   }
2415
2416   /* Get the client entry */
2417   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2418                                                 client_id, NULL);
2419   if (!remote_client) {
2420     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2421                                                   client_id, NULL);
2422     if (!remote_client) {
2423       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2424                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
2425       goto out;
2426     }
2427   }
2428
2429   /* Get comment */
2430   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2431   if (tmp_len2 > 128)
2432     comment = NULL;
2433
2434   /* Send reply to the sender */
2435   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2436                                         SILC_STATUS_OK);
2437
2438   /* Send the KILL notify packets. First send it to the channel, then
2439      to our primary router and then directly to the client who is being
2440      killed right now. */
2441
2442   /* Send KILLED notify to the channels. It is not sent to the client
2443      as it will be sent differently destined directly to the client and not
2444      to the channel. */
2445   silc_server_send_notify_on_channels(server, remote_client, 
2446                                       remote_client, SILC_NOTIFY_TYPE_KILLED,
2447                                       comment ? 2 : 1,
2448                                       tmp, tmp_len,
2449                                       comment, comment ? tmp_len2 : 0);
2450
2451   /* Send KILLED notify to primary route */
2452   if (!server->standalone)
2453     silc_server_send_notify_killed(server, server->router->connection, TRUE,
2454                                    remote_client->id, SILC_ID_CLIENT_LEN,
2455                                    comment);
2456
2457   /* Send KILLED notify to the client directly */
2458   silc_server_send_notify_killed(server, remote_client->connection ? 
2459                                  remote_client->connection : 
2460                                  remote_client->router->connection, FALSE,
2461                                  remote_client->id, SILC_ID_CLIENT_LEN,
2462                                  comment);
2463
2464   /* Remove the client from all channels. This generates new keys to the
2465      channels as well. */
2466   silc_server_remove_from_channels(server, NULL, remote_client, FALSE, 
2467                                    NULL, TRUE);
2468
2469   /* Remove the client entry, If it is locally connected then we will also
2470      disconnect the client here */
2471   if (remote_client->data.registered && remote_client->connection) {
2472     /* Remove locally conneted client */
2473     SilcSocketConnection sock = remote_client->connection;
2474     silc_server_free_client_data(server, sock, remote_client, FALSE, NULL);
2475     silc_server_close_connection(server, sock);
2476   } else {
2477     /* Remove remote client */
2478     if (!silc_idlist_del_client(server->global_list, remote_client))
2479       silc_idlist_del_client(server->local_list, remote_client);
2480   }
2481
2482  out:
2483   silc_server_command_free(cmd);
2484 }
2485
2486 /* Server side of command INFO. This sends information about us to 
2487    the client. If client requested specific server we will send the 
2488    command to that server. */
2489
2490 SILC_SERVER_CMD_FUNC(info)
2491 {
2492   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2493   SilcServer server = cmd->server;
2494   SilcBuffer packet, idp;
2495   char *dest_server, *server_info = NULL, *server_name;
2496   unsigned short ident = silc_command_get_ident(cmd->payload);
2497   SilcServerEntry entry = NULL;
2498
2499   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
2500
2501   /* Get server name */
2502   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2503   if (!dest_server) {
2504     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2505                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2506     goto out;
2507   }
2508
2509   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
2510     /* Send our reply */
2511     char info_string[256];
2512
2513     memset(info_string, 0, sizeof(info_string));
2514     snprintf(info_string, sizeof(info_string), 
2515              "location: %s server: %s admin: %s <%s>",
2516              server->config->admin_info->location,
2517              server->config->admin_info->server_type,
2518              server->config->admin_info->admin_name,
2519              server->config->admin_info->admin_email);
2520
2521     server_info = info_string;
2522     entry = server->id_entry;
2523   } else {
2524     /* Check whether we have this server cached */
2525     entry = silc_idlist_find_server_by_name(server->global_list,
2526                                             dest_server, NULL);
2527     if (!entry) {
2528       entry = silc_idlist_find_server_by_name(server->local_list,
2529                                               dest_server, NULL);
2530     }
2531
2532     if (server->server_type == SILC_ROUTER && entry && !entry->server_info) {
2533       /* Send to the server */
2534       SilcBuffer tmpbuf;
2535       unsigned short old_ident;
2536
2537       old_ident = silc_command_get_ident(cmd->payload);
2538       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2539       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2540
2541       silc_server_packet_send(server, entry->connection,
2542                               SILC_PACKET_COMMAND, cmd->packet->flags,
2543                               tmpbuf->data, tmpbuf->len, TRUE);
2544
2545       /* Reprocess this packet after received reply from router */
2546       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2547                                   silc_command_get_ident(cmd->payload),
2548                                   silc_server_command_destructor,
2549                                   silc_server_command_info,
2550                                   silc_server_command_dup(cmd));
2551       cmd->pending = TRUE;
2552       silc_command_set_ident(cmd->payload, old_ident);
2553       silc_buffer_free(tmpbuf);
2554       return;
2555     }
2556
2557     if (!entry && !cmd->pending && !server->standalone) {
2558       /* Send to the primary router */
2559       SilcBuffer tmpbuf;
2560       unsigned short old_ident;
2561
2562       old_ident = silc_command_get_ident(cmd->payload);
2563       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2564       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2565
2566       silc_server_packet_send(server, server->router->connection,
2567                               SILC_PACKET_COMMAND, cmd->packet->flags,
2568                               tmpbuf->data, tmpbuf->len, TRUE);
2569
2570       /* Reprocess this packet after received reply from router */
2571       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2572                                   silc_command_get_ident(cmd->payload),
2573                                   silc_server_command_destructor,
2574                                   silc_server_command_info,
2575                                   silc_server_command_dup(cmd));
2576       cmd->pending = TRUE;
2577       silc_command_set_ident(cmd->payload, old_ident);
2578       silc_buffer_free(tmpbuf);
2579       return;
2580     }
2581   }
2582
2583   if (!entry) {
2584     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2585                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2586     goto out;
2587   }
2588
2589   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
2590   if (!server_info)
2591     server_info = entry->server_info;
2592   server_name = dest_server;
2593
2594   /* Send the reply */
2595   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
2596                                                 SILC_STATUS_OK, ident, 3,
2597                                                 2, idp->data, idp->len,
2598                                                 3, server_name, 
2599                                                 strlen(server_name),
2600                                                 4, server_info, 
2601                                                 strlen(server_info));
2602   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2603                           packet->data, packet->len, FALSE);
2604     
2605   silc_buffer_free(packet);
2606   silc_buffer_free(idp);
2607
2608  out:
2609   silc_server_command_free(cmd);
2610 }
2611
2612 /* Server side of command PING. This just replies to the ping. */
2613
2614 SILC_SERVER_CMD_FUNC(ping)
2615 {
2616   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2617   SilcServer server = cmd->server;
2618   SilcServerID *id;
2619   unsigned int len;
2620   unsigned char *tmp;
2621
2622   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
2623
2624   /* Get Server ID */
2625   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2626   if (!tmp) {
2627     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2628                                           SILC_STATUS_ERR_NO_SERVER_ID);
2629     goto out;
2630   }
2631   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
2632   if (!id)
2633     goto out;
2634
2635   if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
2636     /* Send our reply */
2637     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2638                                           SILC_STATUS_OK);
2639   } else {
2640     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
2641                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
2642     goto out;
2643   }
2644
2645   silc_free(id);
2646
2647  out:
2648   silc_server_command_free(cmd);
2649 }
2650
2651 /* Internal routine to join channel. The channel sent to this function
2652    has been either created or resolved from ID lists. This joins the sent
2653    client to the channel. */
2654
2655 static void silc_server_command_join_channel(SilcServer server, 
2656                                              SilcServerCommandContext cmd,
2657                                              SilcChannelEntry channel,
2658                                              SilcClientID *client_id,
2659                                              int created,
2660                                              unsigned int umode)
2661 {
2662   SilcSocketConnection sock = cmd->sock;
2663   unsigned char *tmp;
2664   unsigned int tmp_len, user_count;
2665   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
2666   SilcClientEntry client;
2667   SilcChannelClientEntry chl;
2668   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
2669   unsigned short ident = silc_command_get_ident(cmd->payload);
2670   char check[512];
2671
2672   SILC_LOG_DEBUG(("Start"));
2673
2674   if (!channel)
2675     return;
2676
2677   /* Get the client entry */
2678   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2679     client = (SilcClientEntry)sock->user_data;
2680   } else {
2681     client = silc_idlist_find_client_by_id(server->local_list, client_id, 
2682                                            NULL);
2683     if (!client)
2684       goto out;
2685   }
2686
2687   /*
2688    * Check channel modes
2689    */
2690
2691   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2692     strncat(check, client->nickname, strlen(client->nickname));
2693     if (!strchr(client->nickname, '@')) {
2694       strncat(check, "@", 1);
2695       strncat(check, server->server_name, strlen(server->server_name));
2696     }
2697     strncat(check, "!", 1);
2698     strncat(check, client->username, strlen(client->username));
2699     if (!strchr(client->username, '@')) {
2700       strncat(check, "@", 1);
2701       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
2702     }
2703   }
2704
2705   /* Check invite list if channel is invite-only channel */
2706   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
2707       channel->mode & SILC_CHANNEL_MODE_INVITE) {
2708     if (!channel->invite_list) {
2709       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2710                                             SILC_STATUS_ERR_NOT_INVITED);
2711       goto out;
2712     }
2713
2714     if (!silc_string_match(channel->invite_list, check)) {
2715       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2716                                             SILC_STATUS_ERR_NOT_INVITED);
2717       goto out;
2718     }
2719   }
2720
2721   /* Check ban list if it exists. If the client's nickname, server,
2722      username and/or hostname is in the ban list the access to the
2723      channel is denied. */
2724   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && channel->ban_list) {
2725     if (silc_string_match(channel->ban_list, check)) {
2726       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2727                               SILC_STATUS_ERR_BANNED_FROM_CHANNEL);
2728       goto out;
2729     }
2730   }
2731
2732   /* Get passphrase */
2733   tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2734   if (tmp) {
2735     passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
2736     memcpy(passphrase, tmp, tmp_len);
2737   }
2738   
2739   /* Check the channel passphrase if set. */
2740   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2741     if (!passphrase || memcmp(channel->passphrase, passphrase,
2742                               strlen(channel->passphrase))) {
2743       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2744                                             SILC_STATUS_ERR_BAD_PASSWORD);
2745       goto out;
2746     }
2747   }
2748
2749   /* Check user count limit if set. */
2750   if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
2751     if (silc_list_count(channel->user_list) + 1 > 
2752         channel->user_limit) {
2753       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2754                                             SILC_STATUS_ERR_CHANNEL_IS_FULL);
2755       goto out;
2756     }
2757   }
2758
2759   /*
2760    * Client is allowed to join to the channel. Make it happen.
2761    */
2762
2763   /* Check whether the client already is on the channel */
2764   if (silc_server_client_on_channel(client, channel)) {
2765     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2766                                           SILC_STATUS_ERR_USER_ON_CHANNEL);
2767     goto out;
2768   }
2769
2770   /* Generate new channel key as protocol dictates */
2771   if ((!created && silc_list_count(channel->user_list) > 0) || 
2772       !channel->channel_key)
2773     silc_server_create_channel_key(server, channel, 0);
2774
2775   /* Send the channel key. This is broadcasted to the channel but is not
2776      sent to the client who is joining to the channel. */
2777   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
2778     silc_server_send_channel_key(server, NULL, channel, 
2779                                  server->server_type == SILC_ROUTER ? 
2780                                  FALSE : !server->standalone);
2781
2782   /* Join the client to the channel by adding it to channel's user list.
2783      Add also the channel to client entry's channels list for fast cross-
2784      referencing. */
2785   chl = silc_calloc(1, sizeof(*chl));
2786   chl->mode = umode;
2787   chl->client = client;
2788   chl->channel = channel;
2789   silc_list_add(channel->user_list, chl);
2790   silc_list_add(client->channels, chl);
2791
2792   /* Get users on the channel */
2793   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2794                                    &user_count);
2795
2796   /* Encode Client ID Payload of the original client who wants to join */
2797   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2798
2799   /* Encode command reply packet */
2800   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2801   SILC_PUT32_MSB(channel->mode, mode);
2802   SILC_PUT32_MSB(created, tmp2);
2803   SILC_PUT32_MSB(user_count, tmp3);
2804
2805   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
2806     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2807     keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2808                                            strlen(channel->channel_key->
2809                                                   cipher->name),
2810                                            channel->channel_key->cipher->name,
2811                                            channel->key_len / 8, channel->key);
2812     silc_free(tmp);
2813   }
2814
2815   reply = 
2816     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2817                                          SILC_STATUS_OK, ident, 13,
2818                                          2, channel->channel_name,
2819                                          strlen(channel->channel_name),
2820                                          3, chidp->data, chidp->len,
2821                                          4, clidp->data, clidp->len,
2822                                          5, mode, 4,
2823                                          6, tmp2, 4,
2824                                          7, keyp ? keyp->data : NULL, 
2825                                          keyp ? keyp->len : 0,
2826                                          8, channel->ban_list, 
2827                                          channel->ban_list ?
2828                                          strlen(channel->ban_list) : 0,
2829                                          9, channel->invite_list,
2830                                          channel->invite_list ?
2831                                          strlen(channel->invite_list) : 0,
2832                                          10, channel->topic,
2833                                          channel->topic ?
2834                                          strlen(channel->topic) : 0,
2835                                          11, channel->hmac->hmac->name,
2836                                          strlen(channel->hmac->hmac->name),
2837                                          12, tmp3, 4,
2838                                          13, user_list->data, user_list->len,
2839                                          14, mode_list->data, 
2840                                          mode_list->len);
2841
2842   /* Send command reply */
2843   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2844                           reply->data, reply->len, FALSE);
2845
2846   if (!cmd->pending) {
2847     /* Send JOIN notify to locally connected clients on the channel */
2848     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2849                                        SILC_NOTIFY_TYPE_JOIN, 2,
2850                                        clidp->data, clidp->len,
2851                                        chidp->data, chidp->len);
2852
2853     /* Send JOIN notify packet to our primary router */
2854     if (!server->standalone)
2855       silc_server_send_notify_join(server, server->router->connection,
2856                                    server->server_type == SILC_ROUTER ?
2857                                    TRUE : FALSE, channel, client->id,
2858                                    SILC_ID_CLIENT_LEN);
2859   }
2860
2861   silc_buffer_free(reply);
2862   silc_buffer_free(clidp);
2863   silc_buffer_free(chidp);
2864   silc_buffer_free(keyp);
2865   silc_buffer_free(user_list);
2866   silc_buffer_free(mode_list);
2867
2868  out:
2869   if (passphrase)
2870     silc_free(passphrase);
2871 }
2872
2873 /* Server side of command JOIN. Joins client into requested channel. If 
2874    the channel does not exist it will be created. */
2875
2876 SILC_SERVER_CMD_FUNC(join)
2877 {
2878   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2879   SilcServer server = cmd->server;
2880   int tmp_len;
2881   char *tmp, *channel_name = NULL, *cipher, *hmac;
2882   SilcChannelEntry channel;
2883   unsigned int umode = 0;
2884   int created = FALSE;
2885   SilcClientID *client_id;
2886
2887   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2888
2889   /* Get channel name */
2890   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2891   if (!tmp) {
2892     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2893                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2894     goto out;
2895   }
2896   channel_name = tmp;
2897
2898   if (strlen(channel_name) > 256)
2899     channel_name[255] = '\0';
2900
2901   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2902     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2903                                           SILC_STATUS_ERR_BAD_CHANNEL);
2904     silc_free(channel_name);
2905     goto out;
2906   }
2907
2908   /* Get Client ID of the client who is joining to the channel */
2909   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2910   if (!tmp) {
2911     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2912                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2913     goto out;
2914   }
2915   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2916   if (!client_id) {
2917     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2918                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2919     goto out;
2920   }
2921
2922   /* Get cipher and hmac name */
2923   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2924   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2925
2926   /* See if the channel exists */
2927   channel = silc_idlist_find_channel_by_name(server->local_list, 
2928                                              channel_name, NULL);
2929
2930   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2931     /* If this is coming from client the Client ID in the command packet must
2932        be same as the client's ID. */
2933     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2934       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2935       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2936         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2937                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2938         goto out;
2939       }
2940     }
2941
2942     if (!channel) {
2943       /* Channel not found */
2944
2945       /* If we are standalone server we don't have a router, we just create 
2946          the channel by ourselves. */
2947       if (server->standalone) {
2948         channel = silc_server_create_new_channel(server, server->id, cipher, 
2949                                                  hmac, channel_name, TRUE);
2950         if (!channel) {
2951           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2952                                      SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2953           goto out;
2954         }
2955
2956         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2957         created = TRUE;
2958
2959       } else {
2960
2961         /* The channel does not exist on our server. If we are normal server 
2962            we will send JOIN command to our router which will handle the
2963            joining procedure (either creates the channel if it doesn't exist 
2964            or joins the client to it). */
2965         if (server->server_type == SILC_SERVER) {
2966           SilcBuffer tmpbuf;
2967           unsigned short old_ident;
2968           
2969           old_ident = silc_command_get_ident(cmd->payload);
2970           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2971           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2972           
2973           /* Send JOIN command to our router */
2974           silc_server_packet_send(server, (SilcSocketConnection)
2975                                   server->router->connection,
2976                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2977                                   tmpbuf->data, tmpbuf->len, TRUE);
2978           
2979           /* Reprocess this packet after received reply from router */
2980           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2981                                       silc_command_get_ident(cmd->payload),
2982                                       silc_server_command_destructor,
2983                                       silc_server_command_join,
2984                                       silc_server_command_dup(cmd));
2985           cmd->pending = TRUE;
2986           return;
2987         }
2988         
2989         /* We are router and the channel does not seem exist so we will check
2990            our global list as well for the channel. */
2991         channel = silc_idlist_find_channel_by_name(server->global_list, 
2992                                                    channel_name, NULL);
2993         if (!channel) {
2994           /* Channel really does not exist, create it */
2995           channel = silc_server_create_new_channel(server, server->id, cipher, 
2996                                                    hmac, channel_name, TRUE);
2997           if (!channel) {
2998             silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2999                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3000             goto out;
3001           }
3002
3003           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3004           created = TRUE;
3005         }
3006       }
3007     }
3008   } else {
3009     if (!channel) {
3010       /* Channel not found */
3011
3012       /* If the command came from router and/or we are normal server then
3013          something went wrong with the joining as the channel was not found.
3014          We can't do anything else but ignore this. */
3015       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3016           server->server_type == SILC_SERVER)
3017         goto out;
3018       
3019       /* We are router and the channel does not seem exist so we will check
3020          our global list as well for the channel. */
3021       channel = silc_idlist_find_channel_by_name(server->global_list, 
3022                                                  channel_name, NULL);
3023       if (!channel) {
3024         /* Channel really does not exist, create it */
3025         channel = silc_server_create_new_channel(server, server->id, cipher, 
3026                                                  hmac, channel_name, TRUE);
3027         if (!channel) {
3028           silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3029                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3030           goto out;
3031         }
3032
3033         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3034         created = TRUE;
3035       }
3036     }
3037   }
3038
3039   /* If the channel does not have global users and is also empty it means the
3040      channel was created globally (by our router) and the client will be the
3041      channel founder and operator. */
3042   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3043     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3044     created = TRUE;             /* Created globally by our router */
3045   }
3046
3047   /* Join to the channel */
3048   silc_server_command_join_channel(server, cmd, channel, client_id,
3049                                    created, umode);
3050
3051   silc_free(client_id);
3052
3053  out:
3054   silc_server_command_free(cmd);
3055 }
3056
3057 /* Server side of command MOTD. Sends server's current "message of the
3058    day" to the client. */
3059
3060 SILC_SERVER_CMD_FUNC(motd)
3061 {
3062   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3063   SilcServer server = cmd->server;
3064   SilcBuffer packet, idp;
3065   char *motd, *dest_server;
3066   int motd_len;
3067   unsigned short ident = silc_command_get_ident(cmd->payload);
3068   
3069   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3070
3071   /* Get server name */
3072   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3073   if (!dest_server) {
3074     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3075                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3076     goto out;
3077   }
3078
3079   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3080     /* Send our MOTD */
3081
3082     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3083
3084     if (server->config && server->config->motd && 
3085         server->config->motd->motd_file) {
3086       /* Send motd */
3087       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3088       if (!motd)
3089         goto out;
3090       
3091       motd[motd_len] = 0;
3092       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3093                                                     SILC_STATUS_OK, ident, 2,
3094                                                     2, idp, idp->len,
3095                                                     3, motd, motd_len);
3096       goto out;
3097     } else {
3098       /* No motd */
3099       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3100                                                     SILC_STATUS_OK, ident, 1,
3101                                                     2, idp, idp->len);
3102     }
3103
3104     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3105                             packet->data, packet->len, FALSE);
3106     silc_buffer_free(packet);
3107     silc_buffer_free(idp);
3108   } else {
3109     SilcServerEntry entry;
3110
3111     /* Check whether we have this server cached */
3112     entry = silc_idlist_find_server_by_name(server->global_list,
3113                                             dest_server, NULL);
3114     if (!entry) {
3115       entry = silc_idlist_find_server_by_name(server->local_list,
3116                                               dest_server, NULL);
3117     }
3118
3119     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3120         entry && !entry->motd) {
3121       /* Send to the server */
3122       SilcBuffer tmpbuf;
3123       unsigned short old_ident;
3124
3125       old_ident = silc_command_get_ident(cmd->payload);
3126       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3127       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3128
3129       silc_server_packet_send(server, entry->connection,
3130                               SILC_PACKET_COMMAND, cmd->packet->flags,
3131                               tmpbuf->data, tmpbuf->len, TRUE);
3132
3133       /* Reprocess this packet after received reply from router */
3134       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3135                                   silc_command_get_ident(cmd->payload),
3136                                   silc_server_command_destructor,
3137                                   silc_server_command_motd,
3138                                   silc_server_command_dup(cmd));
3139       cmd->pending = TRUE;
3140       silc_command_set_ident(cmd->payload, old_ident);
3141       silc_buffer_free(tmpbuf);
3142       return;
3143     }
3144
3145     if (!entry && !cmd->pending && !server->standalone) {
3146       /* Send to the primary router */
3147       SilcBuffer tmpbuf;
3148       unsigned short old_ident;
3149
3150       old_ident = silc_command_get_ident(cmd->payload);
3151       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3152       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3153
3154       silc_server_packet_send(server, server->router->connection,
3155                               SILC_PACKET_COMMAND, cmd->packet->flags,
3156                               tmpbuf->data, tmpbuf->len, TRUE);
3157
3158       /* Reprocess this packet after received reply from router */
3159       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3160                                   silc_command_get_ident(cmd->payload),
3161                                   silc_server_command_destructor,
3162                                   silc_server_command_motd,
3163                                   silc_server_command_dup(cmd));
3164       cmd->pending = TRUE;
3165       silc_command_set_ident(cmd->payload, old_ident);
3166       silc_buffer_free(tmpbuf);
3167       return;
3168     }
3169
3170     if (!entry) {
3171       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3172                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3173       goto out;
3174     }
3175
3176     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3177
3178     if (entry->motd)
3179       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3180                                                     SILC_STATUS_OK, ident, 2,
3181                                                     2, idp, idp->len,
3182                                                     3, entry->motd,
3183                                                     strlen(entry->motd));
3184     else
3185       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3186                                                     SILC_STATUS_OK, ident, 1,
3187                                                     2, idp, idp->len);
3188
3189     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3190                             packet->data, packet->len, FALSE);
3191     silc_buffer_free(packet);
3192     silc_buffer_free(idp);
3193   }
3194
3195  out:
3196   silc_server_command_free(cmd);
3197 }
3198
3199 /* Server side of command UMODE. Client can use this command to set/unset
3200    user mode. Client actually cannot set itself to be as server/router
3201    operator so this can be used only to unset the modes. */
3202
3203 SILC_SERVER_CMD_FUNC(umode)
3204 {
3205   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3206   SilcServer server = cmd->server;
3207   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3208   SilcBuffer packet;
3209   unsigned char *tmp_mask;
3210   unsigned int mask;
3211   unsigned short ident = silc_command_get_ident(cmd->payload);
3212
3213   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3214     goto out;
3215
3216   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3217
3218   /* Get the client's mode mask */
3219   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3220   if (!tmp_mask) {
3221     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3222                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3223     goto out;
3224   }
3225   SILC_GET32_MSB(mask, tmp_mask);
3226
3227   /* 
3228    * Change the mode 
3229    */
3230
3231   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3232     /* Cannot operator mode */
3233     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3234                                           SILC_STATUS_ERR_PERM_DENIED);
3235     goto out;
3236   } else {
3237     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3238       /* Remove the server operator rights */
3239       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3240   }
3241
3242   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3243     /* Cannot operator mode */
3244     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3245                                           SILC_STATUS_ERR_PERM_DENIED);
3246     goto out;
3247   } else {
3248     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3249       /* Remove the router operator rights */
3250       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3251   }
3252
3253   /* Send UMODE change to primary router */
3254   if (!server->standalone)
3255     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3256                                   client->id, SILC_ID_CLIENT_LEN,
3257                                   client->mode);
3258
3259   /* Send command reply to sender */
3260   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3261                                                 SILC_STATUS_OK, ident, 1,
3262                                                 2, tmp_mask, 4);
3263   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3264                           packet->data, packet->len, FALSE);
3265   silc_buffer_free(packet);
3266
3267  out:
3268   silc_server_command_free(cmd);
3269 }
3270
3271 /* Checks that client has rights to add or remove channel modes. If any
3272    of the checks fails FALSE is returned. */
3273
3274 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3275                                    SilcChannelClientEntry client,
3276                                    unsigned int mode)
3277 {
3278   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3279   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3280
3281   /* Check whether has rights to change anything */
3282   if (!is_op && !is_fo)
3283     return FALSE;
3284
3285   /* Check whether has rights to change everything */
3286   if (is_op && is_fo)
3287     return TRUE;
3288
3289   /* We know that client is channel operator, check that they are not
3290      changing anything that requires channel founder rights. Rest of the
3291      modes are available automatically for channel operator. */
3292
3293   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3294     if (is_op && !is_fo)
3295       return FALSE;
3296   } else {
3297     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3298       if (is_op && !is_fo)
3299         return FALSE;
3300     }
3301   }
3302   
3303   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3304     if (is_op && !is_fo)
3305       return FALSE;
3306   } else {
3307     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3308       if (is_op && !is_fo)
3309         return FALSE;
3310     }
3311   }
3312
3313   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3314     if (is_op && !is_fo)
3315       return FALSE;
3316   } else {
3317     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3318       if (is_op && !is_fo)
3319         return FALSE;
3320     }
3321   }
3322   
3323   return TRUE;
3324 }
3325
3326 /* Server side command of CMODE. Changes channel mode */
3327
3328 SILC_SERVER_CMD_FUNC(cmode)
3329 {
3330   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3331   SilcServer server = cmd->server;
3332   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3333   SilcChannelID *channel_id;
3334   SilcChannelEntry channel;
3335   SilcChannelClientEntry chl;
3336   SilcBuffer packet, cidp;
3337   unsigned char *tmp, *tmp_id, *tmp_mask;
3338   char *cipher = NULL, *hmac = NULL;
3339   unsigned int argc, mode_mask, tmp_len, tmp_len2;
3340   unsigned short ident = silc_command_get_ident(cmd->payload);
3341
3342   SILC_LOG_DEBUG(("Start"));
3343
3344   argc = silc_argument_get_arg_num(cmd->args);
3345   if (argc < 2) {
3346     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3347                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3348     goto out;
3349   }
3350   if (argc > 8) {
3351     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3352                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
3353     goto out;
3354   }
3355
3356   /* Get Channel ID */
3357   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3358   if (!tmp_id) {
3359     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3360                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3361     goto out;
3362   }
3363   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3364   if (!channel_id) {
3365     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3366                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3367     goto out;
3368   }
3369
3370   /* Get the channel mode mask */
3371   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3372   if (!tmp_mask) {
3373     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3374                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3375     goto out;
3376   }
3377   SILC_GET32_MSB(mode_mask, tmp_mask);
3378
3379   /* Get channel entry */
3380   channel = silc_idlist_find_channel_by_id(server->local_list, 
3381                                            channel_id, NULL);
3382   if (!channel) {
3383     channel = silc_idlist_find_channel_by_id(server->global_list, 
3384                                              channel_id, NULL);
3385     if (!channel) {
3386       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3387                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3388       goto out;
3389     }
3390   }
3391
3392   /* Check whether this client is on the channel */
3393   if (!silc_server_client_on_channel(client, channel)) {
3394     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3395                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3396     goto out;
3397   }
3398
3399   /* Get entry to the channel user list */
3400   silc_list_start(channel->user_list);
3401   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3402     if (chl->client == client)
3403       break;
3404
3405   /* Check that client has rights to change any requested channel modes */
3406   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3407     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3408                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3409     goto out;
3410   }
3411
3412   /*
3413    * Check the modes. Modes that requires nothing special operation are
3414    * not checked here.
3415    */
3416
3417   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3418     /* Channel uses private keys to protect traffic. Client(s) has set the
3419        key locally they want to use, server does not know that key. */
3420     /* Nothing interesting to do here */
3421   } else {
3422     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3423       /* The mode is removed and we need to generate and distribute
3424          new channel key. Clients are not using private channel keys
3425          anymore after this. */
3426
3427       /* Re-generate channel key */
3428       silc_server_create_channel_key(server, channel, 0);
3429       
3430       /* Send the channel key. This sends it to our local clients and if
3431          we are normal server to our router as well. */
3432       silc_server_send_channel_key(server, NULL, channel, 
3433                                    server->server_type == SILC_ROUTER ? 
3434                                    FALSE : !server->standalone);
3435
3436       cipher = channel->channel_key->cipher->name;
3437       hmac = channel->hmac->hmac->name;
3438     }
3439   }
3440   
3441   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3442     /* User limit is set on channel */
3443     unsigned int user_limit;
3444       
3445     /* Get user limit */
3446     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3447     if (!tmp) {
3448       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3449         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3450                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3451         goto out;
3452       }
3453     } else {
3454       SILC_GET32_MSB(user_limit, tmp);
3455       channel->user_limit = user_limit;
3456     }
3457   } else {
3458     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3459       /* User limit mode is unset. Remove user limit */
3460       channel->user_limit = 0;
3461   }
3462
3463   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3464     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3465       /* Passphrase has been set to channel */
3466       
3467       /* Get the passphrase */
3468       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3469       if (!tmp) {
3470         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3471                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3472         goto out;
3473       }
3474
3475       /* Save the passphrase */
3476       channel->passphrase = strdup(tmp);
3477     }
3478   } else {
3479     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3480       /* Passphrase mode is unset. remove the passphrase */
3481       if (channel->passphrase) {
3482         silc_free(channel->passphrase);
3483         channel->passphrase = NULL;
3484       }
3485     }
3486   }
3487
3488   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3489     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3490       /* Cipher to use protect the traffic */
3491
3492       /* Get cipher */
3493       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3494       if (!cipher) {
3495         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3496                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3497         goto out;
3498       }
3499
3500       /* Delete old cipher and allocate the new one */
3501       silc_cipher_free(channel->channel_key);
3502       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3503         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3504                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3505         goto out;
3506       }
3507
3508       /* Re-generate channel key */
3509       silc_server_create_channel_key(server, channel, 0);
3510     
3511       /* Send the channel key. This sends it to our local clients and if
3512          we are normal server to our router as well. */
3513       silc_server_send_channel_key(server, NULL, channel, 
3514                                    server->server_type == SILC_ROUTER ? 
3515                                    FALSE : !server->standalone);
3516     }
3517   } else {
3518     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3519       /* Cipher mode is unset. Remove the cipher and revert back to 
3520          default cipher */
3521       cipher = channel->cipher;
3522
3523       /* Delete old cipher and allocate default one */
3524       silc_cipher_free(channel->channel_key);
3525       if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", 
3526                              &channel->channel_key)) {
3527         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3528                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3529         goto out;
3530       }
3531
3532       /* Re-generate channel key */
3533       silc_server_create_channel_key(server, channel, 0);
3534       
3535       /* Send the channel key. This sends it to our local clients and if
3536          we are normal server to our router as well. */
3537       silc_server_send_channel_key(server, NULL, channel, 
3538                                    server->server_type == SILC_ROUTER ? 
3539                                    FALSE : !server->standalone);
3540     }
3541   }
3542
3543   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3544     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3545       /* HMAC to use protect the traffic */
3546       unsigned char hash[32];
3547
3548       /* Get hmac */
3549       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3550       if (!hmac) {
3551         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3552                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3553         goto out;
3554       }
3555
3556       /* Delete old hmac and allocate the new one */
3557       silc_hmac_free(channel->hmac);
3558       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3559         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3560                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3561         goto out;
3562       }
3563
3564       /* Set the HMAC key out of current channel key. The client must do
3565          this locally. */
3566       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3567                      hash);
3568       silc_hmac_set_key(channel->hmac, hash, 
3569                         silc_hash_len(channel->hmac->hash));
3570       memset(hash, 0, sizeof(hash));
3571     }
3572   } else {
3573     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3574       /* Hmac mode is unset. Remove the hmac and revert back to 
3575          default hmac */
3576       unsigned char hash[32];
3577       hmac = channel->hmac_name;
3578
3579       /* Delete old hmac and allocate default one */
3580       silc_hmac_free(channel->hmac);
3581       if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
3582                            &channel->hmac)) {
3583         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3584                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3585         goto out;
3586       }
3587
3588       /* Set the HMAC key out of current channel key. The client must do
3589          this locally. */
3590       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3591                      hash);
3592       silc_hmac_set_key(channel->hmac, hash, 
3593                         silc_hash_len(channel->hmac->hash));
3594       memset(hash, 0, sizeof(hash));
3595     }
3596   }
3597
3598   /* Finally, set the mode */
3599   channel->mode = mode_mask;
3600
3601   /* Send CMODE_CHANGE notify */
3602   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3603   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3604                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3605                                      cidp->data, cidp->len, 
3606                                      tmp_mask, tmp_len,
3607                                      cipher, cipher ? strlen(cipher) : 0,
3608                                      hmac, hmac ? strlen(hmac) : 0);
3609
3610   /* Set CMODE notify type to network */
3611   if (!server->standalone)
3612     silc_server_send_notify_cmode(server, server->router->connection,
3613                                   server->server_type == SILC_ROUTER ? 
3614                                   TRUE : FALSE, channel,
3615                                   mode_mask, client->id, SILC_ID_CLIENT_LEN,
3616                                   cipher, hmac);
3617
3618   /* Send command reply to sender */
3619   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3620                                                 SILC_STATUS_OK, ident, 1,
3621                                                 2, tmp_mask, 4);
3622   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3623                           packet->data, packet->len, FALSE);
3624     
3625   silc_buffer_free(packet);
3626   silc_free(channel_id);
3627   silc_free(cidp);
3628
3629  out:
3630   silc_server_command_free(cmd);
3631 }
3632
3633 /* Server side of CUMODE command. Changes client's mode on a channel. */
3634
3635 SILC_SERVER_CMD_FUNC(cumode)
3636 {
3637   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3638   SilcServer server = cmd->server;
3639   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3640   SilcChannelID *channel_id;
3641   SilcClientID *client_id;
3642   SilcChannelEntry channel;
3643   SilcClientEntry target_client;
3644   SilcChannelClientEntry chl;
3645   SilcBuffer packet, idp;
3646   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3647   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3648   int notify = FALSE;
3649   unsigned short ident = silc_command_get_ident(cmd->payload);
3650
3651   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3652
3653   /* Get Channel ID */
3654   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3655   if (!tmp_ch_id) {
3656     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3657                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3658     goto out;
3659   }
3660   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3661   if (!channel_id) {
3662     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3663                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3664     goto out;
3665   }
3666
3667   /* Get channel entry */
3668   channel = silc_idlist_find_channel_by_id(server->local_list, 
3669                                            channel_id, NULL);
3670   if (!channel) {
3671     channel = silc_idlist_find_channel_by_id(server->global_list, 
3672                                              channel_id, NULL);
3673     if (!channel) {
3674       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3675                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3676       goto out;
3677     }
3678   }
3679
3680   /* Check whether sender is on the channel */
3681   if (!silc_server_client_on_channel(client, channel)) {
3682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3683                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3684     goto out;
3685   }
3686
3687   /* Check that client has rights to change other's rights */
3688   silc_list_start(channel->user_list);
3689   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3690     if (chl->client == client) {
3691       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3692           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3693         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3694                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3695         goto out;
3696       }
3697
3698       sender_mask = chl->mode;
3699       break;
3700     }
3701   }
3702   
3703   /* Get the target client's channel mode mask */
3704   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3705   if (!tmp_mask) {
3706     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3707                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3708     goto out;
3709   }
3710   SILC_GET32_MSB(target_mask, tmp_mask);
3711
3712   /* Get target Client ID */
3713   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3714   if (!tmp_id) {
3715     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3716                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3717     goto out;
3718   }
3719   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3720   if (!client_id) {
3721     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3722                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3723     goto out;
3724   }
3725
3726   /* Get target client's entry */
3727   target_client = silc_idlist_find_client_by_id(server->local_list, 
3728                                                 client_id, NULL);
3729   if (!target_client) {
3730     target_client = silc_idlist_find_client_by_id(server->global_list, 
3731                                                   client_id, NULL);
3732   }
3733
3734   /* Check whether target client is on the channel */
3735   if (!silc_server_client_on_channel(target_client, channel)) {
3736     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3737                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3738     goto out;
3739   }
3740
3741   /* Get entry to the channel user list */
3742   silc_list_start(channel->user_list);
3743   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3744     if (chl->client == target_client)
3745       break;
3746
3747   /* 
3748    * Change the mode 
3749    */
3750
3751   /* If the target client is founder, no one else can change their mode
3752      but themselves. */
3753   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3754     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3755                                           SILC_STATUS_ERR_NOT_YOU);
3756     goto out;
3757   }
3758
3759   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3760     /* Cannot promote anyone to channel founder */
3761     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3762                                           SILC_STATUS_ERR_NOT_YOU);
3763     goto out;
3764   } else {
3765     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3766       if (target_client == client) {
3767         /* Remove channel founder rights from itself */
3768         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3769         notify = TRUE;
3770       } else {
3771         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3772                                               SILC_STATUS_ERR_NOT_YOU);
3773         goto out;
3774       }
3775     }
3776   }
3777
3778   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3779     /* Promote to operator */
3780     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3781       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3782       notify = TRUE;
3783     }
3784   } else {
3785     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3786       /* Demote to normal user */
3787       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3788       notify = TRUE;
3789     }
3790   }
3791
3792   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3793
3794   /* Send notify to channel, notify only if mode was actually changed. */
3795   if (notify) {
3796     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3797                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3798                                        idp->data, idp->len,
3799                                        tmp_mask, 4, 
3800                                        tmp_id, tmp_len);
3801
3802     /* Set CUMODE notify type to network */
3803     if (!server->standalone)
3804       silc_server_send_notify_cumode(server, server->router->connection,
3805                                      server->server_type == SILC_ROUTER ? 
3806                                      TRUE : FALSE, channel,
3807                                      target_mask, client->id, 
3808                                      SILC_ID_CLIENT_LEN,
3809                                      target_client->id, 
3810                                      SILC_ID_CLIENT_LEN);
3811   }
3812
3813   /* Send command reply to sender */
3814   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3815                                                 SILC_STATUS_OK, ident, 2,
3816                                                 2, tmp_mask, 4,
3817                                                 3, tmp_id, tmp_len);
3818   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3819                           packet->data, packet->len, FALSE);
3820     
3821   silc_buffer_free(packet);
3822   silc_free(channel_id);
3823   silc_free(client_id);
3824   silc_buffer_free(idp);
3825
3826  out:
3827   silc_server_command_free(cmd);
3828 }
3829
3830 /* Server side of KICK command. Kicks client out of channel. */
3831
3832 SILC_SERVER_CMD_FUNC(kick)
3833 {
3834   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3835   SilcServer server = cmd->server;
3836   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3837   SilcClientEntry target_client;
3838   SilcChannelID *channel_id;
3839   SilcClientID *client_id;
3840   SilcChannelEntry channel;
3841   SilcChannelClientEntry chl;
3842   SilcBuffer idp;
3843   unsigned int tmp_len;
3844   unsigned char *tmp, *comment;
3845
3846   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3847
3848   /* Get Channel ID */
3849   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3850   if (!tmp) {
3851     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3852                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3853     goto out;
3854   }
3855   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3856   if (!channel_id) {
3857     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3858                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3859     goto out;
3860   }
3861
3862   /* Get channel entry */
3863   channel = silc_idlist_find_channel_by_id(server->local_list, 
3864                                            channel_id, NULL);
3865   if (!channel) {
3866     channel = silc_idlist_find_channel_by_id(server->local_list, 
3867                                              channel_id, NULL);
3868     if (!channel) {
3869       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3870                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3871       goto out;
3872     }
3873   }
3874
3875   /* Check whether sender is on the channel */
3876   if (!silc_server_client_on_channel(client, channel)) {
3877     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3878                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3879     goto out;
3880   }
3881
3882   /* Check that the kicker is channel operator or channel founder */
3883   silc_list_start(channel->user_list);
3884   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3885     if (chl->client == client) {
3886       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3887         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3888                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3889         goto out;
3890       }
3891       break;
3892     }
3893   }
3894   
3895   /* Get target Client ID */
3896   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3897   if (!tmp) {
3898     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3899                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3900     goto out;
3901   }
3902   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3903   if (!client_id) {
3904     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3905                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3906     goto out;
3907   }
3908
3909   /* Get target client's entry */
3910   target_client = silc_idlist_find_client_by_id(server->local_list, 
3911                                                 client_id, NULL);
3912   if (!target_client) {
3913     target_client = silc_idlist_find_client_by_id(server->global_list, 
3914                                                   client_id, NULL);
3915   }
3916
3917   /* Check that the target client is not channel founder. Channel founder
3918      cannot be kicked from the channel. */
3919   silc_list_start(channel->user_list);
3920   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3921     if (chl->client == target_client) {
3922       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3923         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3924                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3925         goto out;
3926       }
3927       break;
3928     }
3929   }
3930   
3931   /* Check whether target client is on the channel */
3932   if (!silc_server_client_on_channel(target_client, channel)) {
3933     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3934                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3935     goto out;
3936   }
3937
3938   /* Get comment */
3939   tmp_len = 0;
3940   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3941   if (tmp_len > 128)
3942     comment = NULL;
3943
3944   /* Send command reply to sender */
3945   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
3946                                         SILC_STATUS_OK);
3947
3948   /* Send KICKED notify to local clients on the channel */
3949   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3950   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3951                                      SILC_NOTIFY_TYPE_KICKED, 
3952                                      comment ? 2 : 1,
3953                                      idp->data, idp->len,
3954                                      comment, comment ? strlen(comment) : 0);
3955   silc_buffer_free(idp);
3956
3957   /* Remove the client from the channel. If the channel does not exist
3958      after removing the client then the client kicked itself off the channel
3959      and we don't have to send anything after that. */
3960   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
3961                                            target_client, FALSE))
3962     goto out;
3963
3964   /* Send KICKED notify to primary route */
3965   if (!server->standalone)
3966     silc_server_send_notify_kicked(server, server->router->connection,
3967                                    server->server_type == SILC_ROUTER ?
3968                                    TRUE : FALSE, channel,
3969                                    target_client->id, SILC_ID_CLIENT_LEN,
3970                                    comment);
3971
3972   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3973     /* Re-generate channel key */
3974     silc_server_create_channel_key(server, channel, 0);
3975     
3976     /* Send the channel key to the channel. The key of course is not sent
3977        to the client who was kicked off the channel. */
3978     silc_server_send_channel_key(server, target_client->connection, channel, 
3979                                  server->server_type == SILC_ROUTER ? 
3980                                  FALSE : !server->standalone);
3981   }
3982
3983  out:
3984   silc_server_command_free(cmd);
3985 }
3986
3987 /* Server side of OPER command. Client uses this comand to obtain server
3988    operator privileges to this server/router. */
3989
3990 SILC_SERVER_CMD_FUNC(oper)
3991 {
3992   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3993   SilcServer server = cmd->server;
3994   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3995   unsigned char *username, *auth;
3996   unsigned int tmp_len;
3997   SilcServerConfigSectionAdminConnection *admin;
3998   SilcIDListData idata = (SilcIDListData)client;
3999
4000   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
4001
4002   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4003     goto out;
4004
4005   /* Get the username */
4006   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4007   if (!username) {
4008     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4009                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4010     goto out;
4011   }
4012
4013   /* Get the admin configuration */
4014   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4015                                         username, client->nickname);
4016   if (!admin) {
4017     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4018                                           username, client->nickname);
4019     if (!admin) {
4020       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4021                                             SILC_STATUS_ERR_AUTH_FAILED);
4022       goto out;
4023     }
4024   }
4025
4026   /* Get the authentication payload */
4027   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4028   if (!auth) {
4029     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4030                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4031     goto out;
4032   }
4033
4034   /* Verify the authentication data */
4035   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4036                              admin->auth_data, admin->auth_data_len,
4037                              idata->hash, client->id, SILC_ID_CLIENT)) {
4038     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4039                                           SILC_STATUS_ERR_AUTH_FAILED);
4040     goto out;
4041   }
4042
4043   /* Client is now server operator */
4044   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4045
4046   /* Send UMODE change to primary router */
4047   if (!server->standalone)
4048     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4049                                   client->id, SILC_ID_CLIENT_LEN,
4050                                   client->mode);
4051
4052   /* Send reply to the sender */
4053   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4054                                         SILC_STATUS_OK);
4055
4056  out:
4057   silc_server_command_free(cmd);
4058 }
4059
4060 /* Server side of SILCOPER command. Client uses this comand to obtain router
4061    operator privileges to this router. */
4062
4063 SILC_SERVER_CMD_FUNC(silcoper)
4064 {
4065   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4066   SilcServer server = cmd->server;
4067   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4068   unsigned char *username, *auth;
4069   unsigned int tmp_len;
4070   SilcServerConfigSectionAdminConnection *admin;
4071   SilcIDListData idata = (SilcIDListData)client;
4072
4073   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4074
4075   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4076     goto out;
4077
4078   /* Get the username */
4079   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4080   if (!username) {
4081     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4082                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4083     goto out;
4084   }
4085
4086   /* Get the admin configuration */
4087   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4088                                         username, client->nickname);
4089   if (!admin) {
4090     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4091                                           username, client->nickname);
4092     if (!admin) {
4093       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4094                                             SILC_STATUS_ERR_AUTH_FAILED);
4095       goto out;
4096     }
4097   }
4098
4099   /* Get the authentication payload */
4100   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4101   if (!auth) {
4102     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4103                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4104     goto out;
4105   }
4106
4107   /* Verify the authentication data */
4108   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4109                              admin->auth_data, admin->auth_data_len,
4110                              idata->hash, client->id, SILC_ID_CLIENT)) {
4111     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4112                                           SILC_STATUS_ERR_AUTH_FAILED);
4113     goto out;
4114   }
4115
4116   /* Client is now router operator */
4117   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4118
4119   /* Send UMODE change to primary router */
4120   if (!server->standalone)
4121     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4122                                   client->id, SILC_ID_CLIENT_LEN,
4123                                   client->mode);
4124
4125   /* Send reply to the sender */
4126   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4127                                         SILC_STATUS_OK);
4128
4129  out:
4130   silc_server_command_free(cmd);
4131 }
4132
4133 /* Server side command of CONNECT. Connects us to the specified remote
4134    server or router. */
4135
4136 SILC_SERVER_CMD_FUNC(connect)
4137 {
4138   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4139   SilcServer server = cmd->server;
4140   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4141   unsigned char *tmp, *host;
4142   unsigned int tmp_len;
4143   unsigned int port = SILC_PORT;
4144
4145   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4146
4147   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4148     goto out;
4149
4150   /* Check whether client has the permissions. */
4151   if (client->mode == SILC_UMODE_NONE) {
4152     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4153                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4154     goto out;
4155   }
4156
4157   if (server->server_type == SILC_ROUTER && 
4158       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4159     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4160                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4161     goto out;
4162   }
4163
4164   /* Get the remote server */
4165   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4166   if (!host) {
4167     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4168                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4169     goto out;
4170   }
4171
4172   /* Get port */
4173   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4174   if (tmp)
4175     SILC_GET32_MSB(port, tmp);
4176
4177   /* Create the connection. It is done with timeout and is async. */
4178   silc_server_create_connection(server, host, port);
4179
4180   /* Send reply to the sender */
4181   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4182                                         SILC_STATUS_OK);
4183
4184  out:
4185   silc_server_command_free(cmd);
4186 }
4187
4188 SILC_SERVER_CMD_FUNC(restart)
4189 {
4190 }
4191
4192 /* Server side command of CLOSE. Closes connection to a specified server. */
4193  
4194 SILC_SERVER_CMD_FUNC(close)
4195 {
4196   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4197   SilcServer server = cmd->server;
4198   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4199   SilcServerEntry server_entry;
4200   SilcSocketConnection sock;
4201   unsigned char *tmp;
4202   unsigned int tmp_len;
4203   unsigned char *name;
4204   unsigned int port = SILC_PORT;
4205
4206   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4207
4208   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4209     goto out;
4210
4211   /* Check whether client has the permissions. */
4212   if (client->mode == SILC_UMODE_NONE) {
4213     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4214                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4215     goto out;
4216   }
4217
4218   /* Get the remote server */
4219   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4220   if (!name) {
4221     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4222                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4223     goto out;
4224   }
4225
4226   /* Get port */
4227   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4228   if (tmp)
4229     SILC_GET32_MSB(port, tmp);
4230
4231   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4232                                                  name, port, NULL);
4233   if (!server_entry) {
4234     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4235                                           SILC_STATUS_ERR_NO_SERVER_ID);
4236     goto out;
4237   }
4238
4239   /* Send reply to the sender */
4240   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4241                                         SILC_STATUS_OK);
4242
4243   /* Close the connection to the server */
4244   sock = (SilcSocketConnection)server_entry->connection;
4245   silc_server_free_sock_user_data(server, sock);
4246   silc_server_close_connection(server, sock);
4247   
4248  out:
4249   silc_server_command_free(cmd);
4250 }
4251
4252 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4253    active connections. */
4254  
4255 SILC_SERVER_CMD_FUNC(shutdown)
4256 {
4257   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4258   SilcServer server = cmd->server;
4259   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4260
4261   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4262
4263   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4264     goto out;
4265
4266   /* Check whether client has the permission. */
4267   if (client->mode == SILC_UMODE_NONE) {
4268     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4269                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4270     goto out;
4271   }
4272
4273   /* Send reply to the sender */
4274   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4275                                         SILC_STATUS_OK);
4276
4277   /* Then, gracefully, or not, bring the server down. */
4278   silc_server_stop(server);
4279   exit(0);
4280
4281  out:
4282   silc_server_command_free(cmd);
4283 }
4284  
4285 /* Server side command of LEAVE. Removes client from a channel. */
4286
4287 SILC_SERVER_CMD_FUNC(leave)
4288 {
4289   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4290   SilcServer server = cmd->server;
4291   SilcSocketConnection sock = cmd->sock;
4292   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4293   SilcChannelID *id;
4294   SilcChannelEntry channel;
4295   SilcBuffer packet;
4296   unsigned int i, len;
4297   unsigned char *tmp;
4298
4299   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4300
4301   /* Get Channel ID */
4302   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4303   if (!tmp) {
4304     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4305                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4306     goto out;
4307   }
4308   id = silc_id_payload_parse_id(tmp, len);
4309   if (!id) {
4310     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4311                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4312     goto out;
4313   }
4314
4315   /* Get channel entry */
4316   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4317   if (!channel) {
4318     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4319     if (!channel) {
4320       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4321                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4322       goto out;
4323     }
4324   }
4325
4326   /* Check whether this client is on the channel */
4327   if (!silc_server_client_on_channel(id_entry, channel)) {
4328     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4329                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4330     goto out;
4331   }
4332
4333   /* Notify routers that they should remove this client from their list
4334      of clients on the channel. Send LEAVE notify type. */
4335   if (!server->standalone)
4336     silc_server_send_notify_leave(server, server->router->connection,
4337                                   server->server_type == SILC_ROUTER ?
4338                                   TRUE : FALSE, channel, id_entry->id,
4339                                   SILC_ID_CLIENT_LEN);
4340
4341   /* Remove client from channel */
4342   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4343                                           TRUE);
4344   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4345                                         SILC_STATUS_OK);
4346
4347   /* If the channel does not exist anymore we won't send anything */
4348   if (!i)
4349     goto out;
4350
4351   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4352     /* Re-generate channel key */
4353     silc_server_create_channel_key(server, channel, 0);
4354
4355     /* Encode channel key payload to be distributed on the channel */
4356     packet = 
4357       silc_channel_key_payload_encode(len, tmp,
4358                                       strlen(channel->channel_key->
4359                                              cipher->name),
4360                                       channel->channel_key->cipher->name,
4361                                       channel->key_len / 8, channel->key);
4362
4363     /* If we are normal server then we will send it to our router.  If we
4364        are router we will send it to all local servers that has clients on
4365        the channel */
4366     if (server->server_type == SILC_SERVER) {
4367       if (!server->standalone)
4368         silc_server_packet_send(server, 
4369                                 cmd->server->router->connection,
4370                                 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4371                                 packet->len, FALSE);
4372     } else {
4373       
4374     }
4375
4376     /* Send to locally connected clients on the channel */
4377     silc_server_packet_send_local_channel(server, channel, 
4378                                           SILC_PACKET_CHANNEL_KEY, 0,
4379                                           packet->data, packet->len, FALSE);
4380
4381     silc_buffer_free(packet);
4382   }
4383
4384   silc_free(id);
4385
4386  out:
4387   silc_server_command_free(cmd);
4388 }
4389
4390 /* Server side of command USERS. Resolves clients and their USERS currently
4391    joined on the requested channel. The list of Client ID's and their modes
4392    on the channel is sent back. */
4393
4394 SILC_SERVER_CMD_FUNC(users)
4395 {
4396   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4397   SilcServer server = cmd->server;
4398   SilcChannelEntry channel;
4399   SilcChannelID *id;
4400   SilcBuffer packet;
4401   unsigned char *channel_id;
4402   unsigned int channel_id_len;
4403   SilcBuffer client_id_list;
4404   SilcBuffer client_mode_list;
4405   unsigned char lc[4];
4406   unsigned int list_count = 0;
4407   unsigned short ident = silc_command_get_ident(cmd->payload);
4408
4409   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4410
4411   /* Get Channel ID */
4412   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4413   if (!channel_id) {
4414     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4415                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4416     goto out;
4417   }
4418   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4419   if (!id) {
4420     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4421                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4422     goto out;
4423   }
4424
4425   /* If we are server and we don't know about this channel we will send
4426      the command to our router. If we know about the channel then we also
4427      have the list of users already. */
4428   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4429   if (!channel) {
4430     if (server->server_type == SILC_SERVER && !server->standalone &&
4431         !cmd->pending) {
4432       SilcBuffer tmpbuf;
4433       
4434       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4435       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4436       
4437       /* Send USERS command */
4438       silc_server_packet_send(server, server->router->connection,
4439                               SILC_PACKET_COMMAND, cmd->packet->flags,
4440                               tmpbuf->data, tmpbuf->len, TRUE);
4441       
4442       /* Reprocess this packet after received reply */
4443       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4444                                   silc_command_get_ident(cmd->payload),
4445                                   silc_server_command_destructor,
4446                                   silc_server_command_users,
4447                                   silc_server_command_dup(cmd));
4448       cmd->pending = TRUE;
4449       silc_command_set_ident(cmd->payload, ident);
4450       
4451       silc_buffer_free(tmpbuf);
4452       silc_free(id);
4453       return;
4454     }
4455
4456     /* We are router and we will check the global list as well. */
4457     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4458     if (!channel) {
4459       /* Channel really does not exist */
4460       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4461                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4462       goto out;
4463     }
4464   }
4465
4466   /* Get the users list */
4467   silc_server_get_users_on_channel(server, channel, &client_id_list,
4468                                    &client_mode_list, &list_count);
4469
4470   /* List count */
4471   SILC_PUT32_MSB(list_count, lc);
4472
4473   /* Send reply */
4474   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4475                                                 SILC_STATUS_OK, ident, 4,
4476                                                 2, channel_id, channel_id_len,
4477                                                 3, lc, 4,
4478                                                 4, client_id_list->data,
4479                                                 client_id_list->len,
4480                                                 5, client_mode_list->data,
4481                                                 client_mode_list->len);
4482   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4483                           packet->data, packet->len, FALSE);
4484     
4485   silc_buffer_free(packet);
4486   silc_buffer_free(client_id_list);
4487   silc_buffer_free(client_mode_list);
4488   silc_free(id);
4489
4490  out:
4491   silc_server_command_free(cmd);
4492 }
4493
4494 /* Server side of command BAN. This is used to manage the ban list of the
4495    channel. To add clients and remove clients from the ban list. */
4496
4497 SILC_SERVER_CMD_FUNC(ban)
4498 {
4499   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4500   SilcServer server = cmd->server;
4501   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4502   SilcBuffer packet;
4503   SilcChannelEntry channel;
4504   SilcChannelClientEntry chl;
4505   SilcChannelID *channel_id = NULL;
4506   unsigned char *id, *add, *del;
4507   unsigned int id_len, tmp_len;
4508   unsigned short ident = silc_command_get_ident(cmd->payload);
4509
4510   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4511     goto out;
4512
4513   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4514
4515   /* Get Channel ID */
4516   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4517   if (id) {
4518     channel_id = silc_id_payload_parse_id(id, id_len);
4519     if (!channel_id) {
4520       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4521                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4522       goto out;
4523     }
4524   }
4525
4526   /* Get channel entry. The server must know about the channel since the
4527      client is expected to be on the channel. */
4528   channel = silc_idlist_find_channel_by_id(server->local_list, 
4529                                            channel_id, NULL);
4530   if (!channel) {
4531     channel = silc_idlist_find_channel_by_id(server->global_list, 
4532                                              channel_id, NULL);
4533     if (!channel) {
4534       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4535                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4536       goto out;
4537     }
4538   }
4539
4540   /* Check whether this client is on the channel */
4541   if (!silc_server_client_on_channel(client, channel)) {
4542     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4543                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4544     goto out;
4545   }
4546
4547   /* Get entry to the channel user list */
4548   silc_list_start(channel->user_list);
4549   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4550     if (chl->client == client)
4551       break;
4552
4553   /* The client must be at least channel operator. */
4554   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4555     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4556                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4557     goto out;
4558   }
4559
4560   /* Get the new ban and add it to the ban list */
4561   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4562   if (add) {
4563     if (!channel->ban_list)
4564       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4565     else
4566       channel->ban_list = silc_realloc(channel->ban_list, 
4567                                        sizeof(*channel->ban_list) * 
4568                                        (tmp_len + 
4569                                         strlen(channel->ban_list) + 2));
4570     if (add[tmp_len - 1] == ',')
4571       add[tmp_len - 1] = '\0';
4572
4573     strncat(channel->ban_list, add, tmp_len);
4574     strncat(channel->ban_list, ",", 1);
4575   }
4576
4577   /* Get the ban to be removed and remove it from the list */
4578   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4579   if (del && channel->ban_list) {
4580     char *start, *end, *n;
4581
4582     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4583       silc_free(channel->ban_list);
4584       channel->ban_list = NULL;
4585     } else {
4586       start = strstr(channel->ban_list, del);
4587       if (start && strlen(start) >= tmp_len) {
4588         end = start + tmp_len;
4589         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4590         strncat(n, channel->ban_list, start - channel->ban_list);
4591         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4592                              end) - 1);
4593         silc_free(channel->ban_list);
4594         channel->ban_list = n;
4595       }
4596     }
4597   }
4598
4599   /* Send the BAN notify type to our primary router. */
4600   if (!server->standalone && (add || del))
4601     silc_server_send_notify_ban(server, server->router->connection,
4602                                 server->server_type == SILC_ROUTER ?
4603                                 TRUE : FALSE, channel, add, del);
4604
4605   /* Send the reply back to the client */
4606   if (channel->ban_list)
4607     packet = 
4608       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4609                                            SILC_STATUS_OK, ident, 2,
4610                                            2, id, id_len,
4611                                            3, channel->ban_list, 
4612                                            strlen(channel->ban_list) - 1);
4613   else
4614     packet = 
4615       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4616                                            SILC_STATUS_OK, ident, 1,
4617                                            2, id, id_len);
4618
4619   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4620                           packet->data, packet->len, FALSE);
4621     
4622   silc_buffer_free(packet);
4623
4624  out:
4625   if (channel_id)
4626     silc_free(channel_id);
4627   silc_server_command_free(cmd);
4628 }