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, 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   silc_server_send_channel_key(server, NULL, channel, 
2778                                server->server_type == SILC_ROUTER ? 
2779                                FALSE : !server->standalone);
2780
2781   /* Join the client to the channel by adding it to channel's user list.
2782      Add also the channel to client entry's channels list for fast cross-
2783      referencing. */
2784   chl = silc_calloc(1, sizeof(*chl));
2785   chl->mode = umode;
2786   chl->client = client;
2787   chl->channel = channel;
2788   silc_list_add(channel->user_list, chl);
2789   silc_list_add(client->channels, chl);
2790
2791   /* Get users on the channel */
2792   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
2793                                    &user_count);
2794
2795   /* Encode Client ID Payload of the original client who wants to join */
2796   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2797
2798   /* Encode command reply packet */
2799   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
2800   SILC_PUT32_MSB(channel->mode, mode);
2801   SILC_PUT32_MSB(created, tmp2);
2802   SILC_PUT32_MSB(user_count, tmp3);
2803   tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
2804   keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp, 
2805                                          strlen(channel->channel_key->
2806                                                 cipher->name),
2807                                          channel->channel_key->cipher->name,
2808                                          channel->key_len / 8, channel->key);
2809   silc_free(tmp);
2810   reply = 
2811     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
2812                                          SILC_STATUS_OK, ident, 13,
2813                                          2, channel->channel_name,
2814                                          strlen(channel->channel_name),
2815                                          3, chidp->data, chidp->len,
2816                                          4, clidp->data, clidp->len,
2817                                          5, mode, 4,
2818                                          6, tmp2, 4,
2819                                          7, keyp->data, keyp->len,
2820                                          8, channel->ban_list, 
2821                                          channel->ban_list ?
2822                                          strlen(channel->ban_list) : 0,
2823                                          9, channel->invite_list,
2824                                          channel->invite_list ?
2825                                          strlen(channel->invite_list) : 0,
2826                                          10, channel->topic,
2827                                          channel->topic ?
2828                                          strlen(channel->topic) : 0,
2829                                          11, channel->hmac->hmac->name,
2830                                          strlen(channel->hmac->hmac->name),
2831                                          12, tmp3, 4,
2832                                          13, user_list->data, user_list->len,
2833                                          14, mode_list->data, 
2834                                          mode_list->len);
2835
2836   /* Send command reply */
2837   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
2838                           reply->data, reply->len, FALSE);
2839
2840   if (!cmd->pending) {
2841     /* Send JOIN notify to locally connected clients on the channel */
2842     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2843                                        SILC_NOTIFY_TYPE_JOIN, 2,
2844                                        clidp->data, clidp->len,
2845                                        chidp->data, chidp->len);
2846
2847     /* Send JOIN notify packet to our primary router */
2848     if (!server->standalone)
2849       silc_server_send_notify_join(server, server->router->connection,
2850                                    server->server_type == SILC_ROUTER ?
2851                                    TRUE : FALSE, channel, client->id,
2852                                    SILC_ID_CLIENT_LEN);
2853   }
2854
2855   silc_buffer_free(reply);
2856   silc_buffer_free(clidp);
2857   silc_buffer_free(chidp);
2858   silc_buffer_free(keyp);
2859   silc_buffer_free(user_list);
2860   silc_buffer_free(mode_list);
2861
2862  out:
2863   if (passphrase)
2864     silc_free(passphrase);
2865 }
2866
2867 /* Server side of command JOIN. Joins client into requested channel. If 
2868    the channel does not exist it will be created. */
2869
2870 SILC_SERVER_CMD_FUNC(join)
2871 {
2872   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2873   SilcServer server = cmd->server;
2874   int tmp_len;
2875   char *tmp, *channel_name = NULL, *cipher, *hmac;
2876   SilcChannelEntry channel;
2877   unsigned int umode = 0;
2878   int created = FALSE;
2879   SilcClientID *client_id;
2880
2881   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2882
2883   /* Get channel name */
2884   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2885   if (!tmp) {
2886     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2887                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2888     goto out;
2889   }
2890   channel_name = tmp;
2891
2892   if (strlen(channel_name) > 256)
2893     channel_name[255] = '\0';
2894
2895   if (silc_server_command_bad_chars(channel_name) == TRUE) {
2896     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2897                                           SILC_STATUS_ERR_BAD_CHANNEL);
2898     silc_free(channel_name);
2899     goto out;
2900   }
2901
2902   /* Get Client ID of the client who is joining to the channel */
2903   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2904   if (!tmp) {
2905     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2906                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2907     goto out;
2908   }
2909   client_id = silc_id_payload_parse_id(tmp, tmp_len);
2910   if (!client_id) {
2911     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2912                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2913     goto out;
2914   }
2915
2916   /* Get cipher and hmac name */
2917   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2918   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2919
2920   /* See if the channel exists */
2921   channel = silc_idlist_find_channel_by_name(server->local_list, 
2922                                              channel_name, NULL);
2923
2924   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2925     /* If this is coming from client the Client ID in the command packet must
2926        be same as the client's ID. */
2927     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2928       SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2929       if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2930         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2931                                         SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2932         goto out;
2933       }
2934     }
2935
2936     if (!channel) {
2937       /* Channel not found */
2938
2939       /* If we are standalone server we don't have a router, we just create 
2940          the channel by ourselves. */
2941       if (server->standalone) {
2942         channel = silc_server_create_new_channel(server, server->id, cipher, 
2943                                                  hmac, channel_name, TRUE);
2944         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2945         created = TRUE;
2946
2947       } else {
2948
2949         /* The channel does not exist on our server. If we are normal server 
2950            we will send JOIN command to our router which will handle the
2951            joining procedure (either creates the channel if it doesn't exist 
2952            or joins the client to it). */
2953         if (server->server_type == SILC_SERVER) {
2954           SilcBuffer tmpbuf;
2955           unsigned short old_ident;
2956           
2957           old_ident = silc_command_get_ident(cmd->payload);
2958           silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2959           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2960           
2961           /* Send JOIN command to our router */
2962           silc_server_packet_send(server, (SilcSocketConnection)
2963                                   server->router->connection,
2964                                   SILC_PACKET_COMMAND, cmd->packet->flags,
2965                                   tmpbuf->data, tmpbuf->len, TRUE);
2966           
2967           /* Reprocess this packet after received reply from router */
2968           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
2969                                       silc_command_get_ident(cmd->payload),
2970                                       silc_server_command_destructor,
2971                                       silc_server_command_join,
2972                                       silc_server_command_dup(cmd));
2973           cmd->pending = TRUE;
2974           return;
2975         }
2976         
2977         /* We are router and the channel does not seem exist so we will check
2978            our global list as well for the channel. */
2979         channel = silc_idlist_find_channel_by_name(server->global_list, 
2980                                                    channel_name, NULL);
2981         if (!channel) {
2982           /* Channel really does not exist, create it */
2983           channel = silc_server_create_new_channel(server, server->id, cipher, 
2984                                                    hmac, channel_name, TRUE);
2985           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2986           created = TRUE;
2987         }
2988       }
2989     }
2990   } else {
2991     if (!channel) {
2992       /* Channel not found */
2993
2994       /* If the command came from router and/or we are normal server then
2995          something went wrong with the joining as the channel was not found.
2996          We can't do anything else but ignore this. */
2997       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2998           server->server_type == SILC_SERVER)
2999         goto out;
3000       
3001       /* We are router and the channel does not seem exist so we will check
3002          our global list as well for the channel. */
3003       channel = silc_idlist_find_channel_by_name(server->global_list, 
3004                                                  channel_name, NULL);
3005       if (!channel) {
3006         /* Channel really does not exist, create it */
3007         channel = silc_server_create_new_channel(server, server->id, cipher, 
3008                                                  hmac, channel_name, TRUE);
3009         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3010         created = TRUE;
3011       }
3012     }
3013   }
3014
3015   /* If the channel does not have global users and is also empty it means the
3016      channel was created globally (by our router) and the client will be the
3017      channel founder and operator. */
3018   if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
3019     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3020     created = TRUE;             /* Created globally by our router */
3021   }
3022
3023   /* Join to the channel */
3024   silc_server_command_join_channel(server, cmd, channel, client_id,
3025                                    created, umode);
3026
3027   silc_free(client_id);
3028
3029  out:
3030   silc_server_command_free(cmd);
3031 }
3032
3033 /* Server side of command MOTD. Sends server's current "message of the
3034    day" to the client. */
3035
3036 SILC_SERVER_CMD_FUNC(motd)
3037 {
3038   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3039   SilcServer server = cmd->server;
3040   SilcBuffer packet, idp;
3041   char *motd, *dest_server;
3042   int motd_len;
3043   unsigned short ident = silc_command_get_ident(cmd->payload);
3044   
3045   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 1);
3046
3047   /* Get server name */
3048   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3049   if (!dest_server) {
3050     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3051                                           SILC_STATUS_ERR_NO_SUCH_SERVER);
3052     goto out;
3053   }
3054
3055   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3056     /* Send our MOTD */
3057
3058     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3059
3060     if (server->config && server->config->motd && 
3061         server->config->motd->motd_file) {
3062       /* Send motd */
3063       motd = silc_file_read(server->config->motd->motd_file, &motd_len);
3064       if (!motd)
3065         goto out;
3066       
3067       motd[motd_len] = 0;
3068       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3069                                                     SILC_STATUS_OK, ident, 2,
3070                                                     2, idp, idp->len,
3071                                                     3, motd, motd_len);
3072       goto out;
3073     } else {
3074       /* No motd */
3075       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3076                                                     SILC_STATUS_OK, ident, 1,
3077                                                     2, idp, idp->len);
3078     }
3079
3080     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3081                             packet->data, packet->len, FALSE);
3082     silc_buffer_free(packet);
3083     silc_buffer_free(idp);
3084   } else {
3085     SilcServerEntry entry;
3086
3087     /* Check whether we have this server cached */
3088     entry = silc_idlist_find_server_by_name(server->global_list,
3089                                             dest_server, NULL);
3090     if (!entry) {
3091       entry = silc_idlist_find_server_by_name(server->local_list,
3092                                               dest_server, NULL);
3093     }
3094
3095     if (server->server_type == SILC_ROUTER && !cmd->pending && 
3096         entry && !entry->motd) {
3097       /* Send to the server */
3098       SilcBuffer tmpbuf;
3099       unsigned short old_ident;
3100
3101       old_ident = silc_command_get_ident(cmd->payload);
3102       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3103       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3104
3105       silc_server_packet_send(server, entry->connection,
3106                               SILC_PACKET_COMMAND, cmd->packet->flags,
3107                               tmpbuf->data, tmpbuf->len, TRUE);
3108
3109       /* Reprocess this packet after received reply from router */
3110       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3111                                   silc_command_get_ident(cmd->payload),
3112                                   silc_server_command_destructor,
3113                                   silc_server_command_motd,
3114                                   silc_server_command_dup(cmd));
3115       cmd->pending = TRUE;
3116       silc_command_set_ident(cmd->payload, old_ident);
3117       silc_buffer_free(tmpbuf);
3118       return;
3119     }
3120
3121     if (!entry && !cmd->pending && !server->standalone) {
3122       /* Send to the primary router */
3123       SilcBuffer tmpbuf;
3124       unsigned short old_ident;
3125
3126       old_ident = silc_command_get_ident(cmd->payload);
3127       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3128       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3129
3130       silc_server_packet_send(server, server->router->connection,
3131                               SILC_PACKET_COMMAND, cmd->packet->flags,
3132                               tmpbuf->data, tmpbuf->len, TRUE);
3133
3134       /* Reprocess this packet after received reply from router */
3135       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3136                                   silc_command_get_ident(cmd->payload),
3137                                   silc_server_command_destructor,
3138                                   silc_server_command_motd,
3139                                   silc_server_command_dup(cmd));
3140       cmd->pending = TRUE;
3141       silc_command_set_ident(cmd->payload, old_ident);
3142       silc_buffer_free(tmpbuf);
3143       return;
3144     }
3145
3146     if (!entry) {
3147       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3148                                             SILC_STATUS_ERR_NO_SUCH_SERVER);
3149       goto out;
3150     }
3151
3152     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3153
3154     if (entry->motd)
3155       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3156                                                     SILC_STATUS_OK, ident, 2,
3157                                                     2, idp, idp->len,
3158                                                     3, entry->motd,
3159                                                     strlen(entry->motd));
3160     else
3161       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3162                                                     SILC_STATUS_OK, ident, 1,
3163                                                     2, idp, idp->len);
3164
3165     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3166                             packet->data, packet->len, FALSE);
3167     silc_buffer_free(packet);
3168     silc_buffer_free(idp);
3169   }
3170
3171  out:
3172   silc_server_command_free(cmd);
3173 }
3174
3175 /* Server side of command UMODE. Client can use this command to set/unset
3176    user mode. Client actually cannot set itself to be as server/router
3177    operator so this can be used only to unset the modes. */
3178
3179 SILC_SERVER_CMD_FUNC(umode)
3180 {
3181   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3182   SilcServer server = cmd->server;
3183   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3184   SilcBuffer packet;
3185   unsigned char *tmp_mask;
3186   unsigned int mask;
3187   unsigned short ident = silc_command_get_ident(cmd->payload);
3188
3189   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3190     goto out;
3191
3192   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_UMODE, cmd, 2, 2);
3193
3194   /* Get the client's mode mask */
3195   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3196   if (!tmp_mask) {
3197     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3198                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3199     goto out;
3200   }
3201   SILC_GET32_MSB(mask, tmp_mask);
3202
3203   /* 
3204    * Change the mode 
3205    */
3206
3207   if (mask & SILC_UMODE_SERVER_OPERATOR) {
3208     /* Cannot operator mode */
3209     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3210                                           SILC_STATUS_ERR_PERM_DENIED);
3211     goto out;
3212   } else {
3213     if (client->mode & SILC_UMODE_SERVER_OPERATOR)
3214       /* Remove the server operator rights */
3215       client->mode &= ~SILC_UMODE_SERVER_OPERATOR;
3216   }
3217
3218   if (mask & SILC_UMODE_ROUTER_OPERATOR) {
3219     /* Cannot operator mode */
3220     silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3221                                           SILC_STATUS_ERR_PERM_DENIED);
3222     goto out;
3223   } else {
3224     if (client->mode & SILC_UMODE_ROUTER_OPERATOR)
3225       /* Remove the router operator rights */
3226       client->mode &= ~SILC_UMODE_ROUTER_OPERATOR;
3227   }
3228
3229   /* Send UMODE change to primary router */
3230   if (!server->standalone)
3231     silc_server_send_notify_umode(server, server->router->connection, TRUE,
3232                                   client->id, SILC_ID_CLIENT_LEN,
3233                                   client->mode);
3234
3235   /* Send command reply to sender */
3236   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3237                                                 SILC_STATUS_OK, ident, 1,
3238                                                 2, tmp_mask, 4);
3239   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3240                           packet->data, packet->len, FALSE);
3241   silc_buffer_free(packet);
3242
3243  out:
3244   silc_server_command_free(cmd);
3245 }
3246
3247 /* Checks that client has rights to add or remove channel modes. If any
3248    of the checks fails FALSE is returned. */
3249
3250 int silc_server_check_cmode_rights(SilcChannelEntry channel,
3251                                    SilcChannelClientEntry client,
3252                                    unsigned int mode)
3253 {
3254   int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
3255   int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
3256
3257   /* Check whether has rights to change anything */
3258   if (!is_op && !is_fo)
3259     return FALSE;
3260
3261   /* Check whether has rights to change everything */
3262   if (is_op && is_fo)
3263     return TRUE;
3264
3265   /* We know that client is channel operator, check that they are not
3266      changing anything that requires channel founder rights. Rest of the
3267      modes are available automatically for channel operator. */
3268
3269   if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
3270     if (is_op && !is_fo)
3271       return FALSE;
3272   } else {
3273     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3274       if (is_op && !is_fo)
3275         return FALSE;
3276     }
3277   }
3278   
3279   if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3280     if (is_op && !is_fo)
3281       return FALSE;
3282   } else {
3283     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3284       if (is_op && !is_fo)
3285         return FALSE;
3286     }
3287   }
3288
3289   if (mode & SILC_CHANNEL_MODE_CIPHER) {
3290     if (is_op && !is_fo)
3291       return FALSE;
3292   } else {
3293     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3294       if (is_op && !is_fo)
3295         return FALSE;
3296     }
3297   }
3298   
3299   return TRUE;
3300 }
3301
3302 /* Server side command of CMODE. Changes channel mode */
3303
3304 SILC_SERVER_CMD_FUNC(cmode)
3305 {
3306   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3307   SilcServer server = cmd->server;
3308   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3309   SilcChannelID *channel_id;
3310   SilcChannelEntry channel;
3311   SilcChannelClientEntry chl;
3312   SilcBuffer packet, cidp;
3313   unsigned char *tmp, *tmp_id, *tmp_mask;
3314   char *cipher = NULL, *hmac = NULL;
3315   unsigned int argc, mode_mask, tmp_len, tmp_len2;
3316   unsigned short ident = silc_command_get_ident(cmd->payload);
3317
3318   SILC_LOG_DEBUG(("Start"));
3319
3320   argc = silc_argument_get_arg_num(cmd->args);
3321   if (argc < 2) {
3322     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3323                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3324     goto out;
3325   }
3326   if (argc > 8) {
3327     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3328                                           SILC_STATUS_ERR_TOO_MANY_PARAMS);
3329     goto out;
3330   }
3331
3332   /* Get Channel ID */
3333   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3334   if (!tmp_id) {
3335     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3336                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3337     goto out;
3338   }
3339   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
3340   if (!channel_id) {
3341     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3342                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3343     goto out;
3344   }
3345
3346   /* Get the channel mode mask */
3347   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3348   if (!tmp_mask) {
3349     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3350                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3351     goto out;
3352   }
3353   SILC_GET32_MSB(mode_mask, tmp_mask);
3354
3355   /* Get channel entry */
3356   channel = silc_idlist_find_channel_by_id(server->local_list, 
3357                                            channel_id, NULL);
3358   if (!channel) {
3359     channel = silc_idlist_find_channel_by_id(server->global_list, 
3360                                              channel_id, NULL);
3361     if (!channel) {
3362       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3363                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3364       goto out;
3365     }
3366   }
3367
3368   /* Check whether this client is on the channel */
3369   if (!silc_server_client_on_channel(client, channel)) {
3370     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3371                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3372     goto out;
3373   }
3374
3375   /* Get entry to the channel user list */
3376   silc_list_start(channel->user_list);
3377   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3378     if (chl->client == client)
3379       break;
3380
3381   /* Check that client has rights to change any requested channel modes */
3382   if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
3383     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3384                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3385     goto out;
3386   }
3387
3388   /*
3389    * Check the modes. Modes that requires nothing special operation are
3390    * not checked here.
3391    */
3392
3393   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
3394     /* Channel uses private keys to protect traffic. Client(s) has set the
3395        key locally they want to use, server does not know that key. */
3396     /* Nothing interesting to do here */
3397   } else {
3398     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
3399       /* The mode is removed and we need to generate and distribute
3400          new channel key. Clients are not using private channel keys
3401          anymore after this. */
3402
3403       /* Re-generate channel key */
3404       silc_server_create_channel_key(server, channel, 0);
3405       
3406       /* Send the channel key. This sends it to our local clients and if
3407          we are normal server to our router as well. */
3408       silc_server_send_channel_key(server, NULL, channel, 
3409                                    server->server_type == SILC_ROUTER ? 
3410                                    FALSE : !server->standalone);
3411
3412       cipher = channel->channel_key->cipher->name;
3413       hmac = channel->hmac->hmac->name;
3414     }
3415   }
3416   
3417   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
3418     /* User limit is set on channel */
3419     unsigned int user_limit;
3420       
3421     /* Get user limit */
3422     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
3423     if (!tmp) {
3424       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
3425         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3426                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3427         goto out;
3428       }
3429     } else {
3430       SILC_GET32_MSB(user_limit, tmp);
3431       channel->user_limit = user_limit;
3432     }
3433   } else {
3434     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
3435       /* User limit mode is unset. Remove user limit */
3436       channel->user_limit = 0;
3437   }
3438
3439   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
3440     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
3441       /* Passphrase has been set to channel */
3442       
3443       /* Get the passphrase */
3444       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
3445       if (!tmp) {
3446         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3447                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3448         goto out;
3449       }
3450
3451       /* Save the passphrase */
3452       channel->passphrase = strdup(tmp);
3453     }
3454   } else {
3455     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3456       /* Passphrase mode is unset. remove the passphrase */
3457       if (channel->passphrase) {
3458         silc_free(channel->passphrase);
3459         channel->passphrase = NULL;
3460       }
3461     }
3462   }
3463
3464   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
3465     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
3466       /* Cipher to use protect the traffic */
3467
3468       /* Get cipher */
3469       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
3470       if (!cipher) {
3471         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3472                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3473         goto out;
3474       }
3475
3476       /* Delete old cipher and allocate the new one */
3477       silc_cipher_free(channel->channel_key);
3478       if (!silc_cipher_alloc(cipher, &channel->channel_key)) {
3479         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3480                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3481         goto out;
3482       }
3483
3484       /* Re-generate channel key */
3485       silc_server_create_channel_key(server, channel, 0);
3486     
3487       /* Send the channel key. This sends it to our local clients and if
3488          we are normal server to our router as well. */
3489       silc_server_send_channel_key(server, NULL, channel, 
3490                                    server->server_type == SILC_ROUTER ? 
3491                                    FALSE : !server->standalone);
3492     }
3493   } else {
3494     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
3495       /* Cipher mode is unset. Remove the cipher and revert back to 
3496          default cipher */
3497       cipher = channel->cipher;
3498
3499       /* Delete old cipher and allocate default one */
3500       silc_cipher_free(channel->channel_key);
3501       if (!silc_cipher_alloc(cipher ? cipher : "aes-256-cbc", 
3502                              &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   }
3518
3519   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
3520     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
3521       /* HMAC to use protect the traffic */
3522       unsigned char hash[32];
3523
3524       /* Get hmac */
3525       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
3526       if (!hmac) {
3527         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3528                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3529         goto out;
3530       }
3531
3532       /* Delete old hmac and allocate the new one */
3533       silc_hmac_free(channel->hmac);
3534       if (!silc_hmac_alloc(hmac, NULL, &channel->hmac)) {
3535         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3536                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
3537         goto out;
3538       }
3539
3540       /* Set the HMAC key out of current channel key. The client must do
3541          this locally. */
3542       silc_hash_make(channel->hmac->hash, channel->key, channel->key_len / 8, 
3543                      hash);
3544       silc_hmac_set_key(channel->hmac, hash, 
3545                         silc_hash_len(channel->hmac->hash));
3546       memset(hash, 0, sizeof(hash));
3547     }
3548   } else {
3549     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
3550       /* Hmac mode is unset. Remove the hmac and revert back to 
3551          default hmac */
3552       unsigned char hash[32];
3553       hmac = channel->hmac_name;
3554
3555       /* Delete old hmac and allocate default one */
3556       silc_hmac_free(channel->hmac);
3557       if (!silc_hmac_alloc(hmac ? hmac : "hmac-sha1-96", NULL, 
3558                            &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   }
3573
3574   /* Finally, set the mode */
3575   channel->mode = mode_mask;
3576
3577   /* Send CMODE_CHANGE notify */
3578   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3579   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3580                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 4,
3581                                      cidp->data, cidp->len, 
3582                                      tmp_mask, tmp_len,
3583                                      cipher, cipher ? strlen(cipher) : 0,
3584                                      hmac, hmac ? strlen(hmac) : 0);
3585
3586   /* Set CMODE notify type to network */
3587   if (!server->standalone)
3588     silc_server_send_notify_cmode(server, server->router->connection,
3589                                   server->server_type == SILC_ROUTER ? 
3590                                   TRUE : FALSE, channel,
3591                                   mode_mask, client->id, SILC_ID_CLIENT_LEN,
3592                                   cipher, hmac);
3593
3594   /* Send command reply to sender */
3595   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
3596                                                 SILC_STATUS_OK, ident, 1,
3597                                                 2, tmp_mask, 4);
3598   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3599                           packet->data, packet->len, FALSE);
3600     
3601   silc_buffer_free(packet);
3602   silc_free(channel_id);
3603   silc_free(cidp);
3604
3605  out:
3606   silc_server_command_free(cmd);
3607 }
3608
3609 /* Server side of CUMODE command. Changes client's mode on a channel. */
3610
3611 SILC_SERVER_CMD_FUNC(cumode)
3612 {
3613   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3614   SilcServer server = cmd->server;
3615   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3616   SilcChannelID *channel_id;
3617   SilcClientID *client_id;
3618   SilcChannelEntry channel;
3619   SilcClientEntry target_client;
3620   SilcChannelClientEntry chl;
3621   SilcBuffer packet, idp;
3622   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
3623   unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
3624   int notify = FALSE;
3625   unsigned short ident = silc_command_get_ident(cmd->payload);
3626
3627   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
3628
3629   /* Get Channel ID */
3630   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
3631   if (!tmp_ch_id) {
3632     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3633                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3634     goto out;
3635   }
3636   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
3637   if (!channel_id) {
3638     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3639                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3640     goto out;
3641   }
3642
3643   /* Get channel entry */
3644   channel = silc_idlist_find_channel_by_id(server->local_list, 
3645                                            channel_id, NULL);
3646   if (!channel) {
3647     channel = silc_idlist_find_channel_by_id(server->global_list, 
3648                                              channel_id, NULL);
3649     if (!channel) {
3650       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3651                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3652       goto out;
3653     }
3654   }
3655
3656   /* Check whether sender is on the channel */
3657   if (!silc_server_client_on_channel(client, channel)) {
3658     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3659                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3660     goto out;
3661   }
3662
3663   /* Check that client has rights to change other's rights */
3664   silc_list_start(channel->user_list);
3665   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3666     if (chl->client == client) {
3667       if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
3668           !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3669         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3670                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3671         goto out;
3672       }
3673
3674       sender_mask = chl->mode;
3675       break;
3676     }
3677   }
3678   
3679   /* Get the target client's channel mode mask */
3680   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3681   if (!tmp_mask) {
3682     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3683                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3684     goto out;
3685   }
3686   SILC_GET32_MSB(target_mask, tmp_mask);
3687
3688   /* Get target Client ID */
3689   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3690   if (!tmp_id) {
3691     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3692                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3693     goto out;
3694   }
3695   client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
3696   if (!client_id) {
3697     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3698                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3699     goto out;
3700   }
3701
3702   /* Get target client's entry */
3703   target_client = silc_idlist_find_client_by_id(server->local_list, 
3704                                                 client_id, NULL);
3705   if (!target_client) {
3706     target_client = silc_idlist_find_client_by_id(server->global_list, 
3707                                                   client_id, NULL);
3708   }
3709
3710   /* Check whether target client is on the channel */
3711   if (!silc_server_client_on_channel(target_client, channel)) {
3712     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3713                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3714     goto out;
3715   }
3716
3717   /* Get entry to the channel user list */
3718   silc_list_start(channel->user_list);
3719   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
3720     if (chl->client == target_client)
3721       break;
3722
3723   /* 
3724    * Change the mode 
3725    */
3726
3727   /* If the target client is founder, no one else can change their mode
3728      but themselves. */
3729   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
3730     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3731                                           SILC_STATUS_ERR_NOT_YOU);
3732     goto out;
3733   }
3734
3735   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
3736     /* Cannot promote anyone to channel founder */
3737     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3738                                           SILC_STATUS_ERR_NOT_YOU);
3739     goto out;
3740   } else {
3741     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3742       if (target_client == client) {
3743         /* Remove channel founder rights from itself */
3744         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3745         notify = TRUE;
3746       } else {
3747         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
3748                                               SILC_STATUS_ERR_NOT_YOU);
3749         goto out;
3750       }
3751     }
3752   }
3753
3754   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
3755     /* Promote to operator */
3756     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
3757       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
3758       notify = TRUE;
3759     }
3760   } else {
3761     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
3762       /* Demote to normal user */
3763       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
3764       notify = TRUE;
3765     }
3766   }
3767
3768   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3769
3770   /* Send notify to channel, notify only if mode was actually changed. */
3771   if (notify) {
3772     silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3773                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
3774                                        idp->data, idp->len,
3775                                        tmp_mask, 4, 
3776                                        tmp_id, tmp_len);
3777
3778     /* Set CUMODE notify type to network */
3779     if (!server->standalone)
3780       silc_server_send_notify_cumode(server, server->router->connection,
3781                                      server->server_type == SILC_ROUTER ? 
3782                                      TRUE : FALSE, channel,
3783                                      target_mask, client->id, 
3784                                      SILC_ID_CLIENT_LEN,
3785                                      target_client->id, 
3786                                      SILC_ID_CLIENT_LEN);
3787   }
3788
3789   /* Send command reply to sender */
3790   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
3791                                                 SILC_STATUS_OK, ident, 2,
3792                                                 2, tmp_mask, 4,
3793                                                 3, tmp_id, tmp_len);
3794   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3795                           packet->data, packet->len, FALSE);
3796     
3797   silc_buffer_free(packet);
3798   silc_free(channel_id);
3799   silc_free(client_id);
3800   silc_buffer_free(idp);
3801
3802  out:
3803   silc_server_command_free(cmd);
3804 }
3805
3806 /* Server side of KICK command. Kicks client out of channel. */
3807
3808 SILC_SERVER_CMD_FUNC(kick)
3809 {
3810   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3811   SilcServer server = cmd->server;
3812   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3813   SilcClientEntry target_client;
3814   SilcChannelID *channel_id;
3815   SilcClientID *client_id;
3816   SilcChannelEntry channel;
3817   SilcChannelClientEntry chl;
3818   SilcBuffer idp;
3819   unsigned int tmp_len;
3820   unsigned char *tmp, *comment;
3821
3822   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
3823
3824   /* Get Channel ID */
3825   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3826   if (!tmp) {
3827     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3828                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3829     goto out;
3830   }
3831   channel_id = silc_id_payload_parse_id(tmp, tmp_len);
3832   if (!channel_id) {
3833     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3834                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
3835     goto out;
3836   }
3837
3838   /* Get channel entry */
3839   channel = silc_idlist_find_channel_by_id(server->local_list, 
3840                                            channel_id, NULL);
3841   if (!channel) {
3842     channel = silc_idlist_find_channel_by_id(server->local_list, 
3843                                              channel_id, NULL);
3844     if (!channel) {
3845       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3846                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3847       goto out;
3848     }
3849   }
3850
3851   /* Check whether sender is on the channel */
3852   if (!silc_server_client_on_channel(client, channel)) {
3853     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3854                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
3855     goto out;
3856   }
3857
3858   /* Check that the kicker is channel operator or channel founder */
3859   silc_list_start(channel->user_list);
3860   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3861     if (chl->client == client) {
3862       if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
3863         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3864                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV);
3865         goto out;
3866       }
3867       break;
3868     }
3869   }
3870   
3871   /* Get target Client ID */
3872   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3873   if (!tmp) {
3874     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3875                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3876     goto out;
3877   }
3878   client_id = silc_id_payload_parse_id(tmp, tmp_len);
3879   if (!client_id) {
3880     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3881                                           SILC_STATUS_ERR_NO_CLIENT_ID);
3882     goto out;
3883   }
3884
3885   /* Get target client's entry */
3886   target_client = silc_idlist_find_client_by_id(server->local_list, 
3887                                                 client_id, NULL);
3888   if (!target_client) {
3889     target_client = silc_idlist_find_client_by_id(server->global_list, 
3890                                                   client_id, NULL);
3891   }
3892
3893   /* Check that the target client is not channel founder. Channel founder
3894      cannot be kicked from the channel. */
3895   silc_list_start(channel->user_list);
3896   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
3897     if (chl->client == target_client) {
3898       if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
3899         silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3900                                   SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
3901         goto out;
3902       }
3903       break;
3904     }
3905   }
3906   
3907   /* Check whether target client is on the channel */
3908   if (!silc_server_client_on_channel(target_client, channel)) {
3909     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
3910                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
3911     goto out;
3912   }
3913
3914   /* Get comment */
3915   tmp_len = 0;
3916   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3917   if (tmp_len > 128)
3918     comment = NULL;
3919
3920   /* Send command reply to sender */
3921   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
3922                                         SILC_STATUS_OK);
3923
3924   /* Send KICKED notify to local clients on the channel */
3925   idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
3926   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
3927                                      SILC_NOTIFY_TYPE_KICKED, 
3928                                      comment ? 2 : 1,
3929                                      idp->data, idp->len,
3930                                      comment, comment ? strlen(comment) : 0);
3931   silc_buffer_free(idp);
3932
3933   /* Remove the client from the channel. If the channel does not exist
3934      after removing the client then the client kicked itself off the channel
3935      and we don't have to send anything after that. */
3936   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
3937                                            target_client, FALSE))
3938     goto out;
3939
3940   /* Send KICKED notify to primary route */
3941   if (!server->standalone)
3942     silc_server_send_notify_kicked(server, server->router->connection,
3943                                    server->server_type == SILC_ROUTER ?
3944                                    TRUE : FALSE, channel,
3945                                    target_client->id, SILC_ID_CLIENT_LEN,
3946                                    comment);
3947
3948   /* Re-generate channel key */
3949   silc_server_create_channel_key(server, channel, 0);
3950
3951   /* Send the channel key to the channel. The key of course is not sent
3952      to the client who was kicked off the channel. */
3953   silc_server_send_channel_key(server, target_client->connection, channel, 
3954                                server->server_type == SILC_ROUTER ? 
3955                                FALSE : !server->standalone);
3956
3957  out:
3958   silc_server_command_free(cmd);
3959 }
3960
3961 /* Server side of OPER command. Client uses this comand to obtain server
3962    operator privileges to this server/router. */
3963
3964 SILC_SERVER_CMD_FUNC(oper)
3965 {
3966   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3967   SilcServer server = cmd->server;
3968   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3969   unsigned char *username, *auth;
3970   unsigned int tmp_len;
3971   SilcServerConfigSectionAdminConnection *admin;
3972   SilcIDListData idata = (SilcIDListData)client;
3973
3974   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_OPER, cmd, 1, 2);
3975
3976   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3977     goto out;
3978
3979   /* Get the username */
3980   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3981   if (!username) {
3982     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3983                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3984     goto out;
3985   }
3986
3987   /* Get the admin configuration */
3988   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
3989                                         username, client->nickname);
3990   if (!admin) {
3991     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
3992                                           username, client->nickname);
3993     if (!admin) {
3994       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
3995                                             SILC_STATUS_ERR_AUTH_FAILED);
3996       goto out;
3997     }
3998   }
3999
4000   /* Get the authentication payload */
4001   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4002   if (!auth) {
4003     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4004                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4005     goto out;
4006   }
4007
4008   /* Verify the authentication data */
4009   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4010                              admin->auth_data, admin->auth_data_len,
4011                              idata->hash, client->id, SILC_ID_CLIENT)) {
4012     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4013                                           SILC_STATUS_ERR_AUTH_FAILED);
4014     goto out;
4015   }
4016
4017   /* Client is now server operator */
4018   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4019
4020   /* Send UMODE change to primary router */
4021   if (!server->standalone)
4022     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4023                                   client->id, SILC_ID_CLIENT_LEN,
4024                                   client->mode);
4025
4026   /* Send reply to the sender */
4027   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4028                                         SILC_STATUS_OK);
4029
4030  out:
4031   silc_server_command_free(cmd);
4032 }
4033
4034 /* Server side of SILCOPER command. Client uses this comand to obtain router
4035    operator privileges to this router. */
4036
4037 SILC_SERVER_CMD_FUNC(silcoper)
4038 {
4039   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4040   SilcServer server = cmd->server;
4041   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4042   unsigned char *username, *auth;
4043   unsigned int tmp_len;
4044   SilcServerConfigSectionAdminConnection *admin;
4045   SilcIDListData idata = (SilcIDListData)client;
4046
4047   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SILCOPER, cmd, 1, 2);
4048
4049   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4050     goto out;
4051
4052   /* Get the username */
4053   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4054   if (!username) {
4055     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4056                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4057     goto out;
4058   }
4059
4060   /* Get the admin configuration */
4061   admin = silc_server_config_find_admin(server->config, cmd->sock->ip,
4062                                         username, client->nickname);
4063   if (!admin) {
4064     admin = silc_server_config_find_admin(server->config, cmd->sock->hostname,
4065                                           username, client->nickname);
4066     if (!admin) {
4067       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4068                                             SILC_STATUS_ERR_AUTH_FAILED);
4069       goto out;
4070     }
4071   }
4072
4073   /* Get the authentication payload */
4074   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4075   if (!auth) {
4076     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4077                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4078     goto out;
4079   }
4080
4081   /* Verify the authentication data */
4082   if (!silc_auth_verify_data(auth, tmp_len, admin->auth_meth, 
4083                              admin->auth_data, admin->auth_data_len,
4084                              idata->hash, client->id, SILC_ID_CLIENT)) {
4085     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4086                                           SILC_STATUS_ERR_AUTH_FAILED);
4087     goto out;
4088   }
4089
4090   /* Client is now router operator */
4091   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
4092
4093   /* Send UMODE change to primary router */
4094   if (!server->standalone)
4095     silc_server_send_notify_umode(server, server->router->connection, TRUE,
4096                                   client->id, SILC_ID_CLIENT_LEN,
4097                                   client->mode);
4098
4099   /* Send reply to the sender */
4100   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
4101                                         SILC_STATUS_OK);
4102
4103  out:
4104   silc_server_command_free(cmd);
4105 }
4106
4107 /* Server side command of CONNECT. Connects us to the specified remote
4108    server or router. */
4109
4110 SILC_SERVER_CMD_FUNC(connect)
4111 {
4112   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4113   SilcServer server = cmd->server;
4114   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4115   unsigned char *tmp, *host;
4116   unsigned int tmp_len;
4117   unsigned int port = SILC_PORT;
4118
4119   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
4120
4121   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4122     goto out;
4123
4124   /* Check whether client has the permissions. */
4125   if (client->mode == SILC_UMODE_NONE) {
4126     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4127                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4128     goto out;
4129   }
4130
4131   if (server->server_type == SILC_ROUTER && 
4132       client->mode & SILC_UMODE_SERVER_OPERATOR) {
4133     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4134                                           SILC_STATUS_ERR_NO_ROUTER_PRIV);
4135     goto out;
4136   }
4137
4138   /* Get the remote server */
4139   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4140   if (!host) {
4141     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4142                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4143     goto out;
4144   }
4145
4146   /* Get port */
4147   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4148   if (tmp)
4149     SILC_GET32_MSB(port, tmp);
4150
4151   /* Create the connection. It is done with timeout and is async. */
4152   silc_server_create_connection(server, host, port);
4153
4154   /* Send reply to the sender */
4155   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
4156                                         SILC_STATUS_OK);
4157
4158  out:
4159   silc_server_command_free(cmd);
4160 }
4161
4162 SILC_SERVER_CMD_FUNC(restart)
4163 {
4164 }
4165
4166 /* Server side command of CLOSE. Closes connection to a specified server. */
4167  
4168 SILC_SERVER_CMD_FUNC(close)
4169 {
4170   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4171   SilcServer server = cmd->server;
4172   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4173   SilcServerEntry server_entry;
4174   SilcSocketConnection sock;
4175   unsigned char *tmp;
4176   unsigned int tmp_len;
4177   unsigned char *name;
4178   unsigned int port = SILC_PORT;
4179
4180   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
4181
4182   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4183     goto out;
4184
4185   /* Check whether client has the permissions. */
4186   if (client->mode == SILC_UMODE_NONE) {
4187     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4188                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4189     goto out;
4190   }
4191
4192   /* Get the remote server */
4193   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4194   if (!name) {
4195     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4196                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
4197     goto out;
4198   }
4199
4200   /* Get port */
4201   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4202   if (tmp)
4203     SILC_GET32_MSB(port, tmp);
4204
4205   server_entry = silc_idlist_find_server_by_conn(server->local_list,
4206                                                  name, port, NULL);
4207   if (!server_entry) {
4208     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4209                                           SILC_STATUS_ERR_NO_SERVER_ID);
4210     goto out;
4211   }
4212
4213   /* Send reply to the sender */
4214   silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
4215                                         SILC_STATUS_OK);
4216
4217   /* Close the connection to the server */
4218   sock = (SilcSocketConnection)server_entry->connection;
4219   silc_server_free_sock_user_data(server, sock);
4220   silc_server_close_connection(server, sock);
4221   
4222  out:
4223   silc_server_command_free(cmd);
4224 }
4225
4226 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
4227    active connections. */
4228  
4229 SILC_SERVER_CMD_FUNC(shutdown)
4230 {
4231   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4232   SilcServer server = cmd->server;
4233   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4234
4235   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
4236
4237   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4238     goto out;
4239
4240   /* Check whether client has the permission. */
4241   if (client->mode == SILC_UMODE_NONE) {
4242     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4243                                           SILC_STATUS_ERR_NO_SERVER_PRIV);
4244     goto out;
4245   }
4246
4247   /* Send reply to the sender */
4248   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
4249                                         SILC_STATUS_OK);
4250
4251   /* Then, gracefully, or not, bring the server down. */
4252   silc_server_stop(server);
4253   exit(0);
4254
4255  out:
4256   silc_server_command_free(cmd);
4257 }
4258  
4259 /* Server side command of LEAVE. Removes client from a channel. */
4260
4261 SILC_SERVER_CMD_FUNC(leave)
4262 {
4263   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4264   SilcServer server = cmd->server;
4265   SilcSocketConnection sock = cmd->sock;
4266   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
4267   SilcChannelID *id;
4268   SilcChannelEntry channel;
4269   SilcBuffer packet;
4270   unsigned int i, len;
4271   unsigned char *tmp;
4272
4273   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
4274
4275   /* Get Channel ID */
4276   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
4277   if (!tmp) {
4278     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4279                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4280     goto out;
4281   }
4282   id = silc_id_payload_parse_id(tmp, len);
4283   if (!id) {
4284     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4285                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4286     goto out;
4287   }
4288
4289   /* Get channel entry */
4290   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4291   if (!channel) {
4292     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4293     if (!channel) {
4294       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4295                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4296       goto out;
4297     }
4298   }
4299
4300   /* Check whether this client is on the channel */
4301   if (!silc_server_client_on_channel(id_entry, channel)) {
4302     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4303                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4304     goto out;
4305   }
4306
4307   /* Notify routers that they should remove this client from their list
4308      of clients on the channel. Send LEAVE notify type. */
4309   if (!server->standalone)
4310     silc_server_send_notify_leave(server, server->router->connection,
4311                                   server->server_type == SILC_ROUTER ?
4312                                   TRUE : FALSE, channel, id_entry->id,
4313                                   SILC_ID_CLIENT_LEN);
4314
4315   /* Remove client from channel */
4316   i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
4317                                           TRUE);
4318   silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
4319                                         SILC_STATUS_OK);
4320
4321   /* If the channel does not exist anymore we won't send anything */
4322   if (!i)
4323     goto out;
4324
4325   /* Re-generate channel key */
4326   silc_server_create_channel_key(server, channel, 0);
4327
4328   /* Encode channel key payload to be distributed on the channel */
4329   packet = 
4330     silc_channel_key_payload_encode(len, tmp,
4331                                     strlen(channel->channel_key->cipher->name),
4332                                     channel->channel_key->cipher->name,
4333                                     channel->key_len / 8, channel->key);
4334
4335   /* If we are normal server then we will send it to our router.  If we
4336      are router we will send it to all local servers that has clients on
4337      the channel */
4338   if (server->server_type == SILC_SERVER) {
4339     if (!server->standalone)
4340       silc_server_packet_send(server, 
4341                               cmd->server->router->connection,
4342                               SILC_PACKET_CHANNEL_KEY, 0, packet->data,
4343                               packet->len, FALSE);
4344   } else {
4345
4346   }
4347
4348   /* Send to locally connected clients on the channel */
4349   silc_server_packet_send_local_channel(server, channel, 
4350                                         SILC_PACKET_CHANNEL_KEY, 0,
4351                                         packet->data, packet->len, FALSE);
4352
4353   silc_buffer_free(packet);
4354   silc_free(id);
4355
4356  out:
4357   silc_server_command_free(cmd);
4358 }
4359
4360 /* Server side of command USERS. Resolves clients and their USERS currently
4361    joined on the requested channel. The list of Client ID's and their modes
4362    on the channel is sent back. */
4363
4364 SILC_SERVER_CMD_FUNC(users)
4365 {
4366   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4367   SilcServer server = cmd->server;
4368   SilcChannelEntry channel;
4369   SilcChannelID *id;
4370   SilcBuffer packet;
4371   unsigned char *channel_id;
4372   unsigned int channel_id_len;
4373   SilcBuffer client_id_list;
4374   SilcBuffer client_mode_list;
4375   unsigned char lc[4];
4376   unsigned int list_count = 0;
4377   unsigned short ident = silc_command_get_ident(cmd->payload);
4378
4379   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
4380
4381   /* Get Channel ID */
4382   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
4383   if (!channel_id) {
4384     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4385                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4386     goto out;
4387   }
4388   id = silc_id_payload_parse_id(channel_id, channel_id_len);
4389   if (!id) {
4390     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4391                                           SILC_STATUS_ERR_NO_CHANNEL_ID);
4392     goto out;
4393   }
4394
4395   /* If we are server and we don't know about this channel we will send
4396      the command to our router. If we know about the channel then we also
4397      have the list of users already. */
4398   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
4399   if (!channel) {
4400     if (server->server_type == SILC_SERVER && !server->standalone &&
4401         !cmd->pending) {
4402       SilcBuffer tmpbuf;
4403       
4404       silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
4405       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
4406       
4407       /* Send USERS command */
4408       silc_server_packet_send(server, server->router->connection,
4409                               SILC_PACKET_COMMAND, cmd->packet->flags,
4410                               tmpbuf->data, tmpbuf->len, TRUE);
4411       
4412       /* Reprocess this packet after received reply */
4413       silc_server_command_pending(server, SILC_COMMAND_USERS, 
4414                                   silc_command_get_ident(cmd->payload),
4415                                   silc_server_command_destructor,
4416                                   silc_server_command_users,
4417                                   silc_server_command_dup(cmd));
4418       cmd->pending = TRUE;
4419       silc_command_set_ident(cmd->payload, ident);
4420       
4421       silc_buffer_free(tmpbuf);
4422       silc_free(id);
4423       return;
4424     }
4425
4426     /* We are router and we will check the global list as well. */
4427     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
4428     if (!channel) {
4429       /* Channel really does not exist */
4430       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
4431                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4432       goto out;
4433     }
4434   }
4435
4436   /* Get the users list */
4437   silc_server_get_users_on_channel(server, channel, &client_id_list,
4438                                    &client_mode_list, &list_count);
4439
4440   /* List count */
4441   SILC_PUT32_MSB(list_count, lc);
4442
4443   /* Send reply */
4444   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
4445                                                 SILC_STATUS_OK, ident, 4,
4446                                                 2, channel_id, channel_id_len,
4447                                                 3, lc, 4,
4448                                                 4, client_id_list->data,
4449                                                 client_id_list->len,
4450                                                 5, client_mode_list->data,
4451                                                 client_mode_list->len);
4452   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4453                           packet->data, packet->len, FALSE);
4454     
4455   silc_buffer_free(packet);
4456   silc_buffer_free(client_id_list);
4457   silc_buffer_free(client_mode_list);
4458   silc_free(id);
4459
4460  out:
4461   silc_server_command_free(cmd);
4462 }
4463
4464 /* Server side of command BAN. This is used to manage the ban list of the
4465    channel. To add clients and remove clients from the ban list. */
4466
4467 SILC_SERVER_CMD_FUNC(ban)
4468 {
4469   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4470   SilcServer server = cmd->server;
4471   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4472   SilcBuffer packet;
4473   SilcChannelEntry channel;
4474   SilcChannelClientEntry chl;
4475   SilcChannelID *channel_id = NULL;
4476   unsigned char *id, *add, *del;
4477   unsigned int id_len, tmp_len;
4478   unsigned short ident = silc_command_get_ident(cmd->payload);
4479
4480   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4481     goto out;
4482
4483   SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_BAN, cmd, 0, 3);
4484
4485   /* Get Channel ID */
4486   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
4487   if (id) {
4488     channel_id = silc_id_payload_parse_id(id, id_len);
4489     if (!channel_id) {
4490       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4491                                             SILC_STATUS_ERR_NO_CHANNEL_ID);
4492       goto out;
4493     }
4494   }
4495
4496   /* Get channel entry. The server must know about the channel since the
4497      client is expected to be on the channel. */
4498   channel = silc_idlist_find_channel_by_id(server->local_list, 
4499                                            channel_id, NULL);
4500   if (!channel) {
4501     channel = silc_idlist_find_channel_by_id(server->global_list, 
4502                                              channel_id, NULL);
4503     if (!channel) {
4504       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4505                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL);
4506       goto out;
4507     }
4508   }
4509
4510   /* Check whether this client is on the channel */
4511   if (!silc_server_client_on_channel(client, channel)) {
4512     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4513                                           SILC_STATUS_ERR_NOT_ON_CHANNEL);
4514     goto out;
4515   }
4516
4517   /* Get entry to the channel user list */
4518   silc_list_start(channel->user_list);
4519   while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
4520     if (chl->client == client)
4521       break;
4522
4523   /* The client must be at least channel operator. */
4524   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4525     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
4526                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV);
4527     goto out;
4528   }
4529
4530   /* Get the new ban and add it to the ban list */
4531   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4532   if (add) {
4533     if (!channel->ban_list)
4534       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
4535     else
4536       channel->ban_list = silc_realloc(channel->ban_list, 
4537                                        sizeof(*channel->ban_list) * 
4538                                        (tmp_len + 
4539                                         strlen(channel->ban_list) + 2));
4540     if (add[tmp_len - 1] == ',')
4541       add[tmp_len - 1] = '\0';
4542
4543     strncat(channel->ban_list, add, tmp_len);
4544     strncat(channel->ban_list, ",", 1);
4545   }
4546
4547   /* Get the ban to be removed and remove it from the list */
4548   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4549   if (del && channel->ban_list) {
4550     char *start, *end, *n;
4551
4552     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
4553       silc_free(channel->ban_list);
4554       channel->ban_list = NULL;
4555     } else {
4556       start = strstr(channel->ban_list, del);
4557       if (start && strlen(start) >= tmp_len) {
4558         end = start + tmp_len;
4559         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
4560         strncat(n, channel->ban_list, start - channel->ban_list);
4561         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
4562                              end) - 1);
4563         silc_free(channel->ban_list);
4564         channel->ban_list = n;
4565       }
4566     }
4567   }
4568
4569   /* Send the BAN notify type to our primary router. */
4570   if (!server->standalone && (add || del))
4571     silc_server_send_notify_ban(server, server->router->connection,
4572                                 server->server_type == SILC_ROUTER ?
4573                                 TRUE : FALSE, channel, add, del);
4574
4575   /* Send the reply back to the client */
4576   if (channel->ban_list)
4577     packet = 
4578       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4579                                            SILC_STATUS_OK, ident, 2,
4580                                            2, id, id_len,
4581                                            3, channel->ban_list, 
4582                                            strlen(channel->ban_list) - 1);
4583   else
4584     packet = 
4585       silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
4586                                            SILC_STATUS_OK, ident, 1,
4587                                            2, id, id_len);
4588
4589   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4590                           packet->data, packet->len, FALSE);
4591     
4592   silc_buffer_free(packet);
4593
4594  out:
4595   if (channel_id)
4596     silc_free(channel_id);
4597   silc_server_command_free(cmd);
4598 }