5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 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 static void silc_server_command_free(SilcServerCommandContext cmd);
41 void silc_server_command_send_names(SilcServer server,
42 SilcSocketConnection sock,
43 SilcChannelEntry channel);
45 /* Server command list. */
46 SilcServerCommand silc_command_list[] =
48 SILC_SERVER_CMD(whois, WHOIS, SILC_CF_LAG | SILC_CF_REG),
49 SILC_SERVER_CMD(whowas, WHOWAS, SILC_CF_LAG | SILC_CF_REG),
50 SILC_SERVER_CMD(identify, IDENTIFY, SILC_CF_LAG | SILC_CF_REG),
51 SILC_SERVER_CMD(nick, NICK, SILC_CF_LAG | SILC_CF_REG),
52 SILC_SERVER_CMD(list, LIST, SILC_CF_LAG | SILC_CF_REG),
53 SILC_SERVER_CMD(topic, TOPIC, SILC_CF_LAG | SILC_CF_REG),
54 SILC_SERVER_CMD(invite, INVITE, SILC_CF_LAG | SILC_CF_REG),
55 SILC_SERVER_CMD(quit, QUIT, SILC_CF_LAG | SILC_CF_REG),
56 SILC_SERVER_CMD(kill, KILL, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
57 SILC_SERVER_CMD(info, INFO, SILC_CF_LAG | SILC_CF_REG),
58 SILC_SERVER_CMD(connect, CONNECT,
59 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
60 SILC_SERVER_CMD(ping, PING, SILC_CF_LAG | SILC_CF_REG),
61 SILC_SERVER_CMD(oper, OPER, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
62 SILC_SERVER_CMD(join, JOIN, SILC_CF_LAG | SILC_CF_REG),
63 SILC_SERVER_CMD(motd, MOTD, SILC_CF_LAG | SILC_CF_REG),
64 SILC_SERVER_CMD(umode, UMODE, SILC_CF_LAG | SILC_CF_REG),
65 SILC_SERVER_CMD(cmode, CMODE, SILC_CF_LAG | SILC_CF_REG),
66 SILC_SERVER_CMD(cumode, CUMODE, SILC_CF_LAG | SILC_CF_REG),
67 SILC_SERVER_CMD(kick, KICK, SILC_CF_LAG | SILC_CF_REG),
68 SILC_SERVER_CMD(restart, RESTART,
69 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
70 SILC_SERVER_CMD(close, CLOSE,
71 SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
72 SILC_SERVER_CMD(die, DIE, SILC_CF_LAG | SILC_CF_REG | SILC_CF_OPER),
73 SILC_SERVER_CMD(silcoper, SILCOPER,
74 SILC_CF_LAG | SILC_CF_REG | SILC_CF_SILC_OPER),
75 SILC_SERVER_CMD(leave, LEAVE, SILC_CF_LAG | SILC_CF_REG),
76 SILC_SERVER_CMD(names, NAMES, SILC_CF_LAG | SILC_CF_REG),
81 #define SILC_SERVER_COMMAND_CHECK_ARGC(command, context, min, max) \
83 unsigned int _argc = silc_argument_get_arg_num(cmd->args); \
85 SILC_LOG_DEBUG(("Start")); \
88 silc_server_command_send_status_reply(cmd, command, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, command, \
95 SILC_STATUS_ERR_TOO_MANY_PARAMS); \
96 silc_server_command_free(cmd); \
101 /* Returns TRUE if the connection is registered. Unregistered connections
102 usually cannot send commands hence the check. */
104 static int silc_server_is_registered(SilcServer server,
105 SilcSocketConnection sock,
106 SilcServerCommandContext cmd,
109 SilcIDListData idata = (SilcIDListData)sock->user_data;
110 if (idata->registered)
113 silc_server_command_send_status_reply(cmd, command,
114 SILC_STATUS_ERR_NOT_REGISTERED);
115 silc_server_command_free(cmd);
119 /* Processes received command packet. */
121 void silc_server_command_process(SilcServer server,
122 SilcSocketConnection sock,
123 SilcPacketContext *packet)
125 SilcServerCommandContext ctx;
126 SilcServerCommand *cmd;
129 /* XXX allow commands in but do not execute them more than once per
132 /* Check whether it is allowed for this connection to execute any
134 if (sock->type == SILC_SOCKET_TYPE_CLIENT) {
136 SilcClientEntry client = (SilcClientEntry)sock->user_data;
141 /* Allow only one command executed in 2 seconds. */
142 curtime = time(NULL);
143 if (client->last_command && (curtime - client->last_command) < 2)
146 /* Update access time */
147 client->last_command = curtime;
151 /* Allocate command context. This must be free'd by the
152 command routine receiving it. */
153 ctx = silc_calloc(1, sizeof(*ctx));
154 ctx->server = server;
156 ctx->packet = silc_packet_context_dup(packet); /* Save original packet */
158 /* Parse the command payload in the packet */
159 ctx->payload = silc_command_payload_parse(packet->buffer);
161 SILC_LOG_ERROR(("Bad command payload, packet dropped"));
162 silc_buffer_free(packet->buffer);
163 silc_packet_context_free(packet);
167 ctx->args = silc_command_get_args(ctx->payload);
169 /* Execute command. If this fails the packet is dropped. */
170 for (cmd = silc_command_list; cmd->cb; cmd++)
171 if (cmd->cmd == silc_command_get(ctx->payload)) {
173 if (!(cmd->flags & SILC_CF_REG)) {
178 if (silc_server_is_registered(server, sock, ctx, cmd->cmd)) {
185 SILC_LOG_ERROR(("Unknown command, packet dropped"));
186 silc_server_command_free(ctx);
191 /* Add new pending command to be executed when reply to a command has been
192 received. The `reply_cmd' is the command that will call the `callback'
193 with `context' when reply has been received. If `ident' is non-zero
194 the `callback' will be executed when received reply with command
195 identifier `ident'. */
197 void silc_server_command_pending(SilcServer server,
198 SilcCommand reply_cmd,
199 unsigned short ident,
200 SilcCommandCb callback,
203 SilcServerCommandPending *reply;
205 reply = silc_calloc(1, sizeof(*reply));
206 reply->reply_cmd = reply_cmd;
207 reply->ident = ident;
208 reply->context = context;
209 reply->callback = callback;
210 silc_dlist_add(server->pending_commands, reply);
213 /* Deletes pending command by reply command type. */
215 void silc_server_command_pending_del(SilcServer server,
216 SilcCommand reply_cmd,
217 unsigned short ident)
219 SilcServerCommandPending *r;
221 silc_dlist_start(server->pending_commands);
222 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
223 if (r->reply_cmd == reply_cmd && r->ident == ident) {
224 silc_dlist_del(server->pending_commands, r);
230 /* Checks for pending commands and marks callbacks to be called from
231 the command reply function. Returns TRUE if there were pending command. */
233 int silc_server_command_pending_check(SilcServer server,
234 SilcServerCommandReplyContext ctx,
236 unsigned short ident)
238 SilcServerCommandPending *r;
240 silc_dlist_start(server->pending_commands);
241 while ((r = silc_dlist_get(server->pending_commands)) != SILC_LIST_END) {
242 if (r->reply_cmd == command && r->ident == ident) {
243 ctx->context = r->context;
244 ctx->callback = r->callback;
253 /* Free's the command context allocated before executing the command */
255 static void silc_server_command_free(SilcServerCommandContext cmd)
259 silc_command_free_payload(cmd->payload);
261 silc_packet_context_free(cmd->packet);
266 /* Sends simple status message as command reply packet */
269 silc_server_command_send_status_reply(SilcServerCommandContext cmd,
271 SilcCommandStatus status)
275 SILC_LOG_DEBUG(("Sending command status %d", status));
277 buffer = silc_command_reply_payload_encode_va(command, status, 0, 0);
278 silc_server_packet_send(cmd->server, cmd->sock,
279 SILC_PACKET_COMMAND_REPLY, 0,
280 buffer->data, buffer->len, FALSE);
281 silc_buffer_free(buffer);
284 /* Sends command status reply with one extra argument. The argument
285 type must be sent as argument. */
288 silc_server_command_send_status_data(SilcServerCommandContext cmd,
290 SilcCommandStatus status,
291 unsigned int arg_type,
293 unsigned int arg_len)
297 SILC_LOG_DEBUG(("Sending command status %d", status));
299 buffer = silc_command_reply_payload_encode_va(command, status, 0, 1,
300 arg_type, arg, arg_len);
301 silc_server_packet_send(cmd->server, cmd->sock,
302 SILC_PACKET_COMMAND_REPLY, 0,
303 buffer->data, buffer->len, FALSE);
304 silc_buffer_free(buffer);
307 /******************************************************************************
311 ******************************************************************************/
314 silc_server_command_whois_parse(SilcServerCommandContext cmd,
315 SilcClientID **client_id,
322 unsigned int argc = silc_argument_get_arg_num(cmd->args);
324 /* If client ID is in the command it must be used instead of nickname */
325 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
327 /* No ID, get the nickname@server string and parse it. */
328 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
330 if (strchr(tmp, '@')) {
331 len = strcspn(tmp, "@");
332 *nickname = silc_calloc(len + 1, sizeof(char));
333 memcpy(*nickname, tmp, len);
334 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
335 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
337 *nickname = strdup(tmp);
340 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
341 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
345 /* Command includes ID, use that */
346 *client_id = silc_id_payload_parse_id(tmp, len);
349 /* Get the max count of reply messages allowed */
351 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS,
354 SILC_STATUS_ERR_TOO_MANY_PARAMS);
356 silc_free(*nickname);
358 silc_free(*server_name);
369 silc_server_command_whois_check(SilcServerCommandContext cmd,
370 SilcClientEntry *clients,
371 unsigned int clients_count)
373 SilcServer server = cmd->server;
375 SilcClientEntry entry;
377 for (i = 0; i < clients_count; i++) {
380 if (!entry->nickname || !entry->username || !entry->userinfo) {
382 unsigned short old_ident;
384 old_ident = silc_command_get_ident(cmd->payload);
385 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
386 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
388 /* Send WHOIS command */
389 silc_server_packet_send(server, entry->router->connection,
390 SILC_PACKET_COMMAND, cmd->packet->flags,
391 tmpbuf->data, tmpbuf->len, TRUE);
393 /* Reprocess this packet after received reply */
394 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
395 silc_command_get_ident(cmd->payload),
396 silc_server_command_whois, (void *)cmd);
399 silc_command_set_ident(cmd->payload, old_ident);
401 silc_buffer_free(tmpbuf);
410 silc_server_command_whois_send_reply(SilcServerCommandContext cmd,
411 SilcClientEntry *clients,
412 unsigned int clients_count)
414 SilcServer server = cmd->server;
416 int i, count = 0, len;
417 SilcBuffer packet, idp;
418 SilcClientEntry entry;
419 SilcCommandStatus status;
420 unsigned short ident = silc_command_get_ident(cmd->payload);
422 status = SILC_STATUS_OK;
423 if (clients_count > 1)
424 status = SILC_STATUS_LIST_START;
426 for (i = 0; i < clients_count; i++) {
429 if (count && i - 1 == count)
432 if (clients_count > 2)
433 status = SILC_STATUS_LIST_ITEM;
435 if (clients_count > 1 && i == clients_count - 1)
436 status = SILC_STATUS_LIST_END;
438 /* Send WHOIS reply */
439 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
440 tmp = silc_argument_get_first_arg(cmd->args, NULL);
444 char nh[256], uh[256];
445 unsigned char idle[4];
446 SilcSocketConnection hsock;
448 memset(uh, 0, sizeof(uh));
449 memset(nh, 0, sizeof(nh));
451 strncat(nh, entry->nickname, strlen(entry->nickname));
452 if (!strchr(entry->nickname, '@')) {
454 len = entry->router ? strlen(entry->router->server_name) :
455 strlen(server->server_name);
456 strncat(nh, entry->router ? entry->router->server_name :
457 server->server_name, len);
460 strncat(uh, entry->username, strlen(entry->username));
461 if (!strchr(entry->username, '@')) {
463 hsock = (SilcSocketConnection)entry->connection;
464 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
465 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
468 SILC_PUT32_MSB((time(NULL) - entry->data.last_receive), idle);
473 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
475 2, idp->data, idp->len,
479 strlen(entry->userinfo),
483 silc_command_reply_payload_encode_va(SILC_COMMAND_WHOIS,
485 2, idp->data, idp->len,
491 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
492 0, packet->data, packet->len, FALSE);
494 silc_buffer_free(packet);
495 silc_buffer_free(idp);
500 silc_server_command_whois_from_client(SilcServerCommandContext cmd)
502 SilcServer server = cmd->server;
503 char *nick = NULL, *server_name = NULL;
504 int count = 0, clients_count;
505 SilcClientID *client_id = NULL;
506 SilcClientEntry *clients = NULL, entry;
509 /* Parse the whois request */
510 if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
511 &server_name, &count))
514 /* Protocol dictates that we must always send the received WHOIS request
515 to our router if we are normal server, so let's do it now unless we
516 are standalone. We will not send any replies to the client until we
517 have received reply from the router. */
518 if (server->server_type == SILC_SERVER &&
519 !cmd->pending && !server->standalone) {
521 unsigned short old_ident;
523 old_ident = silc_command_get_ident(cmd->payload);
524 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
525 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
527 /* Send WHOIS command to our router */
528 silc_server_packet_send(server, (SilcSocketConnection)
529 server->router->connection,
530 SILC_PACKET_COMMAND, cmd->packet->flags,
531 tmpbuf->data, tmpbuf->len, TRUE);
533 /* Reprocess this packet after received reply from router */
534 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
535 silc_command_get_ident(cmd->payload),
536 silc_server_command_whois, (void *)cmd);
539 silc_command_set_ident(cmd->payload, old_ident);
541 silc_buffer_free(tmpbuf);
546 /* We are ready to process the command request. Let's search for the
547 requested client and send reply to the requesting client. */
549 /* Get all clients matching that ID or nickname from local list */
551 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
553 clients = silc_calloc(1, sizeof(*clients));
558 clients = silc_idlist_get_clients_by_nickname(server->local_list,
563 /* Check global list as well */
566 entry = silc_idlist_find_client_by_id(server->global_list,
569 clients = silc_calloc(1, sizeof(*clients));
574 clients = silc_idlist_get_clients_by_nickname(server->global_list,
581 /* Such a client really does not exist in the SILC network. */
582 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
583 SILC_STATUS_ERR_NO_SUCH_NICK,
584 3, nick, strlen(nick));
588 /* Router always finds the client entry if it exists in the SILC network.
589 However, it might be incomplete entry and does not include all the
590 mandatory fields that WHOIS command reply requires. Check for these and
591 make query from the server who owns the client if some fields are
593 if (server->server_type == SILC_ROUTER &&
594 !silc_server_command_whois_check(cmd, clients, clients_count)) {
599 /* Send the command reply to the client */
600 silc_server_command_whois_send_reply(cmd, clients, clients_count);
606 silc_free(client_id);
610 silc_free(server_name);
616 silc_server_command_whois_from_server(SilcServerCommandContext cmd)
618 SilcServer server = cmd->server;
619 char *nick = NULL, *server_name = NULL;
620 int count = 0, clients_count;
621 SilcClientID *client_id = NULL;
622 SilcClientEntry *clients = NULL, entry;
625 /* Parse the whois request */
626 if (!silc_server_command_whois_parse(cmd, &client_id, &nick,
627 &server_name, &count))
630 /* Process the command request. Let's search for the requested client and
631 send reply to the requesting server. */
634 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
636 clients = silc_calloc(1, sizeof(*clients));
641 clients = silc_idlist_get_clients_by_nickname(server->local_list,
645 clients = silc_idlist_get_clients_by_hash(server->local_list,
646 nick, server->md5hash,
650 /* If we are router we will check our global list as well. */
651 if (!clients && server->server_type == SILC_ROUTER) {
653 entry = silc_idlist_find_client_by_id(server->global_list,
656 clients = silc_calloc(1, sizeof(*clients));
661 clients = silc_idlist_get_clients_by_nickname(server->global_list,
665 clients = silc_idlist_get_clients_by_hash(server->global_list,
666 nick, server->md5hash,
672 /* Such a client really does not exist in the SILC network. */
673 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
674 SILC_STATUS_ERR_NO_SUCH_NICK,
675 3, nick, strlen(nick));
679 /* Router always finds the client entry if it exists in the SILC network.
680 However, it might be incomplete entry and does not include all the
681 mandatory fields that WHOIS command reply requires. Check for these and
682 make query from the server who owns the client if some fields are
684 if (!cmd->pending && server->server_type == SILC_ROUTER &&
685 !silc_server_command_whois_check(cmd, clients, clients_count)) {
690 /* Send the command reply to the client */
691 silc_server_command_whois_send_reply(cmd, clients, clients_count);
697 silc_free(client_id);
701 silc_free(server_name);
706 /* Server side of command WHOIS. Processes user's query and sends found
707 results as command replies back to the client. */
709 SILC_SERVER_CMD_FUNC(whois)
711 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
714 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
716 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
717 ret = silc_server_command_whois_from_client(cmd);
719 ret = silc_server_command_whois_from_server(cmd);
722 silc_server_command_free(cmd);
725 SILC_SERVER_CMD_FUNC(whowas)
729 /******************************************************************************
733 ******************************************************************************/
736 silc_server_command_identify_parse(SilcServerCommandContext cmd,
737 SilcClientID **client_id,
744 unsigned int argc = silc_argument_get_arg_num(cmd->args);
746 /* If client ID is in the command it must be used instead of nickname */
747 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
749 /* No ID, get the nickname@server string and parse it. */
750 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
752 if (strchr(tmp, '@')) {
753 len = strcspn(tmp, "@");
754 *nickname = silc_calloc(len + 1, sizeof(char));
755 memcpy(*nickname, tmp, len);
756 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
757 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
759 *nickname = strdup(tmp);
762 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
763 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
767 /* Command includes ID, use that */
768 *client_id = silc_id_payload_parse_id(tmp, len);
771 /* Get the max count of reply messages allowed */
773 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
775 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
776 SILC_STATUS_ERR_TOO_MANY_PARAMS);
778 silc_free(*nickname);
780 silc_free(*server_name);
791 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
792 SilcClientEntry *clients,
793 unsigned int clients_count)
795 SilcServer server = cmd->server;
797 int i, count = 0, len;
798 SilcBuffer packet, idp;
799 SilcClientEntry entry;
800 SilcCommandStatus status;
801 unsigned short ident = silc_command_get_ident(cmd->payload);
803 status = SILC_STATUS_OK;
804 if (clients_count > 1)
805 status = SILC_STATUS_LIST_START;
807 for (i = 0; i < clients_count; i++) {
810 if (count && i - 1 == count)
813 if (clients_count > 2)
814 status = SILC_STATUS_LIST_ITEM;
816 if (clients_count > 1 && i == clients_count - 1)
817 status = SILC_STATUS_LIST_END;
819 /* Send IDENTIFY reply */
820 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
821 tmp = silc_argument_get_first_arg(cmd->args, NULL);
825 char nh[256], uh[256];
826 SilcSocketConnection hsock;
828 memset(uh, 0, sizeof(uh));
829 memset(nh, 0, sizeof(nh));
831 strncat(nh, entry->nickname, strlen(entry->nickname));
832 if (!strchr(entry->nickname, '@')) {
834 len = entry->router ? strlen(entry->router->server_name) :
835 strlen(server->server_name);
836 strncat(nh, entry->router ? entry->router->server_name :
837 server->server_name, len);
840 if (!entry->username) {
841 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
842 SILC_STATUS_OK, ident, 2,
843 2, idp->data, idp->len,
846 strncat(uh, entry->username, strlen(entry->username));
847 if (!strchr(entry->username, '@')) {
849 hsock = (SilcSocketConnection)entry->connection;
850 len = hsock->hostname ? strlen(hsock->hostname) : strlen(hsock->ip);
851 strncat(uh, hsock->hostname ? hsock->hostname : hsock->ip, len);
854 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
855 SILC_STATUS_OK, ident, 3,
856 2, idp->data, idp->len,
861 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
862 0, packet->data, packet->len, FALSE);
864 silc_buffer_free(packet);
865 silc_buffer_free(idp);
871 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
873 SilcServer server = cmd->server;
874 char *nick = NULL, *server_name = NULL;
875 int count = 0, clients_count;
876 SilcClientID *client_id = NULL;
877 SilcClientEntry *clients = NULL, entry;
880 /* Parse the IDENTIFY request */
881 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
882 &server_name, &count))
885 /* Protocol dictates that we must always send the received IDENTIFY request
886 to our router if we are normal server, so let's do it now unless we
887 are standalone. We will not send any replies to the client until we
888 have received reply from the router. */
889 if (server->server_type == SILC_SERVER &&
890 !cmd->pending && !server->standalone) {
892 unsigned short old_ident;
894 old_ident = silc_command_get_ident(cmd->payload);
895 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
896 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
898 /* Send IDENTIFY command to our router */
899 silc_server_packet_send(server, (SilcSocketConnection)
900 server->router->connection,
901 SILC_PACKET_COMMAND, cmd->packet->flags,
902 tmpbuf->data, tmpbuf->len, TRUE);
904 /* Reprocess this packet after received reply from router */
905 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
906 silc_command_get_ident(cmd->payload),
907 silc_server_command_identify, (void *)cmd);
910 silc_command_set_ident(cmd->payload, old_ident);
912 silc_buffer_free(tmpbuf);
917 /* We are ready to process the command request. Let's search for the
918 requested client and send reply to the requesting client. */
920 /* Get all clients matching that ID or nickname from local list */
922 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
924 clients = silc_calloc(1, sizeof(*clients));
929 clients = silc_idlist_get_clients_by_nickname(server->local_list,
934 /* Check global list as well */
937 entry = silc_idlist_find_client_by_id(server->global_list,
940 clients = silc_calloc(1, sizeof(*clients));
945 clients = silc_idlist_get_clients_by_nickname(server->global_list,
952 /* Such a client really does not exist in the SILC network. */
953 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
954 SILC_STATUS_ERR_NO_SUCH_NICK,
955 3, nick, strlen(nick));
959 /* Send the command reply to the client */
960 silc_server_command_identify_send_reply(cmd, clients, clients_count);
966 silc_free(client_id);
970 silc_free(server_name);
976 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
978 SilcServer server = cmd->server;
979 char *nick = NULL, *server_name = NULL;
980 int count = 0, clients_count;
981 SilcClientID *client_id = NULL;
982 SilcClientEntry *clients = NULL, entry;
985 /* Parse the IDENTIFY request */
986 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
987 &server_name, &count))
990 /* Process the command request. Let's search for the requested client and
991 send reply to the requesting server. */
994 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
996 clients = silc_calloc(1, sizeof(*clients));
1001 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1005 clients = silc_idlist_get_clients_by_hash(server->local_list,
1006 nick, server->md5hash,
1010 /* If we are router we will check our global list as well. */
1011 if (!clients && server->server_type == SILC_ROUTER) {
1013 entry = silc_idlist_find_client_by_id(server->global_list,
1016 clients = silc_calloc(1, sizeof(*clients));
1021 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1025 clients = silc_idlist_get_clients_by_hash(server->global_list,
1026 nick, server->md5hash,
1032 /* Such a client really does not exist in the SILC network. */
1033 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1034 SILC_STATUS_ERR_NO_SUCH_NICK,
1035 3, nick, strlen(nick));
1039 /* Send the command reply to the client */
1040 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1046 silc_free(client_id);
1050 silc_free(server_name);
1055 SILC_SERVER_CMD_FUNC(identify)
1057 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1060 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1062 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1063 ret = silc_server_command_identify_from_client(cmd);
1065 ret = silc_server_command_identify_from_server(cmd);
1068 silc_server_command_free(cmd);
1071 /* Checks string for bad characters and returns TRUE if they are found. */
1073 static int silc_server_command_bad_chars(char *nick)
1075 if (strchr(nick, '\\')) return TRUE;
1076 if (strchr(nick, '\"')) return TRUE;
1077 if (strchr(nick, '´')) return TRUE;
1078 if (strchr(nick, '`')) return TRUE;
1079 if (strchr(nick, '\'')) return TRUE;
1080 if (strchr(nick, '*')) return TRUE;
1081 if (strchr(nick, '/')) return TRUE;
1082 if (strchr(nick, '@')) return TRUE;
1087 /* Server side of command NICK. Sets nickname for user. Setting
1088 nickname causes generation of a new client ID for the client. The
1089 new client ID is sent to the client after changing the nickname. */
1091 SILC_SERVER_CMD_FUNC(nick)
1093 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1094 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1095 SilcServer server = cmd->server;
1096 SilcBuffer packet, nidp, oidp;
1097 SilcClientID *new_id;
1100 SILC_LOG_DEBUG(("Start"));
1102 /* Check number of arguments */
1103 if (silc_argument_get_arg_num(cmd->args) < 1) {
1104 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1105 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1109 /* Check nickname */
1110 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1111 if (silc_server_command_bad_chars(nick) == TRUE) {
1112 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1113 SILC_STATUS_ERR_BAD_NICKNAME);
1117 /* Create new Client ID */
1118 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1119 cmd->server->md5hash, nick,
1122 /* Send notify about nickname change to our router. We send the new
1123 ID and ask to replace it with the old one. If we are router the
1124 packet is broadcasted. */
1125 if (!cmd->server->standalone)
1126 silc_server_send_replace_id(server, server->router->connection,
1127 server->server_type == SILC_SERVER ?
1128 FALSE : TRUE, client->id,
1129 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1130 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1132 /* Remove old cache entry */
1133 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1136 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1140 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1141 silc_free(client->id);
1144 /* Save the nickname as this client is our local client */
1145 if (client->nickname)
1146 silc_free(client->nickname);
1148 client->nickname = strdup(nick);
1149 client->id = new_id;
1151 /* Update client cache */
1152 silc_idcache_add(server->local_list->clients, client->nickname,
1153 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1155 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1157 /* Send NICK_CHANGE notify */
1158 silc_server_send_notify_on_channels(server, client,
1159 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1160 oidp->data, oidp->len,
1161 nidp->data, nidp->len);
1163 /* Send the new Client ID as reply command back to client */
1164 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1165 SILC_STATUS_OK, 0, 1,
1166 2, nidp->data, nidp->len);
1167 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1168 0, packet->data, packet->len, FALSE);
1170 silc_buffer_free(packet);
1171 silc_buffer_free(nidp);
1172 silc_buffer_free(oidp);
1175 silc_server_command_free(cmd);
1178 SILC_SERVER_CMD_FUNC(list)
1182 /* Server side of TOPIC command. Sets topic for channel and/or returns
1183 current topic to client. */
1185 SILC_SERVER_CMD_FUNC(topic)
1187 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1188 SilcServer server = cmd->server;
1189 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1190 SilcChannelID *channel_id;
1191 SilcChannelEntry channel;
1192 SilcChannelClientEntry chl;
1193 SilcBuffer packet, idp;
1195 unsigned int argc, tmp_len;
1197 /* Check number of arguments */
1198 argc = silc_argument_get_arg_num(cmd->args);
1200 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1201 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1205 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1206 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1210 /* Get Channel ID */
1211 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1213 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1214 SILC_STATUS_ERR_NO_CHANNEL_ID);
1217 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1219 /* Check whether the channel exists */
1220 channel = silc_idlist_find_channel_by_id(server->local_list,
1223 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1224 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1230 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1232 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1233 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1237 if (strlen(tmp) > 256) {
1238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1239 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1243 /* See whether has rights to change topic */
1244 silc_list_start(channel->user_list);
1245 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1246 if (chl->client == client) {
1247 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1248 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1249 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1257 /* Set the topic for channel */
1259 silc_free(channel->topic);
1260 channel->topic = strdup(tmp);
1262 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1264 /* Send notify about topic change to all clients on the channel */
1265 silc_server_send_notify_to_channel(server, channel, TRUE,
1266 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1267 idp->data, idp->len,
1268 channel->topic, strlen(channel->topic));
1269 silc_buffer_free(idp);
1272 /* Send the topic to client as reply packet */
1273 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1275 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1276 SILC_STATUS_OK, 0, 2,
1277 2, idp->data, idp->len,
1279 strlen(channel->topic));
1281 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1282 SILC_STATUS_OK, 0, 1,
1283 2, idp->data, idp->len);
1284 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1285 0, packet->data, packet->len, FALSE);
1287 silc_buffer_free(packet);
1288 silc_buffer_free(idp);
1289 silc_free(channel_id);
1292 silc_server_command_free(cmd);
1295 /* Server side of INVITE command. Invites some client to join some channel. */
1297 SILC_SERVER_CMD_FUNC(invite)
1299 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1300 SilcServer server = cmd->server;
1301 SilcSocketConnection sock = cmd->sock, dest_sock;
1302 SilcClientEntry sender, dest;
1303 SilcClientID *dest_id;
1304 SilcChannelEntry channel;
1305 SilcChannelID *channel_id;
1308 unsigned int argc, len;
1310 /* Check number of arguments */
1311 argc = silc_argument_get_arg_num(cmd->args);
1313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1314 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1318 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1319 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1323 /* Get destination ID */
1324 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1326 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1327 SILC_STATUS_ERR_NO_CLIENT_ID);
1330 dest_id = silc_id_payload_parse_id(tmp, len);
1332 /* Get Channel ID */
1333 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1335 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1336 SILC_STATUS_ERR_NO_CHANNEL_ID);
1339 channel_id = silc_id_payload_parse_id(tmp, len);
1341 /* Check whether the channel exists */
1342 channel = silc_idlist_find_channel_by_id(server->local_list,
1345 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1346 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1350 /* Check whether the sender of this command is on the channel. */
1351 sender = (SilcClientEntry)sock->user_data;
1352 if (!silc_server_client_on_channel(sender, channel)) {
1353 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1354 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1358 /* Check whether the channel is invite-only channel. If yes then the
1359 sender of this command must be at least channel operator. */
1360 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1361 SilcChannelClientEntry chl;
1363 silc_list_start(channel->user_list);
1364 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1365 if (chl->client == sender) {
1366 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1367 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1368 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1375 /* Find the connection data for the destination. If it is local we will
1376 send it directly otherwise we will send it to router for routing. */
1377 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1379 dest_sock = (SilcSocketConnection)dest->connection;
1381 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1383 /* Check whether the requested client is already on the channel. */
1384 /* XXX if we are normal server we don't know about global clients on
1385 the channel thus we must request it (NAMES command), check from
1386 local cache as well. */
1387 if (silc_server_client_on_channel(dest, channel)) {
1388 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1389 SILC_STATUS_ERR_USER_ON_CHANNEL);
1393 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1395 /* Send notify to the client that is invited to the channel */
1396 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1397 SILC_NOTIFY_TYPE_INVITE, 2,
1398 sidp->data, sidp->len, tmp, len);
1400 /* Send command reply */
1401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1404 silc_buffer_free(sidp);
1407 silc_server_command_free(cmd);
1410 /* Quits connection to client. This gets called if client won't
1411 close the connection even when it has issued QUIT command. */
1413 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1415 SilcServer server = (SilcServer)context;
1416 SilcSocketConnection sock = server->sockets[fd];
1418 /* Free all client specific data, such as client entry and entires
1419 on channels this client may be on. */
1420 silc_server_free_sock_user_data(server, sock);
1422 /* Close the connection on our side */
1423 silc_server_close_connection(server, sock);
1426 /* Quits SILC session. This is the normal way to disconnect client. */
1428 SILC_SERVER_CMD_FUNC(quit)
1430 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1431 SilcServer server = cmd->server;
1432 SilcSocketConnection sock = cmd->sock;
1434 SILC_LOG_DEBUG(("Start"));
1436 /* We quit the connection with little timeout */
1437 silc_task_register(server->timeout_queue, sock->sock,
1438 silc_server_command_quit_cb, server,
1439 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1441 silc_server_command_free(cmd);
1444 SILC_SERVER_CMD_FUNC(kill)
1448 /* Server side of command INFO. This sends information about us to
1449 the client. If client requested specific server we will send the
1450 command to that server. */
1452 SILC_SERVER_CMD_FUNC(info)
1454 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1455 SilcServer server = cmd->server;
1456 SilcBuffer packet, idp;
1458 char info_string[256], *dest_server;
1460 argc = silc_argument_get_arg_num(cmd->args);
1462 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1463 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1467 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1468 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1472 /* Get server name */
1473 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1476 SILC_STATUS_ERR_NO_SUCH_SERVER);
1480 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1481 /* Send our reply */
1482 memset(info_string, 0, sizeof(info_string));
1483 snprintf(info_string, sizeof(info_string),
1484 "location: %s server: %s admin: %s <%s>",
1485 server->config->admin_info->location,
1486 server->config->admin_info->server_type,
1487 server->config->admin_info->admin_name,
1488 server->config->admin_info->admin_email);
1490 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1492 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1493 SILC_STATUS_OK, 0, 2,
1494 2, idp->data, idp->len,
1496 strlen(info_string));
1497 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1498 packet->data, packet->len, FALSE);
1500 silc_buffer_free(packet);
1501 silc_buffer_free(idp);
1503 /* Send this command to the requested server */
1505 if (server->server_type == SILC_SERVER && !server->standalone) {
1509 if (server->server_type == SILC_ROUTER) {
1515 silc_server_command_free(cmd);
1518 SILC_SERVER_CMD_FUNC(connect)
1522 /* Server side of command PING. This just replies to the ping. */
1524 SILC_SERVER_CMD_FUNC(ping)
1526 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1527 SilcServer server = cmd->server;
1529 unsigned int argc, len;
1532 argc = silc_argument_get_arg_num(cmd->args);
1534 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1535 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1539 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1540 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1545 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1547 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1548 SILC_STATUS_ERR_NO_SERVER_ID);
1551 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1555 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1556 /* Send our reply */
1557 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1560 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1561 SILC_STATUS_ERR_NO_SUCH_SERVER);
1568 silc_server_command_free(cmd);
1571 SILC_SERVER_CMD_FUNC(oper)
1580 SilcChannelEntry channel;
1582 SilcClientEntry client;
1583 } JoinInternalContext;
1585 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1587 JoinInternalContext *ctx = (JoinInternalContext *)context;
1589 if (ctx->channel->key && ctx->channel->key_len) {
1592 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1594 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1595 SILC_NOTIFY_TYPE_JOIN, 1,
1596 clidp->data, clidp->len);
1598 /* Send NEW_CHANNEL_USER packet to primary route */
1599 silc_server_send_new_channel_user(server, server->router->connection,
1600 server->server_type == SILC_SERVER ?
1602 channel->id, SILC_ID_CHANNEL_LEN,
1603 client->id, SILC_ID_CLIENT_LEN);
1606 /* Send NAMES command reply to the joined channel so the user sees who
1607 is currently on the channel. */
1608 silc_server_command_send_names(ctx->server, ctx->client->connection,
1611 silc_buffer_free(clidp);
1614 silc_task_register(ctx->server->timeout_queue, fd,
1615 silc_server_command_join_notify, context,
1616 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1620 /* Assembles NAMES command and executes it. This is called when client
1621 joins to a channel and we wan't to send NAMES command reply to the
1624 void silc_server_command_send_names(SilcServer server,
1625 SilcSocketConnection sock,
1626 SilcChannelEntry channel)
1628 SilcServerCommandContext cmd;
1629 SilcBuffer buffer, idp;
1631 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1632 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1633 1, idp->data, idp->len);
1635 cmd = silc_calloc(1, sizeof(*cmd));
1636 cmd->payload = silc_command_payload_parse(buffer);
1637 cmd->args = silc_command_get_args(cmd->payload);
1638 cmd->server = server;
1640 cmd->pending = FALSE;
1642 silc_server_command_names((void *)cmd);
1647 /* Internal routine that is called after router has replied to server's
1648 JOIN command it forwarded to the router. The route has joined and possibly
1649 creaetd the channel. This function adds the client to the channel's user
1652 SILC_SERVER_CMD_FUNC(add_to_channel)
1654 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1655 SilcServer server = cmd->server;
1656 SilcClientEntry client;
1657 SilcChannelEntry channel;
1658 SilcChannelClientEntry chl;
1661 /* Get channel name */
1662 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1664 /* Get client entry */
1665 client = (SilcClientEntry)cmd->sock->user_data;
1667 /* Get channel entry */
1668 channel = silc_idlist_find_channel_by_name(server->local_list,
1669 channel_name, NULL);
1671 /* Join the client to the channel by adding it to channel's user list.
1672 Add also the channel to client entry's channels list for fast cross-
1674 chl = silc_calloc(1, sizeof(*chl));
1675 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1676 chl->client = client;
1677 chl->channel = channel;
1678 silc_list_add(channel->user_list, chl);
1679 silc_list_add(client->channels, chl);
1682 silc_server_command_free(cmd);
1685 /* Internal routine to join channel. The channel sent to this function
1686 has been either created or resolved from ID lists. This joins the sent
1687 client to the channel. */
1689 static void silc_server_command_join_channel(SilcServer server,
1690 SilcServerCommandContext cmd,
1691 SilcChannelEntry channel,
1695 SilcSocketConnection sock = cmd->sock;
1697 unsigned int tmp_len;
1698 unsigned char *passphrase = NULL, mode[4];
1699 SilcClientEntry client;
1700 SilcChannelClientEntry chl;
1701 SilcBuffer reply, chidp, clidp;
1706 /* Get passphrase */
1707 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1709 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1710 memcpy(passphrase, tmp, tmp_len);
1714 * Check channel modes
1717 /* Check invite list if channel is invite-only channel */
1718 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1719 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1720 /* Invite list is specified. Check whether client is invited in the
1721 list. If not, then check whether it has been invited otherwise. */
1724 /* XXX client must be invited to be able to join the channel */
1728 /* Check ban list if set */
1729 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1733 /* Check the channel passphrase if set. */
1734 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1735 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1736 strlen(channel->mode_data.passphrase))) {
1737 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1738 SILC_STATUS_ERR_BAD_PASSWORD);
1743 /* Check user count limit if set. */
1744 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1745 if (silc_list_count(channel->user_list) + 1 >
1746 channel->mode_data.user_limit) {
1747 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1748 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1754 * Client is allowed to join to the channel. Make it happen.
1757 /* If the JOIN request was forwarded to us we will make a bit slower
1758 query to get the client pointer. Otherwise, we get the client pointer
1760 if (cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1761 void *id = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1762 client = silc_idlist_find_client_by_id(server->local_list, id, NULL);
1765 SILC_LOG_ERROR(("Forwarded join command did not find the client who "
1766 "wanted to join the channel"));
1771 client = (SilcClientEntry)sock->user_data;
1774 /* Check whether the client already is on the channel */
1775 if (silc_server_client_on_channel(client, channel)) {
1776 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1777 SILC_STATUS_ERR_USER_ON_CHANNEL);
1781 /* Generate new channel key as protocol dictates */
1783 silc_server_create_channel_key(server, channel, 0);
1785 /* Join the client to the channel by adding it to channel's user list.
1786 Add also the channel to client entry's channels list for fast cross-
1788 chl = silc_calloc(1, sizeof(*chl));
1790 chl->client = client;
1791 chl->channel = channel;
1792 silc_list_add(channel->user_list, chl);
1793 silc_list_add(client->channels, chl);
1795 /* Encode Client ID Payload of the original client who wants to join */
1796 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1798 /* Encode command reply packet */
1799 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1800 SILC_PUT32_MSB(channel->mode, mode);
1801 if (!channel->topic) {
1803 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1804 SILC_STATUS_OK, 0, 3,
1805 2, channel->channel_name,
1806 strlen(channel->channel_name),
1807 3, chidp->data, chidp->len,
1811 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1812 SILC_STATUS_OK, 0, 4,
1813 2, channel->channel_name,
1814 strlen(channel->channel_name),
1815 3, chidp->data, chidp->len,
1818 strlen(channel->topic));
1821 if (server->server_type == SILC_ROUTER &&
1822 cmd->packet->flags & SILC_PACKET_FLAG_FORWARDED) {
1823 /* We are router and server has forwarded this command to us. Send
1824 all replys to the server. */
1827 /* Send command reply destined to the original client */
1828 tmpid = silc_id_str2id(cmd->packet->src_id, cmd->packet->src_id_type);
1829 silc_server_packet_send_dest(cmd->server, sock,
1830 SILC_PACKET_COMMAND_REPLY, 0,
1831 tmpid, cmd->packet->src_id_type,
1832 reply->data, reply->len, FALSE);
1834 /* Distribute new channel key to local cell and local clients. */
1835 silc_server_send_channel_key(server, channel, FALSE);
1837 /* Distribute JOIN notify into the cell for everbody on the channel */
1838 silc_server_send_notify_to_channel(server, channel, FALSE,
1839 SILC_NOTIFY_TYPE_JOIN, 1,
1840 clidp->data, clidp->len);
1842 /* Broadcast NEW_CHANNEL_USER packet to primary route */
1843 silc_server_send_new_channel_user(server, server->router->connection,
1844 TRUE, channel->id, SILC_ID_CHANNEL_LEN,
1845 client->id, SILC_ID_CLIENT_LEN);
1849 /* Client sent the command. Send all replies directly to the client. */
1851 /* Send command reply */
1852 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1853 reply->data, reply->len, FALSE);
1855 /* Send the channel key. Channel key is sent before any other packet
1857 silc_server_send_channel_key(server, channel, server->standalone ?
1860 /* Send JOIN notify to locally connected clients on the channel */
1861 silc_server_send_notify_to_channel(server, channel, FALSE,
1862 SILC_NOTIFY_TYPE_JOIN, 1,
1863 clidp->data, clidp->len);
1865 /* Send NEW_CHANNEL_USER packet to our primary router */
1866 if (!server->standalone)
1867 silc_server_send_new_channel_user(server, server->router->connection,
1869 channel->id, SILC_ID_CHANNEL_LEN,
1870 client->id, SILC_ID_CLIENT_LEN);
1872 /* Send NAMES command reply to the joined channel so the user sees who
1873 is currently on the channel. */
1874 silc_server_command_send_names(server, sock, channel);
1877 silc_buffer_free(reply);
1878 silc_buffer_free(clidp);
1879 silc_buffer_free(chidp);
1883 silc_free(passphrase);
1886 /* Server side of command JOIN. Joins client into requested channel. If
1887 the channel does not exist it will be created. */
1889 SILC_SERVER_CMD_FUNC(join)
1891 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1892 SilcServer server = cmd->server;
1894 char *tmp, *channel_name = NULL, *cipher = NULL;
1895 SilcChannelEntry channel;
1896 unsigned int umode = 0;
1897 int created = FALSE;
1899 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 3);
1901 /* Get channel name */
1902 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1905 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1910 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1911 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1912 SILC_STATUS_ERR_BAD_CHANNEL);
1913 silc_free(channel_name);
1917 /* Get cipher name */
1918 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1920 /* See if the channel exists */
1921 channel = silc_idlist_find_channel_by_name(server->local_list,
1922 channel_name, NULL);
1924 /* Channel not found */
1926 /* If we are standalone server we don't have a router, we just create
1927 the channel by ourselves. */
1928 if (server->standalone) {
1929 channel = silc_server_create_new_channel(server, server->id, cipher,
1931 umode |= SILC_CHANNEL_UMODE_CHANOP;
1932 umode |= SILC_CHANNEL_UMODE_CHANFO;
1936 /* The channel does not exist on our server. If we are normal server
1937 we will send JOIN command to our router which will handle the joining
1938 procedure (either creates the channel if it doesn't exist or joins
1939 the client to it). */
1940 if (server->server_type == SILC_SERVER) {
1941 /* Forward the original JOIN command to the router */
1942 silc_buffer_push(cmd->packet->buffer,
1943 cmd->packet->buffer->data -
1944 cmd->packet->buffer->head);
1945 silc_server_packet_forward(server, (SilcSocketConnection)
1946 server->router->connection,
1947 cmd->packet->buffer->data,
1948 cmd->packet->buffer->len, TRUE);
1950 /* Register handler that will be called after the router has replied
1951 to us. We will add the client to the new channel in this callback
1952 function. Will be called from JOIN command reply. */
1953 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1954 ++server->router->data.cmd_ident,
1955 silc_server_command_add_to_channel,
1960 /* We are router and the channel does not seem exist so we will check
1961 our global list as well for the channel. */
1962 channel = silc_idlist_find_channel_by_name(server->global_list,
1963 channel_name, NULL);
1965 /* Channel really does not exist, create it */
1966 channel = silc_server_create_new_channel(server, server->id, cipher,
1968 umode |= SILC_CHANNEL_UMODE_CHANOP;
1969 umode |= SILC_CHANNEL_UMODE_CHANFO;
1975 /* Join to the channel */
1976 silc_server_command_join_channel(server, cmd, channel, created, umode);
1979 silc_server_command_free(cmd);
1982 /* Server side of command MOTD. Sends server's current "message of the
1983 day" to the client. */
1985 SILC_SERVER_CMD_FUNC(motd)
1987 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1988 SilcServer server = cmd->server;
1993 SILC_LOG_DEBUG(("Start"));
1995 argc = silc_argument_get_arg_num(cmd->args);
1997 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
1998 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2002 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2003 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2007 /* XXX show currently only our motd */
2009 if (server->config && server->config->motd &&
2010 server->config->motd->motd_file) {
2013 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2018 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2024 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2029 silc_server_command_free(cmd);
2032 SILC_SERVER_CMD_FUNC(umode)
2036 /* Checks that client has rights to add or remove channel modes. If any
2037 of the checks fails FALSE is returned. */
2039 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2040 SilcChannelClientEntry client,
2043 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2044 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2046 /* Check whether has rights to change anything */
2047 if (!is_op && !is_fo)
2050 /* Check whether has rights to change everything */
2054 /* We know that client is channel operator, check that they are not
2055 changing anything that requires channel founder rights. Rest of the
2056 modes are available automatically for channel operator. */
2058 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2059 if (is_op && !is_fo)
2062 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2063 if (is_op && !is_fo)
2068 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2069 if (is_op && !is_fo)
2072 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2073 if (is_op && !is_fo)
2078 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2079 if (is_op && !is_fo)
2082 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2083 if (is_op && !is_fo)
2091 /* Server side command of CMODE. Changes channel mode */
2093 SILC_SERVER_CMD_FUNC(cmode)
2095 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2096 SilcServer server = cmd->server;
2097 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2098 SilcChannelID *channel_id;
2099 SilcChannelEntry channel;
2100 SilcChannelClientEntry chl;
2101 SilcBuffer packet, cidp;
2102 unsigned char *tmp, *tmp_id, *tmp_mask;
2103 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2105 SILC_LOG_DEBUG(("Start"));
2107 argc = silc_argument_get_arg_num(cmd->args);
2109 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2110 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2114 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2115 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2119 /* Get Channel ID */
2120 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2123 SILC_STATUS_ERR_NO_CHANNEL_ID);
2126 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2128 /* Get the channel mode mask */
2129 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2131 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2132 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2135 SILC_GET32_MSB(mode_mask, tmp_mask);
2137 /* Get channel entry */
2138 channel = silc_idlist_find_channel_by_id(server->local_list,
2141 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2142 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2146 /* Check whether this client is on the channel */
2147 if (!silc_server_client_on_channel(client, channel)) {
2148 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2149 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2153 /* Get entry to the channel user list */
2154 silc_list_start(channel->user_list);
2155 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2156 if (chl->client == client)
2159 /* Check that client has rights to change any requested channel modes */
2160 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2162 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2167 * Check the modes. Modes that requires nothing special operation are
2171 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2172 /* Channel uses private keys to protect traffic. Client(s) has set the
2173 key locally they want to use, server does not know that key. */
2174 /* Nothing interesting to do here now */
2176 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2177 /* The mode is removed and we need to generate and distribute
2178 new channel key. Clients are not using private channel keys
2179 anymore after this. */
2181 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2184 /* Re-generate channel key */
2185 silc_server_create_channel_key(server, channel, 0);
2187 /* Encode channel key payload to be distributed on the channel */
2189 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2190 strlen(channel->channel_key->
2192 channel->channel_key->cipher->name,
2193 channel->key_len / 8, channel->key);
2195 /* If we are normal server then we will send it to our router. If we
2196 are router we will send it to all local servers that has clients on
2198 if (server->server_type == SILC_SERVER) {
2199 if (!server->standalone)
2200 silc_server_packet_send(server,
2201 cmd->server->router->connection,
2202 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2208 /* Send to locally connected clients on the channel */
2209 silc_server_packet_send_local_channel(server, channel,
2210 SILC_PACKET_CHANNEL_KEY, 0,
2211 packet->data, packet->len, FALSE);
2212 silc_buffer_free(packet);
2216 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2217 /* User limit is set on channel */
2218 unsigned int user_limit;
2220 /* Get user limit */
2221 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2223 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2224 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2225 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2229 SILC_GET32_MSB(user_limit, tmp);
2230 channel->mode_data.user_limit = user_limit;
2233 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2234 /* User limit mode is unset. Remove user limit */
2235 channel->mode_data.user_limit = 0;
2238 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2239 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2240 /* Passphrase has been set to channel */
2242 /* Get the passphrase */
2243 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2245 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2246 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2250 /* Save the passphrase */
2251 channel->mode_data.passphrase = strdup(tmp);
2254 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2255 /* Passphrase mode is unset. remove the passphrase */
2256 if (channel->mode_data.passphrase) {
2257 silc_free(channel->mode_data.passphrase);
2258 channel->mode_data.passphrase = NULL;
2263 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2264 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2265 /* Ban list is specified for channel */
2268 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2270 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2271 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2275 /* XXX check that channel founder is not banned */
2277 /* Save the ban list */
2278 channel->mode_data.ban_list = strdup(tmp);
2281 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2282 /* Ban mode is unset. Remove the entire ban list */
2283 if (channel->mode_data.ban_list) {
2284 silc_free(channel->mode_data.ban_list);
2285 channel->mode_data.ban_list = NULL;
2290 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2291 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2292 /* Invite list is specified for channel */
2294 /* Get invite list */
2295 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2298 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2302 /* Save the invite linst */
2303 channel->mode_data.invite_list = strdup(tmp);
2306 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2307 /* Invite list mode is unset. Remove the entire invite list */
2308 if (channel->mode_data.invite_list) {
2309 silc_free(channel->mode_data.invite_list);
2310 channel->mode_data.invite_list = NULL;
2315 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2316 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2317 /* Cipher to use protect the traffic */
2318 unsigned int key_len = 128;
2322 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2324 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2325 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2329 cp = strchr(tmp, ':');
2335 /* XXX Duplicated code, make own function for this!! */
2337 /* Delete old cipher and allocate the new one */
2338 silc_cipher_free(channel->channel_key);
2339 silc_cipher_alloc(tmp, &channel->channel_key);
2345 /* Re-generate channel key */
2346 silc_server_create_channel_key(server, channel, key_len);
2348 /* Encode channel key payload to be distributed on the channel */
2350 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2351 strlen(channel->channel_key->
2353 channel->channel_key->cipher->name,
2354 channel->key_len / 8, channel->key);
2356 /* If we are normal server then we will send it to our router. If we
2357 are router we will send it to all local servers that has clients on
2359 if (server->server_type == SILC_SERVER) {
2360 if (!server->standalone)
2361 silc_server_packet_send(server,
2362 cmd->server->router->connection,
2363 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2369 /* Send to locally connected clients on the channel */
2370 silc_server_packet_send_local_channel(server, channel,
2371 SILC_PACKET_CHANNEL_KEY, 0,
2372 packet->data, packet->len, FALSE);
2373 silc_buffer_free(packet);
2376 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2377 /* Cipher mode is unset. Remove the cipher and revert back to
2380 if (channel->mode_data.cipher) {
2381 silc_free(channel->mode_data.cipher);
2382 channel->mode_data.cipher = NULL;
2383 channel->mode_data.key_len = 0;
2386 /* Generate new cipher and key for the channel */
2388 /* XXX Duplicated code, make own function for this!! */
2390 /* Delete old cipher and allocate default one */
2391 silc_cipher_free(channel->channel_key);
2392 if (!channel->cipher)
2393 silc_cipher_alloc("twofish", &channel->channel_key);
2395 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2397 /* Re-generate channel key */
2398 silc_server_create_channel_key(server, channel, 0);
2400 /* Encode channel key payload to be distributed on the channel */
2402 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2403 strlen(channel->channel_key->
2405 channel->channel_key->cipher->name,
2406 channel->key_len / 8, channel->key);
2408 /* If we are normal server then we will send it to our router. If we
2409 are router we will send it to all local servers that has clients on
2411 if (server->server_type == SILC_SERVER) {
2412 if (!server->standalone)
2413 silc_server_packet_send(server,
2414 cmd->server->router->connection,
2415 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2421 /* Send to locally connected clients on the channel */
2422 silc_server_packet_send_local_channel(server, channel,
2423 SILC_PACKET_CHANNEL_KEY, 0,
2424 packet->data, packet->len, FALSE);
2425 silc_buffer_free(packet);
2429 /* Finally, set the mode */
2430 channel->mode = mode_mask;
2432 /* Send CMODE_CHANGE notify */
2433 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2434 silc_server_send_notify_to_channel(server, channel, TRUE,
2435 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2436 cidp->data, cidp->len,
2440 /* Send command reply to sender */
2441 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2442 SILC_STATUS_OK, 0, 1,
2444 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2445 packet->data, packet->len, FALSE);
2447 silc_buffer_free(packet);
2448 silc_free(channel_id);
2451 silc_server_command_free(cmd);
2454 /* Server side of CUMODE command. Changes client's mode on a channel. */
2456 SILC_SERVER_CMD_FUNC(cumode)
2458 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2459 SilcServer server = cmd->server;
2460 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2461 SilcChannelID *channel_id;
2462 SilcClientID *client_id;
2463 SilcChannelEntry channel;
2464 SilcClientEntry target_client;
2465 SilcChannelClientEntry chl;
2466 SilcBuffer packet, idp;
2467 unsigned char *tmp_id, *tmp_mask;
2468 unsigned int argc, target_mask, sender_mask, tmp_len;
2471 SILC_LOG_DEBUG(("Start"));
2473 argc = silc_argument_get_arg_num(cmd->args);
2475 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2476 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2480 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2481 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2485 /* Get Channel ID */
2486 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2489 SILC_STATUS_ERR_NO_CHANNEL_ID);
2492 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2494 /* Get channel entry */
2495 channel = silc_idlist_find_channel_by_id(server->local_list,
2498 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2499 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2503 /* Check whether sender is on the channel */
2504 if (!silc_server_client_on_channel(client, channel)) {
2505 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2506 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2510 /* Check that client has rights to change other's rights */
2511 silc_list_start(channel->user_list);
2512 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2513 if (chl->client == client) {
2514 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2515 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2516 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2517 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2521 sender_mask = chl->mode;
2526 /* Get the target client's channel mode mask */
2527 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2530 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2533 SILC_GET32_MSB(target_mask, tmp_mask);
2535 /* Get target Client ID */
2536 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2538 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2539 SILC_STATUS_ERR_NO_CHANNEL_ID);
2542 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2544 /* Get target client's entry */
2545 target_client = silc_idlist_find_client_by_id(server->local_list,
2547 if (!target_client) {
2548 /* XXX If target client is not one of mine send to primary route */
2551 /* Check whether target client is on the channel */
2552 if (!silc_server_client_on_channel(target_client, channel)) {
2553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2554 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2558 /* Get entry to the channel user list */
2559 silc_list_start(channel->user_list);
2560 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2561 if (chl->client == target_client)
2568 /* If the target client is founder, no one else can change their mode
2570 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2571 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2572 SILC_STATUS_ERR_NOT_YOU);
2576 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2577 /* Cannot promote anyone to channel founder */
2578 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2579 SILC_STATUS_ERR_NOT_YOU);
2582 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2583 if (target_client == client) {
2584 /* Remove channel founder rights from itself */
2585 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2588 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2589 SILC_STATUS_ERR_NOT_YOU);
2595 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2596 /* Promote to operator */
2597 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2598 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2602 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2603 /* Demote to normal user */
2604 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2609 /* Send notify to channel, notify only if mode was actually changed. */
2611 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2612 silc_server_send_notify_to_channel(server, channel, TRUE,
2613 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2614 idp->data, idp->len,
2615 tmp_mask, 4, tmp_id, tmp_len);
2616 silc_buffer_free(idp);
2619 /* Send command reply to sender */
2620 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2621 SILC_STATUS_OK, 0, 2,
2623 3, tmp_id, tmp_len);
2624 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2625 packet->data, packet->len, FALSE);
2627 silc_buffer_free(packet);
2628 silc_free(channel_id);
2629 silc_free(client_id);
2632 silc_server_command_free(cmd);
2635 /* Server side of KICK command. Kicks client out of channel. */
2637 SILC_SERVER_CMD_FUNC(kick)
2641 SILC_SERVER_CMD_FUNC(restart)
2645 SILC_SERVER_CMD_FUNC(close)
2649 SILC_SERVER_CMD_FUNC(die)
2653 SILC_SERVER_CMD_FUNC(silcoper)
2657 /* Server side command of LEAVE. Removes client from a channel. */
2659 SILC_SERVER_CMD_FUNC(leave)
2661 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2662 SilcServer server = cmd->server;
2663 SilcSocketConnection sock = cmd->sock;
2664 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2666 SilcChannelEntry channel;
2668 unsigned int i, argc, len;
2671 SILC_LOG_DEBUG(("Start"));
2673 argc = silc_argument_get_arg_num(cmd->args);
2675 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2676 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2680 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2681 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2685 /* Get Channel ID */
2686 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2689 SILC_STATUS_ERR_NO_CHANNEL_ID);
2692 id = silc_id_payload_parse_id(tmp, len);
2694 /* Get channel entry */
2695 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2697 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2698 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2702 /* Check whether this client is on the channel */
2703 if (!silc_server_client_on_channel(id_entry, channel)) {
2704 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2705 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2709 /* Notify routers that they should remove this client from their list
2710 of clients on the channel. */
2711 if (!server->standalone)
2712 silc_server_send_remove_channel_user(server,
2713 server->router->connection,
2714 server->server_type == SILC_ROUTER ?
2715 TRUE : FALSE, id_entry->id, id);
2717 /* Remove client from channel */
2718 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2720 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2723 /* If the channel does not exist anymore we won't send anything */
2727 /* Re-generate channel key */
2728 silc_server_create_channel_key(server, channel, 0);
2730 /* Encode channel key payload to be distributed on the channel */
2732 silc_channel_key_payload_encode(len, tmp,
2733 strlen(channel->channel_key->cipher->name),
2734 channel->channel_key->cipher->name,
2735 channel->key_len / 8, channel->key);
2737 /* If we are normal server then we will send it to our router. If we
2738 are router we will send it to all local servers that has clients on
2740 if (server->server_type == SILC_SERVER) {
2741 if (!server->standalone)
2742 silc_server_packet_send(server,
2743 cmd->server->router->connection,
2744 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2750 /* Send to locally connected clients on the channel */
2751 silc_server_packet_send_local_channel(server, channel,
2752 SILC_PACKET_CHANNEL_KEY, 0,
2753 packet->data, packet->len, FALSE);
2755 silc_buffer_free(packet);
2759 silc_server_command_free(cmd);
2762 /* Server side of command NAMES. Resolves clients and their names currently
2763 joined on the requested channel. The name list is sent back to the
2766 SILC_SERVER_CMD_FUNC(names)
2768 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2769 SilcServer server = cmd->server;
2770 SilcChannelEntry channel;
2771 SilcChannelClientEntry chl;
2774 unsigned int i, len, len2, tmp_len, argc;
2776 char *name_list = NULL, *n;
2777 SilcBuffer client_id_list;
2778 SilcBuffer client_mode_list;
2780 SILC_LOG_DEBUG(("Start"));
2782 argc = silc_argument_get_arg_num(cmd->args);
2784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2785 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2789 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2790 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2794 /* Get Channel ID */
2795 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2798 SILC_STATUS_ERR_NO_CHANNEL_ID);
2801 id = silc_id_payload_parse_id(tmp, tmp_len);
2803 /* Check whether the channel exists. If we are normal server and the
2804 channel does not exist we will send this same command to our router
2805 which will know if the channel exists. */
2806 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2808 if (server->server_type == SILC_SERVER && !server->standalone) {
2809 /* XXX Send names command */
2811 cmd->pending = TRUE;
2812 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2813 silc_server_command_names, context);
2817 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2818 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2822 /* Assemble the name list now */
2825 silc_list_start(channel->user_list);
2827 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2828 n = chl->client->nickname;
2832 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2833 memcpy(name_list + (len - len2), n, len2);
2836 if (i == silc_list_count(channel->user_list) - 1)
2838 memcpy(name_list + len, ",", 1);
2846 /* Assemble the Client ID list now */
2847 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2848 silc_list_count(channel->user_list));
2849 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2850 silc_list_start(channel->user_list);
2851 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2854 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2855 silc_buffer_format(client_id_list,
2856 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2858 silc_buffer_pull(client_id_list, idp->len);
2859 silc_buffer_free(idp);
2861 silc_buffer_push(client_id_list,
2862 client_id_list->data - client_id_list->head);
2864 /* Assemble mode list */
2865 client_mode_list = silc_buffer_alloc(4 *
2866 silc_list_count(channel->user_list));
2867 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2868 silc_list_start(channel->user_list);
2869 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2870 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2871 silc_buffer_pull(client_mode_list, 4);
2873 silc_buffer_push(client_mode_list,
2874 client_mode_list->data - client_mode_list->head);
2877 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2878 SILC_STATUS_OK, 0, 4,
2882 4, client_id_list->data,
2883 client_id_list->len,
2884 5, client_mode_list->data,
2885 client_mode_list->len);
2886 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2887 packet->data, packet->len, FALSE);
2889 silc_buffer_free(packet);
2890 silc_free(name_list);
2891 silc_buffer_free(client_id_list);
2892 silc_buffer_free(client_mode_list);
2896 silc_server_command_free(cmd);