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 = strlen(hsock->hostname);
465 strncat(uh, hsock->hostname, 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. */
674 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
675 SILC_STATUS_ERR_NO_SUCH_NICK,
676 3, nick, strlen(nick));
678 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
679 silc_server_command_send_status_data(cmd, SILC_COMMAND_WHOIS,
680 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
681 2, idp->data, idp->len);
682 silc_buffer_free(idp);
687 /* Router always finds the client entry if it exists in the SILC network.
688 However, it might be incomplete entry and does not include all the
689 mandatory fields that WHOIS command reply requires. Check for these and
690 make query from the server who owns the client if some fields are
692 if (server->server_type == SILC_ROUTER &&
693 !silc_server_command_whois_check(cmd, clients, clients_count)) {
698 /* Send the command reply to the client */
699 silc_server_command_whois_send_reply(cmd, clients, clients_count);
705 silc_free(client_id);
709 silc_free(server_name);
714 /* Server side of command WHOIS. Processes user's query and sends found
715 results as command replies back to the client. */
717 SILC_SERVER_CMD_FUNC(whois)
719 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
722 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_WHOIS, cmd, 1, 3);
724 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
725 ret = silc_server_command_whois_from_client(cmd);
727 ret = silc_server_command_whois_from_server(cmd);
730 silc_server_command_free(cmd);
733 SILC_SERVER_CMD_FUNC(whowas)
737 /******************************************************************************
741 ******************************************************************************/
744 silc_server_command_identify_parse(SilcServerCommandContext cmd,
745 SilcClientID **client_id,
752 unsigned int argc = silc_argument_get_arg_num(cmd->args);
754 /* If client ID is in the command it must be used instead of nickname */
755 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
757 /* No ID, get the nickname@server string and parse it. */
758 tmp = silc_argument_get_arg_type(cmd->args, 1, NULL);
760 if (strchr(tmp, '@')) {
761 len = strcspn(tmp, "@");
762 *nickname = silc_calloc(len + 1, sizeof(char));
763 memcpy(*nickname, tmp, len);
764 *server_name = silc_calloc(strlen(tmp) - len, sizeof(char));
765 memcpy(*server_name, tmp + len + 1, strlen(tmp) - len - 1);
767 *nickname = strdup(tmp);
770 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
771 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
775 /* Command includes ID, use that */
776 *client_id = silc_id_payload_parse_id(tmp, len);
779 /* Get the max count of reply messages allowed */
781 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
783 silc_server_command_send_status_reply(cmd, SILC_COMMAND_IDENTIFY,
784 SILC_STATUS_ERR_TOO_MANY_PARAMS);
786 silc_free(*nickname);
788 silc_free(*server_name);
798 /* Checks that all mandatory fields are present. If not then send WHOIS
799 request to the server who owns the client. We use WHOIS because we want
800 to get as much information as possible at once. */
803 silc_server_command_identify_check(SilcServerCommandContext cmd,
804 SilcClientEntry *clients,
805 unsigned int clients_count)
807 SilcServer server = cmd->server;
809 SilcClientEntry entry;
811 for (i = 0; i < clients_count; i++) {
814 if (!entry->nickname) {
816 unsigned short old_ident;
818 old_ident = silc_command_get_ident(cmd->payload);
819 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
820 silc_command_set_command(cmd->payload, SILC_COMMAND_WHOIS);
821 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
823 /* Send WHOIS request. We send WHOIS since we're doing the requesting
824 now anyway so make it a good one. */
825 silc_server_packet_send(server, entry->router->connection,
826 SILC_PACKET_COMMAND, cmd->packet->flags,
827 tmpbuf->data, tmpbuf->len, TRUE);
829 /* Reprocess this packet after received reply */
830 silc_server_command_pending(server, SILC_COMMAND_WHOIS,
831 silc_command_get_ident(cmd->payload),
832 silc_server_command_identify, (void *)cmd);
835 /* Put old data back to the Command Payload we just changed */
836 silc_command_set_ident(cmd->payload, old_ident);
837 silc_command_set_command(cmd->payload, SILC_COMMAND_IDENTIFY);
839 silc_buffer_free(tmpbuf);
848 silc_server_command_identify_send_reply(SilcServerCommandContext cmd,
849 SilcClientEntry *clients,
850 unsigned int clients_count)
852 SilcServer server = cmd->server;
854 int i, count = 0, len;
855 SilcBuffer packet, idp;
856 SilcClientEntry entry;
857 SilcCommandStatus status;
858 unsigned short ident = silc_command_get_ident(cmd->payload);
860 status = SILC_STATUS_OK;
861 if (clients_count > 1)
862 status = SILC_STATUS_LIST_START;
864 for (i = 0; i < clients_count; i++) {
867 if (count && i - 1 == count)
870 if (clients_count > 2)
871 status = SILC_STATUS_LIST_ITEM;
873 if (clients_count > 1 && i == clients_count - 1)
874 status = SILC_STATUS_LIST_END;
876 /* Send IDENTIFY reply */
877 idp = silc_id_payload_encode(entry->id, SILC_ID_CLIENT);
878 tmp = silc_argument_get_first_arg(cmd->args, NULL);
882 char nh[256], uh[256];
883 SilcSocketConnection hsock;
885 memset(uh, 0, sizeof(uh));
886 memset(nh, 0, sizeof(nh));
888 strncat(nh, entry->nickname, strlen(entry->nickname));
889 if (!strchr(entry->nickname, '@')) {
891 len = entry->router ? strlen(entry->router->server_name) :
892 strlen(server->server_name);
893 strncat(nh, entry->router ? entry->router->server_name :
894 server->server_name, len);
897 if (!entry->username) {
898 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
899 SILC_STATUS_OK, ident, 2,
900 2, idp->data, idp->len,
903 strncat(uh, entry->username, strlen(entry->username));
904 if (!strchr(entry->username, '@')) {
906 hsock = (SilcSocketConnection)entry->connection;
907 len = strlen(hsock->hostname);
908 strncat(uh, hsock->hostname, len);
911 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_IDENTIFY,
912 SILC_STATUS_OK, ident, 3,
913 2, idp->data, idp->len,
918 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
919 0, packet->data, packet->len, FALSE);
921 silc_buffer_free(packet);
922 silc_buffer_free(idp);
928 silc_server_command_identify_from_client(SilcServerCommandContext cmd)
930 SilcServer server = cmd->server;
931 char *nick = NULL, *server_name = NULL;
932 int count = 0, clients_count;
933 SilcClientID *client_id = NULL;
934 SilcClientEntry *clients = NULL, entry;
937 /* Parse the IDENTIFY request */
938 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
939 &server_name, &count))
942 /* Protocol dictates that we must always send the received IDENTIFY request
943 to our router if we are normal server, so let's do it now unless we
944 are standalone. We will not send any replies to the client until we
945 have received reply from the router. */
946 if (server->server_type == SILC_SERVER &&
947 !cmd->pending && !server->standalone) {
949 unsigned short old_ident;
951 old_ident = silc_command_get_ident(cmd->payload);
952 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
953 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
955 /* Send IDENTIFY command to our router */
956 silc_server_packet_send(server, (SilcSocketConnection)
957 server->router->connection,
958 SILC_PACKET_COMMAND, cmd->packet->flags,
959 tmpbuf->data, tmpbuf->len, TRUE);
961 /* Reprocess this packet after received reply from router */
962 silc_server_command_pending(server, SILC_COMMAND_IDENTIFY,
963 silc_command_get_ident(cmd->payload),
964 silc_server_command_identify, (void *)cmd);
967 silc_command_set_ident(cmd->payload, old_ident);
969 silc_buffer_free(tmpbuf);
974 /* We are ready to process the command request. Let's search for the
975 requested client and send reply to the requesting client. */
977 /* Get all clients matching that ID or nickname from local list */
979 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
981 clients = silc_calloc(1, sizeof(*clients));
986 clients = silc_idlist_get_clients_by_nickname(server->local_list,
991 /* Check global list as well */
994 entry = silc_idlist_find_client_by_id(server->global_list,
997 clients = silc_calloc(1, sizeof(*clients));
1002 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1009 /* Such a client really does not exist in the SILC network. */
1011 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1012 SILC_STATUS_ERR_NO_SUCH_NICK,
1013 3, nick, strlen(nick));
1015 SilcBuffer idp = silc_id_payload_encode(client_id, SILC_ID_CLIENT);
1016 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1017 SILC_STATUS_ERR_NO_SUCH_CLIENT_ID,
1018 2, idp->data, idp->len);
1019 silc_buffer_free(idp);
1024 /* Check that all mandatory fields are present and request those data
1025 from the server who owns the client if necessary. */
1026 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1027 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1032 /* Send the command reply to the client */
1033 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1039 silc_free(client_id);
1043 silc_free(server_name);
1049 silc_server_command_identify_from_server(SilcServerCommandContext cmd)
1051 SilcServer server = cmd->server;
1052 char *nick = NULL, *server_name = NULL;
1053 int count = 0, clients_count;
1054 SilcClientID *client_id = NULL;
1055 SilcClientEntry *clients = NULL, entry;
1058 /* Parse the IDENTIFY request */
1059 if (!silc_server_command_identify_parse(cmd, &client_id, &nick,
1060 &server_name, &count))
1063 /* Process the command request. Let's search for the requested client and
1064 send reply to the requesting server. */
1067 entry = silc_idlist_find_client_by_id(server->local_list, client_id, NULL);
1069 clients = silc_calloc(1, sizeof(*clients));
1074 clients = silc_idlist_get_clients_by_nickname(server->local_list,
1078 clients = silc_idlist_get_clients_by_hash(server->local_list,
1079 nick, server->md5hash,
1083 /* If we are router we will check our global list as well. */
1084 if (!clients && server->server_type == SILC_ROUTER) {
1086 entry = silc_idlist_find_client_by_id(server->global_list,
1089 clients = silc_calloc(1, sizeof(*clients));
1094 clients = silc_idlist_get_clients_by_nickname(server->global_list,
1098 clients = silc_idlist_get_clients_by_hash(server->global_list,
1099 nick, server->md5hash,
1105 /* Such a client really does not exist in the SILC network. */
1106 silc_server_command_send_status_data(cmd, SILC_COMMAND_IDENTIFY,
1107 SILC_STATUS_ERR_NO_SUCH_NICK,
1108 3, nick, strlen(nick));
1112 /* Check that all mandatory fields are present and request those data
1113 from the server who owns the client if necessary. */
1114 if (!cmd->pending && server->server_type == SILC_ROUTER &&
1115 !silc_server_command_identify_check(cmd, clients, clients_count)) {
1120 /* Send the command reply */
1121 silc_server_command_identify_send_reply(cmd, clients, clients_count);
1127 silc_free(client_id);
1131 silc_free(server_name);
1136 SILC_SERVER_CMD_FUNC(identify)
1138 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1141 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_IDENTIFY, cmd, 1, 3);
1143 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT)
1144 ret = silc_server_command_identify_from_client(cmd);
1146 ret = silc_server_command_identify_from_server(cmd);
1149 silc_server_command_free(cmd);
1152 /* Checks string for bad characters and returns TRUE if they are found. */
1154 static int silc_server_command_bad_chars(char *nick)
1156 if (strchr(nick, '\\')) return TRUE;
1157 if (strchr(nick, '\"')) return TRUE;
1158 if (strchr(nick, '´')) return TRUE;
1159 if (strchr(nick, '`')) return TRUE;
1160 if (strchr(nick, '\'')) return TRUE;
1161 if (strchr(nick, '*')) return TRUE;
1162 if (strchr(nick, '/')) return TRUE;
1163 if (strchr(nick, '@')) return TRUE;
1168 /* Server side of command NICK. Sets nickname for user. Setting
1169 nickname causes generation of a new client ID for the client. The
1170 new client ID is sent to the client after changing the nickname. */
1172 SILC_SERVER_CMD_FUNC(nick)
1174 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1175 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1176 SilcServer server = cmd->server;
1177 SilcBuffer packet, nidp, oidp;
1178 SilcClientID *new_id;
1181 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NICK, cmd, 1, 1);
1183 /* Check nickname */
1184 nick = silc_argument_get_arg_type(cmd->args, 1, NULL);
1185 if (silc_server_command_bad_chars(nick) == TRUE) {
1186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_NICK,
1187 SILC_STATUS_ERR_BAD_NICKNAME);
1191 /* Create new Client ID */
1192 silc_id_create_client_id(cmd->server->id, cmd->server->rng,
1193 cmd->server->md5hash, nick,
1196 /* Send notify about nickname change to our router. We send the new
1197 ID and ask to replace it with the old one. If we are router the
1198 packet is broadcasted. */
1199 if (!cmd->server->standalone)
1200 silc_server_send_replace_id(server, server->router->connection,
1201 server->server_type == SILC_SERVER ?
1202 FALSE : TRUE, client->id,
1203 SILC_ID_CLIENT, SILC_ID_CLIENT_LEN,
1204 new_id, SILC_ID_CLIENT, SILC_ID_CLIENT_LEN);
1206 /* Remove old cache entry */
1207 silc_idcache_del_by_id(server->local_list->clients, SILC_ID_CLIENT,
1210 oidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1214 memset(client->id, 0, SILC_ID_CLIENT_LEN);
1215 silc_free(client->id);
1218 /* Save the nickname as this client is our local client */
1219 if (client->nickname)
1220 silc_free(client->nickname);
1222 client->nickname = strdup(nick);
1223 client->id = new_id;
1225 /* Update client cache */
1226 silc_idcache_add(server->local_list->clients, client->nickname,
1227 SILC_ID_CLIENT, client->id, (void *)client, TRUE);
1229 nidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1231 /* Send NICK_CHANGE notify */
1232 silc_server_send_notify_on_channels(server, client,
1233 SILC_NOTIFY_TYPE_NICK_CHANGE, 2,
1234 oidp->data, oidp->len,
1235 nidp->data, nidp->len);
1237 /* Send the new Client ID as reply command back to client */
1238 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NICK,
1239 SILC_STATUS_OK, 0, 1,
1240 2, nidp->data, nidp->len);
1241 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1242 0, packet->data, packet->len, FALSE);
1244 silc_buffer_free(packet);
1245 silc_buffer_free(nidp);
1246 silc_buffer_free(oidp);
1249 silc_server_command_free(cmd);
1252 SILC_SERVER_CMD_FUNC(list)
1256 /* Server side of TOPIC command. Sets topic for channel and/or returns
1257 current topic to client. */
1259 SILC_SERVER_CMD_FUNC(topic)
1261 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1262 SilcServer server = cmd->server;
1263 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
1264 SilcChannelID *channel_id;
1265 SilcChannelEntry channel;
1266 SilcChannelClientEntry chl;
1267 SilcBuffer packet, idp;
1269 unsigned int argc, tmp_len;
1271 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_TOPIC, cmd, 1, 2);
1273 argc = silc_argument_get_arg_num(cmd->args);
1275 /* Get Channel ID */
1276 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1278 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1279 SILC_STATUS_ERR_NO_CHANNEL_ID);
1282 channel_id = silc_id_payload_parse_id(tmp, tmp_len);
1284 /* Check whether the channel exists */
1285 channel = silc_idlist_find_channel_by_id(server->local_list,
1288 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1289 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1295 tmp = silc_argument_get_arg_type(cmd->args, 2, NULL);
1297 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1298 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1302 if (strlen(tmp) > 256) {
1303 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1304 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1308 /* See whether has rights to change topic */
1309 silc_list_start(channel->user_list);
1310 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
1311 if (chl->client == client) {
1312 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1313 silc_server_command_send_status_reply(cmd, SILC_COMMAND_TOPIC,
1314 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1322 /* Set the topic for channel */
1324 silc_free(channel->topic);
1325 channel->topic = strdup(tmp);
1327 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1329 /* Send notify about topic change to all clients on the channel */
1330 silc_server_send_notify_to_channel(server, channel, TRUE,
1331 SILC_NOTIFY_TYPE_TOPIC_SET, 2,
1332 idp->data, idp->len,
1333 channel->topic, strlen(channel->topic));
1334 silc_buffer_free(idp);
1337 /* Send the topic to client as reply packet */
1338 idp = silc_id_payload_encode(channel_id, SILC_ID_CHANNEL);
1340 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1341 SILC_STATUS_OK, 0, 2,
1342 2, idp->data, idp->len,
1344 strlen(channel->topic));
1346 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_TOPIC,
1347 SILC_STATUS_OK, 0, 1,
1348 2, idp->data, idp->len);
1349 silc_server_packet_send(cmd->server, cmd->sock, SILC_PACKET_COMMAND_REPLY,
1350 0, packet->data, packet->len, FALSE);
1352 silc_buffer_free(packet);
1353 silc_buffer_free(idp);
1354 silc_free(channel_id);
1357 silc_server_command_free(cmd);
1360 /* Server side of INVITE command. Invites some client to join some channel. */
1362 SILC_SERVER_CMD_FUNC(invite)
1364 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1365 SilcServer server = cmd->server;
1366 SilcSocketConnection sock = cmd->sock, dest_sock;
1367 SilcClientEntry sender, dest;
1368 SilcClientID *dest_id;
1369 SilcChannelEntry channel;
1370 SilcChannelID *channel_id;
1375 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INVITE, cmd, 1, 2);
1377 /* Get destination ID */
1378 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1380 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1381 SILC_STATUS_ERR_NO_CLIENT_ID);
1384 dest_id = silc_id_payload_parse_id(tmp, len);
1386 /* Get Channel ID */
1387 tmp = silc_argument_get_arg_type(cmd->args, 2, &len);
1389 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1390 SILC_STATUS_ERR_NO_CHANNEL_ID);
1393 channel_id = silc_id_payload_parse_id(tmp, len);
1395 /* Check whether the channel exists */
1396 channel = silc_idlist_find_channel_by_id(server->local_list,
1399 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1400 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
1404 /* Check whether the sender of this command is on the channel. */
1405 sender = (SilcClientEntry)sock->user_data;
1406 if (!silc_server_client_on_channel(sender, channel)) {
1407 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1408 SILC_STATUS_ERR_NOT_ON_CHANNEL);
1412 /* Check whether the channel is invite-only channel. If yes then the
1413 sender of this command must be at least channel operator. */
1414 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1415 SilcChannelClientEntry chl;
1417 silc_list_start(channel->user_list);
1418 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
1419 if (chl->client == sender) {
1420 if (chl->mode == SILC_CHANNEL_UMODE_NONE) {
1421 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1422 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
1429 /* Find the connection data for the destination. If it is local we will
1430 send it directly otherwise we will send it to router for routing. */
1431 dest = silc_idlist_find_client_by_id(server->local_list, dest_id, NULL);
1433 dest_sock = (SilcSocketConnection)dest->connection;
1435 dest_sock = silc_server_route_get(server, dest_id, SILC_ID_CLIENT);
1437 /* Check whether the requested client is already on the channel. */
1438 /* XXX if we are normal server we don't know about global clients on
1439 the channel thus we must request it (NAMES command), check from
1440 local cache as well. */
1441 if (silc_server_client_on_channel(dest, channel)) {
1442 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1443 SILC_STATUS_ERR_USER_ON_CHANNEL);
1447 sidp = silc_id_payload_encode(sender->id, SILC_ID_CLIENT);
1449 /* Send notify to the client that is invited to the channel */
1450 silc_server_send_notify_dest(server, dest_sock, dest_id, SILC_ID_CLIENT,
1451 SILC_NOTIFY_TYPE_INVITE, 2,
1452 sidp->data, sidp->len, tmp, len);
1454 /* Send command reply */
1455 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
1458 silc_buffer_free(sidp);
1461 silc_server_command_free(cmd);
1464 /* Quits connection to client. This gets called if client won't
1465 close the connection even when it has issued QUIT command. */
1467 SILC_TASK_CALLBACK(silc_server_command_quit_cb)
1469 SilcServer server = (SilcServer)context;
1470 SilcSocketConnection sock = server->sockets[fd];
1472 /* Free all client specific data, such as client entry and entires
1473 on channels this client may be on. */
1474 silc_server_free_sock_user_data(server, sock);
1476 /* Close the connection on our side */
1477 silc_server_close_connection(server, sock);
1480 /* Quits SILC session. This is the normal way to disconnect client. */
1482 SILC_SERVER_CMD_FUNC(quit)
1484 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1485 SilcServer server = cmd->server;
1486 SilcSocketConnection sock = cmd->sock;
1488 SILC_LOG_DEBUG(("Start"));
1490 /* We quit the connection with little timeout */
1491 silc_task_register(server->timeout_queue, sock->sock,
1492 silc_server_command_quit_cb, server,
1493 0, 300000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1495 silc_server_command_free(cmd);
1498 SILC_SERVER_CMD_FUNC(kill)
1502 /* Server side of command INFO. This sends information about us to
1503 the client. If client requested specific server we will send the
1504 command to that server. */
1506 SILC_SERVER_CMD_FUNC(info)
1508 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1509 SilcServer server = cmd->server;
1510 SilcBuffer packet, idp;
1511 char info_string[256], *dest_server;
1513 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 1);
1515 /* Get server name */
1516 dest_server = silc_argument_get_arg_type(cmd->args, 1, NULL);
1518 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INFO,
1519 SILC_STATUS_ERR_NO_SUCH_SERVER);
1523 if (!strncasecmp(dest_server, server->server_name, strlen(dest_server))) {
1524 /* Send our reply */
1525 memset(info_string, 0, sizeof(info_string));
1526 snprintf(info_string, sizeof(info_string),
1527 "location: %s server: %s admin: %s <%s>",
1528 server->config->admin_info->location,
1529 server->config->admin_info->server_type,
1530 server->config->admin_info->admin_name,
1531 server->config->admin_info->admin_email);
1533 idp = silc_id_payload_encode(server->id, SILC_ID_SERVER);
1535 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_INFO,
1536 SILC_STATUS_OK, 0, 2,
1537 2, idp->data, idp->len,
1539 strlen(info_string));
1540 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
1541 packet->data, packet->len, FALSE);
1543 silc_buffer_free(packet);
1544 silc_buffer_free(idp);
1546 /* Send this command to the requested server */
1548 if (server->server_type == SILC_SERVER && !server->standalone) {
1552 if (server->server_type == SILC_ROUTER) {
1558 silc_server_command_free(cmd);
1561 SILC_SERVER_CMD_FUNC(connect)
1565 /* Server side of command PING. This just replies to the ping. */
1567 SILC_SERVER_CMD_FUNC(ping)
1569 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1570 SilcServer server = cmd->server;
1575 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_INFO, cmd, 1, 2);
1578 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
1580 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1581 SILC_STATUS_ERR_NO_SERVER_ID);
1584 id = silc_id_str2id(tmp, SILC_ID_SERVER);
1588 if (!SILC_ID_SERVER_COMPARE(id, server->id)) {
1589 /* Send our reply */
1590 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1593 silc_server_command_send_status_reply(cmd, SILC_COMMAND_PING,
1594 SILC_STATUS_ERR_NO_SUCH_SERVER);
1601 silc_server_command_free(cmd);
1604 SILC_SERVER_CMD_FUNC(oper)
1613 SilcChannelEntry channel;
1615 SilcClientEntry client;
1616 } JoinInternalContext;
1618 SILC_TASK_CALLBACK(silc_server_command_join_notify)
1620 JoinInternalContext *ctx = (JoinInternalContext *)context;
1622 if (ctx->channel->key && ctx->channel->key_len) {
1625 clidp = silc_id_payload_encode(ctx->client->id, SILC_ID_CLIENT);
1627 silc_server_send_notify_to_channel(ctx->server, ctx->channel, FALSE,
1628 SILC_NOTIFY_TYPE_JOIN, 1,
1629 clidp->data, clidp->len);
1631 /* Send NEW_CHANNEL_USER packet to primary route */
1632 silc_server_send_new_channel_user(server, server->router->connection,
1633 server->server_type == SILC_SERVER ?
1635 channel->id, SILC_ID_CHANNEL_LEN,
1636 client->id, SILC_ID_CLIENT_LEN);
1639 /* Send NAMES command reply to the joined channel so the user sees who
1640 is currently on the channel. */
1641 silc_server_command_send_names(ctx->server, ctx->client->connection,
1644 silc_buffer_free(clidp);
1647 silc_task_register(ctx->server->timeout_queue, fd,
1648 silc_server_command_join_notify, context,
1649 0, 200000, SILC_TASK_TIMEOUT, SILC_TASK_PRI_LOW);
1653 /* Assembles NAMES command and executes it. This is called when client
1654 joins to a channel and we wan't to send NAMES command reply to the
1657 void silc_server_command_send_names(SilcServer server,
1658 SilcSocketConnection sock,
1659 SilcChannelEntry channel)
1661 SilcServerCommandContext cmd;
1662 SilcBuffer buffer, idp;
1664 idp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1665 buffer = silc_command_payload_encode_va(SILC_COMMAND_NAMES, 0, 1,
1666 1, idp->data, idp->len);
1668 cmd = silc_calloc(1, sizeof(*cmd));
1669 cmd->payload = silc_command_payload_parse(buffer);
1670 cmd->args = silc_command_get_args(cmd->payload);
1671 cmd->server = server;
1673 cmd->pending = FALSE;
1675 silc_server_command_names((void *)cmd);
1680 /* Internal routine that is called after router has replied to server's
1681 JOIN command it forwarded to the router. The route has joined and possibly
1682 creaetd the channel. This function adds the client to the channel's user
1685 SILC_SERVER_CMD_FUNC(add_to_channel)
1687 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1688 SilcServer server = cmd->server;
1689 SilcClientEntry client;
1690 SilcChannelEntry channel;
1691 SilcChannelClientEntry chl;
1694 /* Get channel name */
1695 channel_name = silc_argument_get_arg_type(cmd->args, 1, NULL);
1697 /* Get client entry */
1698 client = (SilcClientEntry)cmd->sock->user_data;
1700 /* Get channel entry */
1701 channel = silc_idlist_find_channel_by_name(server->local_list,
1702 channel_name, NULL);
1704 /* Join the client to the channel by adding it to channel's user list.
1705 Add also the channel to client entry's channels list for fast cross-
1707 chl = silc_calloc(1, sizeof(*chl));
1708 //chl->mode = SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO;
1709 chl->client = client;
1710 chl->channel = channel;
1711 silc_list_add(channel->user_list, chl);
1712 silc_list_add(client->channels, chl);
1715 silc_server_command_free(cmd);
1718 /* Internal routine to join channel. The channel sent to this function
1719 has been either created or resolved from ID lists. This joins the sent
1720 client to the channel. */
1722 static void silc_server_command_join_channel(SilcServer server,
1723 SilcServerCommandContext cmd,
1724 SilcChannelEntry channel,
1725 SilcClientID *client_id,
1729 SilcSocketConnection sock = cmd->sock;
1731 unsigned int tmp_len;
1732 unsigned char *passphrase = NULL, mode[4], tmp2[4];
1733 SilcClientEntry client;
1734 SilcChannelClientEntry chl;
1735 SilcBuffer reply, chidp, clidp, keyp;
1736 unsigned short ident = silc_command_get_ident(cmd->payload);
1738 SILC_LOG_DEBUG(("Start"));
1743 /* Get passphrase */
1744 tmp = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
1746 passphrase = silc_calloc(tmp_len, sizeof(*passphrase));
1747 memcpy(passphrase, tmp, tmp_len);
1751 * Check channel modes
1754 /* Check invite list if channel is invite-only channel */
1755 if (channel->mode & SILC_CHANNEL_MODE_INVITE) {
1756 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
1757 /* Invite list is specified. Check whether client is invited in the
1758 list. If not, then check whether it has been invited otherwise. */
1761 /* XXX client must be invited to be able to join the channel */
1765 /* Check ban list if set */
1766 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
1770 /* Check the channel passphrase if set. */
1771 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
1772 if (!passphrase || memcmp(channel->mode_data.passphrase, passphrase,
1773 strlen(channel->mode_data.passphrase))) {
1774 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1775 SILC_STATUS_ERR_BAD_PASSWORD);
1780 /* Check user count limit if set. */
1781 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT) {
1782 if (silc_list_count(channel->user_list) + 1 >
1783 channel->mode_data.user_limit) {
1784 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1785 SILC_STATUS_ERR_CHANNEL_IS_FULL);
1791 * Client is allowed to join to the channel. Make it happen.
1794 /* Get the client entry */
1795 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1796 client = (SilcClientEntry)sock->user_data;
1798 client = silc_idlist_find_client_by_id(server->local_list, client_id,
1801 /* XXX actually this is useless since router finds always cell's
1802 local clients from its local lists. */
1803 client = silc_idlist_find_client_by_id(server->global_list, client_id,
1810 /* Check whether the client already is on the channel */
1811 if (silc_server_client_on_channel(client, channel)) {
1812 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1813 SILC_STATUS_ERR_USER_ON_CHANNEL);
1817 /* Generate new channel key as protocol dictates */
1818 if (!created || !channel->channel_key)
1819 silc_server_create_channel_key(server, channel, 0);
1821 /* Send the channel key. This is broadcasted to the channel but is not
1822 sent to the client who is joining to the channel. */
1823 silc_server_send_channel_key(server, channel,
1824 server->server_type == SILC_ROUTER ?
1825 FALSE : server->standalone);
1827 /* Join the client to the channel by adding it to channel's user list.
1828 Add also the channel to client entry's channels list for fast cross-
1830 chl = silc_calloc(1, sizeof(*chl));
1832 chl->client = client;
1833 chl->channel = channel;
1834 silc_list_add(channel->user_list, chl);
1835 silc_list_add(client->channels, chl);
1837 /* Encode Client ID Payload of the original client who wants to join */
1838 clidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
1840 /* Encode command reply packet */
1841 chidp = silc_id_payload_encode(channel->id, SILC_ID_CHANNEL);
1842 SILC_PUT32_MSB(channel->mode, mode);
1843 SILC_PUT32_MSB(created, tmp2);
1844 tmp = silc_id_id2str(channel->id, SILC_ID_CHANNEL);
1845 keyp = silc_channel_key_payload_encode(SILC_ID_CHANNEL_LEN, tmp,
1846 SILC_ID_CHANNEL_LEN,
1847 channel->channel_key->cipher->name,
1848 channel->key_len / 8, channel->key);
1850 if (!channel->topic) {
1852 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1853 SILC_STATUS_OK, ident, 5,
1854 2, channel->channel_name,
1855 strlen(channel->channel_name),
1856 3, chidp->data, chidp->len,
1859 6, keyp->data, keyp->len);
1862 silc_command_reply_payload_encode_va(SILC_COMMAND_JOIN,
1863 SILC_STATUS_OK, ident, 6,
1864 2, channel->channel_name,
1865 strlen(channel->channel_name),
1866 3, chidp->data, chidp->len,
1869 6, keyp->data, keyp->len,
1871 strlen(channel->topic));
1874 /* Send command reply */
1875 silc_server_packet_send(server, sock, SILC_PACKET_COMMAND_REPLY, 0,
1876 reply->data, reply->len, FALSE);
1879 /* Send JOIN notify to locally connected clients on the channel */
1880 silc_server_send_notify_to_channel(server, channel, FALSE,
1881 SILC_NOTIFY_TYPE_JOIN, 1,
1882 clidp->data, clidp->len);
1884 /* Send NEW_CHANNEL_USER packet to our primary router */
1885 if (!cmd->pending && !server->standalone)
1886 silc_server_send_new_channel_user(server, server->router->connection,
1887 server->server_type == SILC_SERVER ?
1889 channel->id, SILC_ID_CHANNEL_LEN,
1890 client->id, SILC_ID_CLIENT_LEN);
1892 /* Send NAMES command reply to the joined channel so the user sees who
1893 is currently on the channel. */
1894 silc_server_command_send_names(server, sock, channel);
1900 * Kuinka NAMES komento händlätään serverissä kun router lähettää sen
1901 serverille joka on lähettäny sille clientin puolesta JOIN komennon?
1903 R: Serverin pitää ymmärtää NAMES comman replyjä.
1907 silc_buffer_free(reply);
1908 silc_buffer_free(clidp);
1909 silc_buffer_free(chidp);
1910 silc_buffer_free(keyp);
1914 silc_free(passphrase);
1917 /* Server side of command JOIN. Joins client into requested channel. If
1918 the channel does not exist it will be created. */
1920 SILC_SERVER_CMD_FUNC(join)
1922 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
1923 SilcServer server = cmd->server;
1925 char *tmp, *channel_name = NULL, *cipher = NULL;
1926 SilcChannelEntry channel;
1927 unsigned int umode = 0;
1928 int created = FALSE;
1929 SilcClientID *client_id;
1931 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_JOIN, cmd, 1, 4);
1933 /* Get channel name */
1934 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
1936 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1937 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1942 if (silc_server_command_bad_chars(channel_name) == TRUE) {
1943 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1944 SILC_STATUS_ERR_BAD_CHANNEL);
1945 silc_free(channel_name);
1949 /* Get Client ID of the client who is joining to the channel */
1950 tmp = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
1952 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1953 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1956 client_id = silc_id_payload_parse_id(tmp, tmp_len);
1958 /* Get cipher name */
1959 cipher = silc_argument_get_arg_type(cmd->args, 4, NULL);
1961 /* See if the channel exists */
1962 channel = silc_idlist_find_channel_by_name(server->local_list,
1963 channel_name, NULL);
1965 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1966 /* If this is coming from client the Client ID in the command packet must
1967 be same as the client's ID. */
1968 if (cmd->sock->type == SILC_SOCKET_TYPE_CLIENT) {
1969 SilcClientEntry entry = (SilcClientEntry)cmd->sock->user_data;
1970 if (SILC_ID_CLIENT_COMPARE(entry->id, client_id)) {
1971 silc_server_command_send_status_reply(cmd, SILC_COMMAND_JOIN,
1972 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
1978 /* Channel not found */
1980 /* If we are standalone server we don't have a router, we just create
1981 the channel by ourselves. */
1982 if (server->standalone) {
1983 channel = silc_server_create_new_channel(server, server->id, cipher,
1985 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
1990 /* The channel does not exist on our server. If we are normal server
1991 we will send JOIN command to our router which will handle the
1992 joining procedure (either creates the channel if it doesn't exist
1993 or joins the client to it). */
1994 if (server->server_type == SILC_SERVER) {
1996 unsigned short old_ident;
1998 old_ident = silc_command_get_ident(cmd->payload);
1999 silc_command_set_ident(cmd->payload, silc_rng_get_rn16(server->rng));
2000 tmpbuf = silc_command_payload_encode_payload(cmd->payload);
2002 /* Send JOIN command to our router */
2003 silc_server_packet_send(server, (SilcSocketConnection)
2004 server->router->connection,
2005 SILC_PACKET_COMMAND, cmd->packet->flags,
2006 tmpbuf->data, tmpbuf->len, TRUE);
2008 /* Reprocess this packet after received reply from router */
2009 silc_server_command_pending(server, SILC_COMMAND_JOIN,
2010 silc_command_get_ident(cmd->payload),
2011 silc_server_command_join, context);
2012 cmd->pending = TRUE;
2016 /* We are router and the channel does not seem exist so we will check
2017 our global list as well for the channel. */
2018 channel = silc_idlist_find_channel_by_name(server->global_list,
2019 channel_name, NULL);
2021 /* Channel really does not exist, create it */
2022 channel = silc_server_create_new_channel(server, server->id, cipher,
2024 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2031 /* Channel not found */
2033 /* If the command came from router and/or we are normal server then
2034 something went wrong with the joining as the channel was not found.
2035 We can't do anything else but ignore this. */
2036 if (cmd->sock->type == SILC_SOCKET_TYPE_ROUTER ||
2037 server->server_type == SILC_SERVER)
2040 /* We are router and the channel does not seem exist so we will check
2041 our global list as well for the channel. */
2042 channel = silc_idlist_find_channel_by_name(server->global_list,
2043 channel_name, NULL);
2045 /* Channel really does not exist, create it */
2046 channel = silc_server_create_new_channel(server, server->id, cipher,
2048 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2054 /* If the channel does not have global users and is also empty it means the
2055 channel was created globally (by our router) and the client will be the
2056 channel founder and operator. */
2057 if (!channel->global_users && silc_list_count(channel->user_list) == 0) {
2058 umode = (SILC_CHANNEL_UMODE_CHANOP | SILC_CHANNEL_UMODE_CHANFO);
2059 created = TRUE; /* Created globally by our router */
2062 /* Join to the channel */
2063 silc_server_command_join_channel(server, cmd, channel, client_id,
2066 silc_free(client_id);
2069 silc_server_command_free(cmd);
2072 /* Server side of command MOTD. Sends server's current "message of the
2073 day" to the client. */
2075 SILC_SERVER_CMD_FUNC(motd)
2077 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2078 SilcServer server = cmd->server;
2082 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_MOTD, cmd, 1, 2);
2084 /* XXX show currently only our motd */
2086 if (server->config && server->config->motd &&
2087 server->config->motd->motd_file) {
2090 motd = silc_file_read(server->config->motd->motd_file, &motd_len);
2095 silc_server_command_send_status_data(cmd, SILC_COMMAND_MOTD,
2101 silc_server_command_send_status_reply(cmd, SILC_COMMAND_MOTD,
2106 silc_server_command_free(cmd);
2109 SILC_SERVER_CMD_FUNC(umode)
2113 /* Checks that client has rights to add or remove channel modes. If any
2114 of the checks fails FALSE is returned. */
2116 int silc_server_check_cmode_rights(SilcChannelEntry channel,
2117 SilcChannelClientEntry client,
2120 int is_op = client->mode & SILC_CHANNEL_UMODE_CHANOP;
2121 int is_fo = client->mode & SILC_CHANNEL_UMODE_CHANFO;
2123 /* Check whether has rights to change anything */
2124 if (!is_op && !is_fo)
2127 /* Check whether has rights to change everything */
2131 /* We know that client is channel operator, check that they are not
2132 changing anything that requires channel founder rights. Rest of the
2133 modes are available automatically for channel operator. */
2135 if (mode & SILC_CHANNEL_MODE_PRIVKEY) {
2136 if (is_op && !is_fo)
2139 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2140 if (is_op && !is_fo)
2145 if (mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2146 if (is_op && !is_fo)
2149 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2150 if (is_op && !is_fo)
2155 if (mode & SILC_CHANNEL_MODE_CIPHER) {
2156 if (is_op && !is_fo)
2159 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2160 if (is_op && !is_fo)
2168 /* Server side command of CMODE. Changes channel mode */
2170 SILC_SERVER_CMD_FUNC(cmode)
2172 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2173 SilcServer server = cmd->server;
2174 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2175 SilcChannelID *channel_id;
2176 SilcChannelEntry channel;
2177 SilcChannelClientEntry chl;
2178 SilcBuffer packet, cidp;
2179 unsigned char *tmp, *tmp_id, *tmp_mask;
2180 unsigned int argc, mode_mask, tmp_len, tmp_len2;
2182 SILC_LOG_DEBUG(("Start"));
2184 argc = silc_argument_get_arg_num(cmd->args);
2186 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2187 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2191 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2192 SILC_STATUS_ERR_TOO_MANY_PARAMS);
2196 /* Get Channel ID */
2197 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len2);
2199 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2200 SILC_STATUS_ERR_NO_CHANNEL_ID);
2203 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len2);
2205 /* Get the channel mode mask */
2206 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, &tmp_len);
2208 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2209 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2212 SILC_GET32_MSB(mode_mask, tmp_mask);
2214 /* Get channel entry */
2215 channel = silc_idlist_find_channel_by_id(server->local_list,
2218 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2219 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2223 /* Check whether this client is on the channel */
2224 if (!silc_server_client_on_channel(client, channel)) {
2225 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2226 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2230 /* Get entry to the channel user list */
2231 silc_list_start(channel->user_list);
2232 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2233 if (chl->client == client)
2236 /* Check that client has rights to change any requested channel modes */
2237 if (!silc_server_check_cmode_rights(channel, chl, mode_mask)) {
2238 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2239 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2244 * Check the modes. Modes that requires nothing special operation are
2248 if (mode_mask & SILC_CHANNEL_MODE_PRIVKEY) {
2249 /* Channel uses private keys to protect traffic. Client(s) has set the
2250 key locally they want to use, server does not know that key. */
2251 /* Nothing interesting to do here now */
2253 if (channel->mode & SILC_CHANNEL_MODE_PRIVKEY) {
2254 /* The mode is removed and we need to generate and distribute
2255 new channel key. Clients are not using private channel keys
2256 anymore after this. */
2258 /* XXX Duplicated code, make own function for this!! LEAVE uses this
2261 /* Re-generate channel key */
2262 silc_server_create_channel_key(server, channel, 0);
2264 /* Encode channel key payload to be distributed on the channel */
2266 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2267 strlen(channel->channel_key->
2269 channel->channel_key->cipher->name,
2270 channel->key_len / 8, channel->key);
2272 /* If we are normal server then we will send it to our router. If we
2273 are router we will send it to all local servers that has clients on
2275 if (server->server_type == SILC_SERVER) {
2276 if (!server->standalone)
2277 silc_server_packet_send(server,
2278 cmd->server->router->connection,
2279 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2285 /* Send to locally connected clients on the channel */
2286 silc_server_packet_send_local_channel(server, channel,
2287 SILC_PACKET_CHANNEL_KEY, 0,
2288 packet->data, packet->len, FALSE);
2289 silc_buffer_free(packet);
2293 if (mode_mask & SILC_CHANNEL_MODE_ULIMIT) {
2294 /* User limit is set on channel */
2295 unsigned int user_limit;
2297 /* Get user limit */
2298 tmp = silc_argument_get_arg_type(cmd->args, 3, NULL);
2300 if (!(channel->mode & SILC_CHANNEL_MODE_ULIMIT)) {
2301 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2302 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2306 SILC_GET32_MSB(user_limit, tmp);
2307 channel->mode_data.user_limit = user_limit;
2310 if (channel->mode & SILC_CHANNEL_MODE_ULIMIT)
2311 /* User limit mode is unset. Remove user limit */
2312 channel->mode_data.user_limit = 0;
2315 if (mode_mask & SILC_CHANNEL_MODE_PASSPHRASE) {
2316 if (!(channel->mode & SILC_CHANNEL_MODE_PASSPHRASE)) {
2317 /* Passphrase has been set to channel */
2319 /* Get the passphrase */
2320 tmp = silc_argument_get_arg_type(cmd->args, 4, NULL);
2322 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2323 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2327 /* Save the passphrase */
2328 channel->mode_data.passphrase = strdup(tmp);
2331 if (channel->mode & SILC_CHANNEL_MODE_PASSPHRASE) {
2332 /* Passphrase mode is unset. remove the passphrase */
2333 if (channel->mode_data.passphrase) {
2334 silc_free(channel->mode_data.passphrase);
2335 channel->mode_data.passphrase = NULL;
2340 if (mode_mask & SILC_CHANNEL_MODE_BAN) {
2341 if (!(channel->mode & SILC_CHANNEL_MODE_BAN)) {
2342 /* Ban list is specified for channel */
2345 tmp = silc_argument_get_arg_type(cmd->args, 5, NULL);
2347 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2348 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2352 /* XXX check that channel founder is not banned */
2354 /* Save the ban list */
2355 channel->mode_data.ban_list = strdup(tmp);
2358 if (channel->mode & SILC_CHANNEL_MODE_BAN) {
2359 /* Ban mode is unset. Remove the entire ban list */
2360 if (channel->mode_data.ban_list) {
2361 silc_free(channel->mode_data.ban_list);
2362 channel->mode_data.ban_list = NULL;
2367 if (mode_mask & SILC_CHANNEL_MODE_INVITE_LIST) {
2368 if (!(channel->mode & SILC_CHANNEL_MODE_INVITE_LIST)) {
2369 /* Invite list is specified for channel */
2371 /* Get invite list */
2372 tmp = silc_argument_get_arg_type(cmd->args, 6, NULL);
2374 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2375 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2379 /* Save the invite linst */
2380 channel->mode_data.invite_list = strdup(tmp);
2383 if (channel->mode & SILC_CHANNEL_MODE_INVITE_LIST) {
2384 /* Invite list mode is unset. Remove the entire invite list */
2385 if (channel->mode_data.invite_list) {
2386 silc_free(channel->mode_data.invite_list);
2387 channel->mode_data.invite_list = NULL;
2392 if (mode_mask & SILC_CHANNEL_MODE_CIPHER) {
2393 if (!(channel->mode & SILC_CHANNEL_MODE_CIPHER)) {
2394 /* Cipher to use protect the traffic */
2395 unsigned int key_len = 128;
2399 tmp = silc_argument_get_arg_type(cmd->args, 8, NULL);
2401 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CMODE,
2402 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2406 cp = strchr(tmp, ':');
2412 /* XXX Duplicated code, make own function for this!! */
2414 /* Delete old cipher and allocate the new one */
2415 silc_cipher_free(channel->channel_key);
2416 silc_cipher_alloc(tmp, &channel->channel_key);
2422 /* Re-generate channel key */
2423 silc_server_create_channel_key(server, channel, key_len);
2425 /* Encode channel key payload to be distributed on the channel */
2427 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2428 strlen(channel->channel_key->
2430 channel->channel_key->cipher->name,
2431 channel->key_len / 8, channel->key);
2433 /* If we are normal server then we will send it to our router. If we
2434 are router we will send it to all local servers that has clients on
2436 if (server->server_type == SILC_SERVER) {
2437 if (!server->standalone)
2438 silc_server_packet_send(server,
2439 cmd->server->router->connection,
2440 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2446 /* Send to locally connected clients on the channel */
2447 silc_server_packet_send_local_channel(server, channel,
2448 SILC_PACKET_CHANNEL_KEY, 0,
2449 packet->data, packet->len, FALSE);
2450 silc_buffer_free(packet);
2453 if (channel->mode & SILC_CHANNEL_MODE_CIPHER) {
2454 /* Cipher mode is unset. Remove the cipher and revert back to
2457 if (channel->mode_data.cipher) {
2458 silc_free(channel->mode_data.cipher);
2459 channel->mode_data.cipher = NULL;
2460 channel->mode_data.key_len = 0;
2463 /* Generate new cipher and key for the channel */
2465 /* XXX Duplicated code, make own function for this!! */
2467 /* Delete old cipher and allocate default one */
2468 silc_cipher_free(channel->channel_key);
2469 if (!channel->cipher)
2470 silc_cipher_alloc("twofish", &channel->channel_key);
2472 silc_cipher_alloc(channel->cipher, &channel->channel_key);
2474 /* Re-generate channel key */
2475 silc_server_create_channel_key(server, channel, 0);
2477 /* Encode channel key payload to be distributed on the channel */
2479 silc_channel_key_payload_encode(tmp_len2, tmp_id,
2480 strlen(channel->channel_key->
2482 channel->channel_key->cipher->name,
2483 channel->key_len / 8, channel->key);
2485 /* If we are normal server then we will send it to our router. If we
2486 are router we will send it to all local servers that has clients on
2488 if (server->server_type == SILC_SERVER) {
2489 if (!server->standalone)
2490 silc_server_packet_send(server,
2491 cmd->server->router->connection,
2492 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2498 /* Send to locally connected clients on the channel */
2499 silc_server_packet_send_local_channel(server, channel,
2500 SILC_PACKET_CHANNEL_KEY, 0,
2501 packet->data, packet->len, FALSE);
2502 silc_buffer_free(packet);
2506 /* Finally, set the mode */
2507 channel->mode = mode_mask;
2509 /* Send CMODE_CHANGE notify */
2510 cidp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2511 silc_server_send_notify_to_channel(server, channel, TRUE,
2512 SILC_NOTIFY_TYPE_CMODE_CHANGE, 2,
2513 cidp->data, cidp->len,
2517 /* Send command reply to sender */
2518 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CMODE,
2519 SILC_STATUS_OK, 0, 1,
2521 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2522 packet->data, packet->len, FALSE);
2524 silc_buffer_free(packet);
2525 silc_free(channel_id);
2528 silc_server_command_free(cmd);
2531 /* Server side of CUMODE command. Changes client's mode on a channel. */
2533 SILC_SERVER_CMD_FUNC(cumode)
2535 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2536 SilcServer server = cmd->server;
2537 SilcClientEntry client = (SilcClientEntry)cmd->sock->user_data;
2538 SilcChannelID *channel_id;
2539 SilcClientID *client_id;
2540 SilcChannelEntry channel;
2541 SilcClientEntry target_client;
2542 SilcChannelClientEntry chl;
2543 SilcBuffer packet, idp;
2544 unsigned char *tmp_id, *tmp_mask;
2545 unsigned int target_mask, sender_mask, tmp_len;
2548 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_CUMODE, cmd, 3, 3);
2550 /* Get Channel ID */
2551 tmp_id = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2553 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2554 SILC_STATUS_ERR_NO_CHANNEL_ID);
2557 channel_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2559 /* Get channel entry */
2560 channel = silc_idlist_find_channel_by_id(server->local_list,
2563 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2564 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2568 /* Check whether sender is on the channel */
2569 if (!silc_server_client_on_channel(client, channel)) {
2570 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2571 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2575 /* Check that client has rights to change other's rights */
2576 silc_list_start(channel->user_list);
2577 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2578 if (chl->client == client) {
2579 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANFO) &&
2580 !(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2581 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2582 SILC_STATUS_ERR_NO_CHANNEL_PRIV);
2586 sender_mask = chl->mode;
2591 /* Get the target client's channel mode mask */
2592 tmp_mask = silc_argument_get_arg_type(cmd->args, 2, NULL);
2594 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2595 SILC_STATUS_ERR_NOT_ENOUGH_PARAMS);
2598 SILC_GET32_MSB(target_mask, tmp_mask);
2600 /* Get target Client ID */
2601 tmp_id = silc_argument_get_arg_type(cmd->args, 3, &tmp_len);
2603 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2604 SILC_STATUS_ERR_NO_CHANNEL_ID);
2607 client_id = silc_id_payload_parse_id(tmp_id, tmp_len);
2609 /* Get target client's entry */
2610 target_client = silc_idlist_find_client_by_id(server->local_list,
2612 if (!target_client) {
2613 /* XXX If target client is not one of mine send to primary route */
2616 /* Check whether target client is on the channel */
2617 if (!silc_server_client_on_channel(target_client, channel)) {
2618 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2619 SILC_STATUS_ERR_USER_NOT_ON_CHANNEL);
2623 /* Get entry to the channel user list */
2624 silc_list_start(channel->user_list);
2625 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END)
2626 if (chl->client == target_client)
2633 /* If the target client is founder, no one else can change their mode
2635 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO && chl->client != target_client) {
2636 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2637 SILC_STATUS_ERR_NOT_YOU);
2641 if (target_mask & SILC_CHANNEL_UMODE_CHANFO) {
2642 /* Cannot promote anyone to channel founder */
2643 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2644 SILC_STATUS_ERR_NOT_YOU);
2647 if (chl->mode & SILC_CHANNEL_UMODE_CHANFO) {
2648 if (target_client == client) {
2649 /* Remove channel founder rights from itself */
2650 chl->mode &= ~SILC_CHANNEL_UMODE_CHANFO;
2653 silc_server_command_send_status_reply(cmd, SILC_COMMAND_CUMODE,
2654 SILC_STATUS_ERR_NOT_YOU);
2660 if (target_mask & SILC_CHANNEL_UMODE_CHANOP) {
2661 /* Promote to operator */
2662 if (!(chl->mode & SILC_CHANNEL_UMODE_CHANOP)) {
2663 chl->mode |= SILC_CHANNEL_UMODE_CHANOP;
2667 if (chl->mode & SILC_CHANNEL_UMODE_CHANOP) {
2668 /* Demote to normal user */
2669 chl->mode &= ~SILC_CHANNEL_UMODE_CHANOP;
2674 /* Send notify to channel, notify only if mode was actually changed. */
2676 idp = silc_id_payload_encode(client->id, SILC_ID_CLIENT);
2677 silc_server_send_notify_to_channel(server, channel, TRUE,
2678 SILC_NOTIFY_TYPE_CUMODE_CHANGE, 3,
2679 idp->data, idp->len,
2680 tmp_mask, 4, tmp_id, tmp_len);
2681 silc_buffer_free(idp);
2684 /* Send command reply to sender */
2685 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_CUMODE,
2686 SILC_STATUS_OK, 0, 2,
2688 3, tmp_id, tmp_len);
2689 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2690 packet->data, packet->len, FALSE);
2692 silc_buffer_free(packet);
2693 silc_free(channel_id);
2694 silc_free(client_id);
2697 silc_server_command_free(cmd);
2700 /* Server side of KICK command. Kicks client out of channel. */
2702 SILC_SERVER_CMD_FUNC(kick)
2706 SILC_SERVER_CMD_FUNC(restart)
2710 SILC_SERVER_CMD_FUNC(close)
2714 SILC_SERVER_CMD_FUNC(die)
2718 SILC_SERVER_CMD_FUNC(silcoper)
2722 /* Server side command of LEAVE. Removes client from a channel. */
2724 SILC_SERVER_CMD_FUNC(leave)
2726 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2727 SilcServer server = cmd->server;
2728 SilcSocketConnection sock = cmd->sock;
2729 SilcClientEntry id_entry = (SilcClientEntry)cmd->sock->user_data;
2731 SilcChannelEntry channel;
2733 unsigned int i, len;
2736 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_LEAVE, cmd, 1, 2);
2738 /* Get Channel ID */
2739 tmp = silc_argument_get_arg_type(cmd->args, 1, &len);
2741 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2742 SILC_STATUS_ERR_NO_CHANNEL_ID);
2745 id = silc_id_payload_parse_id(tmp, len);
2747 /* Get channel entry */
2748 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2750 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2751 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2755 /* Check whether this client is on the channel */
2756 if (!silc_server_client_on_channel(id_entry, channel)) {
2757 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2758 SILC_STATUS_ERR_NOT_ON_CHANNEL);
2762 /* Notify routers that they should remove this client from their list
2763 of clients on the channel. */
2764 if (!server->standalone)
2765 silc_server_send_remove_channel_user(server,
2766 server->router->connection,
2767 server->server_type == SILC_ROUTER ?
2768 TRUE : FALSE, id_entry->id, id);
2770 /* Remove client from channel */
2771 i = silc_server_remove_from_one_channel(server, sock, channel, id_entry,
2773 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2776 /* If the channel does not exist anymore we won't send anything */
2780 /* Re-generate channel key */
2781 silc_server_create_channel_key(server, channel, 0);
2783 /* Encode channel key payload to be distributed on the channel */
2785 silc_channel_key_payload_encode(len, tmp,
2786 strlen(channel->channel_key->cipher->name),
2787 channel->channel_key->cipher->name,
2788 channel->key_len / 8, channel->key);
2790 /* If we are normal server then we will send it to our router. If we
2791 are router we will send it to all local servers that has clients on
2793 if (server->server_type == SILC_SERVER) {
2794 if (!server->standalone)
2795 silc_server_packet_send(server,
2796 cmd->server->router->connection,
2797 SILC_PACKET_CHANNEL_KEY, 0, packet->data,
2803 /* Send to locally connected clients on the channel */
2804 silc_server_packet_send_local_channel(server, channel,
2805 SILC_PACKET_CHANNEL_KEY, 0,
2806 packet->data, packet->len, FALSE);
2808 silc_buffer_free(packet);
2812 silc_server_command_free(cmd);
2815 /* Server side of command NAMES. Resolves clients and their names currently
2816 joined on the requested channel. The name list is sent back to the
2819 SILC_SERVER_CMD_FUNC(names)
2821 SilcServerCommandContext cmd = (SilcServerCommandContext)context;
2822 SilcServer server = cmd->server;
2823 SilcChannelEntry channel;
2824 SilcChannelClientEntry chl;
2827 unsigned int i, len, len2, tmp_len;
2829 char *name_list = NULL, *n;
2830 SilcBuffer client_id_list;
2831 SilcBuffer client_mode_list;
2833 SILC_SERVER_COMMAND_CHECK_ARGC(SILC_COMMAND_NAMES, cmd, 1, 2);
2835 /* Get Channel ID */
2836 tmp = silc_argument_get_arg_type(cmd->args, 1, &tmp_len);
2838 silc_server_command_send_status_reply(cmd, SILC_COMMAND_LEAVE,
2839 SILC_STATUS_ERR_NO_CHANNEL_ID);
2842 id = silc_id_payload_parse_id(tmp, tmp_len);
2844 /* Check whether the channel exists. If we are normal server and the
2845 channel does not exist we will send this same command to our router
2846 which will know if the channel exists. */
2847 channel = silc_idlist_find_channel_by_id(server->local_list, id, NULL);
2849 if (server->server_type == SILC_SERVER && !server->standalone) {
2850 /* XXX Send names command */
2852 cmd->pending = TRUE;
2853 silc_server_command_pending(server, SILC_COMMAND_NAMES, 0,
2854 silc_server_command_names, context);
2858 silc_server_command_send_status_reply(cmd, SILC_COMMAND_INVITE,
2859 SILC_STATUS_ERR_NO_SUCH_CHANNEL);
2863 /* Assemble the name list now */
2866 silc_list_start(channel->user_list);
2868 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2869 n = chl->client->nickname;
2873 name_list = silc_realloc(name_list, sizeof(*name_list) * (len + 1));
2874 memcpy(name_list + (len - len2), n, len2);
2877 if (i == silc_list_count(channel->user_list) - 1)
2879 memcpy(name_list + len, ",", 1);
2887 /* Assemble the Client ID list now */
2888 client_id_list = silc_buffer_alloc((SILC_ID_CLIENT_LEN + 4) *
2889 silc_list_count(channel->user_list));
2890 silc_buffer_pull_tail(client_id_list, SILC_BUFFER_END(client_id_list));
2891 silc_list_start(channel->user_list);
2892 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2895 idp = silc_id_payload_encode(chl->client->id, SILC_ID_CLIENT);
2896 silc_buffer_format(client_id_list,
2897 SILC_STR_UI_XNSTRING(idp->data, idp->len),
2899 silc_buffer_pull(client_id_list, idp->len);
2900 silc_buffer_free(idp);
2902 silc_buffer_push(client_id_list,
2903 client_id_list->data - client_id_list->head);
2905 /* Assemble mode list */
2906 client_mode_list = silc_buffer_alloc(4 *
2907 silc_list_count(channel->user_list));
2908 silc_buffer_pull_tail(client_mode_list, SILC_BUFFER_END(client_mode_list));
2909 silc_list_start(channel->user_list);
2910 while ((chl = silc_list_get(channel->user_list)) != SILC_LIST_END) {
2911 SILC_PUT32_MSB(chl->mode, client_mode_list->data);
2912 silc_buffer_pull(client_mode_list, 4);
2914 silc_buffer_push(client_mode_list,
2915 client_mode_list->data - client_mode_list->head);
2918 packet = silc_command_reply_payload_encode_va(SILC_COMMAND_NAMES,
2919 SILC_STATUS_OK, 0, 4,
2923 4, client_id_list->data,
2924 client_id_list->len,
2925 5, client_mode_list->data,
2926 client_mode_list->len);
2927 silc_server_packet_send(server, cmd->sock, SILC_PACKET_COMMAND_REPLY, 0,
2928 packet->data, packet->len, FALSE);
2930 silc_buffer_free(packet);
2931 silc_free(name_list);
2932 silc_buffer_free(client_id_list);
2933 silc_buffer_free(client_mode_list);
2937 silc_server_command_free(cmd);