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