Go through whole list of pending commands when deleting by
[silc.git] / apps / silcd / command.c
1 /*
2
3   command.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2002 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                                       SilcStatus status,
33                                       SilcStatus error);
34 static void 
35 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36                                      SilcCommand command,
37                                      SilcStatus status,
38                                      SilcStatus error,
39                                      SilcUInt32 arg_type,
40                                      const unsigned char *arg,
41                                      SilcUInt32 arg_len);
42 static bool
43 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
44                                         SilcServerCommandReplyContext cmdr,
45                                         SilcCommand command);
46 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
47
48 /* Server command list. */
49 SilcServerCommand silc_command_list[] =
50 {
51   SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
52   SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
53   SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
54   SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
55   SILC_SERVER_CMD(list, LIST, SILC_CF_LAG_STRICT | SILC_CF_REG),
56   SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
57   SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
58   SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
59   SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG_STRICT | SILC_CF_REG | SILC_CF_OPER),
60   SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
61   SILC_SERVER_CMD(stats, STATS, SILC_CF_LAG | SILC_CF_REG),
62   SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
63   SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
64   SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG_STRICT | SILC_CF_REG),
65   SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
66   SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
67   SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG_STRICT | SILC_CF_REG),
68   SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
69   SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG_STRICT | SILC_CF_REG),
70   SILC_SERVER_CMD(ban, BAN, SILC_CF_LAG_STRICT | SILC_CF_REG),
71   SILC_SERVER_CMD(detach, DETACH, SILC_CF_LAG_STRICT | SILC_CF_REG),
72   SILC_SERVER_CMD(watch, WATCH, SILC_CF_LAG | SILC_CF_REG),
73   SILC_SERVER_CMD(silcoper, SILCOPER,
74                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75   SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG_STRICT | SILC_CF_REG),
76   SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
77   SILC_SERVER_CMD(getkey, GETKEY, SILC_CF_LAG | SILC_CF_REG),
78
79   SILC_SERVER_CMD(connect, PRIV_CONNECT, 
80                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
81   SILC_SERVER_CMD(close, PRIV_CLOSE,
82                   SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
83   SILC_SERVER_CMD(shutdown, PRIV_SHUTDOWN, SILC_CF_LAG | SILC_CF_REG | 
84                   SILC_CF_OPER),
85
86   { NULL, 0 },
87 };
88
89 /* Performs several checks to the command. It first checks whether this
90    command was called as pending command callback. If it was then it checks
91    whether error occurred in the command reply where the pending command
92    callback was called. 
93
94    It also checks that the requested command includes correct amount
95    of arguments. */
96 #define SILC_SERVER_COMMAND_CHECK(command, context, min, max)                \
97 do {                                                                         \
98   SilcUInt32 _argc;                                                          \
99                                                                              \
100   if (silc_server_command_pending_error_check(cmd, context2, command)) {     \
101     SILC_LOG_DEBUG(("Error occurred in command reply, command not called")); \
102     silc_server_command_free(cmd);                                           \
103     return;                                                                  \
104   }                                                                          \
105                                                                              \
106   _argc = silc_argument_get_arg_num(cmd->args);                              \
107   if (_argc < min) {                                                         \
108     SILC_LOG_DEBUG(("Not enough parameters in command"));                    \
109     silc_server_command_send_status_reply(cmd, command,                      \
110                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, \
111                                           0);                                \
112     silc_server_command_free(cmd);                                           \
113     return;                                                                  \
114   }                                                                          \
115   if (_argc > max) {                                                         \
116     SILC_LOG_DEBUG(("Too many parameters in command"));                      \
117     silc_server_command_send_status_reply(cmd, command,                      \
118                                           SILC_STATUS_ERR_TOO_MANY_PARAMS,   \
119                                           0);                                \
120     silc_server_command_free(cmd);                                           \
121     return;                                                                  \
122   }                                                                          \
123 } while(0)
124
125 /* Returns TRUE if the connection is registered. Unregistered connections
126    usually cannot send commands hence the check. */
127
128 static int silc_server_is_registered(SilcServer server,
129                                      SilcSocketConnection sock,
130                                      SilcServerCommandContext cmd,
131                                      SilcCommand command)
132 {
133   SilcIDListData idata = (SilcIDListData)sock->user_data;
134
135   if (!idata)
136     return FALSE;
137
138   if (idata->status & SILC_IDLIST_STATUS_REGISTERED)
139     return TRUE;
140
141   silc_server_command_send_status_reply(cmd, command,
142                                         SILC_STATUS_ERR_NOT_REGISTERED, 0);
143   return FALSE;
144 }
145
146 /* Internal context to hold data when executed command with timeout. */
147 typedef struct {
148   SilcServerCommandContext ctx;
149   SilcServerCommand *cmd;
150 } *SilcServerCommandTimeout;
151
152 /* Timeout callback to process commands with timeout for client. Client's
153    commands are always executed with timeout. */
154
155 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
156 {
157   SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
158   SilcClientEntry client = (SilcClientEntry)timeout->ctx->sock->user_data;
159
160   if (!client) {
161     SILC_LOG_DEBUG(("Client entry is invalid"));
162     silc_server_command_free(timeout->ctx);
163     silc_free(timeout);
164   }
165
166   /* Update access time */
167   client->last_command = time(NULL);
168
169   if (!(timeout->cmd->flags & SILC_CF_REG)) {
170     SILC_LOG_DEBUG(("Calling %s command",
171                     silc_get_command_name(timeout->cmd->cmd)));
172     timeout->cmd->cb(timeout->ctx, NULL);
173   } else if (silc_server_is_registered(timeout->ctx->server, 
174                                        timeout->ctx->sock, 
175                                        timeout->ctx, 
176                                        timeout->cmd->cmd)) {
177     SILC_LOG_DEBUG(("Calling %s command",
178                     silc_get_command_name(timeout->cmd->cmd)));
179     timeout->cmd->cb(timeout->ctx, NULL);
180   } else {
181     SILC_LOG_DEBUG(("Client is not registered"));
182     silc_server_command_free(timeout->ctx);
183   }
184
185   silc_free(timeout);
186 }
187
188 /* Processes received command packet. */
189
190 void silc_server_command_process(SilcServer server,
191                                  SilcSocketConnection sock,
192                                  SilcPacketContext *packet)
193 {
194   SilcServerCommandContext ctx;
195   SilcServerCommand *cmd;
196   SilcCommand command;
197
198   /* Allocate command context. This must be free'd by the
199      command routine receiving it. */
200   ctx = silc_server_command_alloc();
201   ctx->server = server;
202   ctx->sock = silc_socket_dup(sock);
203   ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
204   
205   /* Parse the command payload in the packet */
206   ctx->payload = silc_command_payload_parse(packet->buffer->data,
207                                             packet->buffer->len);
208   if (!ctx->payload) {
209     SILC_LOG_ERROR(("Bad command payload, packet dropped"));
210     silc_packet_context_free(packet);
211     silc_socket_free(ctx->sock);
212     silc_free(ctx);
213     return;
214   }
215   ctx->args = silc_command_get_args(ctx->payload);
216
217   /* Get the command */
218   command = silc_command_get(ctx->payload);
219   for (cmd = silc_command_list; cmd->cb; cmd++)
220     if (cmd->cmd == command)
221       break;
222
223   if (!cmd || !cmd->cb) {
224     SILC_LOG_DEBUG(("Unknown command %d", command));
225     silc_server_command_send_status_reply(ctx, command,
226                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
227     silc_server_command_free(ctx);
228     return;
229   }
230
231   /* Execute client's commands always with timeout.  Normally they are
232      executed with zero (0) timeout but if client is sending command more
233      frequently than once in 2 seconds, then the timeout may be 0 to 2
234      seconds. */
235   if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
236     SilcClientEntry client = (SilcClientEntry)sock->user_data;
237     SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
238     int fast;
239
240     timeout->ctx = ctx;
241     timeout->cmd = cmd;
242
243     if (client->last_command && (time(NULL) - client->last_command) < 2) {
244       client->fast_command++;
245       fast = FALSE;
246     } else {
247       if (client->fast_command - 2 <= 0)
248         client->fast_command = 0;
249       else
250         client->fast_command -= 2;
251       fast = TRUE;
252     }
253
254     if (!fast && ((cmd->flags & SILC_CF_LAG_STRICT) ||
255                   (client->fast_command > 5 && cmd->flags & SILC_CF_LAG)))
256       silc_schedule_task_add(server->schedule, sock->sock, 
257                              silc_server_command_process_timeout, timeout,
258                              (client->fast_command < 3 ? 0 :
259                               2 - (time(NULL) - client->last_command)),
260                              (client->fast_command < 3 ? 200000 : 0),
261                              SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
262     else
263       silc_schedule_task_add(server->schedule, sock->sock, 
264                              silc_server_command_process_timeout, timeout,
265                              0, 1, SILC_TASK_TIMEOUT, SILC_TASK_PRI_NORMAL);
266     return;
267   }
268
269   /* Execute for server */
270
271   if (!(cmd->flags & SILC_CF_REG)) {
272     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
273     cmd->cb(ctx, NULL);
274   } else if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
275     SILC_LOG_DEBUG(("Calling %s command", silc_get_command_name(cmd->cmd)));
276     cmd->cb(ctx, NULL);
277   } else {
278     SILC_LOG_DEBUG(("Server is not registered"));
279     silc_server_command_free(ctx);
280   }
281 }
282
283 /* Allocate Command Context */
284
285 SilcServerCommandContext silc_server_command_alloc()
286 {
287   SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
288   ctx->users++;
289   return ctx;
290 }
291
292 /* Free's the command context allocated before executing the command */
293
294 void silc_server_command_free(SilcServerCommandContext ctx)
295 {
296   ctx->users--;
297   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
298                   ctx->users));
299   if (ctx->users < 1) {
300     if (ctx->payload)
301       silc_command_payload_free(ctx->payload);
302     if (ctx->packet)
303       silc_packet_context_free(ctx->packet);
304     if (ctx->sock)
305       silc_socket_free(ctx->sock); /* Decrease reference counter */
306     silc_free(ctx);
307   }
308 }
309
310 /* Duplicate Command Context by adding reference counter. The context won't
311    be free'd untill it hits zero. */
312
313 SilcServerCommandContext 
314 silc_server_command_dup(SilcServerCommandContext ctx)
315 {
316   ctx->users++;
317   SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
318                   ctx->users));
319   return ctx;
320 }
321
322 /* Add new pending command to be executed when reply to a command has been
323    received. The `reply_cmd' is the command that will call the `callback'
324    with `context' when reply has been received.  It can be SILC_COMMAND_NONE
325    to match any command with the `ident'.  If `ident' is non-zero
326    the `callback' will be executed when received reply with command
327    identifier `ident'. If there already exists pending command for the
328    specified command, ident, callback and context this function has no
329    effect. */
330
331 bool silc_server_command_pending(SilcServer server,
332                                  SilcCommand reply_cmd,
333                                  SilcUInt16 ident,
334                                  SilcCommandCb callback,
335                                  void *context)
336 {
337   SilcServerCommandPending *reply;
338
339   /* Check whether identical pending already exists for same command,
340      ident, callback and callback context. If it does then it would be
341      error to register it again. */
342   silc_dlist_start(server->pending_commands);
343   while ((reply = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
344     if (reply->reply_cmd == reply_cmd && reply->ident == ident &&
345         reply->callback == callback && reply->context == context)
346       return FALSE;
347   }
348
349   reply = silc_calloc(1, sizeof(*reply));
350   reply->reply_cmd = reply_cmd;
351   reply->ident = ident;
352   reply->context = context;
353   reply->callback = callback;
354   silc_dlist_add(server->pending_commands, reply);
355
356   return TRUE;
357 }
358
359 /* Deletes pending command by reply command type. */
360
361 void silc_server_command_pending_del(SilcServer server,
362                                      SilcCommand reply_cmd,
363                                      SilcUInt16 ident)
364 {
365   SilcServerCommandPending *r;
366
367   silc_dlist_start(server->pending_commands);
368   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
369     if (r->reply_cmd == reply_cmd && r->ident == ident) {
370       silc_dlist_del(server->pending_commands, r);
371       silc_free(r);
372     }
373   }
374 }
375
376 /* Checks for pending commands and marks callbacks to be called from
377    the command reply function. Returns TRUE if there were pending command. */
378
379 SilcServerCommandPendingCallbacks
380 silc_server_command_pending_check(SilcServer server,
381                                   SilcServerCommandReplyContext ctx,
382                                   SilcCommand command, 
383                                   SilcUInt16 ident,
384                                   SilcUInt32 *callbacks_count)
385 {
386   SilcServerCommandPending *r;
387   SilcServerCommandPendingCallbacks callbacks = NULL;
388   int i = 0;
389
390   silc_dlist_start(server->pending_commands);
391   while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
392     if ((r->reply_cmd == command || r->reply_cmd == SILC_COMMAND_NONE)
393         && r->ident == ident) {
394       callbacks = silc_realloc(callbacks, sizeof(*callbacks) * (i + 1));
395       callbacks[i].context = r->context;
396       callbacks[i].callback = r->callback;
397       ctx->ident = ident;
398       i++;
399     }
400   }
401
402   *callbacks_count = i;
403   return callbacks;
404 }
405
406 /* Sends simple status message as command reply packet */
407
408 static void 
409 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
410                                       SilcCommand command,
411                                       SilcStatus status,
412                                       SilcStatus error)
413 {
414   SilcBuffer buffer;
415
416   SILC_LOG_DEBUG(("Sending command status %d", status));
417
418   buffer = 
419     silc_command_reply_payload_encode_va(command, status, error,
420                                          silc_command_get_ident(cmd->payload),
421                                          0);
422   silc_server_packet_send(cmd->server, cmd->sock,
423                           SILC_PACKET_COMMAND_REPLY, 0, 
424                           buffer->data, buffer->len, FALSE);
425   silc_buffer_free(buffer);
426 }
427
428 /* Sends command status reply with one extra argument. The argument
429    type must be sent as argument. */
430
431 static void 
432 silc_server_command_send_status_data(SilcServerCommandContext cmd,
433                                      SilcCommand command,
434                                      SilcStatus status,
435                                      SilcStatus error,
436                                      SilcUInt32 arg_type,
437                                      const unsigned char *arg,
438                                      SilcUInt32 arg_len)
439 {
440   SilcBuffer buffer;
441
442   SILC_LOG_DEBUG(("Sending command status %d", status));
443
444   buffer = 
445     silc_command_reply_payload_encode_va(command, status, 0,
446                                          silc_command_get_ident(cmd->payload),
447                                          1, arg_type, arg, arg_len);
448   silc_server_packet_send(cmd->server, cmd->sock,
449                           SILC_PACKET_COMMAND_REPLY, 0, 
450                           buffer->data, buffer->len, FALSE);
451   silc_buffer_free(buffer);
452 }
453
454 /* This function can be called to check whether in the command reply
455    an error occurred. This function has no effect if this is called
456    when the command function was not called as pending command callback. 
457    This returns TRUE if error had occurred. */
458
459 static bool
460 silc_server_command_pending_error_check(SilcServerCommandContext cmd,
461                                         SilcServerCommandReplyContext cmdr,
462                                         SilcCommand command)
463 {
464   if (!cmd->pending || !cmdr)
465     return FALSE;
466
467   if (!silc_command_get_status(cmdr->payload, NULL, NULL)) {
468     SilcBuffer buffer;
469
470     /* Send the same command reply payload */
471     silc_command_set_ident(cmdr->payload, 
472                            silc_command_get_ident(cmd->payload));
473     buffer = silc_command_payload_encode_payload(cmdr->payload);
474     silc_server_packet_send(cmd->server, cmd->sock,
475                             SILC_PACKET_COMMAND_REPLY, 0, 
476                             buffer->data, buffer->len, FALSE);
477     silc_buffer_free(buffer);
478     return TRUE;
479   }
480
481   return FALSE;
482 }
483
484 /******************************************************************************
485
486                               WHOIS Functions
487
488 ******************************************************************************/
489
490 typedef struct {
491   void *id;
492   SilcIdType id_type;
493   SilcUInt32 index;
494   SilcStatus error;
495 } *ResolveError;
496
497 #define ADD_ERROR(errptr, errptr_count, _id, _id_type, _index, _status) \
498 do {                                                                    \
499   errptr = silc_realloc(errptr, sizeof(*errptr) * (errptr_count + 1));  \
500   if (!errptr)                                                          \
501     return FALSE;                                                       \
502   errptr[errptr_count].id = _id;                                        \
503   errptr[errptr_count].id_type = _id_type;                              \
504   errptr[errptr_count].index = _index;                                  \
505   errptr[errptr_count].error = _status;                                 \
506   errptr_count++;                                                       \
507 } while(0)
508
509 static int
510 silc_server_command_whois_parse(SilcServerCommandContext cmd,
511                                 SilcClientID ***client_id,
512                                 SilcUInt32 *client_id_count,
513                                 char **nickname,
514                                 char **server_name,
515                                 int *count,
516                                 ResolveError *error_client,
517                                 SilcUInt32 *error_client_count)
518 {
519   unsigned char *tmp;
520   SilcUInt32 len;
521   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
522   void *id;
523   int i, k;
524
525   /* If client ID is in the command it must be used instead of nickname */
526   tmp = silc_argument_get_arg_type(cmd->args, 4, &len);
527   if (!tmp) {
528     /* No ID, get the nickname@server string and parse it. */
529     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
530     if (tmp) {
531       silc_parse_userfqdn(tmp, nickname, server_name);
532     } else {
533       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
534                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
535       return FALSE;
536     }
537   } else {
538     /* Command includes ID, we must use that.  Take all ID's from the 
539        command packet */
540     for (k = 0, i = 0; i < argc; i++) {
541       tmp = silc_argument_get_arg_type(cmd->args, i + 4, &len);
542       if (!tmp)
543         continue;
544       id = silc_id_payload_parse_id(tmp, len, NULL);
545       if (id) {
546         *client_id = silc_realloc(*client_id, sizeof(**client_id) *
547                                   (*client_id_count + 1));
548         (*client_id)[k] = id;
549         (*client_id_count)++;
550         k++;
551       } else {
552         ADD_ERROR((*error_client), (*error_client_count), NULL, 0, i + 4,
553                   SILC_STATUS_ERR_BAD_CLIENT_ID);
554       }
555     }
556   }
557
558   /* Get the max count of reply messages allowed */
559   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
560   if (tmp)
561     SILC_GET32_MSB(*count, tmp);
562   else
563     *count = 0;
564
565   return TRUE;
566 }
567
568 /* Resolve context used by both WHOIS and IDENTIFY commands */
569 typedef struct {
570   SilcServerEntry router;
571   SilcUInt16 ident;
572   unsigned char **res_argv;
573   SilcUInt32 *res_argv_lens;
574   SilcUInt32 *res_argv_types;
575   SilcUInt32 res_argc;
576 } *SilcServerResolveContext;
577
578 static bool
579 silc_server_command_whois_check(SilcServerCommandContext cmd,
580                                 SilcClientEntry *clients,
581                                 SilcUInt32 clients_count)
582 {
583   SilcServer server = cmd->server;
584   SilcClientEntry entry;
585   SilcServerResolveContext resolve = NULL, r = NULL;
586   SilcUInt32 resolve_count = 0;
587   int i, k;
588   bool no_res = TRUE;
589
590   SILC_LOG_DEBUG(("Start"));
591
592   for (i = 0; i < clients_count; i++) {
593     entry = clients[i];
594     if (!entry)
595       continue;
596
597     if ((entry->nickname && entry->username && entry->userinfo) ||
598         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
599       if (!entry->router)
600         continue;
601
602       /* If we are normal server, and we've not resolved this client from
603          router and it is global client, we'll check whether it is on some
604          channel.  If not then we cannot be sure about its validity, and
605          we'll resolve it from router. */
606       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
607           entry->connection || silc_hash_table_count(entry->channels))
608         continue;
609     }
610
611     /* We need to resolve this entry since it is not complete */
612
613     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
614       /* The entry is being resolved (and we are not the resolver) so attach
615          to the command reply and we're done with this one. */
616       silc_server_command_pending(server, SILC_COMMAND_NONE, 
617                                   entry->resolve_cmd_ident,
618                                   silc_server_command_whois,
619                                   silc_server_command_dup(cmd));
620       no_res = FALSE;
621     } else {
622       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
623         /* We've resolved this and it still is not ready.  We'll return
624            and are that this will be handled again after it is resolved. */
625         for (i = 0; i < resolve_count; i++) {
626           for (k = 0; k < r->res_argc; k++)
627             silc_free(r->res_argv[k]);
628           silc_free(r->res_argv);
629           silc_free(r->res_argv_lens);
630           silc_free(r->res_argv_types);
631         }
632         silc_free(resolve);
633         return FALSE;
634       } else {
635         /* We'll resolve this client */
636         SilcBuffer idp;
637
638         r = NULL;
639         for (k = 0; k < resolve_count; k++) {
640           if (resolve[k].router == entry->router) {
641             r = &resolve[k];
642             break;
643           }
644         }
645
646         if (!r) {
647           resolve = silc_realloc(resolve, sizeof(*resolve) * 
648                                  (resolve_count + 1));
649           r = &resolve[resolve_count];
650           memset(r, 0, sizeof(*r));
651           r->router = entry->router;
652           r->ident = ++server->cmd_ident;
653           resolve_count++;
654         }
655
656         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
657                                    (r->res_argc + 1));
658         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
659                                         sizeof(*r->res_argv_lens) *
660                                         (r->res_argc + 1));
661         r->res_argv_types = silc_realloc(r->res_argv_types, 
662                                          sizeof(*r->res_argv_types) *
663                                          (r->res_argc + 1));
664         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
665         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
666                                                sizeof(**r->res_argv));
667         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
668         r->res_argv_lens[r->res_argc] = idp->len;
669         r->res_argv_types[r->res_argc] = r->res_argc + 4;
670         r->res_argc++;
671         silc_buffer_free(idp);
672
673         entry->resolve_cmd_ident = r->ident;
674         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
675         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
676       }
677     }
678   }
679
680   /* Do the resolving */
681   for (i = 0; i < resolve_count; i++) {
682     SilcBuffer res_cmd;
683
684     r = &resolve[i];
685
686     /* Send WHOIS request. We send WHOIS since we're doing the requesting
687        now anyway so make it a good one. */
688     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
689                                           r->res_argc, r->res_argv, 
690                                           r->res_argv_lens,
691                                           r->res_argv_types, 
692                                           r->ident);
693     silc_server_packet_send(server, r->router->connection,
694                             SILC_PACKET_COMMAND, cmd->packet->flags,
695                             res_cmd->data, res_cmd->len, FALSE);
696
697     /* Reprocess this packet after received reply */
698     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
699                                 r->ident,
700                                 silc_server_command_whois,
701                                 silc_server_command_dup(cmd));
702     cmd->pending = TRUE;
703
704     silc_buffer_free(res_cmd);
705     for (k = 0; k < r->res_argc; k++)
706       silc_free(r->res_argv[k]);
707     silc_free(r->res_argv);
708     silc_free(r->res_argv_lens);
709     silc_free(r->res_argv_types);
710     no_res = FALSE;
711   }
712   silc_free(resolve);
713
714   return no_res;
715 }
716
717 static void
718 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
719                                      SilcClientEntry *clients,
720                                      SilcUInt32 clients_count, 
721                                      ResolveError errors,
722                                      SilcUInt32 errors_count,
723                                      int count, const char *nickname,
724                                      SilcClientID **client_ids)
725 {
726   SilcServer server = cmd->server;
727   char *tmp;
728   int i, k, valid_count = clients_count;
729   SilcUInt32 len;
730   SilcBuffer packet, idp, channels, umode_list = NULL;
731   SilcClientEntry entry;
732   SilcStatus status;
733   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
734   char nh[256], uh[256];
735   unsigned char idle[4], mode[4];
736   unsigned char *fingerprint;
737   SilcSocketConnection hsock;
738
739   if (nickname) {
740     /* Process only valid clients and ignore those that are not registered. 
741        This is checked with nickname only because when resolved client IDs
742        we check that they are registered earlier. */
743     valid_count = 0;
744     for (i = 0; i < clients_count; i++)
745       if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
746         valid_count++;
747       else
748         clients[i] = NULL;
749
750     if (!valid_count) {
751       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
752                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
753                                            3, nickname, strlen(nickname));
754       return;
755     }
756   }
757
758   /* Start processing found clients. */
759   status = SILC_STATUS_OK;
760   if (valid_count > 1)
761     status = SILC_STATUS_LIST_START;
762
763   for (i = 0, k = 0; i < clients_count; i++) {
764     entry = clients[i];
765     if (!entry)
766       continue;
767
768     if (k >= 1)
769       status = SILC_STATUS_LIST_ITEM;
770     if (valid_count > 1 && k == valid_count - 1 && !errors_count)
771       status = SILC_STATUS_LIST_END;
772     if (count && k - 1 == count)
773       status = SILC_STATUS_LIST_END;
774
775     /* Send WHOIS reply */
776     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
777     tmp = silc_argument_get_first_arg(cmd->args, NULL);
778     
779     memset(uh, 0, sizeof(uh));
780     memset(nh, 0, sizeof(nh));
781     memset(idle, 0, sizeof(idle));
782     
783     strncat(nh, entry->nickname, strlen(entry->nickname));
784     if (!strchr(entry->nickname, '@')) {
785       strncat(nh, "@", 1);
786       if (entry->servername) {
787         strncat(nh, entry->servername, strlen(entry->servername));
788       } else {
789         len = entry->router ? strlen(entry->router->server_name) :
790           strlen(server->server_name);
791         strncat(nh, entry->router ? entry->router->server_name :
792                 server->server_name, len);
793       }
794     }
795       
796     strncat(uh, entry->username, strlen(entry->username));
797     if (!strchr(entry->username, '@') && entry->connection) {
798       strncat(uh, "@", 1);
799       hsock = (SilcSocketConnection)entry->connection;
800       len = strlen(hsock->hostname);
801       strncat(uh, hsock->hostname, len);
802     }
803
804     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
805       channels = silc_server_get_client_channel_list(server, entry, FALSE, 
806                                                      FALSE, &umode_list);
807     else
808       channels = silc_server_get_client_channel_list(server, entry, TRUE, 
809                                                      TRUE, &umode_list);
810
811     if (entry->data.fingerprint[0] != 0 && entry->data.fingerprint[1] != 0)
812       fingerprint = entry->data.fingerprint;
813     else
814       fingerprint = NULL;
815       
816     SILC_PUT32_MSB(entry->mode, mode);
817     if (entry->connection)
818       SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
819
820     packet = 
821       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
822                                            status, 0, ident, 9, 
823                                            2, idp->data, idp->len,
824                                            3, nh, strlen(nh),
825                                            4, uh, strlen(uh),
826                                            5, entry->userinfo, 
827                                            strlen(entry->userinfo),
828                                            6, channels ? channels->data : NULL,
829                                            channels ? channels->len : 0,
830                                            7, mode, 4,
831                                            8, idle, 4,
832                                            9, fingerprint,
833                                            fingerprint ? 20 : 0,
834                                            10, umode_list ? umode_list->data :
835                                            NULL, umode_list ? umode_list->len :
836                                            0);
837
838     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
839                             0, packet->data, packet->len, FALSE);
840     
841     silc_buffer_free(packet);
842     silc_buffer_free(idp);
843     if (channels)
844       silc_buffer_free(channels);
845     if (umode_list) {
846       silc_buffer_free(umode_list);
847       umode_list = NULL;
848     }
849
850     if (status == SILC_STATUS_LIST_END)
851       break;
852     k++;
853   }
854
855   /* Send error replies */
856   if (status == SILC_STATUS_OK && errors_count > 1)
857     status = SILC_STATUS_LIST_START;
858
859   idp = NULL;
860   for (i = 0, k = 0; i < errors_count; i++) {
861     if (errors[i].id) {
862       idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
863       tmp = idp->data;
864       len = idp->len;
865     } else {
866       tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
867     }
868       
869     if (k >= 1)
870       status = SILC_STATUS_LIST_ITEM;
871     if (errors_count > 1 && k == errors_count - 1)
872       status = SILC_STATUS_LIST_END;
873     if (count && k - 1 == count)
874       status = SILC_STATUS_LIST_END;
875       
876     /* Send error */
877     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
878                                          (status == SILC_STATUS_OK ?
879                                           errors[i].error : status),
880                                          (status == SILC_STATUS_OK ?
881                                           0 : errors[i].error),
882                                          2, tmp, len);
883     silc_buffer_free(idp);
884     idp = NULL;
885       
886     if (status == SILC_STATUS_LIST_END)
887       break;
888     k++;
889   }
890 }
891
892 static void 
893 silc_server_command_whois_send_router(SilcServerCommandContext cmd)
894 {
895   SilcServer server = cmd->server;
896   SilcBuffer tmpbuf;
897   SilcUInt16 old_ident;
898
899   old_ident = silc_command_get_ident(cmd->payload);
900   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
901   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
902
903   /* Send WHOIS command to our router */
904   silc_server_packet_send(server, (SilcSocketConnection)
905                           SILC_PRIMARY_ROUTE(server),
906                           SILC_PACKET_COMMAND, cmd->packet->flags,
907                           tmpbuf->data, tmpbuf->len, TRUE);
908
909   /* Reprocess this packet after received reply from router */
910   silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
911                               silc_command_get_ident(cmd->payload),
912                               silc_server_command_whois,
913                               silc_server_command_dup(cmd));
914   cmd->pending = TRUE;
915   silc_command_set_ident(cmd->payload, old_ident);
916   silc_buffer_free(tmpbuf);
917 }
918
919 static int
920 silc_server_command_whois_process(SilcServerCommandContext cmd)
921 {
922   SilcServer server = cmd->server;
923   char *nick = NULL, *server_name = NULL;
924   int count = 0;
925   SilcClientEntry *clients = NULL, entry;
926   SilcClientID **client_id = NULL;
927   SilcUInt32 client_id_count = 0, clients_count = 0, error_client_count = 0;
928   ResolveError error_client = NULL;
929   int i, ret = 0;
930   bool check_global = FALSE;
931
932   /* Parse the whois request */
933   if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count, 
934                                        &nick, &server_name, &count,
935                                        &error_client, &error_client_count))
936     return 0;
937
938   /* Send the WHOIS request to the router only if it included nickname.
939      Since nicknames can be expanded into many clients we need to send it
940      to router.  If the WHOIS included only client ID's we will check them
941      first locally since we just might have them. */
942   if (nick && !client_id_count && cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
943       server->server_type == SILC_SERVER && !cmd->pending &&
944       !server->standalone) {
945     silc_server_command_whois_send_router(cmd);
946     ret = -1;
947     goto out;
948   }
949
950   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
951     check_global = TRUE;
952   else if (server->server_type != SILC_SERVER)
953     check_global = TRUE;
954
955   /* Get all clients matching that ID or nickname from local list */
956   if (client_id_count) {
957     /* Check all Client ID's received in the command packet */
958     for (i = 0; i < client_id_count; i++) {
959       entry = silc_idlist_find_client_by_id(server->local_list, 
960                                             client_id[i], TRUE, NULL);
961       if (!entry && check_global)
962         entry = silc_idlist_find_client_by_id(server->global_list, 
963                                               client_id[i], TRUE, NULL);
964       if (entry) {
965         clients = silc_realloc(clients, sizeof(*clients) * 
966                                (clients_count + 1));
967         clients[clients_count++] = entry;
968       } else {
969         /* If we are normal server and did not send the request first to router
970            do it now, since we do not have the Client ID information. */
971         if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
972             server->server_type == SILC_SERVER && !cmd->pending && 
973             !server->standalone) {
974           silc_server_command_whois_send_router(cmd);
975           ret = -1;
976           goto out;
977         }
978
979         ADD_ERROR(error_client, error_client_count, client_id[i], 
980                   SILC_ID_CLIENT, 0, SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
981       }
982     }
983   } else if (nick) {
984     /* Find by nickname */
985     if (!silc_idlist_get_clients_by_hash(server->local_list, 
986                                          nick, server->md5hash,
987                                          &clients, &clients_count))
988       silc_idlist_get_clients_by_nickname(server->local_list, 
989                                           nick, server_name,
990                                           &clients, &clients_count);
991     if (check_global) {
992       if (!silc_idlist_get_clients_by_hash(server->global_list, 
993                                            nick, server->md5hash,
994                                            &clients, &clients_count))
995         silc_idlist_get_clients_by_nickname(server->global_list, 
996                                             nick, server_name,
997                                             &clients, &clients_count);
998     }
999   }
1000   
1001   if (!clients && (client_id_count || nick)) {
1002     /* If we are normal server and did not send the request first to router
1003        do it now, since we do not have the information. */
1004     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1005         server->server_type == SILC_SERVER && !cmd->pending && 
1006         !server->standalone) {
1007       silc_server_command_whois_send_router(cmd);
1008       ret = -1;
1009       goto out;
1010     }
1011
1012     /* Such client(s) really does not exist in the SILC network. */
1013     if (!client_id_count)
1014       silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
1015                                            SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1016                                            3, nick, strlen(nick));
1017     else
1018       silc_server_command_whois_send_reply(cmd, NULL, 0,
1019                                            error_client, error_client_count,
1020                                            0, NULL, NULL);
1021     goto out;
1022   }
1023
1024   /* Router always finds the client entry if it exists in the SILC network.
1025      However, it might be incomplete entry and does not include all the
1026      mandatory fields that WHOIS command reply requires. Check for these and
1027      make query from the server who owns the client if some fields are 
1028      missing. */
1029   if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
1030     ret = -1;
1031     goto out;
1032   }
1033
1034   /* Send the command reply */
1035   silc_server_command_whois_send_reply(cmd, clients, clients_count,
1036                                        error_client, error_client_count,
1037                                        count, nick, client_id);
1038
1039  out:
1040   if (client_id_count) {
1041     for (i = 0; i < client_id_count; i++)
1042       silc_free(client_id[i]);
1043     silc_free(client_id);
1044   }
1045   silc_free(clients);
1046   silc_free(error_client);
1047   silc_free(nick);
1048   silc_free(server_name);
1049
1050   return ret;
1051 }
1052
1053 /* Server side of command WHOIS. Processes user's query and sends found 
1054    results as command replies back to the client. */
1055
1056 SILC_SERVER_CMD_FUNC(whois)
1057 {
1058   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1059   int ret = 0;
1060
1061   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOIS, cmd, 1, 3328);
1062
1063   ret = silc_server_command_whois_process(cmd);
1064   silc_server_command_free(cmd);
1065 }
1066
1067 /******************************************************************************
1068
1069                               WHOWAS Functions
1070
1071 ******************************************************************************/
1072
1073 static int
1074 silc_server_command_whowas_parse(SilcServerCommandContext cmd,
1075                                  char **nickname,
1076                                  char **server_name,
1077                                  int *count)
1078 {
1079   unsigned char *tmp;
1080   SilcUInt32 len;
1081
1082   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1083   if (!tmp) {
1084     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOWAS,
1085                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 
1086                                           0);
1087     return FALSE;
1088   }
1089
1090   /* Get the nickname@server string and parse it. */
1091   silc_parse_userfqdn(tmp, nickname, server_name);
1092
1093   /* Get the max count of reply messages allowed */
1094   tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1095   if (tmp)
1096     SILC_GET32_MSB(*count, tmp);
1097   else
1098     *count = 0;
1099
1100   return TRUE;
1101 }
1102
1103 static char
1104 silc_server_command_whowas_check(SilcServerCommandContext cmd,
1105                                  SilcClientEntry *clients,
1106                                  SilcUInt32 clients_count)
1107 {
1108   SilcServer server = cmd->server;
1109   int i;
1110   SilcClientEntry entry;
1111
1112   for (i = 0; i < clients_count; i++) {
1113     entry = clients[i];
1114
1115     if (!entry->nickname || !entry->username) {
1116       SilcBuffer tmpbuf;
1117       SilcUInt16 old_ident;
1118
1119       if (!entry->router)
1120         continue;
1121       
1122       old_ident = silc_command_get_ident(cmd->payload);
1123       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1124       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1125
1126       /* Send WHOWAS command */
1127       silc_server_packet_send(server, entry->router->connection,
1128                               SILC_PACKET_COMMAND, cmd->packet->flags,
1129                               tmpbuf->data, tmpbuf->len, TRUE);
1130       
1131       /* Reprocess this packet after received reply */
1132       silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1133                                   silc_command_get_ident(cmd->payload),
1134                                   silc_server_command_whowas, 
1135                                   silc_server_command_dup(cmd));
1136       cmd->pending = TRUE;
1137       silc_command_set_ident(cmd->payload, old_ident);
1138
1139       silc_buffer_free(tmpbuf);
1140       return FALSE;
1141     }
1142   }
1143
1144   return TRUE;
1145 }
1146
1147 static void
1148 silc_server_command_whowas_send_reply(SilcServerCommandContext cmd,
1149                                       SilcClientEntry *clients,
1150                                       SilcUInt32 clients_count)
1151 {
1152   SilcServer server = cmd->server;
1153   char *tmp;
1154   int i, k, count = 0, len;
1155   SilcBuffer packet, idp;
1156   SilcClientEntry entry = NULL;
1157   SilcStatus status;
1158   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1159   char nh[256], uh[256];
1160   int valid_count;
1161
1162   status = SILC_STATUS_OK;
1163
1164   /* Process only entries that are not registered anymore. */
1165   valid_count = 0;
1166   for (i = 0; i < clients_count; i++) {
1167     if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1168       clients[i] = NULL;
1169     else
1170       valid_count++;
1171   }
1172
1173   if (!valid_count) {
1174     /* No valid entries found at all, just send error */
1175     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1176     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1177                                          SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1178                                          3, tmp, tmp ? strlen(tmp) : 0);
1179     return;
1180   }
1181
1182   if (valid_count > 1)
1183     status = SILC_STATUS_LIST_START;
1184
1185   for (i = 0, k = 0; i < clients_count; i++) {
1186     entry = clients[i];
1187     if (!entry)
1188       continue;
1189
1190     if (k >= 1)
1191       status = SILC_STATUS_LIST_ITEM;
1192     if (valid_count > 1 && k == valid_count - 1)
1193       status = SILC_STATUS_LIST_END;
1194     if (count && k - 1 == count)
1195       status = SILC_STATUS_LIST_END;
1196
1197     /* Send WHOWAS reply */
1198     idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1199     tmp = silc_argument_get_first_arg(cmd->args, NULL);
1200     memset(uh, 0, sizeof(uh));
1201     memset(nh, 0, sizeof(nh));
1202
1203     strncat(nh, entry->nickname, strlen(entry->nickname));
1204     if (!strchr(entry->nickname, '@')) {
1205       strncat(nh, "@", 1);
1206       if (entry->servername) {
1207         strncat(nh, entry->servername, strlen(entry->servername));
1208       } else {
1209         len = entry->router ? strlen(entry->router->server_name) :
1210           strlen(server->server_name);
1211         strncat(nh, entry->router ? entry->router->server_name :
1212                 server->server_name, len);
1213       }
1214     }
1215       
1216     strncat(uh, entry->username, strlen(entry->username));
1217     if (!strchr(entry->username, '@')) {
1218       strncat(uh, "@", 1);
1219       strcat(uh, "*private*");
1220     }
1221       
1222     packet = 
1223       silc_command_reply_payload_encode_va(SILC_COMMAND_WHOWAS,
1224                                            status, 0, ident, 4, 
1225                                            2, idp->data, idp->len,
1226                                            3, nh, strlen(nh),
1227                                            4, uh, strlen(uh),
1228                                            5, entry->userinfo, 
1229                                            entry->userinfo ? 
1230                                            strlen(entry->userinfo) : 0);
1231     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1232                             0, packet->data, packet->len, FALSE);
1233     
1234     silc_buffer_free(packet);
1235     silc_buffer_free(idp);
1236
1237     if (status == SILC_STATUS_LIST_END)
1238       break;
1239     k++;
1240   }
1241 }
1242
1243 static int
1244 silc_server_command_whowas_process(SilcServerCommandContext cmd)
1245 {
1246   SilcServer server = cmd->server;
1247   char *nick = NULL, *server_name = NULL;
1248   int count = 0;
1249   SilcClientEntry *clients = NULL;
1250   SilcUInt32 clients_count = 0;
1251   int ret = 0;
1252   bool check_global = FALSE;
1253
1254   /* Protocol dictates that we must always send the received WHOWAS request
1255      to our router if we are normal server, so let's do it now unless we
1256      are standalone. We will not send any replies to the client until we
1257      have received reply from the router. */
1258   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT &&
1259       server->server_type == SILC_SERVER && !cmd->pending && 
1260       !server->standalone) {
1261     SilcBuffer tmpbuf;
1262     SilcUInt16 old_ident;
1263
1264     old_ident = silc_command_get_ident(cmd->payload);
1265     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1266     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1267
1268     /* Send WHOWAS command to our router */
1269     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
1270                             SILC_PACKET_COMMAND, cmd->packet->flags,
1271                             tmpbuf->data, tmpbuf->len, TRUE);
1272
1273     /* Reprocess this packet after received reply from router */
1274     silc_server_command_pending(server, SILC_COMMAND_WHOWAS, 
1275                                 silc_command_get_ident(cmd->payload),
1276                                 silc_server_command_whowas,
1277                                 silc_server_command_dup(cmd));
1278     cmd->pending = TRUE;
1279     silc_command_set_ident(cmd->payload, old_ident);
1280
1281     silc_buffer_free(tmpbuf);
1282     ret = -1;
1283     goto out;
1284   }
1285
1286   /* We are ready to process the command request. Let's search for the
1287      requested client and send reply to the requesting client. */
1288
1289   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1290     check_global = TRUE;
1291   else if (server->server_type != SILC_SERVER)
1292     check_global = TRUE;
1293
1294   /* Parse the whowas request */
1295   if (!silc_server_command_whowas_parse(cmd, &nick, &server_name, &count))
1296     return 0;
1297
1298   /* Get all clients matching that nickname from local list */
1299   if (!silc_idlist_get_clients_by_nickname(server->local_list, 
1300                                            nick, server_name,
1301                                            &clients, &clients_count))
1302     silc_idlist_get_clients_by_hash(server->local_list, 
1303                                     nick, server->md5hash,
1304                                     &clients, &clients_count);
1305   
1306   /* Check global list as well */
1307   if (check_global) {
1308     if (!silc_idlist_get_clients_by_nickname(server->global_list, 
1309                                              nick, server_name,
1310                                              &clients, &clients_count))
1311       silc_idlist_get_clients_by_hash(server->global_list, 
1312                                       nick, server->md5hash,
1313                                       &clients, &clients_count);
1314   }
1315   
1316   if (!clients) {
1317     /* Such a client really does not exist in the SILC network. */
1318     silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOWAS,
1319                                          SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1320                                          3, nick, strlen(nick));
1321     goto out;
1322   }
1323
1324   if (!silc_server_command_whowas_check(cmd, clients, clients_count)) {
1325     ret = -1;
1326     goto out;
1327   }
1328
1329   /* Send the command reply to the client */
1330   silc_server_command_whowas_send_reply(cmd, clients, clients_count);
1331
1332  out:
1333   silc_free(clients);
1334   silc_free(nick);
1335   silc_free(server_name);
1336   return ret;
1337 }
1338
1339 /* Server side of command WHOWAS. */
1340
1341 SILC_SERVER_CMD_FUNC(whowas)
1342 {
1343   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1344   int ret = 0;
1345
1346   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WHOWAS, cmd, 1, 2);
1347
1348   ret = silc_server_command_whowas_process(cmd);
1349   silc_server_command_free(cmd);
1350 }
1351
1352 /******************************************************************************
1353
1354                               IDENTIFY Functions
1355
1356 ******************************************************************************/
1357
1358 static void 
1359 silc_server_command_identify_send_router(SilcServerCommandContext cmd)
1360 {
1361   SilcServer server = cmd->server;
1362   SilcBuffer tmpbuf;
1363   SilcUInt16 old_ident;
1364
1365   old_ident = silc_command_get_ident(cmd->payload);
1366   silc_command_set_ident(cmd->payload, ++server->cmd_ident);
1367   tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1368
1369   /* Send IDENTIFY command to our router */
1370   silc_server_packet_send(server, (SilcSocketConnection)
1371                           SILC_PRIMARY_ROUTE(server),
1372                           SILC_PACKET_COMMAND, cmd->packet->flags,
1373                           tmpbuf->data, tmpbuf->len, TRUE);
1374
1375   /* Reprocess this packet after received reply from router */
1376   silc_server_command_pending(server, SILC_COMMAND_IDENTIFY, 
1377                               silc_command_get_ident(cmd->payload),
1378                               silc_server_command_identify,
1379                               silc_server_command_dup(cmd));
1380   cmd->pending = TRUE;
1381   silc_command_set_ident(cmd->payload, old_ident);
1382   silc_buffer_free(tmpbuf);
1383 }
1384
1385 static int
1386 silc_server_command_identify_parse(SilcServerCommandContext cmd,
1387                                    SilcClientEntry **clients,
1388                                    SilcUInt32 *clients_count,
1389                                    SilcServerEntry **servers,
1390                                    SilcUInt32 *servers_count,
1391                                    SilcChannelEntry **channels,
1392                                    SilcUInt32 *channels_count,
1393                                    SilcUInt32 *count,
1394                                    ResolveError *error_id,
1395                                    SilcUInt32 *error_id_count)
1396 {
1397   SilcServer server = cmd->server;
1398   unsigned char *tmp;
1399   SilcUInt32 len;
1400   SilcUInt32 argc = silc_argument_get_arg_num(cmd->args);
1401   SilcIDPayload idp;
1402   bool check_global = FALSE;
1403   void *entry;
1404   int i;
1405
1406   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1407     check_global = TRUE;
1408   else if (server->server_type != SILC_SERVER)
1409     check_global = TRUE;
1410
1411   /* If ID Payload is in the command it must be used instead of names */
1412   tmp = silc_argument_get_arg_type(cmd->args, 5, &len);
1413   if (!tmp) {
1414     /* No ID, get the names. */
1415
1416     /* If we are normal server and have not resolved information from
1417        router yet, do so now. */
1418     if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1419         server->server_type == SILC_SERVER && !cmd->pending && 
1420         !server->standalone) {
1421       silc_server_command_identify_send_router(cmd);
1422       return -1;
1423     }
1424
1425     /* Try to get nickname@server. */
1426     tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1427     if (tmp) {
1428       char *nick = NULL;
1429       char *nick_server = NULL;
1430
1431       silc_parse_userfqdn(tmp, &nick, &nick_server);
1432
1433       if (!silc_idlist_get_clients_by_hash(server->local_list, 
1434                                            nick, server->md5hash,
1435                                            clients, clients_count))
1436         silc_idlist_get_clients_by_nickname(server->local_list, 
1437                                             nick, nick_server,
1438                                             clients, clients_count);
1439       if (check_global) {
1440         if (!silc_idlist_get_clients_by_hash(server->global_list, 
1441                                              nick, server->md5hash,
1442                                              clients, clients_count))
1443           silc_idlist_get_clients_by_nickname(server->global_list, 
1444                                               nick, nick_server,
1445                                               clients, clients_count);
1446       }
1447
1448       silc_free(nick);
1449       silc_free(nick_server);
1450
1451       if (!(*clients)) {
1452         /* the nickname does not exist, send error reply */
1453         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1454                                              SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1455                                              3, tmp, strlen(tmp));
1456         return 0;
1457       }
1458     }
1459
1460     /* Try to get server name */
1461     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1462     if (tmp) {
1463       entry = silc_idlist_find_server_by_name(server->local_list,
1464                                               tmp, TRUE, NULL);
1465       if (!entry && check_global)
1466         entry = silc_idlist_find_server_by_name(server->global_list,
1467                                                 tmp, TRUE, NULL);
1468       if (entry) {
1469         *servers = silc_realloc(*servers, sizeof(**servers) * 
1470                                 (*servers_count + 1));
1471         (*servers)[(*servers_count)++] = entry;
1472       }
1473
1474       if (!(*servers)) {
1475         /* the server does not exist, send error reply */
1476         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1477                                              SILC_STATUS_ERR_NO_SUCH_SERVER,
1478                                              0, 3, tmp, strlen(tmp));
1479         return 0;
1480       }
1481     }
1482
1483     /* Try to get channel name */
1484     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
1485     if (tmp) {
1486       entry = silc_idlist_find_channel_by_name(server->local_list,
1487                                                tmp, NULL);
1488       if (!entry && check_global)
1489         entry = silc_idlist_find_channel_by_name(server->global_list,
1490                                                  tmp, NULL);
1491       if (entry) {
1492         *channels = silc_realloc(*channels, sizeof(**channels) * 
1493                                  (*channels_count + 1));
1494         (*channels)[(*channels_count)++] = entry;
1495       }
1496
1497       if (!(*channels)) {
1498         /* The channel does not exist, send error reply */
1499         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1500                                              SILC_STATUS_ERR_NO_SUCH_CHANNEL,
1501                                              0, 3, tmp, strlen(tmp));
1502         return 0;
1503       }
1504     }
1505
1506     if (!(*clients) && !(*servers) && !(*channels)) {
1507       silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
1508                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
1509                                             0);
1510       return 0;
1511     }
1512   } else {
1513     /* Command includes ID, we must use that.  Also check whether the command
1514        has more than one ID set - take them all. */
1515
1516     /* Take all ID's from the command packet */
1517     for (i = 0; i < argc; i++) {
1518       void *id;
1519
1520       tmp = silc_argument_get_arg_type(cmd->args, i + 5, &len);
1521       if (!tmp)
1522         continue;
1523       
1524       idp = silc_id_payload_parse(tmp, len);
1525       if (!idp)
1526         ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1527                   SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1528
1529       id = silc_id_payload_get_id(idp);
1530       switch (silc_id_payload_get_type(idp)) {
1531         
1532       case SILC_ID_CLIENT:
1533         entry = silc_idlist_find_client_by_id(server->local_list, 
1534                                               id, TRUE, NULL);
1535         if (!entry && check_global)
1536           entry = silc_idlist_find_client_by_id(server->global_list, 
1537                                                 id, TRUE, NULL);
1538         if (entry) {
1539           *clients = silc_realloc(*clients, sizeof(**clients) * 
1540                                   (*clients_count + 1));
1541           (*clients)[(*clients_count)++] = (SilcClientEntry)entry;
1542         } else {
1543           /* If we are normal server and have not resolved information from
1544              router yet, do so now. */
1545           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1546               server->server_type == SILC_SERVER && !cmd->pending && 
1547               !server->standalone) {
1548             silc_server_command_identify_send_router(cmd);
1549             silc_free(*clients);
1550             silc_free(*servers);
1551             silc_free(*channels);
1552             silc_free(*error_id);
1553             return -1;
1554           }
1555
1556           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1557                     SILC_STATUS_ERR_NO_SUCH_CLIENT_ID);
1558         }
1559
1560         break;
1561         
1562       case SILC_ID_SERVER:
1563         entry = silc_idlist_find_server_by_id(server->local_list, 
1564                                               id, TRUE, NULL);
1565         if (!entry && check_global)
1566           entry = silc_idlist_find_server_by_id(server->global_list, 
1567                                                 id, TRUE, NULL);
1568         if (entry) {
1569           *servers = silc_realloc(*servers, sizeof(**servers) * 
1570                                   (*servers_count + 1));
1571           (*servers)[(*servers_count)++] = (SilcServerEntry)entry;
1572         } else {
1573           /* If we are normal server and have not resolved information from
1574              router yet, do so now. */
1575           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1576               server->server_type == SILC_SERVER && !cmd->pending && 
1577               !server->standalone) {
1578             silc_server_command_identify_send_router(cmd);
1579             silc_free(*clients);
1580             silc_free(*servers);
1581             silc_free(*channels);
1582             silc_free(*error_id);
1583             return -1;
1584           }
1585
1586           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1587                     SILC_STATUS_ERR_NO_SUCH_SERVER_ID);
1588         }
1589         break;
1590         
1591       case SILC_ID_CHANNEL:
1592         entry = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
1593         if (!entry && check_global)
1594           entry = silc_idlist_find_channel_by_id(server->global_list, id,
1595                                                  NULL);
1596         if (entry) {
1597           *channels = silc_realloc(*channels, sizeof(**channels) * 
1598                                    (*channels_count + 1));
1599           (*channels)[(*channels_count)++] = (SilcChannelEntry)entry;
1600         } else {
1601           /* If we are normal server and have not resolved information from
1602              router yet, do so now. */
1603           if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT && 
1604               server->server_type == SILC_SERVER && !cmd->pending && 
1605               !server->standalone) {
1606             silc_server_command_identify_send_router(cmd);
1607             silc_free(*clients);
1608             silc_free(*servers);
1609             silc_free(*channels);
1610             silc_free(*error_id);
1611             return -1;
1612           }
1613
1614           ADD_ERROR((*error_id), (*error_id_count), NULL, 0, i + 5,
1615                     SILC_STATUS_ERR_NO_SUCH_CHANNEL_ID);
1616         }
1617         break;
1618       }
1619
1620       silc_id_payload_free(idp);
1621       silc_free(id);
1622     }
1623   }
1624
1625   /* Get the max count of reply messages allowed */
1626   tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
1627   if (tmp)
1628     SILC_GET32_MSB(*count, tmp);
1629   else
1630     *count = 0;
1631
1632   return 1;
1633 }
1634
1635 /* Checks that all mandatory fields in client entry are present. If not
1636    then send WHOIS request to the server who owns the client. We use
1637    WHOIS because we want to get as much information as possible at once. */
1638
1639 static bool
1640 silc_server_command_identify_check_client(SilcServerCommandContext cmd,
1641                                           SilcClientEntry *clients,
1642                                           SilcUInt32 clients_count)
1643 {
1644   SilcServer server = cmd->server;
1645   SilcClientEntry entry;
1646   SilcServerResolveContext resolve = NULL, r = NULL;
1647   SilcUInt32 resolve_count = 0;
1648   int i, k;
1649   bool no_res = TRUE;
1650
1651   for (i = 0; i < clients_count; i++) {
1652     entry = clients[i];
1653     if (!entry)
1654       continue;
1655
1656     if (entry->nickname || 
1657         !(entry->data.status & SILC_IDLIST_STATUS_REGISTERED)) {
1658       if (!entry->router)
1659         continue;
1660
1661       /* If we are normal server, and we've not resolved this client from
1662          router and it is global client, we'll check whether it is on some
1663          channel.  If not then we cannot be sure about its validity, and
1664          we'll resolve it from router. */
1665       if (cmd->server->server_type != SILC_SERVER || cmd->pending ||
1666           entry->connection || silc_hash_table_count(entry->channels))
1667         continue;
1668     }
1669
1670     /* We need to resolve this entry since it is not complete */
1671
1672     if (!cmd->pending && entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1673       /* The entry is being resolved (and we are not the resolver) so attach
1674          to the command reply and we're done with this one. */
1675       silc_server_command_pending(server, SILC_COMMAND_NONE, 
1676                                   entry->resolve_cmd_ident,
1677                                   silc_server_command_identify,
1678                                   silc_server_command_dup(cmd));
1679       no_res = FALSE;
1680     } else {
1681       if (entry->data.status & SILC_IDLIST_STATUS_RESOLVING) {
1682         /* We've resolved this and it still is not ready.  We'll return
1683            and are that this will be handled again after it is resolved. */
1684         for (i = 0; i < resolve_count; i++) {
1685           for (k = 0; k < r->res_argc; k++)
1686             silc_free(r->res_argv[k]);
1687           silc_free(r->res_argv);
1688           silc_free(r->res_argv_lens);
1689           silc_free(r->res_argv_types);
1690         }
1691         silc_free(resolve);
1692         return FALSE;
1693       } else {
1694         /* We'll resolve this client */
1695         SilcBuffer idp;
1696
1697         r = NULL;
1698         for (k = 0; k < resolve_count; k++) {
1699           if (resolve[k].router == entry->router) {
1700             r = &resolve[k];
1701             break;
1702           }
1703         }
1704
1705         if (!r) {
1706           resolve = silc_realloc(resolve, sizeof(*resolve) * 
1707                                  (resolve_count + 1));
1708           r = &resolve[resolve_count];
1709           memset(r, 0, sizeof(*r));
1710           r->router = entry->router;
1711           r->ident = ++server->cmd_ident;
1712           resolve_count++;
1713         }
1714
1715         r->res_argv = silc_realloc(r->res_argv, sizeof(*r->res_argv) *
1716                                    (r->res_argc + 1));
1717         r->res_argv_lens = silc_realloc(r->res_argv_lens, 
1718                                         sizeof(*r->res_argv_lens) *
1719                                         (r->res_argc + 1));
1720         r->res_argv_types = silc_realloc(r->res_argv_types, 
1721                                          sizeof(*r->res_argv_types) *
1722                                          (r->res_argc + 1));
1723         idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1724         r->res_argv[r->res_argc] = silc_calloc(idp->len, 
1725                                                sizeof(**r->res_argv));
1726         memcpy(r->res_argv[r->res_argc], idp->data, idp->len);
1727         r->res_argv_lens[r->res_argc] = idp->len;
1728         r->res_argv_types[r->res_argc] = r->res_argc + 4;
1729         r->res_argc++;
1730         silc_buffer_free(idp);
1731
1732         entry->resolve_cmd_ident = r->ident;
1733         entry->data.status |= SILC_IDLIST_STATUS_RESOLVING;
1734         entry->data.status &= ~SILC_IDLIST_STATUS_RESOLVED;
1735       }
1736     }
1737   }
1738
1739   /* Do the resolving */
1740   for (i = 0; i < resolve_count; i++) {
1741     SilcBuffer res_cmd;
1742
1743     r = &resolve[i];
1744
1745     /* Send WHOIS request. We send WHOIS since we're doing the requesting
1746        now anyway so make it a good one. */
1747     res_cmd = silc_command_payload_encode(SILC_COMMAND_WHOIS,
1748                                           r->res_argc, r->res_argv, 
1749                                           r->res_argv_lens,
1750                                           r->res_argv_types, 
1751                                           r->ident);
1752     silc_server_packet_send(server, r->router->connection,
1753                             SILC_PACKET_COMMAND, cmd->packet->flags,
1754                             res_cmd->data, res_cmd->len, FALSE);
1755
1756     /* Reprocess this packet after received reply */
1757     silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
1758                                 r->ident,
1759                                 silc_server_command_identify,
1760                                 silc_server_command_dup(cmd));
1761     cmd->pending = TRUE;
1762
1763     silc_buffer_free(res_cmd);
1764     for (k = 0; k < r->res_argc; k++)
1765       silc_free(r->res_argv[k]);
1766     silc_free(r->res_argv);
1767     silc_free(r->res_argv_lens);
1768     silc_free(r->res_argv_types);
1769     no_res = FALSE;
1770   }
1771   silc_free(resolve);
1772
1773   return no_res;
1774 }
1775
1776 static void
1777 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
1778                                         SilcClientEntry *clients,
1779                                         SilcUInt32 clients_count,
1780                                         SilcServerEntry *servers,
1781                                         SilcUInt32 servers_count,
1782                                         SilcChannelEntry *channels,
1783                                         SilcUInt32 channels_count,
1784                                         ResolveError errors,
1785                                         SilcUInt32 errors_count,
1786                                         int count)
1787 {
1788   SilcServer server = cmd->server;
1789   int i, k, valid_count;
1790   SilcUInt32 len;
1791   SilcBuffer packet, idp;
1792   SilcStatus status;
1793   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
1794   char nh[256], uh[256];
1795   SilcSocketConnection hsock;
1796   unsigned char *tmp;
1797
1798   status = SILC_STATUS_OK;
1799
1800   if (clients) {
1801     SilcClientEntry entry;
1802     valid_count = clients_count;
1803
1804     if (silc_argument_get_arg_type(cmd->args, 1, NULL)) {
1805       /* Process only valid clients and ignore those that are not registered. 
1806          This is checked with nickname only because when resolved client IDs
1807          we check that they are registered earlier. */
1808       valid_count = 0;
1809       for (i = 0; i < clients_count; i++) {
1810         if (clients[i]->data.status & SILC_IDLIST_STATUS_REGISTERED)
1811           valid_count++;
1812         else
1813           clients[i] = NULL;
1814       }
1815
1816       if (!valid_count) {
1817         /* No valid entries found at all, just send error */
1818         tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
1819         silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1820                                              SILC_STATUS_ERR_NO_SUCH_NICK, 0,
1821                                              3, tmp, tmp ? strlen(tmp) : 0);
1822         return;
1823       }
1824     }
1825
1826     /* Process all valid client entries and send command replies */
1827
1828     if (valid_count > 1)
1829       status = SILC_STATUS_LIST_START;
1830
1831     for (i = 0, k = 0; i < clients_count; i++) {
1832       entry = clients[i];
1833       if (!entry)
1834         continue;
1835
1836       if (k >= 1)
1837         status = SILC_STATUS_LIST_ITEM;
1838       if (valid_count > 1 && k == valid_count - 1 
1839           && !servers_count && !channels_count && !errors_count)
1840         status = SILC_STATUS_LIST_END;
1841       if (count && k - 1 == count)
1842         status = SILC_STATUS_LIST_END;
1843
1844       /* Send IDENTIFY reply */
1845
1846       idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1847       memset(uh, 0, sizeof(uh));
1848       memset(nh, 0, sizeof(nh));
1849       strncat(nh, entry->nickname, strlen(entry->nickname));
1850       if (!strchr(entry->nickname, '@')) {
1851         strncat(nh, "@", 1);
1852         if (entry->servername) {
1853           strncat(nh, entry->servername, strlen(entry->servername));
1854         } else {
1855           len = entry->router ? strlen(entry->router->server_name) :
1856             strlen(server->server_name);
1857           strncat(nh, entry->router ? entry->router->server_name :
1858                   server->server_name, len);
1859         }
1860       }
1861
1862       if (!entry->username) {
1863         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1864                                                       status, 0, ident, 2,
1865                                                       2, idp->data, idp->len, 
1866                                                       3, nh, strlen(nh));
1867       } else {
1868         strncat(uh, entry->username, strlen(entry->username));
1869         if (!strchr(entry->username, '@') && entry->connection) {
1870           strncat(uh, "@", 1);
1871           hsock = (SilcSocketConnection)entry->connection;
1872           len = strlen(hsock->hostname);
1873           strncat(uh, hsock->hostname, len);
1874         }
1875         
1876         packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1877                                                       status, 0, ident, 3,
1878                                                       2, idp->data, idp->len, 
1879                                                       3, nh, strlen(nh),
1880                                                       4, uh, strlen(uh));
1881       }
1882       
1883       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1884                               0, packet->data, packet->len, FALSE);
1885       
1886       silc_buffer_free(packet);
1887       silc_buffer_free(idp);
1888       
1889       if (status == SILC_STATUS_LIST_END)
1890         break;
1891       k++;
1892     }
1893   }
1894
1895   if (servers) {
1896     SilcServerEntry entry;
1897
1898     if (status == SILC_STATUS_OK && servers_count > 1)
1899       status = SILC_STATUS_LIST_START;
1900
1901     for (i = 0, k = 0; i < servers_count; i++) {
1902       entry = servers[i];
1903       
1904       if (k >= 1)
1905         status = SILC_STATUS_LIST_ITEM;
1906       if (servers_count > 1 && k == servers_count - 1 && !channels_count &&
1907           !errors_count)
1908         status = SILC_STATUS_LIST_END;
1909       if (count && k - 1 == count)
1910         status = SILC_STATUS_LIST_END;
1911       
1912       /* Send IDENTIFY reply */
1913       idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
1914       packet = 
1915         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1916                                              status, 0, ident, 2,
1917                                              2, idp->data, idp->len, 
1918                                              3, entry->server_name, 
1919                                              entry->server_name ? 
1920                                              strlen(entry->server_name) : 0);
1921       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1922                               0, packet->data, packet->len, FALSE);
1923       
1924       silc_buffer_free(packet);
1925       silc_buffer_free(idp);
1926       
1927       if (status == SILC_STATUS_LIST_END)
1928         break;
1929       k++;
1930     }
1931   }
1932
1933   if (channels) {
1934     SilcChannelEntry entry;
1935
1936     if (status == SILC_STATUS_OK && channels_count > 1)
1937       status = SILC_STATUS_LIST_START;
1938
1939     for (i = 0, k = 0; i < channels_count; i++) {
1940       entry = channels[i];
1941       
1942       if (k >= 1)
1943         status = SILC_STATUS_LIST_ITEM;
1944       if (channels_count > 1 && k == channels_count - 1 && !errors_count)
1945         status = SILC_STATUS_LIST_END;
1946       if (count && k - 1 == count)
1947         status = SILC_STATUS_LIST_END;
1948       
1949       /* Send IDENTIFY reply */
1950       idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
1951       packet = 
1952         silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1953                                              status, 0, ident, 2,
1954                                              2, idp->data, idp->len, 
1955                                              3, entry->channel_name, 
1956                                              entry->channel_name ? 
1957                                              strlen(entry->channel_name): 0);
1958       silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1959                               0, packet->data, packet->len, FALSE);
1960       
1961       silc_buffer_free(packet);
1962       silc_buffer_free(idp);
1963       
1964       if (status == SILC_STATUS_LIST_END)
1965         break;
1966       k++;
1967     }
1968   }
1969
1970   /* Send error replies */
1971   if (errors) {
1972     if (status == SILC_STATUS_OK && errors_count > 1)
1973       status = SILC_STATUS_LIST_START;
1974
1975     idp = NULL;
1976     for (i = 0, k = 0; i < errors_count; i++) {
1977       if (errors[i].id) {
1978         idp = silc_id_payload_encode(errors[i].id, SILC_ID_CLIENT);
1979         tmp = idp->data;
1980         len = idp->len;
1981       } else {
1982         tmp = silc_argument_get_arg_type(cmd->args, errors[i].index, &len);
1983       }
1984       
1985       if (k >= 1)
1986         status = SILC_STATUS_LIST_ITEM;
1987       if (errors_count > 1 && k == errors_count - 1)
1988         status = SILC_STATUS_LIST_END;
1989       if (count && k - 1 == count)
1990         status = SILC_STATUS_LIST_END;
1991       
1992       /* Send error */
1993       silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1994                                            (status == SILC_STATUS_OK ?
1995                                             errors[i].error : status),
1996                                            (status == SILC_STATUS_OK ?
1997                                             0 : errors[i].error),
1998                                            2, tmp, len);
1999       silc_buffer_free(idp);
2000       idp = NULL;
2001       
2002       if (status == SILC_STATUS_LIST_END)
2003         break;
2004       k++;
2005     }
2006   }
2007 }
2008
2009 static int
2010 silc_server_command_identify_process(SilcServerCommandContext cmd)
2011 {
2012   SilcUInt32 count = 0;
2013   int ret = 0;
2014   SilcClientEntry *clients = NULL;
2015   SilcServerEntry *servers = NULL;
2016   SilcChannelEntry *channels = NULL;
2017   SilcUInt32 clients_count = 0, servers_count = 0, channels_count = 0;
2018   SilcUInt32 errors_count = 0;
2019   ResolveError errors = NULL;
2020
2021   /* Parse the IDENTIFY request */
2022   ret = silc_server_command_identify_parse(cmd,
2023                                            &clients, &clients_count,
2024                                            &servers, &servers_count,
2025                                            &channels, &channels_count,
2026                                            &count, &errors, &errors_count);
2027   if (ret < 1)
2028     return ret;
2029   ret = 0;
2030
2031   /* Check that all mandatory fields are present and request those data
2032      from the server who owns the client if necessary. */
2033   if (!silc_server_command_identify_check_client(cmd, clients, 
2034                                                  clients_count)) {
2035     ret = -1;
2036     goto out;
2037   }
2038
2039   /* Send the command reply to the client */
2040   silc_server_command_identify_send_reply(cmd, 
2041                                           clients, clients_count,
2042                                           servers, servers_count,
2043                                           channels, channels_count, 
2044                                           errors, errors_count,
2045                                           count);
2046
2047  out:
2048   silc_free(clients);
2049   silc_free(servers);
2050   silc_free(channels);
2051   silc_free(errors);
2052   return ret;
2053 }
2054
2055 SILC_SERVER_CMD_FUNC(identify)
2056 {
2057   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2058   int ret = 0;
2059
2060   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
2061
2062   ret = silc_server_command_identify_process(cmd);
2063   silc_server_command_free(cmd);
2064 }
2065
2066 /* Server side of command NICK. Sets nickname for user. Setting
2067    nickname causes generation of a new client ID for the client. The
2068    new client ID is sent to the client after changing the nickname. */
2069
2070 SILC_SERVER_CMD_FUNC(nick)
2071 {
2072   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2073   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2074   SilcServer server = cmd->server;
2075   SilcBuffer packet, nidp, oidp = NULL;
2076   SilcClientID *new_id;
2077   SilcUInt32 nick_len;
2078   char *nick;
2079   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2080   int nickfail = 0;
2081
2082   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2083     goto out;
2084
2085   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_NICK, cmd, 1, 1);
2086
2087   /* Check nickname */
2088   nick = silc_argument_get_arg_type(cmd->args, 1, &nick_len);
2089   if (nick_len > 128)
2090     nick[128] = '\0';
2091   if (silc_server_name_bad_chars(nick, nick_len) == TRUE) {
2092     silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2093                                           SILC_STATUS_ERR_BAD_NICKNAME, 0);
2094     goto out;
2095   }
2096
2097   /* Check for same nickname */
2098   if (!strcmp(client->nickname, nick)) {
2099     nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2100     goto send_reply;
2101   }
2102
2103   /* Create new Client ID */
2104   while (!silc_id_create_client_id(cmd->server, cmd->server->id, 
2105                                    cmd->server->rng, 
2106                                    cmd->server->md5hash, nick,
2107                                    &new_id)) {
2108     nickfail++;
2109     if (nickfail > 9) {
2110       silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
2111                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
2112       goto out;
2113     }
2114     snprintf(&nick[strlen(nick) - 1], 1, "%d", nickfail);
2115   }
2116
2117   /* Send notify about nickname change to our router. We send the new
2118      ID and ask to replace it with the old one. If we are router the
2119      packet is broadcasted. Send NICK_CHANGE notify. */
2120   silc_server_send_notify_nick_change(server, SILC_PRIMARY_ROUTE(server),
2121                                       SILC_BROADCAST(server), client->id,
2122                                       new_id, nick);
2123
2124   /* Check if anyone is watching the old nickname */
2125   if (server->server_type == SILC_ROUTER)
2126     silc_server_check_watcher_list(server, client, nick,
2127                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
2128
2129   oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2130
2131   /* Remove old cache entry */
2132   silc_idcache_del_by_context(server->local_list->clients, client);
2133
2134   silc_free(client->id);
2135   client->id = new_id;
2136
2137   silc_free(client->nickname);
2138   client->nickname = strdup(nick);
2139
2140   /* Update client cache */
2141   silc_idcache_add(server->local_list->clients, client->nickname, 
2142                    client->id, (void *)client, 0, NULL);
2143
2144   nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2145
2146   /* Send NICK_CHANGE notify to the client's channels */
2147   silc_server_send_notify_on_channels(server, NULL, client, 
2148                                       SILC_NOTIFY_TYPE_NICK_CHANGE, 3,
2149                                       oidp->data, oidp->len, 
2150                                       nidp->data, nidp->len,
2151                                       client->nickname, 
2152                                       strlen(client->nickname));
2153
2154   /* Check if anyone is watching the new nickname */
2155   if (server->server_type == SILC_ROUTER)
2156     silc_server_check_watcher_list(server, client, NULL,
2157                                    SILC_NOTIFY_TYPE_NICK_CHANGE);
2158
2159  send_reply:
2160   /* Send the new Client ID as reply command back to client */
2161   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK, 
2162                                                 SILC_STATUS_OK, 0, ident, 2,
2163                                                 2, nidp->data, nidp->len,
2164                                                 3, nick, strlen(nick));
2165   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2166                           0, packet->data, packet->len, FALSE);
2167
2168   silc_buffer_free(packet);
2169   silc_buffer_free(nidp);
2170   if (oidp)
2171     silc_buffer_free(oidp);
2172   
2173  out:
2174   silc_server_command_free(cmd);
2175 }
2176
2177 /* Sends the LIST command reply */
2178
2179 static void
2180 silc_server_command_list_send_reply(SilcServerCommandContext cmd,
2181                                     SilcChannelEntry *lch, 
2182                                     SilcUInt32 lch_count,
2183                                     SilcChannelEntry *gch,
2184                                     SilcUInt32 gch_count)
2185 {
2186   int i, k;
2187   SilcBuffer packet, idp;
2188   SilcChannelEntry entry;
2189   SilcStatus status;
2190   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2191   char *topic;
2192   unsigned char usercount[4];
2193   SilcUInt32 users;
2194   int valid_lcount = 0, valid_rcount = 0;
2195
2196   for (i = 0; i < lch_count; i++) {
2197     if (lch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2198       lch[i] = NULL;
2199     else
2200       valid_lcount++;
2201   }
2202   for (i = 0; i < gch_count; i++) {
2203     if (gch[i]->mode & SILC_CHANNEL_MODE_SECRET)
2204       gch[i] = NULL;
2205     else
2206       valid_rcount++;
2207   }
2208
2209   status = SILC_STATUS_OK;
2210   if ((lch_count + gch_count) > 1)
2211     status = SILC_STATUS_LIST_START;
2212
2213   /* Local list */
2214   for (i = 0, k = 0; i < lch_count; i++) {
2215     entry = lch[i];
2216     if (!entry)
2217       continue;
2218
2219     if (k >= 1)
2220       status = SILC_STATUS_LIST_ITEM;
2221     if (valid_lcount > 1 && k == valid_lcount - 1 && !valid_rcount)
2222       status = SILC_STATUS_LIST_END;
2223
2224     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2225
2226     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2227       topic = "*private*";
2228       memset(usercount, 0, sizeof(usercount));
2229     } else {
2230       topic = entry->topic;
2231       users = silc_hash_table_count(entry->user_list);
2232       SILC_PUT32_MSB(users, usercount);
2233     }
2234
2235     /* Send the reply */
2236     packet = 
2237       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2238                                            status, 0, ident, 4,
2239                                            2, idp->data, idp->len,
2240                                            3, entry->channel_name, 
2241                                            strlen(entry->channel_name),
2242                                            4, topic, topic ? strlen(topic) : 0,
2243                                            5, usercount, 4);
2244     silc_server_packet_send(cmd->server, cmd->sock, 
2245                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2246                             packet->len, FALSE);
2247     silc_buffer_free(packet);
2248     silc_buffer_free(idp);
2249     k++;
2250   }
2251
2252   /* Global list */
2253   for (i = 0, k = 0; i < gch_count; i++) {
2254     entry = gch[i];
2255     if (!entry)
2256       continue;
2257
2258     if (k >= 1)
2259       status = SILC_STATUS_LIST_ITEM;
2260     if (valid_rcount > 1 && k == valid_rcount - 1)
2261       status = SILC_STATUS_LIST_END;
2262
2263     idp = silc_id_payload_encode(entry->id, SILC_ID_CHANNEL);
2264
2265     if (entry->mode & SILC_CHANNEL_MODE_PRIVATE) {
2266       topic = "*private*";
2267       memset(usercount, 0, sizeof(usercount));
2268     } else {
2269       topic = entry->topic;
2270       users = entry->user_count;
2271       SILC_PUT32_MSB(users, usercount);
2272     }
2273
2274     /* Send the reply */
2275     packet = 
2276       silc_command_reply_payload_encode_va(SILC_COMMAND_LIST, 
2277                                            status, 0, ident, 4,
2278                                            2, idp->data, idp->len,
2279                                            3, entry->channel_name, 
2280                                            strlen(entry->channel_name),
2281                                            4, topic, topic ? strlen(topic) : 0,
2282                                            5, usercount, 4);
2283     silc_server_packet_send(cmd->server, cmd->sock, 
2284                             SILC_PACKET_COMMAND_REPLY, 0, packet->data, 
2285                             packet->len, FALSE);
2286     silc_buffer_free(packet);
2287     silc_buffer_free(idp);
2288     k++;
2289   }
2290 }
2291
2292 /* Server side of LIST command. This lists the channel of the requested
2293    server. Secret channels are not listed. */
2294
2295 SILC_SERVER_CMD_FUNC(list)
2296 {
2297   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2298   SilcServer server = cmd->server;
2299   SilcChannelID *channel_id = NULL;
2300   unsigned char *tmp;
2301   SilcUInt32 tmp_len;
2302   SilcChannelEntry *lchannels = NULL, *gchannels = NULL;
2303   SilcUInt32 lch_count = 0, gch_count = 0;
2304
2305   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LIST, cmd, 0, 1);
2306
2307   /* If we are normal server, send the command to router, since we
2308      want to know all channels in the network. */
2309   if (!cmd->pending && server->server_type == SILC_SERVER && 
2310       !server->standalone) {
2311     SilcBuffer tmpbuf;
2312     SilcUInt16 old_ident;
2313     
2314     old_ident = silc_command_get_ident(cmd->payload);
2315     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2316     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2317     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2318                             SILC_PACKET_COMMAND, cmd->packet->flags,
2319                             tmpbuf->data, tmpbuf->len, TRUE);
2320
2321     /* Reprocess this packet after received reply from router */
2322     silc_server_command_pending(server, SILC_COMMAND_LIST, 
2323                                 silc_command_get_ident(cmd->payload),
2324                                 silc_server_command_list, 
2325                                 silc_server_command_dup(cmd));
2326     cmd->pending = TRUE;
2327     silc_command_set_ident(cmd->payload, old_ident);
2328     silc_buffer_free(tmpbuf);
2329     goto out;
2330   }
2331
2332   /* Get Channel ID */
2333   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2334   if (tmp) {
2335     channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2336     if (!channel_id) {
2337       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LIST,
2338                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2339       goto out;
2340     }
2341   }
2342
2343   /* Get the channels from local list */
2344   lchannels = silc_idlist_get_channels(server->local_list, channel_id,
2345                                        &lch_count);
2346   
2347   /* Get the channels from global list */
2348   gchannels = silc_idlist_get_channels(server->global_list, channel_id,
2349                                        &gch_count);
2350
2351   /* Send the reply */
2352   silc_server_command_list_send_reply(cmd, lchannels, lch_count, 
2353                                       gchannels, gch_count);
2354
2355   silc_free(lchannels);
2356   silc_free(gchannels);
2357
2358  out:
2359   silc_server_command_free(cmd);
2360 }
2361
2362 /* Server side of TOPIC command. Sets topic for channel and/or returns
2363    current topic to client. */
2364
2365 SILC_SERVER_CMD_FUNC(topic)
2366 {
2367   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2368   SilcServer server = cmd->server;
2369   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2370   SilcChannelID *channel_id;
2371   SilcChannelEntry channel;
2372   SilcChannelClientEntry chl;
2373   SilcBuffer packet, idp;
2374   unsigned char *tmp;
2375   SilcUInt32 argc, tmp_len;
2376   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2377
2378   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_TOPIC, cmd, 1, 2);
2379
2380   argc = silc_argument_get_arg_num(cmd->args);
2381
2382   /* Get Channel ID */
2383   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2384   if (!tmp) {
2385     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2386                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2387     goto out;
2388   }
2389   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2390   if (!channel_id) {
2391     silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2392                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2393     goto out;
2394   }
2395
2396   /* Check whether the channel exists */
2397   channel = silc_idlist_find_channel_by_id(server->local_list, 
2398                                            channel_id, NULL);
2399   if (!channel) {
2400     channel = silc_idlist_find_channel_by_id(server->global_list, 
2401                                              channel_id, NULL);
2402     if (!channel) {
2403       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2404                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2405                                             0);
2406       goto out;
2407     }
2408   }
2409
2410   if (argc > 1) {
2411     /* Get the topic */
2412     tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
2413     if (!tmp) {
2414       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2415                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2416                                             0);
2417       goto out;
2418     }
2419
2420     if (strlen(tmp) > 256) {
2421       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2422                                             SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2423                                             0);
2424       goto out;
2425     }
2426
2427     /* See whether the client is on channel and has rights to change topic */
2428     if (!silc_server_client_on_channel(client, channel, &chl)) {
2429       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2430                                             SILC_STATUS_ERR_NOT_ON_CHANNEL,
2431                                             0);
2432       goto out;
2433     }
2434
2435     if (channel->mode & SILC_CHANNEL_MODE_TOPIC &&
2436         !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2437         !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2438       silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
2439                                             SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2440                                             0);
2441       goto out;
2442     }
2443
2444     if (!channel->topic || strcmp(channel->topic, tmp)) {
2445       /* Set the topic for channel */
2446       silc_free(channel->topic);
2447       channel->topic = strdup(tmp);
2448
2449       /* Send TOPIC_SET notify type to the network */
2450       silc_server_send_notify_topic_set(server, SILC_PRIMARY_ROUTE(server),
2451                                         SILC_BROADCAST(server), channel,
2452                                         client->id, SILC_ID_CLIENT,
2453                                         channel->topic);
2454
2455       /* Send notify about topic change to all clients on the channel */
2456       idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2457       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
2458                                          SILC_NOTIFY_TYPE_TOPIC_SET, 2,
2459                                          idp->data, idp->len,
2460                                          channel->topic,
2461                                          strlen(channel->topic));
2462       silc_buffer_free(idp);
2463     }
2464   }
2465
2466   /* Send the topic to client as reply packet */
2467   idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2468   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC, 
2469                                                 SILC_STATUS_OK, 0, ident, 2, 
2470                                                 2, idp->data, idp->len,
2471                                                 3, channel->topic, 
2472                                                 channel->topic ? 
2473                                                 strlen(channel->topic) : 0);
2474   silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
2475                           0, packet->data, packet->len, FALSE);
2476
2477   silc_buffer_free(packet);
2478   silc_buffer_free(idp);
2479   silc_free(channel_id);
2480
2481  out:
2482   silc_server_command_free(cmd);
2483 }
2484
2485 /* Server side of INVITE command. Invites some client to join some channel. 
2486    This command is also used to manage the invite list of the channel. */
2487
2488 SILC_SERVER_CMD_FUNC(invite)
2489 {
2490   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2491   SilcServer server = cmd->server;
2492   SilcSocketConnection sock = cmd->sock, dest_sock;
2493   SilcChannelClientEntry chl;
2494   SilcClientEntry sender, dest;
2495   SilcClientID *dest_id = NULL;
2496   SilcChannelEntry channel;
2497   SilcChannelID *channel_id = NULL;
2498   SilcIDListData idata;
2499   SilcBuffer idp, idp2, packet;
2500   unsigned char *tmp, *add, *del;
2501   SilcUInt32 len;
2502   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2503
2504   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INVITE, cmd, 1, 4);
2505
2506   /* Get Channel ID */
2507   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2508   if (!tmp) {
2509     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2510                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2511     goto out;
2512   }
2513   channel_id = silc_id_payload_parse_id(tmp, len, NULL);
2514   if (!channel_id) {
2515     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2516                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
2517     goto out;
2518   }
2519
2520   /* Get the channel entry */
2521   channel = silc_idlist_find_channel_by_id(server->local_list, 
2522                                            channel_id, NULL);
2523   if (!channel) {
2524     channel = silc_idlist_find_channel_by_id(server->global_list, 
2525                                              channel_id, NULL);
2526     if (!channel) {
2527       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2528                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
2529                                             0);
2530       goto out;
2531     }
2532   }
2533
2534   /* Check whether the sender of this command is on the channel. */
2535   sender = (SilcClientEntry)sock->user_data;
2536   if (!silc_server_client_on_channel(sender, channel, &chl)) {
2537     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2538                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
2539     goto out;
2540   }
2541
2542   /* Check whether the channel is invite-only channel. If yes then the
2543      sender of this command must be at least channel operator. */
2544   if (channel->mode & SILC_CHANNEL_MODE_INVITE &&
2545       !(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
2546       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
2547     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2548                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV,
2549                                           0);
2550     goto out;
2551   }
2552
2553   /* Get destination client ID */
2554   tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
2555   if (tmp) {
2556     char invite[512];
2557     bool resolve;
2558
2559     dest_id = silc_id_payload_parse_id(tmp, len, NULL);
2560     if (!dest_id) {
2561       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2562                                             SILC_STATUS_ERR_NO_CLIENT_ID, 0);
2563       goto out;
2564     }
2565
2566     /* Get the client entry */
2567     dest = silc_server_get_client_resolve(server, dest_id, FALSE, &resolve);
2568     if (!dest) {
2569       if (server->server_type != SILC_SERVER || !resolve) {
2570         silc_server_command_send_status_reply(
2571                                         cmd, SILC_COMMAND_INVITE,
2572                                         SILC_STATUS_ERR_NO_SUCH_CLIENT_ID, 0);
2573         goto out;
2574       }
2575       
2576       /* The client info is being resolved. Reprocess this packet after
2577          receiving the reply to the query. */
2578       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
2579                                   server->cmd_ident,
2580                                   silc_server_command_invite, 
2581                                   silc_server_command_dup(cmd));
2582       cmd->pending = TRUE;
2583       silc_free(channel_id);
2584       silc_free(dest_id);
2585       goto out;
2586     }
2587
2588     /* Check whether the requested client is already on the channel. */
2589     if (silc_server_client_on_channel(dest, channel, NULL)) {
2590       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2591                                             SILC_STATUS_ERR_USER_ON_CHANNEL,
2592                                             0);
2593       goto out;
2594     }
2595     
2596     /* Get route to the client */
2597     dest_sock = silc_server_get_client_route(server, NULL, 0, dest_id, 
2598                                              &idata, NULL);
2599     if (!dest_sock) {
2600       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2601                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2602                                             0);
2603       goto out;
2604     }
2605
2606     memset(invite, 0, sizeof(invite));
2607     strncat(invite, dest->nickname, strlen(dest->nickname));
2608     strncat(invite, "!", 1);
2609     strncat(invite, dest->username, strlen(dest->username));
2610     if (!strchr(dest->username, '@')) {
2611       strncat(invite, "@", 1);
2612       strncat(invite, cmd->sock->hostname, strlen(cmd->sock->hostname));
2613     }
2614
2615     len = strlen(invite);
2616     if (!channel->invite_list)
2617       channel->invite_list = silc_calloc(len + 2, 
2618                                          sizeof(*channel->invite_list));
2619     else
2620       channel->invite_list = silc_realloc(channel->invite_list, 
2621                                           sizeof(*channel->invite_list) * 
2622                                           (len + 
2623                                            strlen(channel->invite_list) + 2));
2624     strncat(channel->invite_list, invite, len);
2625     strncat(channel->invite_list, ",", 1);
2626
2627     if (!(dest->mode & SILC_UMODE_BLOCK_INVITE)) {
2628       /* Send notify to the client that is invited to the channel */
2629       idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
2630       idp2 = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
2631       silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id, 
2632                                    SILC_ID_CLIENT,
2633                                    SILC_NOTIFY_TYPE_INVITE, 3, 
2634                                    idp->data, idp->len, 
2635                                    channel->channel_name, 
2636                                    strlen(channel->channel_name),
2637                                    idp2->data, idp2->len);
2638       silc_buffer_free(idp);
2639       silc_buffer_free(idp2);
2640     }
2641   }
2642
2643   /* Add the client to the invite list of the channel */
2644   add = silc_argument_get_arg_type(cmd->args, 3, &len);
2645   if (add) {
2646     if (!channel->invite_list)
2647       channel->invite_list = silc_calloc(len + 2, 
2648                                          sizeof(*channel->invite_list));
2649     else
2650       channel->invite_list = silc_realloc(channel->invite_list, 
2651                                           sizeof(*channel->invite_list) * 
2652                                           (len + 
2653                                            strlen(channel->invite_list) + 2));
2654     if (add[len - 1] == ',')
2655       add[len - 1] = '\0';
2656     
2657     strncat(channel->invite_list, add, len);
2658     strncat(channel->invite_list, ",", 1);
2659   }
2660
2661   /* Get the invite to be removed and remove it from the list */
2662   del = silc_argument_get_arg_type(cmd->args, 4, &len);
2663   if (del && channel->invite_list) {
2664     char *start, *end, *n;
2665
2666     if (!strncmp(channel->invite_list, del, 
2667                  strlen(channel->invite_list) - 1)) {
2668       silc_free(channel->invite_list);
2669       channel->invite_list = NULL;
2670     } else {
2671       start = strstr(channel->invite_list, del);
2672       if (start && strlen(start) >= len) {
2673         end = start + len;
2674         n = silc_calloc(strlen(channel->invite_list) - len, sizeof(*n));
2675         strncat(n, channel->invite_list, start - channel->invite_list);
2676         strncat(n, end + 1, ((channel->invite_list + 
2677                               strlen(channel->invite_list)) - end) - 1);
2678         silc_free(channel->invite_list);
2679         channel->invite_list = n;
2680       }
2681     }
2682   }
2683
2684   /* Send notify to the primary router */
2685   silc_server_send_notify_invite(server, SILC_PRIMARY_ROUTE(server),
2686                                  SILC_BROADCAST(server), channel,
2687                                  sender->id, add, del);
2688
2689   /* Send command reply */
2690   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2691
2692   if (add || del)
2693     packet = 
2694       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2695                                            SILC_STATUS_OK, 0, ident, 2,
2696                                            2, tmp, len,
2697                                            3, channel->invite_list,
2698                                            channel->invite_list ?
2699                                            strlen(channel->invite_list) : 0);
2700   else
2701     packet = 
2702       silc_command_reply_payload_encode_va(SILC_COMMAND_INVITE,
2703                                            SILC_STATUS_OK, 0, ident, 1,
2704                                            2, tmp, len);
2705   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
2706                           packet->data, packet->len, FALSE);
2707   silc_buffer_free(packet);
2708
2709  out:
2710   silc_free(dest_id);
2711   silc_free(channel_id);
2712   silc_server_command_free(cmd);
2713 }
2714
2715 typedef struct {
2716   SilcServer server;
2717   SilcSocketConnection sock;
2718   char *signoff;
2719 } *QuitInternal;
2720
2721 /* Quits connection to client. This gets called if client won't
2722    close the connection even when it has issued QUIT command. */
2723
2724 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
2725 {
2726   QuitInternal q = (QuitInternal)context;
2727
2728   /* Free all client specific data, such as client entry and entires
2729      on channels this client may be on. */
2730   silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
2731                                TRUE, q->signoff);
2732   q->sock->user_data = NULL;
2733
2734   /* Close the connection on our side */
2735   silc_server_close_connection(q->server, q->sock);
2736
2737   silc_free(q->signoff);
2738   silc_free(q);
2739 }
2740
2741 /* Quits SILC session. This is the normal way to disconnect client. */
2742  
2743 SILC_SERVER_CMD_FUNC(quit)
2744 {
2745   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2746   SilcServer server = cmd->server;
2747   SilcSocketConnection sock = cmd->sock;
2748   QuitInternal q;
2749   unsigned char *tmp = NULL;
2750   SilcUInt32 len = 0;
2751
2752   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_QUIT, cmd, 0, 1);
2753
2754   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2755     goto out;
2756
2757   /* Get message */
2758   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2759   if (len > 128)
2760     tmp = NULL;
2761
2762   q = silc_calloc(1, sizeof(*q));
2763   q->server = server;
2764   q->sock = sock;
2765   q->signoff = tmp ? strdup(tmp) : NULL;
2766
2767   /* We quit the connection with little timeout */
2768   silc_schedule_task_add(server->schedule, sock->sock,
2769                          silc_server_command_quit_cb, (void *)q,
2770                          0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
2771
2772  out:
2773   silc_server_command_free(cmd);
2774 }
2775
2776 /* Server side of command KILL. This command is used by router operator
2777    to remove an client from the SILC Network temporarily. */
2778
2779 SILC_SERVER_CMD_FUNC(kill)
2780 {
2781   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2782   SilcServer server = cmd->server;
2783   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2784   SilcClientEntry remote_client;
2785   SilcClientID *client_id;
2786   unsigned char *tmp, *comment;
2787   SilcUInt32 tmp_len, tmp_len2;
2788   bool local;
2789
2790   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_KILL, cmd, 1, 2);
2791
2792   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
2793     goto out;
2794
2795   /* KILL command works only on router */
2796   if (server->server_type != SILC_ROUTER) {
2797     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2798                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2799     goto out;
2800   }
2801
2802   /* Check whether client has the permissions. */
2803   if (!(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
2804     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2805                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
2806     goto out;
2807   }
2808
2809   /* Get the client ID */
2810   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2811   if (!tmp) {
2812     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2813                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
2814                                           0);
2815     goto out;
2816   }
2817   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2818   if (!client_id) {
2819     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2820                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2821                                           0);
2822     goto out;
2823   }
2824
2825   /* Get the client entry */
2826   remote_client = silc_idlist_find_client_by_id(server->local_list, 
2827                                                 client_id, TRUE, NULL);
2828   local = TRUE;
2829   if (!remote_client) {
2830     remote_client = silc_idlist_find_client_by_id(server->global_list, 
2831                                                   client_id, TRUE, NULL);
2832     local = FALSE;
2833     if (!remote_client) {
2834       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2835                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
2836                                             0);
2837       goto out;
2838     }
2839   }
2840
2841   /* Get comment */
2842   comment = silc_argument_get_arg_type(cmd->args, 2, &tmp_len2);
2843   if (tmp_len2 > 128)
2844     tmp_len2 = 128;
2845
2846   /* Send reply to the sender */
2847   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KILL,
2848                                         SILC_STATUS_OK, 0);
2849
2850   /* Check if anyone is watching this nickname */
2851   if (server->server_type == SILC_ROUTER)
2852     silc_server_check_watcher_list(server, client, NULL,
2853                                    SILC_NOTIFY_TYPE_KILLED);
2854
2855   /* Now do the killing */
2856   silc_server_kill_client(server, remote_client, comment, client->id,
2857                           SILC_ID_CLIENT);
2858
2859  out:
2860   silc_server_command_free(cmd);
2861 }
2862
2863 /* Server side of command INFO. This sends information about us to 
2864    the client. If client requested specific server we will send the 
2865    command to that server. */
2866
2867 SILC_SERVER_CMD_FUNC(info)
2868 {
2869   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2870   SilcServer server = cmd->server;
2871   SilcBuffer packet, idp;
2872   unsigned char *tmp;
2873   SilcUInt32 tmp_len;
2874   char *dest_server, *server_info = NULL, *server_name;
2875   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
2876   SilcServerEntry entry = NULL;
2877   SilcServerID *server_id = NULL;
2878
2879   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 0, 2);
2880
2881   /* Get server name */
2882   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
2883
2884   /* Get Server ID */
2885   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2886   if (tmp) {
2887     server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
2888     if (!server_id) {
2889       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2890                                             SILC_STATUS_ERR_NO_SERVER_ID, 0);
2891       goto out;
2892     }
2893   }
2894
2895   if (server_id) {
2896     /* Check whether we have this server cached */
2897     entry = silc_idlist_find_server_by_id(server->local_list,
2898                                           server_id, TRUE, NULL);
2899     if (!entry) {
2900       entry = silc_idlist_find_server_by_id(server->global_list,
2901                                             server_id, TRUE, NULL);
2902       if (!entry && server->server_type != SILC_SERVER) {
2903         silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2904                                               SILC_STATUS_ERR_NO_SUCH_SERVER,
2905                                               0);
2906         goto out;
2907       }
2908     }
2909   }
2910
2911   /* Some buggy servers has sent request to router about themselves. */
2912   if (server->server_type != SILC_SERVER && cmd->sock->user_data == entry)
2913     goto out;
2914
2915   if ((!dest_server && !server_id && !entry) || (entry && 
2916                                                  entry == server->id_entry) ||
2917       (dest_server && !cmd->pending && 
2918        !strncasecmp(dest_server, server->server_name, strlen(dest_server)))) {
2919     /* Send our reply */
2920     char info_string[256];
2921
2922     memset(info_string, 0, sizeof(info_string));
2923     snprintf(info_string, sizeof(info_string), 
2924              "location: %s server: %s admin: %s <%s>",
2925              server->config->server_info->location,
2926              server->config->server_info->server_type,
2927              server->config->server_info->admin,
2928              server->config->server_info->email);
2929
2930     server_info = info_string;
2931     entry = server->id_entry;
2932   } else {
2933     /* Check whether we have this server cached */
2934     if (!entry && dest_server) {
2935       entry = silc_idlist_find_server_by_name(server->global_list,
2936                                               dest_server, TRUE, NULL);
2937       if (!entry) {
2938         entry = silc_idlist_find_server_by_name(server->local_list,
2939                                                 dest_server, TRUE, NULL);
2940       }
2941     }
2942
2943     if (!cmd->pending &&
2944         server->server_type != SILC_SERVER && entry && !entry->server_info) {
2945       /* Send to the server */
2946       SilcBuffer tmpbuf;
2947       SilcUInt16 old_ident;
2948
2949       old_ident = silc_command_get_ident(cmd->payload);
2950       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2951       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2952
2953       silc_server_packet_send(server, entry->connection,
2954                               SILC_PACKET_COMMAND, cmd->packet->flags,
2955                               tmpbuf->data, tmpbuf->len, TRUE);
2956
2957       /* Reprocess this packet after received reply from router */
2958       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2959                                   silc_command_get_ident(cmd->payload),
2960                                   silc_server_command_info,
2961                                   silc_server_command_dup(cmd));
2962       cmd->pending = TRUE;
2963       silc_command_set_ident(cmd->payload, old_ident);
2964       silc_buffer_free(tmpbuf);
2965       goto out;
2966     }
2967
2968     if (!entry && !cmd->pending && !server->standalone) {
2969       /* Send to the primary router */
2970       SilcBuffer tmpbuf;
2971       SilcUInt16 old_ident;
2972
2973       old_ident = silc_command_get_ident(cmd->payload);
2974       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
2975       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2976
2977       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
2978                               SILC_PACKET_COMMAND, cmd->packet->flags,
2979                               tmpbuf->data, tmpbuf->len, TRUE);
2980
2981       /* Reprocess this packet after received reply from router */
2982       silc_server_command_pending(server, SILC_COMMAND_INFO, 
2983                                   silc_command_get_ident(cmd->payload),
2984                                   silc_server_command_info,
2985                                   silc_server_command_dup(cmd));
2986       cmd->pending = TRUE;
2987       silc_command_set_ident(cmd->payload, old_ident);
2988       silc_buffer_free(tmpbuf);
2989       goto out;
2990     }
2991   }
2992
2993   silc_free(server_id);
2994
2995   if (!entry) {
2996     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
2997                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
2998     goto out;
2999   }
3000
3001   idp = silc_id_payload_encode(entry->id, SILC_ID_SERVER);
3002   if (!server_info)
3003     server_info = entry->server_info;
3004   server_name = entry->server_name;
3005
3006   /* Send the reply */
3007   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
3008                                                 SILC_STATUS_OK, 0, ident, 3,
3009                                                 2, idp->data, idp->len,
3010                                                 3, server_name, 
3011                                                 strlen(server_name),
3012                                                 4, server_info, 
3013                                                 server_info ? 
3014                                                 strlen(server_info) : 0);
3015   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3016                           packet->data, packet->len, FALSE);
3017     
3018   silc_buffer_free(packet);
3019   silc_buffer_free(idp);
3020
3021  out:
3022   silc_server_command_free(cmd);
3023 }
3024
3025 /* Server side of command PING. This just replies to the ping. */
3026
3027 SILC_SERVER_CMD_FUNC(ping)
3028 {
3029   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3030   SilcServer server = cmd->server;
3031   SilcServerID *id;
3032   SilcUInt32 len;
3033   unsigned char *tmp;
3034
3035   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_INFO, cmd, 1, 2);
3036
3037   /* Get Server ID */
3038   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3039   if (!tmp) {
3040     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3041                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
3042     goto out;
3043   }
3044   id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
3045   if (!id)
3046     goto out;
3047
3048   if (SILC_ID_SERVER_COMPARE(id, server->id)) {
3049     /* Send our reply */
3050     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3051                                           SILC_STATUS_OK, 0);
3052   } else {
3053     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
3054                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3055     goto out;
3056   }
3057
3058   silc_free(id);
3059
3060  out:
3061   silc_server_command_free(cmd);
3062 }
3063
3064 /* Server side of command STATS. */
3065
3066 SILC_SERVER_CMD_FUNC(stats)
3067 {
3068   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3069   SilcServer server = cmd->server;
3070   SilcServerID *server_id;
3071   unsigned char *tmp;
3072   SilcUInt32 tmp_len;
3073   SilcBuffer packet, stats;
3074   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3075   SilcUInt32 uptime;
3076
3077   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_STATS, cmd, 1, 1);
3078
3079   /* Get Server ID */
3080   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3081   if (!tmp) {
3082     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3083                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
3084     goto out;
3085   }
3086   server_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3087   if (!server_id)
3088     goto out;
3089
3090   /* The ID must be ours */
3091   if (!SILC_ID_SERVER_COMPARE(server->id, server_id)) {
3092     silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3093                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3094     silc_free(server_id);
3095     goto out;
3096   }
3097   silc_free(server_id);
3098
3099   /* If we are router then just send everything we got. If we are normal
3100      server then we'll send this to our router to get all the latest
3101      statistical information. */
3102   if (!cmd->pending && server->server_type != SILC_ROUTER && 
3103       !server->standalone) {
3104     /* Send request to our router */
3105     SilcBuffer idp = silc_id_payload_encode(server->router->id, 
3106                                             SILC_ID_SERVER);
3107     packet = silc_command_payload_encode_va(SILC_COMMAND_STATS, 
3108                                             ++server->cmd_ident, 1,
3109                                             1, idp->data, idp->len);
3110     silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3111                             SILC_PACKET_COMMAND, 0, packet->data,
3112                             packet->len, FALSE);
3113
3114     /* Reprocess this packet after received reply from router */
3115     silc_server_command_pending(server, SILC_COMMAND_STATS, 
3116                                 server->cmd_ident,
3117                                 silc_server_command_stats,
3118                                 silc_server_command_dup(cmd));
3119     cmd->pending = TRUE;
3120     silc_buffer_free(packet);
3121     silc_buffer_free(idp);
3122     goto out;
3123   }
3124
3125   /* Send our reply to sender */
3126   uptime = time(NULL) - server->starttime;
3127
3128   stats = silc_buffer_alloc_size(60);
3129   silc_buffer_format(stats,
3130                      SILC_STR_UI_INT(server->starttime),
3131                      SILC_STR_UI_INT(uptime),
3132                      SILC_STR_UI_INT(server->stat.my_clients),
3133                      SILC_STR_UI_INT(server->stat.my_channels),
3134                      SILC_STR_UI_INT(server->stat.my_server_ops),
3135                      SILC_STR_UI_INT(server->stat.my_router_ops),
3136                      SILC_STR_UI_INT(server->stat.cell_clients),
3137                      SILC_STR_UI_INT(server->stat.cell_channels),
3138                      SILC_STR_UI_INT(server->stat.cell_servers),
3139                      SILC_STR_UI_INT(server->stat.clients),
3140                      SILC_STR_UI_INT(server->stat.channels),
3141                      SILC_STR_UI_INT(server->stat.servers),
3142                      SILC_STR_UI_INT(server->stat.routers),
3143                      SILC_STR_UI_INT(server->stat.server_ops),
3144                      SILC_STR_UI_INT(server->stat.router_ops),
3145                      SILC_STR_END);
3146
3147   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_STATS, 
3148                                                 SILC_STATUS_OK, 0, ident, 2,
3149                                                 2, tmp, tmp_len,
3150                                                 3, stats->data, stats->len);
3151   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
3152                           0, packet->data, packet->len, FALSE);
3153   silc_buffer_free(packet);
3154   silc_buffer_free(stats);
3155
3156  out:
3157   silc_server_command_free(cmd);
3158 }
3159
3160 /* Internal routine to join channel. The channel sent to this function
3161    has been either created or resolved from ID lists. This joins the sent
3162    client to the channel. */
3163
3164 static void silc_server_command_join_channel(SilcServer server, 
3165                                              SilcServerCommandContext cmd,
3166                                              SilcChannelEntry channel,
3167                                              SilcClientID *client_id,
3168                                              bool created,
3169                                              bool create_key,
3170                                              SilcUInt32 umode,
3171                                              const unsigned char *auth,
3172                                              SilcUInt32 auth_len)
3173 {
3174   SilcSocketConnection sock = cmd->sock;
3175   unsigned char *tmp;
3176   SilcUInt32 tmp_len, user_count;
3177   unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
3178   SilcClientEntry client;
3179   SilcChannelClientEntry chl;
3180   SilcBuffer reply, chidp, clidp, keyp = NULL, user_list, mode_list;
3181   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3182   char check[512], check2[512];
3183   bool founder = FALSE;
3184   bool resolve;
3185   unsigned char *fkey = NULL;
3186   SilcUInt32 fkey_len = 0;
3187
3188   SILC_LOG_DEBUG(("Joining client to channel"));
3189
3190   if (!channel)
3191     return;
3192
3193   /* Get the client entry */
3194   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3195     client = (SilcClientEntry)sock->user_data;
3196   } else {
3197     client = silc_server_get_client_resolve(server, client_id, FALSE, 
3198                                             &resolve);
3199     if (!client) {
3200       if (cmd->pending)
3201         goto out;
3202
3203       if (!resolve) {
3204         silc_server_command_send_status_reply(
3205                                          cmd, SILC_COMMAND_JOIN,
3206                                          SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
3207         goto out;
3208       }
3209
3210       /* The client info is being resolved. Reprocess this packet after
3211          receiving the reply to the query. */
3212       silc_server_command_pending(server, SILC_COMMAND_WHOIS, 
3213                                   server->cmd_ident,
3214                                   silc_server_command_join, 
3215                                   silc_server_command_dup(cmd));
3216       cmd->pending = TRUE;
3217       goto out;
3218     }
3219
3220     cmd->pending = FALSE;
3221   }
3222
3223   /*
3224    * Check founder auth payload if provided.  If client can gain founder
3225    * privileges it can override various conditions on joining the channel,
3226    * and can have directly the founder mode set on the channel.
3227    */
3228   if (auth && auth_len && channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
3229     SilcIDListData idata = (SilcIDListData)client;
3230     SilcChannelClientEntry chl2;
3231     SilcHashTableList htl;
3232
3233     if (channel->founder_key && idata->public_key &&
3234         silc_pkcs_public_key_compare(channel->founder_key, 
3235                                      idata->public_key)) {
3236       /* Check whether the client is to become founder */
3237       if (silc_auth_verify_data(auth, auth_len, SILC_AUTH_PUBLIC_KEY,
3238                                 channel->founder_key, 0, server->sha1hash,
3239                                 client->id, SILC_ID_CLIENT)) {
3240
3241         /* There cannot be anyone else as founder on the channel now.  This
3242            client is definitely the founder due to this authentication */
3243         silc_hash_table_list(channel->user_list, &htl);
3244         while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
3245           if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
3246             chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
3247             silc_server_force_cumode_change(server, NULL, channel, chl2,
3248                                             chl2->mode);
3249             break;
3250           }
3251         silc_hash_table_list_reset(&htl);
3252
3253         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3254         founder = TRUE;
3255       }
3256     }
3257   }
3258
3259   /*
3260    * Check channel modes
3261    */
3262
3263   if (!umode) {
3264     memset(check, 0, sizeof(check));
3265     memset(check2, 0, sizeof(check2));
3266     strncat(check, client->nickname, strlen(client->nickname));
3267     strncat(check, "!", 1);
3268     strncat(check, client->username, strlen(client->username));
3269     if (!strchr(client->username, '@')) {
3270       strncat(check, "@", 1);
3271       strncat(check, cmd->sock->hostname, strlen(cmd->sock->hostname));
3272     }
3273
3274     strncat(check2, client->nickname, strlen(client->nickname));
3275     if (!strchr(client->nickname, '@')) {
3276       strncat(check2, "@", 1);
3277       strncat(check2, server->server_name, strlen(server->server_name));
3278     }
3279     strncat(check2, "!", 1);
3280     strncat(check2, client->username, strlen(client->username));
3281     if (!strchr(client->username, '@')) {
3282       strncat(check2, "@", 1);
3283       strncat(check2, cmd->sock->hostname, strlen(cmd->sock->hostname));
3284     }
3285     
3286     /* Check invite list if channel is invite-only channel */
3287     if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
3288       if (!channel->invite_list ||
3289           (!silc_string_match(channel->invite_list, check) &&
3290            !silc_string_match(channel->invite_list, check2))) {
3291         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3292                                               SILC_STATUS_ERR_NOT_INVITED, 0);
3293         goto out;
3294       }
3295     }
3296
3297     /* Check ban list if it exists. If the client's nickname, server,
3298        username and/or hostname is in the ban list the access to the
3299        channel is denied. */
3300     if (channel->ban_list) {
3301       if (silc_string_match(channel->ban_list, check) ||
3302           silc_string_match(channel->ban_list, check2)) {
3303         silc_server_command_send_status_reply(
3304                                       cmd, SILC_COMMAND_JOIN,
3305                                       SILC_STATUS_ERR_BANNED_FROM_CHANNEL, 0);
3306         goto out;
3307       }
3308     }
3309     
3310     /* Check user count limit if set. */
3311     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
3312       if (silc_hash_table_count(channel->user_list) + 1 > 
3313           channel->user_limit) {
3314         silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3315                                               SILC_STATUS_ERR_CHANNEL_IS_FULL,
3316                                               0);
3317         goto out;
3318       }
3319     }
3320   }
3321
3322   /* Check the channel passphrase if set. */
3323   if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3324     /* Get passphrase */
3325     tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
3326     if (tmp)
3327       passphrase = silc_memdup(tmp, tmp_len);
3328   
3329     if (!passphrase || !channel->passphrase ||
3330         memcmp(passphrase, channel->passphrase, strlen(channel->passphrase))) {
3331       silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3332                                             SILC_STATUS_ERR_BAD_PASSWORD, 0);
3333       goto out;
3334     }
3335   }
3336
3337   /*
3338    * Client is allowed to join to the channel. Make it happen.
3339    */
3340
3341   /* Check whether the client already is on the channel */
3342   if (silc_server_client_on_channel(client, channel, NULL)) {
3343     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3344                                           SILC_STATUS_ERR_USER_ON_CHANNEL, 0);
3345     goto out;
3346   }
3347
3348   /* Generate new channel key as protocol dictates */
3349   if (create_key) {
3350     if (!silc_server_create_channel_key(server, channel, 0))
3351       goto out;
3352
3353     /* Send the channel key. This is broadcasted to the channel but is not
3354        sent to the client who is joining to the channel. */
3355     if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY))
3356       silc_server_send_channel_key(server, NULL, channel, 
3357                                    server->server_type == SILC_ROUTER ? 
3358                                    FALSE : !server->standalone);
3359   }
3360
3361   /* Join the client to the channel by adding it to channel's user list.
3362      Add also the channel to client entry's channels list for fast cross-
3363      referencing. */
3364   chl = silc_calloc(1, sizeof(*chl));
3365   chl->mode = umode;
3366   chl->client = client;
3367   chl->channel = channel;
3368   silc_hash_table_add(channel->user_list, client, chl);
3369   silc_hash_table_add(client->channels, channel, chl);
3370   channel->user_count++;
3371   channel->disabled = FALSE;
3372
3373   /* Get users on the channel */
3374   silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
3375                                    &user_count);
3376
3377   /* Encode Client ID Payload of the original client who wants to join */
3378   clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
3379
3380   /* Encode command reply packet */
3381   chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
3382   SILC_PUT32_MSB(channel->mode, mode);
3383   SILC_PUT32_MSB(created, tmp2);
3384   SILC_PUT32_MSB(user_count, tmp3);
3385
3386   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
3387     tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
3388     keyp = silc_channel_key_payload_encode(silc_id_get_len(channel->id,
3389                                                            SILC_ID_CHANNEL), 
3390                                            tmp,
3391                                            strlen(channel->channel_key->
3392                                                   cipher->name),
3393                                            channel->channel_key->cipher->name,
3394                                            channel->key_len / 8, channel->key);
3395     silc_free(tmp);
3396   }
3397
3398   if (channel->founder_key)
3399     fkey = silc_pkcs_public_key_encode(channel->founder_key, &fkey_len);
3400
3401   reply = 
3402     silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
3403                                          SILC_STATUS_OK, 0, ident, 14,
3404                                          2, channel->channel_name,
3405                                          strlen(channel->channel_name),
3406                                          3, chidp->data, chidp->len,
3407                                          4, clidp->data, clidp->len,
3408                                          5, mode, 4,
3409                                          6, tmp2, 4,
3410                                          7, keyp ? keyp->data : NULL, 
3411                                          keyp ? keyp->len : 0,
3412                                          8, channel->ban_list, 
3413                                          channel->ban_list ?
3414                                          strlen(channel->ban_list) : 0,
3415                                          9, channel->invite_list,
3416                                          channel->invite_list ?
3417                                          strlen(channel->invite_list) : 0,
3418                                          10, channel->topic,
3419                                          channel->topic ?
3420                                          strlen(channel->topic) : 0,
3421                                          11, silc_hmac_get_name(channel->hmac),
3422                                          strlen(silc_hmac_get_name(channel->
3423                                                                    hmac)),
3424                                          12, tmp3, 4,
3425                                          13, user_list->data, user_list->len,
3426                                          14, mode_list->data, 
3427                                          mode_list->len,
3428                                          15, fkey, fkey_len);
3429
3430   /* Send command reply */
3431   silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0, 
3432                           reply->data, reply->len, FALSE);
3433
3434   /* Send JOIN notify to locally connected clients on the channel. If
3435      we are normal server then router will send or have sent JOIN notify
3436      already. However since we've added the client already to our channel
3437      we'll ignore it (in packet_receive.c) so we must send it here. If
3438      we are router then this will send it to local clients and local
3439      servers. */
3440   SILC_LOG_DEBUG(("Send JOIN notify to channel"));
3441   silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3442                                      SILC_NOTIFY_TYPE_JOIN, 2,
3443                                      clidp->data, clidp->len,
3444                                      chidp->data, chidp->len);
3445
3446   /* Update statistics */
3447   server->stat.my_chanclients++;
3448   if (server->server_type == SILC_ROUTER) {
3449     server->stat.cell_chanclients++;
3450     server->stat.chanclients++;
3451   }
3452
3453   if (!cmd->pending) {
3454     /* Send JOIN notify packet to our primary router */
3455     silc_server_send_notify_join(server, SILC_PRIMARY_ROUTE(server),
3456                                  SILC_BROADCAST(server), channel, client->id);
3457
3458     if (keyp)
3459       /* Distribute the channel key to all backup routers. */
3460       silc_server_backup_send(server, NULL, SILC_PACKET_CHANNEL_KEY, 0,
3461                               keyp->data, keyp->len, FALSE, TRUE);
3462
3463     /* If client became founder by providing correct founder auth data
3464        notify the mode change to the channel. */
3465     if (founder) {
3466       SILC_PUT32_MSB(chl->mode, mode);
3467       SILC_LOG_DEBUG(("Send CUMODE_CHANGE notify to channel"));
3468       silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
3469                                          SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
3470                                          clidp->data, clidp->len,
3471                                          mode, 4, clidp->data, clidp->len,
3472                                          fkey, fkey_len);
3473     }
3474   }
3475
3476   /* Set CUMODE notify type to network */
3477   if (founder)
3478     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
3479                                    SILC_BROADCAST(server), channel,
3480                                    chl->mode, client->id, SILC_ID_CLIENT,
3481                                    client->id, channel->founder_key);
3482
3483   silc_buffer_free(reply);
3484   silc_buffer_free(clidp);
3485   silc_buffer_free(chidp);
3486   silc_buffer_free(keyp);
3487   silc_buffer_free(user_list);
3488   silc_buffer_free(mode_list);
3489   silc_free(fkey);
3490
3491  out:
3492   silc_free(passphrase);
3493 }
3494
3495 /* Server side of command JOIN. Joins client into requested channel. If 
3496    the channel does not exist it will be created. */
3497
3498 SILC_SERVER_CMD_FUNC(join)
3499 {
3500   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3501   SilcServer server = cmd->server;
3502   unsigned char *auth;
3503   SilcUInt32 tmp_len, auth_len;
3504   char *tmp, *channel_name = NULL, *cipher, *hmac;
3505   SilcChannelEntry channel;
3506   SilcUInt32 umode = 0;
3507   bool created = FALSE, create_key = TRUE;
3508   SilcClientID *client_id;
3509
3510   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_JOIN, cmd, 2, 6);
3511
3512   /* Get channel name */
3513   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3514   if (!tmp) {
3515     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3516                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3517                                           0);
3518     goto out;
3519   }
3520   channel_name = tmp;
3521
3522   if (tmp_len > 256)
3523     channel_name[255] = '\0';
3524
3525   if (silc_server_name_bad_chars(channel_name, tmp_len) == TRUE) {
3526     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3527                                           SILC_STATUS_ERR_BAD_CHANNEL, 0);
3528     goto out;
3529   }
3530
3531   /* Get Client ID of the client who is joining to the channel */
3532   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3533   if (!tmp) {
3534     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3535                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3536                                           0);
3537     goto out;
3538   }
3539   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
3540   if (!client_id) {
3541     silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
3542                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
3543                                           0);
3544     goto out;
3545   }
3546
3547   /* Get cipher, hmac name and auth payload */
3548   cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
3549   hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
3550   auth = silc_argument_get_arg_type(cmd->args, 6, &auth_len);
3551
3552   /* See if the channel exists */
3553   channel = silc_idlist_find_channel_by_name(server->local_list, 
3554                                              channel_name, NULL);
3555
3556   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
3557     SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
3558     silc_free(client_id);
3559     client_id = silc_id_dup(entry->id, SILC_ID_CLIENT);
3560
3561     if (!channel || 
3562         (channel->disabled && server->server_type != SILC_ROUTER)) {
3563       /* Channel not found */
3564
3565       /* If we are standalone server we don't have a router, we just create 
3566          the channel by ourselves. */
3567       if (server->standalone) {
3568         channel = silc_server_create_new_channel(server, server->id, cipher, 
3569                                                  hmac, channel_name, TRUE);
3570         if (!channel) {
3571           silc_server_command_send_status_reply(
3572                                          cmd, SILC_COMMAND_JOIN,
3573                                          SILC_STATUS_ERR_UNKNOWN_ALGORITHM,
3574                                          0);
3575           silc_free(client_id);
3576           goto out;
3577         }
3578         
3579         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3580         created = TRUE;
3581         create_key = FALSE;
3582         
3583       } else {
3584
3585         /* The channel does not exist on our server. If we are normal server 
3586            we will send JOIN command to our router which will handle the
3587            joining procedure (either creates the channel if it doesn't exist 
3588            or joins the client to it). */
3589         if (server->server_type != SILC_ROUTER) {
3590           SilcBuffer tmpbuf;
3591           SilcUInt16 old_ident;
3592
3593           /* If this is pending command callback then we've resolved
3594              it and it didn't work, return since we've notified the
3595              client already in the command reply callback. */
3596           if (cmd->pending) {
3597             silc_free(client_id);
3598             goto out;
3599           }
3600           
3601           old_ident = silc_command_get_ident(cmd->payload);
3602           silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3603           tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3604           
3605           /* Send JOIN command to our router */
3606           silc_server_packet_send(server, (SilcSocketConnection)
3607                                   SILC_PRIMARY_ROUTE(server),
3608                                   SILC_PACKET_COMMAND, cmd->packet->flags,
3609                                   tmpbuf->data, tmpbuf->len, TRUE);
3610           
3611           /* Reprocess this packet after received reply from router */
3612           silc_server_command_pending(server, SILC_COMMAND_JOIN, 
3613                                       silc_command_get_ident(cmd->payload),
3614                                       silc_server_command_join,
3615                                       silc_server_command_dup(cmd));
3616           cmd->pending = TRUE;
3617           silc_command_set_ident(cmd->payload, old_ident);
3618           silc_buffer_free(tmpbuf);
3619           silc_free(client_id);
3620           goto out;
3621         }
3622         
3623         /* We are router and the channel does not seem exist so we will check
3624            our global list as well for the channel. */
3625         channel = silc_idlist_find_channel_by_name(server->global_list, 
3626                                                    channel_name, NULL);
3627         if (!channel) {
3628           /* Channel really does not exist, create it */
3629           channel = silc_server_create_new_channel(server, server->id, cipher, 
3630                                                    hmac, channel_name, TRUE);
3631           if (!channel) {
3632             silc_server_command_send_status_reply(
3633                                        cmd, SILC_COMMAND_JOIN,
3634                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3635             silc_free(client_id);
3636             goto out;
3637           }
3638
3639           umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3640           created = TRUE;
3641           create_key = FALSE;
3642         }
3643       }
3644     }
3645   } else {
3646     if (!channel) {
3647       /* Channel not found */
3648
3649       /* If the command came from router and we are normal server then
3650          something went wrong with the joining as the channel was not found.
3651          We can't do anything else but ignore this. */
3652       if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
3653           server->server_type != SILC_ROUTER) {
3654         silc_free(client_id);
3655         goto out;
3656       }
3657       
3658       /* We are router and the channel does not seem exist so we will check
3659          our global list as well for the channel. */
3660       channel = silc_idlist_find_channel_by_name(server->global_list, 
3661                                                  channel_name, NULL);
3662       if (!channel) {
3663         /* Channel really does not exist, create it */
3664         channel = silc_server_create_new_channel(server, server->id, cipher, 
3665                                                  hmac, channel_name, TRUE);
3666         if (!channel) {
3667           silc_server_command_send_status_reply(
3668                                        cmd, SILC_COMMAND_JOIN,
3669                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
3670           silc_free(client_id);
3671           goto out;
3672         }
3673
3674         umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3675         created = TRUE;
3676         create_key = FALSE;
3677       }
3678     }
3679   }
3680
3681   /* Check whether the channel was created by our router */
3682   if (cmd->pending && context2) {
3683     SilcServerCommandReplyContext reply = context2;
3684
3685     if (silc_command_get(reply->payload) == SILC_COMMAND_JOIN) {
3686       tmp = silc_argument_get_arg_type(reply->args, 6, NULL);
3687       SILC_GET32_MSB(created, tmp);
3688       if (silc_argument_get_arg_type(reply->args, 7, NULL))
3689         create_key = FALSE;     /* Router returned the key already */
3690
3691       if (silc_command_get_status(reply->payload, NULL, NULL) &&
3692           channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
3693         /* Save channel passphrase, if user provided it successfully */
3694         unsigned char *pa;
3695         SilcUInt32 pa_len;
3696         pa = silc_argument_get_arg_type(cmd->args, 3, &pa_len);
3697         if (pa) {
3698           silc_free(channel->passphrase);
3699           channel->passphrase = silc_memdup(pa, pa_len);
3700         }
3701       }
3702     }
3703
3704     if (silc_command_get(reply->payload) == SILC_COMMAND_WHOIS &&
3705         !channel->disabled && !silc_hash_table_count(channel->user_list))
3706       created = TRUE;
3707   }
3708
3709   /* If the channel does not have global users and is also empty the client
3710      will be the channel founder and operator. */
3711   if (!channel->disabled &&
3712       !channel->global_users && !silc_hash_table_count(channel->user_list))
3713     umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
3714
3715   /* Join to the channel */
3716   silc_server_command_join_channel(server, cmd, channel, client_id,
3717                                    created, create_key, umode,
3718                                    auth, auth_len);
3719
3720   silc_free(client_id);
3721
3722  out:
3723   silc_server_command_free(cmd);
3724 }
3725
3726 /* Server side of command MOTD. Sends server's current "message of the
3727    day" to the client. */
3728
3729 SILC_SERVER_CMD_FUNC(motd)
3730 {
3731   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3732   SilcServer server = cmd->server;
3733   SilcBuffer packet, idp;
3734   char *motd, *dest_server;
3735   SilcUInt32 motd_len;
3736   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3737   
3738   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_MOTD, cmd, 1, 1);
3739
3740   /* Get server name */
3741   dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
3742   if (!dest_server) {
3743     silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
3744                                           SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3745     goto out;
3746   }
3747
3748   if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
3749     /* Send our MOTD */
3750
3751     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3752
3753     if (server->config && server->config->server_info &&
3754         server->config->server_info->motd_file) {
3755       /* Send motd */
3756       motd = silc_file_readfile(server->config->server_info->motd_file,
3757                                 &motd_len);
3758       if (!motd)
3759         goto out;
3760       
3761       motd[motd_len] = 0;
3762       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3763                                                     SILC_STATUS_OK, 0, 
3764                                                     ident, 2,
3765                                                     2, idp, idp->len,
3766                                                     3, motd, motd_len);
3767     } else {
3768       /* No motd */
3769       packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3770                                                     SILC_STATUS_OK, 0, 
3771                                                     ident, 1,
3772                                                     2, idp, idp->len);
3773     }
3774
3775     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3776                             packet->data, packet->len, FALSE);
3777     silc_buffer_free(packet);
3778     silc_buffer_free(idp);
3779   } else {
3780     SilcServerEntry entry;
3781
3782     /* Check whether we have this server cached */
3783     entry = silc_idlist_find_server_by_name(server->global_list,
3784                                             dest_server, TRUE, NULL);
3785     if (!entry) {
3786       entry = silc_idlist_find_server_by_name(server->local_list,
3787                                               dest_server, TRUE, NULL);
3788     }
3789
3790     if (server->server_type != SILC_SERVER && !cmd->pending && 
3791         entry && !entry->motd) {
3792       /* Send to the server */
3793       SilcBuffer tmpbuf;
3794       SilcUInt16 old_ident;
3795
3796       old_ident = silc_command_get_ident(cmd->payload);
3797       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3798       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3799
3800       silc_server_packet_send(server, entry->connection,
3801                               SILC_PACKET_COMMAND, cmd->packet->flags,
3802                               tmpbuf->data, tmpbuf->len, TRUE);
3803
3804       /* Reprocess this packet after received reply from router */
3805       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3806                                   silc_command_get_ident(cmd->payload),
3807                                   silc_server_command_motd,
3808                                   silc_server_command_dup(cmd));
3809       cmd->pending = TRUE;
3810       silc_command_set_ident(cmd->payload, old_ident);
3811       silc_buffer_free(tmpbuf);
3812       goto out;
3813     }
3814
3815     if (!entry && !cmd->pending && !server->standalone) {
3816       /* Send to the primary router */
3817       SilcBuffer tmpbuf;
3818       SilcUInt16 old_ident;
3819
3820       old_ident = silc_command_get_ident(cmd->payload);
3821       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
3822       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3823
3824       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
3825                               SILC_PACKET_COMMAND, cmd->packet->flags,
3826                               tmpbuf->data, tmpbuf->len, TRUE);
3827
3828       /* Reprocess this packet after received reply from router */
3829       silc_server_command_pending(server, SILC_COMMAND_MOTD, 
3830                                   silc_command_get_ident(cmd->payload),
3831                                   silc_server_command_motd,
3832                                   silc_server_command_dup(cmd));
3833       cmd->pending = TRUE;
3834       silc_command_set_ident(cmd->payload, old_ident);
3835       silc_buffer_free(tmpbuf);
3836       goto out;
3837     }
3838
3839     if (!entry) {
3840       silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
3841                                             SILC_STATUS_ERR_NO_SUCH_SERVER, 0);
3842       goto out;
3843     }
3844
3845     idp = silc_id_payload_encode(server->id_entry->id, SILC_ID_SERVER);
3846     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_MOTD,
3847                                                   SILC_STATUS_OK, 0, ident, 2,
3848                                                   2, idp, idp->len,
3849                                                   3, entry->motd,
3850                                                   entry->motd ? 
3851                                                   strlen(entry->motd) : 0);
3852     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3853                             packet->data, packet->len, FALSE);
3854     silc_buffer_free(packet);
3855     silc_buffer_free(idp);
3856   }
3857
3858  out:
3859   silc_server_command_free(cmd);
3860 }
3861
3862 /* Server side of command UMODE. Client can use this command to set/unset
3863    user mode. Client actually cannot set itself to be as server/router
3864    operator so this can be used only to unset the modes. */
3865
3866 SILC_SERVER_CMD_FUNC(umode)
3867 {
3868   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3869   SilcServer server = cmd->server;
3870   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3871   SilcBuffer packet;
3872   unsigned char *tmp_mask, m[4];
3873   SilcUInt32 mask = 0;
3874   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3875   bool set_mask = FALSE;
3876
3877   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3878     goto out;
3879
3880   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_UMODE, cmd, 1, 2);
3881
3882   /* Get the client's mode mask */
3883   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
3884   if (tmp_mask) {
3885     SILC_GET32_MSB(mask, tmp_mask);
3886     set_mask = TRUE;
3887   }
3888
3889   if (set_mask) {
3890     /* Check that mode changing is allowed. */
3891     if (!silc_server_check_umode_rights(server, client, mask)) {
3892       silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3893                                             SILC_STATUS_ERR_PERM_DENIED, 0);
3894       goto out;
3895     }
3896
3897     /* Anonymous mode cannot be set by client */
3898     if (mask & SILC_UMODE_ANONYMOUS) {
3899       if (!(client->mode & SILC_UMODE_ANONYMOUS)) {
3900         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3901                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3902         goto out;
3903       }
3904     } else {
3905       if (client->mode & SILC_UMODE_ANONYMOUS) {
3906         silc_server_command_send_status_reply(cmd, SILC_COMMAND_UMODE,
3907                                               SILC_STATUS_ERR_PERM_DENIED, 0);
3908         goto out;
3909       }
3910     }
3911
3912     /* Update statistics */
3913     if (mask & SILC_UMODE_GONE) {
3914       if (!(client->mode & SILC_UMODE_GONE))
3915         server->stat.my_aways++;
3916     } else {
3917       if (client->mode & SILC_UMODE_GONE)
3918         server->stat.my_aways--;
3919     }
3920
3921     /* Change the mode */
3922     client->mode = mask;
3923
3924     /* Send UMODE change to primary router */
3925     silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
3926                                   SILC_BROADCAST(server), client->id,
3927                                   client->mode);
3928
3929     /* Check if anyone is watching this nickname */
3930     if (server->server_type == SILC_ROUTER)
3931       silc_server_check_watcher_list(server, client, NULL,
3932                                      SILC_NOTIFY_TYPE_UMODE_CHANGE);
3933   }
3934
3935   /* Send command reply to sender */
3936   SILC_PUT32_MSB(client->mode, m);
3937   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_UMODE,
3938                                                 SILC_STATUS_OK, 0, ident, 1,
3939                                                 2, m, sizeof(m));
3940   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
3941                           packet->data, packet->len, FALSE);
3942   silc_buffer_free(packet);
3943
3944  out:
3945   silc_server_command_free(cmd);
3946 }
3947
3948 /* Server side command of CMODE. Changes channel mode */
3949
3950 SILC_SERVER_CMD_FUNC(cmode)
3951 {
3952   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3953   SilcServer server = cmd->server;
3954   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3955   SilcIDListData idata = (SilcIDListData)client;
3956   SilcChannelID *channel_id = NULL;
3957   SilcChannelEntry channel;
3958   SilcChannelClientEntry chl;
3959   SilcBuffer packet, cidp;
3960   unsigned char *tmp, *tmp_id, *tmp_mask;
3961   char *cipher = NULL, *hmac = NULL, *passphrase = NULL;
3962   SilcUInt32 mode_mask = 0, old_mask = 0, tmp_len, tmp_len2;
3963   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
3964   bool set_mask = FALSE;
3965   SilcPublicKey founder_key = NULL;
3966   unsigned char *fkey = NULL;
3967   SilcUInt32 fkey_len = 0;
3968
3969   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CMODE, cmd, 1, 7);
3970
3971   /* Get Channel ID */
3972   tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
3973   if (!tmp_id) {
3974     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3975                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3976     silc_server_command_free(cmd);
3977     return;
3978   }
3979   channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2, NULL);
3980   if (!channel_id) {
3981     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3982                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
3983     silc_server_command_free(cmd);
3984     return;
3985   }
3986
3987   /* Get channel entry */
3988   channel = silc_idlist_find_channel_by_id(server->local_list, 
3989                                            channel_id, NULL);
3990   if (!channel) {
3991     channel = silc_idlist_find_channel_by_id(server->global_list, 
3992                                              channel_id, NULL);
3993     if (!channel) {
3994       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
3995                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
3996                                             0);
3997       silc_free(channel_id);
3998       silc_server_command_free(cmd);
3999       return;
4000     }
4001   }
4002   old_mask = channel->mode;
4003
4004   /* Get the channel mode mask */
4005   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4006   if (tmp_mask) {
4007     SILC_GET32_MSB(mode_mask, tmp_mask);
4008     set_mask = TRUE;
4009   }
4010
4011   /* Check whether this client is on the channel */
4012   if (!silc_server_client_on_channel(client, channel, &chl)) {
4013     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4014                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4015     goto out;
4016   }
4017
4018   /* Check that client has rights to change any requested channel modes */
4019   if (set_mask && !silc_server_check_cmode_rights(server, channel, chl, 
4020                                                   mode_mask)) {
4021     SILC_LOG_DEBUG(("Client does not have rights to change mode"));
4022     silc_server_command_send_status_reply(
4023                              cmd, SILC_COMMAND_CMODE,
4024                              (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) ? 
4025                               SILC_STATUS_ERR_NO_CHANNEL_PRIV :
4026                               SILC_STATUS_ERR_NO_CHANNEL_FOPRIV), 0);
4027     goto out;
4028   }
4029
4030   /* If mode mask was not sent as argument then merely return the current
4031      mode mask to the sender. */
4032   if (!set_mask) {
4033     unsigned char m[4];
4034     SILC_PUT32_MSB(channel->mode, m);
4035     packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4036                                                   SILC_STATUS_OK, 0, ident, 2,
4037                                                   2, tmp_id, tmp_len2,
4038                                                   3, m, sizeof(m));
4039     silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
4040                             packet->data, packet->len, FALSE);
4041     silc_buffer_free(packet);
4042     goto out;
4043   }
4044
4045   /*
4046    * Check the modes. Modes that requires nothing special operation are
4047    * not checked here.
4048    */
4049
4050   if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
4051     /* Channel uses private keys to protect traffic. Client(s) has set the
4052        key locally they want to use, server does not know that key. */
4053     /* Nothing interesting to do here */
4054   } else {
4055     if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
4056       /* The mode is removed and we need to generate and distribute
4057          new channel key. Clients are not using private channel keys
4058          anymore after this. */
4059       
4060       /* Re-generate channel key */
4061       if (!silc_server_create_channel_key(server, channel, 0))
4062         goto out;
4063         
4064       /* Send the channel key. This sends it to our local clients and if
4065          we are normal server to our router as well. */
4066       silc_server_send_channel_key(server, NULL, channel, 
4067                                    server->server_type == SILC_ROUTER ? 
4068                                    FALSE : !server->standalone);
4069         
4070       cipher = channel->channel_key->cipher->name;
4071       hmac = (char *)silc_hmac_get_name(channel->hmac);
4072     }
4073   }
4074
4075   if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
4076     /* User limit is set on channel */
4077     SilcUInt32 user_limit;
4078       
4079     /* Get user limit */
4080     tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
4081     if (!tmp) {
4082       if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
4083         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4084                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4085         goto out;
4086       }
4087     } else {
4088       SILC_GET32_MSB(user_limit, tmp);
4089       channel->user_limit = user_limit;
4090     }
4091   } else {
4092     if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
4093       /* User limit mode is unset. Remove user limit */
4094       channel->user_limit = 0;
4095   }
4096
4097   if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
4098     if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
4099       /* Passphrase has been set to channel */
4100       
4101       /* Get the passphrase */
4102       tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
4103       if (!tmp) {
4104         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4105                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4106         goto out;
4107       }
4108
4109       /* Save the passphrase */
4110       passphrase = channel->passphrase = silc_memdup(tmp, strlen(tmp));
4111     }
4112   } else {
4113     if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
4114       /* Passphrase mode is unset. remove the passphrase */
4115       silc_free(channel->passphrase);
4116       channel->passphrase = NULL;
4117     }
4118   }
4119
4120   if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
4121     if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
4122       /* Cipher to use protect the traffic */
4123       SilcCipher newkey, oldkey;
4124
4125       /* Get cipher */
4126       cipher = silc_argument_get_arg_type(cmd->args, 5, NULL);
4127       if (!cipher) {
4128         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4129                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4130         goto out;
4131       }
4132
4133       /* Delete old cipher and allocate the new one */
4134       if (!silc_cipher_alloc(cipher, &newkey)) {
4135         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4136                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4137         goto out;
4138       }
4139
4140       oldkey = channel->channel_key;
4141       channel->channel_key = newkey;
4142
4143       /* Re-generate channel key */
4144       if (!silc_server_create_channel_key(server, channel, 0)) {
4145         /* We don't have new key, revert to old one */
4146         channel->channel_key = oldkey;
4147         goto out;
4148       }
4149
4150       /* Remove old channel key for good */
4151       silc_cipher_free(oldkey);
4152
4153       /* Send the channel key. This sends it to our local clients and if
4154          we are normal server to our router as well. */
4155       silc_server_send_channel_key(server, NULL, channel, 
4156                                    server->server_type == SILC_ROUTER ? 
4157                                    FALSE : !server->standalone);
4158     }
4159   } else {
4160     if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
4161       /* Cipher mode is unset. Remove the cipher and revert back to 
4162          default cipher */
4163       SilcCipher newkey, oldkey;
4164       cipher = channel->cipher;
4165
4166       /* Delete old cipher and allocate default one */
4167       if (!silc_cipher_alloc(cipher ? cipher : SILC_DEFAULT_CIPHER, &newkey)) {
4168         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4169                                    SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4170         goto out;
4171       }
4172
4173       oldkey = channel->channel_key;
4174       channel->channel_key = newkey;
4175
4176       /* Re-generate channel key */
4177       if (!silc_server_create_channel_key(server, channel, 0)) {
4178         /* We don't have new key, revert to old one */
4179         channel->channel_key = oldkey;
4180         goto out;
4181       }
4182       
4183       /* Remove old channel key for good */
4184       silc_cipher_free(oldkey);
4185
4186       /* Send the channel key. This sends it to our local clients and if
4187          we are normal server to our router as well. */
4188       silc_server_send_channel_key(server, NULL, channel, 
4189                                    server->server_type == SILC_ROUTER ? 
4190                                    FALSE : !server->standalone);
4191     }
4192   }
4193
4194   if (mode_mask & SILC_CHANNEL_MODE_HMAC) {
4195     if (!(channel->mode & SILC_CHANNEL_MODE_HMAC)) {
4196       /* HMAC to use protect the traffic */
4197       unsigned char hash[32];
4198       SilcHmac newhmac;
4199
4200       /* Get hmac */
4201       hmac = silc_argument_get_arg_type(cmd->args, 6, NULL);
4202       if (!hmac) {
4203         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4204                                    SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4205         goto out;
4206       }
4207
4208       /* Delete old hmac and allocate the new one */
4209       if (!silc_hmac_alloc(hmac, NULL, &newhmac)) {
4210         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4211                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4212         goto out;
4213       }
4214
4215       silc_hmac_free(channel->hmac);
4216       channel->hmac = newhmac;
4217
4218       /* Set the HMAC key out of current channel key. The client must do
4219          this locally. */
4220       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4221                      channel->key_len / 8, hash);
4222       silc_hmac_set_key(channel->hmac, hash, 
4223                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4224       memset(hash, 0, sizeof(hash));
4225     }
4226   } else {
4227     if (channel->mode & SILC_CHANNEL_MODE_HMAC) {
4228       /* Hmac mode is unset. Remove the hmac and revert back to 
4229          default hmac */
4230       SilcHmac newhmac;
4231       unsigned char hash[32];
4232       hmac = channel->hmac_name;
4233
4234       /* Delete old hmac and allocate default one */
4235       silc_hmac_free(channel->hmac);
4236       if (!silc_hmac_alloc(hmac ? hmac : SILC_DEFAULT_HMAC, NULL, &newhmac)) {
4237         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4238                                        SILC_STATUS_ERR_UNKNOWN_ALGORITHM, 0);
4239         goto out;
4240       }
4241
4242       silc_hmac_free(channel->hmac);
4243       channel->hmac = newhmac;
4244
4245       /* Set the HMAC key out of current channel key. The client must do
4246          this locally. */
4247       silc_hash_make(silc_hmac_get_hash(channel->hmac), channel->key, 
4248                      channel->key_len / 8, 
4249                      hash);
4250       silc_hmac_set_key(channel->hmac, hash, 
4251                         silc_hash_len(silc_hmac_get_hash(channel->hmac)));
4252       memset(hash, 0, sizeof(hash));
4253     }
4254   }
4255
4256   if (mode_mask & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4257     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4258       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH)) {
4259         /* Set the founder authentication */
4260         tmp = silc_argument_get_arg_type(cmd->args, 7, &tmp_len);
4261         if (!tmp) {
4262           silc_server_command_send_status_reply(
4263                                      cmd, SILC_COMMAND_CMODE,
4264                                      SILC_STATUS_ERR_NOT_ENOUGH_PARAMS, 0);
4265           goto out;
4266         }
4267
4268         /* Verify the payload before setting the mode */
4269         if (!silc_auth_verify_data(tmp, tmp_len, SILC_AUTH_PUBLIC_KEY, 
4270                                    idata->public_key, 0, server->sha1hash,
4271                                    client->id, SILC_ID_CLIENT)) {
4272           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4273                                                 SILC_STATUS_ERR_AUTH_FAILED,
4274                                                 0);
4275           goto out;
4276         }
4277
4278         /* Save the public key */
4279         channel->founder_key = silc_pkcs_public_key_copy(idata->public_key);
4280         if (!channel->founder_key) {
4281           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4282                                                 SILC_STATUS_ERR_AUTH_FAILED,
4283                                                 0);
4284           goto out;
4285         }
4286
4287         founder_key = channel->founder_key;
4288         fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4289         if (!fkey) {
4290           silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
4291                                                 SILC_STATUS_ERR_AUTH_FAILED,
4292                                                 0);
4293           silc_pkcs_public_key_free(channel->founder_key);
4294           channel->founder_key = NULL;
4295           goto out;
4296         }
4297       }
4298     }
4299   } else {
4300     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4301       if (channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) {
4302         if (channel->founder_key)
4303           silc_pkcs_public_key_free(channel->founder_key);
4304         channel->founder_key = NULL;
4305       }
4306     }
4307   }
4308
4309   /* Finally, set the mode */
4310   old_mask = channel->mode = mode_mask;
4311
4312   /* Send CMODE_CHANGE notify. */
4313   cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4314   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4315                                      SILC_NOTIFY_TYPE_CMODE_CHANGE, 6,
4316                                      cidp->data, cidp->len, 
4317                                      tmp_mask, 4,
4318                                      cipher, cipher ? strlen(cipher) : 0,
4319                                      hmac, hmac ? strlen(hmac) : 0,
4320                                      passphrase, passphrase ? 
4321                                      strlen(passphrase) : 0,
4322                                      fkey, fkey_len);
4323
4324   /* Set CMODE notify type to network */
4325   silc_server_send_notify_cmode(server, SILC_PRIMARY_ROUTE(server),
4326                                 SILC_BROADCAST(server), channel,
4327                                 mode_mask, client->id, SILC_ID_CLIENT,
4328                                 cipher, hmac, passphrase, founder_key);
4329
4330   /* Send command reply to sender */
4331   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
4332                                                 SILC_STATUS_OK, 0, ident, 2,
4333                                                 2, tmp_id, tmp_len2,
4334                                                 3, tmp_mask, 4);
4335   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4336                           packet->data, packet->len, FALSE);
4337
4338   silc_buffer_free(packet);
4339   silc_buffer_free(cidp);
4340
4341  out:
4342   channel->mode = old_mask;
4343   silc_free(fkey);
4344   silc_free(channel_id);
4345   silc_server_command_free(cmd);
4346 }
4347
4348 /* Server side of CUMODE command. Changes client's mode on a channel. */
4349
4350 SILC_SERVER_CMD_FUNC(cumode)
4351 {
4352   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4353   SilcServer server = cmd->server;
4354   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4355   SilcIDListData idata = (SilcIDListData)client;
4356   SilcChannelID *channel_id;
4357   SilcClientID *client_id;
4358   SilcChannelEntry channel;
4359   SilcClientEntry target_client;
4360   SilcChannelClientEntry chl;
4361   SilcBuffer packet, idp;
4362   unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
4363   SilcUInt32 target_mask, sender_mask = 0, tmp_len, tmp_ch_len;
4364   int notify = FALSE;
4365   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
4366   SilcPublicKey founder_key = NULL;
4367   unsigned char *fkey = NULL;
4368   SilcUInt32 fkey_len = 0;
4369
4370   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_CUMODE, cmd, 3, 4);
4371
4372   /* Get Channel ID */
4373   tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
4374   if (!tmp_ch_id) {
4375     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4376                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4377     goto out;
4378   }
4379   channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len, NULL);
4380   if (!channel_id) {
4381     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4382                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4383     goto out;
4384   }
4385
4386   /* Get channel entry */
4387   channel = silc_idlist_find_channel_by_id(server->local_list, 
4388                                            channel_id, NULL);
4389   if (!channel) {
4390     channel = silc_idlist_find_channel_by_id(server->global_list, 
4391                                              channel_id, NULL);
4392     if (!channel) {
4393       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4394                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4395                                             0);
4396       goto out;
4397     }
4398   }
4399
4400   /* Check whether sender is on the channel */
4401   if (!silc_server_client_on_channel(client, channel, &chl)) {
4402     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4403                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4404     goto out;
4405   }
4406   sender_mask = chl->mode;
4407   
4408   /* Get the target client's channel mode mask */
4409   tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
4410   if (!tmp_mask) {
4411     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4412                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4413                                           0);
4414     goto out;
4415   }
4416   SILC_GET32_MSB(target_mask, tmp_mask);
4417
4418   /* Get target Client ID */
4419   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4420   if (!tmp_id) {
4421     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4422                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4423     goto out;
4424   }
4425   client_id = silc_id_payload_parse_id(tmp_id, tmp_len, NULL);
4426   if (!client_id) {
4427     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4428                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4429     goto out;
4430   }
4431
4432   /* Get target client's entry */
4433   target_client = silc_idlist_find_client_by_id(server->local_list, 
4434                                                 client_id, TRUE, NULL);
4435   if (!target_client) {
4436     target_client = silc_idlist_find_client_by_id(server->global_list, 
4437                                                   client_id, TRUE, NULL);
4438   }
4439
4440   if (target_client != client &&
4441       !(sender_mask & SILC_CHANNEL_UMODE_CHANFO) &&
4442       !(sender_mask & SILC_CHANNEL_UMODE_CHANOP)) {
4443     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4444                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4445     goto out;
4446   }
4447
4448   /* Check whether target client is on the channel */
4449   if (target_client != client) {
4450     if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4451       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4452                                  SILC_STATUS_ERR_USER_NOT_ON_CHANNEL, 0);
4453       goto out;
4454     }
4455   }
4456
4457   /* 
4458    * Change the mode 
4459    */
4460
4461   /* If the target client is founder, no one else can change their mode
4462      but themselves. */
4463   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && client != target_client) {
4464     silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4465                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4466                                           0);
4467     goto out;
4468   }
4469
4470   if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
4471     if (target_client != client) {
4472       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4473                                             SILC_STATUS_ERR_NOT_YOU, 0);
4474       goto out;
4475     }
4476
4477     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4478       /* The client tries to claim the founder rights. */
4479       unsigned char *tmp_auth;
4480       SilcUInt32 tmp_auth_len;
4481       SilcChannelClientEntry chl2;
4482       SilcHashTableList htl;
4483
4484       if (!(channel->mode & SILC_CHANNEL_MODE_FOUNDER_AUTH) ||
4485           !channel->founder_key || !idata->public_key ||
4486           !silc_pkcs_public_key_compare(channel->founder_key, 
4487                                         idata->public_key)) {
4488         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4489                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4490         goto out;
4491       }
4492
4493       tmp_auth = silc_argument_get_arg_type(cmd->args, 4, &tmp_auth_len);
4494       if (!tmp_auth) {
4495         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4496                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4497         goto out;
4498       }
4499
4500       /* Verify the authentication payload */
4501       if (!silc_auth_verify_data(tmp_auth, tmp_auth_len, SILC_AUTH_PUBLIC_KEY,
4502                                  channel->founder_key, 0, server->sha1hash,
4503                                  client->id, SILC_ID_CLIENT)) {
4504         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4505                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4506         goto out;
4507       }
4508
4509       notify = TRUE;
4510       founder_key = channel->founder_key;
4511       fkey = silc_pkcs_public_key_encode(founder_key, &fkey_len);
4512       if (!fkey) {
4513         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4514                                               SILC_STATUS_ERR_AUTH_FAILED, 0);
4515         goto out;
4516       }
4517
4518       /* There cannot be anyone else as founder on the channel now.  This
4519          client is definitely the founder due to this authentication */
4520       silc_hash_table_list(channel->user_list, &htl);
4521       while (silc_hash_table_get(&htl, NULL, (void *)&chl2))
4522         if (chl2->mode & SILC_CHANNEL_UMODE_CHANFO) {
4523           chl2->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4524           silc_server_force_cumode_change(server, NULL, channel, chl2,
4525                                           chl2->mode);
4526           break;
4527         }
4528       silc_hash_table_list_reset(&htl);
4529
4530       sender_mask = chl->mode |= SILC_CHANNEL_UMODE_CHANFO;
4531     }
4532   } else {
4533     if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4534       if (target_client == client) {
4535         /* Remove channel founder rights from itself */
4536         chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
4537         notify = TRUE;
4538       } else {
4539         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4540                                               SILC_STATUS_ERR_NOT_YOU, 0);
4541         goto out;
4542       }
4543     }
4544   }
4545
4546   if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
4547     /* Promote to operator */
4548     if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
4549       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) && 
4550           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4551         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4552                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4553                                               0);
4554         goto out;
4555       }
4556
4557       chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
4558       notify = TRUE;
4559     }
4560   } else {
4561     if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
4562       if (!(sender_mask & SILC_CHANNEL_UMODE_CHANOP) &&
4563           !(sender_mask & SILC_CHANNEL_UMODE_CHANFO)) {
4564         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,   
4565                                               SILC_STATUS_ERR_NO_CHANNEL_PRIV,
4566                                               0);
4567         goto out;
4568       }
4569       
4570       /* Demote to normal user */
4571       chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
4572       notify = TRUE;
4573     }
4574   }
4575
4576   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4577     if (target_client != client) {
4578       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4579                                             SILC_STATUS_ERR_NOT_YOU, 0);
4580       goto out;
4581     }
4582
4583     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES)) {
4584       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4585       notify = TRUE;
4586     }
4587   } else {
4588     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES) {
4589       if (target_client != client) {
4590         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4591                                               SILC_STATUS_ERR_NOT_YOU, 0);
4592         goto out;
4593       }
4594
4595       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES;
4596       notify = TRUE;
4597     }
4598   }
4599
4600   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4601     if (target_client != client) {
4602       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4603                                             SILC_STATUS_ERR_NOT_YOU, 0);
4604       goto out;
4605     }
4606
4607     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS)) {
4608       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4609       notify = TRUE;
4610     }
4611   } else {
4612     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS) {
4613       if (target_client != client) {
4614         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4615                                               SILC_STATUS_ERR_NOT_YOU, 0);
4616         goto out;
4617       }
4618
4619       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_USERS;
4620       notify = TRUE;
4621     }
4622   }
4623
4624   if (target_mask & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4625     if (target_client != client) {
4626       silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4627                                             SILC_STATUS_ERR_NOT_YOU, 0);
4628       goto out;
4629     }
4630
4631     if (!(chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS)) {
4632       chl->mode |= SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4633       notify = TRUE;
4634     }
4635   } else {
4636     if (chl->mode & SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS) {
4637       if (target_client != client) {
4638         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4639                                               SILC_STATUS_ERR_NOT_YOU, 0);
4640         goto out;
4641       }
4642
4643       chl->mode &= ~SILC_CHANNEL_UMODE_BLOCK_MESSAGES_ROBOTS;
4644       notify = TRUE;
4645     }
4646   }
4647
4648   if (target_mask & SILC_CHANNEL_UMODE_QUIET) {
4649     if (!(chl->mode & SILC_CHANNEL_UMODE_QUIET)) {
4650       if (client == target_client) {
4651         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4652                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4653         goto out;
4654       }
4655       chl->mode |= SILC_CHANNEL_UMODE_QUIET;
4656       notify = TRUE;
4657     }
4658   } else {
4659     if (chl->mode & SILC_CHANNEL_UMODE_QUIET) {
4660       if (client == target_client) {
4661         silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
4662                                               SILC_STATUS_ERR_PERM_DENIED, 0);
4663         goto out;
4664       }
4665       chl->mode &= ~SILC_CHANNEL_UMODE_QUIET;
4666       notify = TRUE;
4667     }
4668   }
4669
4670   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4671   tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4672
4673   /* Send notify to channel, notify only if mode was actually changed. */
4674   if (notify) {
4675     silc_server_send_notify_to_channel(server, NULL, channel, FALSE, 
4676                                        SILC_NOTIFY_TYPE_CUMODE_CHANGE, 4,
4677                                        idp->data, idp->len,
4678                                        tmp_mask, 4, 
4679                                        tmp_id, tmp_len,
4680                                        fkey, fkey_len);
4681
4682     /* Set CUMODE notify type to network */
4683     silc_server_send_notify_cumode(server, SILC_PRIMARY_ROUTE(server),
4684                                    SILC_BROADCAST(server), channel,
4685                                    target_mask, client->id, SILC_ID_CLIENT,
4686                                    target_client->id, founder_key);
4687   }
4688
4689   /* Send command reply to sender */
4690   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
4691                                                 SILC_STATUS_OK, 0, ident, 3,
4692                                                 2, tmp_mask, 4,
4693                                                 3, tmp_ch_id, tmp_ch_len,
4694                                                 4, tmp_id, tmp_len);
4695   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
4696                           packet->data, packet->len, FALSE);
4697     
4698   silc_buffer_free(packet);
4699   silc_free(channel_id);
4700   silc_free(client_id);
4701   silc_buffer_free(idp);
4702
4703  out:
4704   silc_free(fkey);
4705   silc_server_command_free(cmd);
4706 }
4707
4708 /* Server side of KICK command. Kicks client out of channel. */
4709
4710 SILC_SERVER_CMD_FUNC(kick)
4711 {
4712   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4713   SilcServer server = cmd->server;
4714   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4715   SilcClientEntry target_client;
4716   SilcChannelID *channel_id;
4717   SilcClientID *client_id;
4718   SilcChannelEntry channel;
4719   SilcChannelClientEntry chl;
4720   SilcBuffer idp;
4721   SilcUInt32 tmp_len, target_idp_len;
4722   unsigned char *tmp, *comment, *target_idp;
4723
4724   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 3);
4725
4726   /* Get Channel ID */
4727   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4728   if (!tmp) {
4729     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4730                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4731     goto out;
4732   }
4733   channel_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
4734   if (!channel_id) {
4735     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4736                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
4737     goto out;
4738   }
4739
4740   /* Get channel entry */
4741   channel = silc_idlist_find_channel_by_id(server->local_list, 
4742                                            channel_id, NULL);
4743   if (!channel) {
4744     channel = silc_idlist_find_channel_by_id(server->local_list, 
4745                                              channel_id, NULL);
4746     if (!channel) {
4747       silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4748                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
4749                                             0);
4750       goto out;
4751     }
4752   }
4753
4754   /* Check whether sender is on the channel */
4755   if (!silc_server_client_on_channel(client, channel, &chl)) {
4756     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4757                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
4758     goto out;
4759   }
4760
4761   /* Check that the kicker is channel operator or channel founder */
4762   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP) &&
4763       !(chl->mode & SILC_CHANNEL_UMODE_CHANFO)) {
4764     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4765                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
4766     goto out;
4767   }
4768   
4769   /* Get target Client ID */
4770   target_idp = silc_argument_get_arg_type(cmd->args, 2, &target_idp_len);
4771   if (!target_idp) {
4772     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4773                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4774     goto out;
4775   }
4776   client_id = silc_id_payload_parse_id(target_idp, target_idp_len, NULL);
4777   if (!client_id) {
4778     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4779                                           SILC_STATUS_ERR_NO_CLIENT_ID, 0);
4780     goto out;
4781   }
4782
4783   /* Get target client's entry */
4784   target_client = silc_idlist_find_client_by_id(server->local_list, 
4785                                                 client_id, TRUE, NULL);
4786   if (!target_client) {
4787     target_client = silc_idlist_find_client_by_id(server->global_list, 
4788                                                   client_id, TRUE, NULL);
4789   }
4790
4791   /* Check whether target client is on the channel */
4792   if (!silc_server_client_on_channel(target_client, channel, &chl)) {
4793     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4794                                           SILC_STATUS_ERR_USER_NOT_ON_CHANNEL,
4795                                           0);
4796     goto out;
4797   }
4798
4799   /* Check that the target client is not channel founder. Channel founder
4800      cannot be kicked from the channel. */
4801   if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
4802     silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
4803                                           SILC_STATUS_ERR_NO_CHANNEL_FOPRIV,
4804                                           0);
4805     goto out;
4806   }
4807   
4808   /* Get comment */
4809   tmp_len = 0;
4810   comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
4811   if (tmp_len > 128)
4812     comment = NULL;
4813
4814   /* Send command reply to sender */
4815   silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK, 
4816                                         SILC_STATUS_OK, 0);
4817
4818   /* Send KICKED notify to local clients on the channel */
4819   idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
4820   silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
4821                                      SILC_NOTIFY_TYPE_KICKED, 3,
4822                                      target_idp, target_idp_len,
4823                                      comment, comment ? strlen(comment) : 0,
4824                                      idp->data, idp->len);
4825   silc_buffer_free(idp);
4826
4827   /* Send KICKED notify to primary route */
4828   silc_server_send_notify_kicked(server, SILC_PRIMARY_ROUTE(server),
4829                                  SILC_BROADCAST(server), channel,
4830                                  target_client->id, client->id, comment);
4831
4832   /* Remove the client from the channel. If the channel does not exist
4833      after removing the client then the client kicked itself off the channel
4834      and we don't have to send anything after that. */
4835   if (!silc_server_remove_from_one_channel(server, NULL, channel, 
4836                                            target_client, FALSE))
4837     goto out;
4838
4839   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
4840     /* Re-generate channel key */
4841     if (!silc_server_create_channel_key(server, channel, 0))
4842       goto out;
4843     
4844     /* Send the channel key to the channel. The key of course is not sent
4845        to the client who was kicked off the channel. */
4846     silc_server_send_channel_key(server, target_client->connection, channel, 
4847                                  server->server_type == SILC_ROUTER ? 
4848                                  FALSE : !server->standalone);
4849   }
4850
4851  out:
4852   silc_server_command_free(cmd);
4853 }
4854
4855 /* Server side of OPER command. Client uses this comand to obtain server
4856    operator privileges to this server/router. */
4857
4858 SILC_SERVER_CMD_FUNC(oper)
4859 {
4860   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
4861   SilcServer server = cmd->server;
4862   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
4863   unsigned char *username, *auth;
4864   SilcUInt32 tmp_len;
4865   SilcServerConfigAdmin *admin;
4866   SilcIDListData idata = (SilcIDListData)client;
4867   bool result = FALSE;
4868   SilcPublicKey cached_key;
4869
4870   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_OPER, cmd, 1, 2);
4871
4872   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
4873     goto out;
4874
4875   /* Get the username */
4876   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
4877   if (!username) {
4878     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4879                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4880                                           0);
4881     goto out;
4882   }
4883
4884   /* Get the admin configuration */
4885   admin = silc_server_config_find_admin(server, cmd->sock->ip,
4886                                         username, client->nickname);
4887   if (!admin) {
4888     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
4889                                           username, client->nickname);
4890     if (!admin) {
4891       silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4892                                             SILC_STATUS_ERR_AUTH_FAILED,
4893                                             0);
4894       goto out;
4895     }
4896   }
4897
4898   /* Get the authentication payload */
4899   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
4900   if (!auth) {
4901     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4902                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
4903                                           0);
4904     goto out;
4905   }
4906
4907   /* Verify the authentication data. If both passphrase and public key
4908      is set then try both of them. */
4909   if (admin->passphrase)
4910     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
4911                                    admin->passphrase, admin->passphrase_len,
4912                                    idata->hash, client->id, SILC_ID_CLIENT);
4913   if (!result && admin->publickeys) {
4914     cached_key = silc_server_get_public_key(server, admin->publickeys);
4915     if (!cached_key)
4916       goto out;
4917     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
4918                                    cached_key, 0, idata->hash, 
4919                                    client->id, SILC_ID_CLIENT);
4920   }
4921   if (!result) {
4922     /* Authentication failed */
4923     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4924                                           SILC_STATUS_ERR_AUTH_FAILED,
4925                                           0);
4926     goto out;
4927   }
4928
4929   /* Client is now server operator */
4930   client->mode |= SILC_UMODE_SERVER_OPERATOR;
4931
4932   /* Update statistics */
4933   if (SILC_IS_LOCAL(client))
4934     server->stat.my_server_ops++;
4935   if (server->server_type == SILC_ROUTER)
4936     server->stat.server_ops++;
4937
4938   /* Send UMODE change to primary router */
4939   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
4940                                 SILC_BROADCAST(server), client->id,
4941                                 client->mode);
4942
4943   /* Check if anyone is watching this nickname */
4944   if (server->server_type == SILC_ROUTER)
4945     silc_server_check_watcher_list(server, client, NULL,
4946                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
4947
4948   /* Send reply to the sender */
4949   silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
4950                                         SILC_STATUS_OK, 0);
4951
4952  out:
4953   silc_server_command_free(cmd);
4954 }
4955
4956 SILC_TASK_CALLBACK(silc_server_command_detach_cb)
4957 {
4958   QuitInternal q = (QuitInternal)context;
4959   SilcClientID *client_id = (SilcClientID *)q->sock;
4960   SilcClientEntry client;
4961   SilcSocketConnection sock;
4962
4963   client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4964                                          TRUE, NULL);
4965   if (client && client->connection) {
4966     sock = client->connection;
4967
4968     /* If there is pending outgoing data for the client then purge it
4969        to the network before closing connection. */
4970     silc_server_packet_queue_purge(q->server, sock);
4971
4972     /* Close the connection on our side */
4973     client->router = NULL;
4974     client->connection = NULL;
4975     sock->user_data = NULL;
4976     silc_server_close_connection(q->server, sock);
4977   }
4978
4979   silc_free(client_id);
4980   silc_free(q);
4981 }
4982
4983 SILC_TASK_CALLBACK(silc_server_command_detach_timeout)
4984 {
4985   QuitInternal q = (QuitInternal)context;
4986   SilcClientID *client_id = (SilcClientID *)q->sock;
4987   SilcClientEntry client;
4988
4989   client = silc_idlist_find_client_by_id(q->server->local_list, client_id,
4990                                          TRUE, NULL);
4991   if (client && client->mode & SILC_UMODE_DETACHED) {
4992     SILC_LOG_DEBUG(("Detach timeout"));
4993     silc_server_free_client_data(q->server, NULL, client, TRUE,
4994                                  "Detach timeout");
4995   }
4996
4997   silc_free(client_id);
4998   silc_free(q);
4999 }
5000
5001 /* Server side of DETACH command.  Detached the client from the network
5002    by closing the connection but preserving the session. */
5003
5004 SILC_SERVER_CMD_FUNC(detach)
5005 {
5006   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5007   SilcServer server = cmd->server;
5008   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5009   QuitInternal q;
5010
5011   if (server->config->detach_disabled) {
5012     silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5013                                           SILC_STATUS_ERR_UNKNOWN_COMMAND, 0);
5014     goto out;
5015   }
5016
5017   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5018     goto out;
5019
5020   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_DETACH, cmd, 0, 0);
5021
5022   /* Remove operator privileges, since the client may resume in some
5023      other server which to it does not have operator privileges. */
5024   SILC_OPER_STATS_UPDATE(client, server, SILC_UMODE_SERVER_OPERATOR);
5025   SILC_OPER_STATS_UPDATE(client, router, SILC_UMODE_ROUTER_OPERATOR);
5026
5027   /* Send the user mode notify to notify that client is detached */
5028   client->mode |= SILC_UMODE_DETACHED;
5029   client->data.status &= ~SILC_IDLIST_STATUS_RESUMED;
5030   client->last_command = 0;
5031   client->fast_command = 0;
5032   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5033                                 SILC_BROADCAST(server), client->id,
5034                                 client->mode);
5035   server->stat.my_detached++;
5036
5037   /* Check if anyone is watching this nickname */
5038   if (server->server_type == SILC_ROUTER)
5039     silc_server_check_watcher_list(server, client, NULL,
5040                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5041
5042   q = silc_calloc(1, sizeof(*q));
5043   q->server = server;
5044   q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5045   silc_schedule_task_add(server->schedule, 0, silc_server_command_detach_cb,
5046                          q, 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5047
5048   if (server->config->detach_timeout) {
5049     q = silc_calloc(1, sizeof(*q));
5050     q->server = server;
5051     q->sock = silc_id_dup(client->id, SILC_ID_CLIENT);
5052     silc_schedule_task_add(server->schedule, 0, 
5053                            silc_server_command_detach_timeout,
5054                            q, server->config->detach_timeout * 60,
5055                            0, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
5056   }
5057
5058   /* Send reply to the sender */
5059   silc_server_command_send_status_reply(cmd, SILC_COMMAND_DETACH,
5060                                         SILC_STATUS_OK, 0);
5061
5062  out:
5063   silc_server_command_free(cmd);
5064 }
5065
5066 /* Server side of WATCH command. */
5067
5068 SILC_SERVER_CMD_FUNC(watch)
5069 {
5070   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5071   SilcServer server = cmd->server;
5072   char *add_nick, *del_nick;
5073   SilcUInt32 add_nick_len, del_nick_len, tmp_len;
5074   char nick[128 + 1];
5075   unsigned char hash[16], *tmp;
5076   SilcClientEntry client;
5077   SilcClientID *client_id = NULL;
5078
5079   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_WATCH, cmd, 1, 3);
5080
5081   if (server->server_type == SILC_SERVER && !server->standalone) {
5082     if (!cmd->pending) {
5083       /* Send the command to router */
5084       SilcBuffer tmpbuf;
5085       SilcUInt16 old_ident;
5086
5087       old_ident = silc_command_get_ident(cmd->payload);
5088       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5089       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5090
5091       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5092                               SILC_PACKET_COMMAND, cmd->packet->flags,
5093                               tmpbuf->data, tmpbuf->len, TRUE);
5094
5095       /* Reprocess this packet after received reply from router */
5096       silc_server_command_pending(server, SILC_COMMAND_WATCH,
5097                                   silc_command_get_ident(cmd->payload),
5098                                   silc_server_command_watch,
5099                                   silc_server_command_dup(cmd));
5100       cmd->pending = TRUE;
5101       silc_command_set_ident(cmd->payload, old_ident);
5102       silc_buffer_free(tmpbuf);
5103     } else if (context2) {
5104       /* Received reply from router, just send same data to the client. */
5105       SilcServerCommandReplyContext reply = context2;
5106       SilcStatus status;
5107       silc_command_get_status(reply->payload, &status, NULL);
5108       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH, status,
5109                                             0);
5110     }
5111
5112     goto out;
5113   }
5114
5115   /* We are router and keep the watch list for local cell */
5116
5117   /* Get the client ID */
5118   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5119   if (!tmp) {
5120     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5121                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5122                                           0);
5123     goto out;
5124   }
5125   client_id = silc_id_payload_parse_id(tmp, tmp_len, NULL);
5126   if (!client_id) {
5127     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5128                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5129                                           0);
5130     goto out;
5131   }
5132
5133   /* Get the client entry which must be in local list */
5134   client = silc_idlist_find_client_by_id(server->local_list, 
5135                                          client_id, TRUE, NULL);
5136   if (!client) {
5137     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5138                                           SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5139                                           0);
5140     goto out;
5141   }
5142
5143   /* Take nickname */
5144   add_nick = silc_argument_get_arg_type(cmd->args, 2, &add_nick_len);
5145   del_nick = silc_argument_get_arg_type(cmd->args, 3, &del_nick_len);
5146   if (!add_nick && !del_nick) {
5147     silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5148                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5149                                           0);
5150     goto out;
5151   }
5152
5153   if (add_nick && add_nick_len > 128)
5154     add_nick[128] = '\0';
5155   if (del_nick && del_nick_len > 128)
5156     del_nick[128] = '\0';
5157
5158   memset(nick, 0, sizeof(nick));
5159
5160   /* Add new nickname to be watched in our cell */
5161   if (add_nick) {
5162     if (silc_server_name_bad_chars(add_nick, strlen(add_nick)) == TRUE) {
5163       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5164                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5165       goto out;
5166     }
5167
5168     /* Hash the nick, we have the hash saved, not nicks because we can
5169        do one to one mapping to the nick from Client ID hash this way. */
5170     silc_to_lower(add_nick, nick, sizeof(nick) - 1);
5171     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5172
5173     /* Check whether this client is already watching this nickname */
5174     if (silc_hash_table_find_by_context(server->watcher_list, hash, 
5175                                         client, NULL)) {
5176       /* Nickname is alredy being watched for this client */
5177       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5178                                             SILC_STATUS_ERR_NICKNAME_IN_USE,
5179                                             0);
5180       goto out;
5181     }
5182
5183     /* Get the nickname from the watcher list and use the same key in
5184        new entries as well.  If key doesn't exist then create it. */
5185     if (!silc_hash_table_find(server->watcher_list, hash, (void **)&tmp, NULL))
5186       tmp = silc_memdup(hash, CLIENTID_HASH_LEN);
5187
5188     /* Add the client to the watcher list with the specified nickname hash. */
5189     silc_hash_table_add(server->watcher_list, tmp, client);
5190   }
5191
5192   /* Delete nickname from watch list */
5193   if (del_nick) {
5194     if (silc_server_name_bad_chars(del_nick, strlen(del_nick)) == TRUE) {
5195       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5196                                             SILC_STATUS_ERR_BAD_NICKNAME, 0);
5197       goto out;
5198     }
5199
5200     /* Hash the nick, we have the hash saved, not nicks because we can
5201        do one to one mapping to the nick from Client ID hash this way. */
5202     silc_to_lower(del_nick, nick, sizeof(nick) - 1);
5203     silc_hash_make(server->md5hash, nick, strlen(nick), hash);
5204
5205     /* Check that this client is watching for this nickname */
5206     if (!silc_hash_table_find_by_context(server->watcher_list, hash, 
5207                                          client, (void **)&tmp)) {
5208       /* Nickname is alredy being watched for this client */
5209       silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5210                                             SILC_STATUS_ERR_NO_SUCH_NICK, 0);
5211       goto out;
5212     }
5213
5214     /* Delete the nickname from the watcher list. */
5215     silc_hash_table_del_by_context(server->watcher_list, hash, client);
5216
5217     /* Now check whether there still exists entries with this key, if not
5218        then free the key to not leak memory. */
5219     if (!silc_hash_table_find(server->watcher_list, hash, NULL, NULL))
5220       silc_free(tmp);
5221   }
5222
5223   /* Distribute the watch list to backup routers too */
5224   if (server->backup) {
5225     SilcBuffer tmpbuf;
5226     silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5227     tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5228     silc_server_backup_send(server, NULL, SILC_PACKET_COMMAND,
5229                             cmd->packet->flags, tmpbuf->data, tmpbuf->len,
5230                             FALSE, TRUE);
5231     silc_buffer_free(tmpbuf);
5232   }
5233
5234   silc_server_command_send_status_reply(cmd, SILC_COMMAND_WATCH,
5235                                         SILC_STATUS_OK, 0);
5236
5237  out:
5238   silc_free(client_id);
5239   silc_server_command_free(cmd);
5240 }
5241
5242 /* Server side of SILCOPER command. Client uses this comand to obtain router
5243    operator privileges to this router. */
5244
5245 SILC_SERVER_CMD_FUNC(silcoper)
5246 {
5247   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5248   SilcServer server = cmd->server;
5249   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5250   unsigned char *username, *auth;
5251   SilcUInt32 tmp_len;
5252   SilcServerConfigAdmin *admin;
5253   SilcIDListData idata = (SilcIDListData)client;
5254   bool result = FALSE;
5255   SilcPublicKey cached_key;
5256
5257   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_SILCOPER, cmd, 1, 2);
5258
5259   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5260     goto out;
5261
5262   if (server->server_type != SILC_ROUTER) {
5263     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5264                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5265     goto out;
5266   }
5267
5268   /* Get the username */
5269   username = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5270   if (!username) {
5271     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5272                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5273                                           0);
5274     goto out;
5275   }
5276
5277   /* Get the admin configuration */
5278   admin = silc_server_config_find_admin(server, cmd->sock->ip,
5279                                         username, client->nickname);
5280   if (!admin) {
5281     admin = silc_server_config_find_admin(server, cmd->sock->hostname,
5282                                           username, client->nickname);
5283     if (!admin) {
5284       silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5285                                             SILC_STATUS_ERR_AUTH_FAILED, 0);
5286       goto out;
5287     }
5288   }
5289
5290   /* Get the authentication payload */
5291   auth = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5292   if (!auth) {
5293     silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5294                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5295                                           0);
5296     goto out;
5297   }
5298
5299   /* Verify the authentication data. If both passphrase and public key
5300      is set then try both of them. */
5301   if (admin->passphrase)
5302     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PASSWORD,
5303                                    admin->passphrase, admin->passphrase_len,
5304                                    idata->hash, client->id, SILC_ID_CLIENT);
5305   if (!result && admin->publickeys) {
5306     cached_key = silc_server_get_public_key(server, admin->publickeys);
5307     if (!cached_key)
5308       goto out;
5309     result = silc_auth_verify_data(auth, tmp_len, SILC_AUTH_PUBLIC_KEY,
5310                                    cached_key, 0, idata->hash, 
5311                                    client->id, SILC_ID_CLIENT);
5312   }
5313   if (!result) {
5314     /* Authentication failed */
5315     silc_server_command_send_status_reply(cmd, SILC_COMMAND_OPER,
5316                                           SILC_STATUS_ERR_AUTH_FAILED, 0);
5317     goto out;
5318   }
5319
5320   /* Client is now router operator */
5321   client->mode |= SILC_UMODE_ROUTER_OPERATOR;
5322
5323   /* Update statistics */
5324   if (SILC_IS_LOCAL(client))
5325     server->stat.my_router_ops++;
5326   if (server->server_type == SILC_ROUTER)
5327     server->stat.router_ops++;
5328
5329   /* Send UMODE change to primary router */
5330   silc_server_send_notify_umode(server, SILC_PRIMARY_ROUTE(server),
5331                                 SILC_BROADCAST(server), client->id,
5332                                 client->mode);
5333
5334   /* Check if anyone is watching this nickname */
5335   if (server->server_type == SILC_ROUTER)
5336     silc_server_check_watcher_list(server, client, NULL,
5337                                    SILC_NOTIFY_TYPE_UMODE_CHANGE);
5338
5339   /* Send reply to the sender */
5340   silc_server_command_send_status_reply(cmd, SILC_COMMAND_SILCOPER,
5341                                         SILC_STATUS_OK, 0);
5342
5343  out:
5344   silc_server_command_free(cmd);
5345 }
5346
5347 /* Server side of command BAN. This is used to manage the ban list of the
5348    channel. To add clients and remove clients from the ban list. */
5349
5350 SILC_SERVER_CMD_FUNC(ban)
5351 {
5352   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5353   SilcServer server = cmd->server;
5354   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5355   SilcBuffer packet;
5356   SilcChannelEntry channel;
5357   SilcChannelClientEntry chl;
5358   SilcChannelID *channel_id = NULL;
5359   unsigned char *id, *add, *del;
5360   SilcUInt32 id_len, tmp_len;
5361   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5362
5363   if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5364     goto out;
5365
5366   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_BAN, cmd, 0, 3);
5367
5368   /* Get Channel ID */
5369   id = silc_argument_get_arg_type(cmd->args, 1, &id_len);
5370   if (id) {
5371     channel_id = silc_id_payload_parse_id(id, id_len, NULL);
5372     if (!channel_id) {
5373       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5374                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5375       goto out;
5376     }
5377   }
5378
5379   /* Get channel entry. The server must know about the channel since the
5380      client is expected to be on the channel. */
5381   channel = silc_idlist_find_channel_by_id(server->local_list, 
5382                                            channel_id, NULL);
5383   if (!channel) {
5384     channel = silc_idlist_find_channel_by_id(server->global_list, 
5385                                              channel_id, NULL);
5386     if (!channel) {
5387       silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5388                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5389                                             0);
5390       goto out;
5391     }
5392   }
5393
5394   /* Check whether this client is on the channel */
5395   if (!silc_server_client_on_channel(client, channel, &chl)) {
5396     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5397                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5398     goto out;
5399   }
5400
5401   /* The client must be at least channel operator. */
5402   if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
5403     silc_server_command_send_status_reply(cmd, SILC_COMMAND_BAN,
5404                                           SILC_STATUS_ERR_NO_CHANNEL_PRIV, 0);
5405     goto out;
5406   }
5407
5408   /* Get the new ban and add it to the ban list */
5409   add = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5410   if (add) {
5411     if (!channel->ban_list)
5412       channel->ban_list = silc_calloc(tmp_len + 2, sizeof(*channel->ban_list));
5413     else
5414       channel->ban_list = silc_realloc(channel->ban_list, 
5415                                        sizeof(*channel->ban_list) * 
5416                                        (tmp_len + 
5417                                         strlen(channel->ban_list) + 2));
5418     if (add[tmp_len - 1] == ',')
5419       add[tmp_len - 1] = '\0';
5420
5421     strncat(channel->ban_list, add, tmp_len);
5422     strncat(channel->ban_list, ",", 1);
5423   }
5424
5425   /* Get the ban to be removed and remove it from the list */
5426   del = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
5427   if (del && channel->ban_list) {
5428     char *start, *end, *n;
5429
5430     if (!strncmp(channel->ban_list, del, strlen(channel->ban_list) - 1)) {
5431       silc_free(channel->ban_list);
5432       channel->ban_list = NULL;
5433     } else {
5434       start = strstr(channel->ban_list, del);
5435       if (start && strlen(start) >= tmp_len) {
5436         end = start + tmp_len;
5437         n = silc_calloc(strlen(channel->ban_list) - tmp_len, sizeof(*n));
5438         strncat(n, channel->ban_list, start - channel->ban_list);
5439         strncat(n, end + 1, ((channel->ban_list + strlen(channel->ban_list)) - 
5440                              end) - 1);
5441         silc_free(channel->ban_list);
5442         channel->ban_list = n;
5443       }
5444     }
5445   }
5446
5447   /* Send the BAN notify type to our primary router. */
5448   if (add || del)
5449     silc_server_send_notify_ban(server, SILC_PRIMARY_ROUTE(server),
5450                                 SILC_BROADCAST(server), channel, add, del);
5451
5452   /* Send the reply back to the client */
5453   packet = 
5454     silc_command_reply_payload_encode_va(SILC_COMMAND_BAN,
5455                                          SILC_STATUS_OK, 0, ident, 2,
5456                                          2, id, id_len,
5457                                          3, channel->ban_list, 
5458                                          channel->ban_list ? 
5459                                          strlen(channel->ban_list) -1 : 0);
5460   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5461                           packet->data, packet->len, FALSE);
5462     
5463   silc_buffer_free(packet);
5464
5465  out:
5466   silc_free(channel_id);
5467   silc_server_command_free(cmd);
5468 }
5469
5470 /* Server side command of LEAVE. Removes client from a channel. */
5471
5472 SILC_SERVER_CMD_FUNC(leave)
5473 {
5474   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5475   SilcServer server = cmd->server;
5476   SilcSocketConnection sock = cmd->sock;
5477   SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
5478   SilcChannelID *id = NULL;
5479   SilcChannelEntry channel;
5480   SilcUInt32 len;
5481   unsigned char *tmp;
5482
5483   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_LEAVE, cmd, 1, 2);
5484
5485   /* Get Channel ID */
5486   tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
5487   if (!tmp) {
5488     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5489                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5490     goto out;
5491   }
5492   id = silc_id_payload_parse_id(tmp, len, NULL);
5493   if (!id) {
5494     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5495                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5496     goto out;
5497   }
5498
5499   /* Get channel entry */
5500   channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5501   if (!channel) {
5502     channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5503     if (!channel) {
5504       silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5505                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5506                                             0);
5507       goto out;
5508     }
5509   }
5510
5511   /* Check whether this client is on the channel */
5512   if (!silc_server_client_on_channel(id_entry, channel, NULL)) {
5513     silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
5514                                           SILC_STATUS_ERR_NOT_ON_CHANNEL, 0);
5515     goto out;
5516   }
5517
5518   /* Notify routers that they should remove this client from their list
5519      of clients on the channel. Send LEAVE notify type. */
5520   silc_server_send_notify_leave(server, SILC_PRIMARY_ROUTE(server),
5521                                 SILC_BROADCAST(server), channel, id_entry->id);
5522
5523   silc_server_command_send_status_data(cmd, SILC_COMMAND_LEAVE,
5524                                        SILC_STATUS_OK, 0, 2, tmp, len);
5525
5526   /* Remove client from channel */
5527   if (!silc_server_remove_from_one_channel(server, sock, channel, id_entry,
5528                                            TRUE))
5529     /* If the channel does not exist anymore we won't send anything */
5530     goto out;
5531
5532   if (!(channel->mode & SILC_CHANNEL_MODE_PRIVKEY)) {
5533     /* Re-generate channel key */
5534     if (!silc_server_create_channel_key(server, channel, 0))
5535       goto out;
5536
5537     /* Send the channel key */
5538     silc_server_send_channel_key(server, NULL, channel, 
5539                                  server->server_type == SILC_ROUTER ? 
5540                                  FALSE : !server->standalone);
5541   }
5542
5543  out:
5544   silc_free(id);
5545   silc_server_command_free(cmd);
5546 }
5547
5548 /* Server side of command USERS. Resolves clients and their USERS currently
5549    joined on the requested channel. The list of Client ID's and their modes
5550    on the channel is sent back. */
5551
5552 SILC_SERVER_CMD_FUNC(users)
5553 {
5554   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5555   SilcServer server = cmd->server;
5556   SilcChannelEntry channel;
5557   SilcChannelID *id = NULL;
5558   SilcBuffer packet, idp;
5559   unsigned char *channel_id;
5560   SilcUInt32 channel_id_len;
5561   SilcBuffer client_id_list;
5562   SilcBuffer client_mode_list;
5563   unsigned char lc[4];
5564   SilcUInt32 list_count = 0;
5565   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5566   char *channel_name;
5567
5568   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_USERS, cmd, 1, 2);
5569
5570   /* Get Channel ID */
5571   channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
5572
5573   /* Get channel name */
5574   channel_name = silc_argument_get_arg_type(cmd->args, 2, NULL);
5575
5576   if (!channel_id && !channel_name) {
5577     silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5578                                           SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5579     goto out;
5580   }
5581
5582   if (channel_id) {
5583     id = silc_id_payload_parse_id(channel_id, channel_id_len, NULL);
5584     if (!id) {
5585       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5586                                             SILC_STATUS_ERR_NO_CHANNEL_ID, 0);
5587       goto out;
5588     }
5589   }
5590
5591   /* If we are server and we don't know about this channel we will send
5592      the command to our router. If we know about the channel then we also
5593      have the list of users already. */
5594   if (id)
5595     channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
5596   else
5597     channel = silc_idlist_find_channel_by_name(server->local_list, 
5598                                                channel_name, NULL);
5599
5600   if (!channel || (!server->standalone && (channel->disabled || 
5601                     !channel->users_resolved))) {
5602     if (server->server_type != SILC_ROUTER && !server->standalone &&
5603         !cmd->pending) {
5604       SilcBuffer tmpbuf;
5605       
5606       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5607       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5608       
5609       /* Send USERS command */
5610       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5611                               SILC_PACKET_COMMAND, cmd->packet->flags,
5612                               tmpbuf->data, tmpbuf->len, TRUE);
5613       
5614       /* Reprocess this packet after received reply */
5615       silc_server_command_pending(server, SILC_COMMAND_USERS, 
5616                                   silc_command_get_ident(cmd->payload),
5617                                   silc_server_command_users,
5618                                   silc_server_command_dup(cmd));
5619       cmd->pending = TRUE;
5620       silc_command_set_ident(cmd->payload, ident);
5621       silc_buffer_free(tmpbuf);
5622       silc_free(id);
5623       goto out;
5624     }
5625
5626     /* Check the global list as well. */
5627     if (id)
5628       channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
5629     else
5630       channel = silc_idlist_find_channel_by_name(server->global_list, 
5631                                                  channel_name, NULL);
5632     if (!channel) {
5633       /* Channel really does not exist */
5634       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5635                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5636                                             0);
5637       goto out;
5638     }
5639   }
5640
5641   /* If the channel is private or secret do not send anything, unless the
5642      user requesting this command is on the channel or is server */
5643   if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
5644     if (channel->mode & (SILC_CHANNEL_MODE_PRIVATE | SILC_CHANNEL_MODE_SECRET)
5645         && !silc_server_client_on_channel(cmd->sock->user_data, channel, 
5646                                           NULL)) {
5647       silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
5648                                             SILC_STATUS_ERR_NO_SUCH_CHANNEL,
5649                                             0);
5650       goto out;
5651     }
5652   }
5653
5654   /* Get the users list */
5655   if (!silc_server_get_users_on_channel(server, channel, &client_id_list,
5656                                         &client_mode_list, &list_count)) {
5657     list_count = 0;
5658     client_id_list = NULL;
5659     client_mode_list = NULL;
5660   }
5661
5662   /* List count */
5663   SILC_PUT32_MSB(list_count, lc);
5664
5665   /* Send reply */
5666   idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
5667   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
5668                                                 SILC_STATUS_OK, 0, ident, 4,
5669                                                 2, idp->data, idp->len,
5670                                                 3, lc, 4,
5671                                                 4, client_id_list ? 
5672                                                 client_id_list->data : NULL,
5673                                                 client_id_list ?
5674                                                 client_id_list->len : 0,
5675                                                 5, client_mode_list ?
5676                                                 client_mode_list->data : NULL,
5677                                                 client_mode_list ?
5678                                                 client_mode_list->len : 0);
5679   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5680                           packet->data, packet->len, FALSE);
5681     
5682   silc_buffer_free(idp);
5683   silc_buffer_free(packet);
5684   if (client_id_list)
5685     silc_buffer_free(client_id_list);
5686   if (client_mode_list)
5687     silc_buffer_free(client_mode_list);
5688   silc_free(id);
5689
5690  out:
5691   silc_server_command_free(cmd);
5692 }
5693
5694 /* Server side of command GETKEY. This fetches the client's public key
5695    from the server where to the client is connected. */
5696
5697 SILC_SERVER_CMD_FUNC(getkey)
5698 {
5699   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5700   SilcServer server = cmd->server;
5701   SilcBuffer packet;
5702   SilcClientEntry client;
5703   SilcServerEntry server_entry;
5704   SilcClientID *client_id = NULL;
5705   SilcServerID *server_id = NULL;
5706   SilcIDPayload idp = NULL;
5707   SilcUInt16 ident = silc_command_get_ident(cmd->payload);
5708   unsigned char *tmp, *pkdata;
5709   SilcUInt32 tmp_len, pklen;
5710   SilcBuffer pk = NULL;
5711   SilcIdType id_type;
5712   SilcPublicKey public_key;
5713
5714   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5715   if (!tmp) {
5716     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5717                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5718                                           0);
5719     goto out;
5720   }
5721   idp = silc_id_payload_parse(tmp, tmp_len);
5722   if (!idp) {
5723     silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5724                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5725                                           0);
5726     goto out;
5727   }
5728
5729   id_type = silc_id_payload_get_type(idp);
5730   if (id_type == SILC_ID_CLIENT) {
5731     client_id = silc_id_payload_get_id(idp);
5732
5733     /* If the client is not found from local list there is no chance it
5734        would be locally connected client so send the command further. */
5735     client = silc_idlist_find_client_by_id(server->local_list, 
5736                                            client_id, TRUE, NULL);
5737     if (!client)
5738       client = silc_idlist_find_client_by_id(server->global_list, 
5739                                              client_id, TRUE, NULL);
5740     
5741     if ((!client && !cmd->pending && !server->standalone) ||
5742         (client && !client->connection && !cmd->pending &&
5743          !(client->mode & SILC_UMODE_DETACHED)) ||
5744         (client && !client->data.public_key && !cmd->pending)) {
5745       SilcBuffer tmpbuf;
5746       SilcUInt16 old_ident;
5747       SilcSocketConnection dest_sock;
5748       
5749       dest_sock = silc_server_get_client_route(server, NULL, 0, 
5750                                                client_id, NULL, NULL);
5751       if (!dest_sock)
5752         goto out;
5753       
5754       old_ident = silc_command_get_ident(cmd->payload);
5755       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5756       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5757       
5758       silc_server_packet_send(server, dest_sock,
5759                               SILC_PACKET_COMMAND, cmd->packet->flags,
5760                               tmpbuf->data, tmpbuf->len, TRUE);
5761       
5762       /* Reprocess this packet after received reply from router */
5763       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5764                                   silc_command_get_ident(cmd->payload),
5765                                   silc_server_command_getkey,
5766                                   silc_server_command_dup(cmd));
5767       cmd->pending = TRUE;
5768       silc_command_set_ident(cmd->payload, old_ident);
5769       silc_buffer_free(tmpbuf);
5770       goto out;
5771     }
5772
5773     if (!client) {
5774       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5775                                             SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
5776                                             0);
5777       goto out;
5778     }
5779
5780     /* The client is locally connected, just get the public key and
5781        send it back. If they key does not exist then do not send it, 
5782        send just OK reply */
5783     public_key = client->data.public_key;
5784     if (!public_key) {
5785       pkdata = NULL;
5786       pklen = 0;
5787     } else {
5788       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5789       pk = silc_buffer_alloc(4 + tmp_len);
5790       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5791       silc_buffer_format(pk,
5792                          SILC_STR_UI_SHORT(tmp_len),
5793                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5794                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5795                          SILC_STR_END);
5796       silc_free(tmp);
5797       pkdata = pk->data;
5798       pklen = pk->len;
5799     }
5800   } else if (id_type == SILC_ID_SERVER) {
5801     server_id = silc_id_payload_get_id(idp);
5802
5803     /* If the server is not found from local list there is no chance it
5804        would be locally connected server so send the command further. */
5805     server_entry = silc_idlist_find_server_by_id(server->local_list, 
5806                                                  server_id, TRUE, NULL);
5807     if (!server_entry)
5808       server_entry = silc_idlist_find_server_by_id(server->global_list, 
5809                                                    server_id, TRUE, NULL);
5810     
5811     if (server_entry != server->id_entry &&
5812         ((!server_entry && !cmd->pending && !server->standalone) ||
5813          (server_entry && !server_entry->connection && !cmd->pending &&
5814           !server->standalone) ||
5815          (server_entry && !server_entry->data.public_key && !cmd->pending &&
5816           !server->standalone))) {
5817       SilcBuffer tmpbuf;
5818       SilcUInt16 old_ident;
5819       
5820       old_ident = silc_command_get_ident(cmd->payload);
5821       silc_command_set_ident(cmd->payload, ++server->cmd_ident);
5822       tmpbuf = silc_command_payload_encode_payload(cmd->payload);
5823       
5824       silc_server_packet_send(server, SILC_PRIMARY_ROUTE(server),
5825                               SILC_PACKET_COMMAND, cmd->packet->flags,
5826                               tmpbuf->data, tmpbuf->len, TRUE);
5827       
5828       /* Reprocess this packet after received reply from router */
5829       silc_server_command_pending(server, SILC_COMMAND_GETKEY, 
5830                                   silc_command_get_ident(cmd->payload),
5831                                   silc_server_command_getkey,
5832                                   silc_server_command_dup(cmd));
5833       cmd->pending = TRUE;
5834       silc_command_set_ident(cmd->payload, old_ident);
5835       silc_buffer_free(tmpbuf);
5836       goto out;
5837     }
5838
5839     if (!server_entry) {
5840       silc_server_command_send_status_reply(cmd, SILC_COMMAND_GETKEY,
5841                                             SILC_STATUS_ERR_NO_SUCH_SERVER_ID,
5842                                             0);
5843       goto out;
5844     }
5845
5846     /* If they key does not exist then do not send it, send just OK reply */
5847     public_key = (!server_entry->data.public_key ? 
5848                   (server_entry == server->id_entry ? server->public_key :
5849                    NULL) : server_entry->data.public_key);
5850     if (!public_key) {
5851       pkdata = NULL;
5852       pklen = 0;
5853     } else {
5854       tmp = silc_pkcs_public_key_encode(public_key, &tmp_len);
5855       pk = silc_buffer_alloc(4 + tmp_len);
5856       silc_buffer_pull_tail(pk, SILC_BUFFER_END(pk));
5857       silc_buffer_format(pk,
5858                          SILC_STR_UI_SHORT(tmp_len),
5859                          SILC_STR_UI_SHORT(SILC_SKE_PK_TYPE_SILC),
5860                          SILC_STR_UI_XNSTRING(tmp, tmp_len),
5861                          SILC_STR_END);
5862       silc_free(tmp);
5863       pkdata = pk->data;
5864       pklen = pk->len;
5865     }
5866   } else {
5867     goto out;
5868   }
5869
5870   tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5871   packet = silc_command_reply_payload_encode_va(SILC_COMMAND_GETKEY,
5872                                                 SILC_STATUS_OK, 0, ident, 
5873                                                 pkdata ? 2 : 1,
5874                                                 2, tmp, tmp_len,
5875                                                 3, pkdata, pklen);
5876   silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0, 
5877                           packet->data, packet->len, FALSE);
5878   silc_buffer_free(packet);
5879
5880   if (pk)
5881     silc_buffer_free(pk);
5882
5883  out:
5884   if (idp)
5885     silc_id_payload_free(idp);
5886   silc_free(client_id);
5887   silc_free(server_id);
5888   silc_server_command_free(cmd);
5889 }
5890
5891
5892 /* Private range commands, specific to this implementation */
5893
5894 /* Server side command of CONNECT. Connects us to the specified remote
5895    server or router. */
5896
5897 SILC_SERVER_CMD_FUNC(connect)
5898 {
5899   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5900   SilcServer server = cmd->server;
5901   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5902   unsigned char *tmp, *host;
5903   SilcUInt32 tmp_len;
5904   SilcUInt32 port = SILC_PORT;
5905
5906   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CONNECT, cmd, 1, 2);
5907
5908   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5909     goto out;
5910
5911   /* Check whether client has the permissions. */
5912   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5913       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5914     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5915                                           SILC_STATUS_ERR_NO_SERVER_PRIV, 0);
5916     goto out;
5917   }
5918
5919   if (server->server_type == SILC_ROUTER && 
5920       client->mode & SILC_UMODE_SERVER_OPERATOR) {
5921     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5922                                           SILC_STATUS_ERR_NO_ROUTER_PRIV, 0);
5923     goto out;
5924   }
5925
5926   /* Get the remote server */
5927   host = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5928   if (!host) {
5929     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5930                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5931                                           0);
5932     goto out;
5933   }
5934
5935   /* Get port */
5936   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5937   if (tmp)
5938     SILC_GET32_MSB(port, tmp);
5939
5940   /* Create the connection. It is done with timeout and is async. */
5941   silc_server_create_connection(server, host, port);
5942
5943   /* Send reply to the sender */
5944   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CONNECT,
5945                                         SILC_STATUS_OK, 0);
5946
5947  out:
5948   silc_server_command_free(cmd);
5949 }
5950
5951 /* Server side command of CLOSE. Closes connection to a specified server. */
5952  
5953 SILC_SERVER_CMD_FUNC(close)
5954 {
5955   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
5956   SilcServer server = cmd->server;
5957   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
5958   SilcServerEntry server_entry;
5959   SilcSocketConnection sock;
5960   unsigned char *tmp;
5961   SilcUInt32 tmp_len;
5962   unsigned char *name;
5963   SilcUInt32 port = SILC_PORT;
5964
5965   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_CLOSE, cmd, 1, 2);
5966
5967   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
5968     goto out;
5969
5970   /* Check whether client has the permissions. */
5971   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
5972       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
5973     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5974                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
5975                                           0);
5976     goto out;
5977   }
5978
5979   /* Get the remote server */
5980   name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
5981   if (!name) {
5982     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
5983                                           SILC_STATUS_ERR_NOT_ENOUGH_PARAMS,
5984                                           0);
5985     goto out;
5986   }
5987
5988   /* Get port */
5989   tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
5990   if (tmp)
5991     SILC_GET32_MSB(port, tmp);
5992
5993   server_entry = silc_idlist_find_server_by_conn(server->local_list,
5994                                                  name, port, FALSE, NULL);
5995   if (!server_entry)
5996     server_entry = silc_idlist_find_server_by_conn(server->global_list,
5997                                                    name, port, FALSE, NULL);
5998   if (!server_entry) {
5999     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6000                                           SILC_STATUS_ERR_NO_SERVER_ID, 0);
6001     goto out;
6002   }
6003
6004   /* Send reply to the sender */
6005   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_CLOSE,
6006                                         SILC_STATUS_OK, 0);
6007
6008   /* Close the connection to the server */
6009   sock = (SilcSocketConnection)server_entry->connection;
6010
6011   /* If we shutdown primary router connection manually then don't trigger
6012      any reconnect or backup router connections, by setting the router
6013      to NULL here. */
6014   if (server->router == server_entry) {
6015     server->id_entry->router = NULL;
6016     server->router = NULL;
6017     server->standalone = TRUE;
6018   }
6019   silc_server_free_sock_user_data(server, sock, NULL);
6020   silc_server_close_connection(server, sock);
6021   
6022  out:
6023   silc_server_command_free(cmd);
6024 }
6025
6026 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
6027    active connections. */
6028  
6029 SILC_SERVER_CMD_FUNC(shutdown)
6030 {
6031   SilcServerCommandContext cmd = (SilcServerCommandContext)context;
6032   SilcServer server = cmd->server;
6033   SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
6034
6035   SILC_SERVER_COMMAND_CHECK(SILC_COMMAND_PRIV_SHUTDOWN, cmd, 0, 0);
6036
6037   if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
6038     goto out;
6039
6040   /* Check whether client has the permission. */
6041   if (!(client->mode & SILC_UMODE_SERVER_OPERATOR) &&
6042       !(client->mode & SILC_UMODE_ROUTER_OPERATOR)) {
6043     silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6044                                           SILC_STATUS_ERR_NO_SERVER_PRIV,
6045                                           0);
6046     goto out;
6047   }
6048
6049   /* Send reply to the sender */
6050   silc_server_command_send_status_reply(cmd, SILC_COMMAND_PRIV_SHUTDOWN,
6051                                         SILC_STATUS_OK, 0);
6052
6053   /* Then, gracefully, or not, bring the server down. */
6054   silc_server_stop(server);
6055   exit(0);
6056
6057  out:
6058   silc_server_command_free(cmd);
6059 }