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, SILC_COMMAND_WHOIS, \
89 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS); \
90 silc_server_command_free(cmd); \
94 silc_server_command_send_status_reply(cmd, SILC_COMMAND_WHOIS, \
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_LOG_DEBUG(("Start"));
1901 /* Check number of parameters */
1902 argc = silc_argument_get_arg_num(cmd->args);
1904 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1905 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1909 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1910 SILC_STATUS_ERR_TOO_MANY_PARAMS);
1914 /* Get channel name */
1915 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1917 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1918 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1923 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1924 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1925 SILC_STATUS_ERR_BAD_CHANNEL);
1926 silc_free(channel_name);
1930 /* Get cipher name */
1931 cipher = silc_argument_get_arg_type(cmd->args, 3, NULL);
1933 /* See if the channel exists */
1934 channel = silc_idlist_find_channel_by_name(server->local_list,
1935 channel_name, NULL);
1937 /* Channel not found */
1939 /* If we are standalone server we don't have a router, we just create
1940 the channel by ourselves. */
1941 if (server->standalone) {
1942 channel = silc_server_create_new_channel(server, server->id, cipher,
1944 umode |= SILC_CHANNEL_UMODE_CHANOP;
1945 umode |= SILC_CHANNEL_UMODE_CHANFO;
1949 /* The channel does not exist on our server. If we are normal server
1950 we will send JOIN command to our router which will handle the joining
1951 procedure (either creates the channel if it doesn't exist or joins
1952 the client to it). */
1953 if (server->server_type == SILC_SERVER) {
1954 /* Forward the original JOIN command to the router */
1955 silc_buffer_push(cmd->packet->buffer,
1956 cmd->packet->buffer->data -
1957 cmd->packet->buffer->head);
1958 silc_server_packet_forward(server, (SilcSocketConnection)
1959 server->router->connection,
1960 cmd->packet->buffer->data,
1961 cmd->packet->buffer->len, TRUE);
1963 /* Register handler that will be called after the router has replied
1964 to us. We will add the client to the new channel in this callback
1965 function. Will be called from JOIN command reply. */
1966 silc_server_command_pending(server, SILC_COMMAND_JOIN,
1967 ++server->router->data.cmd_ident,
1968 silc_server_command_add_to_channel,
1973 /* We are router and the channel does not seem exist so we will check
1974 our global list as well for the channel. */
1975 channel = silc_idlist_find_channel_by_name(server->global_list,
1976 channel_name, NULL);
1978 /* Channel really does not exist, create it */
1979 channel = silc_server_create_new_channel(server, server->id, cipher,
1981 umode |= SILC_CHANNEL_UMODE_CHANOP;
1982 umode |= SILC_CHANNEL_UMODE_CHANFO;
1988 /* Join to the channel */
1989 silc_server_command_join_channel(server, cmd, channel, created, umode);
1992 silc_server_command_free(cmd);
1995 /* Server side of command MOTD. Sends server's current "message of the
1996 day" to the client. */
1998 SILC_SERVER_CMD_FUNC(motd)
2000 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2001 SilcServer server = cmd->server;
2006 SILC_LOG_DEBUG(("Start"));
2008 argc = silc_argument_get_arg_num(cmd->args);
2010 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2011 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2015 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2016 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2020 /* XXX show currently only our motd */
2022 if (server->config && server->config->motd &&
2023 server->config->motd->motd_file) {
2026 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2031 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2037 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2042 silc_server_command_free(cmd);
2045 SILC_SERVER_CMD_FUNC(umode)
2049 /* Checks that client has rights to add or remove channel modes. If any
2050 of the checks fails FALSE is returned. */
2052 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2053 SilcChannelClientEntry client,
2056 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2057 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2059 /* Check whether has rights to change anything */
2060 if (!is_op && !is_fo)
2063 /* Check whether has rights to change everything */
2067 /* We know that client is channel operator, check that they are not
2068 changing anything that requires channel founder rights. Rest of the
2069 modes are available automatically for channel operator. */
2071 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2072 if (is_op && !is_fo)
2075 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2076 if (is_op && !is_fo)
2081 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2082 if (is_op && !is_fo)
2085 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2086 if (is_op && !is_fo)
2091 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2092 if (is_op && !is_fo)
2095 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2096 if (is_op && !is_fo)
2104 /* Server side command of CMODE. Changes channel mode */
2106 SILC_SERVER_CMD_FUNC(cmode)
2108 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2109 SilcServer server = cmd->server;
2110 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2111 SilcChannelID *channel_id;
2112 SilcChannelEntry channel;
2113 SilcChannelClientEntry chl;
2114 SilcBuffer packet, cidp;
2115 unsigned char *tmp, *tmp_id, *tmp_mask;
2116 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2118 SILC_LOG_DEBUG(("Start"));
2120 argc = silc_argument_get_arg_num(cmd->args);
2122 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2123 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2127 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2128 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2132 /* Get Channel ID */
2133 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2135 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2136 SILC_STATUS_ERR_NO_CHANNEL_ID);
2139 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2141 /* Get the channel mode mask */
2142 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2144 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2145 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2148 SILC_GET32_MSB(mode_mask, tmp_mask);
2150 /* Get channel entry */
2151 channel = silc_idlist_find_channel_by_id(server->local_list,
2154 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2155 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2159 /* Check whether this client is on the channel */
2160 if (!silc_server_client_on_channel(client, channel)) {
2161 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2162 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2166 /* Get entry to the channel user list */
2167 silc_list_start(channel->user_list);
2168 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2169 if (chl->client == client)
2172 /* Check that client has rights to change any requested channel modes */
2173 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2174 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2175 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2180 * Check the modes. Modes that requires nothing special operation are
2184 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2185 /* Channel uses private keys to protect traffic. Client(s) has set the
2186 key locally they want to use, server does not know that key. */
2187 /* Nothing interesting to do here now */
2189 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2190 /* The mode is removed and we need to generate and distribute
2191 new channel key. Clients are not using private channel keys
2192 anymore after this. */
2194 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2197 /* Re-generate channel key */
2198 silc_server_create_channel_key(server, channel, 0);
2200 /* Encode channel key payload to be distributed on the channel */
2202 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2203 strlen(channel->channel_key->
2205 channel->channel_key->cipher->name,
2206 channel->key_len / 8, channel->key);
2208 /* If we are normal server then we will send it to our router. If we
2209 are router we will send it to all local servers that has clients on
2211 if (server->server_type == SILC_SERVER) {
2212 if (!server->standalone)
2213 silc_server_packet_send(server,
2214 cmd->server->router->connection,
2215 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2221 /* Send to locally connected clients on the channel */
2222 silc_server_packet_send_local_channel(server, channel,
2223 SILC_PACKET_CHANNEL_KEY, 0,
2224 packet->data, packet->len, FALSE);
2225 silc_buffer_free(packet);
2229 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2230 /* User limit is set on channel */
2231 unsigned int user_limit;
2233 /* Get user limit */
2234 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2236 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2237 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2238 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2242 SILC_GET32_MSB(user_limit, tmp);
2243 channel->mode_data.user_limit = user_limit;
2246 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2247 /* User limit mode is unset. Remove user limit */
2248 channel->mode_data.user_limit = 0;
2251 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2252 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2253 /* Passphrase has been set to channel */
2255 /* Get the passphrase */
2256 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2258 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2259 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2263 /* Save the passphrase */
2264 channel->mode_data.passphrase = strdup(tmp);
2267 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2268 /* Passphrase mode is unset. remove the passphrase */
2269 if (channel->mode_data.passphrase) {
2270 silc_free(channel->mode_data.passphrase);
2271 channel->mode_data.passphrase = NULL;
2276 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2277 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2278 /* Ban list is specified for channel */
2281 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2283 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2284 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2288 /* XXX check that channel founder is not banned */
2290 /* Save the ban list */
2291 channel->mode_data.ban_list = strdup(tmp);
2294 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2295 /* Ban mode is unset. Remove the entire ban list */
2296 if (channel->mode_data.ban_list) {
2297 silc_free(channel->mode_data.ban_list);
2298 channel->mode_data.ban_list = NULL;
2303 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2304 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2305 /* Invite list is specified for channel */
2307 /* Get invite list */
2308 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2310 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2311 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2315 /* Save the invite linst */
2316 channel->mode_data.invite_list = strdup(tmp);
2319 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2320 /* Invite list mode is unset. Remove the entire invite list */
2321 if (channel->mode_data.invite_list) {
2322 silc_free(channel->mode_data.invite_list);
2323 channel->mode_data.invite_list = NULL;
2328 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2329 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2330 /* Cipher to use protect the traffic */
2331 unsigned int key_len = 128;
2335 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2337 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2338 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2342 cp = strchr(tmp, ':');
2348 /* XXX Duplicated code, make own function for this!! */
2350 /* Delete old cipher and allocate the new one */
2351 silc_cipher_free(channel->channel_key);
2352 silc_cipher_alloc(tmp, &channel->channel_key);
2358 /* Re-generate channel key */
2359 silc_server_create_channel_key(server, channel, key_len);
2361 /* Encode channel key payload to be distributed on the channel */
2363 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2364 strlen(channel->channel_key->
2366 channel->channel_key->cipher->name,
2367 channel->key_len / 8, channel->key);
2369 /* If we are normal server then we will send it to our router. If we
2370 are router we will send it to all local servers that has clients on
2372 if (server->server_type == SILC_SERVER) {
2373 if (!server->standalone)
2374 silc_server_packet_send(server,
2375 cmd->server->router->connection,
2376 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2382 /* Send to locally connected clients on the channel */
2383 silc_server_packet_send_local_channel(server, channel,
2384 SILC_PACKET_CHANNEL_KEY, 0,
2385 packet->data, packet->len, FALSE);
2386 silc_buffer_free(packet);
2389 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2390 /* Cipher mode is unset. Remove the cipher and revert back to
2393 if (channel->mode_data.cipher) {
2394 silc_free(channel->mode_data.cipher);
2395 channel->mode_data.cipher = NULL;
2396 channel->mode_data.key_len = 0;
2399 /* Generate new cipher and key for the channel */
2401 /* XXX Duplicated code, make own function for this!! */
2403 /* Delete old cipher and allocate default one */
2404 silc_cipher_free(channel->channel_key);
2405 if (!channel->cipher)
2406 silc_cipher_alloc("twofish", &channel->channel_key);
2408 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2410 /* Re-generate channel key */
2411 silc_server_create_channel_key(server, channel, 0);
2413 /* Encode channel key payload to be distributed on the channel */
2415 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2416 strlen(channel->channel_key->
2418 channel->channel_key->cipher->name,
2419 channel->key_len / 8, channel->key);
2421 /* If we are normal server then we will send it to our router. If we
2422 are router we will send it to all local servers that has clients on
2424 if (server->server_type == SILC_SERVER) {
2425 if (!server->standalone)
2426 silc_server_packet_send(server,
2427 cmd->server->router->connection,
2428 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2434 /* Send to locally connected clients on the channel */
2435 silc_server_packet_send_local_channel(server, channel,
2436 SILC_PACKET_CHANNEL_KEY, 0,
2437 packet->data, packet->len, FALSE);
2438 silc_buffer_free(packet);
2442 /* Finally, set the mode */
2443 channel->mode = mode_mask;
2445 /* Send CMODE_CHANGE notify */
2446 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2447 silc_server_send_notify_to_channel(server, channel, TRUE,
2448 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2449 cidp->data, cidp->len,
2453 /* Send command reply to sender */
2454 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2455 SILC_STATUS_OK, 0, 1,
2457 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2458 packet->data, packet->len, FALSE);
2460 silc_buffer_free(packet);
2461 silc_free(channel_id);
2464 silc_server_command_free(cmd);
2467 /* Server side of CUMODE command. Changes client's mode on a channel. */
2469 SILC_SERVER_CMD_FUNC(cumode)
2471 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2472 SilcServer server = cmd->server;
2473 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2474 SilcChannelID *channel_id;
2475 SilcClientID *client_id;
2476 SilcChannelEntry channel;
2477 SilcClientEntry target_client;
2478 SilcChannelClientEntry chl;
2479 SilcBuffer packet, idp;
2480 unsigned char *tmp_id, *tmp_mask;
2481 unsigned int argc, target_mask, sender_mask, tmp_len;
2484 SILC_LOG_DEBUG(("Start"));
2486 argc = silc_argument_get_arg_num(cmd->args);
2488 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2489 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2493 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2494 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2498 /* Get Channel ID */
2499 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2501 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2502 SILC_STATUS_ERR_NO_CHANNEL_ID);
2505 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2507 /* Get channel entry */
2508 channel = silc_idlist_find_channel_by_id(server->local_list,
2511 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2512 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2516 /* Check whether sender is on the channel */
2517 if (!silc_server_client_on_channel(client, channel)) {
2518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2519 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2523 /* Check that client has rights to change other's rights */
2524 silc_list_start(channel->user_list);
2525 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2526 if (chl->client == client) {
2527 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2528 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2529 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2530 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2534 sender_mask = chl->mode;
2539 /* Get the target client's channel mode mask */
2540 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2542 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2543 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2546 SILC_GET32_MSB(target_mask, tmp_mask);
2548 /* Get target Client ID */
2549 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2551 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2552 SILC_STATUS_ERR_NO_CHANNEL_ID);
2555 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2557 /* Get target client's entry */
2558 target_client = silc_idlist_find_client_by_id(server->local_list,
2560 if (!target_client) {
2561 /* XXX If target client is not one of mine send to primary route */
2564 /* Check whether target client is on the channel */
2565 if (!silc_server_client_on_channel(target_client, channel)) {
2566 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2567 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2571 /* Get entry to the channel user list */
2572 silc_list_start(channel->user_list);
2573 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2574 if (chl->client == target_client)
2581 /* If the target client is founder, no one else can change their mode
2583 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2584 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2585 SILC_STATUS_ERR_NOT_YOU);
2589 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2590 /* Cannot promote anyone to channel founder */
2591 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2592 SILC_STATUS_ERR_NOT_YOU);
2595 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2596 if (target_client == client) {
2597 /* Remove channel founder rights from itself */
2598 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2601 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2602 SILC_STATUS_ERR_NOT_YOU);
2608 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2609 /* Promote to operator */
2610 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2611 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2615 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2616 /* Demote to normal user */
2617 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2622 /* Send notify to channel, notify only if mode was actually changed. */
2624 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2625 silc_server_send_notify_to_channel(server, channel, TRUE,
2626 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2627 idp->data, idp->len,
2628 tmp_mask, 4, tmp_id, tmp_len);
2629 silc_buffer_free(idp);
2632 /* Send command reply to sender */
2633 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2634 SILC_STATUS_OK, 0, 2,
2636 3, tmp_id, tmp_len);
2637 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2638 packet->data, packet->len, FALSE);
2640 silc_buffer_free(packet);
2641 silc_free(channel_id);
2642 silc_free(client_id);
2645 silc_server_command_free(cmd);
2648 /* Server side of KICK command. Kicks client out of channel. */
2650 SILC_SERVER_CMD_FUNC(kick)
2654 SILC_SERVER_CMD_FUNC(restart)
2658 SILC_SERVER_CMD_FUNC(close)
2662 SILC_SERVER_CMD_FUNC(die)
2666 SILC_SERVER_CMD_FUNC(silcoper)
2670 /* Server side command of LEAVE. Removes client from a channel. */
2672 SILC_SERVER_CMD_FUNC(leave)
2674 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2675 SilcServer server = cmd->server;
2676 SilcSocketConnection sock = cmd->sock;
2677 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2679 SilcChannelEntry channel;
2681 unsigned int i, argc, len;
2684 SILC_LOG_DEBUG(("Start"));
2686 argc = silc_argument_get_arg_num(cmd->args);
2688 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2689 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2693 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2694 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2698 /* Get Channel ID */
2699 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2701 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2702 SILC_STATUS_ERR_NO_CHANNEL_ID);
2705 id = silc_id_payload_parse_id(tmp, len);
2707 /* Get channel entry */
2708 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2710 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2711 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2715 /* Check whether this client is on the channel */
2716 if (!silc_server_client_on_channel(id_entry, channel)) {
2717 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2718 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2722 /* Notify routers that they should remove this client from their list
2723 of clients on the channel. */
2724 if (!server->standalone)
2725 silc_server_send_remove_channel_user(server,
2726 server->router->connection,
2727 server->server_type == SILC_ROUTER ?
2728 TRUE : FALSE, id_entry->id, id);
2730 /* Remove client from channel */
2731 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2733 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2736 /* If the channel does not exist anymore we won't send anything */
2740 /* Re-generate channel key */
2741 silc_server_create_channel_key(server, channel, 0);
2743 /* Encode channel key payload to be distributed on the channel */
2745 silc_channel_key_payload_encode(len, tmp,
2746 strlen(channel->channel_key->cipher->name),
2747 channel->channel_key->cipher->name,
2748 channel->key_len / 8, channel->key);
2750 /* If we are normal server then we will send it to our router. If we
2751 are router we will send it to all local servers that has clients on
2753 if (server->server_type == SILC_SERVER) {
2754 if (!server->standalone)
2755 silc_server_packet_send(server,
2756 cmd->server->router->connection,
2757 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2763 /* Send to locally connected clients on the channel */
2764 silc_server_packet_send_local_channel(server, channel,
2765 SILC_PACKET_CHANNEL_KEY, 0,
2766 packet->data, packet->len, FALSE);
2768 silc_buffer_free(packet);
2772 silc_server_command_free(cmd);
2775 /* Server side of command NAMES. Resolves clients and their names currently
2776 joined on the requested channel. The name list is sent back to the
2779 SILC_SERVER_CMD_FUNC(names)
2781 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2782 SilcServer server = cmd->server;
2783 SilcChannelEntry channel;
2784 SilcChannelClientEntry chl;
2787 unsigned int i, len, len2, tmp_len, argc;
2789 char *name_list = NULL, *n;
2790 SilcBuffer client_id_list;
2791 SilcBuffer client_mode_list;
2793 SILC_LOG_DEBUG(("Start"));
2795 argc = silc_argument_get_arg_num(cmd->args);
2797 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2798 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2802 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NAMES,
2803 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2807 /* Get Channel ID */
2808 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2810 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2811 SILC_STATUS_ERR_NO_CHANNEL_ID);
2814 id = silc_id_payload_parse_id(tmp, tmp_len);
2816 /* Check whether the channel exists. If we are normal server and the
2817 channel does not exist we will send this same command to our router
2818 which will know if the channel exists. */
2819 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2821 if (server->server_type == SILC_SERVER && !server->standalone) {
2822 /* XXX Send names command */
2824 cmd->pending = TRUE;
2825 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2826 silc_server_command_names, context);
2830 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2831 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2835 /* Assemble the name list now */
2838 silc_list_start(channel->user_list);
2840 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2841 n = chl->client->nickname;
2845 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2846 memcpy(name_list + (len - len2), n, len2);
2849 if (i == silc_list_count(channel->user_list) - 1)
2851 memcpy(name_list + len, ",", 1);
2859 /* Assemble the Client ID list now */
2860 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2861 silc_list_count(channel->user_list));
2862 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2863 silc_list_start(channel->user_list);
2864 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2867 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2868 silc_buffer_format(client_id_list,
2869 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2871 silc_buffer_pull(client_id_list, idp->len);
2872 silc_buffer_free(idp);
2874 silc_buffer_push(client_id_list,
2875 client_id_list->data - client_id_list->head);
2877 /* Assemble mode list */
2878 client_mode_list = silc_buffer_alloc(4 *
2879 silc_list_count(channel->user_list));
2880 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2881 silc_list_start(channel->user_list);
2882 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2883 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2884 silc_buffer_pull(client_mode_list, 4);
2886 silc_buffer_push(client_mode_list,
2887 client_mode_list->data - client_mode_list->head);
2890 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2891 SILC_STATUS_OK, 0, 4,
2895 4, client_id_list->data,
2896 client_id_list->len,
2897 5, client_mode_list->data,
2898 client_mode_list->len);
2899 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2900 packet->data, packet->len, FALSE);
2902 silc_buffer_free(packet);
2903 silc_free(name_list);
2904 silc_buffer_free(client_id_list);
2905 silc_buffer_free(client_mode_list);
2909 silc_server_command_free(cmd);