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