5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2001 Pekka Riikonen
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.
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.
22 #include "serverincludes.h"
23 #include "server_internal.h"
25 static int silc_server_is_registered(SilcServer server,
26 SilcSocketConnection sock,
27 SilcServerCommandContext cmd,
30 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
32 SilcCommandStatus status);
34 silc_server_command_send_status_data(SilcServerCommandContext cmd,
36 SilcCommandStatus status,
37 unsigned int arg_type,
39 unsigned int arg_len);
40 SILC_TASK_CALLBACK(silc_server_command_process_timeout);
42 /* Server command list. */
43 SilcServerCommand silc_command_list[] =
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 | SILC_CF_REG),
49 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | 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 | 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 | 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 | SILC_CF_REG),
63 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | 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 |
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 | SILC_CF_REG),
74 SILC_SERVER_CMD(users, USERS, SILC_CF_LAG | SILC_CF_REG),
79 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
81 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
83 SILC_LOG_DEBUG(("Start")); \
86 silc_server_command_send_status_reply(cmd, command, \
87 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
88 silc_server_command_free(cmd); \
92 silc_server_command_send_status_reply(cmd, command, \
93 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
94 silc_server_command_free(cmd); \
99 /* Returns TRUE if the connection is registered. Unregistered connections
100 usually cannot send commands hence the check. */
102 static int silc_server_is_registered(SilcServer server,
103 SilcSocketConnection sock,
104 SilcServerCommandContext cmd,
107 SilcIDListData idata = (SilcIDListData)sock->user_data;
108 if (idata->registered)
111 silc_server_command_send_status_reply(cmd, command,
112 SILC_STATUS_ERR_NOT_REGISTERED);
113 silc_server_command_free(cmd);
117 /* Internal context to hold data when executed command with timeout. */
120 SilcSocketConnection sock;
121 SilcPacketContext *packet;
122 } *SilcServerCommandTimeout;
124 /* Timeout callback to process commands with timeout for client. Client's
125 commands are always executed with timeout. */
127 SILC_TASK_CALLBACK(silc_server_command_process_timeout)
129 SilcServerCommandTimeout timeout = (SilcServerCommandTimeout)context;
130 SilcServerCommandContext ctx;
131 SilcServerCommand *cmd;
132 SilcClientEntry client = (SilcClientEntry)timeout->sock->user_data;
134 /* Update access time */
135 client->last_command = time(NULL);
137 /* Allocate command context. This must be free'd by the
138 command routine receiving it. */
139 ctx = silc_server_command_alloc();
140 ctx->server = timeout->server;
141 ctx->sock = timeout->sock;
142 ctx->packet = timeout->packet;
144 /* Parse the command payload in the packet */
145 ctx->payload = silc_command_payload_parse(ctx->packet->buffer);
147 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
148 silc_buffer_free(ctx->packet->buffer);
149 silc_socket_free(ctx->sock);
150 silc_packet_context_free(ctx->packet);
155 ctx->args = silc_command_get_args(ctx->payload);
157 /* Execute command. If this fails the packet is dropped. */
158 for (cmd = silc_command_list; cmd->cb; cmd++)
159 if (cmd->cmd == silc_command_get(ctx->payload)) {
161 if (!(cmd->flags & SILC_CF_REG)) {
166 if (silc_server_is_registered(ctx->server, ctx->sock, ctx, cmd->cmd)) {
173 SILC_LOG_ERROR(("Unknown command, packet dropped"));
174 silc_server_command_free(ctx);
182 /* Processes received command packet. */
184 void silc_server_command_process(SilcServer server,
185 SilcSocketConnection sock,
186 SilcPacketContext *packet)
188 SilcServerCommandContext ctx;
189 SilcServerCommand *cmd;
191 /* Execute client's commands always with timeout. Normally they are
192 executed with zero (0) timeout but if client is sending command more
193 frequently than once in 2 seconds, then the timeout may be 0 to 2
195 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
196 SilcClientEntry client = (SilcClientEntry)sock->user_data;
197 SilcServerCommandTimeout timeout = silc_calloc(1, sizeof(*timeout));
199 timeout->server = server;
200 timeout->sock = silc_socket_dup(sock);
201 timeout->packet = silc_packet_context_dup(packet);
203 if (client->last_command && (time(NULL) - client->last_command) < 2)
204 silc_task_register(server->timeout_queue, sock->sock,
205 silc_server_command_process_timeout,
207 2 - (time(NULL) - client->last_command), 0,
209 SILC_TASK_PRI_NORMAL);
211 silc_task_register(server->timeout_queue, sock->sock,
212 silc_server_command_process_timeout,
216 SILC_TASK_PRI_NORMAL);
220 /* Allocate command context. This must be free'd by the
221 command routine receiving it. */
222 ctx = silc_server_command_alloc();
223 ctx->server = server;
224 ctx->sock = silc_socket_dup(sock);
225 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
227 /* Parse the command payload in the packet */
228 ctx->payload = silc_command_payload_parse(packet->buffer);
230 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
231 silc_buffer_free(packet->buffer);
232 silc_packet_context_free(packet);
233 silc_socket_free(ctx->sock);
237 ctx->args = silc_command_get_args(ctx->payload);
239 /* Execute command. If this fails the packet is dropped. */
240 for (cmd = silc_command_list; cmd->cb; cmd++)
241 if (cmd->cmd == silc_command_get(ctx->payload)) {
243 if (!(cmd->flags & SILC_CF_REG)) {
248 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
255 SILC_LOG_ERROR(("Unknown command, packet dropped"));
256 silc_server_command_free(ctx);
261 /* Allocate Command Context */
263 SilcServerCommandContext silc_server_command_alloc()
265 SilcServerCommandContext ctx = silc_calloc(1, sizeof(*ctx));
270 /* Free's the command context allocated before executing the command */
272 void silc_server_command_free(SilcServerCommandContext ctx)
275 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users + 1,
277 if (ctx->users < 1) {
279 silc_command_free_payload(ctx->payload);
281 silc_packet_context_free(ctx->packet);
283 silc_socket_free(ctx->sock); /* Decrease reference counter */
288 /* Duplicate Command Context by adding reference counter. The context won't
289 be free'd untill it hits zero. */
291 SilcServerCommandContext
292 silc_server_command_dup(SilcServerCommandContext ctx)
295 SILC_LOG_DEBUG(("Command context %p refcnt %d->%d", ctx, ctx->users - 1,
300 /* Add new pending command to be executed when reply to a command has been
301 received. The `reply_cmd' is the command that will call the `callback'
302 with `context' when reply has been received. If `ident' is non-zero
303 the `callback' will be executed when received reply with command
304 identifier `ident'. */
306 void silc_server_command_pending(SilcServer server,
307 SilcCommand reply_cmd,
308 unsigned short ident,
309 SilcServerPendingDestructor destructor,
310 SilcCommandCb callback,
313 SilcServerCommandPending *reply;
315 reply = silc_calloc(1, sizeof(*reply));
316 reply->reply_cmd = reply_cmd;
317 reply->ident = ident;
318 reply->context = context;
319 reply->callback = callback;
320 reply->destructor = destructor;
321 silc_dlist_add(server->pending_commands, reply);
324 /* Deletes pending command by reply command type. */
326 void silc_server_command_pending_del(SilcServer server,
327 SilcCommand reply_cmd,
328 unsigned short ident)
330 SilcServerCommandPending *r;
332 silc_dlist_start(server->pending_commands);
333 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
334 if (r->reply_cmd == reply_cmd && r->ident == ident) {
335 silc_dlist_del(server->pending_commands, r);
341 /* Checks for pending commands and marks callbacks to be called from
342 the command reply function. Returns TRUE if there were pending command. */
344 int silc_server_command_pending_check(SilcServer server,
345 SilcServerCommandReplyContext ctx,
347 unsigned short ident)
349 SilcServerCommandPending *r;
351 silc_dlist_start(server->pending_commands);
352 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
353 if (r->reply_cmd == command && r->ident == ident) {
354 ctx->context = r->context;
355 ctx->callback = r->callback;
356 ctx->destructor = r->destructor;
365 /* Destructor function for pending callbacks. This is called when using
366 pending commands to free the context given for the pending command. */
368 static void silc_server_command_destructor(void *context)
370 silc_server_command_free((SilcServerCommandContext)context);
373 /* Sends simple status message as command reply packet */
376 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
378 SilcCommandStatus status)
382 SILC_LOG_DEBUG(("Sending command status %d", status));
384 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
385 silc_server_packet_send(cmd->server, cmd->sock,
386 SILC_PACKET_COMMAND_REPLY, 0,
387 buffer->data, buffer->len, FALSE);
388 silc_buffer_free(buffer);
391 /* Sends command status reply with one extra argument. The argument
392 type must be sent as argument. */
395 silc_server_command_send_status_data(SilcServerCommandContext cmd,
397 SilcCommandStatus status,
398 unsigned int arg_type,
400 unsigned int arg_len)
404 SILC_LOG_DEBUG(("Sending command status %d", status));
406 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
407 arg_type, arg, arg_len);
408 silc_server_packet_send(cmd->server, cmd->sock,
409 SILC_PACKET_COMMAND_REPLY, 0,
410 buffer->data, buffer->len, FALSE);
411 silc_buffer_free(buffer);
414 /******************************************************************************
418 ******************************************************************************/
421 silc_server_command_whois_parse(SilcServerCommandContext cmd,
422 SilcClientID ***client_id,
423 unsigned int *client_id_count,
431 unsigned int argc = silc_argument_get_arg_num(cmd->args);
434 /* If client ID is in the command it must be used instead of nickname */
435 tmp = silc_argument_get_arg_type(cmd->args, 3, &len);
437 /* No ID, get the nickname@server string and parse it. */
438 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
440 if (strchr(tmp, '@')) {
441 len = strcspn(tmp, "@");
442 *nickname = silc_calloc(len + 1, sizeof(char));
443 memcpy(*nickname, tmp, len);
444 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
445 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
447 *nickname = strdup(tmp);
450 silc_server_command_send_status_reply(cmd, command,
451 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
455 /* Command includes ID, we must use that. Also check whether the command
456 has more than one ID set - take them all. */
458 *client_id = silc_calloc(1, sizeof(**client_id));
459 (*client_id)[0] = silc_id_payload_parse_id(tmp, len);
460 if ((*client_id)[0] == NULL) {
461 silc_free(*client_id);
464 *client_id_count = 1;
466 /* Take all ID's from the command packet */
468 for (k = 1, i = 1; i < argc; i++) {
469 tmp = silc_argument_get_arg_type(cmd->args, i + 3, &len);
471 *client_id = silc_realloc(*client_id, sizeof(**client_id) *
472 (*client_id_count + 1));
473 (*client_id)[k] = silc_id_payload_parse_id(tmp, len);
474 if ((*client_id)[k] == NULL) {
475 /* Cleanup all and fail */
476 for (i = 0; i < *client_id_count; i++)
477 silc_free((*client_id)[i]);
478 silc_free(*client_id);
481 (*client_id_count)++;
487 /* Command includes ID, use that */
490 /* Get the max count of reply messages allowed */
491 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
501 silc_server_command_whois_check(SilcServerCommandContext cmd,
502 SilcClientEntry *clients,
503 unsigned int clients_count)
505 SilcServer server = cmd->server;
507 SilcClientEntry entry;
509 for (i = 0; i < clients_count; i++) {
512 if (!entry->nickname || !entry->username) {
514 unsigned short old_ident;
519 old_ident = silc_command_get_ident(cmd->payload);
520 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
521 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
523 /* Send WHOIS command */
524 silc_server_packet_send(server, entry->router->connection,
525 SILC_PACKET_COMMAND, cmd->packet->flags,
526 tmpbuf->data, tmpbuf->len, TRUE);
528 /* Reprocess this packet after received reply */
529 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
530 silc_command_get_ident(cmd->payload),
531 silc_server_command_destructor,
532 silc_server_command_whois,
533 silc_server_command_dup(cmd));
536 silc_command_set_ident(cmd->payload, old_ident);
538 silc_buffer_free(tmpbuf);
547 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
548 SilcClientEntry *clients,
549 unsigned int clients_count)
551 SilcServer server = cmd->server;
553 int i, count = 0, len;
554 SilcBuffer packet, idp;
555 SilcClientEntry entry;
556 SilcCommandStatus status;
557 unsigned short ident = silc_command_get_ident(cmd->payload);
559 status = SILC_STATUS_OK;
560 if (clients_count > 1)
561 status = SILC_STATUS_LIST_START;
563 for (i = 0; i < clients_count; i++) {
566 if (count && i - 1 == count)
569 if (clients_count > 2)
570 status = SILC_STATUS_LIST_ITEM;
572 if (clients_count > 1 && i == clients_count - 1)
573 status = SILC_STATUS_LIST_END;
575 /* Sanity check, however these should never fail. However, as
576 this sanity check has been added here they have failed. */
577 if (!entry->nickname || !entry->username)
580 /* Send WHOIS reply */
581 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
582 tmp = silc_argument_get_first_arg(cmd->args, NULL);
586 char nh[256], uh[256];
587 unsigned char idle[4];
588 SilcSocketConnection hsock;
590 memset(uh, 0, sizeof(uh));
591 memset(nh, 0, sizeof(nh));
593 strncat(nh, entry->nickname, strlen(entry->nickname));
594 if (!strchr(entry->nickname, '@')) {
596 len = entry->router ? strlen(entry->router->server_name) :
597 strlen(server->server_name);
598 strncat(nh, entry->router ? entry->router->server_name :
599 server->server_name, len);
602 strncat(uh, entry->username, strlen(entry->username));
603 if (!strchr(entry->username, '@')) {
605 hsock = (SilcSocketConnection)entry->connection;
606 len = strlen(hsock->hostname);
607 strncat(uh, hsock->hostname, len);
610 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
613 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
615 2, idp->data, idp->len,
619 strlen(entry->userinfo),
623 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
624 0, packet->data, packet->len, FALSE);
626 silc_buffer_free(packet);
627 silc_buffer_free(idp);
632 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
634 SilcServer server = cmd->server;
635 char *nick = NULL, *server_name = NULL;
636 int count = 0, clients_count = 0;
637 SilcClientEntry *clients = NULL, entry;
638 SilcClientID **client_id = NULL;
639 unsigned int client_id_count = 0;
642 /* Protocol dictates that we must always send the received WHOIS request
643 to our router if we are normal server, so let's do it now unless we
644 are standalone. We will not send any replies to the client until we
645 have received reply from the router. */
646 if (server->server_type == SILC_SERVER &&
647 !cmd->pending && !server->standalone) {
649 unsigned short old_ident;
651 old_ident = silc_command_get_ident(cmd->payload);
652 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
653 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
655 /* Send WHOIS command to our router */
656 silc_server_packet_send(server, (SilcSocketConnection)
657 server->router->connection,
658 SILC_PACKET_COMMAND, cmd->packet->flags,
659 tmpbuf->data, tmpbuf->len, TRUE);
661 /* Reprocess this packet after received reply from router */
662 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
663 silc_command_get_ident(cmd->payload),
664 silc_server_command_destructor,
665 silc_server_command_whois,
666 silc_server_command_dup(cmd));
669 silc_command_set_ident(cmd->payload, old_ident);
671 silc_buffer_free(tmpbuf);
676 /* We are ready to process the command request. Let's search for the
677 requested client and send reply to the requesting client. */
679 /* Parse the whois request */
680 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
681 &nick, &server_name, &count,
685 /* Get all clients matching that ID or nickname from local list */
686 if (client_id_count) {
687 /* Check all Client ID's received in the command packet */
688 for (i = 0; i < client_id_count; i++) {
689 entry = silc_idlist_find_client_by_id(server->local_list,
692 clients = silc_realloc(clients, sizeof(*clients) *
693 (clients_count + 1));
694 clients[clients_count++] = entry;
698 clients = silc_idlist_get_clients_by_nickname(server->local_list,
702 clients = silc_idlist_get_clients_by_hash(server->local_list,
703 nick, server->md5hash,
707 /* Check global list as well */
709 if (client_id_count) {
710 /* Check all Client ID's received in the command packet */
711 for (i = 0; i < client_id_count; i++) {
712 entry = silc_idlist_find_client_by_id(server->global_list,
715 clients = silc_realloc(clients, sizeof(*clients) *
716 (clients_count + 1));
717 clients[clients_count++] = entry;
721 clients = silc_idlist_get_clients_by_nickname(server->global_list,
725 clients = silc_idlist_get_clients_by_hash(server->global_list,
726 nick, server->md5hash,
732 /* Such client(s) really does not exist in the SILC network. */
733 if (!client_id_count) {
734 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
735 SILC_STATUS_ERR_NO_SUCH_NICK,
736 3, nick, strlen(nick));
738 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
739 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
740 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
741 2, idp->data, idp->len);
742 silc_buffer_free(idp);
747 /* Router always finds the client entry if it exists in the SILC network.
748 However, it might be incomplete entry and does not include all the
749 mandatory fields that WHOIS command reply requires. Check for these and
750 make query from the server who owns the client if some fields are
752 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
757 /* Send the command reply to the client */
758 silc_server_command_whois_send_reply(cmd, clients, clients_count);
761 if (client_id_count) {
762 for (i = 0; i < client_id_count; i++)
763 silc_free(client_id[i]);
764 silc_free(client_id);
771 silc_free(server_name);
777 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
779 SilcServer server = cmd->server;
780 char *nick = NULL, *server_name = NULL;
781 int count = 0, clients_count = 0;
782 SilcClientEntry *clients = NULL, entry;
783 SilcClientID **client_id = NULL;
784 unsigned int client_id_count = 0;
787 /* Parse the whois request */
788 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
789 &nick, &server_name, &count,
793 /* Process the command request. Let's search for the requested client and
794 send reply to the requesting server. */
796 if (client_id_count) {
797 /* Check all Client ID's received in the command packet */
798 for (i = 0; i < client_id_count; i++) {
799 entry = silc_idlist_find_client_by_id(server->local_list,
802 clients = silc_realloc(clients, sizeof(*clients) *
803 (clients_count + 1));
804 clients[clients_count++] = entry;
808 clients = silc_idlist_get_clients_by_nickname(server->local_list,
812 clients = silc_idlist_get_clients_by_hash(server->local_list,
813 nick, server->md5hash,
817 /* If we are router we will check our global list as well. */
818 if (!clients && server->server_type == SILC_ROUTER) {
819 if (client_id_count) {
820 /* Check all Client ID's received in the command packet */
821 for (i = 0; i < client_id_count; i++) {
822 entry = silc_idlist_find_client_by_id(server->global_list,
825 clients = silc_realloc(clients, sizeof(*clients) *
826 (clients_count + 1));
827 clients[clients_count++] = entry;
831 clients = silc_idlist_get_clients_by_nickname(server->global_list,
835 clients = silc_idlist_get_clients_by_hash(server->global_list,
836 nick, server->md5hash,
842 /* Such a client really does not exist in the SILC network. */
843 if (!client_id_count) {
844 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
845 SILC_STATUS_ERR_NO_SUCH_NICK,
846 3, nick, strlen(nick));
848 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
849 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
850 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
851 2, idp->data, idp->len);
852 silc_buffer_free(idp);
857 /* Router always finds the client entry if it exists in the SILC network.
858 However, it might be incomplete entry and does not include all the
859 mandatory fields that WHOIS command reply requires. Check for these and
860 make query from the server who owns the client if some fields are
862 if (!silc_server_command_whois_check(cmd, clients, clients_count)) {
867 /* Send the command reply to the client */
868 silc_server_command_whois_send_reply(cmd, clients, clients_count);
871 if (client_id_count) {
872 for (i = 0; i < client_id_count; i++)
873 silc_free(client_id[i]);
874 silc_free(client_id);
881 silc_free(server_name);
886 /* Server side of command WHOIS. Processes user's query and sends found
887 results as command replies back to the client. */
889 SILC_SERVER_CMD_FUNC(whois)
891 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
894 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3328);
896 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
897 ret = silc_server_command_whois_from_client(cmd);
898 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) ||
899 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
900 ret = silc_server_command_whois_from_server(cmd);
903 silc_server_command_free(cmd);
906 SILC_SERVER_CMD_FUNC(whowas)
910 /******************************************************************************
914 ******************************************************************************/
916 /* Checks that all mandatory fields are present. If not then send WHOIS
917 request to the server who owns the client. We use WHOIS because we want
918 to get as much information as possible at once. */
921 silc_server_command_identify_check(SilcServerCommandContext cmd,
922 SilcClientEntry *clients,
923 unsigned int clients_count)
925 SilcServer server = cmd->server;
927 SilcClientEntry entry;
929 for (i = 0; i < clients_count; i++) {
932 if (!entry->nickname) {
934 unsigned short old_ident;
939 old_ident = silc_command_get_ident(cmd->payload);
940 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
941 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
942 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
944 /* Send WHOIS request. We send WHOIS since we're doing the requesting
945 now anyway so make it a good one. */
946 silc_server_packet_send(server, entry->router->connection,
947 SILC_PACKET_COMMAND, cmd->packet->flags,
948 tmpbuf->data, tmpbuf->len, TRUE);
950 /* Reprocess this packet after received reply */
951 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
952 silc_command_get_ident(cmd->payload),
953 silc_server_command_destructor,
954 silc_server_command_identify,
955 silc_server_command_dup(cmd));
959 /* Put old data back to the Command Payload we just changed */
960 silc_command_set_ident(cmd->payload, old_ident);
961 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
963 silc_buffer_free(tmpbuf);
972 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
973 SilcClientEntry *clients,
974 unsigned int clients_count)
976 SilcServer server = cmd->server;
978 int i, count = 0, len;
979 SilcBuffer packet, idp;
980 SilcClientEntry entry;
981 SilcCommandStatus status;
982 unsigned short ident = silc_command_get_ident(cmd->payload);
984 status = SILC_STATUS_OK;
985 if (clients_count > 1)
986 status = SILC_STATUS_LIST_START;
988 for (i = 0; i < clients_count; i++) {
991 if (count && i - 1 == count)
994 if (clients_count > 2)
995 status = SILC_STATUS_LIST_ITEM;
997 if (clients_count > 1 && i == clients_count - 1)
998 status = SILC_STATUS_LIST_END;
1000 /* Send IDENTIFY reply */
1001 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
1002 tmp = silc_argument_get_first_arg(cmd->args, NULL);
1006 char nh[256], uh[256];
1007 SilcSocketConnection hsock;
1009 memset(uh, 0, sizeof(uh));
1010 memset(nh, 0, sizeof(nh));
1012 strncat(nh, entry->nickname, strlen(entry->nickname));
1013 if (!strchr(entry->nickname, '@')) {
1014 strncat(nh, "@", 1);
1015 len = entry->router ? strlen(entry->router->server_name) :
1016 strlen(server->server_name);
1017 strncat(nh, entry->router ? entry->router->server_name :
1018 server->server_name, len);
1021 if (!entry->username) {
1022 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1024 2, idp->data, idp->len,
1027 strncat(uh, entry->username, strlen(entry->username));
1028 if (!strchr(entry->username, '@')) {
1029 strncat(uh, "@", 1);
1030 hsock = (SilcSocketConnection)entry->connection;
1031 len = strlen(hsock->hostname);
1032 strncat(uh, hsock->hostname, len);
1035 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
1037 2, idp->data, idp->len,
1042 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1043 0, packet->data, packet->len, FALSE);
1045 silc_buffer_free(packet);
1046 silc_buffer_free(idp);
1052 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
1054 SilcServer server = cmd->server;
1055 char *nick = NULL, *server_name = NULL;
1056 int count = 0, clients_count = 0;
1057 SilcClientEntry *clients = NULL, entry;
1058 SilcClientID **client_id = NULL;
1059 unsigned int client_id_count = 0;
1062 /* Protocol dictates that we must always send the received IDENTIFY request
1063 to our router if we are normal server, so let's do it now unless we
1064 are standalone. We will not send any replies to the client until we
1065 have received reply from the router. */
1066 if (server->server_type == SILC_SERVER &&
1067 !cmd->pending && !server->standalone) {
1069 unsigned short old_ident;
1071 old_ident = silc_command_get_ident(cmd->payload);
1072 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
1073 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
1075 /* Send IDENTIFY command to our router */
1076 silc_server_packet_send(server, (SilcSocketConnection)
1077 server->router->connection,
1078 SILC_PACKET_COMMAND, cmd->packet->flags,
1079 tmpbuf->data, tmpbuf->len, TRUE);
1081 /* Reprocess this packet after received reply from router */
1082 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
1083 silc_command_get_ident(cmd->payload),
1084 silc_server_command_destructor,
1085 silc_server_command_identify,
1086 silc_server_command_dup(cmd));
1087 cmd->pending = TRUE;
1089 silc_command_set_ident(cmd->payload, old_ident);
1091 silc_buffer_free(tmpbuf);
1096 /* We are ready to process the command request. Let's search for the
1097 requested client and send reply to the requesting client. */
1099 /* Parse the IDENTIFY request */
1100 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1101 &nick, &server_name, &count,
1102 SILC_COMMAND_IDENTIFY))
1105 /* Get all clients matching that ID or nickname from local list */
1106 if (client_id_count) {
1107 /* Check all Client ID's received in the command packet */
1108 for (i = 0; i < client_id_count; i++) {
1109 entry = silc_idlist_find_client_by_id(server->local_list,
1110 client_id[i], NULL);
1112 clients = silc_realloc(clients, sizeof(*clients) *
1113 (clients_count + 1));
1114 clients[clients_count++] = entry;
1118 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1122 clients = silc_idlist_get_clients_by_hash(server->local_list,
1123 nick, server->md5hash,
1127 /* Check global list as well */
1129 if (client_id_count) {
1130 /* Check all Client ID's received in the command packet */
1131 for (i = 0; i < client_id_count; i++) {
1132 entry = silc_idlist_find_client_by_id(server->global_list,
1133 client_id[i], NULL);
1135 clients = silc_realloc(clients, sizeof(*clients) *
1136 (clients_count + 1));
1137 clients[clients_count++] = entry;
1141 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1145 clients = silc_idlist_get_clients_by_hash(server->global_list,
1146 nick, server->md5hash,
1152 /* Such a client really does not exist in the SILC network. */
1153 if (!client_id_count) {
1154 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1155 SILC_STATUS_ERR_NO_SUCH_NICK,
1156 3, nick, strlen(nick));
1158 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1159 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1160 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1161 2, idp->data, idp->len);
1162 silc_buffer_free(idp);
1167 /* Check that all mandatory fields are present and request those data
1168 from the server who owns the client if necessary. */
1169 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1174 /* Send the command reply to the client */
1175 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1178 if (client_id_count) {
1179 for (i = 0; i < client_id_count; i++)
1180 silc_free(client_id[i]);
1181 silc_free(client_id);
1188 silc_free(server_name);
1194 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1196 SilcServer server = cmd->server;
1197 char *nick = NULL, *server_name = NULL;
1198 int count = 0, clients_count = 0;
1199 SilcClientEntry *clients = NULL, entry;
1200 SilcClientID **client_id = NULL;
1201 unsigned int client_id_count = 0;
1204 /* Parse the IDENTIFY request */
1205 if (!silc_server_command_whois_parse(cmd, &client_id, &client_id_count,
1206 &nick, &server_name, &count,
1207 SILC_COMMAND_IDENTIFY))
1210 /* Process the command request. Let's search for the requested client and
1211 send reply to the requesting server. */
1213 if (client_id_count) {
1214 /* Check all Client ID's received in the command packet */
1215 for (i = 0; i < client_id_count; i++) {
1216 entry = silc_idlist_find_client_by_id(server->local_list,
1217 client_id[i], NULL);
1219 clients = silc_realloc(clients, sizeof(*clients) *
1220 (clients_count + 1));
1221 clients[clients_count++] = entry;
1225 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1229 clients = silc_idlist_get_clients_by_hash(server->local_list,
1230 nick, server->md5hash,
1234 /* If we are router we will check our global list as well. */
1235 if (!clients && server->server_type == SILC_ROUTER) {
1236 if (client_id_count) {
1237 /* Check all Client ID's received in the command packet */
1238 for (i = 0; i < client_id_count; i++) {
1239 entry = silc_idlist_find_client_by_id(server->global_list,
1240 client_id[i], NULL);
1242 clients = silc_realloc(clients, sizeof(*clients) *
1243 (clients_count + 1));
1244 clients[clients_count++] = entry;
1248 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1252 clients = silc_idlist_get_clients_by_hash(server->global_list,
1253 nick, server->md5hash,
1259 /* Such a client really does not exist in the SILC network. */
1260 if (!client_id_count) {
1261 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1262 SILC_STATUS_ERR_NO_SUCH_NICK,
1263 3, nick, strlen(nick));
1265 SilcBuffer idp = silc_id_payload_encode(client_id[0], SILC_ID_CLIENT);
1266 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1267 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1268 2, idp->data, idp->len);
1269 silc_buffer_free(idp);
1274 /* Check that all mandatory fields are present and request those data
1275 from the server who owns the client if necessary. */
1276 if (!silc_server_command_identify_check(cmd, clients, clients_count)) {
1281 /* Send the command reply */
1282 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1285 if (client_id_count) {
1286 for (i = 0; i < client_id_count; i++)
1287 silc_free(client_id[i]);
1288 silc_free(client_id);
1295 silc_free(server_name);
1300 SILC_SERVER_CMD_FUNC(identify)
1302 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1305 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3328);
1307 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1308 ret = silc_server_command_identify_from_client(cmd);
1309 else if ((cmd->sock->type == SILC_SOCKET_TYPE_SERVER) |
1310 (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER))
1311 ret = silc_server_command_identify_from_server(cmd);
1314 silc_server_command_free(cmd);
1317 /* Checks string for bad characters and returns TRUE if they are found. */
1319 static int silc_server_command_bad_chars(char *nick)
1321 if (strchr(nick, '\\')) return TRUE;
1322 if (strchr(nick, '\"')) return TRUE;
1323 if (strchr(nick, '´')) return TRUE;
1324 if (strchr(nick, '`')) return TRUE;
1325 if (strchr(nick, '\'')) return TRUE;
1326 if (strchr(nick, '*')) return TRUE;
1327 if (strchr(nick, '/')) return TRUE;
1328 if (strchr(nick, '@')) return TRUE;
1333 /* Server side of command NICK. Sets nickname for user. Setting
1334 nickname causes generation of a new client ID for the client. The
1335 new client ID is sent to the client after changing the nickname. */
1337 SILC_SERVER_CMD_FUNC(nick)
1339 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1340 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1341 SilcServer server = cmd->server;
1342 SilcBuffer packet, nidp, oidp;
1343 SilcClientID *new_id;
1346 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1349 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1351 /* Check nickname */
1352 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1353 if (silc_server_command_bad_chars(nick) == TRUE) {
1354 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1355 SILC_STATUS_ERR_BAD_NICKNAME);
1359 if (strlen(nick) > 128)
1362 /* Create new Client ID */
1363 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1364 cmd->server->md5hash, nick,
1367 /* Send notify about nickname change to our router. We send the new
1368 ID and ask to replace it with the old one. If we are router the
1369 packet is broadcasted. Send NICK_CHANGE notify. */
1370 if (!server->standalone)
1371 silc_server_send_notify_nick_change(server, server->router->connection,
1372 server->server_type == SILC_SERVER ?
1373 FALSE : TRUE, client->id,
1374 new_id, SILC_ID_CLIENT_LEN);
1376 /* Remove old cache entry */
1377 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1380 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1384 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1385 silc_free(client->id);
1388 /* Save the nickname as this client is our local client */
1389 if (client->nickname)
1390 silc_free(client->nickname);
1392 client->nickname = strdup(nick);
1393 client->id = new_id;
1395 /* Update client cache */
1396 silc_idcache_add(server->local_list->clients, client->nickname,
1397 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1399 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1401 /* Send NICK_CHANGE notify to the client's channels */
1402 silc_server_send_notify_on_channels(server, client,
1403 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1404 oidp->data, oidp->len,
1405 nidp->data, nidp->len);
1407 /* Send the new Client ID as reply command back to client */
1408 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1409 SILC_STATUS_OK, 0, 1,
1410 2, nidp->data, nidp->len);
1411 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1412 0, packet->data, packet->len, FALSE);
1414 silc_buffer_free(packet);
1415 silc_buffer_free(nidp);
1416 silc_buffer_free(oidp);
1419 silc_server_command_free(cmd);
1422 SILC_SERVER_CMD_FUNC(list)
1426 /* Server side of TOPIC command. Sets topic for channel and/or returns
1427 current topic to client. */
1429 SILC_SERVER_CMD_FUNC(topic)
1431 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1432 SilcServer server = cmd->server;
1433 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1434 SilcChannelID *channel_id;
1435 SilcChannelEntry channel;
1436 SilcChannelClientEntry chl;
1437 SilcBuffer packet, idp;
1439 unsigned int argc, tmp_len;
1441 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1443 argc = silc_argument_get_arg_num(cmd->args);
1445 /* Get Channel ID */
1446 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1448 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1449 SILC_STATUS_ERR_NO_CHANNEL_ID);
1452 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1454 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1455 SILC_STATUS_ERR_NO_CHANNEL_ID);
1459 /* Check whether the channel exists */
1460 channel = silc_idlist_find_channel_by_id(server->local_list,
1463 channel = silc_idlist_find_channel_by_id(server->global_list,
1466 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1467 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1474 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1476 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1477 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1481 if (strlen(tmp) > 256) {
1482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1483 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1487 /* See whether has rights to change topic */
1488 silc_list_start(channel->user_list);
1489 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1490 if (chl->client == client)
1493 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1494 if (channel->mode & SILC_CHANNEL_MODE_TOPIC) {
1495 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1496 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1501 /* Set the topic for channel */
1503 silc_free(channel->topic);
1504 channel->topic = strdup(tmp);
1506 /* Send TOPIC_SET notify type to the network */
1507 if (!server->standalone)
1508 silc_server_send_notify_topic_set(server, server->router->connection,
1509 server->server_type == SILC_ROUTER ?
1510 TRUE : FALSE, channel, client->id,
1511 SILC_ID_CLIENT_LEN, channel->topic);
1513 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1515 /* Send notify about topic change to all clients on the channel */
1516 silc_server_send_notify_to_channel(server, NULL, channel, TRUE,
1517 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1518 idp->data, idp->len,
1519 channel->topic, strlen(channel->topic));
1520 silc_buffer_free(idp);
1523 /* Send the topic to client as reply packet */
1524 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1526 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1527 SILC_STATUS_OK, 0, 2,
1528 2, idp->data, idp->len,
1530 strlen(channel->topic));
1532 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1533 SILC_STATUS_OK, 0, 1,
1534 2, idp->data, idp->len);
1535 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1536 0, packet->data, packet->len, FALSE);
1538 silc_buffer_free(packet);
1539 silc_buffer_free(idp);
1540 silc_free(channel_id);
1543 silc_server_command_free(cmd);
1546 /* Server side of INVITE command. Invites some client to join some channel. */
1548 SILC_SERVER_CMD_FUNC(invite)
1550 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1551 SilcServer server = cmd->server;
1552 SilcSocketConnection sock = cmd->sock, dest_sock;
1553 SilcClientEntry sender, dest;
1554 SilcClientID *dest_id;
1555 SilcChannelEntry channel;
1556 SilcChannelID *channel_id;
1561 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1563 /* Get destination ID */
1564 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1567 SILC_STATUS_ERR_NO_CLIENT_ID);
1570 dest_id = silc_id_payload_parse_id(tmp, len);
1572 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1573 SILC_STATUS_ERR_NO_CLIENT_ID);
1577 /* Get Channel ID */
1578 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1581 SILC_STATUS_ERR_NO_CHANNEL_ID);
1584 channel_id = silc_id_payload_parse_id(tmp, len);
1586 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1587 SILC_STATUS_ERR_NO_CHANNEL_ID);
1591 /* Check whether the channel exists */
1592 channel = silc_idlist_find_channel_by_id(server->local_list,
1595 channel = silc_idlist_find_channel_by_id(server->global_list,
1598 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1599 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1604 /* Check whether the sender of this command is on the channel. */
1605 sender = (SilcClientEntry)sock->user_data;
1606 if (!silc_server_client_on_channel(sender, channel)) {
1607 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1608 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1612 /* Check whether the channel is invite-only channel. If yes then the
1613 sender of this command must be at least channel operator. */
1614 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1615 SilcChannelClientEntry chl;
1617 silc_list_start(channel->user_list);
1618 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1619 if (chl->client == sender) {
1620 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1621 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1622 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1629 /* Find the connection data for the destination. If it is local we will
1630 send it directly otherwise we will send it to router for routing. */
1631 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1633 dest_sock = (SilcSocketConnection)dest->connection;
1635 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1637 /* Check whether the requested client is already on the channel. */
1638 /* XXX if we are normal server we don't know about global clients on
1639 the channel thus we must request it (USERS command), check from
1640 local cache as well. */
1641 if (silc_server_client_on_channel(dest, channel)) {
1642 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1643 SILC_STATUS_ERR_USER_ON_CHANNEL);
1647 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1649 /* Send notify to the client that is invited to the channel */
1650 silc_server_send_notify_dest(server, dest_sock, FALSE, dest_id,
1652 SILC_NOTIFY_TYPE_INVITE, 2,
1653 sidp->data, sidp->len, tmp, len);
1655 /* Send command reply */
1656 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1659 silc_buffer_free(sidp);
1662 silc_server_command_free(cmd);
1667 SilcSocketConnection sock;
1671 /* Quits connection to client. This gets called if client won't
1672 close the connection even when it has issued QUIT command. */
1674 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1676 QuitInternal q = (QuitInternal)context;
1678 /* Free all client specific data, such as client entry and entires
1679 on channels this client may be on. */
1680 silc_server_free_client_data(q->server, q->sock, q->sock->user_data,
1682 q->sock->user_data = NULL;
1684 /* Close the connection on our side */
1685 silc_server_close_connection(q->server, q->sock);
1687 silc_free(q->signoff);
1691 /* Quits SILC session. This is the normal way to disconnect client. */
1693 SILC_SERVER_CMD_FUNC(quit)
1695 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1696 SilcServer server = cmd->server;
1697 SilcSocketConnection sock = cmd->sock;
1699 unsigned char *tmp = NULL;
1700 unsigned int len = 0;
1702 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_QUIT, cmd, 0, 1);
1704 if (cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
1707 /* Get destination ID */
1708 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1712 q = silc_calloc(1, sizeof(*q));
1715 q->signoff = tmp ? strdup(tmp) : NULL;
1717 /* We quit the connection with little timeout */
1718 silc_task_register(server->timeout_queue, sock->sock,
1719 silc_server_command_quit_cb, (void *)q,
1720 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1723 silc_server_command_free(cmd);
1726 SILC_SERVER_CMD_FUNC(kill)
1730 /* Server side of command INFO. This sends information about us to
1731 the client. If client requested specific server we will send the
1732 command to that server. */
1734 SILC_SERVER_CMD_FUNC(info)
1736 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1737 SilcServer server = cmd->server;
1738 SilcBuffer packet, idp;
1739 char info_string[256], *dest_server;
1741 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1743 /* Get server name */
1744 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1746 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1747 SILC_STATUS_ERR_NO_SUCH_SERVER);
1751 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1752 /* Send our reply */
1753 memset(info_string, 0, sizeof(info_string));
1754 snprintf(info_string, sizeof(info_string),
1755 "location: %s server: %s admin: %s <%s>",
1756 server->config->admin_info->location,
1757 server->config->admin_info->server_type,
1758 server->config->admin_info->admin_name,
1759 server->config->admin_info->admin_email);
1761 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1763 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1764 SILC_STATUS_OK, 0, 2,
1765 2, idp->data, idp->len,
1767 strlen(info_string));
1768 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1769 packet->data, packet->len, FALSE);
1771 silc_buffer_free(packet);
1772 silc_buffer_free(idp);
1774 /* Send this command to the requested server */
1776 if (server->server_type == SILC_SERVER && !server->standalone) {
1780 if (server->server_type == SILC_ROUTER) {
1786 silc_server_command_free(cmd);
1789 /* Server side of command PING. This just replies to the ping. */
1791 SILC_SERVER_CMD_FUNC(ping)
1793 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1794 SilcServer server = cmd->server;
1799 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1802 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1804 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1805 SILC_STATUS_ERR_NO_SERVER_ID);
1808 id = silc_id_str2id(tmp, len, SILC_ID_SERVER);
1812 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1813 /* Send our reply */
1814 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1818 SILC_STATUS_ERR_NO_SUCH_SERVER);
1825 silc_server_command_free(cmd);
1828 /* Internal routine to join channel. The channel sent to this function
1829 has been either created or resolved from ID lists. This joins the sent
1830 client to the channel. */
1832 static void silc_server_command_join_channel(SilcServer server,
1833 SilcServerCommandContext cmd,
1834 SilcChannelEntry channel,
1835 SilcClientID *client_id,
1839 SilcSocketConnection sock = cmd->sock;
1841 unsigned int tmp_len, user_count;
1842 unsigned char *passphrase = NULL, mode[4], tmp2[4], tmp3[4];
1843 SilcClientEntry client;
1844 SilcChannelClientEntry chl;
1845 SilcBuffer reply, chidp, clidp, keyp, user_list, mode_list;
1846 unsigned short ident = silc_command_get_ident(cmd->payload);
1848 SILC_LOG_DEBUG(("Start"));
1853 /* Get passphrase */
1854 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1856 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1857 memcpy(passphrase, tmp, tmp_len);
1861 * Check channel modes
1864 /* Check invite list if channel is invite-only channel */
1865 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1866 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1867 /* Invite list is specified. Check whether client is invited in the
1868 list. If not, then check whether it has been invited otherwise. */
1871 /* XXX client must be invited to be able to join the channel */
1875 /* Check ban list if set */
1876 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1880 /* Check the channel passphrase if set. */
1881 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1882 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1883 strlen(channel->mode_data.passphrase))) {
1884 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1885 SILC_STATUS_ERR_BAD_PASSWORD);
1890 /* Check user count limit if set. */
1891 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1892 if (silc_list_count(channel->user_list) + 1 >
1893 channel->mode_data.user_limit) {
1894 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1895 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1901 * Client is allowed to join to the channel. Make it happen.
1904 /* Get the client entry */
1905 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1906 client = (SilcClientEntry)sock->user_data;
1908 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1911 /* XXX actually this is useless since router finds always cell's
1912 local clients from its local lists. */
1913 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1920 /* Check whether the client already is on the channel */
1921 if (silc_server_client_on_channel(client, channel)) {
1922 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1923 SILC_STATUS_ERR_USER_ON_CHANNEL);
1927 /* Generate new channel key as protocol dictates */
1928 if ((!created && silc_list_count(channel->user_list) > 0) ||
1929 !channel->channel_key)
1930 silc_server_create_channel_key(server, channel, 0);
1932 /* Send the channel key. This is broadcasted to the channel but is not
1933 sent to the client who is joining to the channel. */
1934 silc_server_send_channel_key(server, NULL, channel,
1935 server->server_type == SILC_ROUTER ?
1936 FALSE : !server->standalone);
1938 /* Join the client to the channel by adding it to channel's user list.
1939 Add also the channel to client entry's channels list for fast cross-
1941 chl = silc_calloc(1, sizeof(*chl));
1943 chl->client = client;
1944 chl->channel = channel;
1945 silc_list_add(channel->user_list, chl);
1946 silc_list_add(client->channels, chl);
1948 /* Get users on the channel */
1949 silc_server_get_users_on_channel(server, channel, &user_list, &mode_list,
1952 /* Encode Client ID Payload of the original client who wants to join */
1953 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1955 /* Encode command reply packet */
1956 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1957 SILC_PUT32_MSB(channel->mode, mode);
1958 SILC_PUT32_MSB(created, tmp2);
1959 SILC_PUT32_MSB(user_count, tmp3);
1960 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1961 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1962 strlen(channel->channel_key->
1964 channel->channel_key->cipher->name,
1965 channel->key_len / 8, channel->key);
1967 if (!channel->topic) {
1969 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1970 SILC_STATUS_OK, ident, 9,
1971 2, channel->channel_name,
1972 strlen(channel->channel_name),
1973 3, chidp->data, chidp->len,
1974 4, clidp->data, clidp->len,
1977 7, keyp->data, keyp->len,
1979 13, user_list->data, user_list->len,
1980 14, mode_list->data,
1984 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1985 SILC_STATUS_OK, ident, 10,
1986 2, channel->channel_name,
1987 strlen(channel->channel_name),
1988 3, chidp->data, chidp->len,
1989 4, clidp->data, clidp->len,
1992 7, keyp->data, keyp->len,
1994 strlen(channel->topic),
1996 13, user_list->data, user_list->len,
1997 14, mode_list->data,
2001 /* Send command reply */
2002 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
2003 reply->data, reply->len, FALSE);
2005 if (!cmd->pending) {
2006 /* Send JOIN notify to locally connected clients on the channel */
2007 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2008 SILC_NOTIFY_TYPE_JOIN, 2,
2009 clidp->data, clidp->len,
2010 chidp->data, chidp->len);
2012 /* Send JOIN notify packet to our primary router */
2013 if (!server->standalone)
2014 silc_server_send_notify_join(server, server->router->connection,
2015 server->server_type == SILC_ROUTER ?
2016 TRUE : FALSE, channel, client->id,
2017 SILC_ID_CLIENT_LEN);
2020 silc_buffer_free(reply);
2021 silc_buffer_free(clidp);
2022 silc_buffer_free(chidp);
2023 silc_buffer_free(keyp);
2024 silc_buffer_free(user_list);
2025 silc_buffer_free(mode_list);
2029 silc_free(passphrase);
2032 /* Server side of command JOIN. Joins client into requested channel. If
2033 the channel does not exist it will be created. */
2035 SILC_SERVER_CMD_FUNC(join)
2037 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2038 SilcServer server = cmd->server;
2040 char *tmp, *channel_name = NULL, *cipher, *hmac;
2041 SilcChannelEntry channel;
2042 unsigned int umode = 0;
2043 int created = FALSE;
2044 SilcClientID *client_id;
2046 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
2048 /* Get channel name */
2049 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2051 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2052 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2057 if (strlen(channel_name) > 256)
2058 channel_name[255] = '\0';
2060 if (silc_server_command_bad_chars(channel_name) == TRUE) {
2061 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2062 SILC_STATUS_ERR_BAD_CHANNEL);
2063 silc_free(channel_name);
2067 /* Get Client ID of the client who is joining to the channel */
2068 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2070 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2071 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2074 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2076 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2077 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2081 /* Get cipher and hmac name */
2082 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
2083 hmac = silc_argument_get_arg_type(cmd->args, 5, NULL);
2085 /* See if the channel exists */
2086 channel = silc_idlist_find_channel_by_name(server->local_list,
2087 channel_name, NULL);
2089 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2090 /* If this is coming from client the Client ID in the command packet must
2091 be same as the client's ID. */
2092 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
2093 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
2094 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
2095 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
2096 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2102 /* Channel not found */
2104 /* If we are standalone server we don't have a router, we just create
2105 the channel by ourselves. */
2106 if (server->standalone) {
2107 channel = silc_server_create_new_channel(server, server->id, cipher,
2108 hmac, channel_name, TRUE);
2109 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2114 /* The channel does not exist on our server. If we are normal server
2115 we will send JOIN command to our router which will handle the
2116 joining procedure (either creates the channel if it doesn't exist
2117 or joins the client to it). */
2118 if (server->server_type == SILC_SERVER) {
2120 unsigned short old_ident;
2122 old_ident = silc_command_get_ident(cmd->payload);
2123 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2124 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2126 /* Send JOIN command to our router */
2127 silc_server_packet_send(server, (SilcSocketConnection)
2128 server->router->connection,
2129 SILC_PACKET_COMMAND, cmd->packet->flags,
2130 tmpbuf->data, tmpbuf->len, TRUE);
2132 /* Reprocess this packet after received reply from router */
2133 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2134 silc_command_get_ident(cmd->payload),
2135 silc_server_command_destructor,
2136 silc_server_command_join,
2137 silc_server_command_dup(cmd));
2138 cmd->pending = TRUE;
2142 /* We are router and the channel does not seem exist so we will check
2143 our global list as well for the channel. */
2144 channel = silc_idlist_find_channel_by_name(server->global_list,
2145 channel_name, NULL);
2147 /* Channel really does not exist, create it */
2148 channel = silc_server_create_new_channel(server, server->id, cipher,
2149 hmac, channel_name, TRUE);
2150 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2157 /* Channel not found */
2159 /* If the command came from router and/or we are normal server then
2160 something went wrong with the joining as the channel was not found.
2161 We can't do anything else but ignore this. */
2162 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2163 server->server_type == SILC_SERVER)
2166 /* We are router and the channel does not seem exist so we will check
2167 our global list as well for the channel. */
2168 channel = silc_idlist_find_channel_by_name(server->global_list,
2169 channel_name, NULL);
2171 /* Channel really does not exist, create it */
2172 channel = silc_server_create_new_channel(server, server->id, cipher,
2173 hmac, channel_name, TRUE);
2174 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2180 /* If the channel does not have global users and is also empty it means the
2181 channel was created globally (by our router) and the client will be the
2182 channel founder and operator. */
2183 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2184 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2185 created = TRUE; /* Created globally by our router */
2188 /* Join to the channel */
2189 silc_server_command_join_channel(server, cmd, channel, client_id,
2192 silc_free(client_id);
2195 silc_server_command_free(cmd);
2198 /* Server side of command MOTD. Sends server's current "message of the
2199 day" to the client. */
2201 SILC_SERVER_CMD_FUNC(motd)
2203 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2204 SilcServer server = cmd->server;
2208 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2210 /* XXX show currently only our motd */
2212 if (server->config && server->config->motd &&
2213 server->config->motd->motd_file) {
2216 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2221 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2227 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2232 silc_server_command_free(cmd);
2235 SILC_SERVER_CMD_FUNC(umode)
2239 /* Checks that client has rights to add or remove channel modes. If any
2240 of the checks fails FALSE is returned. */
2242 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2243 SilcChannelClientEntry client,
2246 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2247 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2249 /* Check whether has rights to change anything */
2250 if (!is_op && !is_fo)
2253 /* Check whether has rights to change everything */
2257 /* We know that client is channel operator, check that they are not
2258 changing anything that requires channel founder rights. Rest of the
2259 modes are available automatically for channel operator. */
2261 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2262 if (is_op && !is_fo)
2265 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2266 if (is_op && !is_fo)
2271 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2272 if (is_op && !is_fo)
2275 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2276 if (is_op && !is_fo)
2281 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2282 if (is_op && !is_fo)
2285 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2286 if (is_op && !is_fo)
2294 /* Server side command of CMODE. Changes channel mode */
2296 SILC_SERVER_CMD_FUNC(cmode)
2298 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2299 SilcServer server = cmd->server;
2300 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2301 SilcChannelID *channel_id;
2302 SilcChannelEntry channel;
2303 SilcChannelClientEntry chl;
2304 SilcBuffer packet, cidp;
2305 unsigned char *tmp, *tmp_id, *tmp_mask;
2306 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2308 SILC_LOG_DEBUG(("Start"));
2310 argc = silc_argument_get_arg_num(cmd->args);
2312 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2313 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2317 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2318 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2322 /* Get Channel ID */
2323 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2325 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2326 SILC_STATUS_ERR_NO_CHANNEL_ID);
2329 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2331 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2332 SILC_STATUS_ERR_NO_CHANNEL_ID);
2336 /* Get the channel mode mask */
2337 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2339 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2340 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2343 SILC_GET32_MSB(mode_mask, tmp_mask);
2345 /* Get channel entry */
2346 channel = silc_idlist_find_channel_by_id(server->local_list,
2349 channel = silc_idlist_find_channel_by_id(server->global_list,
2352 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2353 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2358 /* Check whether this client is on the channel */
2359 if (!silc_server_client_on_channel(client, channel)) {
2360 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2361 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2365 /* Get entry to the channel user list */
2366 silc_list_start(channel->user_list);
2367 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2368 if (chl->client == client)
2371 /* Check that client has rights to change any requested channel modes */
2372 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2373 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2374 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2379 * Check the modes. Modes that requires nothing special operation are
2383 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2384 /* Channel uses private keys to protect traffic. Client(s) has set the
2385 key locally they want to use, server does not know that key. */
2386 /* Nothing interesting to do here now */
2388 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2389 /* The mode is removed and we need to generate and distribute
2390 new channel key. Clients are not using private channel keys
2391 anymore after this. */
2393 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2396 /* Re-generate channel key */
2397 silc_server_create_channel_key(server, channel, 0);
2399 /* Encode channel key payload to be distributed on the channel */
2401 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2402 strlen(channel->channel_key->
2404 channel->channel_key->cipher->name,
2405 channel->key_len / 8, channel->key);
2407 /* If we are normal server then we will send it to our router. If we
2408 are router we will send it to all local servers that has clients on
2410 if (server->server_type == SILC_SERVER) {
2411 if (!server->standalone)
2412 silc_server_packet_send(server,
2413 cmd->server->router->connection,
2414 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2420 /* Send to locally connected clients on the channel */
2421 silc_server_packet_send_local_channel(server, channel,
2422 SILC_PACKET_CHANNEL_KEY, 0,
2423 packet->data, packet->len, FALSE);
2424 silc_buffer_free(packet);
2428 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2429 /* User limit is set on channel */
2430 unsigned int user_limit;
2432 /* Get user limit */
2433 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2435 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2436 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2437 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2441 SILC_GET32_MSB(user_limit, tmp);
2442 channel->mode_data.user_limit = user_limit;
2445 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2446 /* User limit mode is unset. Remove user limit */
2447 channel->mode_data.user_limit = 0;
2450 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2451 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2452 /* Passphrase has been set to channel */
2454 /* Get the passphrase */
2455 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2457 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2458 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2462 /* Save the passphrase */
2463 channel->mode_data.passphrase = strdup(tmp);
2466 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2467 /* Passphrase mode is unset. remove the passphrase */
2468 if (channel->mode_data.passphrase) {
2469 silc_free(channel->mode_data.passphrase);
2470 channel->mode_data.passphrase = NULL;
2475 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2476 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2477 /* Ban list is specified for channel */
2480 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2482 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2483 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2487 /* XXX check that channel founder is not banned */
2489 /* Save the ban list */
2490 channel->mode_data.ban_list = strdup(tmp);
2493 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2494 /* Ban mode is unset. Remove the entire ban list */
2495 if (channel->mode_data.ban_list) {
2496 silc_free(channel->mode_data.ban_list);
2497 channel->mode_data.ban_list = NULL;
2502 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2503 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2504 /* Invite list is specified for channel */
2506 /* Get invite list */
2507 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2509 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2510 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2514 /* Save the invite linst */
2515 channel->mode_data.invite_list = strdup(tmp);
2518 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2519 /* Invite list mode is unset. Remove the entire invite list */
2520 if (channel->mode_data.invite_list) {
2521 silc_free(channel->mode_data.invite_list);
2522 channel->mode_data.invite_list = NULL;
2527 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2528 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2529 /* Cipher to use protect the traffic */
2530 unsigned int key_len;
2533 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2535 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2536 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2540 /* XXX Duplicated code, make own function for this!! */
2542 /* Delete old cipher and allocate the new one */
2543 silc_cipher_free(channel->channel_key);
2544 if (!silc_cipher_alloc(tmp, &channel->channel_key)) {
2545 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2546 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2549 key_len = silc_cipher_get_key_len(channel->channel_key) / 8;
2551 /* Re-generate channel key */
2552 silc_server_create_channel_key(server, channel, key_len);
2554 /* Encode channel key payload to be distributed on the channel */
2556 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2557 strlen(channel->channel_key->
2559 channel->channel_key->cipher->name,
2560 channel->key_len / 8, channel->key);
2562 /* If we are normal server then we will send it to our router. If we
2563 are router we will send it to all local servers that has clients on
2565 if (server->server_type == SILC_SERVER) {
2566 if (!server->standalone)
2567 silc_server_packet_send(server,
2568 cmd->server->router->connection,
2569 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2575 /* Send to locally connected clients on the channel */
2576 silc_server_packet_send_local_channel(server, channel,
2577 SILC_PACKET_CHANNEL_KEY, 0,
2578 packet->data, packet->len, FALSE);
2579 silc_buffer_free(packet);
2582 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2583 /* Cipher mode is unset. Remove the cipher and revert back to
2586 if (channel->mode_data.cipher) {
2587 silc_free(channel->mode_data.cipher);
2588 channel->mode_data.cipher = NULL;
2589 channel->mode_data.key_len = 0;
2592 /* Generate new cipher and key for the channel */
2594 /* XXX Duplicated code, make own function for this!! */
2596 /* Delete old cipher and allocate default one */
2597 silc_cipher_free(channel->channel_key);
2598 if (!channel->cipher)
2599 silc_cipher_alloc("aes-256-cbc", &channel->channel_key);
2601 if (!silc_cipher_alloc(channel->cipher, &channel->channel_key)) {
2602 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2603 SILC_STATUS_ERR_UNKNOWN_ALGORITHM);
2608 /* Re-generate channel key */
2609 silc_server_create_channel_key(server, channel, 0);
2611 /* Encode channel key payload to be distributed on the channel */
2613 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2614 strlen(channel->channel_key->
2616 channel->channel_key->cipher->name,
2617 channel->key_len / 8, channel->key);
2619 /* If we are normal server then we will send it to our router. If we
2620 are router we will send it to all local servers that has clients on
2622 if (server->server_type == SILC_SERVER) {
2623 if (!server->standalone)
2624 silc_server_packet_send(server,
2625 cmd->server->router->connection,
2626 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2632 /* Send to locally connected clients on the channel */
2633 silc_server_packet_send_local_channel(server, channel,
2634 SILC_PACKET_CHANNEL_KEY, 0,
2635 packet->data, packet->len, FALSE);
2636 silc_buffer_free(packet);
2640 /* Finally, set the mode */
2641 channel->mode = mode_mask;
2643 /* Send CMODE_CHANGE notify */
2644 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2645 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2646 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2647 cidp->data, cidp->len,
2650 /* Set CMODE notify type to network */
2651 if (!server->standalone)
2652 silc_server_send_notify_cmode(server, server->router->connection,
2653 server->server_type == SILC_ROUTER ?
2654 TRUE : FALSE, channel,
2655 mode_mask, client->id, SILC_ID_CLIENT_LEN);
2657 /* Send command reply to sender */
2658 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2659 SILC_STATUS_OK, 0, 1,
2661 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2662 packet->data, packet->len, FALSE);
2664 silc_buffer_free(packet);
2665 silc_free(channel_id);
2669 silc_server_command_free(cmd);
2672 /* Server side of CUMODE command. Changes client's mode on a channel. */
2674 SILC_SERVER_CMD_FUNC(cumode)
2676 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2677 SilcServer server = cmd->server;
2678 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2679 SilcChannelID *channel_id;
2680 SilcClientID *client_id;
2681 SilcChannelEntry channel;
2682 SilcClientEntry target_client;
2683 SilcChannelClientEntry chl;
2684 SilcBuffer packet, idp;
2685 unsigned char *tmp_id, *tmp_ch_id, *tmp_mask;
2686 unsigned int target_mask, sender_mask, tmp_len, tmp_ch_len;
2689 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2691 /* Get Channel ID */
2692 tmp_ch_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_ch_len);
2694 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2695 SILC_STATUS_ERR_NO_CHANNEL_ID);
2698 channel_id = silc_id_payload_parse_id(tmp_ch_id, tmp_ch_len);
2700 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2701 SILC_STATUS_ERR_NO_CHANNEL_ID);
2705 /* Get channel entry */
2706 channel = silc_idlist_find_channel_by_id(server->local_list,
2709 channel = silc_idlist_find_channel_by_id(server->global_list,
2712 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2713 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2718 /* Check whether sender is on the channel */
2719 if (!silc_server_client_on_channel(client, channel)) {
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2721 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2725 /* Check that client has rights to change other's rights */
2726 silc_list_start(channel->user_list);
2727 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2728 if (chl->client == client) {
2729 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2730 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2731 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2732 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2736 sender_mask = chl->mode;
2741 /* Get the target client's channel mode mask */
2742 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2744 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2745 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2748 SILC_GET32_MSB(target_mask, tmp_mask);
2750 /* Get target Client ID */
2751 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2753 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2754 SILC_STATUS_ERR_NO_CLIENT_ID);
2757 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2759 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2760 SILC_STATUS_ERR_NO_CLIENT_ID);
2764 /* Get target client's entry */
2765 target_client = silc_idlist_find_client_by_id(server->local_list,
2767 if (!target_client) {
2768 target_client = silc_idlist_find_client_by_id(server->global_list,
2772 /* Check whether target client is on the channel */
2773 if (!silc_server_client_on_channel(target_client, channel)) {
2774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2775 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2779 /* Get entry to the channel user list */
2780 silc_list_start(channel->user_list);
2781 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2782 if (chl->client == target_client)
2789 /* If the target client is founder, no one else can change their mode
2791 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2792 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2793 SILC_STATUS_ERR_NOT_YOU);
2797 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2798 /* Cannot promote anyone to channel founder */
2799 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2800 SILC_STATUS_ERR_NOT_YOU);
2803 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2804 if (target_client == client) {
2805 /* Remove channel founder rights from itself */
2806 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2809 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2810 SILC_STATUS_ERR_NOT_YOU);
2816 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2817 /* Promote to operator */
2818 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2819 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2823 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2824 /* Demote to normal user */
2825 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2830 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2832 /* Send notify to channel, notify only if mode was actually changed. */
2834 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2835 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2836 idp->data, idp->len,
2840 /* Set CUMODE notify type to network */
2841 if (!server->standalone)
2842 silc_server_send_notify_cumode(server, server->router->connection,
2843 server->server_type == SILC_ROUTER ?
2844 TRUE : FALSE, channel,
2845 target_mask, client->id,
2848 SILC_ID_CLIENT_LEN);
2851 /* Send command reply to sender */
2852 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2853 SILC_STATUS_OK, 0, 2,
2855 3, tmp_id, tmp_len);
2856 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2857 packet->data, packet->len, FALSE);
2859 silc_buffer_free(packet);
2860 silc_free(channel_id);
2861 silc_free(client_id);
2862 silc_buffer_free(idp);
2865 silc_server_command_free(cmd);
2868 /* Server side of KICK command. Kicks client out of channel. */
2870 SILC_SERVER_CMD_FUNC(kick)
2872 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2873 SilcServer server = cmd->server;
2874 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2875 SilcClientEntry target_client;
2876 SilcChannelID *channel_id;
2877 SilcClientID *client_id;
2878 SilcChannelEntry channel;
2879 SilcChannelClientEntry chl;
2881 unsigned int tmp_len;
2882 unsigned char *tmp, *comment;
2884 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 3);
2886 /* Get Channel ID */
2887 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2889 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2890 SILC_STATUS_ERR_NO_CHANNEL_ID);
2893 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
2895 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2896 SILC_STATUS_ERR_NO_CHANNEL_ID);
2900 /* Get channel entry */
2901 channel = silc_idlist_find_channel_by_id(server->local_list,
2904 channel = silc_idlist_find_channel_by_id(server->local_list,
2907 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2908 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2913 /* Check whether sender is on the channel */
2914 if (!silc_server_client_on_channel(client, channel)) {
2915 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2916 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2920 /* Check that the kicker is channel operator or channel founder */
2921 silc_list_start(channel->user_list);
2922 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2923 if (chl->client == client) {
2924 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
2925 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2926 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2933 /* Get target Client ID */
2934 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2937 SILC_STATUS_ERR_NO_CLIENT_ID);
2940 client_id = silc_id_payload_parse_id(tmp, tmp_len);
2942 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2943 SILC_STATUS_ERR_NO_CLIENT_ID);
2947 /* Get target client's entry */
2948 target_client = silc_idlist_find_client_by_id(server->local_list,
2950 if (!target_client) {
2951 target_client = silc_idlist_find_client_by_id(server->global_list,
2955 /* Check that the target client is not channel founder. Channel founder
2956 cannot be kicked from the channel. */
2957 silc_list_start(channel->user_list);
2958 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2959 if (chl->client == target_client) {
2960 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2961 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2962 SILC_STATUS_ERR_NO_CHANNEL_FOPRIV);
2969 /* Check whether target client is on the channel */
2970 if (!silc_server_client_on_channel(target_client, channel)) {
2971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2972 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2978 comment = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2982 /* Send command reply to sender */
2983 silc_server_command_send_status_reply(cmd, SILC_COMMAND_KICK,
2986 /* Send KICKED notify to local clients on the channel */
2987 idp = silc_id_payload_encode(target_client->id, SILC_ID_CLIENT);
2988 silc_server_send_notify_to_channel(server, NULL, channel, FALSE,
2989 SILC_NOTIFY_TYPE_KICKED,
2991 idp->data, idp->len,
2992 comment, comment ? strlen(comment) : 0);
2993 silc_buffer_free(idp);
2995 /* Remove the client from the channel. If the channel does not exist
2996 after removing the client then the client kicked itself of the channel
2997 and we don't have to send anything after that. */
2998 if (!silc_server_remove_from_one_channel(server, NULL, channel,
2999 target_client, FALSE))
3002 /* Send KICKED notify to primary route */
3003 if (!server->standalone)
3004 silc_server_send_notify_kicked(server, server->router->connection,
3005 server->server_type == SILC_ROUTER ?
3006 TRUE : FALSE, channel,
3007 target_client->id, SILC_ID_CLIENT_LEN,
3010 /* Re-generate channel key */
3011 silc_server_create_channel_key(server, channel, 0);
3013 /* Send the channel key to the channel. The key of course is not sent
3014 to the client who joined the channel. */
3015 silc_server_send_channel_key(server, target_client->connection, channel,
3016 server->server_type == SILC_ROUTER ?
3017 FALSE : !server->standalone);
3020 silc_server_command_free(cmd);
3023 SILC_SERVER_CMD_FUNC(oper)
3027 SILC_SERVER_CMD_FUNC(silcoper)
3031 /* Server side command of CONNECT. Connects us to the specified remote
3032 server or router. */
3034 SILC_SERVER_CMD_FUNC(connect)
3036 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3037 SilcServer server = cmd->server;
3038 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3040 unsigned int tmp_len;
3041 unsigned int port = SILC_PORT;
3043 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CONNECT, cmd, 1, 2);
3045 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3048 /* Check whether client has the permissions. */
3049 if (client->mode == SILC_UMODE_NONE) {
3050 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3051 SILC_STATUS_ERR_NO_SERVER_PRIV);
3055 if (server->server_type == SILC_ROUTER &&
3056 client->mode & SILC_UMODE_SERVER_OPERATOR) {
3057 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3058 SILC_STATUS_ERR_NO_ROUTER_PRIV);
3062 /* Get the remote server */
3063 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3065 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3066 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3071 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3073 SILC_GET32_MSB(port, tmp);
3075 /* Create the connection. It is done with timeout and is async. */
3076 silc_server_create_connection(server, tmp, port);
3078 /* Send reply to the sender */
3079 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CONNECT,
3083 silc_server_command_free(cmd);
3086 SILC_SERVER_CMD_FUNC(restart)
3090 /* Server side command of CLOSE. Closes connection to a specified server. */
3092 SILC_SERVER_CMD_FUNC(close)
3094 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3095 SilcServer server = cmd->server;
3096 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3097 SilcServerEntry server_entry;
3099 unsigned int tmp_len;
3100 unsigned char *name;
3101 unsigned int port = SILC_PORT;
3103 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CLOSE, cmd, 1, 2);
3105 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3108 /* Check whether client has the permissions. */
3109 if (client->mode == SILC_UMODE_NONE) {
3110 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3111 SILC_STATUS_ERR_NO_SERVER_PRIV);
3115 /* Get the remote server */
3116 name = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
3118 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3119 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
3124 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
3126 SILC_GET32_MSB(port, tmp);
3128 server_entry = silc_idlist_find_server_by_conn(server->local_list,
3130 if (!server_entry) {
3131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3132 SILC_STATUS_ERR_NO_SERVER_ID);
3136 /* Close the connection to the server */
3137 silc_server_free_sock_user_data(server, server_entry->connection);
3138 silc_server_disconnect_remote(server, server_entry->connection,
3139 "Server closed connection: "
3140 "Closed by operator");
3142 /* Send reply to the sender */
3143 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CLOSE,
3147 silc_server_command_free(cmd);
3150 /* Server side command of SHUTDOWN. Shutdowns the server and closes all
3151 active connections. */
3153 SILC_SERVER_CMD_FUNC(shutdown)
3155 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3156 SilcServer server = cmd->server;
3157 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
3159 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_SHUTDOWN, cmd, 0, 0);
3161 if (!client || cmd->sock->type != SILC_SOCKET_TYPE_CLIENT)
3164 /* Check whether client has the permission. */
3165 if (client->mode == SILC_UMODE_NONE) {
3166 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3167 SILC_STATUS_ERR_NO_SERVER_PRIV);
3171 /* Then, gracefully, or not, bring the server down. */
3172 silc_server_stop(server);
3174 /* Send reply to the sender */
3175 silc_server_command_send_status_reply(cmd, SILC_COMMAND_SHUTDOWN,
3179 silc_server_command_free(cmd);
3182 /* Server side command of LEAVE. Removes client from a channel. */
3184 SILC_SERVER_CMD_FUNC(leave)
3186 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3187 SilcServer server = cmd->server;
3188 SilcSocketConnection sock = cmd->sock;
3189 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
3191 SilcChannelEntry channel;
3193 unsigned int i, len;
3196 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
3198 /* Get Channel ID */
3199 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
3201 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3202 SILC_STATUS_ERR_NO_CHANNEL_ID);
3205 id = silc_id_payload_parse_id(tmp, len);
3207 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3208 SILC_STATUS_ERR_NO_CHANNEL_ID);
3212 /* Get channel entry */
3213 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3215 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3217 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3218 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3223 /* Check whether this client is on the channel */
3224 if (!silc_server_client_on_channel(id_entry, channel)) {
3225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3226 SILC_STATUS_ERR_NOT_ON_CHANNEL);
3230 /* Notify routers that they should remove this client from their list
3231 of clients on the channel. Send LEAVE notify type. */
3232 if (!server->standalone)
3233 silc_server_send_notify_leave(server, server->router->connection,
3234 server->server_type == SILC_ROUTER ?
3235 TRUE : FALSE, channel, id_entry->id,
3236 SILC_ID_CLIENT_LEN);
3238 /* Remove client from channel */
3239 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
3241 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
3244 /* If the channel does not exist anymore we won't send anything */
3248 /* Re-generate channel key */
3249 silc_server_create_channel_key(server, channel, 0);
3251 /* Encode channel key payload to be distributed on the channel */
3253 silc_channel_key_payload_encode(len, tmp,
3254 strlen(channel->channel_key->cipher->name),
3255 channel->channel_key->cipher->name,
3256 channel->key_len / 8, channel->key);
3258 /* If we are normal server then we will send it to our router. If we
3259 are router we will send it to all local servers that has clients on
3261 if (server->server_type == SILC_SERVER) {
3262 if (!server->standalone)
3263 silc_server_packet_send(server,
3264 cmd->server->router->connection,
3265 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
3266 packet->len, FALSE);
3271 /* Send to locally connected clients on the channel */
3272 silc_server_packet_send_local_channel(server, channel,
3273 SILC_PACKET_CHANNEL_KEY, 0,
3274 packet->data, packet->len, FALSE);
3276 silc_buffer_free(packet);
3280 silc_server_command_free(cmd);
3283 /* Server side of command USERS. Resolves clients and their USERS currently
3284 joined on the requested channel. The list of Client ID's and their modes
3285 on the channel is sent back. */
3287 SILC_SERVER_CMD_FUNC(users)
3289 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
3290 SilcServer server = cmd->server;
3291 SilcChannelEntry channel;
3294 unsigned char *channel_id;
3295 unsigned int channel_id_len;
3296 SilcBuffer client_id_list;
3297 SilcBuffer client_mode_list;
3298 unsigned char lc[4];
3299 unsigned int list_count = 0;
3300 unsigned short ident = silc_command_get_ident(cmd->payload);
3302 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_USERS, cmd, 1, 1);
3304 /* Get Channel ID */
3305 channel_id = silc_argument_get_arg_type(cmd->args, 1, &channel_id_len);
3307 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3308 SILC_STATUS_ERR_NO_CHANNEL_ID);
3311 id = silc_id_payload_parse_id(channel_id, channel_id_len);
3313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3314 SILC_STATUS_ERR_NO_CHANNEL_ID);
3318 /* If we are server and we don't know about this channel we will send
3319 the command to our router. If we know about the channel then we also
3320 have the list of users already. */
3321 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
3323 if (server->server_type == SILC_SERVER && !server->standalone &&
3327 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
3328 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
3330 /* Send USERS command */
3331 silc_server_packet_send(server, server->router->connection,
3332 SILC_PACKET_COMMAND, cmd->packet->flags,
3333 tmpbuf->data, tmpbuf->len, TRUE);
3335 /* Reprocess this packet after received reply */
3336 silc_server_command_pending(server, SILC_COMMAND_USERS,
3337 silc_command_get_ident(cmd->payload),
3338 silc_server_command_destructor,
3339 silc_server_command_users,
3340 silc_server_command_dup(cmd));
3341 cmd->pending = TRUE;
3342 silc_command_set_ident(cmd->payload, ident);
3344 silc_buffer_free(tmpbuf);
3349 /* We are router and we will check the global list as well. */
3350 channel = silc_idlist_find_channel_by_id(server->global_list, id, NULL);
3352 /* Channel really does not exist */
3353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_USERS,
3354 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
3359 /* Get the users list */
3360 silc_server_get_users_on_channel(server, channel, &client_id_list,
3361 &client_mode_list, &list_count);
3364 SILC_PUT32_MSB(list_count, lc);
3367 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_USERS,
3368 SILC_STATUS_OK, 0, 4,
3369 2, channel_id, channel_id_len,
3371 4, client_id_list->data,
3372 client_id_list->len,
3373 5, client_mode_list->data,
3374 client_mode_list->len);
3375 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
3376 packet->data, packet->len, FALSE);
3378 silc_buffer_free(packet);
3379 silc_buffer_free(client_id_list);
3380 silc_buffer_free(client_mode_list);
3384 silc_server_command_free(cmd);